ra386att.pas 64 KB

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