ra386att.pas 62 KB

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