ag386nsm.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements an asmoutput class for the Nasm assembler with
  5. Intel syntax for the i386+
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ag386nsm;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. aasmbase,aasmtai,aasmcpu,assemble;
  25. type
  26. T386NasmAssembler = class(texternalassembler)
  27. private
  28. procedure WriteReference(var ref : treference);
  29. procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
  30. procedure WriteOper_jmp(const o:toper; op : tasmop);
  31. public
  32. procedure WriteTree(p:taasmoutput);override;
  33. procedure WriteAsmList;override;
  34. procedure WriteExternals;
  35. end;
  36. implementation
  37. uses
  38. {$ifdef delphi}
  39. sysutils,
  40. {$endif}
  41. cutils,globtype,globals,systems,cclasses,
  42. fmodule,finput,verbose,cpuinfo
  43. ;
  44. const
  45. line_length = 64;
  46. int_nasmreg2str : reg2strtable = ('',
  47. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  48. 'ax','cx','dx','bx','sp','bp','si','di',
  49. 'al','cl','dl','bl','ah','ch','bh','dh',
  50. 'cs','ds','es','ss','fs','gs',
  51. 'st0','st0','st1','st2','st3','st4','st5','st6','st7',
  52. 'dr0','dr1','dr2','dr3','dr6','dr7',
  53. 'cr0','cr2','cr3','cr4',
  54. 'tr3','tr4','tr5','tr6','tr7',
  55. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  56. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  57. );
  58. var
  59. lastfileinfo : tfileposinfo;
  60. infile,
  61. lastinfile : tinputfile;
  62. function fixline(s:string):string;
  63. {
  64. return s with all leading and ending spaces and tabs removed
  65. }
  66. var
  67. i,j,k : longint;
  68. begin
  69. i:=length(s);
  70. while (i>0) and (s[i] in [#9,' ']) do
  71. dec(i);
  72. j:=1;
  73. while (j<i) and (s[j] in [#9,' ']) do
  74. inc(j);
  75. for k:=j to i do
  76. if s[k] in [#0..#31,#127..#255] then
  77. s[k]:='.';
  78. fixline:=Copy(s,j,i-j+1);
  79. end;
  80. function single2str(d : single) : string;
  81. var
  82. hs : string;
  83. p : byte;
  84. begin
  85. str(d,hs);
  86. { nasm expects a lowercase e }
  87. p:=pos('E',hs);
  88. if p>0 then
  89. hs[p]:='e';
  90. p:=pos('+',hs);
  91. if p>0 then
  92. delete(hs,p,1);
  93. single2str:=lower(hs);
  94. end;
  95. function double2str(d : double) : string;
  96. var
  97. hs : string;
  98. p : byte;
  99. begin
  100. str(d,hs);
  101. { nasm expects a lowercase e }
  102. p:=pos('E',hs);
  103. if p>0 then
  104. hs[p]:='e';
  105. p:=pos('+',hs);
  106. if p>0 then
  107. delete(hs,p,1);
  108. double2str:=lower(hs);
  109. end;
  110. function extended2str(e : extended) : string;
  111. var
  112. hs : string;
  113. p : byte;
  114. begin
  115. str(e,hs);
  116. { nasm expects a lowercase e }
  117. p:=pos('E',hs);
  118. if p>0 then
  119. hs[p]:='e';
  120. p:=pos('+',hs);
  121. if p>0 then
  122. delete(hs,p,1);
  123. extended2str:=lower(hs);
  124. end;
  125. function comp2str(d : bestreal) : string;
  126. type
  127. pdouble = ^double;
  128. var
  129. c : comp;
  130. dd : pdouble;
  131. begin
  132. {$ifdef FPC}
  133. c:=comp(d);
  134. {$else}
  135. c:=d;
  136. {$endif}
  137. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  138. comp2str:=double2str(dd^);
  139. end;
  140. function sizestr(s:topsize;dest:boolean):string;
  141. begin
  142. case s of
  143. S_B : sizestr:='byte ';
  144. S_W : sizestr:='word ';
  145. S_L : sizestr:='dword ';
  146. S_IS : sizestr:='word ';
  147. S_IL : sizestr:='dword ';
  148. S_IQ : sizestr:='qword ';
  149. S_FS : sizestr:='dword ';
  150. S_FL : sizestr:='qword ';
  151. S_FX : sizestr:='tword ';
  152. S_BW : if dest then
  153. sizestr:='word '
  154. else
  155. sizestr:='byte ';
  156. S_BL : if dest then
  157. sizestr:='dword '
  158. else
  159. sizestr:='byte ';
  160. S_WL : if dest then
  161. sizestr:='dword '
  162. else
  163. sizestr:='word ';
  164. else { S_NO }
  165. sizestr:='';
  166. end;
  167. end;
  168. Function PadTabs(const p:string;addch:char):string;
  169. var
  170. s : string;
  171. i : longint;
  172. begin
  173. i:=length(p);
  174. if addch<>#0 then
  175. begin
  176. inc(i);
  177. s:=p+addch;
  178. end
  179. else
  180. s:=p;
  181. if i<8 then
  182. PadTabs:=s+#9#9
  183. else
  184. PadTabs:=s+#9;
  185. end;
  186. {****************************************************************************
  187. T386NasmAssembler
  188. ****************************************************************************}
  189. procedure T386NasmAssembler.WriteReference(var ref : treference);
  190. var
  191. first : boolean;
  192. begin
  193. with ref do
  194. begin
  195. if segment.enum>lastreg then
  196. internalerror(200301081);
  197. if base.enum>lastreg then
  198. internalerror(200301081);
  199. if index.enum>lastreg then
  200. internalerror(200301081);
  201. AsmWrite('[');
  202. first:=true;
  203. inc(offset,offsetfixup);
  204. offsetfixup:=0;
  205. if segment.enum<>R_NO then
  206. AsmWrite(std_reg2str[segment.enum]+':');
  207. if assigned(symbol) then
  208. begin
  209. AsmWrite(symbol.name);
  210. first:=false;
  211. end;
  212. if (base.enum<>R_NO) then
  213. begin
  214. if not(first) then
  215. AsmWrite('+')
  216. else
  217. first:=false;
  218. AsmWrite(int_nasmreg2str[base.enum]);
  219. end;
  220. if (index.enum<>R_NO) then
  221. begin
  222. if not(first) then
  223. AsmWrite('+')
  224. else
  225. first:=false;
  226. AsmWrite(int_nasmreg2str[index.enum]);
  227. if scalefactor<>0 then
  228. AsmWrite('*'+tostr(scalefactor));
  229. end;
  230. if offset<0 then
  231. begin
  232. AsmWrite(tostr(offset));
  233. first:=false;
  234. end
  235. else if (offset>0) then
  236. begin
  237. AsmWrite('+'+tostr(offset));
  238. first:=false;
  239. end;
  240. if first then
  241. AsmWrite('0');
  242. AsmWrite(']');
  243. end;
  244. end;
  245. procedure T386NasmAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
  246. begin
  247. case o.typ of
  248. top_reg :
  249. begin
  250. if o.reg.enum>lastreg then
  251. internalerror(200301081);
  252. AsmWrite(int_nasmreg2str[o.reg.enum]);
  253. end;
  254. top_const :
  255. begin
  256. if (ops=1) and (opcode<>A_RET) then
  257. AsmWrite(sizestr(s,dest));
  258. AsmWrite(tostr(longint(o.val)));
  259. end;
  260. top_symbol :
  261. begin
  262. AsmWrite('dword ');
  263. if assigned(o.sym) then
  264. AsmWrite(o.sym.name);
  265. if o.symofs>0 then
  266. AsmWrite('+'+tostr(o.symofs))
  267. else
  268. if o.symofs<0 then
  269. AsmWrite(tostr(o.symofs))
  270. else
  271. if not(assigned(o.sym)) then
  272. AsmWrite('0');
  273. end;
  274. top_ref :
  275. begin
  276. if not ((opcode = A_LEA) or (opcode = A_LGS) or
  277. (opcode = A_LSS) or (opcode = A_LFS) or
  278. (opcode = A_LES) or (opcode = A_LDS) or
  279. (opcode = A_SHR) or (opcode = A_SHL) or
  280. (opcode = A_SAR) or (opcode = A_SAL) or
  281. (opcode = A_OUT) or (opcode = A_IN)) then
  282. AsmWrite(sizestr(s,dest));
  283. WriteReference(o.ref^);
  284. end;
  285. else
  286. internalerror(10001);
  287. end;
  288. end;
  289. procedure T386NasmAssembler.WriteOper_jmp(const o:toper; op : tasmop);
  290. begin
  291. case o.typ of
  292. top_reg :
  293. begin
  294. if o.reg.enum>lastreg then
  295. internalerror(200301081);
  296. AsmWrite(int_nasmreg2str[o.reg.enum]);
  297. end;
  298. top_ref :
  299. WriteReference(o.ref^);
  300. top_const :
  301. AsmWrite(tostr(longint(o.val)));
  302. top_symbol :
  303. begin
  304. if not(
  305. (op=A_JCXZ) or (op=A_JECXZ) or
  306. (op=A_LOOP) or (op=A_LOOPE) or
  307. (op=A_LOOPNE) or (op=A_LOOPNZ) or
  308. (op=A_LOOPZ)
  309. ) then
  310. AsmWrite('NEAR ');
  311. AsmWrite(o.sym.name);
  312. if o.symofs>0 then
  313. AsmWrite('+'+tostr(o.symofs))
  314. else
  315. if o.symofs<0 then
  316. AsmWrite(tostr(o.symofs));
  317. end;
  318. else
  319. internalerror(10001);
  320. end;
  321. end;
  322. var
  323. LasTSec : TSection;
  324. const
  325. ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
  326. (#9'DD'#9,#9'DW'#9,#9'DB'#9);
  327. procedure T386NasmAssembler.WriteTree(p:taasmoutput);
  328. const
  329. allocstr : array[boolean] of string[10]=(' released',' allocated');
  330. var
  331. s : string;
  332. hp : tai;
  333. hp1 : tailineinfo;
  334. counter,
  335. lines,
  336. i,j,l : longint;
  337. InlineLevel : longint;
  338. consttyp : taitype;
  339. found,
  340. do_line,
  341. quoted : boolean;
  342. begin
  343. if not assigned(p) then
  344. exit;
  345. InlineLevel:=0;
  346. { lineinfo is only needed for codesegment (PFV) }
  347. do_line:=(cs_asm_source in aktglobalswitches) or
  348. ((cs_lineinfo in aktmoduleswitches)
  349. and (p=codesegment));
  350. hp:=tai(p.first);
  351. while assigned(hp) do
  352. begin
  353. if not(hp.typ in SkipLineInfo) then
  354. begin
  355. hp1:=hp as tailineinfo;
  356. aktfilepos:=hp1.fileinfo;
  357. if do_line then
  358. begin
  359. { load infile }
  360. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  361. begin
  362. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  363. if assigned(infile) then
  364. begin
  365. { open only if needed !! }
  366. if (cs_asm_source in aktglobalswitches) then
  367. infile.open;
  368. end;
  369. { avoid unnecessary reopens of the same file !! }
  370. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  371. { be sure to change line !! }
  372. lastfileinfo.line:=-1;
  373. end;
  374. { write source }
  375. if (cs_asm_source in aktglobalswitches) and
  376. assigned(infile) then
  377. begin
  378. if (infile<>lastinfile) then
  379. begin
  380. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  381. if assigned(lastinfile) then
  382. lastinfile.close;
  383. end;
  384. if (hp1.fileinfo.line<>lastfileinfo.line) and
  385. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  386. begin
  387. if (hp1.fileinfo.line<>0) and
  388. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  389. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  390. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  391. { set it to a negative value !
  392. to make that is has been read already !! PM }
  393. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  394. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  395. end;
  396. end;
  397. lastfileinfo:=hp1.fileinfo;
  398. lastinfile:=infile;
  399. end;
  400. end;
  401. case hp.typ of
  402. ait_comment :
  403. Begin
  404. AsmWrite(target_asm.comment);
  405. AsmWritePChar(tai_comment(hp).str);
  406. AsmLn;
  407. End;
  408. ait_regalloc :
  409. begin
  410. if (cs_asm_regalloc in aktglobalswitches) then
  411. AsmWriteLn(target_asm.comment+'Register '+std_reg2str[tai_regalloc(hp).reg.enum]+
  412. allocstr[tai_regalloc(hp).allocation]);
  413. end;
  414. ait_tempalloc :
  415. begin
  416. if (cs_asm_tempalloc in aktglobalswitches) then
  417. begin
  418. {$ifdef EXTDEBUG}
  419. if assigned(tai_tempalloc(hp).problem) then
  420. AsmWriteLn(target_asm.comment+tai_tempalloc(hp).problem^+' ('+tostr(tai_tempalloc(hp).temppos)+','+
  421. tostr(tai_tempalloc(hp).tempsize)+')')
  422. else
  423. {$endif EXTDEBUG}
  424. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  425. tostr(tai_tempalloc(hp).tempsize)+allocstr[tai_tempalloc(hp).allocation]);
  426. end;
  427. end;
  428. ait_section :
  429. begin
  430. if tai_section(hp).sec<>sec_none then
  431. begin
  432. AsmLn;
  433. AsmWriteLn('SECTION '+target_asm.secnames[tai_section(hp).sec]);
  434. end;
  435. LasTSec:=tai_section(hp).sec;
  436. end;
  437. ait_align :
  438. AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
  439. ait_datablock :
  440. begin
  441. if tai_datablock(hp).is_global then
  442. begin
  443. AsmWrite(#9'GLOBAL ');
  444. AsmWriteLn(tai_datablock(hp).sym.name);
  445. end;
  446. AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
  447. AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
  448. end;
  449. ait_const_32bit,
  450. ait_const_16bit,
  451. ait_const_8bit :
  452. begin
  453. AsmWrite(ait_const2str[hp.typ]+tostr(tai_const(hp).value));
  454. consttyp:=hp.typ;
  455. l:=0;
  456. repeat
  457. found:=(not (tai(hp.next)=nil)) and (tai(hp.next).typ=consttyp);
  458. if found then
  459. begin
  460. hp:=tai(hp.next);
  461. s:=','+tostr(tai_const(hp).value);
  462. AsmWrite(s);
  463. inc(l,length(s));
  464. end;
  465. until (not found) or (l>line_length);
  466. AsmLn;
  467. end;
  468. ait_const_symbol :
  469. begin
  470. AsmWrite(#9#9'DD'#9);
  471. AsmWrite(tai_const_symbol(hp).sym.name);
  472. if tai_const_symbol(hp).offset>0 then
  473. AsmWrite('+'+tostr(tai_const_symbol(hp).offset))
  474. else if tai_const_symbol(hp).offset<0 then
  475. AsmWrite(tostr(tai_const_symbol(hp).offset));
  476. AsmLn;
  477. end;
  478. ait_const_rva :
  479. begin
  480. AsmWrite(#9#9'RVA'#9);
  481. AsmWriteLn(tai_const_symbol(hp).sym.name);
  482. end;
  483. ait_real_32bit :
  484. AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
  485. ait_real_64bit :
  486. AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
  487. ait_real_80bit :
  488. AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
  489. ait_comp_64bit :
  490. AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
  491. ait_string :
  492. begin
  493. counter := 0;
  494. lines := tai_string(hp).len div line_length;
  495. { separate lines in different parts }
  496. if tai_string(hp).len > 0 then
  497. Begin
  498. for j := 0 to lines-1 do
  499. begin
  500. AsmWrite(#9#9'DB'#9);
  501. quoted:=false;
  502. for i:=counter to counter+line_length-1 do
  503. begin
  504. { it is an ascii character. }
  505. if (ord(tai_string(hp).str[i])>31) and
  506. (ord(tai_string(hp).str[i])<128) and
  507. (tai_string(hp).str[i]<>'"') then
  508. begin
  509. if not(quoted) then
  510. begin
  511. if i>counter then
  512. AsmWrite(',');
  513. AsmWrite('"');
  514. end;
  515. AsmWrite(tai_string(hp).str[i]);
  516. quoted:=true;
  517. end { if > 31 and < 128 and ord('"') }
  518. else
  519. begin
  520. if quoted then
  521. AsmWrite('"');
  522. if i>counter then
  523. AsmWrite(',');
  524. quoted:=false;
  525. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  526. end;
  527. end; { end for i:=0 to... }
  528. if quoted then AsmWrite('"');
  529. AsmWrite(target_info.newline);
  530. inc(counter,line_length);
  531. end; { end for j:=0 ... }
  532. { do last line of lines }
  533. if counter<tai_string(hp).len then
  534. AsmWrite(#9#9'DB'#9);
  535. quoted:=false;
  536. for i:=counter to tai_string(hp).len-1 do
  537. begin
  538. { it is an ascii character. }
  539. if (ord(tai_string(hp).str[i])>31) and
  540. (ord(tai_string(hp).str[i])<128) and
  541. (tai_string(hp).str[i]<>'"') then
  542. begin
  543. if not(quoted) then
  544. begin
  545. if i>counter then
  546. AsmWrite(',');
  547. AsmWrite('"');
  548. end;
  549. AsmWrite(tai_string(hp).str[i]);
  550. quoted:=true;
  551. end { if > 31 and < 128 and " }
  552. else
  553. begin
  554. if quoted then
  555. AsmWrite('"');
  556. if i>counter then
  557. AsmWrite(',');
  558. quoted:=false;
  559. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  560. end;
  561. end; { end for i:=0 to... }
  562. if quoted then
  563. AsmWrite('"');
  564. end;
  565. AsmLn;
  566. end;
  567. ait_label :
  568. begin
  569. if tai_label(hp).l.is_used then
  570. AsmWriteLn(tai_label(hp).l.name+':');
  571. end;
  572. ait_direct :
  573. begin
  574. AsmWritePChar(tai_direct(hp).str);
  575. AsmLn;
  576. end;
  577. ait_symbol :
  578. begin
  579. if tai_symbol(hp).is_global then
  580. begin
  581. AsmWrite(#9'GLOBAL ');
  582. AsmWriteLn(tai_symbol(hp).sym.name);
  583. end;
  584. AsmWrite(tai_symbol(hp).sym.name);
  585. if assigned(hp.next) and not(tai(hp.next).typ in
  586. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  587. ait_const_symbol,ait_const_rva,
  588. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
  589. AsmWriteLn(':')
  590. end;
  591. ait_symbol_end : ;
  592. ait_instruction :
  593. begin
  594. taicpu(hp).CheckNonCommutativeOpcodes;
  595. { We need intel order, no At&t }
  596. taicpu(hp).SetOperandOrder(op_intel);
  597. s:='';
  598. if ((taicpu(hp).opcode=A_FADDP) or
  599. (taicpu(hp).opcode=A_FMULP))
  600. and (taicpu(hp).ops=0) then
  601. begin
  602. taicpu(hp).ops:=2;
  603. taicpu(hp).oper[0].typ:=top_reg;
  604. taicpu(hp).oper[0].reg.enum:=R_ST1;
  605. taicpu(hp).oper[1].typ:=top_reg;
  606. taicpu(hp).oper[1].reg.enum:=R_ST;
  607. end;
  608. if taicpu(hp).opcode=A_FWAIT then
  609. AsmWriteln(#9#9'DB'#9'09bh')
  610. else
  611. begin
  612. { We need to explicitely set
  613. word prefix to get selectors
  614. to be pushed in 2 bytes PM }
  615. if (taicpu(hp).opsize=S_W) and
  616. ((taicpu(hp).opcode=A_PUSH) or
  617. (taicpu(hp).opcode=A_POP)) and
  618. (taicpu(hp).oper[0].typ=top_reg) and
  619. ((taicpu(hp).oper[0].reg.enum in [firstsreg..lastsreg])) then
  620. AsmWriteln(#9#9'DB'#9'066h');
  621. AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
  622. if taicpu(hp).ops<>0 then
  623. begin
  624. if is_calljmp(taicpu(hp).opcode) then
  625. begin
  626. AsmWrite(#9);
  627. WriteOper_jmp(taicpu(hp).oper[0],taicpu(hp).opcode);
  628. end
  629. else
  630. begin
  631. for i:=0 to taicpu(hp).ops-1 do
  632. begin
  633. if i=0 then
  634. AsmWrite(#9)
  635. else
  636. AsmWrite(',');
  637. WriteOper(taicpu(hp).oper[i],taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
  638. end;
  639. end;
  640. end;
  641. AsmLn;
  642. end;
  643. end;
  644. {$ifdef GDB}
  645. ait_stabn,
  646. ait_stabs,
  647. ait_force_line,
  648. ait_stab_function_name : ;
  649. {$endif GDB}
  650. ait_cut :
  651. begin
  652. { only reset buffer if nothing has changed }
  653. if AsmSize=AsmStartSize then
  654. AsmClear
  655. else
  656. begin
  657. AsmClose;
  658. DoAssemble;
  659. AsmCreate(tai_cut(hp).place);
  660. end;
  661. { avoid empty files }
  662. while assigned(hp.next) and (tai(hp.next).typ in [ait_cut,ait_section,ait_comment]) do
  663. begin
  664. if tai(hp.next).typ=ait_section then
  665. lasTSec:=tai_section(hp.next).sec;
  666. hp:=tai(hp.next);
  667. end;
  668. if lasTSec<>sec_none then
  669. AsmWriteLn('SECTION '+target_asm.secnames[lasTSec]);
  670. AsmStartSize:=AsmSize;
  671. end;
  672. ait_marker :
  673. if tai_marker(hp).kind=InlineStart then
  674. inc(InlineLevel)
  675. else if tai_marker(hp).kind=InlineEnd then
  676. dec(InlineLevel);
  677. else
  678. internalerror(10000);
  679. end;
  680. hp:=tai(hp.next);
  681. end;
  682. end;
  683. var
  684. currentasmlist : TExternalAssembler;
  685. procedure writeexternal(p:tnamedindexitem;arg:pointer);
  686. begin
  687. if tasmsymbol(p).defbind=AB_EXTERNAL then
  688. currentasmlist.AsmWriteln('EXTERN'#9+p.name);
  689. end;
  690. procedure T386NasmAssembler.WriteExternals;
  691. begin
  692. currentasmlist:=self;
  693. objectlibrary.symbolsearch.foreach_static({$ifdef fpcprocvar}@{$endif}writeexternal,nil);
  694. end;
  695. procedure T386NasmAssembler.WriteAsmList;
  696. begin
  697. {$ifdef EXTDEBUG}
  698. if assigned(current_module.mainsource) then
  699. comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource^);
  700. {$endif}
  701. LasTSec:=sec_none;
  702. AsmWriteLn('BITS 32');
  703. AsmLn;
  704. lastfileinfo.line:=-1;
  705. lastfileinfo.fileindex:=0;
  706. lastinfile:=nil;
  707. WriteExternals;
  708. { Nasm doesn't support stabs
  709. WriteTree(debuglist);}
  710. WriteTree(codesegment);
  711. WriteTree(datasegment);
  712. WriteTree(consts);
  713. WriteTree(rttilist);
  714. WriteTree(resourcestringlist);
  715. WriteTree(bsssegment);
  716. Writetree(importssection);
  717. { exports are written by DLLTOOL
  718. if we use it so don't insert it twice (PM) }
  719. if not UseDeffileForExport and assigned(exportssection) then
  720. Writetree(exportssection);
  721. Writetree(resourcesection);
  722. AsmLn;
  723. {$ifdef EXTDEBUG}
  724. if assigned(current_module.mainsource) then
  725. comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource^);
  726. {$endif EXTDEBUG}
  727. end;
  728. {*****************************************************************************
  729. Initialize
  730. *****************************************************************************}
  731. const
  732. as_i386_nasmcoff_info : tasminfo =
  733. (
  734. id : as_i386_nasmcoff;
  735. idtxt : 'NASMCOFF';
  736. asmbin : 'nasm';
  737. asmcmd : '-f coff -o $OBJ $ASM';
  738. supported_target : system_i386_go32v2;
  739. outputbinary: false;
  740. allowdirect : true;
  741. needar : true;
  742. labelprefix_only_inside_procedure: false;
  743. labelprefix : '..@';
  744. comment : '; ';
  745. secnames : ('',
  746. '.text','.data','.bss',
  747. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  748. '.stab','.stabstr','')
  749. );
  750. as_i386_nasmwin32_info : tasminfo =
  751. (
  752. id : as_i386_nasmwin32;
  753. idtxt : 'NASMWIN32';
  754. asmbin : 'nasm';
  755. asmcmd : '-f win32 -o $OBJ $ASM';
  756. supported_target : system_i386_win32;
  757. outputbinary: false;
  758. allowdirect : true;
  759. needar : true;
  760. labelprefix_only_inside_procedure: false;
  761. labelprefix : '..@';
  762. comment : '; ';
  763. secnames : ('',
  764. '.text','.data','.bss',
  765. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  766. '.stab','.stabstr','')
  767. );
  768. as_i386_nasmobj_info : tasminfo =
  769. (
  770. id : as_i386_nasmobj;
  771. idtxt : 'NASMOBJ';
  772. asmbin : 'nasm';
  773. asmcmd : '-f obj -o $OBJ $ASM';
  774. supported_target : system_any; { what should I write here ?? }
  775. outputbinary: false;
  776. allowdirect : true;
  777. needar : true;
  778. labelprefix_only_inside_procedure: false;
  779. labelprefix : '..@';
  780. comment : '; ';
  781. secnames : ('',
  782. '.text','.data','.bss',
  783. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  784. '.stab','.stabstr','')
  785. );
  786. as_i386_nasmwdosx_info : tasminfo =
  787. (
  788. id : as_i386_nasmwdosx;
  789. idtxt : 'NASMWDOSX';
  790. asmbin : 'nasm';
  791. asmcmd : '-f win32 -o $OBJ $ASM';
  792. supported_target : system_i386_wdosx;
  793. outputbinary: false;
  794. allowdirect : true;
  795. needar : true;
  796. labelprefix_only_inside_procedure: false;
  797. labelprefix : '..@';
  798. comment : '; ';
  799. secnames : ('',
  800. '.text','.data','.bss',
  801. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  802. '.stab','.stabstr','')
  803. );
  804. as_i386_nasmelf_info : tasminfo =
  805. (
  806. id : as_i386_nasmelf;
  807. idtxt : 'NASMELF';
  808. asmbin : 'nasm';
  809. asmcmd : '-f elf -o $OBJ $ASM';
  810. supported_target : system_i386_linux;
  811. outputbinary: false;
  812. allowdirect : true;
  813. needar : true;
  814. labelprefix_only_inside_procedure: false;
  815. labelprefix : '..@';
  816. comment : '; ';
  817. secnames : ('',
  818. '.text','.data','.bss',
  819. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  820. '.stab','.stabstr','')
  821. );
  822. initialization
  823. RegisterAssembler(as_i386_nasmcoff_info,T386NasmAssembler);
  824. RegisterAssembler(as_i386_nasmwin32_info,T386NasmAssembler);
  825. RegisterAssembler(as_i386_nasmwdosx_info,T386NasmAssembler);
  826. RegisterAssembler(as_i386_nasmobj_info,T386NasmAssembler);
  827. RegisterAssembler(as_i386_nasmelf_info,T386NasmAssembler);
  828. end.
  829. {
  830. $Log$
  831. Revision 1.30 2003-01-08 18:43:57 daniel
  832. * Tregister changed into a record
  833. Revision 1.29 2002/12/24 18:10:34 peter
  834. * Long symbol names support
  835. Revision 1.28 2002/11/17 16:31:59 carl
  836. * memory optimization (3-4%) : cleanup of tai fields,
  837. cleanup of tdef and tsym fields.
  838. * make it work for m68k
  839. Revision 1.27 2002/11/15 01:58:56 peter
  840. * merged changes from 1.0.7 up to 04-11
  841. - -V option for generating bug report tracing
  842. - more tracing for option parsing
  843. - errors for cdecl and high()
  844. - win32 import stabs
  845. - win32 records<=8 are returned in eax:edx (turned off by default)
  846. - heaptrc update
  847. - more info for temp management in .s file with EXTDEBUG
  848. Revision 1.26 2002/08/18 20:06:28 peter
  849. * inlining is now also allowed in interface
  850. * renamed write/load to ppuwrite/ppuload
  851. * tnode storing in ppu
  852. * nld,ncon,nbas are already updated for storing in ppu
  853. Revision 1.25 2002/08/12 15:08:41 carl
  854. + stab register indexes for powerpc (moved from gdb to cpubase)
  855. + tprocessor enumeration moved to cpuinfo
  856. + linker in target_info is now a class
  857. * many many updates for m68k (will soon start to compile)
  858. - removed some ifdef or correct them for correct cpu
  859. Revision 1.24 2002/08/11 14:32:29 peter
  860. * renamed current_library to objectlibrary
  861. Revision 1.23 2002/08/11 13:24:16 peter
  862. * saving of asmsymbols in ppu supported
  863. * asmsymbollist global is removed and moved into a new class
  864. tasmlibrarydata that will hold the info of a .a file which
  865. corresponds with a single module. Added librarydata to tmodule
  866. to keep the library info stored for the module. In the future the
  867. objectfiles will also be stored to the tasmlibrarydata class
  868. * all getlabel/newasmsymbol and friends are moved to the new class
  869. Revision 1.22 2002/07/26 21:15:43 florian
  870. * rewrote the system handling
  871. Revision 1.21 2002/07/01 18:46:29 peter
  872. * internal linker
  873. * reorganized aasm layer
  874. Revision 1.20 2002/05/18 13:34:21 peter
  875. * readded missing revisions
  876. Revision 1.19 2002/05/16 19:46:50 carl
  877. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  878. + try to fix temp allocation (still in ifdef)
  879. + generic constructor calls
  880. + start of tassembler / tmodulebase class cleanup
  881. Revision 1.17 2002/05/12 16:53:16 peter
  882. * moved entry and exitcode to ncgutil and cgobj
  883. * foreach gets extra argument for passing local data to the
  884. iterator function
  885. * -CR checks also class typecasts at runtime by changing them
  886. into as
  887. * fixed compiler to cycle with the -CR option
  888. * fixed stabs with elf writer, finally the global variables can
  889. be watched
  890. * removed a lot of routines from cga unit and replaced them by
  891. calls to cgobj
  892. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  893. u32bit then the other is typecasted also to u32bit without giving
  894. a rangecheck warning/error.
  895. * fixed pascal calling method with reversing also the high tree in
  896. the parast, detected by tcalcst3 test
  897. Revision 1.16 2002/04/15 19:12:09 carl
  898. + target_info.size_of_pointer -> pointer_size
  899. + some cleanup of unused types/variables
  900. * move several constants from cpubase to their specific units
  901. (where they are used)
  902. + att_Reg2str -> gas_reg2str
  903. + int_reg2str -> std_reg2str
  904. Revision 1.15 2002/04/14 16:58:41 carl
  905. + att_reg2str -> gas_reg2str
  906. Revision 1.14 2002/04/04 18:27:37 carl
  907. + added wdosx support (patch from Pavel)
  908. Revision 1.13 2002/04/02 17:11:33 peter
  909. * tlocation,treference update
  910. * LOC_CONSTANT added for better constant handling
  911. * secondadd splitted in multiple routines
  912. * location_force_reg added for loading a location to a register
  913. of a specified size
  914. * secondassignment parses now first the right and then the left node
  915. (this is compatible with Kylix). This saves a lot of push/pop especially
  916. with string operations
  917. * adapted some routines to use the new cg methods
  918. }