ag386nsm.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  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. nolinetai =[ait_label,
  317. ait_regalloc,ait_tempalloc,
  318. {$ifdef GDB}
  319. ait_stabn,ait_stabs,ait_stab_function_name,
  320. {$endif GDB}
  321. ait_cut,ait_marker,ait_align,ait_section];
  322. var
  323. s : string;
  324. {prefix,
  325. suffix : string; no need here }
  326. hp : tai;
  327. counter,
  328. lines,
  329. i,j,l : longint;
  330. InlineLevel : longint;
  331. consttyp : taitype;
  332. found,
  333. do_line,
  334. quoted : boolean;
  335. sep : char;
  336. begin
  337. if not assigned(p) then
  338. exit;
  339. InlineLevel:=0;
  340. { lineinfo is only needed for codesegment (PFV) }
  341. do_line:=(cs_asm_source in aktglobalswitches) or
  342. ((cs_lineinfo in aktmoduleswitches)
  343. and (p=codesegment));
  344. hp:=tai(p.first);
  345. while assigned(hp) do
  346. begin
  347. aktfilepos:=hp.fileinfo;
  348. if not(hp.typ in nolinetai) then
  349. begin
  350. if do_line then
  351. begin
  352. { load infile }
  353. if lastfileinfo.fileindex<>hp.fileinfo.fileindex then
  354. begin
  355. infile:=current_module.sourcefiles.get_file(hp.fileinfo.fileindex);
  356. if assigned(infile) then
  357. begin
  358. { open only if needed !! }
  359. if (cs_asm_source in aktglobalswitches) then
  360. infile.open;
  361. end;
  362. { avoid unnecessary reopens of the same file !! }
  363. lastfileinfo.fileindex:=hp.fileinfo.fileindex;
  364. { be sure to change line !! }
  365. lastfileinfo.line:=-1;
  366. end;
  367. { write source }
  368. if (cs_asm_source in aktglobalswitches) and
  369. assigned(infile) then
  370. begin
  371. if (infile<>lastinfile) then
  372. begin
  373. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  374. if assigned(lastinfile) then
  375. lastinfile.close;
  376. end;
  377. if (hp.fileinfo.line<>lastfileinfo.line) and
  378. ((hp.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  379. begin
  380. if (hp.fileinfo.line<>0) and
  381. ((infile.linebuf^[hp.fileinfo.line]>=0) or (InlineLevel>0)) then
  382. AsmWriteLn(target_asm.comment+'['+tostr(hp.fileinfo.line)+'] '+
  383. fixline(infile.GetLineStr(hp.fileinfo.line)));
  384. { set it to a negative value !
  385. to make that is has been read already !! PM }
  386. if (infile.linebuf^[hp.fileinfo.line]>=0) then
  387. infile.linebuf^[hp.fileinfo.line]:=-infile.linebuf^[hp.fileinfo.line]-1;
  388. end;
  389. end;
  390. lastfileinfo:=hp.fileinfo;
  391. lastinfile:=infile;
  392. end;
  393. end;
  394. case hp.typ of
  395. ait_comment :
  396. Begin
  397. AsmWrite(target_asm.comment);
  398. AsmWritePChar(tai_comment(hp).str);
  399. AsmLn;
  400. End;
  401. ait_regalloc :
  402. begin
  403. if (cs_asm_regalloc in aktglobalswitches) then
  404. AsmWriteLn(target_asm.comment+'Register '+std_reg2str[tai_regalloc(hp).reg]+
  405. allocstr[tai_regalloc(hp).allocation]);
  406. end;
  407. ait_tempalloc :
  408. begin
  409. if (cs_asm_tempalloc in aktglobalswitches) then
  410. begin
  411. {$ifdef EXTDEBUG}
  412. if assigned(tai_tempalloc(hp).problem) then
  413. AsmWriteLn(target_asm.comment+tai_tempalloc(hp).problem^+' ('+tostr(tai_tempalloc(hp).temppos)+','+
  414. tostr(tai_tempalloc(hp).tempsize)+')')
  415. else
  416. {$endif EXTDEBUG}
  417. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  418. tostr(tai_tempalloc(hp).tempsize)+allocstr[tai_tempalloc(hp).allocation]);
  419. end;
  420. end;
  421. ait_section :
  422. begin
  423. if tai_section(hp).sec<>sec_none then
  424. begin
  425. AsmLn;
  426. AsmWriteLn('SECTION '+target_asm.secnames[tai_section(hp).sec]);
  427. end;
  428. LasTSec:=tai_section(hp).sec;
  429. end;
  430. ait_align :
  431. AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
  432. ait_datablock :
  433. begin
  434. if tai_datablock(hp).is_global then
  435. begin
  436. AsmWrite(#9'GLOBAL ');
  437. AsmWriteLn(tai_datablock(hp).sym.name);
  438. end;
  439. AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
  440. AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
  441. end;
  442. ait_const_32bit,
  443. ait_const_16bit,
  444. ait_const_8bit :
  445. begin
  446. AsmWrite(ait_const2str[hp.typ]+tostr(tai_const(hp).value));
  447. consttyp:=hp.typ;
  448. l:=0;
  449. repeat
  450. found:=(not (tai(hp.next)=nil)) and (tai(hp.next).typ=consttyp);
  451. if found then
  452. begin
  453. hp:=tai(hp.next);
  454. s:=','+tostr(tai_const(hp).value);
  455. AsmWrite(s);
  456. inc(l,length(s));
  457. end;
  458. until (not found) or (l>line_length);
  459. AsmLn;
  460. end;
  461. ait_const_symbol :
  462. begin
  463. AsmWrite(#9#9'DD'#9);
  464. AsmWrite(tai_const_symbol(hp).sym.name);
  465. if tai_const_symbol(hp).offset>0 then
  466. AsmWrite('+'+tostr(tai_const_symbol(hp).offset))
  467. else if tai_const_symbol(hp).offset<0 then
  468. AsmWrite(tostr(tai_const_symbol(hp).offset));
  469. AsmLn;
  470. end;
  471. ait_const_rva :
  472. begin
  473. AsmWrite(#9#9'RVA'#9);
  474. AsmWriteLn(tai_const_symbol(hp).sym.name);
  475. end;
  476. ait_real_32bit :
  477. AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
  478. ait_real_64bit :
  479. AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
  480. ait_real_80bit :
  481. AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
  482. ait_comp_64bit :
  483. AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
  484. ait_string :
  485. begin
  486. counter := 0;
  487. lines := tai_string(hp).len div line_length;
  488. { separate lines in different parts }
  489. if tai_string(hp).len > 0 then
  490. Begin
  491. for j := 0 to lines-1 do
  492. begin
  493. AsmWrite(#9#9'DB'#9);
  494. quoted:=false;
  495. for i:=counter to counter+line_length-1 do
  496. begin
  497. { it is an ascii character. }
  498. if (ord(tai_string(hp).str[i])>31) and
  499. (ord(tai_string(hp).str[i])<128) and
  500. (tai_string(hp).str[i]<>'"') then
  501. begin
  502. if not(quoted) then
  503. begin
  504. if i>counter then
  505. AsmWrite(',');
  506. AsmWrite('"');
  507. end;
  508. AsmWrite(tai_string(hp).str[i]);
  509. quoted:=true;
  510. end { if > 31 and < 128 and ord('"') }
  511. else
  512. begin
  513. if quoted then
  514. AsmWrite('"');
  515. if i>counter then
  516. AsmWrite(',');
  517. quoted:=false;
  518. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  519. end;
  520. end; { end for i:=0 to... }
  521. if quoted then AsmWrite('"');
  522. AsmWrite(target_info.newline);
  523. inc(counter,line_length);
  524. end; { end for j:=0 ... }
  525. { do last line of lines }
  526. if counter<tai_string(hp).len then
  527. AsmWrite(#9#9'DB'#9);
  528. quoted:=false;
  529. for i:=counter to tai_string(hp).len-1 do
  530. begin
  531. { it is an ascii character. }
  532. if (ord(tai_string(hp).str[i])>31) and
  533. (ord(tai_string(hp).str[i])<128) and
  534. (tai_string(hp).str[i]<>'"') then
  535. begin
  536. if not(quoted) then
  537. begin
  538. if i>counter then
  539. AsmWrite(',');
  540. AsmWrite('"');
  541. end;
  542. AsmWrite(tai_string(hp).str[i]);
  543. quoted:=true;
  544. end { if > 31 and < 128 and " }
  545. else
  546. begin
  547. if quoted then
  548. AsmWrite('"');
  549. if i>counter then
  550. AsmWrite(',');
  551. quoted:=false;
  552. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  553. end;
  554. end; { end for i:=0 to... }
  555. if quoted then
  556. AsmWrite('"');
  557. end;
  558. AsmLn;
  559. end;
  560. ait_label :
  561. begin
  562. if tai_label(hp).l.is_used then
  563. AsmWriteLn(tai_label(hp).l.name+':');
  564. end;
  565. ait_direct :
  566. begin
  567. AsmWritePChar(tai_direct(hp).str);
  568. AsmLn;
  569. end;
  570. ait_symbol :
  571. begin
  572. if tai_symbol(hp).is_global then
  573. begin
  574. AsmWrite(#9'GLOBAL ');
  575. AsmWriteLn(tai_symbol(hp).sym.name);
  576. end;
  577. AsmWrite(tai_symbol(hp).sym.name);
  578. if assigned(hp.next) and not(tai(hp.next).typ in
  579. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  580. ait_const_symbol,ait_const_rva,
  581. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
  582. AsmWriteLn(':')
  583. end;
  584. ait_symbol_end : ;
  585. ait_instruction :
  586. begin
  587. taicpu(hp).CheckNonCommutativeOpcodes;
  588. { We need intel order, no At&t }
  589. taicpu(hp).SetOperandOrder(op_intel);
  590. { Reset
  591. suffix:='';
  592. prefix:='';}
  593. s:='';
  594. if ((taicpu(hp).opcode=A_FADDP) or
  595. (taicpu(hp).opcode=A_FMULP))
  596. and (taicpu(hp).ops=0) then
  597. begin
  598. taicpu(hp).ops:=2;
  599. taicpu(hp).oper[0].typ:=top_reg;
  600. taicpu(hp).oper[0].reg:=R_ST1;
  601. taicpu(hp).oper[1].typ:=top_reg;
  602. taicpu(hp).oper[1].reg:=R_ST;
  603. end;
  604. if taicpu(hp).ops<>0 then
  605. begin
  606. if is_calljmp(taicpu(hp).opcode) then
  607. s:=#9+getopstr_jmp(taicpu(hp).oper[0],taicpu(hp).opcode)
  608. else
  609. begin
  610. { We need to explicitely set
  611. word prefix to get selectors
  612. to be pushed in 2 bytes PM }
  613. if (taicpu(hp).opsize=S_W) and
  614. ((taicpu(hp).opcode=A_PUSH) or
  615. (taicpu(hp).opcode=A_POP)) and
  616. (taicpu(hp).oper[0].typ=top_reg) and
  617. ((taicpu(hp).oper[0].reg>=firstsreg) and
  618. (taicpu(hp).oper[0].reg<=lastsreg)) then
  619. AsmWriteln(#9#9'DB'#9'066h');
  620. for i:=0 to taicpu(hp).ops-1 do
  621. begin
  622. if i=0 then
  623. sep:=#9
  624. else
  625. sep:=',';
  626. s:=s+sep+getopstr(taicpu(hp).oper[i],taicpu(hp).opsize,taicpu(hp).opcode,
  627. taicpu(hp).ops,(i=2));
  628. end;
  629. end;
  630. end;
  631. if taicpu(hp).opcode=A_FWAIT then
  632. AsmWriteln(#9#9'DB'#9'09bh')
  633. else
  634. AsmWriteLn(#9#9+{prefix+}std_op2str[taicpu(hp).opcode]+
  635. cond2str[taicpu(hp).condition]+{suffix+}s);
  636. end;
  637. {$ifdef GDB}
  638. ait_stabn,
  639. ait_stabs,
  640. ait_force_line,
  641. ait_stab_function_name : ;
  642. {$endif GDB}
  643. ait_cut :
  644. begin
  645. { only reset buffer if nothing has changed }
  646. if AsmSize=AsmStartSize then
  647. AsmClear
  648. else
  649. begin
  650. AsmClose;
  651. DoAssemble;
  652. AsmCreate(tai_cut(hp).place);
  653. end;
  654. { avoid empty files }
  655. while assigned(hp.next) and (tai(hp.next).typ in [ait_cut,ait_section,ait_comment]) do
  656. begin
  657. if tai(hp.next).typ=ait_section then
  658. lasTSec:=tai_section(hp.next).sec;
  659. hp:=tai(hp.next);
  660. end;
  661. if lasTSec<>sec_none then
  662. AsmWriteLn('SECTION '+target_asm.secnames[lasTSec]);
  663. AsmStartSize:=AsmSize;
  664. end;
  665. ait_marker :
  666. if tai_marker(hp).kind=InlineStart then
  667. inc(InlineLevel)
  668. else if tai_marker(hp).kind=InlineEnd then
  669. dec(InlineLevel);
  670. else
  671. internalerror(10000);
  672. end;
  673. hp:=tai(hp.next);
  674. end;
  675. end;
  676. var
  677. currentasmlist : TExternalAssembler;
  678. procedure writeexternal(p:tnamedindexitem;arg:pointer);
  679. begin
  680. if tasmsymbol(p).defbind=AB_EXTERNAL then
  681. currentasmlist.AsmWriteln('EXTERN'#9+p.name);
  682. end;
  683. procedure T386NasmAssembler.WriteExternals;
  684. begin
  685. currentasmlist:=self;
  686. objectlibrary.symbolsearch.foreach_static({$ifdef fpcprocvar}@{$endif}writeexternal,nil);
  687. end;
  688. procedure T386NasmAssembler.WriteAsmList;
  689. begin
  690. {$ifdef EXTDEBUG}
  691. if assigned(current_module.mainsource) then
  692. comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource^);
  693. {$endif}
  694. LasTSec:=sec_none;
  695. AsmWriteLn('BITS 32');
  696. AsmLn;
  697. lastfileinfo.line:=-1;
  698. lastfileinfo.fileindex:=0;
  699. lastinfile:=nil;
  700. WriteExternals;
  701. { Nasm doesn't support stabs
  702. WriteTree(debuglist);}
  703. WriteTree(codesegment);
  704. WriteTree(datasegment);
  705. WriteTree(consts);
  706. WriteTree(rttilist);
  707. WriteTree(resourcestringlist);
  708. WriteTree(bsssegment);
  709. Writetree(importssection);
  710. { exports are written by DLLTOOL
  711. if we use it so don't insert it twice (PM) }
  712. if not UseDeffileForExport and assigned(exportssection) then
  713. Writetree(exportssection);
  714. Writetree(resourcesection);
  715. AsmLn;
  716. {$ifdef EXTDEBUG}
  717. if assigned(current_module.mainsource) then
  718. comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource^);
  719. {$endif EXTDEBUG}
  720. end;
  721. {*****************************************************************************
  722. Initialize
  723. *****************************************************************************}
  724. const
  725. as_i386_nasmcoff_info : tasminfo =
  726. (
  727. id : as_i386_nasmcoff;
  728. idtxt : 'NASMCOFF';
  729. asmbin : 'nasm';
  730. asmcmd : '-f coff -o $OBJ $ASM';
  731. supported_target : system_i386_go32v2;
  732. outputbinary: false;
  733. allowdirect : true;
  734. needar : true;
  735. labelprefix_only_inside_procedure: false;
  736. labelprefix : '..@';
  737. comment : '; ';
  738. secnames : ('',
  739. '.text','.data','.bss',
  740. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  741. '.stab','.stabstr','')
  742. );
  743. as_i386_nasmwin32_info : tasminfo =
  744. (
  745. id : as_i386_nasmwin32;
  746. idtxt : 'NASMWIN32';
  747. asmbin : 'nasm';
  748. asmcmd : '-f win32 -o $OBJ $ASM';
  749. supported_target : system_i386_win32;
  750. outputbinary: false;
  751. allowdirect : true;
  752. needar : true;
  753. labelprefix_only_inside_procedure: false;
  754. labelprefix : '..@';
  755. comment : '; ';
  756. secnames : ('',
  757. '.text','.data','.bss',
  758. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  759. '.stab','.stabstr','')
  760. );
  761. as_i386_nasmobj_info : tasminfo =
  762. (
  763. id : as_i386_nasmobj;
  764. idtxt : 'NASMOBJ';
  765. asmbin : 'nasm';
  766. asmcmd : '-f obj -o $OBJ $ASM';
  767. supported_target : system_any; { what should I write here ?? }
  768. outputbinary: false;
  769. allowdirect : true;
  770. needar : true;
  771. labelprefix_only_inside_procedure: false;
  772. labelprefix : '..@';
  773. comment : '; ';
  774. secnames : ('',
  775. '.text','.data','.bss',
  776. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  777. '.stab','.stabstr','')
  778. );
  779. as_i386_nasmwdosx_info : tasminfo =
  780. (
  781. id : as_i386_nasmwdosx;
  782. idtxt : 'NASMWDOSX';
  783. asmbin : 'nasm';
  784. asmcmd : '-f win32 -o $OBJ $ASM';
  785. supported_target : system_i386_wdosx;
  786. outputbinary: false;
  787. allowdirect : true;
  788. needar : true;
  789. labelprefix_only_inside_procedure: false;
  790. labelprefix : '..@';
  791. comment : '; ';
  792. secnames : ('',
  793. '.text','.data','.bss',
  794. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  795. '.stab','.stabstr','')
  796. );
  797. as_i386_nasmelf_info : tasminfo =
  798. (
  799. id : as_i386_nasmelf;
  800. idtxt : 'NASMELF';
  801. asmbin : 'nasm';
  802. asmcmd : '-f elf -o $OBJ $ASM';
  803. supported_target : system_i386_linux;
  804. outputbinary: false;
  805. allowdirect : true;
  806. needar : true;
  807. labelprefix_only_inside_procedure: false;
  808. labelprefix : '..@';
  809. comment : '; ';
  810. secnames : ('',
  811. '.text','.data','.bss',
  812. '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
  813. '.stab','.stabstr','')
  814. );
  815. initialization
  816. RegisterAssembler(as_i386_nasmcoff_info,T386NasmAssembler);
  817. RegisterAssembler(as_i386_nasmwin32_info,T386NasmAssembler);
  818. RegisterAssembler(as_i386_nasmwdosx_info,T386NasmAssembler);
  819. RegisterAssembler(as_i386_nasmobj_info,T386NasmAssembler);
  820. RegisterAssembler(as_i386_nasmelf_info,T386NasmAssembler);
  821. end.
  822. {
  823. $Log$
  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. }