ra386att.pas 62 KB

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