ra386int.pas 43 KB

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