ra386att.pas 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091
  1. {
  2. $Id$
  3. Copyright (c) 1997-99 by Carl Eric Codere and Peter Vreman
  4. Does the parsing for the AT&T 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. {$N+,E+}
  20. {$endif TP}
  21. Unit Ra386att;
  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,symtable,scanner,hcodegen
  31. ,i386base
  32. ,rautils,ra386;
  33. type
  34. tasmtoken = (
  35. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  36. AS_REALNUM,AS_COMMA,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,AS_DOLLAR,
  39. {------------------ Assembler directives --------------------}
  40. AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,AS_ALIGN,AS_ASCII,
  41. AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
  42. AS_DATA,AS_TEXT,AS_END,
  43. {------------------ Assembler Operators --------------------}
  44. AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR);
  45. tasmkeyword = string[8];
  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. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  52. _count_asmprefixes = 5;
  53. _count_asmspecialops = 25;
  54. _count_asmoverrides = 3;
  55. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  56. ('.byte','.word','.long','.quad','.globl','.align','.ascii',
  57. '.asciz','.lcomm','.comm','.single','.double','.tfloat',
  58. '.data','.text','END');
  59. const
  60. newline = #10;
  61. firsttoken : boolean = TRUE;
  62. operandnum : byte = 0;
  63. charcount : byte = 0;
  64. var
  65. _asmsorted,
  66. inexpression : boolean;
  67. curlist : paasmoutput;
  68. c : char;
  69. actasmtoken : tasmtoken;
  70. prevasmtoken : tasmtoken;
  71. actasmpattern : string;
  72. actopcode : tasmop;
  73. actasmregister : tregister;
  74. actopsize : topsize;
  75. actcondition : tasmcond;
  76. Instr : TInstruction;
  77. labellist : TAsmLabelList;
  78. iasmops : ^op2strtable;
  79. iasmregs : ^reg2strtable;
  80. Procedure SetupTables;
  81. { creates uppercased symbol tables for speed access }
  82. var
  83. i : tasmop;
  84. j : tregister;
  85. Begin
  86. Message(assem_d_creating_lookup_tables);
  87. { opcodes }
  88. new(iasmops);
  89. for i:=firstop to lastop do
  90. iasmops^[i] := upper(att_op2str[i]);
  91. { registers }
  92. new(iasmregs);
  93. for j:=firstreg to lastreg do
  94. iasmregs^[j] := upper(att_reg2str[j]);
  95. end;
  96. {---------------------------------------------------------------------}
  97. { Routines for the tokenizing }
  98. {---------------------------------------------------------------------}
  99. function is_asmopcode(const s: string):boolean;
  100. const
  101. att_sizesuffixstr : array[0..8] of string[2] = (
  102. '','B','W','L','BW','BL','WL','Q','T'
  103. );
  104. att_sizesuffix : array[0..8] of topsize = (
  105. S_NO,S_B,S_W,S_L,S_BW,S_BL,S_WL,S_IQ,S_FX
  106. );
  107. var
  108. i : tasmop;
  109. cond : string[4];
  110. cnd : tasmcond;
  111. len,
  112. j,
  113. sufidx : longint;
  114. hid : string;
  115. Begin
  116. is_asmopcode:=FALSE;
  117. actopcode:=A_None;
  118. actcondition:=C_None;
  119. actopsize:=S_NO;
  120. { search for all possible suffixes }
  121. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  122. begin
  123. len:=length(s)-length(att_sizesuffixstr[sufidx]);
  124. if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
  125. begin
  126. { here we search the entire table... }
  127. hid:=copy(s,1,len);
  128. for i:=firstop to lastop do
  129. if (length(hid) > 0) and (hid=iasmops^[i]) then
  130. begin
  131. actopsize:=att_sizesuffix[sufidx];
  132. actopcode:=i;
  133. actasmtoken:=AS_OPCODE;
  134. is_asmopcode:=TRUE;
  135. exit;
  136. end;
  137. { not found, check condition opcodes }
  138. j:=0;
  139. while (j<CondAsmOps) do
  140. begin
  141. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  142. begin
  143. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  144. if cond<>'' then
  145. begin
  146. for cnd:=low(TasmCond) to high(TasmCond) do
  147. if Cond=Upper(cond2str[cnd]) then
  148. begin
  149. actopcode:=CondASmOp[j];
  150. actopsize:=att_sizesuffix[sufidx];
  151. actcondition:=cnd;
  152. actasmtoken:=AS_OPCODE;
  153. is_asmopcode:=TRUE;
  154. exit;
  155. end;
  156. end;
  157. end;
  158. inc(j);
  159. end;
  160. end;
  161. end;
  162. end;
  163. Function is_asmdirective(const s: string):boolean;
  164. var
  165. i : longint;
  166. Begin
  167. for i:=0 to _count_asmdirectives do
  168. if s=_asmdirectives[i] then
  169. begin
  170. actasmtoken:=tasmtoken(longint(firstdirective)+i);
  171. is_asmdirective:=true;
  172. exit;
  173. end;
  174. is_asmdirective:=false;
  175. end;
  176. Function is_register(const s: string):boolean;
  177. Var
  178. i : tregister;
  179. Begin
  180. actasmregister:=R_NO;
  181. for i:=firstreg to lastreg do
  182. if s=iasmregs^[i] then
  183. begin
  184. actasmtoken:=AS_REGISTER;
  185. actasmregister:=i;
  186. is_register:=true;
  187. exit;
  188. end;
  189. is_register:=false;
  190. end;
  191. Procedure GetToken;
  192. {*********************************************************************}
  193. { FUNCTION GetToken: tasmtoken; }
  194. { Description: This routine returns intel assembler tokens and }
  195. { does some minor syntax error checking. }
  196. {*********************************************************************}
  197. var
  198. forcelabel: boolean;
  199. errorflag : boolean;
  200. len : longint;
  201. begin
  202. { save old token and reset new token }
  203. prevasmtoken:=actasmtoken;
  204. actasmtoken:=AS_NONE;
  205. { reset }
  206. errorflag:=FALSE;
  207. forcelabel:=FALSE;
  208. actasmpattern:='';
  209. { while space and tab , continue scan... }
  210. while c in [' ',#9] do
  211. c:=current_scanner^.asmgetchar;
  212. { get token pos }
  213. if not (c in [newline,#13,'{',';']) then
  214. current_scanner^.gettokenpos;
  215. { Local Label, Label, Directive, Prefix or Opcode }
  216. if firsttoken and not(c in [newline,#13,'{',';']) then
  217. begin
  218. firsttoken:=FALSE;
  219. len:=0;
  220. { directive or local label }
  221. if c = '.' then
  222. begin
  223. inc(len);
  224. actasmpattern[len]:=c;
  225. { Let us point to the next character }
  226. c:=current_scanner^.asmgetchar;
  227. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  228. begin
  229. inc(len);
  230. actasmpattern[len]:=c;
  231. c:=current_scanner^.asmgetchar;
  232. end;
  233. actasmpattern[0]:=chr(len);
  234. { this is a local label... }
  235. if (actasmpattern[2] = 'L') and (c = ':') then
  236. Begin
  237. { local variables are case sensitive }
  238. actasmtoken:=AS_LLABEL;
  239. { delete .L }
  240. delete(actasmpattern,1,2);
  241. { point to next character ... }
  242. c:=current_scanner^.asmgetchar;
  243. exit;
  244. end
  245. { must be a directive }
  246. else
  247. Begin
  248. { directives are case sensitive!! }
  249. if is_asmdirective(actasmpattern) then
  250. exit;
  251. Message1(assem_e_not_directive_or_local_symbol,actasmpattern);
  252. end;
  253. end;
  254. { only opcodes and global labels are allowed now. }
  255. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  256. begin
  257. inc(len);
  258. actasmpattern[len]:=c;
  259. c:=current_scanner^.asmgetchar;
  260. end;
  261. actasmpattern[0]:=chr(len);
  262. { Label ? }
  263. if c = ':' then
  264. begin
  265. actasmtoken:=AS_LABEL;
  266. { let us point to the next character }
  267. c:=current_scanner^.asmgetchar;
  268. exit;
  269. end;
  270. { Opcode ? }
  271. If is_asmopcode(upper(actasmpattern)) then
  272. Begin
  273. uppervar(actasmpattern);
  274. exit;
  275. end;
  276. { End of assemblerblock ? }
  277. if upper(actasmpattern) = 'END' then
  278. begin
  279. actasmtoken:=AS_END;
  280. exit;
  281. end;
  282. actasmtoken:=AS_NONE;
  283. end
  284. else { else firsttoken }
  285. { Here we must handle all possible cases }
  286. begin
  287. case c of
  288. '.' : { possiblities : - local label reference , such as in jmp @local1 }
  289. { - field of object/record }
  290. { - directive. }
  291. begin
  292. if (prevasmtoken=AS_ID) then
  293. begin
  294. c:=current_scanner^.asmgetchar;
  295. actasmtoken:=AS_DOT;
  296. exit;
  297. end;
  298. actasmpattern:=c;
  299. c:=current_scanner^.asmgetchar;
  300. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  301. begin
  302. actasmpattern:=actasmpattern + c;
  303. c:=current_scanner^.asmgetchar;
  304. end;
  305. if is_asmdirective(actasmpattern) then
  306. exit;
  307. { local label references and directives }
  308. { are case sensitive }
  309. actasmtoken:=AS_ID;
  310. exit;
  311. end;
  312. { identifier, register, prefix or directive }
  313. '_','A'..'Z','a'..'z':
  314. begin
  315. len:=0;
  316. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  317. begin
  318. inc(len);
  319. actasmpattern[len]:=c;
  320. c:=current_scanner^.asmgetchar;
  321. end;
  322. actasmpattern[0]:=chr(len);
  323. uppervar(actasmpattern);
  324. { Opcode, can only be when the previous was a prefix }
  325. If (OperandNum=0) and is_asmopcode(upper(actasmpattern)) then
  326. Begin
  327. uppervar(actasmpattern);
  328. exit;
  329. end;
  330. { check for end which is a reserved word unlike the opcodes }
  331. if actasmpattern = 'END' then
  332. Begin
  333. actasmtoken:=AS_END;
  334. exit;
  335. end;
  336. actasmtoken:=AS_ID;
  337. exit;
  338. end;
  339. '%' : { register or modulo }
  340. begin
  341. len:=1;
  342. actasmpattern[len]:='%';
  343. c:=current_scanner^.asmgetchar;
  344. while c in ['a'..'z','A'..'Z','0'..'9'] do
  345. Begin
  346. inc(len);
  347. actasmpattern[len]:=c;
  348. c:=current_scanner^.asmgetchar;
  349. end;
  350. actasmpattern[0]:=chr(len);
  351. uppervar(actasmpattern);
  352. if (actasmpattern = '%ST') and (c='(') then
  353. Begin
  354. actasmpattern:=actasmpattern+c;
  355. c:=current_scanner^.asmgetchar;
  356. if c in ['0'..'9'] then
  357. actasmpattern:=actasmpattern + c
  358. else
  359. Message(assem_e_invalid_fpu_register);
  360. c:=current_scanner^.asmgetchar;
  361. if c <> ')' then
  362. Message(assem_e_invalid_fpu_register)
  363. else
  364. Begin
  365. actasmpattern:=actasmpattern + c;
  366. c:=current_scanner^.asmgetchar; { let us point to next character. }
  367. end;
  368. end;
  369. if is_register(actasmpattern) then
  370. exit;
  371. Message(assem_w_modulo_not_supported);
  372. end;
  373. '1'..'9': { integer number }
  374. begin
  375. len:=0;
  376. while c in ['0'..'9'] do
  377. Begin
  378. inc(len);
  379. actasmpattern[len]:=c;
  380. c:=current_scanner^.asmgetchar;
  381. end;
  382. actasmpattern[0]:=chr(len);
  383. actasmpattern:=tostr(ValDecimal(actasmpattern));
  384. actasmtoken:=AS_INTNUM;
  385. exit;
  386. end;
  387. '0' : { octal,hexa,real or binary number. }
  388. begin
  389. actasmpattern:=c;
  390. c:=current_scanner^.asmgetchar;
  391. case upcase(c) of
  392. 'B': { binary }
  393. Begin
  394. c:=current_scanner^.asmgetchar;
  395. while c in ['0','1'] do
  396. Begin
  397. actasmpattern:=actasmpattern + c;
  398. c:=current_scanner^.asmgetchar;
  399. end;
  400. actasmpattern:=tostr(ValBinary(actasmpattern));
  401. actasmtoken:=AS_INTNUM;
  402. exit;
  403. end;
  404. 'D': { real }
  405. Begin
  406. c:=current_scanner^.asmgetchar;
  407. { get ridd of the 0d }
  408. if (c in ['+','-']) then
  409. begin
  410. actasmpattern:=c;
  411. c:=current_scanner^.asmgetchar;
  412. end
  413. else
  414. actasmpattern:='';
  415. while c in ['0'..'9'] do
  416. Begin
  417. actasmpattern:=actasmpattern + c;
  418. c:=current_scanner^.asmgetchar;
  419. end;
  420. if c='.' then
  421. begin
  422. actasmpattern:=actasmpattern + c;
  423. c:=current_scanner^.asmgetchar;
  424. while c in ['0'..'9'] do
  425. Begin
  426. actasmpattern:=actasmpattern + c;
  427. c:=current_scanner^.asmgetchar;
  428. end;
  429. if upcase(c) = 'E' then
  430. begin
  431. actasmpattern:=actasmpattern + c;
  432. c:=current_scanner^.asmgetchar;
  433. if (c in ['+','-']) then
  434. begin
  435. actasmpattern:=actasmpattern + c;
  436. c:=current_scanner^.asmgetchar;
  437. end;
  438. while c in ['0'..'9'] do
  439. Begin
  440. actasmpattern:=actasmpattern + c;
  441. c:=current_scanner^.asmgetchar;
  442. end;
  443. end;
  444. actasmtoken:=AS_REALNUM;
  445. exit;
  446. end
  447. else
  448. begin
  449. Message1(assem_e_invalid_float_const,actasmpattern+c);
  450. actasmtoken:=AS_NONE;
  451. end;
  452. end;
  453. 'X': { hexadecimal }
  454. Begin
  455. c:=current_scanner^.asmgetchar;
  456. while c in ['0'..'9','a'..'f','A'..'F'] do
  457. Begin
  458. actasmpattern:=actasmpattern + c;
  459. c:=current_scanner^.asmgetchar;
  460. end;
  461. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  462. actasmtoken:=AS_INTNUM;
  463. exit;
  464. end;
  465. '1'..'7': { octal }
  466. begin
  467. actasmpattern:=actasmpattern + c;
  468. while c in ['0'..'7'] do
  469. Begin
  470. actasmpattern:=actasmpattern + c;
  471. c:=current_scanner^.asmgetchar;
  472. end;
  473. actasmpattern:=tostr(ValOctal(actasmpattern));
  474. actasmtoken:=AS_INTNUM;
  475. exit;
  476. end;
  477. else { octal number zero value...}
  478. Begin
  479. actasmpattern:=tostr(ValOctal(actasmpattern));
  480. actasmtoken:=AS_INTNUM;
  481. exit;
  482. end;
  483. end; { end case }
  484. end;
  485. '&' :
  486. begin
  487. c:=current_scanner^.asmgetchar;
  488. actasmtoken:=AS_AND;
  489. end;
  490. '''' : { char }
  491. begin
  492. actasmpattern:='';
  493. repeat
  494. c:=current_scanner^.asmgetchar;
  495. case c of
  496. '\' :
  497. begin
  498. { copy also the next char so \" is parsed correctly }
  499. c:=current_scanner^.asmgetchar;
  500. actasmpattern:=actasmpattern+c;
  501. end;
  502. '''' :
  503. begin
  504. c:=current_scanner^.asmgetchar;
  505. break;
  506. end;
  507. newline:
  508. Message(scan_f_string_exceeds_line);
  509. else
  510. actasmpattern:=actasmpattern+c;
  511. end;
  512. until false;
  513. actasmpattern:=EscapeToPascal(actasmpattern);
  514. actasmtoken:=AS_STRING;
  515. exit;
  516. end;
  517. '"' : { string }
  518. begin
  519. actasmpattern:='';
  520. repeat
  521. c:=current_scanner^.asmgetchar;
  522. case c of
  523. '\' :
  524. begin
  525. { copy also the next char so \" is parsed correctly }
  526. c:=current_scanner^.asmgetchar;
  527. actasmpattern:=actasmpattern+c;
  528. end;
  529. '"' :
  530. begin
  531. c:=current_scanner^.asmgetchar;
  532. break;
  533. end;
  534. newline:
  535. Message(scan_f_string_exceeds_line);
  536. else
  537. actasmpattern:=actasmpattern+c;
  538. end;
  539. until false;
  540. actasmpattern:=EscapeToPascal(actasmpattern);
  541. actasmtoken:=AS_STRING;
  542. exit;
  543. end;
  544. '$' :
  545. begin
  546. actasmtoken:=AS_DOLLAR;
  547. c:=current_scanner^.asmgetchar;
  548. exit;
  549. end;
  550. ',' :
  551. begin
  552. actasmtoken:=AS_COMMA;
  553. c:=current_scanner^.asmgetchar;
  554. exit;
  555. end;
  556. '<' :
  557. begin
  558. actasmtoken:=AS_SHL;
  559. c:=current_scanner^.asmgetchar;
  560. if c = '<' then
  561. c:=current_scanner^.asmgetchar;
  562. exit;
  563. end;
  564. '>' :
  565. begin
  566. actasmtoken:=AS_SHL;
  567. c:=current_scanner^.asmgetchar;
  568. if c = '>' then
  569. c:=current_scanner^.asmgetchar;
  570. exit;
  571. end;
  572. '|' :
  573. begin
  574. actasmtoken:=AS_OR;
  575. c:=current_scanner^.asmgetchar;
  576. exit;
  577. end;
  578. '^' :
  579. begin
  580. actasmtoken:=AS_XOR;
  581. c:=current_scanner^.asmgetchar;
  582. exit;
  583. end;
  584. '!' :
  585. begin
  586. Message(assem_e_nor_not_supported);
  587. c:=current_scanner^.asmgetchar;
  588. actasmtoken:=AS_NONE;
  589. exit;
  590. end;
  591. '(' :
  592. begin
  593. actasmtoken:=AS_LPAREN;
  594. c:=current_scanner^.asmgetchar;
  595. exit;
  596. end;
  597. ')' :
  598. begin
  599. actasmtoken:=AS_RPAREN;
  600. c:=current_scanner^.asmgetchar;
  601. exit;
  602. end;
  603. ':' :
  604. begin
  605. actasmtoken:=AS_COLON;
  606. c:=current_scanner^.asmgetchar;
  607. exit;
  608. end;
  609. '+' :
  610. begin
  611. actasmtoken:=AS_PLUS;
  612. c:=current_scanner^.asmgetchar;
  613. exit;
  614. end;
  615. '-' :
  616. begin
  617. actasmtoken:=AS_MINUS;
  618. c:=current_scanner^.asmgetchar;
  619. exit;
  620. end;
  621. '*' :
  622. begin
  623. actasmtoken:=AS_STAR;
  624. c:=current_scanner^.asmgetchar;
  625. exit;
  626. end;
  627. '/' :
  628. begin
  629. c:=current_scanner^.asmgetchar;
  630. actasmtoken:=AS_SLASH;
  631. exit;
  632. end;
  633. '{',#13,newline,';' :
  634. begin
  635. { the comment is read by asmgetchar }
  636. c:=current_scanner^.asmgetchar;
  637. firsttoken:=TRUE;
  638. actasmtoken:=AS_SEPARATOR;
  639. exit;
  640. end;
  641. else
  642. Begin
  643. Message(scan_f_illegal_char);
  644. end;
  645. end;
  646. end;
  647. end;
  648. procedure consume(t : tasmtoken);
  649. begin
  650. if t<>actasmtoken then
  651. Message(assem_e_syntax_error);
  652. gettoken;
  653. { if the token must be ignored, then }
  654. { get another token to parse. }
  655. if actasmtoken = AS_NONE then
  656. gettoken;
  657. end;
  658. procedure RecoverConsume(allowcomma:boolean);
  659. begin
  660. While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
  661. begin
  662. if allowcomma and (actasmtoken=AS_COMMA) then
  663. break;
  664. Consume(actasmtoken);
  665. end;
  666. end;
  667. {*****************************************************************************
  668. Parsing Helpers
  669. *****************************************************************************}
  670. Procedure BuildRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  671. { Description: This routine builds up a record offset after a AS_DOT }
  672. { token is encountered. }
  673. { On entry actasmtoken should be equal to AS_DOT }
  674. var
  675. s : string;
  676. Begin
  677. offset:=0;
  678. size:=0;
  679. s:=expr;
  680. while (actasmtoken=AS_DOT) do
  681. begin
  682. Consume(AS_DOT);
  683. if actasmtoken=AS_ID then
  684. begin
  685. s:=s+'.'+actasmpattern;
  686. Consume(AS_ID);
  687. end
  688. else
  689. begin
  690. Message(assem_e_syntax_error);
  691. RecoverConsume(true);
  692. break;
  693. end;
  694. end;
  695. if not GetRecordOffsetSize(s,offset,size) then
  696. Comment(V_Error,'Error building record offset');
  697. end;
  698. Procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:longint;var asmsym:string);
  699. {*********************************************************************}
  700. { FUNCTION BuildConstExpression: longint }
  701. { Description: This routine calculates a constant expression to }
  702. { a given value. The return value is the value calculated from }
  703. { the expression. }
  704. { The following tokens (not strings) are recognized: }
  705. { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  706. {*********************************************************************}
  707. { ENTRY: On entry the token should be any valid expression token. }
  708. { EXIT: On Exit the token points to any token after the closing }
  709. { RBRACKET }
  710. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  711. { invalid tokens. }
  712. {*********************************************************************}
  713. var
  714. hs,tempstr,expr : string;
  715. parenlevel,l,k : longint;
  716. errorflag : boolean;
  717. prevtok : tasmtoken;
  718. sym : psym;
  719. hl : plabel;
  720. Begin
  721. asmsym:='';
  722. value:=0;
  723. errorflag:=FALSE;
  724. tempstr:='';
  725. expr:='';
  726. inexpression:=TRUE;
  727. parenlevel:=0;
  728. Repeat
  729. Case actasmtoken of
  730. AS_LPAREN:
  731. Begin
  732. { Exit if ref? }
  733. if allowref and (prevasmtoken in [AS_INTNUM,AS_ID]) then
  734. break;
  735. Consume(AS_LPAREN);
  736. expr:=expr + '(';
  737. inc(parenlevel);
  738. end;
  739. AS_RPAREN:
  740. Begin
  741. { end of ref ? }
  742. if (parenlevel=0) and betweenbracket then
  743. break;
  744. Consume(AS_RPAREN);
  745. expr:=expr + ')';
  746. dec(parenlevel);
  747. end;
  748. AS_SHL:
  749. Begin
  750. Consume(AS_SHL);
  751. expr:=expr + '<';
  752. end;
  753. AS_SHR:
  754. Begin
  755. Consume(AS_SHR);
  756. expr:=expr + '>';
  757. end;
  758. AS_SLASH:
  759. Begin
  760. Consume(AS_SLASH);
  761. expr:=expr + '/';
  762. end;
  763. AS_MOD:
  764. Begin
  765. Consume(AS_MOD);
  766. expr:=expr + '%';
  767. end;
  768. AS_STAR:
  769. Begin
  770. Consume(AS_STAR);
  771. expr:=expr + '*';
  772. end;
  773. AS_PLUS:
  774. Begin
  775. Consume(AS_PLUS);
  776. expr:=expr + '+';
  777. end;
  778. AS_MINUS:
  779. Begin
  780. Consume(AS_MINUS);
  781. expr:=expr + '-';
  782. end;
  783. AS_AND:
  784. Begin
  785. Consume(AS_AND);
  786. expr:=expr + '&';
  787. end;
  788. AS_NOT:
  789. Begin
  790. Consume(AS_NOT);
  791. expr:=expr + '~';
  792. end;
  793. AS_XOR:
  794. Begin
  795. Consume(AS_XOR);
  796. expr:=expr + '^';
  797. end;
  798. AS_OR:
  799. Begin
  800. Consume(AS_OR);
  801. expr:=expr + '|';
  802. end;
  803. AS_INTNUM:
  804. Begin
  805. expr:=expr + actasmpattern;
  806. Consume(AS_INTNUM);
  807. end;
  808. AS_DOLLAR:
  809. begin
  810. Consume(AS_DOLLAR);
  811. if actasmtoken<>AS_ID then
  812. Comment(V_Error,'assem_e_dollar_without_identifier');
  813. end;
  814. AS_ID:
  815. Begin
  816. tempstr:=actasmpattern;
  817. prevtok:=prevasmtoken;
  818. consume(AS_ID);
  819. if actasmtoken=AS_DOT then
  820. begin
  821. BuildRecordOffsetSize(tempstr,l,k);
  822. str(l, tempstr);
  823. expr:=expr + tempstr;
  824. end
  825. else
  826. if SearchIConstant(tempstr,l) then
  827. begin
  828. str(l, tempstr);
  829. expr:=expr + tempstr;
  830. end
  831. else
  832. begin
  833. hs:='';
  834. if SearchLabel(tempstr,hl) then
  835. hs:=lab2str(hl)
  836. else
  837. begin
  838. getsym(tempstr,false);
  839. sym:=srsym;
  840. if assigned(sym) then
  841. begin
  842. if sym^.owner^.symtabletype in [localsymtable,parasymtable] then
  843. Writeln('can''t use local variable or parameters here');
  844. case srsym^.typ of
  845. varsym :
  846. hs:=pvarsym(srsym)^.mangledname;
  847. typedconstsym :
  848. hs:=ptypedconstsym(srsym)^.mangledname;
  849. procsym :
  850. hs:=pprocsym(srsym)^.mangledname;
  851. else
  852. Writeln('Error: wrong sym type');
  853. end;
  854. end
  855. else
  856. Message1(assem_e_unknown_id,tempstr);
  857. end;
  858. { symbol found? }
  859. if hs<>'' then
  860. begin
  861. if needofs and (prevtok<>AS_DOLLAR) then
  862. Comment(V_Error,'assem_e_need_offset');
  863. if asmsym='' then
  864. asmsym:=hs
  865. else
  866. Comment(V_Error,'assem_e_cant_have_multiple_relocatable_symbols');
  867. if (expr='') or (expr[length(expr)]='+') then
  868. begin
  869. delete(expr,length(expr),1);
  870. if not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END]) then
  871. Comment(V_Error,'assem_e_only_add_relocatable_symbol');
  872. end
  873. else
  874. Comment(V_Error,'assem_e_only_add_relocatable_symbol');
  875. end;
  876. end;
  877. end;
  878. AS_SEPARATOR,
  879. AS_COMMA:
  880. Begin
  881. break;
  882. end;
  883. else
  884. Begin
  885. { write error only once. }
  886. if not errorflag then
  887. Message(assem_e_invalid_constant_expression);
  888. { consume tokens until we find COMMA or SEPARATOR }
  889. Consume(actasmtoken);
  890. errorflag:=TRUE;
  891. end;
  892. end;
  893. Until false;
  894. { calculate expression }
  895. if not ErrorFlag then
  896. value:=CalculateExpression(expr)
  897. else
  898. value:=0;
  899. { no longer in an expression }
  900. inexpression:=FALSE;
  901. end;
  902. Function BuildConstExpression(allowref,betweenbracket:boolean): longint;
  903. var
  904. l : longint;
  905. hs : string;
  906. begin
  907. BuildConstSymbolExpression(allowref,betweenbracket,false,l,hs);
  908. if hs<>'' then
  909. Comment(V_Error,'no relocatable symbols allowed');
  910. BuildConstExpression:=l;
  911. end;
  912. Procedure BuildRealConstant(typ : tfloattype);
  913. {*********************************************************************}
  914. { PROCEDURE BuilRealConst }
  915. { Description: This routine calculates a constant expression to }
  916. { a given value. The return value is the value calculated from }
  917. { the expression. }
  918. { The following tokens (not strings) are recognized: }
  919. { +/-,numbers and real numbers }
  920. {*********************************************************************}
  921. { ENTRY: On entry the token should be any valid expression token. }
  922. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  923. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  924. { invalid tokens. }
  925. {*********************************************************************}
  926. var expr: string;
  927. tempstr: string;
  928. r : bestreal;
  929. code : word;
  930. negativ : boolean;
  931. errorflag: boolean;
  932. Begin
  933. errorflag:=FALSE;
  934. Repeat
  935. negativ:=false;
  936. expr:='';
  937. tempstr:='';
  938. if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  939. else if actasmtoken=AS_MINUS then
  940. begin
  941. negativ:=true;
  942. consume(AS_MINUS);
  943. end;
  944. Case actasmtoken of
  945. AS_INTNUM: Begin
  946. expr:=actasmpattern;
  947. Consume(AS_INTNUM);
  948. end;
  949. AS_REALNUM: Begin
  950. expr:=actasmpattern;
  951. { in ATT syntax you have 0d in front of the real }
  952. { should this be forced ? yes i think so, as to }
  953. { conform to gas as much as possible. }
  954. if (expr[1]='0') and (upper(expr[2])='D') then
  955. expr:=copy(expr,3,255);
  956. Consume(AS_REALNUM);
  957. end;
  958. else
  959. Begin
  960. { only write error once. }
  961. if not errorflag then
  962. Message(assem_e_invalid_real_const);
  963. { consume tokens until we find COMMA or SEPARATOR }
  964. Consume(actasmtoken);
  965. errorflag:=TRUE;
  966. End;
  967. end;
  968. { go to next term }
  969. if (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  970. Begin
  971. if negativ then expr:='-'+expr;
  972. val(expr,r,code);
  973. if code<>0 then
  974. Begin
  975. r:=0;
  976. Message(assem_e_invalid_real_const);
  977. ConcatRealConstant(curlist,r,typ);
  978. End
  979. else
  980. Begin
  981. ConcatRealConstant(curlist,r,typ);
  982. End;
  983. end
  984. else
  985. Message(assem_e_invalid_real_const);
  986. Until actasmtoken=AS_SEPARATOR;
  987. end;
  988. Procedure BuildReference(var Instr: TInstruction);
  989. {*********************************************************************}
  990. { PROCEDURE BuildReference }
  991. { Description: This routine builds up an expression after a LPAREN }
  992. { token is encountered. }
  993. { On entry actasmtoken should be equal to AS_LPAREN }
  994. {*********************************************************************}
  995. { EXIT CONDITION: On exit the routine should point to either the }
  996. { AS_COMMA or AS_SEPARATOR token. }
  997. {*********************************************************************}
  998. procedure Consume_RParen;
  999. begin
  1000. if actasmtoken <> AS_RPAREN then
  1001. Begin
  1002. Message(assem_e_invalid_reference);
  1003. RecoverConsume(true);
  1004. end
  1005. else
  1006. begin
  1007. Consume(AS_RPAREN);
  1008. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1009. Begin
  1010. Message(assem_e_invalid_reference);
  1011. RecoverConsume(true);
  1012. end;
  1013. end;
  1014. end;
  1015. var
  1016. l:longint;
  1017. Begin
  1018. Consume(AS_LPAREN);
  1019. initAsmRef(instr,operandnum);
  1020. Case actasmtoken of
  1021. AS_INTNUM,
  1022. AS_MINUS,
  1023. AS_PLUS: { absolute offset, such as fs:(0x046c) }
  1024. Begin
  1025. { offset(offset) is invalid }
  1026. If Instr.Operands[OperandNum].Ref.Offset <> 0 Then
  1027. Begin
  1028. Message(assem_e_invalid_reference);
  1029. RecoverConsume(true);
  1030. End
  1031. Else
  1032. Begin
  1033. Instr.Operands[OperandNum].Ref.Offset:=BuildConstExpression(false,true);
  1034. Consume_RParen;
  1035. end;
  1036. exit;
  1037. End;
  1038. AS_REGISTER: { (reg ... }
  1039. Begin
  1040. { Check if there is already a base (mostly ebp,esp) than this is
  1041. not allowed,becuase it will give crashing code }
  1042. if instr.operands[operandnum].ref.base<>R_NO then
  1043. Message(assem_e_cannot_index_relative_var);
  1044. instr.operands[operandnum].ref.base:=actasmregister;
  1045. Consume(AS_REGISTER);
  1046. { can either be a register or a right parenthesis }
  1047. { (reg) }
  1048. if actasmtoken=AS_RPAREN then
  1049. Begin
  1050. Consume_RParen;
  1051. exit;
  1052. end;
  1053. { (reg,reg .. }
  1054. Consume(AS_COMMA);
  1055. if actasmtoken=AS_REGISTER then
  1056. Begin
  1057. instr.operands[operandnum].ref.index:=actasmregister;
  1058. Consume(AS_REGISTER);
  1059. { check for scaling ... }
  1060. case actasmtoken of
  1061. AS_RPAREN:
  1062. Begin
  1063. Consume_RParen;
  1064. exit;
  1065. end;
  1066. AS_COMMA:
  1067. Begin
  1068. Consume(AS_COMMA);
  1069. { we have to process the scaling }
  1070. l:=BuildConstExpression(false,true);
  1071. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  1072. instr.operands[operandnum].ref.scalefactor:=l
  1073. else
  1074. Begin
  1075. Message(assem_e_invalid_scaling_value);
  1076. instr.operands[operandnum].ref.scalefactor:=0;
  1077. end;
  1078. Consume_RParen;
  1079. end;
  1080. else
  1081. Begin
  1082. Message(assem_e_invalid_reference_syntax);
  1083. while (actasmtoken <> AS_SEPARATOR) do
  1084. Consume(actasmtoken);
  1085. end;
  1086. end; { end case }
  1087. end
  1088. else
  1089. Begin
  1090. Message(assem_e_invalid_reference_syntax);
  1091. while (actasmtoken <> AS_SEPARATOR) do
  1092. Consume(actasmtoken);
  1093. end;
  1094. end; {end case }
  1095. AS_COMMA: { (, ... can either be scaling, or index }
  1096. Begin
  1097. Consume(AS_COMMA);
  1098. { Index }
  1099. if (actasmtoken=AS_REGISTER) then
  1100. Begin
  1101. instr.operands[operandnum].ref.index:=actasmregister;
  1102. Consume(AS_REGISTER);
  1103. { check for scaling ... }
  1104. case actasmtoken of
  1105. AS_RPAREN:
  1106. Begin
  1107. Consume_RParen;
  1108. exit;
  1109. end;
  1110. AS_COMMA:
  1111. Begin
  1112. Consume(AS_COMMA);
  1113. { we have to process the scaling }
  1114. l:=BuildConstExpression(false,true);
  1115. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  1116. instr.operands[operandnum].ref.scalefactor:=l
  1117. else
  1118. Begin
  1119. Message(assem_e_invalid_scaling_value);
  1120. instr.operands[operandnum].ref.scalefactor:=0;
  1121. end;
  1122. Consume_RParen;
  1123. end;
  1124. else
  1125. Begin
  1126. Message(assem_e_invalid_reference_syntax);
  1127. while (actasmtoken <> AS_SEPARATOR) do
  1128. Consume(actasmtoken);
  1129. end;
  1130. end; {end case }
  1131. end
  1132. { Scaling }
  1133. else
  1134. Begin
  1135. l:=BuildConstExpression(false,true);
  1136. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  1137. instr.operands[operandnum].ref.scalefactor:=l
  1138. else
  1139. Begin
  1140. Message(assem_e_invalid_scaling_value);
  1141. instr.operands[operandnum].ref.scalefactor:=0;
  1142. end;
  1143. Consume_RParen;
  1144. exit;
  1145. end;
  1146. end;
  1147. else
  1148. Begin
  1149. Message(assem_e_invalid_reference_syntax);
  1150. while (actasmtoken <> AS_SEPARATOR) do
  1151. Consume(actasmtoken);
  1152. end;
  1153. end; { end case }
  1154. end;
  1155. Procedure BuildOperand(var instr: TInstruction);
  1156. Procedure BuildConstOperand(var instr: TInstruction);
  1157. var
  1158. l : longint;
  1159. tempstr : string;
  1160. begin
  1161. BuildConstSymbolExpression(false,false,true,l,tempstr);
  1162. if tempstr<>'' then
  1163. begin
  1164. instr.operands[operandnum].operandtype:=OPR_SYMBOL;
  1165. instr.operands[operandnum].symofs:=l;
  1166. instr.operands[operandnum].symbol:=newasmsymbol(tempstr);
  1167. end
  1168. else
  1169. begin
  1170. instr.operands[operandnum].operandtype:=OPR_CONSTANT;
  1171. instr.operands[operandnum].val:=l;
  1172. end;
  1173. end;
  1174. function MaybeBuildReference:boolean;
  1175. { Try to create a reference, if not a reference is found then false
  1176. is returned }
  1177. begin
  1178. MaybeBuildReference:=true;
  1179. case actasmtoken of
  1180. AS_INTNUM,
  1181. AS_MINUS,
  1182. AS_PLUS:
  1183. Begin
  1184. instr.operands[operandnum].ref.offset:=BuildConstExpression(True,False);
  1185. if actasmtoken<>AS_LPAREN then
  1186. Message(assem_e_invalid_reference_syntax)
  1187. else
  1188. BuildReference(instr);
  1189. end;
  1190. AS_LPAREN:
  1191. BuildReference(instr);
  1192. AS_ID: { only a variable is allowed ... }
  1193. Begin
  1194. { is it a normal variable ? }
  1195. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  1196. begin
  1197. { check for direct symbolic names }
  1198. { only if compiling the system unit }
  1199. if (cs_compilesystem in aktmoduleswitches) then
  1200. begin
  1201. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  1202. Message(assem_e_invalid_seg_override);
  1203. end
  1204. else
  1205. Message(assem_e_invalid_seg_override);
  1206. end;
  1207. Consume(actasmtoken);
  1208. case actasmtoken of
  1209. AS_SEPARATOR,
  1210. AS_COMMA: ;
  1211. AS_LPAREN: BuildReference(instr);
  1212. else
  1213. Begin
  1214. Message(assem_e_invalid_seg_override);
  1215. Consume(actasmtoken);
  1216. end;
  1217. end; {end case }
  1218. end;
  1219. else
  1220. MaybeBuildReference:=false;
  1221. end; { end case }
  1222. end;
  1223. var
  1224. expr,
  1225. tempstr : string;
  1226. tempreg : tregister;
  1227. lab : Pasmlabel;
  1228. hl : plabel;
  1229. tsize,l,
  1230. toffset : longint;
  1231. Begin
  1232. tempstr:='';
  1233. expr:='';
  1234. case actasmtoken of
  1235. AS_LPAREN: { Memory reference or constant expression }
  1236. Begin
  1237. initAsmRef(instr,operandnum);
  1238. BuildReference(instr);
  1239. end;
  1240. AS_DOLLAR: { Constant expression }
  1241. Begin
  1242. Consume(AS_DOLLAR);
  1243. BuildConstOperand(instr);
  1244. end;
  1245. AS_INTNUM,
  1246. AS_MINUS,
  1247. AS_PLUS:
  1248. Begin
  1249. { Constant memory offset }
  1250. { This must absolutely be followed by ( }
  1251. initAsmRef(instr,operandnum);
  1252. instr.operands[operandnum].ref.offset:=BuildConstExpression(True,False);
  1253. if actasmtoken<>AS_LPAREN then
  1254. Message(assem_e_invalid_reference_syntax)
  1255. else
  1256. BuildReference(instr);
  1257. end;
  1258. AS_STAR: { Call from memory address }
  1259. Begin
  1260. Consume(AS_STAR);
  1261. if actasmtoken=AS_REGISTER then
  1262. begin
  1263. instr.operands[operandnum].operandtype:=OPR_REGISTER;
  1264. instr.operands[operandnum].reg:=actasmregister;
  1265. instr.operands[operandnum].size:=reg_2_opsize[actasmregister];
  1266. Consume(AS_REGISTER);
  1267. end
  1268. else
  1269. begin
  1270. initAsmRef(instr,operandnum);
  1271. if not MaybeBuildReference then
  1272. Message(assem_e_syn_opcode_operand);
  1273. end;
  1274. { this is only allowed for call's and jmp's }
  1275. case instr.opcode of
  1276. A_CALL,
  1277. A_JMP,
  1278. A_Jcc : ;
  1279. else
  1280. Message(assem_e_syn_opcode_operand);
  1281. end;
  1282. end;
  1283. AS_ID: { A constant expression, or a Variable ref. }
  1284. Begin
  1285. { Local label ? }
  1286. if (actasmpattern[1] ='.') and (actasmpattern[2] = 'L') then
  1287. Begin
  1288. delete(actasmpattern,1,2);
  1289. if actasmpattern = '' then
  1290. Message(assem_e_null_label_ref_not_allowed);
  1291. lab:=labellist.search(actasmpattern);
  1292. { check if the label is already defined }
  1293. { if so, we then check if the plabel is }
  1294. { non-nil, if so we add it to instruction }
  1295. if assigned(lab) then
  1296. Begin
  1297. if assigned(lab^.lab) then
  1298. Begin
  1299. instr.operands[operandnum].operandtype:=OPR_LABINSTR;
  1300. instr.operands[operandnum].hl:=lab^.lab;
  1301. instr.labeled:=TRUE;
  1302. end;
  1303. end
  1304. else
  1305. Begin
  1306. { the label does not exist, create it }
  1307. { emit the opcode, but set that the }
  1308. { label has not been emitted }
  1309. getlabel(hl);
  1310. labellist.insert(actasmpattern,hl,FALSE);
  1311. instr.operands[operandnum].operandtype:=OPR_LABINSTR;
  1312. instr.operands[operandnum].hl:=hl;
  1313. instr.labeled:=TRUE;
  1314. end;
  1315. Consume(AS_ID);
  1316. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1317. Begin
  1318. Message(assem_e_syntax_error);
  1319. end;
  1320. end
  1321. else
  1322. { probably a variable or normal expression }
  1323. { or a procedure (such as in CALL ID) }
  1324. Begin
  1325. { check if this is a label, if so then }
  1326. { emit it as a label. }
  1327. if SearchLabel(actasmpattern,hl) then
  1328. Begin
  1329. instr.operands[operandnum].operandtype:=OPR_LABINSTR;
  1330. instr.operands[operandnum].hl:=hl;
  1331. instr.labeled:=TRUE;
  1332. Consume(AS_ID);
  1333. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1334. Message(assem_e_syntax_error);
  1335. end
  1336. else
  1337. { is it a normal variable ? }
  1338. Begin
  1339. { context for scanner }
  1340. initAsmRef(instr,operandnum);
  1341. if not CreateVarInstr(instr,actasmpattern,operandnum) then
  1342. Begin
  1343. { look for special symbols ... }
  1344. if actasmpattern = '__RESULT' then
  1345. SetUpResult(instr,operandnum)
  1346. else
  1347. if actasmpattern = '__SELF' then
  1348. Begin
  1349. if assigned(procinfo._class) then
  1350. Begin
  1351. instr.operands[operandnum].operandtype:=OPR_REFERENCE;
  1352. instr.operands[operandnum].ref.offset:=procinfo.ESI_offset;
  1353. instr.operands[operandnum].ref.base:=procinfo.framepointer;
  1354. end
  1355. else
  1356. Message(assem_e_cannot_use___SELF_outside_methode);
  1357. end
  1358. else
  1359. if actasmpattern = '__OLDEBP' then
  1360. Begin
  1361. if lexlevel>normal_function_level then
  1362. Begin
  1363. instr.operands[operandnum].operandtype:=OPR_REFERENCE;
  1364. instr.operands[operandnum].ref.offset:=procinfo.framepointer_offset;
  1365. instr.operands[operandnum].ref.base:=procinfo.framepointer;
  1366. end
  1367. else
  1368. Message(assem_e_cannot_use___OLDEBP_outside_nested_procedure);
  1369. end
  1370. else
  1371. { check for direct symbolic names }
  1372. { only if compiling the system unit }
  1373. if (cs_compilesystem in aktmoduleswitches) then
  1374. begin
  1375. if not SearchDirectVar(instr,actasmpattern,operandnum) then
  1376. Begin
  1377. { not found, finally ... add it anyways ... }
  1378. Message1(assem_w_id_supposed_external,actasmpattern);
  1379. instr.operands[operandnum].ref.symbol:=newasmsymbol(actasmpattern);
  1380. end;
  1381. end
  1382. else
  1383. Message1(assem_e_unknown_id,actasmpattern);
  1384. end;
  1385. { constant expression? }
  1386. if (instr.operands[operandnum].operandtype=OPR_CONSTANT) then
  1387. begin
  1388. l:=BuildConstExpression(true,false);
  1389. { indexing? }
  1390. if actasmtoken=AS_LPAREN then
  1391. begin
  1392. instr.operands[operandnum].operandtype:=OPR_REFERENCE;
  1393. reset_reference(Instr.Operands[OperandNum].Ref);
  1394. Instr.Operands[OperandNum].Ref.Offset:=l;
  1395. BuildReference(instr);
  1396. end
  1397. else
  1398. Instr.Operands[OperandNum].Val:=l;
  1399. end
  1400. else
  1401. begin
  1402. expr:=actasmpattern;
  1403. Consume(AS_ID);
  1404. if actasmtoken=AS_DOT then
  1405. begin
  1406. BuildRecordOffsetSize(expr,toffset,tsize);
  1407. inc(instr.operands[operandnum].ref.offset,toffset);
  1408. SetOperandSize(instr,operandnum,tsize);
  1409. end;
  1410. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1411. inc(instr.operands[operandnum].ref.offset,BuildConstExpression(true,false));
  1412. if actasmtoken=AS_LPAREN then
  1413. BuildReference(instr);
  1414. end;
  1415. end; { end if }
  1416. end; { end if }
  1417. end;
  1418. AS_REGISTER: { Register, a variable reference or a constant reference }
  1419. Begin
  1420. { save the type of register used. }
  1421. tempreg:=actasmregister;
  1422. Consume(AS_REGISTER);
  1423. if actasmtoken = AS_COLON then
  1424. Begin
  1425. Consume(AS_COLON);
  1426. initAsmRef(instr,operandnum);
  1427. instr.operands[operandnum].ref.segment:=tempreg;
  1428. { This must absolutely be followed by a reference }
  1429. if not MaybeBuildReference then
  1430. Begin
  1431. Message(assem_e_invalid_seg_override);
  1432. Consume(actasmtoken);
  1433. end;
  1434. end
  1435. { Simple register }
  1436. else if (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1437. Begin
  1438. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  1439. Message(assem_e_invalid_operand_type);
  1440. instr.operands[operandnum].operandtype:=OPR_REGISTER;
  1441. instr.operands[operandnum].reg:=tempreg;
  1442. instr.operands[operandnum].size:=reg_2_opsize[tempreg];
  1443. end
  1444. else
  1445. Message1(assem_e_syn_register,att_reg2str[tempreg]);
  1446. end;
  1447. AS_SEPARATOR,
  1448. AS_COMMA: ;
  1449. else
  1450. Begin
  1451. Message(assem_e_syn_opcode_operand);
  1452. Consume(actasmtoken);
  1453. end;
  1454. end; { end case }
  1455. end;
  1456. Procedure BuildConstant(maxvalue: longint);
  1457. {*********************************************************************}
  1458. { PROCEDURE BuildConstant }
  1459. { Description: This routine takes care of parsing a DB,DD,or DW }
  1460. { line and adding those to the assembler node. Expressions, range- }
  1461. { checking are fullly taken care of. }
  1462. { maxvalue: $ff -> indicates that this is a DB node. }
  1463. { $ffff -> indicates that this is a DW node. }
  1464. { $ffffffff -> indicates that this is a DD node. }
  1465. {*********************************************************************}
  1466. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1467. {*********************************************************************}
  1468. var
  1469. strlength: byte;
  1470. asmsym,
  1471. expr: string;
  1472. value : longint;
  1473. Begin
  1474. Repeat
  1475. Case actasmtoken of
  1476. AS_STRING:
  1477. Begin
  1478. if maxvalue = $ff then
  1479. strlength:=1
  1480. else
  1481. Message(assem_e_string_not_allowed_as_const);
  1482. expr:=actasmpattern;
  1483. if length(expr) > 1 then
  1484. Message(assem_e_string_not_allowed_as_const);
  1485. Consume(AS_STRING);
  1486. Case actasmtoken of
  1487. AS_COMMA: Consume(AS_COMMA);
  1488. AS_SEPARATOR: ;
  1489. else
  1490. Message(assem_e_invalid_string_expression);
  1491. end; { end case }
  1492. ConcatString(curlist,expr);
  1493. end;
  1494. AS_INTNUM,
  1495. AS_PLUS,
  1496. AS_MINUS,
  1497. AS_LPAREN,
  1498. AS_NOT,
  1499. AS_ID :
  1500. Begin
  1501. BuildConstSymbolExpression(false,false,false,value,asmsym);
  1502. if asmsym<>'' then
  1503. begin
  1504. if maxvalue<>$ffffffff then
  1505. Comment(V_Warning,'32bit constant created for address');
  1506. ConcatConstSymbol(curlist,asmsym,value)
  1507. end
  1508. else
  1509. ConcatConstant(curlist,value,maxvalue);
  1510. end;
  1511. AS_COMMA:
  1512. Consume(AS_COMMA);
  1513. AS_SEPARATOR:
  1514. break;
  1515. else
  1516. Message(assem_f_internal_error_in_buildconstant);
  1517. end; { end case }
  1518. Until false;
  1519. end;
  1520. Procedure BuildStringConstant(asciiz: boolean);
  1521. {*********************************************************************}
  1522. { PROCEDURE BuildStringConstant }
  1523. { Description: Takes care of a ASCII, or ASCIIZ directive. }
  1524. { asciiz: boolean -> if true then string will be null terminated. }
  1525. {*********************************************************************}
  1526. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1527. { On ENTRY: Token should point to AS_STRING }
  1528. {*********************************************************************}
  1529. var
  1530. expr: string;
  1531. errorflag : boolean;
  1532. Begin
  1533. errorflag:=FALSE;
  1534. Repeat
  1535. Case actasmtoken of
  1536. AS_STRING:
  1537. Begin
  1538. expr:=actasmpattern;
  1539. if asciiz then
  1540. expr:=expr+#0;
  1541. ConcatPasString(curlist,expr);
  1542. Consume(AS_STRING);
  1543. end;
  1544. AS_COMMA:
  1545. begin
  1546. Consume(AS_COMMA);
  1547. end;
  1548. AS_SEPARATOR:
  1549. begin
  1550. break;
  1551. end;
  1552. else
  1553. Begin
  1554. Consume(actasmtoken);
  1555. if not errorflag then
  1556. Message(assem_e_invalid_string_expression);
  1557. errorflag:=TRUE;
  1558. end;
  1559. end;
  1560. Until false;
  1561. end;
  1562. Procedure BuildOpCode;
  1563. {*********************************************************************}
  1564. { PROCEDURE BuildOpcode; }
  1565. { Description: Parses the intel opcode and operands, and writes it }
  1566. { in the TInstruction object. }
  1567. {*********************************************************************}
  1568. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1569. { On ENTRY: Token should point to AS_OPCODE }
  1570. {*********************************************************************}
  1571. var
  1572. PrefixOp,OverrideOp: tasmop;
  1573. expr : string;
  1574. Begin
  1575. expr:='';
  1576. PrefixOp:=A_None;
  1577. OverrideOp:=A_None;
  1578. { prefix seg opcode / prefix opcode }
  1579. repeat
  1580. if is_prefix(actopcode) then
  1581. begin
  1582. if (PrefixOp<>A_None) or (OverrideOp<>A_None) then
  1583. Message(assem_w_repeat_prefix_and_seg_override);
  1584. PrefixOp:=ActOpcode;
  1585. instr.opcode:=ActOpcode;
  1586. instr.condition:=ActCondition;
  1587. instr.opsize:=ActOpsize;
  1588. ConcatInstruction(curlist,instr);
  1589. Consume(AS_OPCODE);
  1590. end
  1591. else
  1592. if is_override(actopcode) then
  1593. begin
  1594. if (PrefixOp<>A_None) or (OverrideOp<>A_None) then
  1595. Message(assem_w_repeat_prefix_and_seg_override);
  1596. OverrideOp:=ActOpcode;
  1597. instr.opcode:=ActOpcode;
  1598. instr.condition:=ActCondition;
  1599. instr.opsize:=ActOpsize;
  1600. ConcatInstruction(curlist,instr);
  1601. Consume(AS_OPCODE);
  1602. end
  1603. else
  1604. break;
  1605. { allow for newline as in gas styled syntax }
  1606. while actasmtoken=AS_SEPARATOR do
  1607. Consume(AS_SEPARATOR);
  1608. until (actasmtoken<>AS_OPCODE);
  1609. { opcode }
  1610. if (actasmtoken <> AS_OPCODE) then
  1611. Begin
  1612. Message(assem_e_invalid_or_missing_opcode);
  1613. RecoverConsume(true);
  1614. exit;
  1615. end;
  1616. { Fill the instr object with the current state }
  1617. instr.Opcode:=ActOpcode;
  1618. instr.condition:=ActCondition;
  1619. instr.opsize:=ActOpsize;
  1620. { Valid combination of prefix/override and instruction ? }
  1621. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1622. Message1(assem_e_invalid_prefix_and_opcode,actasmpattern);
  1623. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1624. Message1(assem_e_invalid_override_and_opcode,actasmpattern);
  1625. { We are reading operands, so opcode will be an AS_ID }
  1626. operandnum:=1;
  1627. Consume(AS_OPCODE);
  1628. { Zero operand opcode ? }
  1629. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1630. begin
  1631. operandnum:=0;
  1632. exit;
  1633. end;
  1634. { Read the operands }
  1635. repeat
  1636. case actasmtoken of
  1637. AS_COMMA: { Operand delimiter }
  1638. Begin
  1639. if operandnum > MaxOperands then
  1640. Message(assem_e_too_many_operands)
  1641. else
  1642. Inc(operandnum);
  1643. Consume(AS_COMMA);
  1644. end;
  1645. AS_SEPARATOR,
  1646. AS_END : { End of asm operands for this opcode }
  1647. begin
  1648. break;
  1649. end;
  1650. else
  1651. BuildOperand(instr);
  1652. end; { end case }
  1653. until false;
  1654. end;
  1655. Function Assemble: Ptree;
  1656. {*********************************************************************}
  1657. { PROCEDURE Assemble; }
  1658. { Description: Parses the att assembler syntax, parsing is done }
  1659. { according to GAs rules. }
  1660. {*********************************************************************}
  1661. Var
  1662. hl : plabel;
  1663. labelptr,
  1664. nextlabel : pasmlabel;
  1665. commname : string;
  1666. lastsec : tsection;
  1667. Begin
  1668. Message(assem_d_start_att);
  1669. firsttoken:=TRUE;
  1670. operandnum:=0;
  1671. if assigned(procinfo.retdef) and
  1672. (is_fpu(procinfo.retdef) or
  1673. ret_in_acc(procinfo.retdef)) then
  1674. procinfo.funcret_is_valid:=true;
  1675. { sets up all opcode and register tables in uppercase }
  1676. if not _asmsorted then
  1677. Begin
  1678. SetupTables;
  1679. _asmsorted:=TRUE;
  1680. end;
  1681. curlist:=new(paasmoutput,init);
  1682. lastsec:=sec_code;
  1683. { setup label linked list }
  1684. labellist.init;
  1685. { start tokenizer }
  1686. c:=current_scanner^.asmgetchar;
  1687. gettoken;
  1688. { main loop }
  1689. repeat
  1690. case actasmtoken of
  1691. AS_LLABEL:
  1692. Begin
  1693. labelptr:=labellist.search(actasmpattern);
  1694. if not assigned(labelptr) then
  1695. Begin
  1696. getlabel(hl);
  1697. labellist.insert(actasmpattern,hl,TRUE);
  1698. ConcatLabel(curlist,hl);
  1699. end
  1700. else
  1701. Begin
  1702. { the label has already been inserted into the }
  1703. { label list, either as an instruction label (in}
  1704. { this case it has not been emitted), or as a }
  1705. { duplicate local symbol (in this case it has }
  1706. { already been emitted). }
  1707. if labelptr^.emitted then
  1708. Message1(assem_e_dup_local_sym,'.L'+labelptr^.name^)
  1709. else
  1710. Begin
  1711. if assigned(labelptr^.lab) then
  1712. ConcatLabel(curlist,labelptr^.lab);
  1713. labelptr^.emitted:=TRUE;
  1714. end;
  1715. end;
  1716. Consume(AS_LLABEL);
  1717. end;
  1718. AS_LABEL:
  1719. Begin
  1720. { when looking for Pascal labels, these must }
  1721. { be in uppercase. }
  1722. if SearchLabel(upper(actasmpattern),hl) then
  1723. ConcatLabel(curlist,hl)
  1724. else
  1725. Begin
  1726. if (cs_compilesystem in aktmoduleswitches) then
  1727. begin
  1728. Message1(assem_e_unknown_label_identifer,actasmpattern);
  1729. { once again we don't know what it represents }
  1730. { so we simply concatenate it }
  1731. ConcatLocal(curlist,actasmpattern);
  1732. end
  1733. else
  1734. Message1(assem_e_unknown_label_identifer,actasmpattern);
  1735. end;
  1736. Consume(AS_LABEL);
  1737. end;
  1738. AS_DW:
  1739. Begin
  1740. Consume(AS_DW);
  1741. BuildConstant($ffff);
  1742. end;
  1743. AS_DATA:
  1744. Begin
  1745. curlist^.Concat(new(pai_section,init(sec_data)));
  1746. lastsec:=sec_data;
  1747. Consume(AS_DATA);
  1748. end;
  1749. AS_TEXT:
  1750. Begin
  1751. curlist^.Concat(new(pai_section,init(sec_code)));
  1752. lastsec:=sec_code;
  1753. Consume(AS_TEXT);
  1754. end;
  1755. AS_DB:
  1756. Begin
  1757. Consume(AS_DB);
  1758. BuildConstant($ff);
  1759. end;
  1760. AS_DD:
  1761. Begin
  1762. Consume(AS_DD);
  1763. BuildConstant($ffffffff);
  1764. end;
  1765. AS_DQ:
  1766. Begin
  1767. Consume(AS_DQ);
  1768. BuildRealConstant(s64bit);
  1769. end;
  1770. AS_SINGLE:
  1771. Begin
  1772. Consume(AS_SINGLE);
  1773. BuildRealConstant(s32real);
  1774. end;
  1775. AS_DOUBLE:
  1776. Begin
  1777. Consume(AS_DOUBLE);
  1778. BuildRealConstant(s64real);
  1779. end;
  1780. AS_EXTENDED:
  1781. Begin
  1782. Consume(AS_EXTENDED);
  1783. BuildRealConstant(s80real);
  1784. end;
  1785. AS_GLOBAL:
  1786. Begin
  1787. { normal units should not be able to declare }
  1788. { direct label names like this... anyhow }
  1789. { procedural calls in asm blocks are }
  1790. { supposedely replaced automatically }
  1791. if (cs_compilesystem in aktmoduleswitches) then
  1792. begin
  1793. Consume(AS_GLOBAL);
  1794. if actasmtoken <> AS_ID then
  1795. Message(assem_e_invalid_global_def)
  1796. else
  1797. ConcatPublic(curlist,actasmpattern);
  1798. Consume(actasmtoken);
  1799. if actasmtoken <> AS_SEPARATOR then
  1800. Begin
  1801. Message(assem_e_line_separator_expected);
  1802. RecoverConsume(false);
  1803. end;
  1804. end
  1805. else
  1806. begin
  1807. Message(assem_w_globl_not_supported);
  1808. RecoverConsume(false);
  1809. end;
  1810. end;
  1811. AS_ALIGN:
  1812. Begin
  1813. Message(assem_w_align_not_supported);
  1814. RecoverConsume(false);
  1815. end;
  1816. AS_ASCIIZ:
  1817. Begin
  1818. Consume(AS_ASCIIZ);
  1819. BuildStringConstant(TRUE);
  1820. end;
  1821. AS_ASCII:
  1822. Begin
  1823. Consume(AS_ASCII);
  1824. BuildStringConstant(FALSE);
  1825. end;
  1826. AS_LCOMM:
  1827. Begin
  1828. { -- this should only be allowed for system development -- }
  1829. { -- otherwise may mess up future enhancements we might -- }
  1830. { -- add. -- }
  1831. if (cs_compilesystem in aktmoduleswitches) then
  1832. begin
  1833. Consume(AS_LCOMM);
  1834. if actasmtoken <> AS_ID then
  1835. begin
  1836. Message(assem_e_invalid_lcomm_def);
  1837. RecoverConsume(false);
  1838. end
  1839. else
  1840. begin
  1841. commname:=actasmpattern;
  1842. Consume(AS_COMMA);
  1843. ConcatLocalBss(actasmpattern,BuildConstExpression(false,false));
  1844. if actasmtoken <> AS_SEPARATOR then
  1845. Begin
  1846. Message(assem_e_line_separator_expected);
  1847. RecoverConsume(false);
  1848. end;
  1849. end;
  1850. end
  1851. else
  1852. begin
  1853. Message(assem_w_lcomm_not_supported);
  1854. RecoverConsume(false);
  1855. end;
  1856. end;
  1857. AS_COMM:
  1858. Begin
  1859. { -- this should only be allowed for system development -- }
  1860. { -- otherwise may mess up future enhancements we might -- }
  1861. { -- add. -- }
  1862. if (cs_compilesystem in aktmoduleswitches) then
  1863. begin
  1864. Consume(AS_COMM);
  1865. if actasmtoken <> AS_ID then
  1866. begin
  1867. Message(assem_e_invalid_comm_def);
  1868. RecoverConsume(false);
  1869. end
  1870. else
  1871. begin
  1872. commname:=actasmpattern;
  1873. Consume(AS_COMMA);
  1874. ConcatGlobalBss(actasmpattern,BuildConstExpression(false,false));
  1875. if actasmtoken <> AS_SEPARATOR then
  1876. Begin
  1877. Message(assem_e_line_separator_expected);
  1878. RecoverConsume(false);
  1879. end;
  1880. end;
  1881. end
  1882. else
  1883. begin
  1884. Message(assem_w_comm_not_supported);
  1885. RecoverConsume(false);
  1886. end;
  1887. end;
  1888. AS_OPCODE:
  1889. Begin
  1890. instr.init;
  1891. BuildOpcode;
  1892. instr.ops:=operandnum;
  1893. AddReferenceSizes(instr);
  1894. SetInstructionOpsize(instr);
  1895. CheckOperandSizes(instr);
  1896. ConcatInstruction(curlist,instr);
  1897. instr.done;
  1898. operandnum:=0;
  1899. end;
  1900. AS_SEPARATOR:
  1901. Begin
  1902. Consume(AS_SEPARATOR);
  1903. { let us go back to the first operand }
  1904. operandnum:=0;
  1905. end;
  1906. AS_END:
  1907. begin
  1908. break; { end assembly block }
  1909. end;
  1910. else
  1911. Begin
  1912. Message(assem_e_syntax_error);
  1913. RecoverConsume(false);
  1914. end;
  1915. end;
  1916. until false;
  1917. { check if there were undefined symbols. }
  1918. { if so, then list each of those undefined }
  1919. { labels. }
  1920. if assigned(labellist.First) then
  1921. Begin
  1922. labelptr:=labellist.First;
  1923. While labelptr <> nil do
  1924. Begin
  1925. nextlabel:=labelptr^.next;
  1926. if not labelptr^.emitted then
  1927. Message1(assem_e_local_sym_not_found_in_asm_statement,'.L'+labelptr^.name^);
  1928. labelptr:=nextlabel;
  1929. end;
  1930. end;
  1931. { are we back in the code section? }
  1932. if lastsec<>sec_code then
  1933. begin
  1934. Message(assem_e_assembler_code_not_returned_to_text);
  1935. curlist^.Concat(new(pai_section,init(sec_code)));
  1936. end;
  1937. assemble:=genasmnode(curlist);
  1938. labellist.done;
  1939. Message(assem_d_finish_att);
  1940. end;
  1941. {*****************************************************************************
  1942. Initialize
  1943. *****************************************************************************}
  1944. var
  1945. old_exit : pointer;
  1946. procedure ra386att_exit;{$ifndef FPC}far;{$endif}
  1947. begin
  1948. if assigned(iasmops) then
  1949. dispose(iasmops);
  1950. if assigned(iasmregs) then
  1951. dispose(iasmregs);
  1952. exitproc:=old_exit;
  1953. end;
  1954. begin
  1955. old_exit:=exitproc;
  1956. exitproc:=@ra386att_exit;
  1957. end.
  1958. {
  1959. $Log$
  1960. Revision 1.42 1999-05-02 14:25:07 peter
  1961. * only allow *<reg/ref> when call/jmp is used
  1962. Revision 1.41 1999/05/01 13:48:39 peter
  1963. * merged nasm compiler
  1964. Revision 1.7 1999/04/29 09:37:47 peter
  1965. * fixed var+const support
  1966. Revision 1.6 1999/04/26 23:26:17 peter
  1967. * redesigned record offset parsing to support nested records
  1968. * normal compiler uses the redesigned createvarinstr()
  1969. Revision 1.5 1999/04/20 11:01:23 peter
  1970. * better tokenpos info
  1971. Revision 1.4 1999/04/14 09:07:45 peter
  1972. * asm reader improvements
  1973. Revision 1.3 1999/03/06 17:24:26 peter
  1974. * rewritten intel parser a lot, especially reference reading
  1975. * size checking added for asm parsers
  1976. Revision 1.2 1999/03/02 02:56:30 peter
  1977. + stabs support for binary writers
  1978. * more fixes and missing updates from the previous commit :(
  1979. Revision 1.1 1999/03/01 15:46:26 peter
  1980. * ag386bin finally make cycles correct
  1981. * prefixes are now also normal opcodes
  1982. }