ag386nsm.pas 32 KB

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