ag386nsm.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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. AsmWrite('[');
  196. first:=true;
  197. inc(offset,offsetfixup);
  198. offsetfixup:=0;
  199. if ref.segment<>R_NO then
  200. AsmWrite(std_reg2str[segment]+':');
  201. if assigned(symbol) then
  202. begin
  203. AsmWrite(symbol.name);
  204. first:=false;
  205. end;
  206. if (base<>R_NO) then
  207. begin
  208. if not(first) then
  209. AsmWrite('+')
  210. else
  211. first:=false;
  212. AsmWrite(int_nasmreg2str[base]);
  213. end;
  214. if (index<>R_NO) then
  215. begin
  216. if not(first) then
  217. AsmWrite('+')
  218. else
  219. first:=false;
  220. AsmWrite(int_nasmreg2str[index]);
  221. if scalefactor<>0 then
  222. AsmWrite('*'+tostr(scalefactor));
  223. end;
  224. if offset<0 then
  225. begin
  226. AsmWrite(tostr(offset));
  227. first:=false;
  228. end
  229. else if (offset>0) then
  230. begin
  231. AsmWrite('+'+tostr(offset));
  232. first:=false;
  233. end;
  234. if first then
  235. AsmWrite('0');
  236. AsmWrite(']');
  237. end;
  238. end;
  239. procedure T386NasmAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
  240. begin
  241. case o.typ of
  242. top_reg :
  243. AsmWrite(int_nasmreg2str[o.reg]);
  244. top_const :
  245. begin
  246. if (ops=1) and (opcode<>A_RET) then
  247. AsmWrite(sizestr(s,dest));
  248. AsmWrite(tostr(longint(o.val)));
  249. end;
  250. top_symbol :
  251. begin
  252. AsmWrite('dword ');
  253. if assigned(o.sym) then
  254. AsmWrite(o.sym.name);
  255. if o.symofs>0 then
  256. AsmWrite('+'+tostr(o.symofs))
  257. else
  258. if o.symofs<0 then
  259. AsmWrite(tostr(o.symofs))
  260. else
  261. if not(assigned(o.sym)) then
  262. AsmWrite('0');
  263. end;
  264. top_ref :
  265. begin
  266. if not ((opcode = A_LEA) or (opcode = A_LGS) or
  267. (opcode = A_LSS) or (opcode = A_LFS) or
  268. (opcode = A_LES) or (opcode = A_LDS) or
  269. (opcode = A_SHR) or (opcode = A_SHL) or
  270. (opcode = A_SAR) or (opcode = A_SAL) or
  271. (opcode = A_OUT) or (opcode = A_IN)) then
  272. AsmWrite(sizestr(s,dest));
  273. WriteReference(o.ref^);
  274. end;
  275. else
  276. internalerror(10001);
  277. end;
  278. end;
  279. procedure T386NasmAssembler.WriteOper_jmp(const o:toper; op : tasmop);
  280. begin
  281. case o.typ of
  282. top_reg :
  283. AsmWrite(int_nasmreg2str[o.reg]);
  284. top_ref :
  285. WriteReference(o.ref^);
  286. top_const :
  287. AsmWrite(tostr(longint(o.val)));
  288. top_symbol :
  289. begin
  290. if not(
  291. (op=A_JCXZ) or (op=A_JECXZ) or
  292. (op=A_LOOP) or (op=A_LOOPE) or
  293. (op=A_LOOPNE) or (op=A_LOOPNZ) or
  294. (op=A_LOOPZ)
  295. ) then
  296. AsmWrite('NEAR ');
  297. AsmWrite(o.sym.name);
  298. if o.symofs>0 then
  299. AsmWrite('+'+tostr(o.symofs))
  300. else
  301. if o.symofs<0 then
  302. AsmWrite(tostr(o.symofs));
  303. end;
  304. else
  305. internalerror(10001);
  306. end;
  307. end;
  308. var
  309. LasTSec : TSection;
  310. const
  311. ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
  312. (#9'DD'#9,#9'DW'#9,#9'DB'#9);
  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. begin
  329. if not assigned(p) then
  330. exit;
  331. InlineLevel:=0;
  332. { lineinfo is only needed for codesegment (PFV) }
  333. do_line:=(cs_asm_source in aktglobalswitches) or
  334. ((cs_lineinfo in aktmoduleswitches)
  335. and (p=codesegment));
  336. hp:=tai(p.first);
  337. while assigned(hp) do
  338. begin
  339. if not(hp.typ in SkipLineInfo) then
  340. begin
  341. hp1:=hp as tailineinfo;
  342. aktfilepos:=hp1.fileinfo;
  343. if do_line then
  344. begin
  345. { load infile }
  346. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  347. begin
  348. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  349. if assigned(infile) then
  350. begin
  351. { open only if needed !! }
  352. if (cs_asm_source in aktglobalswitches) then
  353. infile.open;
  354. end;
  355. { avoid unnecessary reopens of the same file !! }
  356. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  357. { be sure to change line !! }
  358. lastfileinfo.line:=-1;
  359. end;
  360. { write source }
  361. if (cs_asm_source in aktglobalswitches) and
  362. assigned(infile) then
  363. begin
  364. if (infile<>lastinfile) then
  365. begin
  366. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  367. if assigned(lastinfile) then
  368. lastinfile.close;
  369. end;
  370. if (hp1.fileinfo.line<>lastfileinfo.line) and
  371. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  372. begin
  373. if (hp1.fileinfo.line<>0) and
  374. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  375. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  376. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  377. { set it to a negative value !
  378. to make that is has been read already !! PM }
  379. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  380. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  381. end;
  382. end;
  383. lastfileinfo:=hp1.fileinfo;
  384. lastinfile:=infile;
  385. end;
  386. end;
  387. case hp.typ of
  388. ait_comment :
  389. Begin
  390. AsmWrite(target_asm.comment);
  391. AsmWritePChar(tai_comment(hp).str);
  392. AsmLn;
  393. End;
  394. ait_regalloc :
  395. begin
  396. if (cs_asm_regalloc in aktglobalswitches) then
  397. AsmWriteLn(target_asm.comment+'Register '+std_reg2str[tai_regalloc(hp).reg]+
  398. allocstr[tai_regalloc(hp).allocation]);
  399. end;
  400. ait_tempalloc :
  401. begin
  402. if (cs_asm_tempalloc in aktglobalswitches) then
  403. begin
  404. {$ifdef EXTDEBUG}
  405. if assigned(tai_tempalloc(hp).problem) then
  406. AsmWriteLn(target_asm.comment+tai_tempalloc(hp).problem^+' ('+tostr(tai_tempalloc(hp).temppos)+','+
  407. tostr(tai_tempalloc(hp).tempsize)+')')
  408. else
  409. {$endif EXTDEBUG}
  410. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  411. tostr(tai_tempalloc(hp).tempsize)+allocstr[tai_tempalloc(hp).allocation]);
  412. end;
  413. end;
  414. ait_section :
  415. begin
  416. if tai_section(hp).sec<>sec_none then
  417. begin
  418. AsmLn;
  419. AsmWriteLn('SECTION '+target_asm.secnames[tai_section(hp).sec]);
  420. end;
  421. LasTSec:=tai_section(hp).sec;
  422. end;
  423. ait_align :
  424. AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
  425. ait_datablock :
  426. begin
  427. if tai_datablock(hp).is_global then
  428. begin
  429. AsmWrite(#9'GLOBAL ');
  430. AsmWriteLn(tai_datablock(hp).sym.name);
  431. end;
  432. AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
  433. AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
  434. end;
  435. ait_const_32bit,
  436. ait_const_16bit,
  437. ait_const_8bit :
  438. begin
  439. AsmWrite(ait_const2str[hp.typ]+tostr(tai_const(hp).value));
  440. consttyp:=hp.typ;
  441. l:=0;
  442. repeat
  443. found:=(not (tai(hp.next)=nil)) and (tai(hp.next).typ=consttyp);
  444. if found then
  445. begin
  446. hp:=tai(hp.next);
  447. s:=','+tostr(tai_const(hp).value);
  448. AsmWrite(s);
  449. inc(l,length(s));
  450. end;
  451. until (not found) or (l>line_length);
  452. AsmLn;
  453. end;
  454. ait_const_symbol :
  455. begin
  456. AsmWrite(#9#9'DD'#9);
  457. AsmWrite(tai_const_symbol(hp).sym.name);
  458. if tai_const_symbol(hp).offset>0 then
  459. AsmWrite('+'+tostr(tai_const_symbol(hp).offset))
  460. else if tai_const_symbol(hp).offset<0 then
  461. AsmWrite(tostr(tai_const_symbol(hp).offset));
  462. AsmLn;
  463. end;
  464. ait_const_rva :
  465. begin
  466. AsmWrite(#9#9'RVA'#9);
  467. AsmWriteLn(tai_const_symbol(hp).sym.name);
  468. end;
  469. ait_real_32bit :
  470. AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
  471. ait_real_64bit :
  472. AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
  473. ait_real_80bit :
  474. AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
  475. ait_comp_64bit :
  476. AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
  477. ait_string :
  478. begin
  479. counter := 0;
  480. lines := tai_string(hp).len div line_length;
  481. { separate lines in different parts }
  482. if tai_string(hp).len > 0 then
  483. Begin
  484. for j := 0 to lines-1 do
  485. begin
  486. AsmWrite(#9#9'DB'#9);
  487. quoted:=false;
  488. for i:=counter to counter+line_length-1 do
  489. begin
  490. { it is an ascii character. }
  491. if (ord(tai_string(hp).str[i])>31) and
  492. (ord(tai_string(hp).str[i])<128) and
  493. (tai_string(hp).str[i]<>'"') then
  494. begin
  495. if not(quoted) then
  496. begin
  497. if i>counter then
  498. AsmWrite(',');
  499. AsmWrite('"');
  500. end;
  501. AsmWrite(tai_string(hp).str[i]);
  502. quoted:=true;
  503. end { if > 31 and < 128 and ord('"') }
  504. else
  505. begin
  506. if quoted then
  507. AsmWrite('"');
  508. if i>counter then
  509. AsmWrite(',');
  510. quoted:=false;
  511. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  512. end;
  513. end; { end for i:=0 to... }
  514. if quoted then AsmWrite('"');
  515. AsmWrite(target_info.newline);
  516. inc(counter,line_length);
  517. end; { end for j:=0 ... }
  518. { do last line of lines }
  519. if counter<tai_string(hp).len then
  520. AsmWrite(#9#9'DB'#9);
  521. quoted:=false;
  522. for i:=counter to tai_string(hp).len-1 do
  523. begin
  524. { it is an ascii character. }
  525. if (ord(tai_string(hp).str[i])>31) and
  526. (ord(tai_string(hp).str[i])<128) and
  527. (tai_string(hp).str[i]<>'"') then
  528. begin
  529. if not(quoted) then
  530. begin
  531. if i>counter then
  532. AsmWrite(',');
  533. AsmWrite('"');
  534. end;
  535. AsmWrite(tai_string(hp).str[i]);
  536. quoted:=true;
  537. end { if > 31 and < 128 and " }
  538. else
  539. begin
  540. if quoted then
  541. AsmWrite('"');
  542. if i>counter then
  543. AsmWrite(',');
  544. quoted:=false;
  545. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  546. end;
  547. end; { end for i:=0 to... }
  548. if quoted then
  549. AsmWrite('"');
  550. end;
  551. AsmLn;
  552. end;
  553. ait_label :
  554. begin
  555. if tai_label(hp).l.is_used then
  556. AsmWriteLn(tai_label(hp).l.name+':');
  557. end;
  558. ait_direct :
  559. begin
  560. AsmWritePChar(tai_direct(hp).str);
  561. AsmLn;
  562. end;
  563. ait_symbol :
  564. begin
  565. if tai_symbol(hp).is_global then
  566. begin
  567. AsmWrite(#9'GLOBAL ');
  568. AsmWriteLn(tai_symbol(hp).sym.name);
  569. end;
  570. AsmWrite(tai_symbol(hp).sym.name);
  571. if assigned(hp.next) and not(tai(hp.next).typ in
  572. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  573. ait_const_symbol,ait_const_rva,
  574. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
  575. AsmWriteLn(':')
  576. end;
  577. ait_symbol_end : ;
  578. ait_instruction :
  579. begin
  580. taicpu(hp).CheckNonCommutativeOpcodes;
  581. { We need intel order, no At&t }
  582. taicpu(hp).SetOperandOrder(op_intel);
  583. s:='';
  584. if ((taicpu(hp).opcode=A_FADDP) or
  585. (taicpu(hp).opcode=A_FMULP))
  586. and (taicpu(hp).ops=0) then
  587. begin
  588. taicpu(hp).ops:=2;
  589. taicpu(hp).oper[0].typ:=top_reg;
  590. taicpu(hp).oper[0].reg:=R_ST1;
  591. taicpu(hp).oper[1].typ:=top_reg;
  592. taicpu(hp).oper[1].reg:=R_ST;
  593. end;
  594. if taicpu(hp).opcode=A_FWAIT then
  595. AsmWriteln(#9#9'DB'#9'09bh')
  596. else
  597. begin
  598. { We need to explicitely set
  599. word prefix to get selectors
  600. to be pushed in 2 bytes PM }
  601. if (taicpu(hp).opsize=S_W) and
  602. ((taicpu(hp).opcode=A_PUSH) or
  603. (taicpu(hp).opcode=A_POP)) and
  604. (taicpu(hp).oper[0].typ=top_reg) and
  605. ((taicpu(hp).oper[0].reg>=firstsreg) and
  606. (taicpu(hp).oper[0].reg<=lastsreg)) then
  607. AsmWriteln(#9#9'DB'#9'066h');
  608. AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
  609. if taicpu(hp).ops<>0 then
  610. begin
  611. if is_calljmp(taicpu(hp).opcode) then
  612. begin
  613. AsmWrite(#9);
  614. WriteOper_jmp(taicpu(hp).oper[0],taicpu(hp).opcode);
  615. end
  616. else
  617. begin
  618. for i:=0 to taicpu(hp).ops-1 do
  619. begin
  620. if i=0 then
  621. AsmWrite(#9)
  622. else
  623. AsmWrite(',');
  624. WriteOper(taicpu(hp).oper[i],taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
  625. end;
  626. end;
  627. end;
  628. AsmLn;
  629. end;
  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.29 2002-12-24 18:10:34 peter
  819. * Long symbol names support
  820. Revision 1.28 2002/11/17 16:31:59 carl
  821. * memory optimization (3-4%) : cleanup of tai fields,
  822. cleanup of tdef and tsym fields.
  823. * make it work for m68k
  824. Revision 1.27 2002/11/15 01:58:56 peter
  825. * merged changes from 1.0.7 up to 04-11
  826. - -V option for generating bug report tracing
  827. - more tracing for option parsing
  828. - errors for cdecl and high()
  829. - win32 import stabs
  830. - win32 records<=8 are returned in eax:edx (turned off by default)
  831. - heaptrc update
  832. - more info for temp management in .s file with EXTDEBUG
  833. Revision 1.26 2002/08/18 20:06:28 peter
  834. * inlining is now also allowed in interface
  835. * renamed write/load to ppuwrite/ppuload
  836. * tnode storing in ppu
  837. * nld,ncon,nbas are already updated for storing in ppu
  838. Revision 1.25 2002/08/12 15:08:41 carl
  839. + stab register indexes for powerpc (moved from gdb to cpubase)
  840. + tprocessor enumeration moved to cpuinfo
  841. + linker in target_info is now a class
  842. * many many updates for m68k (will soon start to compile)
  843. - removed some ifdef or correct them for correct cpu
  844. Revision 1.24 2002/08/11 14:32:29 peter
  845. * renamed current_library to objectlibrary
  846. Revision 1.23 2002/08/11 13:24:16 peter
  847. * saving of asmsymbols in ppu supported
  848. * asmsymbollist global is removed and moved into a new class
  849. tasmlibrarydata that will hold the info of a .a file which
  850. corresponds with a single module. Added librarydata to tmodule
  851. to keep the library info stored for the module. In the future the
  852. objectfiles will also be stored to the tasmlibrarydata class
  853. * all getlabel/newasmsymbol and friends are moved to the new class
  854. Revision 1.22 2002/07/26 21:15:43 florian
  855. * rewrote the system handling
  856. Revision 1.21 2002/07/01 18:46:29 peter
  857. * internal linker
  858. * reorganized aasm layer
  859. Revision 1.20 2002/05/18 13:34:21 peter
  860. * readded missing revisions
  861. Revision 1.19 2002/05/16 19:46:50 carl
  862. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  863. + try to fix temp allocation (still in ifdef)
  864. + generic constructor calls
  865. + start of tassembler / tmodulebase class cleanup
  866. Revision 1.17 2002/05/12 16:53:16 peter
  867. * moved entry and exitcode to ncgutil and cgobj
  868. * foreach gets extra argument for passing local data to the
  869. iterator function
  870. * -CR checks also class typecasts at runtime by changing them
  871. into as
  872. * fixed compiler to cycle with the -CR option
  873. * fixed stabs with elf writer, finally the global variables can
  874. be watched
  875. * removed a lot of routines from cga unit and replaced them by
  876. calls to cgobj
  877. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  878. u32bit then the other is typecasted also to u32bit without giving
  879. a rangecheck warning/error.
  880. * fixed pascal calling method with reversing also the high tree in
  881. the parast, detected by tcalcst3 test
  882. Revision 1.16 2002/04/15 19:12:09 carl
  883. + target_info.size_of_pointer -> pointer_size
  884. + some cleanup of unused types/variables
  885. * move several constants from cpubase to their specific units
  886. (where they are used)
  887. + att_Reg2str -> gas_reg2str
  888. + int_reg2str -> std_reg2str
  889. Revision 1.15 2002/04/14 16:58:41 carl
  890. + att_reg2str -> gas_reg2str
  891. Revision 1.14 2002/04/04 18:27:37 carl
  892. + added wdosx support (patch from Pavel)
  893. Revision 1.13 2002/04/02 17:11:33 peter
  894. * tlocation,treference update
  895. * LOC_CONSTANT added for better constant handling
  896. * secondadd splitted in multiple routines
  897. * location_force_reg added for loading a location to a register
  898. of a specified size
  899. * secondassignment parses now first the right and then the left node
  900. (this is compatible with Kylix). This saves a lot of push/pop especially
  901. with string operations
  902. * adapted some routines to use the new cg methods
  903. }