ra386int.pas 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 by Carl Eric Codere
  4. Does the parsing process for the intel styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$ifdef TP}
  19. {$E+,N+}
  20. {$endif}
  21. Unit Ra386int;
  22. Interface
  23. uses
  24. tree;
  25. function assemble: ptree;
  26. Implementation
  27. Uses
  28. globtype,
  29. strings,cobjects,systems,verbose,globals,
  30. files,aasm,types,scanner,hcodegen,symtable
  31. ,i386base
  32. ,rautils,ra386;
  33. type
  34. tasmtoken = (
  35. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  36. AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
  37. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
  38. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,
  39. {------------------ Assembler directives --------------------}
  40. AS_DB,AS_DW,AS_DD,AS_END,
  41. {------------------ Assembler Operators --------------------}
  42. AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_NEAR,AS_FAR,
  43. AS_HIGH,AS_LOW,AS_OFFSET,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
  44. AS_AND,AS_OR,AS_XOR);
  45. tasmkeyword = string[6];
  46. const
  47. { These tokens should be modified accordingly to the modifications }
  48. { in the different enumerations. }
  49. firstdirective = AS_DB;
  50. lastdirective = AS_END;
  51. firstoperator = AS_BYTE;
  52. lastoperator = AS_XOR;
  53. firstsreg = R_CS;
  54. lastsreg = R_SS;
  55. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  56. _count_asmoperators = longint(lastoperator)-longint(firstoperator);
  57. _count_asmprefixes = 5;
  58. _count_asmspecialops = 25;
  59. _count_asmoverrides = 3;
  60. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  61. ('DB','DW','DD','END');
  62. { problems with shl,shr,not,and,or and xor, they are }
  63. { context sensitive. }
  64. _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
  65. 'BYTE','WORD','DWORD','QWORD','TBYTE','NEAR','FAR','HIGH',
  66. 'LOW','OFFSET','SEG','TYPE','PTR','MOD','SHL','SHR','NOT','AND',
  67. 'OR','XOR');
  68. token2str : array[tasmtoken] of string[10] = (
  69. '','Label','LLabel','String','Integer',
  70. ',','[',']','(',
  71. ')',':','.','+','-','*',
  72. ';','identifier','register','opcode','/',
  73. '','','','END',
  74. '','','','','','','','',
  75. '','','','type','ptr','mod','shl','shr','not',
  76. 'and','or','xor'
  77. );
  78. const
  79. newline = #10;
  80. firsttoken : boolean = TRUE;
  81. var
  82. _asmsorted : boolean;
  83. inexpression : boolean;
  84. curlist : paasmoutput;
  85. c : char;
  86. prevasmtoken : tasmtoken;
  87. actasmtoken : tasmtoken;
  88. actasmpattern : string;
  89. actasmregister : tregister;
  90. actopcode : tasmop;
  91. actopsize : topsize;
  92. actcondition : tasmcond;
  93. iasmops : ^op2strtable;
  94. iasmregs : ^reg2strtable;
  95. Procedure SetupTables;
  96. { creates uppercased symbol tables for speed access }
  97. var
  98. i : tasmop;
  99. j : tregister;
  100. Begin
  101. { opcodes }
  102. new(iasmops);
  103. for i:=firstop to lastop do
  104. iasmops^[i] := upper(int_op2str[i]);
  105. { registers }
  106. new(iasmregs);
  107. for j:=firstreg to lastreg do
  108. iasmregs^[j] := upper(int_reg2str[j]);
  109. end;
  110. {---------------------------------------------------------------------}
  111. { Routines for the tokenizing }
  112. {---------------------------------------------------------------------}
  113. function is_asmopcode(const s: string):boolean;
  114. var
  115. i: tasmop;
  116. cond : string[4];
  117. cnd : tasmcond;
  118. j: longint;
  119. Begin
  120. is_asmopcode:=FALSE;
  121. actopcode:=A_None;
  122. actcondition:=C_None;
  123. actopsize:=S_NO;
  124. for i:=firstop to lastop do
  125. if s=iasmops^[i] then
  126. begin
  127. actopcode:=i;
  128. actasmtoken:=AS_OPCODE;
  129. is_asmopcode:=TRUE;
  130. exit;
  131. end;
  132. { not found yet, check condition opcodes }
  133. j:=0;
  134. while (j<CondAsmOps) do
  135. begin
  136. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  137. begin
  138. cond:=Copy(s,Length(CondAsmOpStr[j])+1,255);
  139. if cond<>'' then
  140. begin
  141. for cnd:=low(TasmCond) to high(TasmCond) do
  142. if Cond=Upper(cond2str[cnd]) then
  143. begin
  144. actopcode:=CondASmOp[j];
  145. actcondition:=cnd;
  146. is_asmopcode:=TRUE;
  147. actasmtoken:=AS_OPCODE;
  148. exit
  149. end;
  150. end;
  151. end;
  152. inc(j);
  153. end;
  154. end;
  155. function is_asmoperator(const s: string):boolean;
  156. var
  157. i : longint;
  158. Begin
  159. for i:=0 to _count_asmoperators do
  160. if s=_asmoperators[i] then
  161. begin
  162. actasmtoken:=tasmtoken(longint(firstoperator)+i);
  163. is_asmoperator:=true;
  164. exit;
  165. end;
  166. is_asmoperator:=false;
  167. end;
  168. Function is_asmdirective(const s: string):boolean;
  169. var
  170. i : longint;
  171. Begin
  172. for i:=0 to _count_asmdirectives do
  173. if s=_asmdirectives[i] then
  174. begin
  175. actasmtoken:=tasmtoken(longint(firstdirective)+i);
  176. is_asmdirective:=true;
  177. exit;
  178. end;
  179. is_asmdirective:=false;
  180. end;
  181. Function is_register(const s: string):boolean;
  182. Var
  183. i : tregister;
  184. Begin
  185. actasmregister:=R_NO;
  186. for i:=firstreg to lastreg do
  187. if s=iasmregs^[i] then
  188. begin
  189. actasmtoken:=AS_REGISTER;
  190. actasmregister:=i;
  191. is_register:=true;
  192. exit;
  193. end;
  194. is_register:=false;
  195. end;
  196. function is_locallabel(const s:string):boolean;
  197. begin
  198. is_locallabel:=(length(s)>1) and (s[1]='@');
  199. end;
  200. Procedure GetToken;
  201. var
  202. len : longint;
  203. forcelabel : boolean;
  204. begin
  205. { save old token and reset new token }
  206. prevasmtoken:=actasmtoken;
  207. actasmtoken:=AS_NONE;
  208. { reset }
  209. forcelabel:=FALSE;
  210. actasmpattern:='';
  211. { while space and tab , continue scan... }
  212. while (c in [' ',#9]) do
  213. c:=current_scanner^.asmgetchar;
  214. { get token pos }
  215. if not (c in [newline,#13,'{',';']) then
  216. current_scanner^.gettokenpos;
  217. { Local Label, Label, Directive, Prefix or Opcode }
  218. if firsttoken and not (c in [newline,#13,'{',';']) then
  219. begin
  220. firsttoken:=FALSE;
  221. len:=0;
  222. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  223. begin
  224. { if there is an at_sign, then this must absolutely be a label }
  225. if c = '@' then
  226. forcelabel:=TRUE;
  227. inc(len);
  228. actasmpattern[len]:=c;
  229. c:=current_scanner^.asmgetchar;
  230. end;
  231. actasmpattern[0]:=chr(len);
  232. uppervar(actasmpattern);
  233. { label ? }
  234. if c = ':' then
  235. begin
  236. if actasmpattern[1]='@' then
  237. actasmtoken:=AS_LLABEL
  238. else
  239. actasmtoken:=AS_LABEL;
  240. { let us point to the next character }
  241. c:=current_scanner^.asmgetchar;
  242. exit;
  243. end;
  244. { Are we trying to create an identifier with }
  245. { an at-sign...? }
  246. if forcelabel then
  247. Message(asmr_e_none_label_contain_at);
  248. { opcode ? }
  249. If is_asmopcode(actasmpattern) then
  250. Begin
  251. { check if we are in an expression }
  252. { then continue with asm directives }
  253. if not inexpression then
  254. exit;
  255. end;
  256. if is_asmdirective(actasmpattern) then
  257. exit;
  258. actasmtoken:=AS_NONE;
  259. exit;
  260. end
  261. else { else firsttoken }
  262. begin
  263. case c of
  264. '@' : { possiblities : - local label reference , such as in jmp @local1 }
  265. { - @Result, @Code or @Data special variables. }
  266. begin
  267. actasmpattern:=c;
  268. c:=current_scanner^.asmgetchar;
  269. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  270. begin
  271. actasmpattern:=actasmpattern + c;
  272. c:=current_scanner^.asmgetchar;
  273. end;
  274. uppervar(actasmpattern);
  275. actasmtoken:=AS_ID;
  276. exit;
  277. end;
  278. 'A'..'Z','a'..'z','_': { identifier, register, opcode, prefix or directive }
  279. begin
  280. actasmpattern:=c;
  281. c:=current_scanner^.asmgetchar;
  282. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  283. begin
  284. actasmpattern:=actasmpattern + c;
  285. c:=current_scanner^.asmgetchar;
  286. end;
  287. uppervar(actasmpattern);
  288. { after prefix we allow also a new opcode }
  289. If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
  290. Begin
  291. { if we are not in a constant }
  292. { expression than this is an }
  293. { opcode. }
  294. if not inexpression then
  295. exit;
  296. end;
  297. if is_register(actasmpattern) then
  298. exit;
  299. if is_asmdirective(actasmpattern) then
  300. exit;
  301. if is_asmoperator(actasmpattern) then
  302. exit;
  303. actasmtoken:=AS_ID;
  304. exit;
  305. end;
  306. '&' : { override operator... not supported }
  307. begin
  308. Message(asmr_w_override_op_not_supported);
  309. c:=current_scanner^.asmgetchar;
  310. actasmtoken:=AS_NONE;
  311. end;
  312. '''' : { string or character }
  313. begin
  314. actasmpattern:='';
  315. repeat
  316. if c = '''' then
  317. begin
  318. c:=current_scanner^.asmgetchar;
  319. if c=newline then
  320. begin
  321. Message(scan_f_string_exceeds_line);
  322. break;
  323. end;
  324. repeat
  325. if c='''' then
  326. begin
  327. c:=current_scanner^.asmgetchar;
  328. if c='''' then
  329. begin
  330. actasmpattern:=actasmpattern+'''';
  331. c:=current_scanner^.asmgetchar;
  332. if c=newline then
  333. begin
  334. Message(scan_f_string_exceeds_line);
  335. break;
  336. end;
  337. end
  338. else
  339. break;
  340. end
  341. else
  342. begin
  343. actasmpattern:=actasmpattern+c;
  344. c:=current_scanner^.asmgetchar;
  345. if c=newline then
  346. begin
  347. Message(scan_f_string_exceeds_line);
  348. break
  349. end;
  350. end;
  351. until false; { end repeat }
  352. end
  353. else
  354. break; { end if }
  355. until false;
  356. actasmtoken:=AS_STRING;
  357. exit;
  358. end;
  359. '"' : { string or character }
  360. begin
  361. actasmpattern:='';
  362. repeat
  363. if c = '"' then
  364. begin
  365. c:=current_scanner^.asmgetchar;
  366. if c=newline then
  367. begin
  368. Message(scan_f_string_exceeds_line);
  369. break;
  370. end;
  371. repeat
  372. if c='"' then
  373. begin
  374. c:=current_scanner^.asmgetchar;
  375. if c='"' then
  376. begin
  377. actasmpattern:=actasmpattern+'"';
  378. c:=current_scanner^.asmgetchar;
  379. if c=newline then
  380. begin
  381. Message(scan_f_string_exceeds_line);
  382. break;
  383. end;
  384. end
  385. else
  386. break;
  387. end
  388. else
  389. begin
  390. actasmpattern:=actasmpattern+c;
  391. c:=current_scanner^.asmgetchar;
  392. if c=newline then
  393. begin
  394. Message(scan_f_string_exceeds_line);
  395. break
  396. end;
  397. end;
  398. until false; { end repeat }
  399. end
  400. else
  401. break; { end if }
  402. until false;
  403. actasmtoken:=AS_STRING;
  404. exit;
  405. end;
  406. '$' :
  407. begin
  408. c:=current_scanner^.asmgetchar;
  409. while c in ['0'..'9','A'..'F','a'..'f'] do
  410. begin
  411. actasmpattern:=actasmpattern + c;
  412. c:=current_scanner^.asmgetchar;
  413. end;
  414. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  415. actasmtoken:=AS_INTNUM;
  416. exit;
  417. end;
  418. ',' :
  419. begin
  420. actasmtoken:=AS_COMMA;
  421. c:=current_scanner^.asmgetchar;
  422. exit;
  423. end;
  424. '[' :
  425. begin
  426. actasmtoken:=AS_LBRACKET;
  427. c:=current_scanner^.asmgetchar;
  428. exit;
  429. end;
  430. ']' :
  431. begin
  432. actasmtoken:=AS_RBRACKET;
  433. c:=current_scanner^.asmgetchar;
  434. exit;
  435. end;
  436. '(' :
  437. begin
  438. actasmtoken:=AS_LPAREN;
  439. c:=current_scanner^.asmgetchar;
  440. exit;
  441. end;
  442. ')' :
  443. begin
  444. actasmtoken:=AS_RPAREN;
  445. c:=current_scanner^.asmgetchar;
  446. exit;
  447. end;
  448. ':' :
  449. begin
  450. actasmtoken:=AS_COLON;
  451. c:=current_scanner^.asmgetchar;
  452. exit;
  453. end;
  454. '.' :
  455. begin
  456. actasmtoken:=AS_DOT;
  457. c:=current_scanner^.asmgetchar;
  458. exit;
  459. end;
  460. '+' :
  461. begin
  462. actasmtoken:=AS_PLUS;
  463. c:=current_scanner^.asmgetchar;
  464. exit;
  465. end;
  466. '-' :
  467. begin
  468. actasmtoken:=AS_MINUS;
  469. c:=current_scanner^.asmgetchar;
  470. exit;
  471. end;
  472. '*' :
  473. begin
  474. actasmtoken:=AS_STAR;
  475. c:=current_scanner^.asmgetchar;
  476. exit;
  477. end;
  478. '/' :
  479. begin
  480. actasmtoken:=AS_SLASH;
  481. c:=current_scanner^.asmgetchar;
  482. exit;
  483. end;
  484. '0'..'9':
  485. begin
  486. actasmpattern:=c;
  487. c:=current_scanner^.asmgetchar;
  488. { Get the possible characters }
  489. while c in ['0'..'9','A'..'F','a'..'f'] do
  490. begin
  491. actasmpattern:=actasmpattern + c;
  492. c:=current_scanner^.asmgetchar;
  493. end;
  494. { Get ending character }
  495. uppervar(actasmpattern);
  496. c:=upcase(c);
  497. { possibly a binary number. }
  498. if (actasmpattern[length(actasmpattern)] = 'B') and (c <> 'H') then
  499. Begin
  500. { Delete the last binary specifier }
  501. delete(actasmpattern,length(actasmpattern),1);
  502. actasmpattern:=tostr(ValBinary(actasmpattern));
  503. actasmtoken:=AS_INTNUM;
  504. exit;
  505. end
  506. else
  507. Begin
  508. case c of
  509. 'O' :
  510. Begin
  511. actasmpattern:=tostr(ValOctal(actasmpattern));
  512. actasmtoken:=AS_INTNUM;
  513. c:=current_scanner^.asmgetchar;
  514. exit;
  515. end;
  516. 'H' :
  517. Begin
  518. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  519. actasmtoken:=AS_INTNUM;
  520. c:=current_scanner^.asmgetchar;
  521. exit;
  522. end;
  523. else { must be an integer number }
  524. begin
  525. actasmpattern:=tostr(ValDecimal(actasmpattern));
  526. actasmtoken:=AS_INTNUM;
  527. exit;
  528. end;
  529. end;
  530. end;
  531. end;
  532. ';','{',#13,newline :
  533. begin
  534. c:=current_scanner^.asmgetchar;
  535. firsttoken:=TRUE;
  536. actasmtoken:=AS_SEPARATOR;
  537. exit;
  538. end;
  539. else
  540. Begin
  541. Message(scan_f_illegal_char);
  542. end;
  543. end;
  544. end;
  545. end;
  546. function consume(t : tasmtoken):boolean;
  547. begin
  548. Consume:=true;
  549. if t<>actasmtoken then
  550. begin
  551. Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
  552. Consume:=false;
  553. end;
  554. repeat
  555. gettoken;
  556. until actasmtoken<>AS_NONE;
  557. end;
  558. procedure RecoverConsume(allowcomma:boolean);
  559. begin
  560. While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
  561. begin
  562. if allowcomma and (actasmtoken=AS_COMMA) then
  563. break;
  564. Consume(actasmtoken);
  565. end;
  566. end;
  567. {*****************************************************************************
  568. Parsing Helpers
  569. *****************************************************************************}
  570. Procedure BuildRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  571. { Description: This routine builds up a record offset after a AS_DOT }
  572. { token is encountered. }
  573. { On entry actasmtoken should be equal to AS_DOT }
  574. var
  575. s : string;
  576. Begin
  577. offset:=0;
  578. size:=0;
  579. s:=expr;
  580. while (actasmtoken=AS_DOT) do
  581. begin
  582. Consume(AS_DOT);
  583. if actasmtoken=AS_ID then
  584. s:=s+'.'+actasmpattern;
  585. if not Consume(AS_ID) then
  586. begin
  587. RecoverConsume(true);
  588. break;
  589. end;
  590. end;
  591. if not GetRecordOffsetSize(s,offset,size) then
  592. Message(asmr_e_building_record_offset);
  593. end;
  594. Procedure BuildConstSymbolExpression(needofs:boolean;var value:longint;var asmsym:string);
  595. var
  596. tempstr,expr,hs : string;
  597. parenlevel,l,k : longint;
  598. errorflag : boolean;
  599. prevtok : tasmtoken;
  600. hl : PAsmLabel;
  601. sym : psym;
  602. Begin
  603. { reset }
  604. value:=0;
  605. asmsym:='';
  606. errorflag:=FALSE;
  607. tempstr:='';
  608. expr:='';
  609. inexpression:=TRUE;
  610. parenlevel:=0;
  611. Repeat
  612. Case actasmtoken of
  613. AS_LPAREN:
  614. Begin
  615. Consume(AS_LPAREN);
  616. expr:=expr + '(';
  617. inc(parenlevel);
  618. end;
  619. AS_RPAREN:
  620. Begin
  621. Consume(AS_RPAREN);
  622. expr:=expr + ')';
  623. dec(parenlevel);
  624. end;
  625. AS_SHL:
  626. Begin
  627. Consume(AS_SHL);
  628. expr:=expr + '<';
  629. end;
  630. AS_SHR:
  631. Begin
  632. Consume(AS_SHR);
  633. expr:=expr + '>';
  634. end;
  635. AS_SLASH:
  636. Begin
  637. Consume(AS_SLASH);
  638. expr:=expr + '/';
  639. end;
  640. AS_MOD:
  641. Begin
  642. Consume(AS_MOD);
  643. expr:=expr + '%';
  644. end;
  645. AS_STAR:
  646. Begin
  647. Consume(AS_STAR);
  648. expr:=expr + '*';
  649. end;
  650. AS_PLUS:
  651. Begin
  652. Consume(AS_PLUS);
  653. expr:=expr + '+';
  654. end;
  655. AS_MINUS:
  656. Begin
  657. Consume(AS_MINUS);
  658. expr:=expr + '-';
  659. end;
  660. AS_AND:
  661. Begin
  662. Consume(AS_AND);
  663. expr:=expr + '&';
  664. end;
  665. AS_NOT:
  666. Begin
  667. Consume(AS_NOT);
  668. expr:=expr + '~';
  669. end;
  670. AS_XOR:
  671. Begin
  672. Consume(AS_XOR);
  673. expr:=expr + '^';
  674. end;
  675. AS_OR:
  676. Begin
  677. Consume(AS_OR);
  678. expr:=expr + '|';
  679. end;
  680. AS_INTNUM:
  681. Begin
  682. expr:=expr + actasmpattern;
  683. Consume(AS_INTNUM);
  684. end;
  685. AS_OFFSET:
  686. begin
  687. Consume(AS_OFFSET);
  688. if actasmtoken<>AS_ID then
  689. Message(asmr_e_offset_without_identifier);
  690. end;
  691. AS_ID:
  692. Begin
  693. tempstr:=actasmpattern;
  694. prevtok:=prevasmtoken;
  695. consume(AS_ID);
  696. if actasmtoken=AS_DOT then
  697. begin
  698. BuildRecordOffsetSize(tempstr,l,k);
  699. str(l, tempstr);
  700. expr:=expr + tempstr;
  701. end
  702. else
  703. if SearchIConstant(tempstr,l) then
  704. begin
  705. str(l, tempstr);
  706. expr:=expr + tempstr;
  707. end
  708. else
  709. begin
  710. hs:='';
  711. if is_locallabel(tempstr) then
  712. begin
  713. CreateLocalLabel(tempstr,hl,false);
  714. hs:=hl^.name
  715. end
  716. else
  717. if SearchLabel(tempstr,hl,false) then
  718. hs:=hl^.name
  719. else
  720. begin
  721. getsym(tempstr,false);
  722. sym:=srsym;
  723. if assigned(sym) then
  724. begin
  725. if sym^.owner^.symtabletype in [localsymtable,parasymtable] then
  726. Message(asmr_e_no_local_or_para_allowed);
  727. case srsym^.typ of
  728. varsym :
  729. hs:=pvarsym(srsym)^.mangledname;
  730. typedconstsym :
  731. hs:=ptypedconstsym(srsym)^.mangledname;
  732. procsym :
  733. hs:=pprocsym(srsym)^.mangledname;
  734. else
  735. Message(asmr_e_wrong_sym_type);
  736. end;
  737. end
  738. else
  739. Message1(sym_e_unknown_id,tempstr);
  740. end;
  741. { symbol found? }
  742. if hs<>'' then
  743. begin
  744. if needofs and (prevtok<>AS_OFFSET) then
  745. Message(asmr_e_need_offset);
  746. if asmsym='' then
  747. asmsym:=hs
  748. else
  749. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  750. if (expr='') or (expr[length(expr)]='+') then
  751. begin
  752. delete(expr,length(expr),1);
  753. if not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END]) then
  754. Message(asmr_e_only_add_relocatable_symbol);
  755. end
  756. else
  757. Message(asmr_e_only_add_relocatable_symbol);
  758. end;
  759. end;
  760. end;
  761. AS_RBRACKET,
  762. AS_SEPARATOR,
  763. AS_COMMA:
  764. Begin
  765. break;
  766. end;
  767. else
  768. Begin
  769. { write error only once. }
  770. if not errorflag then
  771. Message(asmr_e_invalid_constant_expression);
  772. { consume tokens until we find COMMA or SEPARATOR }
  773. Consume(actasmtoken);
  774. errorflag:=TRUE;
  775. end;
  776. end;
  777. Until false;
  778. { calculate expression }
  779. if not ErrorFlag then
  780. value:=CalculateExpression(expr)
  781. else
  782. value:=0;
  783. { no longer in an expression }
  784. inexpression:=FALSE;
  785. end;
  786. Function BuildConstExpression:longint;
  787. var
  788. l : longint;
  789. hs : string;
  790. begin
  791. BuildConstSymbolExpression(false,l,hs);
  792. if hs<>'' then
  793. Message(asmr_e_relocatable_symbol_not_allowed);
  794. BuildConstExpression:=l;
  795. end;
  796. {****************************************************************************
  797. T386IntelOperand
  798. ****************************************************************************}
  799. type
  800. P386IntelOperand=^T386IntelOperand;
  801. T386IntelOperand=object(T386Operand)
  802. Procedure BuildOperand;virtual;
  803. private
  804. Procedure BuildReference;
  805. Procedure BuildConstant;
  806. end;
  807. Procedure T386IntelOperand.BuildReference;
  808. var
  809. l : longint;
  810. hs : string;
  811. code : integer;
  812. hreg,
  813. oldbase : tregister;
  814. GotPlus,Negative : boolean;
  815. Begin
  816. Consume(AS_LBRACKET);
  817. InitRef;
  818. GotPlus:=true;
  819. Negative:=false;
  820. repeat
  821. Case actasmtoken of
  822. AS_ID: { Constant reference expression OR variable reference expression }
  823. Begin
  824. if not GotPlus then
  825. Message(asmr_e_invalid_reference_syntax);
  826. if actasmpattern[1] = '@' then
  827. Message(asmr_e_local_symbol_not_allowed_as_ref);
  828. if SearchIConstant(actasmpattern,l) then
  829. begin
  830. l:=BuildConstExpression;
  831. if actasmtoken=AS_STAR then
  832. opr.ref.scalefactor:=l
  833. else
  834. begin
  835. if negative then
  836. Dec(opr.ref.offset,l)
  837. else
  838. Inc(opr.ref.offset,l);
  839. end;
  840. end
  841. else
  842. Begin
  843. if hasvar then
  844. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  845. if negative then
  846. Message(asmr_e_only_add_relocatable_symbol);
  847. oldbase:=opr.ref.base;
  848. opr.ref.base:=R_NO;
  849. if not SetupVar(actasmpattern) then
  850. Message1(sym_e_unknown_id,actasmpattern);
  851. { is the base register loaded by the var ? }
  852. if (opr.ref.base<>R_NO) then
  853. begin
  854. { check if we can move the old base to the index register }
  855. if (opr.ref.index<>R_NO) then
  856. Message(asmr_e_wrong_base_index)
  857. else
  858. opr.ref.index:=oldbase;
  859. end
  860. else
  861. opr.ref.base:=oldbase;
  862. { we can't have a Constant here so add the constant value to the
  863. offset }
  864. if opr.typ=OPR_CONSTANT then
  865. begin
  866. opr.typ:=OPR_REFERENCE;
  867. inc(opr.ref.offset,opr.val);
  868. end;
  869. Consume(AS_ID);
  870. end;
  871. GotPlus:=false;
  872. end;
  873. AS_PLUS :
  874. Begin
  875. Consume(AS_PLUS);
  876. Negative:=false;
  877. GotPlus:=true;
  878. end;
  879. AS_MINUS :
  880. begin
  881. Consume(AS_MINUS);
  882. Negative:=true;
  883. GotPlus:=true;
  884. end;
  885. AS_STAR : { Scaling }
  886. begin
  887. Consume(AS_STAR);
  888. hs:='';
  889. l:=0;
  890. case actasmtoken of
  891. AS_LPAREN :
  892. l:=BuildConstExpression;
  893. AS_INTNUM:
  894. Begin
  895. hs:=actasmpattern;
  896. Consume(AS_INTNUM);
  897. end;
  898. AS_REGISTER :
  899. begin
  900. if opr.ref.scalefactor=0 then
  901. Message(asmr_e_wrong_scale_factor);
  902. end;
  903. else
  904. Message(asmr_e_invalid_reference_syntax);
  905. end;
  906. if actasmtoken<>AS_REGISTER then
  907. begin
  908. if hs<>'' then
  909. val(hs,l,code);
  910. opr.ref.scalefactor:=l
  911. end;
  912. GotPlus:=false;
  913. end;
  914. AS_REGISTER :
  915. begin
  916. if (not GotPlus) and (actasmtoken<>AS_STAR) then
  917. Message(asmr_e_invalid_reference_syntax);
  918. hreg:=actasmregister;
  919. Consume(AS_REGISTER);
  920. { this register will be the index }
  921. if (actasmtoken=AS_STAR) or
  922. (opr.ref.base<>R_NO) then
  923. begin
  924. if (opr.ref.index<>R_NO) then
  925. Message(asmr_e_multiple_index);
  926. opr.ref.index:=hreg;
  927. end
  928. else
  929. opr.ref.base:=hreg;
  930. GotPlus:=false;
  931. end;
  932. AS_NOT,
  933. AS_INTNUM,
  934. AS_LPAREN : { Constant reference expression }
  935. begin
  936. if not GotPlus then
  937. Message(asmr_e_invalid_reference_syntax);
  938. l:=BuildConstExpression;
  939. if actasmtoken=AS_STAR then
  940. opr.ref.scalefactor:=l
  941. else
  942. begin
  943. if negative then
  944. Dec(opr.ref.offset,l)
  945. else
  946. Inc(opr.ref.offset,l);
  947. end;
  948. GotPlus:=false;
  949. end;
  950. AS_RBRACKET :
  951. begin
  952. if GotPlus then
  953. Message(asmr_e_invalid_reference_syntax);
  954. Consume(AS_RBRACKET);
  955. break;
  956. end;
  957. else
  958. Begin
  959. Message(asmr_e_invalid_reference_syntax);
  960. RecoverConsume(true);
  961. break;
  962. end;
  963. end;
  964. until false;
  965. end;
  966. Procedure T386IntelOperand.BuildConstant;
  967. var
  968. l : longint;
  969. tempstr : string;
  970. begin
  971. BuildConstSymbolExpression(true,l,tempstr);
  972. if tempstr<>'' then
  973. begin
  974. opr.typ:=OPR_SYMBOL;
  975. opr.symofs:=l;
  976. opr.symbol:=newasmsymbol(tempstr);
  977. end
  978. else
  979. begin
  980. opr.typ:=OPR_CONSTANT;
  981. opr.val:=l;
  982. end;
  983. end;
  984. Procedure T386IntelOperand.BuildOperand;
  985. procedure AddLabelOperand(hl:pasmlabel);
  986. begin
  987. if is_calljmp(actopcode) then
  988. begin
  989. opr.typ:=OPR_SYMBOL;
  990. opr.symbol:=hl;
  991. end
  992. else
  993. begin
  994. InitRef;
  995. opr.ref.symbol:=hl;
  996. end;
  997. end;
  998. var
  999. expr,
  1000. tempstr : string;
  1001. tempreg : tregister;
  1002. l,
  1003. toffset,
  1004. tsize : longint;
  1005. hl : PAsmLabel;
  1006. Begin
  1007. tempstr:='';
  1008. expr:='';
  1009. case actasmtoken of
  1010. AS_OFFSET,
  1011. AS_INTNUM,
  1012. AS_PLUS,
  1013. AS_MINUS,
  1014. AS_NOT,
  1015. AS_LPAREN :
  1016. Begin
  1017. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1018. Message(asmr_e_invalid_operand_type);
  1019. BuildConstant;
  1020. end;
  1021. AS_STRING :
  1022. Begin
  1023. if not (opr.typ in [OPR_NONE]) then
  1024. Message(asmr_e_invalid_operand_type);
  1025. if not PadZero(actasmpattern,4) then
  1026. Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
  1027. opr.typ:=OPR_CONSTANT;
  1028. opr.val:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
  1029. Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
  1030. Consume(AS_STRING);
  1031. end;
  1032. AS_ID : { A constant expression, or a Variable ref. }
  1033. Begin
  1034. { Label or Special symbol reference? }
  1035. if actasmpattern[1] = '@' then
  1036. Begin
  1037. if actasmpattern = '@RESULT' then
  1038. Begin
  1039. InitRef;
  1040. SetupResult;
  1041. end
  1042. else
  1043. if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1044. Message(asmr_w_CODE_and_DATA_not_supported)
  1045. else
  1046. { Local Label }
  1047. begin
  1048. CreateLocalLabel(actasmpattern,hl,false);
  1049. Consume(AS_ID);
  1050. AddLabelOperand(hl);
  1051. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1052. Message(asmr_e_syntax_error);
  1053. end;
  1054. end
  1055. else
  1056. { support result for delphi modes }
  1057. if (m_objpas in aktmodeswitches) and (actasmpattern='RESULT') then
  1058. begin
  1059. InitRef;
  1060. SetUpResult;
  1061. Consume(AS_ID);
  1062. end
  1063. { probably a variable or normal expression }
  1064. { or a procedure (such as in CALL ID) }
  1065. else
  1066. Begin
  1067. { is it a constant ? }
  1068. if SearchIConstant(actasmpattern,l) then
  1069. Begin
  1070. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1071. Message(asmr_e_invalid_operand_type);
  1072. BuildConstant;
  1073. end
  1074. else
  1075. { Check for pascal label }
  1076. if SearchLabel(actasmpattern,hl,false) then
  1077. begin
  1078. Consume(AS_ID);
  1079. AddLabelOperand(hl);
  1080. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1081. Message(asmr_e_syntax_error);
  1082. end
  1083. else
  1084. { is it a normal variable ? }
  1085. Begin
  1086. InitRef;
  1087. if not SetupVar(actasmpattern) then
  1088. Begin
  1089. { not a variable, check special variables.. }
  1090. if actasmpattern = 'SELF' then
  1091. SetupSelf
  1092. else
  1093. Message1(sym_e_unknown_id,actasmpattern);
  1094. end;
  1095. l:=0;
  1096. expr:=actasmpattern;
  1097. Consume(AS_ID);
  1098. if actasmtoken=AS_LBRACKET then
  1099. begin
  1100. opr.typ:=OPR_REFERENCE;
  1101. reset_reference(opr.Ref);
  1102. BuildReference;
  1103. end;
  1104. if actasmtoken=AS_DOT then
  1105. begin
  1106. if expr='' then
  1107. Message(asmr_e_no_var_type_specified)
  1108. else
  1109. begin
  1110. BuildRecordOffsetSize(expr,toffset,tsize);
  1111. inc(l,toffset);
  1112. SetSize(tsize);
  1113. end;
  1114. end;
  1115. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1116. inc(l,BuildConstExpression);
  1117. if opr.typ=OPR_REFERENCE then
  1118. inc(opr.ref.offset,l)
  1119. else
  1120. inc(opr.val,l);
  1121. end;
  1122. end;
  1123. end;
  1124. AS_REGISTER : { Register, a variable reference or a constant reference }
  1125. Begin
  1126. { save the type of register used. }
  1127. tempreg:=actasmregister;
  1128. Consume(AS_REGISTER);
  1129. if actasmtoken = AS_COLON then
  1130. Begin
  1131. Consume(AS_COLON);
  1132. InitRef;
  1133. opr.ref.segment:=tempreg;
  1134. BuildReference;
  1135. end
  1136. else
  1137. { Simple register }
  1138. begin
  1139. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1140. Message(asmr_e_invalid_operand_type);
  1141. opr.typ:=OPR_REGISTER;
  1142. opr.reg:=tempreg;
  1143. size:=reg_2_opsize[opr.reg];
  1144. end;
  1145. end;
  1146. AS_LBRACKET: { a variable reference, register ref. or a constant reference }
  1147. Begin
  1148. BuildReference;
  1149. end;
  1150. AS_SEG :
  1151. Begin
  1152. Message(asmr_e_seg_not_supported);
  1153. Consume(actasmtoken);
  1154. end;
  1155. AS_SEPARATOR,
  1156. AS_COMMA: ;
  1157. else
  1158. Message(asmr_e_syn_operand);
  1159. end;
  1160. if not(actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1161. begin
  1162. Message(asmr_e_syntax_error);
  1163. RecoverConsume(true);
  1164. end;
  1165. end;
  1166. {*****************************************************************************
  1167. T386IntelInstruction
  1168. *****************************************************************************}
  1169. type
  1170. P386IntelInstruction=^T386IntelInstruction;
  1171. T386IntelInstruction=object(T386Instruction)
  1172. procedure InitOperands;virtual;
  1173. procedure BuildOpcode;virtual;
  1174. end;
  1175. procedure T386IntelInstruction.InitOperands;
  1176. var
  1177. i : longint;
  1178. begin
  1179. for i:=1to 3 do
  1180. Operands[i]:=new(P386IntelOperand,Init);
  1181. end;
  1182. Procedure T386IntelInstruction.BuildOpCode;
  1183. var
  1184. PrefixOp,OverrideOp: tasmop;
  1185. expr : string;
  1186. size : topsize;
  1187. operandnum : longint;
  1188. Begin
  1189. expr:='';
  1190. PrefixOp:=A_None;
  1191. OverrideOp:=A_None;
  1192. { prefix seg opcode / prefix opcode }
  1193. repeat
  1194. if is_prefix(actopcode) then
  1195. begin
  1196. PrefixOp:=ActOpcode;
  1197. opcode:=ActOpcode;
  1198. condition:=ActCondition;
  1199. opsize:=ActOpsize;
  1200. ConcatInstruction(curlist);
  1201. Consume(AS_OPCODE);
  1202. end
  1203. else
  1204. if is_override(actopcode) then
  1205. begin
  1206. OverrideOp:=ActOpcode;
  1207. opcode:=ActOpcode;
  1208. condition:=ActCondition;
  1209. opsize:=ActOpsize;
  1210. ConcatInstruction(curlist);
  1211. Consume(AS_OPCODE);
  1212. end
  1213. else
  1214. break;
  1215. until (actasmtoken<>AS_OPCODE);
  1216. { opcode }
  1217. if (actasmtoken <> AS_OPCODE) then
  1218. Begin
  1219. Message(asmr_e_invalid_or_missing_opcode);
  1220. RecoverConsume(false);
  1221. exit;
  1222. end;
  1223. { Fill the instr object with the current state }
  1224. Opcode:=ActOpcode;
  1225. condition:=ActCondition;
  1226. opsize:=ActOpsize;
  1227. { Valid combination of prefix/override and instruction ? }
  1228. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1229. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1230. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1231. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1232. { We are reading operands, so opcode will be an AS_ID }
  1233. operandnum:=1;
  1234. Consume(AS_OPCODE);
  1235. { Zero operand opcode ? }
  1236. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1237. begin
  1238. operandnum:=0;
  1239. exit;
  1240. end;
  1241. { Read Operands }
  1242. repeat
  1243. case actasmtoken of
  1244. { End of asm operands for this opcode }
  1245. AS_END,
  1246. AS_SEPARATOR :
  1247. break;
  1248. { Operand delimiter }
  1249. AS_COMMA :
  1250. Begin
  1251. if operandnum > MaxOperands then
  1252. Message(asmr_e_too_many_operands)
  1253. else
  1254. Inc(operandnum);
  1255. Consume(AS_COMMA);
  1256. end;
  1257. { Typecast, Constant Expression, Type Specifier }
  1258. AS_DWORD,
  1259. AS_BYTE,
  1260. AS_WORD,
  1261. AS_TBYTE,
  1262. AS_QWORD :
  1263. Begin
  1264. { load the size in a temp variable, so it can be set when the
  1265. operand is read }
  1266. Case actasmtoken of
  1267. AS_DWORD : size:=S_L;
  1268. AS_WORD : size:=S_W;
  1269. AS_BYTE : size:=S_B;
  1270. AS_QWORD : size:=S_IQ;
  1271. AS_TBYTE : size:=S_FX;
  1272. end;
  1273. Consume(actasmtoken);
  1274. if actasmtoken=AS_PTR then
  1275. begin
  1276. Consume(AS_PTR);
  1277. Operands[operandnum]^.InitRef;
  1278. end;
  1279. Operands[operandnum]^.BuildOperand;
  1280. { now set the size which was specified by the override }
  1281. Operands[operandnum]^.size:=size;
  1282. end;
  1283. { Type specifier }
  1284. AS_NEAR,
  1285. AS_FAR :
  1286. Begin
  1287. if actasmtoken = AS_NEAR then
  1288. Message(asmr_w_near_ignored)
  1289. else
  1290. Message(asmr_w_far_ignored);
  1291. Consume(actasmtoken);
  1292. if actasmtoken=AS_PTR then
  1293. begin
  1294. Consume(AS_PTR);
  1295. Operands[operandnum]^.InitRef;
  1296. end;
  1297. Operands[operandnum]^.BuildOperand;
  1298. end;
  1299. else
  1300. Operands[operandnum]^.BuildOperand;
  1301. end; { end case }
  1302. until false;
  1303. Ops:=operandnum;
  1304. end;
  1305. Procedure BuildConstant(maxvalue: longint);
  1306. var
  1307. strlength: byte;
  1308. asmsym,
  1309. expr: string;
  1310. value : longint;
  1311. Begin
  1312. strlength:=0; { assume it is a DB }
  1313. Repeat
  1314. Case actasmtoken of
  1315. AS_STRING:
  1316. Begin
  1317. if maxvalue = $ffff then
  1318. strlength:=2
  1319. else
  1320. if maxvalue = $ffffffff then
  1321. strlength:=4;
  1322. { DD and DW cases }
  1323. if strlength <> 0 then
  1324. Begin
  1325. if Not PadZero(actasmpattern,strlength) then
  1326. Message(scan_f_string_exceeds_line);
  1327. end;
  1328. expr:=actasmpattern;
  1329. Consume(AS_STRING);
  1330. Case actasmtoken of
  1331. AS_COMMA:
  1332. Consume(AS_COMMA);
  1333. AS_SEPARATOR: ;
  1334. else
  1335. Message(asmr_e_invalid_string_expression);
  1336. end;
  1337. ConcatString(curlist,expr);
  1338. end;
  1339. AS_PLUS,
  1340. AS_MINUS,
  1341. AS_LPAREN,
  1342. AS_NOT,
  1343. AS_INTNUM,
  1344. AS_ID :
  1345. Begin
  1346. BuildConstSymbolExpression(false,value,asmsym);
  1347. if asmsym<>'' then
  1348. begin
  1349. if maxvalue<>$ffffffff then
  1350. Message(asmr_w_const32bit_for_address);
  1351. ConcatConstSymbol(curlist,asmsym,value)
  1352. end
  1353. else
  1354. ConcatConstant(curlist,value,maxvalue);
  1355. end;
  1356. AS_COMMA:
  1357. Consume(AS_COMMA);
  1358. AS_SEPARATOR:
  1359. break;
  1360. else
  1361. begin
  1362. Message(asmr_e_syn_constant);
  1363. RecoverConsume(false);
  1364. end
  1365. end;
  1366. Until false;
  1367. end;
  1368. Function Assemble: Ptree;
  1369. Var
  1370. hl : PAsmLabel;
  1371. instr : T386IntelInstruction;
  1372. Begin
  1373. Message1(asmr_d_start_reading,'intel');
  1374. inexpression:=FALSE;
  1375. firsttoken:=TRUE;
  1376. if assigned(procinfo.retdef) and
  1377. (is_fpu(procinfo.retdef) or
  1378. ret_in_acc(procinfo.retdef)) then
  1379. procinfo.funcret_is_valid:=true;
  1380. { sets up all opcode and register tables in uppercase }
  1381. if not _asmsorted then
  1382. Begin
  1383. SetupTables;
  1384. _asmsorted:=TRUE;
  1385. end;
  1386. curlist:=new(paasmoutput,init);
  1387. { setup label linked list }
  1388. new(LocalLabelList,Init);
  1389. { start tokenizer }
  1390. c:=current_scanner^.asmgetchar;
  1391. gettoken;
  1392. { main loop }
  1393. repeat
  1394. case actasmtoken of
  1395. AS_LLABEL:
  1396. Begin
  1397. if CreateLocalLabel(actasmpattern,hl,true) then
  1398. ConcatLabel(curlist,hl);
  1399. Consume(AS_LLABEL);
  1400. end;
  1401. AS_LABEL:
  1402. Begin
  1403. if SearchLabel(upper(actasmpattern),hl,true) then
  1404. ConcatLabel(curlist,hl)
  1405. else
  1406. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1407. Consume(AS_LABEL);
  1408. end;
  1409. AS_DW :
  1410. Begin
  1411. inexpression:=true;
  1412. Consume(AS_DW);
  1413. BuildConstant($ffff);
  1414. inexpression:=false;
  1415. end;
  1416. AS_DB :
  1417. Begin
  1418. inexpression:=true;
  1419. Consume(AS_DB);
  1420. BuildConstant($ff);
  1421. inexpression:=false;
  1422. end;
  1423. AS_DD :
  1424. Begin
  1425. inexpression:=true;
  1426. Consume(AS_DD);
  1427. BuildConstant($ffffffff);
  1428. inexpression:=false;
  1429. end;
  1430. AS_OPCODE :
  1431. Begin
  1432. instr.init;
  1433. instr.BuildOpcode;
  1434. { We need AT&T style operands }
  1435. instr.SwapOperands;
  1436. instr.AddReferenceSizes;
  1437. instr.SetInstructionOpsize;
  1438. instr.CheckOperandSizes;
  1439. instr.ConcatInstruction(curlist);
  1440. instr.done;
  1441. end;
  1442. AS_SEPARATOR :
  1443. Begin
  1444. Consume(AS_SEPARATOR);
  1445. end;
  1446. AS_END :
  1447. break; { end assembly block }
  1448. else
  1449. Begin
  1450. Message(asmr_e_syntax_error);
  1451. { error recovery }
  1452. Consume(actasmtoken);
  1453. end;
  1454. end; { end case }
  1455. until false;
  1456. { Check LocalLabelList }
  1457. LocalLabelList^.CheckEmitted;
  1458. dispose(LocalLabelList,Done);
  1459. { Return the list in an asmnode }
  1460. assemble:=genasmnode(curlist);
  1461. Message1(asmr_d_finish_reading,'intel');
  1462. end;
  1463. {*****************************************************************************
  1464. Initialize
  1465. *****************************************************************************}
  1466. var
  1467. old_exit : pointer;
  1468. procedure ra386int_exit;{$ifndef FPC}far;{$endif}
  1469. begin
  1470. if assigned(iasmops) then
  1471. dispose(iasmops);
  1472. if assigned(iasmregs) then
  1473. dispose(iasmregs);
  1474. exitproc:=old_exit;
  1475. end;
  1476. begin
  1477. old_exit:=exitproc;
  1478. exitproc:=@ra386int_exit;
  1479. end.
  1480. {
  1481. $Log$
  1482. Revision 1.36 1999-06-01 19:56:37 peter
  1483. * fixed llabel with delete the first @
  1484. Revision 1.35 1999/05/27 19:44:59 peter
  1485. * removed oldasm
  1486. * plabel -> pasmlabel
  1487. * -a switches to source writing automaticly
  1488. * assembler readers OOPed
  1489. * asmsymbol automaticly external
  1490. * jumptables and other label fixes for asm readers
  1491. Revision 1.34 1999/05/21 13:55:16 peter
  1492. * NEWLAB for label as symbol
  1493. Revision 1.33 1999/05/05 22:22:03 peter
  1494. * updated messages
  1495. Revision 1.32 1999/05/04 21:45:02 florian
  1496. * changes to compile it with Delphi 4.0
  1497. Revision 1.31 1999/05/01 13:48:41 peter
  1498. * merged nasm compiler
  1499. Revision 1.6 1999/04/26 23:26:18 peter
  1500. * redesigned record offset parsing to support nested records
  1501. * normal compiler uses the redesigned createvarinstr()
  1502. Revision 1.5 1999/04/20 11:01:24 peter
  1503. * better tokenpos info
  1504. Revision 1.4 1999/04/14 09:07:46 peter
  1505. * asm reader improvements
  1506. Revision 1.3 1999/03/06 17:24:27 peter
  1507. * rewritten intel parser a lot, especially reference reading
  1508. * size checking added for asm parsers
  1509. Revision 1.2 1999/03/02 02:56:31 peter
  1510. + stabs support for binary writers
  1511. * more fixes and missing updates from the previous commit :(
  1512. Revision 1.1 1999/03/01 15:46:26 peter
  1513. * ag386bin finally make cycles correct
  1514. * prefixes are now also normal opcodes
  1515. }