ra386att.pas 61 KB

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