ag386nsm.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  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. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  411. tostr(tai_tempalloc(hp).tempsize)+allocstr[tai_tempalloc(hp).allocation]);
  412. end;
  413. ait_section :
  414. begin
  415. if tai_section(hp).sec<>sec_none then
  416. begin
  417. AsmLn;
  418. AsmWriteLn('SECTION '+target_asm.secnames[tai_section(hp).sec]);
  419. end;
  420. LasTSec:=tai_section(hp).sec;
  421. end;
  422. ait_align :
  423. AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
  424. ait_datablock :
  425. begin
  426. if tai_datablock(hp).is_global then
  427. begin
  428. AsmWrite(#9'GLOBAL ');
  429. AsmWriteLn(tai_datablock(hp).sym.name);
  430. end;
  431. AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
  432. AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
  433. end;
  434. ait_const_32bit,
  435. ait_const_16bit,
  436. ait_const_8bit :
  437. begin
  438. AsmWrite(ait_const2str[hp.typ]+tostr(tai_const(hp).value));
  439. consttyp:=hp.typ;
  440. l:=0;
  441. repeat
  442. found:=(not (tai(hp.next)=nil)) and (tai(hp.next).typ=consttyp);
  443. if found then
  444. begin
  445. hp:=tai(hp.next);
  446. s:=','+tostr(tai_const(hp).value);
  447. AsmWrite(s);
  448. inc(l,length(s));
  449. end;
  450. until (not found) or (l>line_length);
  451. AsmLn;
  452. end;
  453. ait_const_symbol :
  454. begin
  455. AsmWrite(#9#9'DD'#9);
  456. AsmWrite(tai_const_symbol(hp).sym.name);
  457. if tai_const_symbol(hp).offset>0 then
  458. AsmWrite('+'+tostr(tai_const_symbol(hp).offset))
  459. else if tai_const_symbol(hp).offset<0 then
  460. AsmWrite(tostr(tai_const_symbol(hp).offset));
  461. AsmLn;
  462. end;
  463. ait_const_rva :
  464. begin
  465. AsmWrite(#9#9'RVA'#9);
  466. AsmWriteLn(tai_const_symbol(hp).sym.name);
  467. end;
  468. ait_real_32bit :
  469. AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
  470. ait_real_64bit :
  471. AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
  472. ait_real_80bit :
  473. AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
  474. ait_comp_64bit :
  475. AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
  476. ait_string :
  477. begin
  478. counter := 0;
  479. lines := tai_string(hp).len div line_length;
  480. { separate lines in different parts }
  481. if tai_string(hp).len > 0 then
  482. Begin
  483. for j := 0 to lines-1 do
  484. begin
  485. AsmWrite(#9#9'DB'#9);
  486. quoted:=false;
  487. for i:=counter to counter+line_length-1 do
  488. begin
  489. { it is an ascii character. }
  490. if (ord(tai_string(hp).str[i])>31) and
  491. (ord(tai_string(hp).str[i])<128) and
  492. (tai_string(hp).str[i]<>'"') then
  493. begin
  494. if not(quoted) then
  495. begin
  496. if i>counter then
  497. AsmWrite(',');
  498. AsmWrite('"');
  499. end;
  500. AsmWrite(tai_string(hp).str[i]);
  501. quoted:=true;
  502. end { if > 31 and < 128 and ord('"') }
  503. else
  504. begin
  505. if quoted then
  506. AsmWrite('"');
  507. if i>counter then
  508. AsmWrite(',');
  509. quoted:=false;
  510. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  511. end;
  512. end; { end for i:=0 to... }
  513. if quoted then AsmWrite('"');
  514. AsmWrite(target_info.newline);
  515. inc(counter,line_length);
  516. end; { end for j:=0 ... }
  517. { do last line of lines }
  518. if counter<tai_string(hp).len then
  519. AsmWrite(#9#9'DB'#9);
  520. quoted:=false;
  521. for i:=counter to tai_string(hp).len-1 do
  522. begin
  523. { it is an ascii character. }
  524. if (ord(tai_string(hp).str[i])>31) and
  525. (ord(tai_string(hp).str[i])<128) and
  526. (tai_string(hp).str[i]<>'"') then
  527. begin
  528. if not(quoted) then
  529. begin
  530. if i>counter then
  531. AsmWrite(',');
  532. AsmWrite('"');
  533. end;
  534. AsmWrite(tai_string(hp).str[i]);
  535. quoted:=true;
  536. end { if > 31 and < 128 and " }
  537. else
  538. begin
  539. if quoted then
  540. AsmWrite('"');
  541. if i>counter then
  542. AsmWrite(',');
  543. quoted:=false;
  544. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  545. end;
  546. end; { end for i:=0 to... }
  547. if quoted then
  548. AsmWrite('"');
  549. end;
  550. AsmLn;
  551. end;
  552. ait_label :
  553. begin
  554. if tai_label(hp).l.is_used then
  555. AsmWriteLn(tai_label(hp).l.name+':');
  556. end;
  557. ait_direct :
  558. begin
  559. AsmWritePChar(tai_direct(hp).str);
  560. AsmLn;
  561. end;
  562. ait_symbol :
  563. begin
  564. if tai_symbol(hp).is_global then
  565. begin
  566. AsmWrite(#9'GLOBAL ');
  567. AsmWriteLn(tai_symbol(hp).sym.name);
  568. end;
  569. AsmWrite(tai_symbol(hp).sym.name);
  570. if assigned(hp.next) and not(tai(hp.next).typ in
  571. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  572. ait_const_symbol,ait_const_rva,
  573. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
  574. AsmWriteLn(':')
  575. end;
  576. ait_symbol_end : ;
  577. ait_instruction :
  578. begin
  579. { Must be done with args in ATT order }
  580. taicpu(hp).SetOperandOrder(op_att);
  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.26 2002-08-18 20:06:28 peter
  819. * inlining is now also allowed in interface
  820. * renamed write/load to ppuwrite/ppuload
  821. * tnode storing in ppu
  822. * nld,ncon,nbas are already updated for storing in ppu
  823. Revision 1.25 2002/08/12 15:08:41 carl
  824. + stab register indexes for powerpc (moved from gdb to cpubase)
  825. + tprocessor enumeration moved to cpuinfo
  826. + linker in target_info is now a class
  827. * many many updates for m68k (will soon start to compile)
  828. - removed some ifdef or correct them for correct cpu
  829. Revision 1.24 2002/08/11 14:32:29 peter
  830. * renamed current_library to objectlibrary
  831. Revision 1.23 2002/08/11 13:24:16 peter
  832. * saving of asmsymbols in ppu supported
  833. * asmsymbollist global is removed and moved into a new class
  834. tasmlibrarydata that will hold the info of a .a file which
  835. corresponds with a single module. Added librarydata to tmodule
  836. to keep the library info stored for the module. In the future the
  837. objectfiles will also be stored to the tasmlibrarydata class
  838. * all getlabel/newasmsymbol and friends are moved to the new class
  839. Revision 1.22 2002/07/26 21:15:43 florian
  840. * rewrote the system handling
  841. Revision 1.21 2002/07/01 18:46:29 peter
  842. * internal linker
  843. * reorganized aasm layer
  844. Revision 1.20 2002/05/18 13:34:21 peter
  845. * readded missing revisions
  846. Revision 1.19 2002/05/16 19:46:50 carl
  847. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  848. + try to fix temp allocation (still in ifdef)
  849. + generic constructor calls
  850. + start of tassembler / tmodulebase class cleanup
  851. Revision 1.17 2002/05/12 16:53:16 peter
  852. * moved entry and exitcode to ncgutil and cgobj
  853. * foreach gets extra argument for passing local data to the
  854. iterator function
  855. * -CR checks also class typecasts at runtime by changing them
  856. into as
  857. * fixed compiler to cycle with the -CR option
  858. * fixed stabs with elf writer, finally the global variables can
  859. be watched
  860. * removed a lot of routines from cga unit and replaced them by
  861. calls to cgobj
  862. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  863. u32bit then the other is typecasted also to u32bit without giving
  864. a rangecheck warning/error.
  865. * fixed pascal calling method with reversing also the high tree in
  866. the parast, detected by tcalcst3 test
  867. Revision 1.16 2002/04/15 19:12:09 carl
  868. + target_info.size_of_pointer -> pointer_size
  869. + some cleanup of unused types/variables
  870. * move several constants from cpubase to their specific units
  871. (where they are used)
  872. + att_Reg2str -> gas_reg2str
  873. + int_reg2str -> std_reg2str
  874. Revision 1.15 2002/04/14 16:58:41 carl
  875. + att_reg2str -> gas_reg2str
  876. Revision 1.14 2002/04/04 18:27:37 carl
  877. + added wdosx support (patch from Pavel)
  878. Revision 1.13 2002/04/02 17:11:33 peter
  879. * tlocation,treference update
  880. * LOC_CONSTANT added for better constant handling
  881. * secondadd splitted in multiple routines
  882. * location_force_reg added for loading a location to a register
  883. of a specified size
  884. * secondassignment parses now first the right and then the left node
  885. (this is compatible with Kylix). This saves a lot of push/pop especially
  886. with string operations
  887. * adapted some routines to use the new cg methods
  888. }