ag386nsm.pas 36 KB

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