ra386att.pas 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Does the parsing for the AT&T styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit Ra386att;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. node;
  23. function assemble: tnode;
  24. Implementation
  25. uses
  26. { common }
  27. cutils,cclasses,
  28. { global }
  29. globtype,globals,verbose,
  30. systems,
  31. { aasm }
  32. cpubase,cpuinfo,aasmbase,aasmtai,aasmcpu,
  33. { symtable }
  34. symconst,symbase,symtype,symsym,symtable,
  35. { pass 1 }
  36. nbas,
  37. { parser }
  38. scanner,
  39. ra386,ag386att,rautils
  40. ;
  41. type
  42. tasmtoken = (
  43. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  44. AS_REALNUM,AS_COMMA,AS_LPAREN,
  45. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
  46. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
  47. {------------------ Assembler directives --------------------}
  48. AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
  49. AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
  50. AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
  51. AS_DATA,AS_TEXT,AS_END,
  52. {------------------ Assembler Operators --------------------}
  53. AS_TYPE,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR);
  54. tasmkeyword = string[10];
  55. const
  56. { These tokens should be modified accordingly to the modifications }
  57. { in the different enumerations. }
  58. firstdirective = AS_DB;
  59. lastdirective = AS_END;
  60. token2str : array[tasmtoken] of tasmkeyword=(
  61. '','Label','LLabel','string','integer',
  62. 'float',',','(',
  63. ')',':','.','+','-','*',
  64. ';','identifier','register','opcode','/','$',
  65. '.byte','.word','.long','.quad','.globl',
  66. '.align','.balign','.p2align','.ascii',
  67. '.asciz','.lcomm','.comm','.single','.double','.tfloat',
  68. '.data','.text','END',
  69. 'TYPE','%','<<','>>','!','&','|','^','~');
  70. const
  71. newline = #10;
  72. firsttoken : boolean = TRUE;
  73. var
  74. _asmsorted : boolean;
  75. curlist : TAAsmoutput;
  76. c : char;
  77. actasmtoken : tasmtoken;
  78. prevasmtoken : tasmtoken;
  79. actasmpattern : string;
  80. actopcode : tasmop;
  81. actasmregister : tregister;
  82. actopsize : topsize;
  83. actcondition : tasmcond;
  84. iasmops : tdictionary;
  85. iasmregs : ^reg2strtable;
  86. Procedure SetupTables;
  87. { creates uppercased symbol tables for speed access }
  88. var
  89. i : tasmop;
  90. j : Toldregister;
  91. str2opentry: tstr2opentry;
  92. Begin
  93. { opcodes }
  94. iasmops:=TDictionary.Create;
  95. iasmops.delete_doubles:=true;
  96. for i:=firstop to lastop do
  97. begin
  98. str2opentry:=tstr2opentry.createname(upper(gas_op2str[i]));
  99. str2opentry.op:=i;
  100. iasmops.insert(str2opentry);
  101. end;
  102. { registers }
  103. new(iasmregs);
  104. for j:=firstreg to lastreg do
  105. iasmregs^[j] := upper(gas_reg2str[j]);
  106. end;
  107. {---------------------------------------------------------------------}
  108. { Routines for the tokenizing }
  109. {---------------------------------------------------------------------}
  110. function is_asmopcode(const s: string):boolean;
  111. const
  112. { We need first to check the long prefixes, else we get probs
  113. with things like movsbl }
  114. att_sizesuffixstr : array[0..9] of string[2] = (
  115. '','BW','BL','WL','B','W','L','S','Q','T'
  116. );
  117. att_sizesuffix : array[0..9] of topsize = (
  118. S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
  119. );
  120. att_sizefpusuffix : array[0..9] of topsize = (
  121. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
  122. );
  123. att_sizefpuintsuffix : array[0..9] of topsize = (
  124. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
  125. );
  126. var
  127. str2opentry: tstr2opentry;
  128. cond : string[4];
  129. cnd : tasmcond;
  130. len,
  131. j,
  132. sufidx : longint;
  133. Begin
  134. is_asmopcode:=FALSE;
  135. actopcode:=A_None;
  136. actcondition:=C_None;
  137. actopsize:=S_NO;
  138. { search for all possible suffixes }
  139. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  140. begin
  141. len:=length(s)-length(att_sizesuffixstr[sufidx]);
  142. if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
  143. begin
  144. { here we search the entire table... }
  145. str2opentry:=nil;
  146. if {(length(s)>0) and} (len>0) then
  147. str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
  148. if assigned(str2opentry) then
  149. begin
  150. actopcode:=str2opentry.op;
  151. if gas_needsuffix[actopcode]=attsufFPU then
  152. actopsize:=att_sizefpusuffix[sufidx]
  153. else if gas_needsuffix[actopcode]=attsufFPUint then
  154. actopsize:=att_sizefpuintsuffix[sufidx]
  155. else
  156. actopsize:=att_sizesuffix[sufidx];
  157. actasmtoken:=AS_OPCODE;
  158. is_asmopcode:=TRUE;
  159. exit;
  160. end;
  161. { not found, check condition opcodes }
  162. j:=0;
  163. while (j<CondAsmOps) do
  164. begin
  165. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  166. begin
  167. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  168. if cond<>'' then
  169. begin
  170. for cnd:=low(TasmCond) to high(TasmCond) do
  171. if Cond=Upper(cond2str[cnd]) then
  172. begin
  173. actopcode:=CondASmOp[j];
  174. if gas_needsuffix[actopcode]=attsufFPU then
  175. actopsize:=att_sizefpusuffix[sufidx]
  176. else if gas_needsuffix[actopcode]=attsufFPUint then
  177. actopsize:=att_sizefpuintsuffix[sufidx]
  178. else
  179. actopsize:=att_sizesuffix[sufidx];
  180. actcondition:=cnd;
  181. actasmtoken:=AS_OPCODE;
  182. is_asmopcode:=TRUE;
  183. exit;
  184. end;
  185. end;
  186. end;
  187. inc(j);
  188. end;
  189. end;
  190. end;
  191. end;
  192. Function is_asmdirective(const s: string):boolean;
  193. var
  194. i : tasmtoken;
  195. hs : string;
  196. Begin
  197. { GNU as is also not casesensitive with this }
  198. hs:=lower(s);
  199. for i:=firstdirective to lastdirective do
  200. if hs=token2str[i] then
  201. begin
  202. actasmtoken:=i;
  203. is_asmdirective:=true;
  204. exit;
  205. end;
  206. is_asmdirective:=false;
  207. end;
  208. Function is_register(const s: string):boolean;
  209. Var
  210. i : Toldregister;
  211. Begin
  212. actasmregister.enum:=R_NO;
  213. for i:=firstreg to lastreg do
  214. if s=iasmregs^[i] then
  215. begin
  216. actasmtoken:=AS_REGISTER;
  217. actasmregister.enum:=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.enum>lastreg then
  1099. internalerror(200301081);
  1100. if opr.ref.base.enum<>R_NO then
  1101. Message(asmr_e_cannot_index_relative_var);
  1102. opr.ref.base:=actasmregister;
  1103. Consume(AS_REGISTER);
  1104. { can either be a register or a right parenthesis }
  1105. { (reg) }
  1106. if actasmtoken=AS_RPAREN then
  1107. Begin
  1108. Consume_RParen;
  1109. exit;
  1110. end;
  1111. { (reg,reg .. }
  1112. Consume(AS_COMMA);
  1113. if actasmtoken=AS_REGISTER then
  1114. Begin
  1115. opr.ref.index:=actasmregister;
  1116. Consume(AS_REGISTER);
  1117. { check for scaling ... }
  1118. case actasmtoken of
  1119. AS_RPAREN:
  1120. Begin
  1121. Consume_RParen;
  1122. exit;
  1123. end;
  1124. AS_COMMA:
  1125. Begin
  1126. Consume(AS_COMMA);
  1127. Consume_Scale;
  1128. Consume_RParen;
  1129. end;
  1130. else
  1131. Begin
  1132. Message(asmr_e_invalid_reference_syntax);
  1133. RecoverConsume(false);
  1134. end;
  1135. end; { end case }
  1136. end
  1137. else
  1138. Begin
  1139. Message(asmr_e_invalid_reference_syntax);
  1140. RecoverConsume(false);
  1141. end;
  1142. end; {end case }
  1143. AS_COMMA: { (, ... can either be scaling, or index }
  1144. Begin
  1145. Consume(AS_COMMA);
  1146. { Index }
  1147. if (actasmtoken=AS_REGISTER) then
  1148. Begin
  1149. opr.ref.index:=actasmregister;
  1150. Consume(AS_REGISTER);
  1151. { check for scaling ... }
  1152. case actasmtoken of
  1153. AS_RPAREN:
  1154. Begin
  1155. Consume_RParen;
  1156. exit;
  1157. end;
  1158. AS_COMMA:
  1159. Begin
  1160. Consume(AS_COMMA);
  1161. Consume_Scale;
  1162. Consume_RParen;
  1163. end;
  1164. else
  1165. Begin
  1166. Message(asmr_e_invalid_reference_syntax);
  1167. RecoverConsume(false);
  1168. end;
  1169. end; {end case }
  1170. end
  1171. { Scaling }
  1172. else
  1173. Begin
  1174. Consume_Scale;
  1175. Consume_RParen;
  1176. exit;
  1177. end;
  1178. end;
  1179. else
  1180. Begin
  1181. Message(asmr_e_invalid_reference_syntax);
  1182. RecoverConsume(false);
  1183. end;
  1184. end;
  1185. end;
  1186. Procedure T386ATTOperand.BuildConstant;
  1187. var
  1188. l : longint;
  1189. tempstr : string;
  1190. begin
  1191. BuildConstSymbolExpression(false,false,true,l,tempstr);
  1192. if tempstr<>'' then
  1193. begin
  1194. opr.typ:=OPR_SYMBOL;
  1195. opr.symofs:=l;
  1196. opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1197. end
  1198. else
  1199. begin
  1200. opr.typ:=OPR_CONSTANT;
  1201. opr.val:=l;
  1202. end;
  1203. end;
  1204. Procedure T386ATTOperand.BuildOperand;
  1205. var
  1206. tempstr,tempstr2,
  1207. expr : string;
  1208. l,k : longint;
  1209. procedure AddLabelOperand(hl:tasmlabel);
  1210. begin
  1211. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  1212. is_calljmp(actopcode) then
  1213. begin
  1214. opr.typ:=OPR_SYMBOL;
  1215. opr.symbol:=hl;
  1216. end
  1217. else
  1218. begin
  1219. InitRef;
  1220. opr.ref.symbol:=hl;
  1221. end;
  1222. end;
  1223. procedure MaybeRecordOffset;
  1224. var
  1225. hasdot : boolean;
  1226. l,
  1227. toffset,
  1228. tsize : longint;
  1229. begin
  1230. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  1231. exit;
  1232. l:=0;
  1233. hasdot:=(actasmtoken=AS_DOT);
  1234. if hasdot then
  1235. begin
  1236. if expr<>'' then
  1237. begin
  1238. BuildRecordOffsetSize(expr,toffset,tsize);
  1239. inc(l,toffset);
  1240. SetSize(tsize,true);
  1241. end;
  1242. end;
  1243. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1244. inc(l,BuildConstExpression(true,false));
  1245. if opr.typ=OPR_REFERENCE then
  1246. begin
  1247. if hasdot and (not hastype) and (opr.ref.options=ref_parafixup) then
  1248. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1249. inc(opr.ref.offset,l)
  1250. end
  1251. else
  1252. inc(opr.val,l);
  1253. end;
  1254. function MaybeBuildReference:boolean;
  1255. { Try to create a reference, if not a reference is found then false
  1256. is returned }
  1257. begin
  1258. MaybeBuildReference:=true;
  1259. case actasmtoken of
  1260. AS_INTNUM,
  1261. AS_MINUS,
  1262. AS_PLUS:
  1263. Begin
  1264. opr.ref.offset:=BuildConstExpression(True,False);
  1265. if actasmtoken<>AS_LPAREN then
  1266. Message(asmr_e_invalid_reference_syntax)
  1267. else
  1268. BuildReference;
  1269. end;
  1270. AS_LPAREN:
  1271. BuildReference;
  1272. AS_ID: { only a variable is allowed ... }
  1273. Begin
  1274. tempstr:=actasmpattern;
  1275. Consume(AS_ID);
  1276. { typecasting? }
  1277. if (actasmtoken=AS_LPAREN) and
  1278. SearchType(tempstr) then
  1279. begin
  1280. hastype:=true;
  1281. Consume(AS_LPAREN);
  1282. tempstr2:=actasmpattern;
  1283. Consume(AS_ID);
  1284. Consume(AS_RPAREN);
  1285. if not SetupVar(tempstr2,false) then
  1286. Message1(sym_e_unknown_id,tempstr2);
  1287. end
  1288. else
  1289. if not SetupVar(tempstr,false) then
  1290. Message1(sym_e_unknown_id,tempstr);
  1291. { record.field ? }
  1292. if actasmtoken=AS_DOT then
  1293. begin
  1294. BuildRecordOffsetSize(tempstr,l,k);
  1295. inc(opr.ref.offset,l);
  1296. end;
  1297. case actasmtoken of
  1298. AS_END,
  1299. AS_SEPARATOR,
  1300. AS_COMMA: ;
  1301. AS_LPAREN: BuildReference;
  1302. else
  1303. Begin
  1304. Message(asmr_e_invalid_reference_syntax);
  1305. Consume(actasmtoken);
  1306. end;
  1307. end; {end case }
  1308. end;
  1309. else
  1310. MaybeBuildReference:=false;
  1311. end; { end case }
  1312. end;
  1313. var
  1314. tempreg : tregister;
  1315. hl : tasmlabel;
  1316. Begin
  1317. expr:='';
  1318. case actasmtoken of
  1319. AS_LPAREN: { Memory reference or constant expression }
  1320. Begin
  1321. InitRef;
  1322. BuildReference;
  1323. end;
  1324. AS_DOLLAR: { Constant expression }
  1325. Begin
  1326. Consume(AS_DOLLAR);
  1327. BuildConstant;
  1328. end;
  1329. AS_INTNUM,
  1330. AS_MINUS,
  1331. AS_PLUS:
  1332. Begin
  1333. { Constant memory offset }
  1334. { This must absolutely be followed by ( }
  1335. InitRef;
  1336. opr.ref.offset:=BuildConstExpression(True,False);
  1337. if actasmtoken<>AS_LPAREN then
  1338. Message(asmr_e_invalid_reference_syntax)
  1339. else
  1340. BuildReference;
  1341. end;
  1342. AS_STAR: { Call from memory address }
  1343. Begin
  1344. Consume(AS_STAR);
  1345. if actasmtoken=AS_REGISTER then
  1346. begin
  1347. opr.typ:=OPR_REGISTER;
  1348. opr.reg:=actasmregister;
  1349. if opr.reg.enum>lastreg then
  1350. internalerror(200301081);
  1351. size:=reg_2_opsize[actasmregister.enum];
  1352. Consume(AS_REGISTER);
  1353. end
  1354. else
  1355. begin
  1356. InitRef;
  1357. if not MaybeBuildReference then
  1358. Message(asmr_e_syn_operand);
  1359. end;
  1360. { this is only allowed for call's and jmp's }
  1361. if not is_calljmp(actopcode) then
  1362. Message(asmr_e_syn_operand);
  1363. end;
  1364. AS_ID: { A constant expression, or a Variable ref. }
  1365. Begin
  1366. { Local Label ? }
  1367. if is_locallabel(actasmpattern) then
  1368. begin
  1369. CreateLocalLabel(actasmpattern,hl,false);
  1370. Consume(AS_ID);
  1371. AddLabelOperand(hl);
  1372. end
  1373. else
  1374. { Check for label }
  1375. if SearchLabel(actasmpattern,hl,false) then
  1376. begin
  1377. Consume(AS_ID);
  1378. AddLabelOperand(hl);
  1379. end
  1380. else
  1381. { probably a variable or normal expression }
  1382. { or a procedure (such as in CALL ID) }
  1383. Begin
  1384. { is it a constant ? }
  1385. if SearchIConstant(actasmpattern,l) then
  1386. Begin
  1387. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1388. Message(asmr_e_invalid_operand_type);
  1389. BuildConstant;
  1390. end
  1391. else
  1392. begin
  1393. InitRef;
  1394. expr:=actasmpattern;
  1395. Consume(AS_ID);
  1396. { typecasting? }
  1397. if (actasmtoken=AS_LPAREN) and
  1398. SearchType(expr) then
  1399. begin
  1400. hastype:=true;
  1401. Consume(AS_LPAREN);
  1402. tempstr:=actasmpattern;
  1403. Consume(AS_ID);
  1404. Consume(AS_RPAREN);
  1405. if SetupVar(tempstr,false) then
  1406. begin
  1407. MaybeRecordOffset;
  1408. { add a constant expression? }
  1409. if (actasmtoken=AS_PLUS) then
  1410. begin
  1411. l:=BuildConstExpression(true,false);
  1412. if opr.typ=OPR_CONSTANT then
  1413. inc(opr.val,l)
  1414. else
  1415. inc(opr.ref.offset,l);
  1416. end
  1417. end
  1418. else
  1419. Message1(sym_e_unknown_id,tempstr);
  1420. end
  1421. else
  1422. begin
  1423. if SetupVar(expr,false) then
  1424. begin
  1425. MaybeRecordOffset;
  1426. { add a constant expression? }
  1427. if (actasmtoken=AS_PLUS) then
  1428. begin
  1429. l:=BuildConstExpression(true,false);
  1430. if opr.typ=OPR_CONSTANT then
  1431. inc(opr.val,l)
  1432. else
  1433. inc(opr.ref.offset,l);
  1434. end
  1435. end
  1436. else
  1437. Begin
  1438. { look for special symbols ... }
  1439. if expr = '__RESULT' then
  1440. SetUpResult
  1441. else
  1442. if expr = '__SELF' then
  1443. SetupSelf
  1444. else
  1445. if expr = '__OLDEBP' then
  1446. SetupOldEBP
  1447. else
  1448. { check for direct symbolic names }
  1449. { only if compiling the system unit }
  1450. if (cs_compilesystem in aktmoduleswitches) then
  1451. begin
  1452. if not SetupDirectVar(expr) then
  1453. Begin
  1454. { not found, finally ... add it anyways ... }
  1455. Message1(asmr_w_id_supposed_external,expr);
  1456. opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
  1457. end;
  1458. end
  1459. else
  1460. Message1(sym_e_unknown_id,expr);
  1461. end;
  1462. end;
  1463. end;
  1464. end;
  1465. { Do we have a indexing reference, then parse it also }
  1466. if actasmtoken=AS_LPAREN then
  1467. begin
  1468. if (opr.typ=OPR_CONSTANT) then
  1469. begin
  1470. l:=opr.val;
  1471. opr.typ:=OPR_REFERENCE;
  1472. Fillchar(opr.ref,sizeof(treference),0);
  1473. opr.Ref.Offset:=l;
  1474. end;
  1475. BuildReference;
  1476. end;
  1477. end;
  1478. AS_REGISTER: { Register, a variable reference or a constant reference }
  1479. Begin
  1480. { save the type of register used. }
  1481. tempreg:=actasmregister;
  1482. Consume(AS_REGISTER);
  1483. if actasmtoken = AS_COLON then
  1484. Begin
  1485. Consume(AS_COLON);
  1486. InitRef;
  1487. opr.ref.segment:=tempreg;
  1488. { This must absolutely be followed by a reference }
  1489. if not MaybeBuildReference then
  1490. Begin
  1491. Message(asmr_e_invalid_seg_override);
  1492. Consume(actasmtoken);
  1493. end;
  1494. end
  1495. { Simple register }
  1496. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1497. Begin
  1498. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1499. Message(asmr_e_invalid_operand_type);
  1500. opr.typ:=OPR_REGISTER;
  1501. opr.reg:=tempreg;
  1502. size:=reg_2_opsize[tempreg.enum];
  1503. end
  1504. else
  1505. Message(asmr_e_syn_operand);
  1506. end;
  1507. AS_END,
  1508. AS_SEPARATOR,
  1509. AS_COMMA: ;
  1510. else
  1511. Begin
  1512. Message(asmr_e_syn_operand);
  1513. Consume(actasmtoken);
  1514. end;
  1515. end; { end case }
  1516. end;
  1517. {*****************************************************************************
  1518. T386ATTInstruction
  1519. *****************************************************************************}
  1520. type
  1521. T386AttInstruction=class(T386Instruction)
  1522. procedure InitOperands;override;
  1523. procedure BuildOpcode;override;
  1524. end;
  1525. procedure T386AttInstruction.InitOperands;
  1526. var
  1527. i : longint;
  1528. begin
  1529. OpOrder:=op_att;
  1530. for i:=1to max_operands do
  1531. Operands[i]:=T386AttOperand.Create;
  1532. end;
  1533. Procedure T386AttInstruction.BuildOpCode;
  1534. var
  1535. operandnum : longint;
  1536. PrefixOp,OverrideOp: tasmop;
  1537. Begin
  1538. PrefixOp:=A_None;
  1539. OverrideOp:=A_None;
  1540. { prefix seg opcode / prefix opcode }
  1541. repeat
  1542. if is_prefix(actopcode) then
  1543. begin
  1544. PrefixOp:=ActOpcode;
  1545. opcode:=ActOpcode;
  1546. condition:=ActCondition;
  1547. opsize:=ActOpsize;
  1548. ConcatInstruction(curlist);
  1549. Consume(AS_OPCODE);
  1550. end
  1551. else
  1552. if is_override(actopcode) then
  1553. begin
  1554. OverrideOp:=ActOpcode;
  1555. opcode:=ActOpcode;
  1556. condition:=ActCondition;
  1557. opsize:=ActOpsize;
  1558. ConcatInstruction(curlist);
  1559. Consume(AS_OPCODE);
  1560. end
  1561. else
  1562. break;
  1563. { allow for newline as in gas styled syntax }
  1564. while actasmtoken=AS_SEPARATOR do
  1565. Consume(AS_SEPARATOR);
  1566. until (actasmtoken<>AS_OPCODE);
  1567. { opcode }
  1568. if (actasmtoken <> AS_OPCODE) then
  1569. Begin
  1570. Message(asmr_e_invalid_or_missing_opcode);
  1571. RecoverConsume(true);
  1572. exit;
  1573. end;
  1574. { Fill the instr object with the current state }
  1575. Opcode:=ActOpcode;
  1576. condition:=ActCondition;
  1577. opsize:=ActOpsize;
  1578. { Valid combination of prefix/override and instruction ? }
  1579. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1580. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1581. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1582. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1583. { We are reading operands, so opcode will be an AS_ID }
  1584. operandnum:=1;
  1585. Consume(AS_OPCODE);
  1586. { Zero operand opcode ? }
  1587. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1588. begin
  1589. operandnum:=0;
  1590. exit;
  1591. end;
  1592. { Read the operands }
  1593. repeat
  1594. case actasmtoken of
  1595. AS_COMMA: { Operand delimiter }
  1596. Begin
  1597. if operandnum > Max_Operands then
  1598. Message(asmr_e_too_many_operands)
  1599. else
  1600. Inc(operandnum);
  1601. Consume(AS_COMMA);
  1602. end;
  1603. AS_SEPARATOR,
  1604. AS_END : { End of asm operands for this opcode }
  1605. begin
  1606. break;
  1607. end;
  1608. else
  1609. Operands[operandnum].BuildOperand;
  1610. end; { end case }
  1611. until false;
  1612. Ops:=operandnum;
  1613. end;
  1614. Procedure BuildConstant(maxvalue: longint);
  1615. var
  1616. asmsym,
  1617. expr: string;
  1618. value : longint;
  1619. Begin
  1620. Repeat
  1621. Case actasmtoken of
  1622. AS_STRING:
  1623. Begin
  1624. expr:=actasmpattern;
  1625. if length(expr) > 1 then
  1626. Message(asmr_e_string_not_allowed_as_const);
  1627. Consume(AS_STRING);
  1628. Case actasmtoken of
  1629. AS_COMMA: Consume(AS_COMMA);
  1630. AS_END,
  1631. AS_SEPARATOR: ;
  1632. else
  1633. Message(asmr_e_invalid_string_expression);
  1634. end; { end case }
  1635. ConcatString(curlist,expr);
  1636. end;
  1637. AS_INTNUM,
  1638. AS_PLUS,
  1639. AS_MINUS,
  1640. AS_LPAREN,
  1641. AS_NOT,
  1642. AS_ID :
  1643. Begin
  1644. BuildConstSymbolExpression(false,false,false,value,asmsym);
  1645. if asmsym<>'' then
  1646. begin
  1647. if maxvalue<>longint($ffffffff) then
  1648. Message(asmr_w_32bit_const_for_address);
  1649. ConcatConstSymbol(curlist,asmsym,value)
  1650. end
  1651. else
  1652. ConcatConstant(curlist,value,maxvalue);
  1653. end;
  1654. AS_COMMA:
  1655. Consume(AS_COMMA);
  1656. AS_END,
  1657. AS_SEPARATOR:
  1658. break;
  1659. else
  1660. begin
  1661. Message(asmr_e_syn_constant);
  1662. RecoverConsume(false);
  1663. end
  1664. end; { end case }
  1665. Until false;
  1666. end;
  1667. Procedure BuildRealConstant(typ : tfloattype);
  1668. var
  1669. expr : string;
  1670. r : bestreal;
  1671. code : integer;
  1672. negativ : boolean;
  1673. errorflag: boolean;
  1674. Begin
  1675. errorflag:=FALSE;
  1676. Repeat
  1677. negativ:=false;
  1678. expr:='';
  1679. if actasmtoken=AS_PLUS then
  1680. Consume(AS_PLUS)
  1681. else
  1682. if actasmtoken=AS_MINUS then
  1683. begin
  1684. negativ:=true;
  1685. consume(AS_MINUS);
  1686. end;
  1687. Case actasmtoken of
  1688. AS_INTNUM:
  1689. Begin
  1690. expr:=actasmpattern;
  1691. Consume(AS_INTNUM);
  1692. if negativ then
  1693. expr:='-'+expr;
  1694. val(expr,r,code);
  1695. if code<>0 then
  1696. Begin
  1697. r:=0;
  1698. Message(asmr_e_invalid_float_expr);
  1699. End;
  1700. ConcatRealConstant(curlist,r,typ);
  1701. end;
  1702. AS_REALNUM:
  1703. Begin
  1704. expr:=actasmpattern;
  1705. Consume(AS_REALNUM);
  1706. { in ATT syntax you have 0d in front of the real }
  1707. { should this be forced ? yes i think so, as to }
  1708. { conform to gas as much as possible. }
  1709. if (expr[1]='0') and (upper(expr[2])='D') then
  1710. Delete(expr,1,2);
  1711. if negativ then
  1712. expr:='-'+expr;
  1713. val(expr,r,code);
  1714. if code<>0 then
  1715. Begin
  1716. r:=0;
  1717. Message(asmr_e_invalid_float_expr);
  1718. End;
  1719. ConcatRealConstant(curlist,r,typ);
  1720. end;
  1721. AS_COMMA:
  1722. begin
  1723. Consume(AS_COMMA);
  1724. end;
  1725. AS_END,
  1726. AS_SEPARATOR:
  1727. begin
  1728. break;
  1729. end;
  1730. else
  1731. Begin
  1732. Consume(actasmtoken);
  1733. if not errorflag then
  1734. Message(asmr_e_invalid_float_expr);
  1735. errorflag:=TRUE;
  1736. end;
  1737. end;
  1738. Until false;
  1739. end;
  1740. Procedure BuildStringConstant(asciiz: boolean);
  1741. var
  1742. expr: string;
  1743. errorflag : boolean;
  1744. Begin
  1745. errorflag:=FALSE;
  1746. Repeat
  1747. Case actasmtoken of
  1748. AS_STRING:
  1749. Begin
  1750. expr:=actasmpattern;
  1751. if asciiz then
  1752. expr:=expr+#0;
  1753. ConcatPasString(curlist,expr);
  1754. Consume(AS_STRING);
  1755. end;
  1756. AS_COMMA:
  1757. begin
  1758. Consume(AS_COMMA);
  1759. end;
  1760. AS_END,
  1761. AS_SEPARATOR:
  1762. begin
  1763. break;
  1764. end;
  1765. else
  1766. Begin
  1767. Consume(actasmtoken);
  1768. if not errorflag then
  1769. Message(asmr_e_invalid_string_expression);
  1770. errorflag:=TRUE;
  1771. end;
  1772. end;
  1773. Until false;
  1774. end;
  1775. Function Assemble: tnode;
  1776. Var
  1777. hl : tasmlabel;
  1778. commname : string;
  1779. lasTSec : TSection;
  1780. l1,l2 : longint;
  1781. instr : T386ATTInstruction;
  1782. Begin
  1783. Message1(asmr_d_start_reading,'AT&T');
  1784. firsttoken:=TRUE;
  1785. { sets up all opcode and register tables in uppercase }
  1786. if not _asmsorted then
  1787. Begin
  1788. SetupTables;
  1789. _asmsorted:=TRUE;
  1790. end;
  1791. curlist:=TAAsmoutput.Create;
  1792. lasTSec:=sec_code;
  1793. { setup label linked list }
  1794. LocalLabelList:=TLocalLabelList.Create;
  1795. { start tokenizer }
  1796. c:=current_scanner.asmgetchar;
  1797. gettoken;
  1798. { main loop }
  1799. repeat
  1800. case actasmtoken of
  1801. AS_LLABEL:
  1802. Begin
  1803. if CreateLocalLabel(actasmpattern,hl,true) then
  1804. ConcatLabel(curlist,hl);
  1805. Consume(AS_LLABEL);
  1806. end;
  1807. AS_LABEL:
  1808. Begin
  1809. if SearchLabel(upper(actasmpattern),hl,true) then
  1810. ConcatLabel(curlist,hl)
  1811. else
  1812. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1813. Consume(AS_LABEL);
  1814. end;
  1815. AS_DW:
  1816. Begin
  1817. Consume(AS_DW);
  1818. BuildConstant($ffff);
  1819. end;
  1820. AS_DATA:
  1821. Begin
  1822. curList.Concat(Tai_section.Create(sec_data));
  1823. lasTSec:=sec_data;
  1824. Consume(AS_DATA);
  1825. end;
  1826. AS_TEXT:
  1827. Begin
  1828. curList.Concat(Tai_section.Create(sec_code));
  1829. lasTSec:=sec_code;
  1830. Consume(AS_TEXT);
  1831. end;
  1832. AS_DB:
  1833. Begin
  1834. Consume(AS_DB);
  1835. BuildConstant($ff);
  1836. end;
  1837. AS_DD:
  1838. Begin
  1839. Consume(AS_DD);
  1840. BuildConstant(longint($ffffffff));
  1841. end;
  1842. AS_DQ:
  1843. Begin
  1844. Consume(AS_DQ);
  1845. BuildRealConstant(s64comp);
  1846. end;
  1847. AS_SINGLE:
  1848. Begin
  1849. Consume(AS_SINGLE);
  1850. BuildRealConstant(s32real);
  1851. end;
  1852. AS_DOUBLE:
  1853. Begin
  1854. Consume(AS_DOUBLE);
  1855. BuildRealConstant(s64real);
  1856. end;
  1857. AS_EXTENDED:
  1858. Begin
  1859. Consume(AS_EXTENDED);
  1860. BuildRealConstant(s80real);
  1861. end;
  1862. AS_GLOBAL:
  1863. Begin
  1864. Consume(AS_GLOBAL);
  1865. if actasmtoken=AS_ID then
  1866. ConcatPublic(curlist,actasmpattern);
  1867. Consume(AS_ID);
  1868. if actasmtoken<>AS_SEPARATOR then
  1869. Consume(AS_SEPARATOR);
  1870. end;
  1871. AS_ALIGN:
  1872. Begin
  1873. Consume(AS_ALIGN);
  1874. l1:=BuildConstExpression(false,false);
  1875. if (target_info.system in [system_i386_GO32V2]) then
  1876. begin
  1877. l2:=1;
  1878. if (l1>=0) and (l1<=16) then
  1879. while (l1>0) do
  1880. begin
  1881. l2:=2*l2;
  1882. dec(l1);
  1883. end;
  1884. l1:=l2;
  1885. end;
  1886. ConcatAlign(curlist,l1);
  1887. Message(asmr_n_align_is_target_specific);
  1888. if actasmtoken<>AS_SEPARATOR then
  1889. Consume(AS_SEPARATOR);
  1890. end;
  1891. AS_BALIGN:
  1892. Begin
  1893. Consume(AS_BALIGN);
  1894. ConcatAlign(curlist,BuildConstExpression(false,false));
  1895. if actasmtoken<>AS_SEPARATOR then
  1896. Consume(AS_SEPARATOR);
  1897. end;
  1898. AS_P2ALIGN:
  1899. Begin
  1900. Consume(AS_P2ALIGN);
  1901. l1:=BuildConstExpression(false,false);
  1902. l2:=1;
  1903. if (l1>=0) and (l1<=16) then
  1904. while (l1>0) do
  1905. begin
  1906. l2:=2*l2;
  1907. dec(l1);
  1908. end;
  1909. l1:=l2;
  1910. ConcatAlign(curlist,l1);
  1911. if actasmtoken<>AS_SEPARATOR then
  1912. Consume(AS_SEPARATOR);
  1913. end;
  1914. AS_ASCIIZ:
  1915. Begin
  1916. Consume(AS_ASCIIZ);
  1917. BuildStringConstant(TRUE);
  1918. end;
  1919. AS_ASCII:
  1920. Begin
  1921. Consume(AS_ASCII);
  1922. BuildStringConstant(FALSE);
  1923. end;
  1924. AS_LCOMM:
  1925. Begin
  1926. Consume(AS_LCOMM);
  1927. commname:=actasmpattern;
  1928. Consume(AS_ID);
  1929. Consume(AS_COMMA);
  1930. ConcatLocalBss(commname,BuildConstExpression(false,false));
  1931. if actasmtoken<>AS_SEPARATOR then
  1932. Consume(AS_SEPARATOR);
  1933. end;
  1934. AS_COMM:
  1935. Begin
  1936. Consume(AS_COMM);
  1937. commname:=actasmpattern;
  1938. Consume(AS_ID);
  1939. Consume(AS_COMMA);
  1940. ConcatGlobalBss(commname,BuildConstExpression(false,false));
  1941. if actasmtoken<>AS_SEPARATOR then
  1942. Consume(AS_SEPARATOR);
  1943. end;
  1944. AS_OPCODE:
  1945. Begin
  1946. instr:=T386ATTInstruction.Create;
  1947. instr.BuildOpcode;
  1948. instr.AddReferenceSizes;
  1949. instr.SetInstructionOpsize;
  1950. instr.CheckOperandSizes;
  1951. instr.ConcatInstruction(curlist);
  1952. instr.Free;
  1953. end;
  1954. AS_SEPARATOR:
  1955. Begin
  1956. Consume(AS_SEPARATOR);
  1957. end;
  1958. AS_END:
  1959. begin
  1960. break; { end assembly block }
  1961. end;
  1962. else
  1963. Begin
  1964. Message(asmr_e_syntax_error);
  1965. RecoverConsume(false);
  1966. end;
  1967. end;
  1968. until false;
  1969. { Check LocalLabelList }
  1970. LocalLabelList.CheckEmitted;
  1971. LocalLabelList.Free;
  1972. { are we back in the code section? }
  1973. if lasTSec<>sec_code then
  1974. begin
  1975. Message(asmr_w_assembler_code_not_returned_to_text);
  1976. curList.Concat(Tai_section.Create(sec_code));
  1977. end;
  1978. { Return the list in an asmnode }
  1979. assemble:=casmnode.create(curlist);
  1980. Message1(asmr_d_finish_reading,'AT&T');
  1981. end;
  1982. {*****************************************************************************
  1983. Initialize
  1984. *****************************************************************************}
  1985. const
  1986. asmmode_i386_att_info : tasmmodeinfo =
  1987. (
  1988. id : asmmode_i386_att;
  1989. idtxt : 'ATT'
  1990. );
  1991. initialization
  1992. RegisterAsmMode(asmmode_i386_att_info);
  1993. finalization
  1994. if assigned(iasmops) then
  1995. iasmops.Free;
  1996. if assigned(iasmregs) then
  1997. dispose(iasmregs);
  1998. end.
  1999. {
  2000. $Log$
  2001. Revision 1.36 2003-01-08 18:43:57 daniel
  2002. * Tregister changed into a record
  2003. Revision 1.35 2002/12/14 15:02:03 carl
  2004. * maxoperands -> max_operands (for portability in rautils.pas)
  2005. * fix some range-check errors with loadconst
  2006. + add ncgadd unit to m68k
  2007. * some bugfix of a_param_reg with LOC_CREFERENCE
  2008. Revision 1.34 2002/12/01 22:08:34 carl
  2009. * some small cleanup (remove some specific operators which are not supported)
  2010. Revision 1.33 2002/11/30 23:16:39 carl
  2011. - removed unused message
  2012. Revision 1.32 2002/11/15 01:58:58 peter
  2013. * merged changes from 1.0.7 up to 04-11
  2014. - -V option for generating bug report tracing
  2015. - more tracing for option parsing
  2016. - errors for cdecl and high()
  2017. - win32 import stabs
  2018. - win32 records<=8 are returned in eax:edx (turned off by default)
  2019. - heaptrc update
  2020. - more info for temp management in .s file with EXTDEBUG
  2021. Revision 1.31 2002/09/03 16:26:28 daniel
  2022. * Make Tprocdef.defs protected
  2023. Revision 1.30 2002/08/13 18:01:52 carl
  2024. * rename swatoperands to swapoperands
  2025. + m68k first compilable version (still needs a lot of testing):
  2026. assembler generator, system information , inline
  2027. assembler reader.
  2028. Revision 1.29 2002/08/12 15:08:42 carl
  2029. + stab register indexes for powerpc (moved from gdb to cpubase)
  2030. + tprocessor enumeration moved to cpuinfo
  2031. + linker in target_info is now a class
  2032. * many many updates for m68k (will soon start to compile)
  2033. - removed some ifdef or correct them for correct cpu
  2034. Revision 1.28 2002/08/11 14:32:31 peter
  2035. * renamed current_library to objectlibrary
  2036. Revision 1.27 2002/08/11 13:24:17 peter
  2037. * saving of asmsymbols in ppu supported
  2038. * asmsymbollist global is removed and moved into a new class
  2039. tasmlibrarydata that will hold the info of a .a file which
  2040. corresponds with a single module. Added librarydata to tmodule
  2041. to keep the library info stored for the module. In the future the
  2042. objectfiles will also be stored to the tasmlibrarydata class
  2043. * all getlabel/newasmsymbol and friends are moved to the new class
  2044. Revision 1.26 2002/07/26 21:15:44 florian
  2045. * rewrote the system handling
  2046. Revision 1.25 2002/07/01 18:46:34 peter
  2047. * internal linker
  2048. * reorganized aasm layer
  2049. Revision 1.24 2002/05/18 13:34:25 peter
  2050. * readded missing revisions
  2051. Revision 1.23 2002/05/16 19:46:52 carl
  2052. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2053. + try to fix temp allocation (still in ifdef)
  2054. + generic constructor calls
  2055. + start of tassembler / tmodulebase class cleanup
  2056. Revision 1.21 2002/04/15 19:12:09 carl
  2057. + target_info.size_of_pointer -> pointer_size
  2058. + some cleanup of unused types/variables
  2059. * move several constants from cpubase to their specific units
  2060. (where they are used)
  2061. + att_Reg2str -> gas_reg2str
  2062. + int_reg2str -> std_reg2str
  2063. Revision 1.20 2002/04/14 17:01:52 carl
  2064. + att_reg2str -> gas_reg2str
  2065. Revision 1.19 2002/04/04 19:06:13 peter
  2066. * removed unused units
  2067. * use tlocation.size in cg.a_*loc*() routines
  2068. Revision 1.18 2002/04/02 17:11:39 peter
  2069. * tlocation,treference update
  2070. * LOC_CONSTANT added for better constant handling
  2071. * secondadd splitted in multiple routines
  2072. * location_force_reg added for loading a location to a register
  2073. of a specified size
  2074. * secondassignment parses now first the right and then the left node
  2075. (this is compatible with Kylix). This saves a lot of push/pop especially
  2076. with string operations
  2077. * adapted some routines to use the new cg methods
  2078. Revision 1.17 2002/03/28 20:48:25 carl
  2079. - remove go32v1 support
  2080. Revision 1.16 2002/01/24 18:25:53 peter
  2081. * implicit result variable generation for assembler routines
  2082. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  2083. }