ra386att.pas 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253
  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 : Toldregister;
  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 i:Toldregister;
  210. begin
  211. actasmregister.enum:=R_INTREGISTER;
  212. actasmregister.number:=gas_regnum_search(s);
  213. if actasmregister.number=NR_NO then
  214. begin
  215. for i:=firstreg to lastreg do
  216. if s=iasmregs^[i] then
  217. begin
  218. actasmtoken:=AS_REGISTER;
  219. actasmregister.enum:=i;
  220. is_register:=true;
  221. exit;
  222. end;
  223. is_register:=false;
  224. end
  225. else
  226. begin
  227. is_register:=true;
  228. actasmtoken:=AS_REGISTER;
  229. end;
  230. end;
  231. Function is_locallabel(const s: string):boolean;
  232. begin
  233. is_locallabel:=(length(s)>=2) and (s[1]='.') and (s[2]='L');
  234. end;
  235. Procedure GetToken;
  236. var
  237. len : longint;
  238. srsym : tsym;
  239. srsymtable : tsymtable;
  240. begin
  241. { save old token and reset new token }
  242. prevasmtoken:=actasmtoken;
  243. actasmtoken:=AS_NONE;
  244. { reset }
  245. actasmpattern:='';
  246. { while space and tab , continue scan... }
  247. while c in [' ',#9] do
  248. c:=current_scanner.asmgetchar;
  249. { get token pos }
  250. if not (c in [newline,#13,'{',';']) then
  251. current_scanner.gettokenpos;
  252. { Local Label, Label, Directive, Prefix or Opcode }
  253. if firsttoken and not(c in [newline,#13,'{',';']) then
  254. begin
  255. firsttoken:=FALSE;
  256. len:=0;
  257. { directive or local label }
  258. if c = '.' then
  259. begin
  260. inc(len);
  261. actasmpattern[len]:=c;
  262. { Let us point to the next character }
  263. c:=current_scanner.asmgetchar;
  264. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  265. begin
  266. inc(len);
  267. actasmpattern[len]:=c;
  268. c:=current_scanner.asmgetchar;
  269. end;
  270. actasmpattern[0]:=chr(len);
  271. { this is a local label... }
  272. if (c=':') and is_locallabel(actasmpattern) then
  273. Begin
  274. { local variables are case sensitive }
  275. actasmtoken:=AS_LLABEL;
  276. c:=current_scanner.asmgetchar;
  277. firsttoken:=true;
  278. exit;
  279. end
  280. { must be a directive }
  281. else
  282. Begin
  283. { directives are case sensitive!! }
  284. if is_asmdirective(actasmpattern) then
  285. exit;
  286. Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
  287. end;
  288. end;
  289. { only opcodes and global labels are allowed now. }
  290. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  291. begin
  292. inc(len);
  293. actasmpattern[len]:=c;
  294. c:=current_scanner.asmgetchar;
  295. end;
  296. actasmpattern[0]:=chr(len);
  297. { Label ? }
  298. if c = ':' then
  299. begin
  300. actasmtoken:=AS_LABEL;
  301. { let us point to the next character }
  302. c:=current_scanner.asmgetchar;
  303. firsttoken:=true;
  304. exit;
  305. end;
  306. { Opcode ? }
  307. If is_asmopcode(upper(actasmpattern)) then
  308. Begin
  309. uppervar(actasmpattern);
  310. exit;
  311. end;
  312. { End of assemblerblock ? }
  313. if upper(actasmpattern) = 'END' then
  314. begin
  315. actasmtoken:=AS_END;
  316. exit;
  317. end;
  318. message1(asmr_e_unknown_opcode,actasmpattern);
  319. actasmtoken:=AS_NONE;
  320. end
  321. else { else firsttoken }
  322. { Here we must handle all possible cases }
  323. begin
  324. case c of
  325. '.' : { possiblities : - local label reference , such as in jmp @local1 }
  326. { - field of object/record }
  327. { - directive. }
  328. begin
  329. if (prevasmtoken in [AS_ID,AS_RPAREN]) then
  330. begin
  331. c:=current_scanner.asmgetchar;
  332. actasmtoken:=AS_DOT;
  333. exit;
  334. end;
  335. actasmpattern:=c;
  336. c:=current_scanner.asmgetchar;
  337. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  338. begin
  339. actasmpattern:=actasmpattern + c;
  340. c:=current_scanner.asmgetchar;
  341. end;
  342. if is_asmdirective(actasmpattern) then
  343. exit;
  344. { local label references and directives }
  345. { are case sensitive }
  346. actasmtoken:=AS_ID;
  347. exit;
  348. end;
  349. { identifier, register, prefix or directive }
  350. '_','A'..'Z','a'..'z':
  351. begin
  352. len:=0;
  353. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  354. begin
  355. inc(len);
  356. actasmpattern[len]:=c;
  357. c:=current_scanner.asmgetchar;
  358. end;
  359. actasmpattern[0]:=chr(len);
  360. uppervar(actasmpattern);
  361. { Opcode, can only be when the previous was a prefix }
  362. If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
  363. Begin
  364. uppervar(actasmpattern);
  365. exit;
  366. end;
  367. { check for end which is a reserved word unlike the opcodes }
  368. if actasmpattern = 'END' then
  369. Begin
  370. actasmtoken:=AS_END;
  371. exit;
  372. end;
  373. if actasmpattern = 'TYPE' then
  374. Begin
  375. actasmtoken:=AS_TYPE;
  376. exit;
  377. end;
  378. { if next is a '.' and this is a unitsym then we also need to
  379. parse the identifier }
  380. if (c='.') then
  381. begin
  382. searchsym(actasmpattern,srsym,srsymtable);
  383. if assigned(srsym) and
  384. (srsym.typ=unitsym) and
  385. (srsym.owner.unitid=0) then
  386. begin
  387. actasmpattern:=actasmpattern+c;
  388. c:=current_scanner.asmgetchar;
  389. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  390. begin
  391. actasmpattern:=actasmpattern + upcase(c);
  392. c:=current_scanner.asmgetchar;
  393. end;
  394. end;
  395. end;
  396. actasmtoken:=AS_ID;
  397. exit;
  398. end;
  399. '%' : { register or modulo }
  400. begin
  401. len:=1;
  402. actasmpattern[len]:='%';
  403. c:=current_scanner.asmgetchar;
  404. { to be a register there must be a letter and not a number }
  405. if c in ['0'..'9'] then
  406. begin
  407. actasmtoken:=AS_MOD;
  408. end
  409. else
  410. begin
  411. while c in ['a'..'z','A'..'Z','0'..'9'] do
  412. Begin
  413. inc(len);
  414. actasmpattern[len]:=c;
  415. c:=current_scanner.asmgetchar;
  416. end;
  417. actasmpattern[0]:=chr(len);
  418. uppervar(actasmpattern);
  419. if (actasmpattern = '%ST') and (c='(') then
  420. Begin
  421. actasmpattern:=actasmpattern+c;
  422. c:=current_scanner.asmgetchar;
  423. if c in ['0'..'9'] then
  424. actasmpattern:=actasmpattern + c
  425. else
  426. Message(asmr_e_invalid_fpu_register);
  427. c:=current_scanner.asmgetchar;
  428. if c <> ')' then
  429. Message(asmr_e_invalid_fpu_register)
  430. else
  431. Begin
  432. actasmpattern:=actasmpattern + c;
  433. c:=current_scanner.asmgetchar; { let us point to next character. }
  434. end;
  435. end;
  436. if is_register(actasmpattern) then
  437. exit;
  438. Message(asmr_e_invalid_register);
  439. actasmtoken:=AS_NONE;
  440. end;
  441. end;
  442. '1'..'9': { integer number }
  443. begin
  444. len:=0;
  445. while c in ['0'..'9'] do
  446. Begin
  447. inc(len);
  448. actasmpattern[len]:=c;
  449. c:=current_scanner.asmgetchar;
  450. end;
  451. actasmpattern[0]:=chr(len);
  452. actasmpattern:=tostr(ValDecimal(actasmpattern));
  453. actasmtoken:=AS_INTNUM;
  454. exit;
  455. end;
  456. '0' : { octal,hexa,real or binary number. }
  457. begin
  458. actasmpattern:=c;
  459. c:=current_scanner.asmgetchar;
  460. case upcase(c) of
  461. 'B': { binary }
  462. Begin
  463. c:=current_scanner.asmgetchar;
  464. while c in ['0','1'] do
  465. Begin
  466. actasmpattern:=actasmpattern + c;
  467. c:=current_scanner.asmgetchar;
  468. end;
  469. actasmpattern:=tostr(ValBinary(actasmpattern));
  470. actasmtoken:=AS_INTNUM;
  471. exit;
  472. end;
  473. 'D': { real }
  474. Begin
  475. c:=current_scanner.asmgetchar;
  476. { get ridd of the 0d }
  477. if (c in ['+','-']) then
  478. begin
  479. actasmpattern:=c;
  480. c:=current_scanner.asmgetchar;
  481. end
  482. else
  483. actasmpattern:='';
  484. while c in ['0'..'9'] do
  485. Begin
  486. actasmpattern:=actasmpattern + c;
  487. c:=current_scanner.asmgetchar;
  488. end;
  489. if c='.' then
  490. begin
  491. actasmpattern:=actasmpattern + c;
  492. c:=current_scanner.asmgetchar;
  493. while c in ['0'..'9'] do
  494. Begin
  495. actasmpattern:=actasmpattern + c;
  496. c:=current_scanner.asmgetchar;
  497. end;
  498. if upcase(c) = 'E' then
  499. begin
  500. actasmpattern:=actasmpattern + c;
  501. c:=current_scanner.asmgetchar;
  502. if (c in ['+','-']) then
  503. begin
  504. actasmpattern:=actasmpattern + c;
  505. c:=current_scanner.asmgetchar;
  506. end;
  507. while c in ['0'..'9'] do
  508. Begin
  509. actasmpattern:=actasmpattern + c;
  510. c:=current_scanner.asmgetchar;
  511. end;
  512. end;
  513. actasmtoken:=AS_REALNUM;
  514. exit;
  515. end
  516. else
  517. begin
  518. Message1(asmr_e_invalid_float_const,actasmpattern+c);
  519. actasmtoken:=AS_NONE;
  520. end;
  521. end;
  522. 'X': { hexadecimal }
  523. Begin
  524. c:=current_scanner.asmgetchar;
  525. while c in ['0'..'9','a'..'f','A'..'F'] do
  526. Begin
  527. actasmpattern:=actasmpattern + c;
  528. c:=current_scanner.asmgetchar;
  529. end;
  530. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  531. actasmtoken:=AS_INTNUM;
  532. exit;
  533. end;
  534. '1'..'7': { octal }
  535. begin
  536. actasmpattern:=actasmpattern + c;
  537. while c in ['0'..'7'] do
  538. Begin
  539. actasmpattern:=actasmpattern + c;
  540. c:=current_scanner.asmgetchar;
  541. end;
  542. actasmpattern:=tostr(ValOctal(actasmpattern));
  543. actasmtoken:=AS_INTNUM;
  544. exit;
  545. end;
  546. else { octal number zero value...}
  547. Begin
  548. actasmpattern:=tostr(ValOctal(actasmpattern));
  549. actasmtoken:=AS_INTNUM;
  550. exit;
  551. end;
  552. end; { end case }
  553. end;
  554. '&' :
  555. begin
  556. c:=current_scanner.asmgetchar;
  557. actasmtoken:=AS_AND;
  558. end;
  559. '''' : { char }
  560. begin
  561. current_scanner.in_asm_string:=true;
  562. actasmpattern:='';
  563. repeat
  564. c:=current_scanner.asmgetchar;
  565. case c of
  566. '\' :
  567. begin
  568. { copy also the next char so \" is parsed correctly }
  569. actasmpattern:=actasmpattern+c;
  570. c:=current_scanner.asmgetchar;
  571. actasmpattern:=actasmpattern+c;
  572. end;
  573. '''' :
  574. begin
  575. c:=current_scanner.asmgetchar;
  576. break;
  577. end;
  578. newline:
  579. Message(scan_f_string_exceeds_line);
  580. else
  581. actasmpattern:=actasmpattern+c;
  582. end;
  583. until false;
  584. actasmpattern:=EscapeToPascal(actasmpattern);
  585. actasmtoken:=AS_STRING;
  586. current_scanner.in_asm_string:=false;
  587. exit;
  588. end;
  589. '"' : { string }
  590. begin
  591. current_scanner.in_asm_string:=true;
  592. actasmpattern:='';
  593. repeat
  594. c:=current_scanner.asmgetchar;
  595. case c of
  596. '\' :
  597. begin
  598. { copy also the next char so \" is parsed correctly }
  599. actasmpattern:=actasmpattern+c;
  600. c:=current_scanner.asmgetchar;
  601. actasmpattern:=actasmpattern+c;
  602. end;
  603. '"' :
  604. begin
  605. c:=current_scanner.asmgetchar;
  606. break;
  607. end;
  608. newline:
  609. Message(scan_f_string_exceeds_line);
  610. else
  611. actasmpattern:=actasmpattern+c;
  612. end;
  613. until false;
  614. actasmpattern:=EscapeToPascal(actasmpattern);
  615. actasmtoken:=AS_STRING;
  616. current_scanner.in_asm_string:=false;
  617. exit;
  618. end;
  619. '$' :
  620. begin
  621. actasmtoken:=AS_DOLLAR;
  622. c:=current_scanner.asmgetchar;
  623. exit;
  624. end;
  625. ',' :
  626. begin
  627. actasmtoken:=AS_COMMA;
  628. c:=current_scanner.asmgetchar;
  629. exit;
  630. end;
  631. '<' :
  632. begin
  633. actasmtoken:=AS_SHL;
  634. c:=current_scanner.asmgetchar;
  635. if c = '<' then
  636. c:=current_scanner.asmgetchar;
  637. exit;
  638. end;
  639. '>' :
  640. begin
  641. actasmtoken:=AS_SHL;
  642. c:=current_scanner.asmgetchar;
  643. if c = '>' then
  644. c:=current_scanner.asmgetchar;
  645. exit;
  646. end;
  647. '|' :
  648. begin
  649. actasmtoken:=AS_OR;
  650. c:=current_scanner.asmgetchar;
  651. exit;
  652. end;
  653. '^' :
  654. begin
  655. actasmtoken:=AS_XOR;
  656. c:=current_scanner.asmgetchar;
  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 not((opr.ref.base.enum=R_NO) or
  1107. ((opr.ref.base.enum=R_INTREGISTER) and (opr.ref.base.number=NR_NO))) then
  1108. message(asmr_e_cannot_index_relative_var);
  1109. opr.ref.base:=actasmregister;
  1110. Consume(AS_REGISTER);
  1111. { can either be a register or a right parenthesis }
  1112. { (reg) }
  1113. if actasmtoken=AS_RPAREN then
  1114. Begin
  1115. Consume_RParen;
  1116. exit;
  1117. end;
  1118. { (reg,reg .. }
  1119. Consume(AS_COMMA);
  1120. if actasmtoken=AS_REGISTER then
  1121. Begin
  1122. opr.ref.index:=actasmregister;
  1123. Consume(AS_REGISTER);
  1124. { check for scaling ... }
  1125. case actasmtoken of
  1126. AS_RPAREN:
  1127. Begin
  1128. Consume_RParen;
  1129. exit;
  1130. end;
  1131. AS_COMMA:
  1132. Begin
  1133. Consume(AS_COMMA);
  1134. Consume_Scale;
  1135. Consume_RParen;
  1136. end;
  1137. else
  1138. Begin
  1139. Message(asmr_e_invalid_reference_syntax);
  1140. RecoverConsume(false);
  1141. end;
  1142. end; { end case }
  1143. end
  1144. else
  1145. Begin
  1146. Message(asmr_e_invalid_reference_syntax);
  1147. RecoverConsume(false);
  1148. end;
  1149. end; {end case }
  1150. AS_COMMA: { (, ... can either be scaling, or index }
  1151. Begin
  1152. Consume(AS_COMMA);
  1153. { Index }
  1154. if (actasmtoken=AS_REGISTER) then
  1155. Begin
  1156. opr.ref.index:=actasmregister;
  1157. Consume(AS_REGISTER);
  1158. { check for scaling ... }
  1159. case actasmtoken of
  1160. AS_RPAREN:
  1161. Begin
  1162. Consume_RParen;
  1163. exit;
  1164. end;
  1165. AS_COMMA:
  1166. Begin
  1167. Consume(AS_COMMA);
  1168. Consume_Scale;
  1169. Consume_RParen;
  1170. end;
  1171. else
  1172. Begin
  1173. Message(asmr_e_invalid_reference_syntax);
  1174. RecoverConsume(false);
  1175. end;
  1176. end; {end case }
  1177. end
  1178. { Scaling }
  1179. else
  1180. Begin
  1181. Consume_Scale;
  1182. Consume_RParen;
  1183. exit;
  1184. end;
  1185. end;
  1186. else
  1187. Begin
  1188. Message(asmr_e_invalid_reference_syntax);
  1189. RecoverConsume(false);
  1190. end;
  1191. end;
  1192. end;
  1193. Procedure T386ATTOperand.BuildConstant;
  1194. var
  1195. l : longint;
  1196. tempstr : string;
  1197. begin
  1198. BuildConstSymbolExpression(false,false,true,l,tempstr);
  1199. if tempstr<>'' then
  1200. begin
  1201. opr.typ:=OPR_SYMBOL;
  1202. opr.symofs:=l;
  1203. opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1204. end
  1205. else
  1206. begin
  1207. opr.typ:=OPR_CONSTANT;
  1208. opr.val:=l;
  1209. end;
  1210. end;
  1211. Procedure T386ATTOperand.BuildOperand;
  1212. var
  1213. tempstr,tempstr2,
  1214. expr : string;
  1215. l,k : longint;
  1216. procedure AddLabelOperand(hl:tasmlabel);
  1217. begin
  1218. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  1219. is_calljmp(actopcode) then
  1220. begin
  1221. opr.typ:=OPR_SYMBOL;
  1222. opr.symbol:=hl;
  1223. end
  1224. else
  1225. begin
  1226. InitRef;
  1227. opr.ref.symbol:=hl;
  1228. end;
  1229. end;
  1230. procedure MaybeRecordOffset;
  1231. var
  1232. hasdot : boolean;
  1233. l,
  1234. toffset,
  1235. tsize : longint;
  1236. begin
  1237. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  1238. exit;
  1239. l:=0;
  1240. hasdot:=(actasmtoken=AS_DOT);
  1241. if hasdot then
  1242. begin
  1243. if expr<>'' then
  1244. begin
  1245. BuildRecordOffsetSize(expr,toffset,tsize);
  1246. inc(l,toffset);
  1247. SetSize(tsize,true);
  1248. end;
  1249. end;
  1250. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1251. inc(l,BuildConstExpression(true,false));
  1252. if opr.typ=OPR_REFERENCE then
  1253. begin
  1254. if hasdot and (not hastype) and (opr.ref.options=ref_parafixup) then
  1255. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1256. inc(opr.ref.offset,l)
  1257. end
  1258. else
  1259. inc(opr.val,l);
  1260. end;
  1261. function MaybeBuildReference:boolean;
  1262. { Try to create a reference, if not a reference is found then false
  1263. is returned }
  1264. begin
  1265. MaybeBuildReference:=true;
  1266. case actasmtoken of
  1267. AS_INTNUM,
  1268. AS_MINUS,
  1269. AS_PLUS:
  1270. Begin
  1271. opr.ref.offset:=BuildConstExpression(True,False);
  1272. if actasmtoken<>AS_LPAREN then
  1273. Message(asmr_e_invalid_reference_syntax)
  1274. else
  1275. BuildReference;
  1276. end;
  1277. AS_LPAREN:
  1278. BuildReference;
  1279. AS_ID: { only a variable is allowed ... }
  1280. Begin
  1281. tempstr:=actasmpattern;
  1282. Consume(AS_ID);
  1283. { typecasting? }
  1284. if (actasmtoken=AS_LPAREN) and
  1285. SearchType(tempstr) then
  1286. begin
  1287. hastype:=true;
  1288. Consume(AS_LPAREN);
  1289. tempstr2:=actasmpattern;
  1290. Consume(AS_ID);
  1291. Consume(AS_RPAREN);
  1292. if not SetupVar(tempstr2,false) then
  1293. Message1(sym_e_unknown_id,tempstr2);
  1294. end
  1295. else
  1296. if not SetupVar(tempstr,false) then
  1297. Message1(sym_e_unknown_id,tempstr);
  1298. { record.field ? }
  1299. if actasmtoken=AS_DOT then
  1300. begin
  1301. BuildRecordOffsetSize(tempstr,l,k);
  1302. inc(opr.ref.offset,l);
  1303. end;
  1304. case actasmtoken of
  1305. AS_END,
  1306. AS_SEPARATOR,
  1307. AS_COMMA: ;
  1308. AS_LPAREN: BuildReference;
  1309. else
  1310. Begin
  1311. Message(asmr_e_invalid_reference_syntax);
  1312. Consume(actasmtoken);
  1313. end;
  1314. end; {end case }
  1315. end;
  1316. else
  1317. MaybeBuildReference:=false;
  1318. end; { end case }
  1319. end;
  1320. var
  1321. tempreg : tregister;
  1322. hl : tasmlabel;
  1323. Begin
  1324. expr:='';
  1325. case actasmtoken of
  1326. AS_LPAREN: { Memory reference or constant expression }
  1327. Begin
  1328. InitRef;
  1329. BuildReference;
  1330. end;
  1331. AS_DOLLAR: { Constant expression }
  1332. Begin
  1333. Consume(AS_DOLLAR);
  1334. BuildConstant;
  1335. end;
  1336. AS_INTNUM,
  1337. AS_MINUS,
  1338. AS_PLUS:
  1339. Begin
  1340. { Constant memory offset }
  1341. { This must absolutely be followed by ( }
  1342. InitRef;
  1343. opr.ref.offset:=BuildConstExpression(True,False);
  1344. if actasmtoken<>AS_LPAREN then
  1345. Message(asmr_e_invalid_reference_syntax)
  1346. else
  1347. BuildReference;
  1348. end;
  1349. AS_STAR: { Call from memory address }
  1350. Begin
  1351. Consume(AS_STAR);
  1352. if actasmtoken=AS_REGISTER then
  1353. begin
  1354. opr.typ:=OPR_REGISTER;
  1355. opr.reg:=actasmregister;
  1356. if opr.reg.enum<>R_INTREGISTER then
  1357. internalerror(200302023);
  1358. size:=reg2opsize(actasmregister);
  1359. Consume(AS_REGISTER);
  1360. end
  1361. else
  1362. begin
  1363. InitRef;
  1364. if not MaybeBuildReference then
  1365. Message(asmr_e_syn_operand);
  1366. end;
  1367. { this is only allowed for call's and jmp's }
  1368. if not is_calljmp(actopcode) then
  1369. Message(asmr_e_syn_operand);
  1370. end;
  1371. AS_ID: { A constant expression, or a Variable ref. }
  1372. Begin
  1373. { Local Label ? }
  1374. if is_locallabel(actasmpattern) then
  1375. begin
  1376. CreateLocalLabel(actasmpattern,hl,false);
  1377. Consume(AS_ID);
  1378. AddLabelOperand(hl);
  1379. end
  1380. else
  1381. { Check for label }
  1382. if SearchLabel(actasmpattern,hl,false) then
  1383. begin
  1384. Consume(AS_ID);
  1385. AddLabelOperand(hl);
  1386. end
  1387. else
  1388. { probably a variable or normal expression }
  1389. { or a procedure (such as in CALL ID) }
  1390. Begin
  1391. { is it a constant ? }
  1392. if SearchIConstant(actasmpattern,l) then
  1393. Begin
  1394. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1395. Message(asmr_e_invalid_operand_type);
  1396. BuildConstant;
  1397. end
  1398. else
  1399. begin
  1400. InitRef;
  1401. expr:=actasmpattern;
  1402. Consume(AS_ID);
  1403. { typecasting? }
  1404. if (actasmtoken=AS_LPAREN) and
  1405. SearchType(expr) then
  1406. begin
  1407. hastype:=true;
  1408. Consume(AS_LPAREN);
  1409. tempstr:=actasmpattern;
  1410. Consume(AS_ID);
  1411. Consume(AS_RPAREN);
  1412. if SetupVar(tempstr,false) then
  1413. begin
  1414. MaybeRecordOffset;
  1415. { add a constant expression? }
  1416. if (actasmtoken=AS_PLUS) then
  1417. begin
  1418. l:=BuildConstExpression(true,false);
  1419. if opr.typ=OPR_CONSTANT then
  1420. inc(opr.val,l)
  1421. else
  1422. inc(opr.ref.offset,l);
  1423. end
  1424. end
  1425. else
  1426. Message1(sym_e_unknown_id,tempstr);
  1427. end
  1428. else
  1429. begin
  1430. if SetupVar(expr,false) then
  1431. begin
  1432. MaybeRecordOffset;
  1433. { add a constant expression? }
  1434. if (actasmtoken=AS_PLUS) then
  1435. begin
  1436. l:=BuildConstExpression(true,false);
  1437. if opr.typ=OPR_CONSTANT then
  1438. inc(opr.val,l)
  1439. else
  1440. inc(opr.ref.offset,l);
  1441. end
  1442. end
  1443. else
  1444. Begin
  1445. { look for special symbols ... }
  1446. if expr = '__RESULT' then
  1447. SetUpResult
  1448. else
  1449. if expr = '__SELF' then
  1450. SetupSelf
  1451. else
  1452. if expr = '__OLDEBP' then
  1453. SetupOldEBP
  1454. else
  1455. { check for direct symbolic names }
  1456. { only if compiling the system unit }
  1457. if (cs_compilesystem in aktmoduleswitches) then
  1458. begin
  1459. if not SetupDirectVar(expr) then
  1460. Begin
  1461. { not found, finally ... add it anyways ... }
  1462. Message1(asmr_w_id_supposed_external,expr);
  1463. opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
  1464. end;
  1465. end
  1466. else
  1467. Message1(sym_e_unknown_id,expr);
  1468. end;
  1469. end;
  1470. end;
  1471. end;
  1472. { Do we have a indexing reference, then parse it also }
  1473. if actasmtoken=AS_LPAREN then
  1474. begin
  1475. if (opr.typ=OPR_CONSTANT) then
  1476. begin
  1477. l:=opr.val;
  1478. opr.typ:=OPR_REFERENCE;
  1479. Fillchar(opr.ref,sizeof(treference),0);
  1480. opr.Ref.Offset:=l;
  1481. end;
  1482. BuildReference;
  1483. end;
  1484. end;
  1485. AS_REGISTER: { Register, a variable reference or a constant reference }
  1486. Begin
  1487. { save the type of register used. }
  1488. tempreg:=actasmregister;
  1489. Consume(AS_REGISTER);
  1490. if actasmtoken = AS_COLON then
  1491. Begin
  1492. Consume(AS_COLON);
  1493. InitRef;
  1494. opr.ref.segment:=tempreg;
  1495. { This must absolutely be followed by a reference }
  1496. if not MaybeBuildReference then
  1497. Begin
  1498. Message(asmr_e_invalid_seg_override);
  1499. Consume(actasmtoken);
  1500. end;
  1501. end
  1502. { Simple register }
  1503. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1504. Begin
  1505. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1506. Message(asmr_e_invalid_operand_type);
  1507. opr.typ:=OPR_REGISTER;
  1508. opr.reg:=tempreg;
  1509. size:=reg2opsize(opr.reg);
  1510. end
  1511. else
  1512. Message(asmr_e_syn_operand);
  1513. end;
  1514. AS_END,
  1515. AS_SEPARATOR,
  1516. AS_COMMA: ;
  1517. else
  1518. Begin
  1519. Message(asmr_e_syn_operand);
  1520. Consume(actasmtoken);
  1521. end;
  1522. end; { end case }
  1523. end;
  1524. {*****************************************************************************
  1525. T386ATTInstruction
  1526. *****************************************************************************}
  1527. type
  1528. T386AttInstruction=class(T386Instruction)
  1529. procedure InitOperands;override;
  1530. procedure BuildOpcode;override;
  1531. end;
  1532. procedure T386AttInstruction.InitOperands;
  1533. var
  1534. i : longint;
  1535. begin
  1536. OpOrder:=op_att;
  1537. for i:=1to max_operands do
  1538. Operands[i]:=T386AttOperand.Create;
  1539. end;
  1540. Procedure T386AttInstruction.BuildOpCode;
  1541. var
  1542. operandnum : longint;
  1543. PrefixOp,OverrideOp: tasmop;
  1544. Begin
  1545. PrefixOp:=A_None;
  1546. OverrideOp:=A_None;
  1547. { prefix seg opcode / prefix opcode }
  1548. repeat
  1549. if is_prefix(actopcode) then
  1550. begin
  1551. PrefixOp:=ActOpcode;
  1552. opcode:=ActOpcode;
  1553. condition:=ActCondition;
  1554. opsize:=ActOpsize;
  1555. ConcatInstruction(curlist);
  1556. Consume(AS_OPCODE);
  1557. end
  1558. else
  1559. if is_override(actopcode) then
  1560. begin
  1561. OverrideOp:=ActOpcode;
  1562. opcode:=ActOpcode;
  1563. condition:=ActCondition;
  1564. opsize:=ActOpsize;
  1565. ConcatInstruction(curlist);
  1566. Consume(AS_OPCODE);
  1567. end
  1568. else
  1569. break;
  1570. { allow for newline as in gas styled syntax }
  1571. while actasmtoken=AS_SEPARATOR do
  1572. Consume(AS_SEPARATOR);
  1573. until (actasmtoken<>AS_OPCODE);
  1574. { opcode }
  1575. if (actasmtoken <> AS_OPCODE) then
  1576. Begin
  1577. Message(asmr_e_invalid_or_missing_opcode);
  1578. RecoverConsume(true);
  1579. exit;
  1580. end;
  1581. { Fill the instr object with the current state }
  1582. Opcode:=ActOpcode;
  1583. condition:=ActCondition;
  1584. opsize:=ActOpsize;
  1585. { Valid combination of prefix/override and instruction ? }
  1586. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1587. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1588. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1589. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1590. { We are reading operands, so opcode will be an AS_ID }
  1591. operandnum:=1;
  1592. Consume(AS_OPCODE);
  1593. { Zero operand opcode ? }
  1594. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1595. begin
  1596. operandnum:=0;
  1597. exit;
  1598. end;
  1599. { Read the operands }
  1600. repeat
  1601. case actasmtoken of
  1602. AS_COMMA: { Operand delimiter }
  1603. Begin
  1604. if operandnum > Max_Operands then
  1605. Message(asmr_e_too_many_operands)
  1606. else
  1607. Inc(operandnum);
  1608. Consume(AS_COMMA);
  1609. end;
  1610. AS_SEPARATOR,
  1611. AS_END : { End of asm operands for this opcode }
  1612. begin
  1613. break;
  1614. end;
  1615. else
  1616. Operands[operandnum].BuildOperand;
  1617. end; { end case }
  1618. until false;
  1619. Ops:=operandnum;
  1620. end;
  1621. Procedure BuildConstant(maxvalue: longint);
  1622. var
  1623. asmsym,
  1624. expr: string;
  1625. value : longint;
  1626. Begin
  1627. Repeat
  1628. Case actasmtoken of
  1629. AS_STRING:
  1630. Begin
  1631. expr:=actasmpattern;
  1632. if length(expr) > 1 then
  1633. Message(asmr_e_string_not_allowed_as_const);
  1634. Consume(AS_STRING);
  1635. Case actasmtoken of
  1636. AS_COMMA: Consume(AS_COMMA);
  1637. AS_END,
  1638. AS_SEPARATOR: ;
  1639. else
  1640. Message(asmr_e_invalid_string_expression);
  1641. end; { end case }
  1642. ConcatString(curlist,expr);
  1643. end;
  1644. AS_INTNUM,
  1645. AS_PLUS,
  1646. AS_MINUS,
  1647. AS_LPAREN,
  1648. AS_NOT,
  1649. AS_ID :
  1650. Begin
  1651. BuildConstSymbolExpression(false,false,false,value,asmsym);
  1652. if asmsym<>'' then
  1653. begin
  1654. if maxvalue<>longint($ffffffff) then
  1655. Message(asmr_w_32bit_const_for_address);
  1656. ConcatConstSymbol(curlist,asmsym,value)
  1657. end
  1658. else
  1659. ConcatConstant(curlist,value,maxvalue);
  1660. end;
  1661. AS_COMMA:
  1662. Consume(AS_COMMA);
  1663. AS_END,
  1664. AS_SEPARATOR:
  1665. break;
  1666. else
  1667. begin
  1668. Message(asmr_e_syn_constant);
  1669. RecoverConsume(false);
  1670. end
  1671. end; { end case }
  1672. Until false;
  1673. end;
  1674. Procedure BuildRealConstant(typ : tfloattype);
  1675. var
  1676. expr : string;
  1677. r : bestreal;
  1678. code : integer;
  1679. negativ : boolean;
  1680. errorflag: boolean;
  1681. Begin
  1682. errorflag:=FALSE;
  1683. Repeat
  1684. negativ:=false;
  1685. expr:='';
  1686. if actasmtoken=AS_PLUS then
  1687. Consume(AS_PLUS)
  1688. else
  1689. if actasmtoken=AS_MINUS then
  1690. begin
  1691. negativ:=true;
  1692. consume(AS_MINUS);
  1693. end;
  1694. Case actasmtoken of
  1695. AS_INTNUM:
  1696. Begin
  1697. expr:=actasmpattern;
  1698. Consume(AS_INTNUM);
  1699. if negativ then
  1700. expr:='-'+expr;
  1701. val(expr,r,code);
  1702. if code<>0 then
  1703. Begin
  1704. r:=0;
  1705. Message(asmr_e_invalid_float_expr);
  1706. End;
  1707. ConcatRealConstant(curlist,r,typ);
  1708. end;
  1709. AS_REALNUM:
  1710. Begin
  1711. expr:=actasmpattern;
  1712. Consume(AS_REALNUM);
  1713. { in ATT syntax you have 0d in front of the real }
  1714. { should this be forced ? yes i think so, as to }
  1715. { conform to gas as much as possible. }
  1716. if (expr[1]='0') and (upper(expr[2])='D') then
  1717. Delete(expr,1,2);
  1718. if negativ then
  1719. expr:='-'+expr;
  1720. val(expr,r,code);
  1721. if code<>0 then
  1722. Begin
  1723. r:=0;
  1724. Message(asmr_e_invalid_float_expr);
  1725. End;
  1726. ConcatRealConstant(curlist,r,typ);
  1727. end;
  1728. AS_COMMA:
  1729. begin
  1730. Consume(AS_COMMA);
  1731. end;
  1732. AS_END,
  1733. AS_SEPARATOR:
  1734. begin
  1735. break;
  1736. end;
  1737. else
  1738. Begin
  1739. Consume(actasmtoken);
  1740. if not errorflag then
  1741. Message(asmr_e_invalid_float_expr);
  1742. errorflag:=TRUE;
  1743. end;
  1744. end;
  1745. Until false;
  1746. end;
  1747. Procedure BuildStringConstant(asciiz: boolean);
  1748. var
  1749. expr: string;
  1750. errorflag : boolean;
  1751. Begin
  1752. errorflag:=FALSE;
  1753. Repeat
  1754. Case actasmtoken of
  1755. AS_STRING:
  1756. Begin
  1757. expr:=actasmpattern;
  1758. if asciiz then
  1759. expr:=expr+#0;
  1760. ConcatPasString(curlist,expr);
  1761. Consume(AS_STRING);
  1762. end;
  1763. AS_COMMA:
  1764. begin
  1765. Consume(AS_COMMA);
  1766. end;
  1767. AS_END,
  1768. AS_SEPARATOR:
  1769. begin
  1770. break;
  1771. end;
  1772. else
  1773. Begin
  1774. Consume(actasmtoken);
  1775. if not errorflag then
  1776. Message(asmr_e_invalid_string_expression);
  1777. errorflag:=TRUE;
  1778. end;
  1779. end;
  1780. Until false;
  1781. end;
  1782. Function Assemble: tnode;
  1783. Var
  1784. hl : tasmlabel;
  1785. commname : string;
  1786. lasTSec : TSection;
  1787. l1,l2 : longint;
  1788. instr : T386ATTInstruction;
  1789. Begin
  1790. Message1(asmr_d_start_reading,'AT&T');
  1791. firsttoken:=TRUE;
  1792. { sets up all opcode and register tables in uppercase }
  1793. if not _asmsorted then
  1794. Begin
  1795. SetupTables;
  1796. _asmsorted:=TRUE;
  1797. end;
  1798. curlist:=TAAsmoutput.Create;
  1799. lasTSec:=sec_code;
  1800. { setup label linked list }
  1801. LocalLabelList:=TLocalLabelList.Create;
  1802. { start tokenizer }
  1803. c:=current_scanner.asmgetchar;
  1804. gettoken;
  1805. { main loop }
  1806. repeat
  1807. case actasmtoken of
  1808. AS_LLABEL:
  1809. Begin
  1810. if CreateLocalLabel(actasmpattern,hl,true) then
  1811. ConcatLabel(curlist,hl);
  1812. Consume(AS_LLABEL);
  1813. end;
  1814. AS_LABEL:
  1815. Begin
  1816. if SearchLabel(upper(actasmpattern),hl,true) then
  1817. ConcatLabel(curlist,hl)
  1818. else
  1819. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1820. Consume(AS_LABEL);
  1821. end;
  1822. AS_DW:
  1823. Begin
  1824. Consume(AS_DW);
  1825. BuildConstant($ffff);
  1826. end;
  1827. AS_DATA:
  1828. Begin
  1829. curList.Concat(Tai_section.Create(sec_data));
  1830. lasTSec:=sec_data;
  1831. Consume(AS_DATA);
  1832. end;
  1833. AS_TEXT:
  1834. Begin
  1835. curList.Concat(Tai_section.Create(sec_code));
  1836. lasTSec:=sec_code;
  1837. Consume(AS_TEXT);
  1838. end;
  1839. AS_DB:
  1840. Begin
  1841. Consume(AS_DB);
  1842. BuildConstant($ff);
  1843. end;
  1844. AS_DD:
  1845. Begin
  1846. Consume(AS_DD);
  1847. BuildConstant(longint($ffffffff));
  1848. end;
  1849. AS_DQ:
  1850. Begin
  1851. Consume(AS_DQ);
  1852. BuildRealConstant(s64comp);
  1853. end;
  1854. AS_SINGLE:
  1855. Begin
  1856. Consume(AS_SINGLE);
  1857. BuildRealConstant(s32real);
  1858. end;
  1859. AS_DOUBLE:
  1860. Begin
  1861. Consume(AS_DOUBLE);
  1862. BuildRealConstant(s64real);
  1863. end;
  1864. AS_EXTENDED:
  1865. Begin
  1866. Consume(AS_EXTENDED);
  1867. BuildRealConstant(s80real);
  1868. end;
  1869. AS_GLOBAL:
  1870. Begin
  1871. Consume(AS_GLOBAL);
  1872. if actasmtoken=AS_ID then
  1873. ConcatPublic(curlist,actasmpattern);
  1874. Consume(AS_ID);
  1875. if actasmtoken<>AS_SEPARATOR then
  1876. Consume(AS_SEPARATOR);
  1877. end;
  1878. AS_ALIGN:
  1879. Begin
  1880. Consume(AS_ALIGN);
  1881. l1:=BuildConstExpression(false,false);
  1882. if (target_info.system in [system_i386_GO32V2]) then
  1883. begin
  1884. l2:=1;
  1885. if (l1>=0) and (l1<=16) then
  1886. while (l1>0) do
  1887. begin
  1888. l2:=2*l2;
  1889. dec(l1);
  1890. end;
  1891. l1:=l2;
  1892. end;
  1893. ConcatAlign(curlist,l1);
  1894. Message(asmr_n_align_is_target_specific);
  1895. if actasmtoken<>AS_SEPARATOR then
  1896. Consume(AS_SEPARATOR);
  1897. end;
  1898. AS_BALIGN:
  1899. Begin
  1900. Consume(AS_BALIGN);
  1901. ConcatAlign(curlist,BuildConstExpression(false,false));
  1902. if actasmtoken<>AS_SEPARATOR then
  1903. Consume(AS_SEPARATOR);
  1904. end;
  1905. AS_P2ALIGN:
  1906. Begin
  1907. Consume(AS_P2ALIGN);
  1908. l1:=BuildConstExpression(false,false);
  1909. l2:=1;
  1910. if (l1>=0) and (l1<=16) then
  1911. while (l1>0) do
  1912. begin
  1913. l2:=2*l2;
  1914. dec(l1);
  1915. end;
  1916. l1:=l2;
  1917. ConcatAlign(curlist,l1);
  1918. if actasmtoken<>AS_SEPARATOR then
  1919. Consume(AS_SEPARATOR);
  1920. end;
  1921. AS_ASCIIZ:
  1922. Begin
  1923. Consume(AS_ASCIIZ);
  1924. BuildStringConstant(TRUE);
  1925. end;
  1926. AS_ASCII:
  1927. Begin
  1928. Consume(AS_ASCII);
  1929. BuildStringConstant(FALSE);
  1930. end;
  1931. AS_LCOMM:
  1932. Begin
  1933. Consume(AS_LCOMM);
  1934. commname:=actasmpattern;
  1935. Consume(AS_ID);
  1936. Consume(AS_COMMA);
  1937. ConcatLocalBss(commname,BuildConstExpression(false,false));
  1938. if actasmtoken<>AS_SEPARATOR then
  1939. Consume(AS_SEPARATOR);
  1940. end;
  1941. AS_COMM:
  1942. Begin
  1943. Consume(AS_COMM);
  1944. commname:=actasmpattern;
  1945. Consume(AS_ID);
  1946. Consume(AS_COMMA);
  1947. ConcatGlobalBss(commname,BuildConstExpression(false,false));
  1948. if actasmtoken<>AS_SEPARATOR then
  1949. Consume(AS_SEPARATOR);
  1950. end;
  1951. AS_OPCODE:
  1952. Begin
  1953. instr:=T386ATTInstruction.Create;
  1954. instr.BuildOpcode;
  1955. instr.AddReferenceSizes;
  1956. instr.SetInstructionOpsize;
  1957. instr.CheckOperandSizes;
  1958. instr.ConcatInstruction(curlist);
  1959. instr.Free;
  1960. end;
  1961. AS_SEPARATOR:
  1962. Begin
  1963. Consume(AS_SEPARATOR);
  1964. end;
  1965. AS_END:
  1966. begin
  1967. break; { end assembly block }
  1968. end;
  1969. else
  1970. Begin
  1971. Message(asmr_e_syntax_error);
  1972. RecoverConsume(false);
  1973. end;
  1974. end;
  1975. until false;
  1976. { Check LocalLabelList }
  1977. LocalLabelList.CheckEmitted;
  1978. LocalLabelList.Free;
  1979. { are we back in the code section? }
  1980. if lasTSec<>sec_code then
  1981. begin
  1982. Message(asmr_w_assembler_code_not_returned_to_text);
  1983. curList.Concat(Tai_section.Create(sec_code));
  1984. end;
  1985. { Return the list in an asmnode }
  1986. assemble:=casmnode.create(curlist);
  1987. Message1(asmr_d_finish_reading,'AT&T');
  1988. end;
  1989. {*****************************************************************************
  1990. Initialize
  1991. *****************************************************************************}
  1992. const
  1993. asmmode_i386_att_info : tasmmodeinfo =
  1994. (
  1995. id : asmmode_i386_att;
  1996. idtxt : 'ATT'
  1997. );
  1998. initialization
  1999. RegisterAsmMode(asmmode_i386_att_info);
  2000. finalization
  2001. if assigned(iasmops) then
  2002. iasmops.Free;
  2003. if assigned(iasmregs) then
  2004. dispose(iasmregs);
  2005. end.
  2006. {
  2007. $Log$
  2008. Revision 1.40 2003-03-18 18:15:53 peter
  2009. * changed reg2opsize to function
  2010. Revision 1.39 2003/02/20 15:52:58 pierre
  2011. * fix a range check error
  2012. Revision 1.38 2003/02/19 22:00:16 daniel
  2013. * Code generator converted to new register notation
  2014. - Horribily outdated todo.txt removed
  2015. Revision 1.37 2003/02/03 22:47:14 daniel
  2016. - Removed reg_2_opsize array
  2017. Revision 1.36 2003/01/08 18:43:57 daniel
  2018. * Tregister changed into a record
  2019. Revision 1.35 2002/12/14 15:02:03 carl
  2020. * maxoperands -> max_operands (for portability in rautils.pas)
  2021. * fix some range-check errors with loadconst
  2022. + add ncgadd unit to m68k
  2023. * some bugfix of a_param_reg with LOC_CREFERENCE
  2024. Revision 1.34 2002/12/01 22:08:34 carl
  2025. * some small cleanup (remove some specific operators which are not supported)
  2026. Revision 1.33 2002/11/30 23:16:39 carl
  2027. - removed unused message
  2028. Revision 1.32 2002/11/15 01:58:58 peter
  2029. * merged changes from 1.0.7 up to 04-11
  2030. - -V option for generating bug report tracing
  2031. - more tracing for option parsing
  2032. - errors for cdecl and high()
  2033. - win32 import stabs
  2034. - win32 records<=8 are returned in eax:edx (turned off by default)
  2035. - heaptrc update
  2036. - more info for temp management in .s file with EXTDEBUG
  2037. Revision 1.31 2002/09/03 16:26:28 daniel
  2038. * Make Tprocdef.defs protected
  2039. Revision 1.30 2002/08/13 18:01:52 carl
  2040. * rename swatoperands to swapoperands
  2041. + m68k first compilable version (still needs a lot of testing):
  2042. assembler generator, system information , inline
  2043. assembler reader.
  2044. Revision 1.29 2002/08/12 15:08:42 carl
  2045. + stab register indexes for powerpc (moved from gdb to cpubase)
  2046. + tprocessor enumeration moved to cpuinfo
  2047. + linker in target_info is now a class
  2048. * many many updates for m68k (will soon start to compile)
  2049. - removed some ifdef or correct them for correct cpu
  2050. Revision 1.28 2002/08/11 14:32:31 peter
  2051. * renamed current_library to objectlibrary
  2052. Revision 1.27 2002/08/11 13:24:17 peter
  2053. * saving of asmsymbols in ppu supported
  2054. * asmsymbollist global is removed and moved into a new class
  2055. tasmlibrarydata that will hold the info of a .a file which
  2056. corresponds with a single module. Added librarydata to tmodule
  2057. to keep the library info stored for the module. In the future the
  2058. objectfiles will also be stored to the tasmlibrarydata class
  2059. * all getlabel/newasmsymbol and friends are moved to the new class
  2060. Revision 1.26 2002/07/26 21:15:44 florian
  2061. * rewrote the system handling
  2062. Revision 1.25 2002/07/01 18:46:34 peter
  2063. * internal linker
  2064. * reorganized aasm layer
  2065. Revision 1.24 2002/05/18 13:34:25 peter
  2066. * readded missing revisions
  2067. Revision 1.23 2002/05/16 19:46:52 carl
  2068. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2069. + try to fix temp allocation (still in ifdef)
  2070. + generic constructor calls
  2071. + start of tassembler / tmodulebase class cleanup
  2072. Revision 1.21 2002/04/15 19:12:09 carl
  2073. + target_info.size_of_pointer -> pointer_size
  2074. + some cleanup of unused types/variables
  2075. * move several constants from cpubase to their specific units
  2076. (where they are used)
  2077. + att_Reg2str -> gas_reg2str
  2078. + int_reg2str -> std_reg2str
  2079. Revision 1.20 2002/04/14 17:01:52 carl
  2080. + att_reg2str -> gas_reg2str
  2081. Revision 1.19 2002/04/04 19:06:13 peter
  2082. * removed unused units
  2083. * use tlocation.size in cg.a_*loc*() routines
  2084. Revision 1.18 2002/04/02 17:11:39 peter
  2085. * tlocation,treference update
  2086. * LOC_CONSTANT added for better constant handling
  2087. * secondadd splitted in multiple routines
  2088. * location_force_reg added for loading a location to a register
  2089. of a specified size
  2090. * secondassignment parses now first the right and then the left node
  2091. (this is compatible with Kylix). This saves a lot of push/pop especially
  2092. with string operations
  2093. * adapted some routines to use the new cg methods
  2094. Revision 1.17 2002/03/28 20:48:25 carl
  2095. - remove go32v1 support
  2096. Revision 1.16 2002/01/24 18:25:53 peter
  2097. * implicit result variable generation for assembler routines
  2098. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  2099. }