ra386att.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260
  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. rax86,agx86att,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. size:=reg2opsize(actasmregister);
  1357. Consume(AS_REGISTER);
  1358. end
  1359. else
  1360. begin
  1361. InitRef;
  1362. if not MaybeBuildReference then
  1363. Message(asmr_e_syn_operand);
  1364. end;
  1365. { this is only allowed for call's and jmp's }
  1366. if not is_calljmp(actopcode) then
  1367. Message(asmr_e_syn_operand);
  1368. end;
  1369. AS_ID: { A constant expression, or a Variable ref. }
  1370. Begin
  1371. { Local Label ? }
  1372. if is_locallabel(actasmpattern) then
  1373. begin
  1374. CreateLocalLabel(actasmpattern,hl,false);
  1375. Consume(AS_ID);
  1376. AddLabelOperand(hl);
  1377. end
  1378. else
  1379. { Check for label }
  1380. if SearchLabel(actasmpattern,hl,false) then
  1381. begin
  1382. Consume(AS_ID);
  1383. AddLabelOperand(hl);
  1384. end
  1385. else
  1386. { probably a variable or normal expression }
  1387. { or a procedure (such as in CALL ID) }
  1388. Begin
  1389. { is it a constant ? }
  1390. if SearchIConstant(actasmpattern,l) then
  1391. Begin
  1392. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1393. Message(asmr_e_invalid_operand_type);
  1394. BuildConstant;
  1395. end
  1396. else
  1397. begin
  1398. InitRef;
  1399. expr:=actasmpattern;
  1400. Consume(AS_ID);
  1401. { typecasting? }
  1402. if (actasmtoken=AS_LPAREN) and
  1403. SearchType(expr) then
  1404. begin
  1405. hastype:=true;
  1406. Consume(AS_LPAREN);
  1407. tempstr:=actasmpattern;
  1408. Consume(AS_ID);
  1409. Consume(AS_RPAREN);
  1410. if SetupVar(tempstr,false) then
  1411. begin
  1412. MaybeRecordOffset;
  1413. { add a constant expression? }
  1414. if (actasmtoken=AS_PLUS) then
  1415. begin
  1416. l:=BuildConstExpression(true,false);
  1417. if opr.typ=OPR_CONSTANT then
  1418. inc(opr.val,l)
  1419. else
  1420. inc(opr.ref.offset,l);
  1421. end
  1422. end
  1423. else
  1424. Message1(sym_e_unknown_id,tempstr);
  1425. end
  1426. else
  1427. begin
  1428. if SetupVar(expr,false) then
  1429. begin
  1430. MaybeRecordOffset;
  1431. { add a constant expression? }
  1432. if (actasmtoken=AS_PLUS) then
  1433. begin
  1434. l:=BuildConstExpression(true,false);
  1435. if opr.typ=OPR_CONSTANT then
  1436. inc(opr.val,l)
  1437. else
  1438. inc(opr.ref.offset,l);
  1439. end
  1440. end
  1441. else
  1442. Begin
  1443. { look for special symbols ... }
  1444. if expr = '__RESULT' then
  1445. SetUpResult
  1446. else
  1447. if expr = '__SELF' then
  1448. SetupSelf
  1449. else
  1450. if expr = '__OLDEBP' then
  1451. SetupOldEBP
  1452. else
  1453. { check for direct symbolic names }
  1454. { only if compiling the system unit }
  1455. if (cs_compilesystem in aktmoduleswitches) then
  1456. begin
  1457. if not SetupDirectVar(expr) then
  1458. Begin
  1459. { not found, finally ... add it anyways ... }
  1460. Message1(asmr_w_id_supposed_external,expr);
  1461. opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
  1462. end;
  1463. end
  1464. else
  1465. Message1(sym_e_unknown_id,expr);
  1466. end;
  1467. end;
  1468. end;
  1469. end;
  1470. { Do we have a indexing reference, then parse it also }
  1471. if actasmtoken=AS_LPAREN then
  1472. begin
  1473. if (opr.typ=OPR_CONSTANT) then
  1474. begin
  1475. l:=opr.val;
  1476. opr.typ:=OPR_REFERENCE;
  1477. Fillchar(opr.ref,sizeof(treference),0);
  1478. opr.Ref.Offset:=l;
  1479. end;
  1480. BuildReference;
  1481. end;
  1482. end;
  1483. AS_REGISTER: { Register, a variable reference or a constant reference }
  1484. Begin
  1485. { save the type of register used. }
  1486. tempreg:=actasmregister;
  1487. Consume(AS_REGISTER);
  1488. if actasmtoken = AS_COLON then
  1489. Begin
  1490. Consume(AS_COLON);
  1491. InitRef;
  1492. opr.ref.segment:=tempreg;
  1493. { This must absolutely be followed by a reference }
  1494. if not MaybeBuildReference then
  1495. Begin
  1496. Message(asmr_e_invalid_seg_override);
  1497. Consume(actasmtoken);
  1498. end;
  1499. end
  1500. { Simple register }
  1501. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1502. Begin
  1503. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1504. Message(asmr_e_invalid_operand_type);
  1505. opr.typ:=OPR_REGISTER;
  1506. opr.reg:=tempreg;
  1507. size:=reg2opsize(opr.reg);
  1508. end
  1509. else
  1510. Message(asmr_e_syn_operand);
  1511. end;
  1512. AS_END,
  1513. AS_SEPARATOR,
  1514. AS_COMMA: ;
  1515. else
  1516. Begin
  1517. Message(asmr_e_syn_operand);
  1518. Consume(actasmtoken);
  1519. end;
  1520. end; { end case }
  1521. end;
  1522. {*****************************************************************************
  1523. T386ATTInstruction
  1524. *****************************************************************************}
  1525. type
  1526. T386AttInstruction=class(T386Instruction)
  1527. procedure InitOperands;override;
  1528. procedure BuildOpcode;override;
  1529. end;
  1530. procedure T386AttInstruction.InitOperands;
  1531. var
  1532. i : longint;
  1533. begin
  1534. OpOrder:=op_att;
  1535. for i:=1to max_operands do
  1536. Operands[i]:=T386AttOperand.Create;
  1537. end;
  1538. Procedure T386AttInstruction.BuildOpCode;
  1539. var
  1540. operandnum : longint;
  1541. PrefixOp,OverrideOp: tasmop;
  1542. Begin
  1543. PrefixOp:=A_None;
  1544. OverrideOp:=A_None;
  1545. { prefix seg opcode / prefix opcode }
  1546. repeat
  1547. if is_prefix(actopcode) then
  1548. begin
  1549. PrefixOp:=ActOpcode;
  1550. opcode:=ActOpcode;
  1551. condition:=ActCondition;
  1552. opsize:=ActOpsize;
  1553. ConcatInstruction(curlist);
  1554. Consume(AS_OPCODE);
  1555. end
  1556. else
  1557. if is_override(actopcode) then
  1558. begin
  1559. OverrideOp:=ActOpcode;
  1560. opcode:=ActOpcode;
  1561. condition:=ActCondition;
  1562. opsize:=ActOpsize;
  1563. ConcatInstruction(curlist);
  1564. Consume(AS_OPCODE);
  1565. end
  1566. else
  1567. break;
  1568. { allow for newline as in gas styled syntax }
  1569. while actasmtoken=AS_SEPARATOR do
  1570. Consume(AS_SEPARATOR);
  1571. until (actasmtoken<>AS_OPCODE);
  1572. { opcode }
  1573. if (actasmtoken <> AS_OPCODE) then
  1574. Begin
  1575. Message(asmr_e_invalid_or_missing_opcode);
  1576. RecoverConsume(true);
  1577. exit;
  1578. end;
  1579. { Fill the instr object with the current state }
  1580. Opcode:=ActOpcode;
  1581. condition:=ActCondition;
  1582. opsize:=ActOpsize;
  1583. { Valid combination of prefix/override and instruction ? }
  1584. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1585. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1586. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1587. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1588. { We are reading operands, so opcode will be an AS_ID }
  1589. operandnum:=1;
  1590. Consume(AS_OPCODE);
  1591. { Zero operand opcode ? }
  1592. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1593. begin
  1594. operandnum:=0;
  1595. exit;
  1596. end;
  1597. { Read the operands }
  1598. repeat
  1599. case actasmtoken of
  1600. AS_COMMA: { Operand delimiter }
  1601. Begin
  1602. if operandnum > Max_Operands then
  1603. Message(asmr_e_too_many_operands)
  1604. else
  1605. Inc(operandnum);
  1606. Consume(AS_COMMA);
  1607. end;
  1608. AS_SEPARATOR,
  1609. AS_END : { End of asm operands for this opcode }
  1610. begin
  1611. break;
  1612. end;
  1613. else
  1614. Operands[operandnum].BuildOperand;
  1615. end; { end case }
  1616. until false;
  1617. Ops:=operandnum;
  1618. end;
  1619. Procedure BuildConstant(maxvalue: longint);
  1620. var
  1621. asmsym,
  1622. expr: string;
  1623. value : longint;
  1624. Begin
  1625. Repeat
  1626. Case actasmtoken of
  1627. AS_STRING:
  1628. Begin
  1629. expr:=actasmpattern;
  1630. if length(expr) > 1 then
  1631. Message(asmr_e_string_not_allowed_as_const);
  1632. Consume(AS_STRING);
  1633. Case actasmtoken of
  1634. AS_COMMA: Consume(AS_COMMA);
  1635. AS_END,
  1636. AS_SEPARATOR: ;
  1637. else
  1638. Message(asmr_e_invalid_string_expression);
  1639. end; { end case }
  1640. ConcatString(curlist,expr);
  1641. end;
  1642. AS_INTNUM,
  1643. AS_PLUS,
  1644. AS_MINUS,
  1645. AS_LPAREN,
  1646. AS_NOT,
  1647. AS_ID :
  1648. Begin
  1649. BuildConstSymbolExpression(false,false,false,value,asmsym);
  1650. if asmsym<>'' then
  1651. begin
  1652. if maxvalue<>longint($ffffffff) then
  1653. Message(asmr_w_32bit_const_for_address);
  1654. ConcatConstSymbol(curlist,asmsym,value)
  1655. end
  1656. else
  1657. ConcatConstant(curlist,value,maxvalue);
  1658. end;
  1659. AS_COMMA:
  1660. Consume(AS_COMMA);
  1661. AS_END,
  1662. AS_SEPARATOR:
  1663. break;
  1664. else
  1665. begin
  1666. Message(asmr_e_syn_constant);
  1667. RecoverConsume(false);
  1668. end
  1669. end; { end case }
  1670. Until false;
  1671. end;
  1672. Procedure BuildRealConstant(typ : tfloattype);
  1673. var
  1674. expr : string;
  1675. r : bestreal;
  1676. code : integer;
  1677. negativ : boolean;
  1678. errorflag: boolean;
  1679. Begin
  1680. errorflag:=FALSE;
  1681. Repeat
  1682. negativ:=false;
  1683. expr:='';
  1684. if actasmtoken=AS_PLUS then
  1685. Consume(AS_PLUS)
  1686. else
  1687. if actasmtoken=AS_MINUS then
  1688. begin
  1689. negativ:=true;
  1690. consume(AS_MINUS);
  1691. end;
  1692. Case actasmtoken of
  1693. AS_INTNUM:
  1694. Begin
  1695. expr:=actasmpattern;
  1696. Consume(AS_INTNUM);
  1697. if negativ then
  1698. expr:='-'+expr;
  1699. val(expr,r,code);
  1700. if code<>0 then
  1701. Begin
  1702. r:=0;
  1703. Message(asmr_e_invalid_float_expr);
  1704. End;
  1705. ConcatRealConstant(curlist,r,typ);
  1706. end;
  1707. AS_REALNUM:
  1708. Begin
  1709. expr:=actasmpattern;
  1710. Consume(AS_REALNUM);
  1711. { in ATT syntax you have 0d in front of the real }
  1712. { should this be forced ? yes i think so, as to }
  1713. { conform to gas as much as possible. }
  1714. if (expr[1]='0') and (upper(expr[2])='D') then
  1715. Delete(expr,1,2);
  1716. if negativ then
  1717. expr:='-'+expr;
  1718. val(expr,r,code);
  1719. if code<>0 then
  1720. Begin
  1721. r:=0;
  1722. Message(asmr_e_invalid_float_expr);
  1723. End;
  1724. ConcatRealConstant(curlist,r,typ);
  1725. end;
  1726. AS_COMMA:
  1727. begin
  1728. Consume(AS_COMMA);
  1729. end;
  1730. AS_END,
  1731. AS_SEPARATOR:
  1732. begin
  1733. break;
  1734. end;
  1735. else
  1736. Begin
  1737. Consume(actasmtoken);
  1738. if not errorflag then
  1739. Message(asmr_e_invalid_float_expr);
  1740. errorflag:=TRUE;
  1741. end;
  1742. end;
  1743. Until false;
  1744. end;
  1745. Procedure BuildStringConstant(asciiz: boolean);
  1746. var
  1747. expr: string;
  1748. errorflag : boolean;
  1749. Begin
  1750. errorflag:=FALSE;
  1751. Repeat
  1752. Case actasmtoken of
  1753. AS_STRING:
  1754. Begin
  1755. expr:=actasmpattern;
  1756. if asciiz then
  1757. expr:=expr+#0;
  1758. ConcatPasString(curlist,expr);
  1759. Consume(AS_STRING);
  1760. end;
  1761. AS_COMMA:
  1762. begin
  1763. Consume(AS_COMMA);
  1764. end;
  1765. AS_END,
  1766. AS_SEPARATOR:
  1767. begin
  1768. break;
  1769. end;
  1770. else
  1771. Begin
  1772. Consume(actasmtoken);
  1773. if not errorflag then
  1774. Message(asmr_e_invalid_string_expression);
  1775. errorflag:=TRUE;
  1776. end;
  1777. end;
  1778. Until false;
  1779. end;
  1780. Function Assemble: tnode;
  1781. Var
  1782. hl : tasmlabel;
  1783. commname : string;
  1784. lasTSec : TSection;
  1785. l1,l2 : longint;
  1786. instr : T386ATTInstruction;
  1787. Begin
  1788. Message1(asmr_d_start_reading,'AT&T');
  1789. firsttoken:=TRUE;
  1790. { sets up all opcode and register tables in uppercase }
  1791. if not _asmsorted then
  1792. Begin
  1793. SetupTables;
  1794. _asmsorted:=TRUE;
  1795. end;
  1796. curlist:=TAAsmoutput.Create;
  1797. lasTSec:=sec_code;
  1798. { setup label linked list }
  1799. LocalLabelList:=TLocalLabelList.Create;
  1800. { start tokenizer }
  1801. c:=current_scanner.asmgetchar;
  1802. gettoken;
  1803. { main loop }
  1804. repeat
  1805. case actasmtoken of
  1806. AS_LLABEL:
  1807. Begin
  1808. if CreateLocalLabel(actasmpattern,hl,true) then
  1809. ConcatLabel(curlist,hl);
  1810. Consume(AS_LLABEL);
  1811. end;
  1812. AS_LABEL:
  1813. Begin
  1814. if SearchLabel(upper(actasmpattern),hl,true) then
  1815. ConcatLabel(curlist,hl)
  1816. else
  1817. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1818. Consume(AS_LABEL);
  1819. end;
  1820. AS_DW:
  1821. Begin
  1822. Consume(AS_DW);
  1823. BuildConstant($ffff);
  1824. end;
  1825. AS_DATA:
  1826. Begin
  1827. curList.Concat(Tai_section.Create(sec_data));
  1828. lasTSec:=sec_data;
  1829. Consume(AS_DATA);
  1830. end;
  1831. AS_TEXT:
  1832. Begin
  1833. curList.Concat(Tai_section.Create(sec_code));
  1834. lasTSec:=sec_code;
  1835. Consume(AS_TEXT);
  1836. end;
  1837. AS_DB:
  1838. Begin
  1839. Consume(AS_DB);
  1840. BuildConstant($ff);
  1841. end;
  1842. AS_DD:
  1843. Begin
  1844. Consume(AS_DD);
  1845. BuildConstant(longint($ffffffff));
  1846. end;
  1847. AS_DQ:
  1848. Begin
  1849. Consume(AS_DQ);
  1850. BuildRealConstant(s64comp);
  1851. end;
  1852. AS_SINGLE:
  1853. Begin
  1854. Consume(AS_SINGLE);
  1855. BuildRealConstant(s32real);
  1856. end;
  1857. AS_DOUBLE:
  1858. Begin
  1859. Consume(AS_DOUBLE);
  1860. BuildRealConstant(s64real);
  1861. end;
  1862. AS_EXTENDED:
  1863. Begin
  1864. Consume(AS_EXTENDED);
  1865. BuildRealConstant(s80real);
  1866. end;
  1867. AS_GLOBAL:
  1868. Begin
  1869. Consume(AS_GLOBAL);
  1870. if actasmtoken=AS_ID then
  1871. ConcatPublic(curlist,actasmpattern);
  1872. Consume(AS_ID);
  1873. if actasmtoken<>AS_SEPARATOR then
  1874. Consume(AS_SEPARATOR);
  1875. end;
  1876. AS_ALIGN:
  1877. Begin
  1878. Consume(AS_ALIGN);
  1879. l1:=BuildConstExpression(false,false);
  1880. if (target_info.system in [system_i386_GO32V2]) then
  1881. begin
  1882. l2:=1;
  1883. if (l1>=0) and (l1<=16) then
  1884. while (l1>0) do
  1885. begin
  1886. l2:=2*l2;
  1887. dec(l1);
  1888. end;
  1889. l1:=l2;
  1890. end;
  1891. ConcatAlign(curlist,l1);
  1892. Message(asmr_n_align_is_target_specific);
  1893. if actasmtoken<>AS_SEPARATOR then
  1894. Consume(AS_SEPARATOR);
  1895. end;
  1896. AS_BALIGN:
  1897. Begin
  1898. Consume(AS_BALIGN);
  1899. ConcatAlign(curlist,BuildConstExpression(false,false));
  1900. if actasmtoken<>AS_SEPARATOR then
  1901. Consume(AS_SEPARATOR);
  1902. end;
  1903. AS_P2ALIGN:
  1904. Begin
  1905. Consume(AS_P2ALIGN);
  1906. l1:=BuildConstExpression(false,false);
  1907. l2:=1;
  1908. if (l1>=0) and (l1<=16) then
  1909. while (l1>0) do
  1910. begin
  1911. l2:=2*l2;
  1912. dec(l1);
  1913. end;
  1914. l1:=l2;
  1915. ConcatAlign(curlist,l1);
  1916. if actasmtoken<>AS_SEPARATOR then
  1917. Consume(AS_SEPARATOR);
  1918. end;
  1919. AS_ASCIIZ:
  1920. Begin
  1921. Consume(AS_ASCIIZ);
  1922. BuildStringConstant(TRUE);
  1923. end;
  1924. AS_ASCII:
  1925. Begin
  1926. Consume(AS_ASCII);
  1927. BuildStringConstant(FALSE);
  1928. end;
  1929. AS_LCOMM:
  1930. Begin
  1931. Consume(AS_LCOMM);
  1932. commname:=actasmpattern;
  1933. Consume(AS_ID);
  1934. Consume(AS_COMMA);
  1935. ConcatLocalBss(commname,BuildConstExpression(false,false));
  1936. if actasmtoken<>AS_SEPARATOR then
  1937. Consume(AS_SEPARATOR);
  1938. end;
  1939. AS_COMM:
  1940. Begin
  1941. Consume(AS_COMM);
  1942. commname:=actasmpattern;
  1943. Consume(AS_ID);
  1944. Consume(AS_COMMA);
  1945. ConcatGlobalBss(commname,BuildConstExpression(false,false));
  1946. if actasmtoken<>AS_SEPARATOR then
  1947. Consume(AS_SEPARATOR);
  1948. end;
  1949. AS_OPCODE:
  1950. Begin
  1951. instr:=T386ATTInstruction.Create;
  1952. instr.BuildOpcode;
  1953. instr.AddReferenceSizes;
  1954. instr.SetInstructionOpsize;
  1955. instr.CheckOperandSizes;
  1956. instr.ConcatInstruction(curlist);
  1957. instr.Free;
  1958. end;
  1959. AS_SEPARATOR:
  1960. Begin
  1961. Consume(AS_SEPARATOR);
  1962. end;
  1963. AS_END:
  1964. begin
  1965. break; { end assembly block }
  1966. end;
  1967. else
  1968. Begin
  1969. Message(asmr_e_syntax_error);
  1970. RecoverConsume(false);
  1971. end;
  1972. end;
  1973. until false;
  1974. { Check LocalLabelList }
  1975. LocalLabelList.CheckEmitted;
  1976. LocalLabelList.Free;
  1977. { are we back in the code section? }
  1978. if lasTSec<>sec_code then
  1979. begin
  1980. Message(asmr_w_assembler_code_not_returned_to_text);
  1981. curList.Concat(Tai_section.Create(sec_code));
  1982. end;
  1983. { Return the list in an asmnode }
  1984. assemble:=casmnode.create(curlist);
  1985. Message1(asmr_d_finish_reading,'AT&T');
  1986. end;
  1987. {*****************************************************************************
  1988. Initialize
  1989. *****************************************************************************}
  1990. const
  1991. asmmode_i386_att_info : tasmmodeinfo =
  1992. (
  1993. id : asmmode_i386_att;
  1994. idtxt : 'ATT'
  1995. );
  1996. initialization
  1997. RegisterAsmMode(asmmode_i386_att_info);
  1998. finalization
  1999. if assigned(iasmops) then
  2000. iasmops.Free;
  2001. if assigned(iasmregs) then
  2002. dispose(iasmregs);
  2003. end.
  2004. {
  2005. $Log$
  2006. Revision 1.43 2003-04-30 15:45:35 florian
  2007. * merged more x86-64/i386 code
  2008. Revision 1.42 2003/04/25 12:04:31 florian
  2009. * merged agx64att and ag386att to x86/agx86att
  2010. Revision 1.41 2003/04/21 20:05:10 peter
  2011. * removed some ie checks
  2012. Revision 1.40 2003/03/18 18:15:53 peter
  2013. * changed reg2opsize to function
  2014. Revision 1.39 2003/02/20 15:52:58 pierre
  2015. * fix a range check error
  2016. Revision 1.38 2003/02/19 22:00:16 daniel
  2017. * Code generator converted to new register notation
  2018. - Horribily outdated todo.txt removed
  2019. Revision 1.37 2003/02/03 22:47:14 daniel
  2020. - Removed reg_2_opsize array
  2021. Revision 1.36 2003/01/08 18:43:57 daniel
  2022. * Tregister changed into a record
  2023. Revision 1.35 2002/12/14 15:02:03 carl
  2024. * maxoperands -> max_operands (for portability in rautils.pas)
  2025. * fix some range-check errors with loadconst
  2026. + add ncgadd unit to m68k
  2027. * some bugfix of a_param_reg with LOC_CREFERENCE
  2028. Revision 1.34 2002/12/01 22:08:34 carl
  2029. * some small cleanup (remove some specific operators which are not supported)
  2030. Revision 1.33 2002/11/30 23:16:39 carl
  2031. - removed unused message
  2032. Revision 1.32 2002/11/15 01:58:58 peter
  2033. * merged changes from 1.0.7 up to 04-11
  2034. - -V option for generating bug report tracing
  2035. - more tracing for option parsing
  2036. - errors for cdecl and high()
  2037. - win32 import stabs
  2038. - win32 records<=8 are returned in eax:edx (turned off by default)
  2039. - heaptrc update
  2040. - more info for temp management in .s file with EXTDEBUG
  2041. Revision 1.31 2002/09/03 16:26:28 daniel
  2042. * Make Tprocdef.defs protected
  2043. Revision 1.30 2002/08/13 18:01:52 carl
  2044. * rename swatoperands to swapoperands
  2045. + m68k first compilable version (still needs a lot of testing):
  2046. assembler generator, system information , inline
  2047. assembler reader.
  2048. Revision 1.29 2002/08/12 15:08:42 carl
  2049. + stab register indexes for powerpc (moved from gdb to cpubase)
  2050. + tprocessor enumeration moved to cpuinfo
  2051. + linker in target_info is now a class
  2052. * many many updates for m68k (will soon start to compile)
  2053. - removed some ifdef or correct them for correct cpu
  2054. Revision 1.28 2002/08/11 14:32:31 peter
  2055. * renamed current_library to objectlibrary
  2056. Revision 1.27 2002/08/11 13:24:17 peter
  2057. * saving of asmsymbols in ppu supported
  2058. * asmsymbollist global is removed and moved into a new class
  2059. tasmlibrarydata that will hold the info of a .a file which
  2060. corresponds with a single module. Added librarydata to tmodule
  2061. to keep the library info stored for the module. In the future the
  2062. objectfiles will also be stored to the tasmlibrarydata class
  2063. * all getlabel/newasmsymbol and friends are moved to the new class
  2064. Revision 1.26 2002/07/26 21:15:44 florian
  2065. * rewrote the system handling
  2066. Revision 1.25 2002/07/01 18:46:34 peter
  2067. * internal linker
  2068. * reorganized aasm layer
  2069. Revision 1.24 2002/05/18 13:34:25 peter
  2070. * readded missing revisions
  2071. Revision 1.23 2002/05/16 19:46:52 carl
  2072. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2073. + try to fix temp allocation (still in ifdef)
  2074. + generic constructor calls
  2075. + start of tassembler / tmodulebase class cleanup
  2076. Revision 1.21 2002/04/15 19:12:09 carl
  2077. + target_info.size_of_pointer -> pointer_size
  2078. + some cleanup of unused types/variables
  2079. * move several constants from cpubase to their specific units
  2080. (where they are used)
  2081. + att_Reg2str -> gas_reg2str
  2082. + int_reg2str -> std_reg2str
  2083. Revision 1.20 2002/04/14 17:01:52 carl
  2084. + att_reg2str -> gas_reg2str
  2085. Revision 1.19 2002/04/04 19:06:13 peter
  2086. * removed unused units
  2087. * use tlocation.size in cg.a_*loc*() routines
  2088. Revision 1.18 2002/04/02 17:11:39 peter
  2089. * tlocation,treference update
  2090. * LOC_CONSTANT added for better constant handling
  2091. * secondadd splitted in multiple routines
  2092. * location_force_reg added for loading a location to a register
  2093. of a specified size
  2094. * secondassignment parses now first the right and then the left node
  2095. (this is compatible with Kylix). This saves a lot of push/pop especially
  2096. with string operations
  2097. * adapted some routines to use the new cg methods
  2098. Revision 1.17 2002/03/28 20:48:25 carl
  2099. - remove go32v1 support
  2100. Revision 1.16 2002/01/24 18:25:53 peter
  2101. * implicit result variable generation for assembler routines
  2102. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  2103. }