ra386att.pas 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. Unit Ra386att;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. node;
  23. function assemble: tnode;
  24. Implementation
  25. uses
  26. { common }
  27. cutils,cclasses,
  28. { global }
  29. globtype,globals,verbose,
  30. systems,
  31. { aasm }
  32. cpubase,cpuinfo,aasmbase,aasmtai,aasmcpu,
  33. { symtable }
  34. symconst,symbase,symtype,symsym,symtable,
  35. { pass 1 }
  36. nbas,
  37. { parser }
  38. scanner,
  39. ra386,ag386att,rautils
  40. ;
  41. type
  42. tasmtoken = (
  43. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  44. AS_REALNUM,AS_COMMA,AS_LPAREN,
  45. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
  46. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
  47. {------------------ Assembler directives --------------------}
  48. AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
  49. AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
  50. AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
  51. AS_DATA,AS_TEXT,AS_END,
  52. {------------------ Assembler Operators --------------------}
  53. AS_TYPE,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR);
  54. tasmkeyword = string[10];
  55. const
  56. { These tokens should be modified accordingly to the modifications }
  57. { in the different enumerations. }
  58. firstdirective = AS_DB;
  59. lastdirective = AS_END;
  60. token2str : array[tasmtoken] of tasmkeyword=(
  61. '','Label','LLabel','string','integer',
  62. 'float',',','(',
  63. ')',':','.','+','-','*',
  64. ';','identifier','register','opcode','/','$',
  65. '.byte','.word','.long','.quad','.globl',
  66. '.align','.balign','.p2align','.ascii',
  67. '.asciz','.lcomm','.comm','.single','.double','.tfloat',
  68. '.data','.text','END',
  69. 'TYPE','%','<<','>>','!','&','|','^','~');
  70. const
  71. newline = #10;
  72. firsttoken : boolean = TRUE;
  73. var
  74. _asmsorted : boolean;
  75. curlist : TAAsmoutput;
  76. c : char;
  77. actasmtoken : tasmtoken;
  78. prevasmtoken : tasmtoken;
  79. actasmpattern : string;
  80. actopcode : tasmop;
  81. actasmregister : tregister;
  82. actopsize : topsize;
  83. actcondition : tasmcond;
  84. iasmops : tdictionary;
  85. iasmregs : ^reg2strtable;
  86. Procedure SetupTables;
  87. { creates uppercased symbol tables for speed access }
  88. var
  89. i : tasmop;
  90. j : tregister;
  91. str2opentry: tstr2opentry;
  92. Begin
  93. { opcodes }
  94. iasmops:=TDictionary.Create;
  95. iasmops.delete_doubles:=true;
  96. for i:=firstop to lastop do
  97. begin
  98. str2opentry:=tstr2opentry.createname(upper(gas_op2str[i]));
  99. str2opentry.op:=i;
  100. iasmops.insert(str2opentry);
  101. end;
  102. { registers }
  103. new(iasmregs);
  104. for j:=firstreg to lastreg do
  105. iasmregs^[j] := upper(gas_reg2str[j]);
  106. end;
  107. {---------------------------------------------------------------------}
  108. { Routines for the tokenizing }
  109. {---------------------------------------------------------------------}
  110. function is_asmopcode(const s: string):boolean;
  111. const
  112. { We need first to check the long prefixes, else we get probs
  113. with things like movsbl }
  114. att_sizesuffixstr : array[0..9] of string[2] = (
  115. '','BW','BL','WL','B','W','L','S','Q','T'
  116. );
  117. att_sizesuffix : array[0..9] of topsize = (
  118. S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
  119. );
  120. att_sizefpusuffix : array[0..9] of topsize = (
  121. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
  122. );
  123. att_sizefpuintsuffix : array[0..9] of topsize = (
  124. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
  125. );
  126. var
  127. str2opentry: tstr2opentry;
  128. cond : string[4];
  129. cnd : tasmcond;
  130. len,
  131. j,
  132. sufidx : longint;
  133. Begin
  134. is_asmopcode:=FALSE;
  135. actopcode:=A_None;
  136. actcondition:=C_None;
  137. actopsize:=S_NO;
  138. { search for all possible suffixes }
  139. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  140. begin
  141. len:=length(s)-length(att_sizesuffixstr[sufidx]);
  142. if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
  143. begin
  144. { here we search the entire table... }
  145. str2opentry:=nil;
  146. if {(length(s)>0) and} (len>0) then
  147. str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
  148. if assigned(str2opentry) then
  149. begin
  150. actopcode:=str2opentry.op;
  151. if gas_needsuffix[actopcode]=attsufFPU then
  152. actopsize:=att_sizefpusuffix[sufidx]
  153. else if gas_needsuffix[actopcode]=attsufFPUint then
  154. actopsize:=att_sizefpuintsuffix[sufidx]
  155. else
  156. actopsize:=att_sizesuffix[sufidx];
  157. actasmtoken:=AS_OPCODE;
  158. is_asmopcode:=TRUE;
  159. exit;
  160. end;
  161. { not found, check condition opcodes }
  162. j:=0;
  163. while (j<CondAsmOps) do
  164. begin
  165. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  166. begin
  167. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  168. if cond<>'' then
  169. begin
  170. for cnd:=low(TasmCond) to high(TasmCond) do
  171. if Cond=Upper(cond2str[cnd]) then
  172. begin
  173. actopcode:=CondASmOp[j];
  174. if gas_needsuffix[actopcode]=attsufFPU then
  175. actopsize:=att_sizefpusuffix[sufidx]
  176. else if gas_needsuffix[actopcode]=attsufFPUint then
  177. actopsize:=att_sizefpuintsuffix[sufidx]
  178. else
  179. actopsize:=att_sizesuffix[sufidx];
  180. actcondition:=cnd;
  181. actasmtoken:=AS_OPCODE;
  182. is_asmopcode:=TRUE;
  183. exit;
  184. end;
  185. end;
  186. end;
  187. inc(j);
  188. end;
  189. end;
  190. end;
  191. end;
  192. Function is_asmdirective(const s: string):boolean;
  193. var
  194. i : tasmtoken;
  195. hs : string;
  196. Begin
  197. { GNU as is also not casesensitive with this }
  198. hs:=lower(s);
  199. for i:=firstdirective to lastdirective do
  200. if hs=token2str[i] then
  201. begin
  202. actasmtoken:=i;
  203. is_asmdirective:=true;
  204. exit;
  205. end;
  206. is_asmdirective:=false;
  207. end;
  208. Function is_register(const s: string):boolean;
  209. Var
  210. i : tregister;
  211. Begin
  212. actasmregister:=R_NO;
  213. for i:=firstreg to lastreg do
  214. if s=iasmregs^[i] then
  215. begin
  216. actasmtoken:=AS_REGISTER;
  217. actasmregister:=i;
  218. is_register:=true;
  219. exit;
  220. end;
  221. is_register:=false;
  222. end;
  223. Function is_locallabel(const s: string):boolean;
  224. begin
  225. is_locallabel:=(length(s)>=2) and (s[1]='.') and (s[2]='L');
  226. end;
  227. Procedure GetToken;
  228. var
  229. len : longint;
  230. srsym : tsym;
  231. srsymtable : tsymtable;
  232. begin
  233. { save old token and reset new token }
  234. prevasmtoken:=actasmtoken;
  235. actasmtoken:=AS_NONE;
  236. { reset }
  237. actasmpattern:='';
  238. { while space and tab , continue scan... }
  239. while c in [' ',#9] do
  240. c:=current_scanner.asmgetchar;
  241. { get token pos }
  242. if not (c in [newline,#13,'{',';']) then
  243. current_scanner.gettokenpos;
  244. { Local Label, Label, Directive, Prefix or Opcode }
  245. if firsttoken and not(c in [newline,#13,'{',';']) then
  246. begin
  247. firsttoken:=FALSE;
  248. len:=0;
  249. { directive or local label }
  250. if c = '.' then
  251. begin
  252. inc(len);
  253. actasmpattern[len]:=c;
  254. { Let us point to the next character }
  255. c:=current_scanner.asmgetchar;
  256. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  257. begin
  258. inc(len);
  259. actasmpattern[len]:=c;
  260. c:=current_scanner.asmgetchar;
  261. end;
  262. actasmpattern[0]:=chr(len);
  263. { this is a local label... }
  264. if (c=':') and is_locallabel(actasmpattern) then
  265. Begin
  266. { local variables are case sensitive }
  267. actasmtoken:=AS_LLABEL;
  268. c:=current_scanner.asmgetchar;
  269. firsttoken:=true;
  270. exit;
  271. end
  272. { must be a directive }
  273. else
  274. Begin
  275. { directives are case sensitive!! }
  276. if is_asmdirective(actasmpattern) then
  277. exit;
  278. Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
  279. end;
  280. end;
  281. { only opcodes and global labels are allowed now. }
  282. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  283. begin
  284. inc(len);
  285. actasmpattern[len]:=c;
  286. c:=current_scanner.asmgetchar;
  287. end;
  288. actasmpattern[0]:=chr(len);
  289. { Label ? }
  290. if c = ':' then
  291. begin
  292. actasmtoken:=AS_LABEL;
  293. { let us point to the next character }
  294. c:=current_scanner.asmgetchar;
  295. firsttoken:=true;
  296. exit;
  297. end;
  298. { Opcode ? }
  299. If is_asmopcode(upper(actasmpattern)) then
  300. Begin
  301. uppervar(actasmpattern);
  302. exit;
  303. end;
  304. { End of assemblerblock ? }
  305. if upper(actasmpattern) = 'END' then
  306. begin
  307. actasmtoken:=AS_END;
  308. exit;
  309. end;
  310. message1(asmr_e_unknown_opcode,actasmpattern);
  311. actasmtoken:=AS_NONE;
  312. end
  313. else { else firsttoken }
  314. { Here we must handle all possible cases }
  315. begin
  316. case c of
  317. '.' : { possiblities : - local label reference , such as in jmp @local1 }
  318. { - field of object/record }
  319. { - directive. }
  320. begin
  321. if (prevasmtoken in [AS_ID,AS_RPAREN]) then
  322. begin
  323. c:=current_scanner.asmgetchar;
  324. actasmtoken:=AS_DOT;
  325. exit;
  326. end;
  327. actasmpattern:=c;
  328. c:=current_scanner.asmgetchar;
  329. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  330. begin
  331. actasmpattern:=actasmpattern + c;
  332. c:=current_scanner.asmgetchar;
  333. end;
  334. if is_asmdirective(actasmpattern) then
  335. exit;
  336. { local label references and directives }
  337. { are case sensitive }
  338. actasmtoken:=AS_ID;
  339. exit;
  340. end;
  341. { identifier, register, prefix or directive }
  342. '_','A'..'Z','a'..'z':
  343. begin
  344. len:=0;
  345. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  346. begin
  347. inc(len);
  348. actasmpattern[len]:=c;
  349. c:=current_scanner.asmgetchar;
  350. end;
  351. actasmpattern[0]:=chr(len);
  352. uppervar(actasmpattern);
  353. { Opcode, can only be when the previous was a prefix }
  354. If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
  355. Begin
  356. uppervar(actasmpattern);
  357. exit;
  358. end;
  359. { check for end which is a reserved word unlike the opcodes }
  360. if actasmpattern = 'END' then
  361. Begin
  362. actasmtoken:=AS_END;
  363. exit;
  364. end;
  365. if actasmpattern = 'TYPE' then
  366. Begin
  367. actasmtoken:=AS_TYPE;
  368. exit;
  369. end;
  370. { if next is a '.' and this is a unitsym then we also need to
  371. parse the identifier }
  372. if (c='.') then
  373. begin
  374. searchsym(actasmpattern,srsym,srsymtable);
  375. if assigned(srsym) and
  376. (srsym.typ=unitsym) and
  377. (srsym.owner.unitid=0) then
  378. begin
  379. actasmpattern:=actasmpattern+c;
  380. c:=current_scanner.asmgetchar;
  381. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  382. begin
  383. actasmpattern:=actasmpattern + upcase(c);
  384. c:=current_scanner.asmgetchar;
  385. end;
  386. end;
  387. end;
  388. actasmtoken:=AS_ID;
  389. exit;
  390. end;
  391. '%' : { register or modulo }
  392. begin
  393. len:=1;
  394. actasmpattern[len]:='%';
  395. c:=current_scanner.asmgetchar;
  396. { to be a register there must be a letter and not a number }
  397. if c in ['0'..'9'] then
  398. begin
  399. actasmtoken:=AS_MOD;
  400. {Message(asmr_w_modulo_not_supported);}
  401. end
  402. else
  403. begin
  404. while c in ['a'..'z','A'..'Z','0'..'9'] do
  405. Begin
  406. inc(len);
  407. actasmpattern[len]:=c;
  408. c:=current_scanner.asmgetchar;
  409. end;
  410. actasmpattern[0]:=chr(len);
  411. uppervar(actasmpattern);
  412. if (actasmpattern = '%ST') and (c='(') then
  413. Begin
  414. actasmpattern:=actasmpattern+c;
  415. c:=current_scanner.asmgetchar;
  416. if c in ['0'..'9'] then
  417. actasmpattern:=actasmpattern + c
  418. else
  419. Message(asmr_e_invalid_fpu_register);
  420. c:=current_scanner.asmgetchar;
  421. if c <> ')' then
  422. Message(asmr_e_invalid_fpu_register)
  423. else
  424. Begin
  425. actasmpattern:=actasmpattern + c;
  426. c:=current_scanner.asmgetchar; { let us point to next character. }
  427. end;
  428. end;
  429. if is_register(actasmpattern) then
  430. exit;
  431. Message(asmr_e_invalid_register);
  432. actasmtoken:=AS_NONE;
  433. end;
  434. end;
  435. '1'..'9': { integer number }
  436. begin
  437. len:=0;
  438. while c in ['0'..'9'] do
  439. Begin
  440. inc(len);
  441. actasmpattern[len]:=c;
  442. c:=current_scanner.asmgetchar;
  443. end;
  444. actasmpattern[0]:=chr(len);
  445. actasmpattern:=tostr(ValDecimal(actasmpattern));
  446. actasmtoken:=AS_INTNUM;
  447. exit;
  448. end;
  449. '0' : { octal,hexa,real or binary number. }
  450. begin
  451. actasmpattern:=c;
  452. c:=current_scanner.asmgetchar;
  453. case upcase(c) of
  454. 'B': { binary }
  455. Begin
  456. c:=current_scanner.asmgetchar;
  457. while c in ['0','1'] do
  458. Begin
  459. actasmpattern:=actasmpattern + c;
  460. c:=current_scanner.asmgetchar;
  461. end;
  462. actasmpattern:=tostr(ValBinary(actasmpattern));
  463. actasmtoken:=AS_INTNUM;
  464. exit;
  465. end;
  466. 'D': { real }
  467. Begin
  468. c:=current_scanner.asmgetchar;
  469. { get ridd of the 0d }
  470. if (c in ['+','-']) then
  471. begin
  472. actasmpattern:=c;
  473. c:=current_scanner.asmgetchar;
  474. end
  475. else
  476. actasmpattern:='';
  477. while c in ['0'..'9'] do
  478. Begin
  479. actasmpattern:=actasmpattern + c;
  480. c:=current_scanner.asmgetchar;
  481. end;
  482. if c='.' then
  483. begin
  484. actasmpattern:=actasmpattern + c;
  485. c:=current_scanner.asmgetchar;
  486. while c in ['0'..'9'] do
  487. Begin
  488. actasmpattern:=actasmpattern + c;
  489. c:=current_scanner.asmgetchar;
  490. end;
  491. if upcase(c) = 'E' then
  492. begin
  493. actasmpattern:=actasmpattern + c;
  494. c:=current_scanner.asmgetchar;
  495. if (c in ['+','-']) then
  496. begin
  497. actasmpattern:=actasmpattern + c;
  498. c:=current_scanner.asmgetchar;
  499. end;
  500. while c in ['0'..'9'] do
  501. Begin
  502. actasmpattern:=actasmpattern + c;
  503. c:=current_scanner.asmgetchar;
  504. end;
  505. end;
  506. actasmtoken:=AS_REALNUM;
  507. exit;
  508. end
  509. else
  510. begin
  511. Message1(asmr_e_invalid_float_const,actasmpattern+c);
  512. actasmtoken:=AS_NONE;
  513. end;
  514. end;
  515. 'X': { hexadecimal }
  516. Begin
  517. c:=current_scanner.asmgetchar;
  518. while c in ['0'..'9','a'..'f','A'..'F'] do
  519. Begin
  520. actasmpattern:=actasmpattern + c;
  521. c:=current_scanner.asmgetchar;
  522. end;
  523. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  524. actasmtoken:=AS_INTNUM;
  525. exit;
  526. end;
  527. '1'..'7': { octal }
  528. begin
  529. actasmpattern:=actasmpattern + c;
  530. while c in ['0'..'7'] do
  531. Begin
  532. actasmpattern:=actasmpattern + c;
  533. c:=current_scanner.asmgetchar;
  534. end;
  535. actasmpattern:=tostr(ValOctal(actasmpattern));
  536. actasmtoken:=AS_INTNUM;
  537. exit;
  538. end;
  539. else { octal number zero value...}
  540. Begin
  541. actasmpattern:=tostr(ValOctal(actasmpattern));
  542. actasmtoken:=AS_INTNUM;
  543. exit;
  544. end;
  545. end; { end case }
  546. end;
  547. '&' :
  548. begin
  549. c:=current_scanner.asmgetchar;
  550. actasmtoken:=AS_AND;
  551. end;
  552. '''' : { char }
  553. begin
  554. current_scanner.in_asm_string:=true;
  555. actasmpattern:='';
  556. repeat
  557. c:=current_scanner.asmgetchar;
  558. case c of
  559. '\' :
  560. begin
  561. { copy also the next char so \" is parsed correctly }
  562. actasmpattern:=actasmpattern+c;
  563. c:=current_scanner.asmgetchar;
  564. actasmpattern:=actasmpattern+c;
  565. end;
  566. '''' :
  567. begin
  568. c:=current_scanner.asmgetchar;
  569. break;
  570. end;
  571. newline:
  572. Message(scan_f_string_exceeds_line);
  573. else
  574. actasmpattern:=actasmpattern+c;
  575. end;
  576. until false;
  577. actasmpattern:=EscapeToPascal(actasmpattern);
  578. actasmtoken:=AS_STRING;
  579. current_scanner.in_asm_string:=false;
  580. exit;
  581. end;
  582. '"' : { string }
  583. begin
  584. current_scanner.in_asm_string:=true;
  585. actasmpattern:='';
  586. repeat
  587. c:=current_scanner.asmgetchar;
  588. case c of
  589. '\' :
  590. begin
  591. { copy also the next char so \" is parsed correctly }
  592. actasmpattern:=actasmpattern+c;
  593. c:=current_scanner.asmgetchar;
  594. actasmpattern:=actasmpattern+c;
  595. end;
  596. '"' :
  597. begin
  598. c:=current_scanner.asmgetchar;
  599. break;
  600. end;
  601. newline:
  602. Message(scan_f_string_exceeds_line);
  603. else
  604. actasmpattern:=actasmpattern+c;
  605. end;
  606. until false;
  607. actasmpattern:=EscapeToPascal(actasmpattern);
  608. actasmtoken:=AS_STRING;
  609. current_scanner.in_asm_string:=false;
  610. exit;
  611. end;
  612. '$' :
  613. begin
  614. actasmtoken:=AS_DOLLAR;
  615. c:=current_scanner.asmgetchar;
  616. exit;
  617. end;
  618. ',' :
  619. begin
  620. actasmtoken:=AS_COMMA;
  621. c:=current_scanner.asmgetchar;
  622. exit;
  623. end;
  624. '<' :
  625. begin
  626. actasmtoken:=AS_SHL;
  627. c:=current_scanner.asmgetchar;
  628. if c = '<' then
  629. c:=current_scanner.asmgetchar;
  630. exit;
  631. end;
  632. '>' :
  633. begin
  634. actasmtoken:=AS_SHL;
  635. c:=current_scanner.asmgetchar;
  636. if c = '>' then
  637. c:=current_scanner.asmgetchar;
  638. exit;
  639. end;
  640. '|' :
  641. begin
  642. actasmtoken:=AS_OR;
  643. c:=current_scanner.asmgetchar;
  644. exit;
  645. end;
  646. '^' :
  647. begin
  648. actasmtoken:=AS_XOR;
  649. c:=current_scanner.asmgetchar;
  650. exit;
  651. end;
  652. '!' :
  653. begin
  654. Message(asmr_e_nor_not_supported);
  655. c:=current_scanner.asmgetchar;
  656. actasmtoken:=AS_NONE;
  657. exit;
  658. end;
  659. '(' :
  660. begin
  661. actasmtoken:=AS_LPAREN;
  662. c:=current_scanner.asmgetchar;
  663. exit;
  664. end;
  665. ')' :
  666. begin
  667. actasmtoken:=AS_RPAREN;
  668. c:=current_scanner.asmgetchar;
  669. exit;
  670. end;
  671. ':' :
  672. begin
  673. actasmtoken:=AS_COLON;
  674. c:=current_scanner.asmgetchar;
  675. exit;
  676. end;
  677. '+' :
  678. begin
  679. actasmtoken:=AS_PLUS;
  680. c:=current_scanner.asmgetchar;
  681. exit;
  682. end;
  683. '-' :
  684. begin
  685. actasmtoken:=AS_MINUS;
  686. c:=current_scanner.asmgetchar;
  687. exit;
  688. end;
  689. '*' :
  690. begin
  691. actasmtoken:=AS_STAR;
  692. c:=current_scanner.asmgetchar;
  693. exit;
  694. end;
  695. '/' :
  696. begin
  697. c:=current_scanner.asmgetchar;
  698. actasmtoken:=AS_SLASH;
  699. exit;
  700. end;
  701. '{',#13,newline,';' :
  702. begin
  703. { the comment is read by asmgetchar }
  704. c:=current_scanner.asmgetchar;
  705. firsttoken:=TRUE;
  706. actasmtoken:=AS_SEPARATOR;
  707. exit;
  708. end;
  709. else
  710. current_scanner.illegal_char(c);
  711. end;
  712. end;
  713. end;
  714. function consume(t : tasmtoken):boolean;
  715. begin
  716. Consume:=true;
  717. if t<>actasmtoken then
  718. begin
  719. Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
  720. Consume:=false;
  721. end;
  722. repeat
  723. gettoken;
  724. until actasmtoken<>AS_NONE;
  725. end;
  726. procedure RecoverConsume(allowcomma:boolean);
  727. begin
  728. While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
  729. begin
  730. if allowcomma and (actasmtoken=AS_COMMA) then
  731. break;
  732. Consume(actasmtoken);
  733. end;
  734. end;
  735. {*****************************************************************************
  736. Parsing Helpers
  737. *****************************************************************************}
  738. Procedure BuildRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  739. { Description: This routine builds up a record offset after a AS_DOT }
  740. { token is encountered. }
  741. { On entry actasmtoken should be equal to AS_DOT }
  742. var
  743. s : string;
  744. Begin
  745. offset:=0;
  746. size:=0;
  747. s:=expr;
  748. while (actasmtoken=AS_DOT) do
  749. begin
  750. Consume(AS_DOT);
  751. if actasmtoken=AS_ID then
  752. s:=s+'.'+actasmpattern;
  753. if not Consume(AS_ID) then
  754. begin
  755. RecoverConsume(true);
  756. break;
  757. end;
  758. end;
  759. if not GetRecordOffsetSize(s,offset,size) then
  760. Message(asmr_e_building_record_offset);
  761. end;
  762. Procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:longint;var asmsym:string);
  763. var
  764. hs,tempstr,expr : string;
  765. parenlevel,l,k : longint;
  766. errorflag : boolean;
  767. prevtok : tasmtoken;
  768. sym : tsym;
  769. srsymtable : tsymtable;
  770. hl : tasmlabel;
  771. Begin
  772. asmsym:='';
  773. value:=0;
  774. errorflag:=FALSE;
  775. tempstr:='';
  776. expr:='';
  777. parenlevel:=0;
  778. Repeat
  779. Case actasmtoken of
  780. AS_LPAREN:
  781. Begin
  782. { Exit if ref? }
  783. if allowref and (prevasmtoken in [AS_INTNUM,AS_ID]) then
  784. break;
  785. Consume(AS_LPAREN);
  786. expr:=expr + '(';
  787. inc(parenlevel);
  788. end;
  789. AS_RPAREN:
  790. Begin
  791. { end of ref ? }
  792. if (parenlevel=0) and betweenbracket then
  793. break;
  794. Consume(AS_RPAREN);
  795. expr:=expr + ')';
  796. dec(parenlevel);
  797. end;
  798. AS_SHL:
  799. Begin
  800. Consume(AS_SHL);
  801. expr:=expr + '<';
  802. end;
  803. AS_SHR:
  804. Begin
  805. Consume(AS_SHR);
  806. expr:=expr + '>';
  807. end;
  808. AS_SLASH:
  809. Begin
  810. Consume(AS_SLASH);
  811. expr:=expr + '/';
  812. end;
  813. AS_MOD:
  814. Begin
  815. Consume(AS_MOD);
  816. expr:=expr + '%';
  817. end;
  818. AS_STAR:
  819. Begin
  820. Consume(AS_STAR);
  821. expr:=expr + '*';
  822. end;
  823. AS_PLUS:
  824. Begin
  825. Consume(AS_PLUS);
  826. expr:=expr + '+';
  827. end;
  828. AS_MINUS:
  829. Begin
  830. Consume(AS_MINUS);
  831. expr:=expr + '-';
  832. end;
  833. AS_AND:
  834. Begin
  835. Consume(AS_AND);
  836. expr:=expr + '&';
  837. end;
  838. AS_NOT:
  839. Begin
  840. Consume(AS_NOT);
  841. expr:=expr + '~';
  842. end;
  843. AS_XOR:
  844. Begin
  845. Consume(AS_XOR);
  846. expr:=expr + '^';
  847. end;
  848. AS_OR:
  849. Begin
  850. Consume(AS_OR);
  851. expr:=expr + '|';
  852. end;
  853. AS_INTNUM:
  854. Begin
  855. expr:=expr + actasmpattern;
  856. Consume(AS_INTNUM);
  857. end;
  858. AS_DOLLAR:
  859. begin
  860. Consume(AS_DOLLAR);
  861. if actasmtoken<>AS_ID then
  862. Message(asmr_e_dollar_without_identifier);
  863. end;
  864. AS_STRING:
  865. Begin
  866. l:=0;
  867. case Length(actasmpattern) of
  868. 1 :
  869. l:=ord(actasmpattern[1]);
  870. 2 :
  871. l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
  872. 3 :
  873. l:=ord(actasmpattern[3]) +
  874. Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
  875. 4 :
  876. l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
  877. Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
  878. else
  879. Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
  880. end;
  881. str(l, tempstr);
  882. expr:=expr + tempstr;
  883. Consume(AS_STRING);
  884. end;
  885. AS_TYPE:
  886. begin
  887. l:=0;
  888. Consume(AS_TYPE);
  889. if actasmtoken<>AS_ID then
  890. Message(asmr_e_type_without_identifier)
  891. else
  892. begin
  893. tempstr:=actasmpattern;
  894. Consume(AS_ID);
  895. if actasmtoken=AS_DOT then
  896. BuildRecordOffsetSize(tempstr,k,l)
  897. else
  898. begin
  899. searchsym(tempstr,sym,srsymtable);
  900. if assigned(sym) then
  901. begin
  902. case sym.typ of
  903. varsym :
  904. l:=tvarsym(sym).getsize;
  905. typedconstsym :
  906. l:=ttypedconstsym(sym).getsize;
  907. typesym :
  908. l:=ttypesym(sym).restype.def.size;
  909. else
  910. Message(asmr_e_wrong_sym_type);
  911. end;
  912. end
  913. else
  914. Message1(sym_e_unknown_id,tempstr);
  915. end;
  916. end;
  917. str(l, tempstr);
  918. expr:=expr + tempstr;
  919. end;
  920. AS_ID:
  921. Begin
  922. hs:='';
  923. tempstr:=actasmpattern;
  924. prevtok:=prevasmtoken;
  925. consume(AS_ID);
  926. if SearchIConstant(tempstr,l) then
  927. begin
  928. str(l, tempstr);
  929. expr:=expr + tempstr;
  930. end
  931. else
  932. begin
  933. if is_locallabel(tempstr) then
  934. begin
  935. CreateLocalLabel(tempstr,hl,false);
  936. hs:=hl.name
  937. end
  938. else
  939. if SearchLabel(tempstr,hl,false) then
  940. hs:=hl.name
  941. else
  942. begin
  943. searchsym(tempstr,sym,srsymtable);
  944. if assigned(sym) then
  945. begin
  946. case sym.typ of
  947. varsym :
  948. begin
  949. if sym.owner.symtabletype in [localsymtable,parasymtable] then
  950. Message(asmr_e_no_local_or_para_allowed);
  951. hs:=tvarsym(sym).mangledname;
  952. end;
  953. typedconstsym :
  954. hs:=ttypedconstsym(sym).mangledname;
  955. procsym :
  956. begin
  957. if Tprocsym(sym).procdef_count>1 then
  958. Message(asmr_w_calling_overload_func);
  959. hs:=tprocsym(sym).first_procdef.mangledname;
  960. end;
  961. typesym :
  962. begin
  963. if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
  964. Message(asmr_e_wrong_sym_type);
  965. end;
  966. else
  967. Message(asmr_e_wrong_sym_type);
  968. end;
  969. end
  970. else
  971. Message1(sym_e_unknown_id,tempstr);
  972. end;
  973. { symbol found? }
  974. if hs<>'' then
  975. begin
  976. if needofs and (prevtok<>AS_DOLLAR) then
  977. Message(asmr_e_need_dollar);
  978. if asmsym='' then
  979. asmsym:=hs
  980. else
  981. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  982. if (expr='') or (expr[length(expr)]='+') then
  983. begin
  984. { don't remove the + if there could be a record field }
  985. if actasmtoken<>AS_DOT then
  986. delete(expr,length(expr),1);
  987. end
  988. else
  989. Message(asmr_e_only_add_relocatable_symbol);
  990. end;
  991. if actasmtoken=AS_DOT then
  992. begin
  993. BuildRecordOffsetSize(tempstr,l,k);
  994. str(l, tempstr);
  995. expr:=expr + tempstr;
  996. end
  997. else
  998. begin
  999. if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
  1000. delete(expr,length(expr),1);
  1001. end;
  1002. end;
  1003. { check if there are wrong operator used like / or mod etc. }
  1004. if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_LPAREN,AS_END]) then
  1005. Message(asmr_e_only_add_relocatable_symbol);
  1006. end;
  1007. AS_END,
  1008. AS_SEPARATOR,
  1009. AS_COMMA:
  1010. Begin
  1011. break;
  1012. end;
  1013. else
  1014. Begin
  1015. { write error only once. }
  1016. if not errorflag then
  1017. Message(asmr_e_invalid_constant_expression);
  1018. { consume tokens until we find COMMA or SEPARATOR }
  1019. Consume(actasmtoken);
  1020. errorflag:=TRUE;
  1021. end;
  1022. end;
  1023. Until false;
  1024. { calculate expression }
  1025. if not ErrorFlag then
  1026. value:=CalculateExpression(expr)
  1027. else
  1028. value:=0;
  1029. end;
  1030. Function BuildConstExpression(allowref,betweenbracket:boolean): longint;
  1031. var
  1032. l : longint;
  1033. hs : string;
  1034. begin
  1035. BuildConstSymbolExpression(allowref,betweenbracket,false,l,hs);
  1036. if hs<>'' then
  1037. Message(asmr_e_relocatable_symbol_not_allowed);
  1038. BuildConstExpression:=l;
  1039. end;
  1040. {****************************************************************************
  1041. T386ATTOperand
  1042. ****************************************************************************}
  1043. type
  1044. T386ATTOperand=class(T386Operand)
  1045. Procedure BuildOperand;override;
  1046. private
  1047. Procedure BuildReference;
  1048. Procedure BuildConstant;
  1049. end;
  1050. Procedure T386ATTOperand.BuildReference;
  1051. procedure Consume_RParen;
  1052. begin
  1053. if actasmtoken <> AS_RPAREN then
  1054. Begin
  1055. Message(asmr_e_invalid_reference_syntax);
  1056. RecoverConsume(true);
  1057. end
  1058. else
  1059. begin
  1060. Consume(AS_RPAREN);
  1061. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
  1062. Begin
  1063. Message(asmr_e_invalid_reference_syntax);
  1064. RecoverConsume(true);
  1065. end;
  1066. end;
  1067. end;
  1068. procedure Consume_Scale;
  1069. var
  1070. l : longint;
  1071. begin
  1072. { we have to process the scaling }
  1073. l:=BuildConstExpression(false,true);
  1074. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  1075. opr.ref.scalefactor:=l
  1076. else
  1077. Begin
  1078. Message(asmr_e_wrong_scale_factor);
  1079. opr.ref.scalefactor:=0;
  1080. end;
  1081. end;
  1082. Begin
  1083. Consume(AS_LPAREN);
  1084. Case actasmtoken of
  1085. AS_INTNUM,
  1086. AS_MINUS,
  1087. AS_PLUS: { absolute offset, such as fs:(0x046c) }
  1088. Begin
  1089. { offset(offset) is invalid }
  1090. If opr.Ref.Offset <> 0 Then
  1091. Begin
  1092. Message(asmr_e_invalid_reference_syntax);
  1093. RecoverConsume(true);
  1094. End
  1095. Else
  1096. Begin
  1097. opr.Ref.Offset:=BuildConstExpression(false,true);
  1098. Consume_RParen;
  1099. end;
  1100. exit;
  1101. End;
  1102. AS_REGISTER: { (reg ... }
  1103. Begin
  1104. { Check if there is already a base (mostly ebp,esp) than this is
  1105. not allowed,becuase it will give crashing code }
  1106. if opr.ref.base<>R_NO then
  1107. Message(asmr_e_cannot_index_relative_var);
  1108. opr.ref.base:=actasmregister;
  1109. Consume(AS_REGISTER);
  1110. { can either be a register or a right parenthesis }
  1111. { (reg) }
  1112. if actasmtoken=AS_RPAREN then
  1113. Begin
  1114. Consume_RParen;
  1115. exit;
  1116. end;
  1117. { (reg,reg .. }
  1118. Consume(AS_COMMA);
  1119. if actasmtoken=AS_REGISTER then
  1120. Begin
  1121. opr.ref.index:=actasmregister;
  1122. Consume(AS_REGISTER);
  1123. { check for scaling ... }
  1124. case actasmtoken of
  1125. AS_RPAREN:
  1126. Begin
  1127. Consume_RParen;
  1128. exit;
  1129. end;
  1130. AS_COMMA:
  1131. Begin
  1132. Consume(AS_COMMA);
  1133. Consume_Scale;
  1134. Consume_RParen;
  1135. end;
  1136. else
  1137. Begin
  1138. Message(asmr_e_invalid_reference_syntax);
  1139. RecoverConsume(false);
  1140. end;
  1141. end; { end case }
  1142. end
  1143. else
  1144. Begin
  1145. Message(asmr_e_invalid_reference_syntax);
  1146. RecoverConsume(false);
  1147. end;
  1148. end; {end case }
  1149. AS_COMMA: { (, ... can either be scaling, or index }
  1150. Begin
  1151. Consume(AS_COMMA);
  1152. { Index }
  1153. if (actasmtoken=AS_REGISTER) then
  1154. Begin
  1155. opr.ref.index:=actasmregister;
  1156. Consume(AS_REGISTER);
  1157. { check for scaling ... }
  1158. case actasmtoken of
  1159. AS_RPAREN:
  1160. Begin
  1161. Consume_RParen;
  1162. exit;
  1163. end;
  1164. AS_COMMA:
  1165. Begin
  1166. Consume(AS_COMMA);
  1167. Consume_Scale;
  1168. Consume_RParen;
  1169. end;
  1170. else
  1171. Begin
  1172. Message(asmr_e_invalid_reference_syntax);
  1173. RecoverConsume(false);
  1174. end;
  1175. end; {end case }
  1176. end
  1177. { Scaling }
  1178. else
  1179. Begin
  1180. Consume_Scale;
  1181. Consume_RParen;
  1182. exit;
  1183. end;
  1184. end;
  1185. else
  1186. Begin
  1187. Message(asmr_e_invalid_reference_syntax);
  1188. RecoverConsume(false);
  1189. end;
  1190. end;
  1191. end;
  1192. Procedure T386ATTOperand.BuildConstant;
  1193. var
  1194. l : longint;
  1195. tempstr : string;
  1196. begin
  1197. BuildConstSymbolExpression(false,false,true,l,tempstr);
  1198. if tempstr<>'' then
  1199. begin
  1200. opr.typ:=OPR_SYMBOL;
  1201. opr.symofs:=l;
  1202. opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1203. end
  1204. else
  1205. begin
  1206. opr.typ:=OPR_CONSTANT;
  1207. opr.val:=l;
  1208. end;
  1209. end;
  1210. Procedure T386ATTOperand.BuildOperand;
  1211. var
  1212. tempstr,tempstr2,
  1213. expr : string;
  1214. l,k : longint;
  1215. procedure AddLabelOperand(hl:tasmlabel);
  1216. begin
  1217. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  1218. is_calljmp(actopcode) then
  1219. begin
  1220. opr.typ:=OPR_SYMBOL;
  1221. opr.symbol:=hl;
  1222. end
  1223. else
  1224. begin
  1225. InitRef;
  1226. opr.ref.symbol:=hl;
  1227. end;
  1228. end;
  1229. procedure MaybeRecordOffset;
  1230. var
  1231. hasdot : boolean;
  1232. l,
  1233. toffset,
  1234. tsize : longint;
  1235. begin
  1236. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  1237. exit;
  1238. l:=0;
  1239. hasdot:=(actasmtoken=AS_DOT);
  1240. if hasdot then
  1241. begin
  1242. if expr<>'' then
  1243. begin
  1244. BuildRecordOffsetSize(expr,toffset,tsize);
  1245. inc(l,toffset);
  1246. SetSize(tsize,true);
  1247. end;
  1248. end;
  1249. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1250. inc(l,BuildConstExpression(true,false));
  1251. if opr.typ=OPR_REFERENCE then
  1252. begin
  1253. if hasdot and (not hastype) and (opr.ref.options=ref_parafixup) then
  1254. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1255. inc(opr.ref.offset,l)
  1256. end
  1257. else
  1258. inc(opr.val,l);
  1259. end;
  1260. function MaybeBuildReference:boolean;
  1261. { Try to create a reference, if not a reference is found then false
  1262. is returned }
  1263. begin
  1264. MaybeBuildReference:=true;
  1265. case actasmtoken of
  1266. AS_INTNUM,
  1267. AS_MINUS,
  1268. AS_PLUS:
  1269. Begin
  1270. opr.ref.offset:=BuildConstExpression(True,False);
  1271. if actasmtoken<>AS_LPAREN then
  1272. Message(asmr_e_invalid_reference_syntax)
  1273. else
  1274. BuildReference;
  1275. end;
  1276. AS_LPAREN:
  1277. BuildReference;
  1278. AS_ID: { only a variable is allowed ... }
  1279. Begin
  1280. tempstr:=actasmpattern;
  1281. Consume(AS_ID);
  1282. { typecasting? }
  1283. if (actasmtoken=AS_LPAREN) and
  1284. SearchType(tempstr) then
  1285. begin
  1286. hastype:=true;
  1287. Consume(AS_LPAREN);
  1288. tempstr2:=actasmpattern;
  1289. Consume(AS_ID);
  1290. Consume(AS_RPAREN);
  1291. if not SetupVar(tempstr2,false) then
  1292. Message1(sym_e_unknown_id,tempstr2);
  1293. end
  1294. else
  1295. if not SetupVar(tempstr,false) then
  1296. Message1(sym_e_unknown_id,tempstr);
  1297. { record.field ? }
  1298. if actasmtoken=AS_DOT then
  1299. begin
  1300. BuildRecordOffsetSize(tempstr,l,k);
  1301. inc(opr.ref.offset,l);
  1302. end;
  1303. case actasmtoken of
  1304. AS_END,
  1305. AS_SEPARATOR,
  1306. AS_COMMA: ;
  1307. AS_LPAREN: BuildReference;
  1308. else
  1309. Begin
  1310. Message(asmr_e_invalid_reference_syntax);
  1311. Consume(actasmtoken);
  1312. end;
  1313. end; {end case }
  1314. end;
  1315. else
  1316. MaybeBuildReference:=false;
  1317. end; { end case }
  1318. end;
  1319. var
  1320. tempreg : tregister;
  1321. hl : tasmlabel;
  1322. Begin
  1323. expr:='';
  1324. case actasmtoken of
  1325. AS_LPAREN: { Memory reference or constant expression }
  1326. Begin
  1327. InitRef;
  1328. BuildReference;
  1329. end;
  1330. AS_DOLLAR: { Constant expression }
  1331. Begin
  1332. Consume(AS_DOLLAR);
  1333. BuildConstant;
  1334. end;
  1335. AS_INTNUM,
  1336. AS_MINUS,
  1337. AS_PLUS:
  1338. Begin
  1339. { Constant memory offset }
  1340. { This must absolutely be followed by ( }
  1341. InitRef;
  1342. opr.ref.offset:=BuildConstExpression(True,False);
  1343. if actasmtoken<>AS_LPAREN then
  1344. Message(asmr_e_invalid_reference_syntax)
  1345. else
  1346. BuildReference;
  1347. end;
  1348. AS_STAR: { Call from memory address }
  1349. Begin
  1350. Consume(AS_STAR);
  1351. if actasmtoken=AS_REGISTER then
  1352. begin
  1353. opr.typ:=OPR_REGISTER;
  1354. opr.reg:=actasmregister;
  1355. size:=reg_2_opsize[actasmregister];
  1356. Consume(AS_REGISTER);
  1357. end
  1358. else
  1359. begin
  1360. InitRef;
  1361. if not MaybeBuildReference then
  1362. Message(asmr_e_syn_operand);
  1363. end;
  1364. { this is only allowed for call's and jmp's }
  1365. if not is_calljmp(actopcode) then
  1366. Message(asmr_e_syn_operand);
  1367. end;
  1368. AS_ID: { A constant expression, or a Variable ref. }
  1369. Begin
  1370. { Local Label ? }
  1371. if is_locallabel(actasmpattern) then
  1372. begin
  1373. CreateLocalLabel(actasmpattern,hl,false);
  1374. Consume(AS_ID);
  1375. AddLabelOperand(hl);
  1376. end
  1377. else
  1378. { Check for label }
  1379. if SearchLabel(actasmpattern,hl,false) then
  1380. begin
  1381. Consume(AS_ID);
  1382. AddLabelOperand(hl);
  1383. end
  1384. else
  1385. { probably a variable or normal expression }
  1386. { or a procedure (such as in CALL ID) }
  1387. Begin
  1388. { is it a constant ? }
  1389. if SearchIConstant(actasmpattern,l) then
  1390. Begin
  1391. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1392. Message(asmr_e_invalid_operand_type);
  1393. BuildConstant;
  1394. end
  1395. else
  1396. begin
  1397. InitRef;
  1398. expr:=actasmpattern;
  1399. Consume(AS_ID);
  1400. { typecasting? }
  1401. if (actasmtoken=AS_LPAREN) and
  1402. SearchType(expr) then
  1403. begin
  1404. hastype:=true;
  1405. Consume(AS_LPAREN);
  1406. tempstr:=actasmpattern;
  1407. Consume(AS_ID);
  1408. Consume(AS_RPAREN);
  1409. if SetupVar(tempstr,false) then
  1410. begin
  1411. MaybeRecordOffset;
  1412. { add a constant expression? }
  1413. if (actasmtoken=AS_PLUS) then
  1414. begin
  1415. l:=BuildConstExpression(true,false);
  1416. if opr.typ=OPR_CONSTANT then
  1417. inc(opr.val,l)
  1418. else
  1419. inc(opr.ref.offset,l);
  1420. end
  1421. end
  1422. else
  1423. Message1(sym_e_unknown_id,tempstr);
  1424. end
  1425. else
  1426. begin
  1427. if SetupVar(expr,false) then
  1428. begin
  1429. MaybeRecordOffset;
  1430. { add a constant expression? }
  1431. if (actasmtoken=AS_PLUS) then
  1432. begin
  1433. l:=BuildConstExpression(true,false);
  1434. if opr.typ=OPR_CONSTANT then
  1435. inc(opr.val,l)
  1436. else
  1437. inc(opr.ref.offset,l);
  1438. end
  1439. end
  1440. else
  1441. Begin
  1442. { look for special symbols ... }
  1443. if expr = '__RESULT' then
  1444. SetUpResult
  1445. else
  1446. if expr = '__SELF' then
  1447. SetupSelf
  1448. else
  1449. if expr = '__OLDEBP' then
  1450. SetupOldEBP
  1451. else
  1452. { check for direct symbolic names }
  1453. { only if compiling the system unit }
  1454. if (cs_compilesystem in aktmoduleswitches) then
  1455. begin
  1456. if not SetupDirectVar(expr) then
  1457. Begin
  1458. { not found, finally ... add it anyways ... }
  1459. Message1(asmr_w_id_supposed_external,expr);
  1460. opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
  1461. end;
  1462. end
  1463. else
  1464. Message1(sym_e_unknown_id,expr);
  1465. end;
  1466. end;
  1467. end;
  1468. end;
  1469. { Do we have a indexing reference, then parse it also }
  1470. if actasmtoken=AS_LPAREN then
  1471. begin
  1472. if (opr.typ=OPR_CONSTANT) then
  1473. begin
  1474. l:=opr.val;
  1475. opr.typ:=OPR_REFERENCE;
  1476. Fillchar(opr.ref,sizeof(treference),0);
  1477. opr.Ref.Offset:=l;
  1478. end;
  1479. BuildReference;
  1480. end;
  1481. end;
  1482. AS_REGISTER: { Register, a variable reference or a constant reference }
  1483. Begin
  1484. { save the type of register used. }
  1485. tempreg:=actasmregister;
  1486. Consume(AS_REGISTER);
  1487. if actasmtoken = AS_COLON then
  1488. Begin
  1489. Consume(AS_COLON);
  1490. InitRef;
  1491. opr.ref.segment:=tempreg;
  1492. { This must absolutely be followed by a reference }
  1493. if not MaybeBuildReference then
  1494. Begin
  1495. Message(asmr_e_invalid_seg_override);
  1496. Consume(actasmtoken);
  1497. end;
  1498. end
  1499. { Simple register }
  1500. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1501. Begin
  1502. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1503. Message(asmr_e_invalid_operand_type);
  1504. opr.typ:=OPR_REGISTER;
  1505. opr.reg:=tempreg;
  1506. size:=reg_2_opsize[tempreg];
  1507. end
  1508. else
  1509. Message(asmr_e_syn_operand);
  1510. end;
  1511. AS_END,
  1512. AS_SEPARATOR,
  1513. AS_COMMA: ;
  1514. else
  1515. Begin
  1516. Message(asmr_e_syn_operand);
  1517. Consume(actasmtoken);
  1518. end;
  1519. end; { end case }
  1520. end;
  1521. {*****************************************************************************
  1522. T386ATTInstruction
  1523. *****************************************************************************}
  1524. type
  1525. T386AttInstruction=class(T386Instruction)
  1526. procedure InitOperands;override;
  1527. procedure BuildOpcode;override;
  1528. end;
  1529. procedure T386AttInstruction.InitOperands;
  1530. var
  1531. i : longint;
  1532. begin
  1533. OpOrder:=op_att;
  1534. for i:=1to max_operands do
  1535. Operands[i]:=T386AttOperand.Create;
  1536. end;
  1537. Procedure T386AttInstruction.BuildOpCode;
  1538. var
  1539. operandnum : longint;
  1540. PrefixOp,OverrideOp: tasmop;
  1541. Begin
  1542. PrefixOp:=A_None;
  1543. OverrideOp:=A_None;
  1544. { prefix seg opcode / prefix opcode }
  1545. repeat
  1546. if is_prefix(actopcode) then
  1547. begin
  1548. PrefixOp:=ActOpcode;
  1549. opcode:=ActOpcode;
  1550. condition:=ActCondition;
  1551. opsize:=ActOpsize;
  1552. ConcatInstruction(curlist);
  1553. Consume(AS_OPCODE);
  1554. end
  1555. else
  1556. if is_override(actopcode) then
  1557. begin
  1558. OverrideOp:=ActOpcode;
  1559. opcode:=ActOpcode;
  1560. condition:=ActCondition;
  1561. opsize:=ActOpsize;
  1562. ConcatInstruction(curlist);
  1563. Consume(AS_OPCODE);
  1564. end
  1565. else
  1566. break;
  1567. { allow for newline as in gas styled syntax }
  1568. while actasmtoken=AS_SEPARATOR do
  1569. Consume(AS_SEPARATOR);
  1570. until (actasmtoken<>AS_OPCODE);
  1571. { opcode }
  1572. if (actasmtoken <> AS_OPCODE) then
  1573. Begin
  1574. Message(asmr_e_invalid_or_missing_opcode);
  1575. RecoverConsume(true);
  1576. exit;
  1577. end;
  1578. { Fill the instr object with the current state }
  1579. Opcode:=ActOpcode;
  1580. condition:=ActCondition;
  1581. opsize:=ActOpsize;
  1582. { Valid combination of prefix/override and instruction ? }
  1583. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1584. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1585. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1586. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1587. { We are reading operands, so opcode will be an AS_ID }
  1588. operandnum:=1;
  1589. Consume(AS_OPCODE);
  1590. { Zero operand opcode ? }
  1591. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1592. begin
  1593. operandnum:=0;
  1594. exit;
  1595. end;
  1596. { Read the operands }
  1597. repeat
  1598. case actasmtoken of
  1599. AS_COMMA: { Operand delimiter }
  1600. Begin
  1601. if operandnum > MaxOperands then
  1602. Message(asmr_e_too_many_operands)
  1603. else
  1604. Inc(operandnum);
  1605. Consume(AS_COMMA);
  1606. end;
  1607. AS_SEPARATOR,
  1608. AS_END : { End of asm operands for this opcode }
  1609. begin
  1610. break;
  1611. end;
  1612. else
  1613. Operands[operandnum].BuildOperand;
  1614. end; { end case }
  1615. until false;
  1616. Ops:=operandnum;
  1617. end;
  1618. Procedure BuildConstant(maxvalue: longint);
  1619. var
  1620. asmsym,
  1621. expr: string;
  1622. value : longint;
  1623. Begin
  1624. Repeat
  1625. Case actasmtoken of
  1626. AS_STRING:
  1627. Begin
  1628. expr:=actasmpattern;
  1629. if length(expr) > 1 then
  1630. Message(asmr_e_string_not_allowed_as_const);
  1631. Consume(AS_STRING);
  1632. Case actasmtoken of
  1633. AS_COMMA: Consume(AS_COMMA);
  1634. AS_END,
  1635. AS_SEPARATOR: ;
  1636. else
  1637. Message(asmr_e_invalid_string_expression);
  1638. end; { end case }
  1639. ConcatString(curlist,expr);
  1640. end;
  1641. AS_INTNUM,
  1642. AS_PLUS,
  1643. AS_MINUS,
  1644. AS_LPAREN,
  1645. AS_NOT,
  1646. AS_ID :
  1647. Begin
  1648. BuildConstSymbolExpression(false,false,false,value,asmsym);
  1649. if asmsym<>'' then
  1650. begin
  1651. if maxvalue<>longint($ffffffff) then
  1652. Message(asmr_w_32bit_const_for_address);
  1653. ConcatConstSymbol(curlist,asmsym,value)
  1654. end
  1655. else
  1656. ConcatConstant(curlist,value,maxvalue);
  1657. end;
  1658. AS_COMMA:
  1659. Consume(AS_COMMA);
  1660. AS_END,
  1661. AS_SEPARATOR:
  1662. break;
  1663. else
  1664. begin
  1665. Message(asmr_e_syn_constant);
  1666. RecoverConsume(false);
  1667. end
  1668. end; { end case }
  1669. Until false;
  1670. end;
  1671. Procedure BuildRealConstant(typ : tfloattype);
  1672. var
  1673. expr : string;
  1674. r : bestreal;
  1675. code : integer;
  1676. negativ : boolean;
  1677. errorflag: boolean;
  1678. Begin
  1679. errorflag:=FALSE;
  1680. Repeat
  1681. negativ:=false;
  1682. expr:='';
  1683. if actasmtoken=AS_PLUS then
  1684. Consume(AS_PLUS)
  1685. else
  1686. if actasmtoken=AS_MINUS then
  1687. begin
  1688. negativ:=true;
  1689. consume(AS_MINUS);
  1690. end;
  1691. Case actasmtoken of
  1692. AS_INTNUM:
  1693. Begin
  1694. expr:=actasmpattern;
  1695. Consume(AS_INTNUM);
  1696. if negativ then
  1697. expr:='-'+expr;
  1698. val(expr,r,code);
  1699. if code<>0 then
  1700. Begin
  1701. r:=0;
  1702. Message(asmr_e_invalid_float_expr);
  1703. End;
  1704. ConcatRealConstant(curlist,r,typ);
  1705. end;
  1706. AS_REALNUM:
  1707. Begin
  1708. expr:=actasmpattern;
  1709. Consume(AS_REALNUM);
  1710. { in ATT syntax you have 0d in front of the real }
  1711. { should this be forced ? yes i think so, as to }
  1712. { conform to gas as much as possible. }
  1713. if (expr[1]='0') and (upper(expr[2])='D') then
  1714. Delete(expr,1,2);
  1715. if negativ then
  1716. expr:='-'+expr;
  1717. val(expr,r,code);
  1718. if code<>0 then
  1719. Begin
  1720. r:=0;
  1721. Message(asmr_e_invalid_float_expr);
  1722. End;
  1723. ConcatRealConstant(curlist,r,typ);
  1724. end;
  1725. AS_COMMA:
  1726. begin
  1727. Consume(AS_COMMA);
  1728. end;
  1729. AS_END,
  1730. AS_SEPARATOR:
  1731. begin
  1732. break;
  1733. end;
  1734. else
  1735. Begin
  1736. Consume(actasmtoken);
  1737. if not errorflag then
  1738. Message(asmr_e_invalid_float_expr);
  1739. errorflag:=TRUE;
  1740. end;
  1741. end;
  1742. Until false;
  1743. end;
  1744. Procedure BuildStringConstant(asciiz: boolean);
  1745. var
  1746. expr: string;
  1747. errorflag : boolean;
  1748. Begin
  1749. errorflag:=FALSE;
  1750. Repeat
  1751. Case actasmtoken of
  1752. AS_STRING:
  1753. Begin
  1754. expr:=actasmpattern;
  1755. if asciiz then
  1756. expr:=expr+#0;
  1757. ConcatPasString(curlist,expr);
  1758. Consume(AS_STRING);
  1759. end;
  1760. AS_COMMA:
  1761. begin
  1762. Consume(AS_COMMA);
  1763. end;
  1764. AS_END,
  1765. AS_SEPARATOR:
  1766. begin
  1767. break;
  1768. end;
  1769. else
  1770. Begin
  1771. Consume(actasmtoken);
  1772. if not errorflag then
  1773. Message(asmr_e_invalid_string_expression);
  1774. errorflag:=TRUE;
  1775. end;
  1776. end;
  1777. Until false;
  1778. end;
  1779. Function Assemble: tnode;
  1780. Var
  1781. hl : tasmlabel;
  1782. commname : string;
  1783. lasTSec : TSection;
  1784. l1,l2 : longint;
  1785. instr : T386ATTInstruction;
  1786. Begin
  1787. Message1(asmr_d_start_reading,'AT&T');
  1788. firsttoken:=TRUE;
  1789. { sets up all opcode and register tables in uppercase }
  1790. if not _asmsorted then
  1791. Begin
  1792. SetupTables;
  1793. _asmsorted:=TRUE;
  1794. end;
  1795. curlist:=TAAsmoutput.Create;
  1796. lasTSec:=sec_code;
  1797. { setup label linked list }
  1798. LocalLabelList:=TLocalLabelList.Create;
  1799. { start tokenizer }
  1800. c:=current_scanner.asmgetchar;
  1801. gettoken;
  1802. { main loop }
  1803. repeat
  1804. case actasmtoken of
  1805. AS_LLABEL:
  1806. Begin
  1807. if CreateLocalLabel(actasmpattern,hl,true) then
  1808. ConcatLabel(curlist,hl);
  1809. Consume(AS_LLABEL);
  1810. end;
  1811. AS_LABEL:
  1812. Begin
  1813. if SearchLabel(upper(actasmpattern),hl,true) then
  1814. ConcatLabel(curlist,hl)
  1815. else
  1816. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1817. Consume(AS_LABEL);
  1818. end;
  1819. AS_DW:
  1820. Begin
  1821. Consume(AS_DW);
  1822. BuildConstant($ffff);
  1823. end;
  1824. AS_DATA:
  1825. Begin
  1826. curList.Concat(Tai_section.Create(sec_data));
  1827. lasTSec:=sec_data;
  1828. Consume(AS_DATA);
  1829. end;
  1830. AS_TEXT:
  1831. Begin
  1832. curList.Concat(Tai_section.Create(sec_code));
  1833. lasTSec:=sec_code;
  1834. Consume(AS_TEXT);
  1835. end;
  1836. AS_DB:
  1837. Begin
  1838. Consume(AS_DB);
  1839. BuildConstant($ff);
  1840. end;
  1841. AS_DD:
  1842. Begin
  1843. Consume(AS_DD);
  1844. BuildConstant(longint($ffffffff));
  1845. end;
  1846. AS_DQ:
  1847. Begin
  1848. Consume(AS_DQ);
  1849. BuildRealConstant(s64comp);
  1850. end;
  1851. AS_SINGLE:
  1852. Begin
  1853. Consume(AS_SINGLE);
  1854. BuildRealConstant(s32real);
  1855. end;
  1856. AS_DOUBLE:
  1857. Begin
  1858. Consume(AS_DOUBLE);
  1859. BuildRealConstant(s64real);
  1860. end;
  1861. AS_EXTENDED:
  1862. Begin
  1863. Consume(AS_EXTENDED);
  1864. BuildRealConstant(s80real);
  1865. end;
  1866. AS_GLOBAL:
  1867. Begin
  1868. Consume(AS_GLOBAL);
  1869. if actasmtoken=AS_ID then
  1870. ConcatPublic(curlist,actasmpattern);
  1871. Consume(AS_ID);
  1872. if actasmtoken<>AS_SEPARATOR then
  1873. Consume(AS_SEPARATOR);
  1874. end;
  1875. AS_ALIGN:
  1876. Begin
  1877. Consume(AS_ALIGN);
  1878. l1:=BuildConstExpression(false,false);
  1879. if (target_info.system in [system_i386_GO32V2]) then
  1880. begin
  1881. l2:=1;
  1882. if (l1>=0) and (l1<=16) then
  1883. while (l1>0) do
  1884. begin
  1885. l2:=2*l2;
  1886. dec(l1);
  1887. end;
  1888. l1:=l2;
  1889. end;
  1890. ConcatAlign(curlist,l1);
  1891. Message(asmr_n_align_is_target_specific);
  1892. if actasmtoken<>AS_SEPARATOR then
  1893. Consume(AS_SEPARATOR);
  1894. end;
  1895. AS_BALIGN:
  1896. Begin
  1897. Consume(AS_BALIGN);
  1898. ConcatAlign(curlist,BuildConstExpression(false,false));
  1899. if actasmtoken<>AS_SEPARATOR then
  1900. Consume(AS_SEPARATOR);
  1901. end;
  1902. AS_P2ALIGN:
  1903. Begin
  1904. Consume(AS_P2ALIGN);
  1905. l1:=BuildConstExpression(false,false);
  1906. l2:=1;
  1907. if (l1>=0) and (l1<=16) then
  1908. while (l1>0) do
  1909. begin
  1910. l2:=2*l2;
  1911. dec(l1);
  1912. end;
  1913. l1:=l2;
  1914. ConcatAlign(curlist,l1);
  1915. if actasmtoken<>AS_SEPARATOR then
  1916. Consume(AS_SEPARATOR);
  1917. end;
  1918. AS_ASCIIZ:
  1919. Begin
  1920. Consume(AS_ASCIIZ);
  1921. BuildStringConstant(TRUE);
  1922. end;
  1923. AS_ASCII:
  1924. Begin
  1925. Consume(AS_ASCII);
  1926. BuildStringConstant(FALSE);
  1927. end;
  1928. AS_LCOMM:
  1929. Begin
  1930. Consume(AS_LCOMM);
  1931. commname:=actasmpattern;
  1932. Consume(AS_ID);
  1933. Consume(AS_COMMA);
  1934. ConcatLocalBss(commname,BuildConstExpression(false,false));
  1935. if actasmtoken<>AS_SEPARATOR then
  1936. Consume(AS_SEPARATOR);
  1937. end;
  1938. AS_COMM:
  1939. Begin
  1940. Consume(AS_COMM);
  1941. commname:=actasmpattern;
  1942. Consume(AS_ID);
  1943. Consume(AS_COMMA);
  1944. ConcatGlobalBss(commname,BuildConstExpression(false,false));
  1945. if actasmtoken<>AS_SEPARATOR then
  1946. Consume(AS_SEPARATOR);
  1947. end;
  1948. AS_OPCODE:
  1949. Begin
  1950. instr:=T386ATTInstruction.Create;
  1951. instr.BuildOpcode;
  1952. instr.AddReferenceSizes;
  1953. instr.SetInstructionOpsize;
  1954. instr.CheckOperandSizes;
  1955. instr.ConcatInstruction(curlist);
  1956. instr.Free;
  1957. end;
  1958. AS_SEPARATOR:
  1959. Begin
  1960. Consume(AS_SEPARATOR);
  1961. end;
  1962. AS_END:
  1963. begin
  1964. break; { end assembly block }
  1965. end;
  1966. else
  1967. Begin
  1968. Message(asmr_e_syntax_error);
  1969. RecoverConsume(false);
  1970. end;
  1971. end;
  1972. until false;
  1973. { Check LocalLabelList }
  1974. LocalLabelList.CheckEmitted;
  1975. LocalLabelList.Free;
  1976. { are we back in the code section? }
  1977. if lasTSec<>sec_code then
  1978. begin
  1979. Message(asmr_w_assembler_code_not_returned_to_text);
  1980. curList.Concat(Tai_section.Create(sec_code));
  1981. end;
  1982. { Return the list in an asmnode }
  1983. assemble:=casmnode.create(curlist);
  1984. Message1(asmr_d_finish_reading,'AT&T');
  1985. end;
  1986. {*****************************************************************************
  1987. Initialize
  1988. *****************************************************************************}
  1989. const
  1990. asmmode_i386_att_info : tasmmodeinfo =
  1991. (
  1992. id : asmmode_i386_att;
  1993. idtxt : 'ATT'
  1994. );
  1995. initialization
  1996. RegisterAsmMode(asmmode_i386_att_info);
  1997. finalization
  1998. if assigned(iasmops) then
  1999. iasmops.Free;
  2000. if assigned(iasmregs) then
  2001. dispose(iasmregs);
  2002. end.
  2003. {
  2004. $Log$
  2005. Revision 1.32 2002-11-15 01:58:58 peter
  2006. * merged changes from 1.0.7 up to 04-11
  2007. - -V option for generating bug report tracing
  2008. - more tracing for option parsing
  2009. - errors for cdecl and high()
  2010. - win32 import stabs
  2011. - win32 records<=8 are returned in eax:edx (turned off by default)
  2012. - heaptrc update
  2013. - more info for temp management in .s file with EXTDEBUG
  2014. Revision 1.31 2002/09/03 16:26:28 daniel
  2015. * Make Tprocdef.defs protected
  2016. Revision 1.30 2002/08/13 18:01:52 carl
  2017. * rename swatoperands to swapoperands
  2018. + m68k first compilable version (still needs a lot of testing):
  2019. assembler generator, system information , inline
  2020. assembler reader.
  2021. Revision 1.29 2002/08/12 15:08:42 carl
  2022. + stab register indexes for powerpc (moved from gdb to cpubase)
  2023. + tprocessor enumeration moved to cpuinfo
  2024. + linker in target_info is now a class
  2025. * many many updates for m68k (will soon start to compile)
  2026. - removed some ifdef or correct them for correct cpu
  2027. Revision 1.28 2002/08/11 14:32:31 peter
  2028. * renamed current_library to objectlibrary
  2029. Revision 1.27 2002/08/11 13:24:17 peter
  2030. * saving of asmsymbols in ppu supported
  2031. * asmsymbollist global is removed and moved into a new class
  2032. tasmlibrarydata that will hold the info of a .a file which
  2033. corresponds with a single module. Added librarydata to tmodule
  2034. to keep the library info stored for the module. In the future the
  2035. objectfiles will also be stored to the tasmlibrarydata class
  2036. * all getlabel/newasmsymbol and friends are moved to the new class
  2037. Revision 1.26 2002/07/26 21:15:44 florian
  2038. * rewrote the system handling
  2039. Revision 1.25 2002/07/01 18:46:34 peter
  2040. * internal linker
  2041. * reorganized aasm layer
  2042. Revision 1.24 2002/05/18 13:34:25 peter
  2043. * readded missing revisions
  2044. Revision 1.23 2002/05/16 19:46:52 carl
  2045. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2046. + try to fix temp allocation (still in ifdef)
  2047. + generic constructor calls
  2048. + start of tassembler / tmodulebase class cleanup
  2049. Revision 1.21 2002/04/15 19:12:09 carl
  2050. + target_info.size_of_pointer -> pointer_size
  2051. + some cleanup of unused types/variables
  2052. * move several constants from cpubase to their specific units
  2053. (where they are used)
  2054. + att_Reg2str -> gas_reg2str
  2055. + int_reg2str -> std_reg2str
  2056. Revision 1.20 2002/04/14 17:01:52 carl
  2057. + att_reg2str -> gas_reg2str
  2058. Revision 1.19 2002/04/04 19:06:13 peter
  2059. * removed unused units
  2060. * use tlocation.size in cg.a_*loc*() routines
  2061. Revision 1.18 2002/04/02 17:11:39 peter
  2062. * tlocation,treference update
  2063. * LOC_CONSTANT added for better constant handling
  2064. * secondadd splitted in multiple routines
  2065. * location_force_reg added for loading a location to a register
  2066. of a specified size
  2067. * secondassignment parses now first the right and then the left node
  2068. (this is compatible with Kylix). This saves a lot of push/pop especially
  2069. with string operations
  2070. * adapted some routines to use the new cg methods
  2071. Revision 1.17 2002/03/28 20:48:25 carl
  2072. - remove go32v1 support
  2073. Revision 1.16 2002/01/24 18:25:53 peter
  2074. * implicit result variable generation for assembler routines
  2075. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  2076. }