ag386nsm.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. {
  2. $Id$
  3. Copyright (c) 1996,97 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. {$ifdef TP}
  20. {$N+,E+}
  21. {$endif}
  22. unit ag386nsm;
  23. interface
  24. uses aasm,assemble;
  25. type
  26. pi386nasmasmlist=^ti386nasmasmlist;
  27. ti386nasmasmlist = object(tasmlist)
  28. procedure WriteTree(p:paasmoutput);virtual;
  29. procedure WriteAsmList;virtual;
  30. end;
  31. implementation
  32. uses
  33. dos,strings,
  34. globtype,globals,systems,cobjects,
  35. files,verbose
  36. {$ifndef OLDASM}
  37. ,i386base,i386asm
  38. {$else}
  39. ,i386
  40. {$endif}
  41. {$ifdef GDB}
  42. ,gdb
  43. {$endif GDB}
  44. ;
  45. const
  46. line_length = 70;
  47. extstr : array[EXT_NEAR..EXT_ABS] of String[8] =
  48. ('NEAR','FAR','PROC','BYTE','WORD','DWORD',
  49. 'CODEPTR','DATAPTR','FWORD','PWORD','QWORD','TBYTE','ABS');
  50. function single2str(d : single) : string;
  51. var
  52. hs : string;
  53. p : byte;
  54. begin
  55. str(d,hs);
  56. { nasm expects a lowercase e }
  57. p:=pos('E',hs);
  58. if p>0 then
  59. hs[p]:='e';
  60. p:=pos('+',hs);
  61. if p>0 then
  62. delete(hs,p,1);
  63. single2str:=lower(hs);
  64. end;
  65. function double2str(d : double) : string;
  66. var
  67. hs : string;
  68. p : byte;
  69. begin
  70. str(d,hs);
  71. { nasm expects a lowercase e }
  72. p:=pos('E',hs);
  73. if p>0 then
  74. hs[p]:='e';
  75. p:=pos('+',hs);
  76. if p>0 then
  77. delete(hs,p,1);
  78. double2str:=lower(hs);
  79. end;
  80. function extended2str(e : extended) : string;
  81. var
  82. hs : string;
  83. p : byte;
  84. begin
  85. str(e,hs);
  86. { nasm expects a lowercase e }
  87. p:=pos('E',hs);
  88. if p>0 then
  89. hs[p]:='e';
  90. p:=pos('+',hs);
  91. if p>0 then
  92. delete(hs,p,1);
  93. extended2str:=lower(hs);
  94. end;
  95. function comp2str(d : bestreal) : string;
  96. type
  97. pdouble = ^double;
  98. var
  99. c : comp;
  100. dd : pdouble;
  101. begin
  102. {$ifdef FPC}
  103. c:=comp(d);
  104. {$else}
  105. c:=d;
  106. {$endif}
  107. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  108. comp2str:=double2str(dd^);
  109. end;
  110. function getreferencestring(const ref : treference) : string;
  111. var
  112. s : string;
  113. first : boolean;
  114. begin
  115. if ref.is_immediate then
  116. begin
  117. getreferencestring:=tostr(ref.offset);
  118. exit;
  119. end
  120. else
  121. with ref do
  122. begin
  123. first:=true;
  124. if ref.segment<>R_NO then
  125. s:='['+int_reg2str[segment]+':'
  126. else
  127. s:='[';
  128. if assigned(symbol) then
  129. begin
  130. s:=s+symbol^.name;
  131. first:=false;
  132. end;
  133. if (base<>R_NO) then
  134. begin
  135. if not(first) then
  136. s:=s+'+'
  137. else
  138. first:=false;
  139. s:=s+int_reg2str[base];
  140. end;
  141. if (index<>R_NO) then
  142. begin
  143. if not(first) then
  144. s:=s+'+'
  145. else
  146. first:=false;
  147. s:=s+int_reg2str[index];
  148. if scalefactor<>0 then
  149. s:=s+'*'+tostr(scalefactor);
  150. end;
  151. if offset<0 then
  152. s:=s+tostr(offset)
  153. else if (offset>0) then
  154. s:=s+'+'+tostr(offset);
  155. s:=s+']';
  156. end;
  157. getreferencestring:=s;
  158. end;
  159. {$ifndef OLDASM}
  160. function getopstr(const o:toper;s : topsize; opcode: tasmop;dest : boolean) : string;
  161. var
  162. hs : string;
  163. begin
  164. case o.typ of
  165. top_reg :
  166. getopstr:=int_nasmreg2str[o.reg];
  167. top_const :
  168. getopstr:=tostr(o.val);
  169. top_symbol :
  170. begin
  171. hs:='dword '+o.sym^.name;
  172. if o.symofs>0 then
  173. hs:=hs+'+'+tostr(o.symofs)
  174. else
  175. if o.symofs<0 then
  176. hs:=hs+tostr(o.symofs);
  177. getopstr:=hs;
  178. end;
  179. top_ref :
  180. begin
  181. hs:=getreferencestring(o.ref^);
  182. if not ((opcode = A_LEA) or (opcode = A_LGS) or
  183. (opcode = A_LSS) or (opcode = A_LFS) or
  184. (opcode = A_LES) or (opcode = A_LDS) or
  185. (opcode = A_SHR) or (opcode = A_SHL) or
  186. (opcode = A_SAR) or (opcode = A_SAL) or
  187. (opcode = A_OUT) or (opcode = A_IN)) then
  188. begin
  189. case s of
  190. S_B : hs:='byte '+hs;
  191. S_W : hs:='word '+hs;
  192. S_L : hs:='dword '+hs;
  193. S_IS : hs:='word '+hs;
  194. S_IL : hs:='dword '+hs;
  195. S_IQ : hs:='qword '+hs;
  196. S_FS : hs:='dword '+hs;
  197. S_FL : hs:='qword '+hs;
  198. S_FX : hs:='tword '+hs;
  199. S_BW : if dest then
  200. hs:='word '+hs
  201. else
  202. hs:='byte '+hs;
  203. S_BL : if dest then
  204. hs:='dword '+hs
  205. else
  206. hs:='byte '+hs;
  207. S_WL : if dest then
  208. hs:='dword '+hs
  209. else
  210. hs:='word '+hs;
  211. end
  212. end;
  213. getopstr:=hs;
  214. end;
  215. else
  216. internalerror(10001);
  217. end;
  218. end;
  219. function getopstr_jmp(const o:toper) : string;
  220. var
  221. hs : string;
  222. begin
  223. case o.typ of
  224. top_reg :
  225. getopstr_jmp:=int_nasmreg2str[o.reg];
  226. top_ref :
  227. getopstr_jmp:=getreferencestring(o.ref^);
  228. top_const :
  229. getopstr_jmp:=tostr(o.val);
  230. top_symbol :
  231. begin
  232. hs:=o.sym^.name;
  233. if o.symofs>0 then
  234. hs:=hs+'+'+tostr(o.symofs)
  235. else
  236. if o.symofs<0 then
  237. hs:=hs+tostr(o.symofs);
  238. getopstr_jmp:=hs;
  239. end;
  240. else
  241. internalerror(10001);
  242. end;
  243. end;
  244. {$else}
  245. function getopstr(t : byte;o : pointer;opofs:longint;s : topsize; opcode: tasmop;dest : boolean) : string;
  246. var
  247. hs : string;
  248. begin
  249. case t of
  250. top_reg : getopstr:=int_nasmreg2str[tregister(o)];
  251. top_const,
  252. top_ref : begin
  253. if t=top_const then
  254. hs := tostr(longint(o))
  255. else
  256. hs:=getreferencestring(preference(o)^);
  257. if not ((opcode = A_LEA) or (opcode = A_LGS) or
  258. (opcode = A_LSS) or (opcode = A_LFS) or
  259. (opcode = A_LES) or (opcode = A_LDS) or
  260. (opcode = A_SHR) or (opcode = A_SHL) or
  261. (opcode = A_SAR) or (opcode = A_SAL) or
  262. (opcode = A_OUT) or (opcode = A_IN)) then
  263. begin
  264. case s of
  265. S_B : hs:='byte '+hs;
  266. S_W : hs:='word '+hs;
  267. S_L : hs:='dword '+hs;
  268. S_IS : hs:='word '+hs;
  269. S_IL : hs:='dword '+hs;
  270. S_IQ : hs:='qword '+hs;
  271. S_FS : hs:='dword '+hs;
  272. S_FL : hs:='qword '+hs;
  273. S_FX : hs:='tword '+hs;
  274. S_BW : if dest then
  275. hs:='word '+hs
  276. else
  277. hs:='byte '+hs;
  278. S_BL : if dest then
  279. hs:='dword '+hs
  280. else
  281. hs:='byte '+hs;
  282. S_WL : if dest then
  283. hs:='dword '+hs
  284. else
  285. hs:='word '+hs;
  286. end
  287. end;
  288. getopstr:=hs;
  289. end;
  290. top_symbol : begin
  291. hs:='dword '+pasmsymbol(o)^.name;
  292. if opofs>0 then
  293. hs:=hs+'+'+tostr(opofs)
  294. else
  295. if opofs<0 then
  296. hs:=hs+tostr(opofs);
  297. getopstr:=hs;
  298. end;
  299. else
  300. internalerror(10001);
  301. end;
  302. end;
  303. function getopstr_jmp(t : byte;o : pointer;opofs:longint) : string;
  304. var
  305. hs : string;
  306. begin
  307. case t of
  308. top_reg : getopstr_jmp:=int_reg2str[tregister(o)];
  309. top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
  310. top_const : getopstr_jmp:=tostr(longint(o));
  311. top_symbol : begin
  312. hs:=pasmsymbol(o)^.name;
  313. if opofs>0 then
  314. hs:=hs+'+'+tostr(opofs)
  315. else
  316. if opofs<0 then
  317. hs:=hs+tostr(opofs);
  318. getopstr_jmp:=hs;
  319. end;
  320. else
  321. internalerror(10001);
  322. end;
  323. end;
  324. {$endif}
  325. {****************************************************************************
  326. Ti386nasmasmlist
  327. ****************************************************************************}
  328. var
  329. LastSec : tsection;
  330. const
  331. ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
  332. (#9'DD'#9,#9'DW'#9,#9'DB'#9);
  333. Function PadTabs(const p:string;addch:char):string;
  334. var
  335. s : string;
  336. i : longint;
  337. begin
  338. i:=length(p);
  339. if addch<>#0 then
  340. begin
  341. inc(i);
  342. s:=p+addch;
  343. end
  344. else
  345. s:=p;
  346. if i<8 then
  347. PadTabs:=s+#9#9
  348. else
  349. PadTabs:=s+#9;
  350. end;
  351. procedure ti386nasmasmlist.WriteTree(p:paasmoutput);
  352. type
  353. twowords=record
  354. word1,word2:word;
  355. end;
  356. var
  357. s,
  358. prefix,
  359. suffix : string;
  360. hp : pai;
  361. counter,
  362. lines,
  363. i,j,l : longint;
  364. op : tasmop;
  365. consttyp : tait;
  366. found,
  367. quoted : boolean;
  368. {$ifndef OLDASM}
  369. sep : char;
  370. {$endif}
  371. begin
  372. if not assigned(p) then
  373. exit;
  374. hp:=pai(p^.first);
  375. while assigned(hp) do
  376. begin
  377. case hp^.typ of
  378. ait_comment : Begin
  379. AsmWrite(target_asm.comment);
  380. AsmWritePChar(pai_asm_comment(hp)^.str);
  381. AsmLn;
  382. End;
  383. ait_regalloc,
  384. ait_tempalloc : ;
  385. ait_section : begin
  386. if pai_section(hp)^.sec<>sec_none then
  387. begin
  388. AsmLn;
  389. AsmWriteLn('SECTION '+target_asm.secnames[pai_section(hp)^.sec]);
  390. end;
  391. LastSec:=pai_section(hp)^.sec;
  392. end;
  393. ait_align : AsmWriteLn(#9'ALIGN '+tostr(pai_align(hp)^.aligntype));
  394. ait_external : AsmWriteLn('EXTERN '+pai_external(hp)^.sym^.name);
  395. ait_datablock : begin
  396. if pai_datablock(hp)^.is_global then
  397. AsmWriteLn(#9'GLOBAL '+pai_datablock(hp)^.sym^.name);
  398. AsmWriteLn(PadTabs(pai_datablock(hp)^.sym^.name,':')+'RESB'#9+tostr(pai_datablock(hp)^.size));
  399. end;
  400. ait_const_32bit,
  401. ait_const_8bit,
  402. ait_const_16bit : begin
  403. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  404. consttyp:=hp^.typ;
  405. l:=0;
  406. repeat
  407. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  408. if found then
  409. begin
  410. hp:=Pai(hp^.next);
  411. s:=','+tostr(pai_const(hp)^.value);
  412. AsmWrite(s);
  413. inc(l,length(s));
  414. end;
  415. until (not found) or (l>line_length);
  416. AsmLn;
  417. end;
  418. ait_const_symbol : begin
  419. AsmWriteLn(#9#9'DD'#9+pai_const_symbol(hp)^.sym^.name);
  420. if pai_const_symbol(hp)^.offset>0 then
  421. AsmWrite('+'+tostr(pai_const_symbol(hp)^.offset))
  422. else if pai_const_symbol(hp)^.offset<0 then
  423. AsmWrite(tostr(pai_const_symbol(hp)^.offset));
  424. AsmLn;
  425. end;
  426. ait_const_rva : begin
  427. AsmWriteLn(#9#9'RVA'#9+pai_const_symbol(hp)^.sym^.name);
  428. end;
  429. ait_real_32bit : AsmWriteLn(#9#9'DD'#9+single2str(pai_real_32bit(hp)^.value));
  430. ait_real_64bit : AsmWriteLn(#9#9'DQ'#9+double2str(pai_real_64bit(hp)^.value));
  431. ait_real_80bit : AsmWriteLn(#9#9'DT'#9+extended2str(pai_real_80bit(hp)^.value));
  432. ait_comp_64bit : AsmWriteLn(#9#9'DQ'#9+comp2str(pai_real_80bit(hp)^.value));
  433. ait_string : begin
  434. counter := 0;
  435. lines := pai_string(hp)^.len div line_length;
  436. { separate lines in different parts }
  437. if pai_string(hp)^.len > 0 then
  438. Begin
  439. for j := 0 to lines-1 do
  440. begin
  441. AsmWrite(#9#9'DB'#9);
  442. quoted:=false;
  443. for i:=counter to counter+line_length do
  444. begin
  445. { it is an ascii character. }
  446. if (ord(pai_string(hp)^.str[i])>31) and
  447. (ord(pai_string(hp)^.str[i])<128) and
  448. (pai_string(hp)^.str[i]<>'"') then
  449. begin
  450. if not(quoted) then
  451. begin
  452. if i>counter then
  453. AsmWrite(',');
  454. AsmWrite('"');
  455. end;
  456. AsmWrite(pai_string(hp)^.str[i]);
  457. quoted:=true;
  458. end { if > 31 and < 128 and ord('"') }
  459. else
  460. begin
  461. if quoted then
  462. AsmWrite('"');
  463. if i>counter then
  464. AsmWrite(',');
  465. quoted:=false;
  466. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  467. end;
  468. end; { end for i:=0 to... }
  469. if quoted then AsmWrite('"');
  470. AsmWrite(target_os.newline);
  471. counter := counter+line_length;
  472. end; { end for j:=0 ... }
  473. { do last line of lines }
  474. AsmWrite(#9#9'DB'#9);
  475. quoted:=false;
  476. for i:=counter to pai_string(hp)^.len-1 do
  477. begin
  478. { it is an ascii character. }
  479. if (ord(pai_string(hp)^.str[i])>31) and
  480. (ord(pai_string(hp)^.str[i])<128) and
  481. (pai_string(hp)^.str[i]<>'"') then
  482. begin
  483. if not(quoted) then
  484. begin
  485. if i>counter then
  486. AsmWrite(',');
  487. AsmWrite('"');
  488. end;
  489. AsmWrite(pai_string(hp)^.str[i]);
  490. quoted:=true;
  491. end { if > 31 and < 128 and " }
  492. else
  493. begin
  494. if quoted then
  495. AsmWrite('"');
  496. if i>counter then
  497. AsmWrite(',');
  498. quoted:=false;
  499. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  500. end;
  501. end; { end for i:=0 to... }
  502. if quoted then
  503. AsmWrite('"');
  504. end;
  505. AsmLn;
  506. end;
  507. ait_label : begin
  508. if pai_label(hp)^.l^.is_used then
  509. AsmWriteLn(lab2str(pai_label(hp)^.l)+':');
  510. end;
  511. ait_direct : begin
  512. AsmWritePChar(pai_direct(hp)^.str);
  513. AsmLn;
  514. end;
  515. ait_labeled_instruction :
  516. begin
  517. op:=pai386_labeled(hp)^.opcode;
  518. if not((op=A_JMP) or (op=A_LOOP) or (op=A_LOOPZ) or
  519. (op=A_LOOPE) or (op=A_LOOPNZ) or (op=A_LOOPNE) or
  520. (op=A_JCXZ) or (op=A_JECXZ)) then
  521. AsmWriteLn(#9#9+int_op2str[pai386_labeled(hp)^.opcode]+
  522. cond2str[pai386_labeled(hp)^.condition]+#9+'near '+lab2str(pai386_labeled(hp)^.lab))
  523. else
  524. AsmWriteLn(#9#9+int_op2str[pai386_labeled(hp)^.opcode]+
  525. cond2str[pai386_labeled(hp)^.condition]+#9+lab2str(pai386_labeled(hp)^.lab));
  526. end;
  527. ait_symbol : begin
  528. if pai_symbol(hp)^.is_global then
  529. AsmWriteLn(#9'GLOBAL '+pai_symbol(hp)^.sym^.name);
  530. AsmWrite(pai_symbol(hp)^.sym^.name);
  531. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  532. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  533. ait_const_symbol,ait_const_rva,
  534. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
  535. AsmWriteLn(':')
  536. end;
  537. ait_instruction : begin
  538. suffix:='';
  539. prefix:='';
  540. s:='';
  541. {$ifndef OLDASM}
  542. if pai386(hp)^.ops<>0 then
  543. begin
  544. if pai386(hp)^.opcode=A_CALL then
  545. s:=#9+getopstr_jmp(pai386(hp)^.oper[0])
  546. else
  547. begin
  548. for i:=0to pai386(hp)^.ops-1 do
  549. begin
  550. if i=0 then
  551. sep:=#9
  552. else
  553. sep:=',';
  554. s:=s+sep+getopstr(pai386(hp)^.oper[i],pai386(hp)^.opsize,pai386(hp)^.opcode,(i=1));
  555. end;
  556. end;
  557. end;
  558. if pai386(hp)^.opcode=A_FWAIT then
  559. AsmWriteln(#9#9'DB'#9'09bh')
  560. else
  561. AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^.opcode]+
  562. cond2str[pai386(hp)^.condition]+suffix+s);
  563. {$else}
  564. { added prefix instructions, must be on same line as opcode }
  565. if (pai386(hp)^.op1t = top_none) and
  566. ((pai386(hp)^.opcode = A_REP) or
  567. (pai386(hp)^.opcode = A_LOCK) or
  568. (pai386(hp)^.opcode = A_REPE) or
  569. (pai386(hp)^.opcode = A_REPNE)) then
  570. Begin
  571. prefix:=int_op2str[pai386(hp)^.opcode]+#9;
  572. hp:=Pai(hp^.next);
  573. { this is theorically impossible... }
  574. if hp=nil then
  575. begin
  576. s:=#9#9+prefix;
  577. AsmWriteLn(s);
  578. break;
  579. end;
  580. { nasm prefers prefix on a line alone }
  581. AsmWriteln(#9#9+prefix);
  582. prefix:='';
  583. end
  584. else
  585. prefix:= '';
  586. { A_FNSTS need the w as suffix at least for nasm}
  587. if (pai386(hp)^.opcode = A_FNSTS) then
  588. pai386(hp)^.opcode:=A_FNSTSW
  589. else
  590. if (pai386(hp)^.opcode = A_FSTS) then
  591. pai386(hp)^.opcode:=A_FSTSW;
  592. if pai386(hp)^.op1t<>top_none then
  593. begin
  594. if pai386(hp)^.opcode=A_CALL then
  595. s:=getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.op1ofs)
  596. else
  597. begin
  598. s:=getopstr(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.op1ofs,
  599. pai386(hp)^.opsize,pai386(hp)^.opcode,false);
  600. if pai386(hp)^.op3t<>top_none then
  601. begin
  602. if pai386(hp)^.op2t<>top_none then
  603. {$ifdef NO_OP3}
  604. s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),0,
  605. pai386(hp)^.opsize,pai386(hp)^.opcode,true)+','+s;
  606. s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),0,
  607. pai386(hp)^.opsize,pai386(hp)^.opcode,false)+','+s;
  608. {$else NO_OP3}
  609. s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,0,
  610. pai386(hp)^.opsize,pai386(hp)^.opcode,true)+','+s;
  611. s:=getopstr(pai386(hp)^.op3t,pai386(hp)^.op3,0,
  612. pai386(hp)^.opsize,pai386(hp)^.opcode,false)+','+s;
  613. {$endif NO_OP3}
  614. end
  615. else
  616. if pai386(hp)^.op2t<>top_none then
  617. s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,0,pai386(hp)^.opsize,
  618. pai386(hp)^.opcode,true)+','+s;
  619. end;
  620. s:=#9+s;
  621. end
  622. else
  623. begin
  624. { check if string instruction }
  625. { long form, otherwise may give range check errors }
  626. { in turbo pascal... }
  627. if ((pai386(hp)^.opcode = A_CMPS) or
  628. (pai386(hp)^.opcode = A_INS) or
  629. (pai386(hp)^.opcode = A_OUTS) or
  630. (pai386(hp)^.opcode = A_SCAS) or
  631. (pai386(hp)^.opcode = A_STOS) or
  632. (pai386(hp)^.opcode = A_MOVS) or
  633. (pai386(hp)^.opcode = A_LODS) or
  634. (pai386(hp)^.opcode = A_XLAT)) then
  635. Begin
  636. case pai386(hp)^.opsize of
  637. S_B: suffix:='b';
  638. S_W: suffix:='w';
  639. S_L: suffix:='d';
  640. else
  641. Message(assem_f_invalid_suffix_intel);
  642. end;
  643. end;
  644. s:='';
  645. end;
  646. if pai386(hp)^.opcode=A_FWAIT then
  647. AsmWriteln(#9#9'DB'#9'09bh')
  648. else
  649. AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^.opcode]+suffix+s);
  650. {$endif OLDASM}
  651. end;
  652. {$ifdef GDB}
  653. ait_stabn,
  654. ait_stabs,
  655. ait_force_line,
  656. ait_stab_function_name : ;
  657. {$endif GDB}
  658. ait_cut : begin
  659. { only reset buffer if nothing has changed }
  660. if AsmSize=AsmStartSize then
  661. AsmClear
  662. else
  663. begin
  664. AsmClose;
  665. DoAssemble;
  666. if pai_cut(hp)^.EndName then
  667. IsEndFile:=true;
  668. AsmCreate;
  669. end;
  670. { avoid empty files }
  671. while assigned(hp^.next) and (pai(hp^.next)^.typ in [ait_cut,ait_section,ait_comment]) do
  672. begin
  673. if pai(hp^.next)^.typ=ait_section then
  674. lastsec:=pai_section(hp^.next)^.sec;
  675. hp:=pai(hp^.next);
  676. end;
  677. if lastsec<>sec_none then
  678. AsmWriteLn('SECTION '+target_asm.secnames[lastsec]);
  679. AsmStartSize:=AsmSize;
  680. end;
  681. ait_marker : ;
  682. else
  683. internalerror(10000);
  684. end;
  685. hp:=pai(hp^.next);
  686. end;
  687. end;
  688. procedure ti386nasmasmlist.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. countlabelref:=false;
  698. WriteTree(externals);
  699. { Nasm doesn't support stabs
  700. WriteTree(debuglist);}
  701. WriteTree(codesegment);
  702. WriteTree(datasegment);
  703. WriteTree(consts);
  704. WriteTree(rttilist);
  705. WriteTree(bsssegment);
  706. countlabelref:=true;
  707. AsmLn;
  708. {$ifdef EXTDEBUG}
  709. if assigned(current_module^.mainsource) then
  710. comment(v_info,'Done writing nasm-styled assembler output for '+current_module^.mainsource^);
  711. {$endif EXTDEBUG}
  712. end;
  713. end.
  714. {
  715. $Log$
  716. Revision 1.37 1999-05-12 00:19:39 peter
  717. * removed R_DEFAULT_SEG
  718. * uniform float names
  719. Revision 1.36 1999/05/11 16:28:16 peter
  720. * long lines fixed
  721. Revision 1.35 1999/05/10 15:18:16 peter
  722. * fixed condition writing
  723. Revision 1.34 1999/05/08 19:52:34 peter
  724. + MessagePos() which is enhanced Message() function but also gets the
  725. position info
  726. * Removed comp warnings
  727. Revision 1.33 1999/05/07 00:08:48 pierre
  728. * AG386BIN cond -> OLDASM, only cosmetic
  729. Revision 1.32 1999/05/06 09:05:11 peter
  730. * generic write_float and str_float
  731. * fixed constant float conversions
  732. Revision 1.31 1999/05/04 21:44:32 florian
  733. * changes to compile it with Delphi 4.0
  734. Revision 1.30 1999/05/02 22:41:50 peter
  735. * moved section names to systems
  736. * fixed nasm,intel writer
  737. Revision 1.29 1999/05/01 13:23:59 peter
  738. * merged nasm compiler
  739. * old asm moved to oldasm/
  740. Revision 1.28 1999/04/17 22:17:06 pierre
  741. * ifdef USE_OP3 released (changed into ifndef NO_OP3)
  742. * SHRD and SHLD first operand (ATT syntax) can only be CL reg or immediate const
  743. Revision 1.27 1999/04/16 11:49:40 peter
  744. + tempalloc
  745. + -at to show temp alloc info in .s file
  746. Revision 1.26 1999/04/16 10:00:56 pierre
  747. + ifdef USE_OP3 code :
  748. added all missing op_... constructors for tai386 needed
  749. for SHRD,SHLD and IMUL code in assembler readers
  750. (check in tests/tbs0123.pp)
  751. Revision 1.25 1999/03/29 16:05:44 peter
  752. * optimizer working for ag386bin
  753. Revision 1.24 1999/03/10 13:25:44 pierre
  754. section order changed to get closer output from coff writer
  755. Revision 1.23 1999/03/04 13:55:39 pierre
  756. * some m68k fixes (still not compilable !)
  757. * new(tobj) does not give warning if tobj has no VMT !
  758. Revision 1.22 1999/03/02 02:56:11 peter
  759. + stabs support for binary writers
  760. * more fixes and missing updates from the previous commit :(
  761. Revision 1.21 1999/03/01 15:46:17 peter
  762. * ag386bin finally make cycles correct
  763. * prefixes are now also normal opcodes
  764. Revision 1.20 1999/02/26 00:48:14 peter
  765. * assembler writers fixed for ag386bin
  766. Revision 1.19 1999/02/25 21:02:19 peter
  767. * ag386bin updates
  768. + coff writer
  769. Revision 1.18 1999/02/22 02:15:00 peter
  770. * updates for ag386bin
  771. Revision 1.17 1998/12/20 16:21:23 peter
  772. * smartlinking doesn't crash anymore
  773. Revision 1.16 1998/12/16 00:27:18 peter
  774. * removed some obsolete version checks
  775. Revision 1.15 1998/12/01 11:19:39 peter
  776. * fixed range problem with in [tasmop]
  777. Revision 1.14 1998/11/30 09:42:56 pierre
  778. * some range check bugs fixed (still not working !)
  779. + added DLL writing support for win32 (also accepts variables)
  780. + TempAnsi for code that could be used for Temporary ansi strings
  781. handling
  782. Revision 1.13 1998/11/17 00:26:10 peter
  783. * fixed for $H+
  784. Revision 1.12 1998/11/12 11:19:34 pierre
  785. * fix for first line of function break
  786. Revision 1.11 1998/10/12 12:20:42 pierre
  787. + added tai_const_symbol_offset
  788. for r : pointer = @var.field;
  789. * better message for different arg names on implementation
  790. of function
  791. Revision 1.10 1998/10/06 17:16:34 pierre
  792. * some memory leaks fixed (thanks to Peter for heaptrc !)
  793. Revision 1.9 1998/10/01 20:19:07 jonas
  794. + ait_marker support
  795. Revision 1.8 1998/09/20 17:11:22 jonas
  796. * released REGALLOC
  797. Revision 1.7 1998/08/11 14:01:43 peter
  798. * fixed fwait bug using direct opcode
  799. Revision 1.6 1998/08/10 15:49:39 peter
  800. * small fixes for 0.99.5
  801. Revision 1.5 1998/08/08 10:19:18 florian
  802. * small fixes to write the extended type correct
  803. Revision 1.4 1998/06/05 17:46:03 peter
  804. * tp doesn't like comp() typecast
  805. Revision 1.3 1998/05/28 17:24:27 peter
  806. - $R- for tp to solve range errors with in[]
  807. Revision 1.2 1998/05/25 17:11:37 pierre
  808. * firstpasscount bug fixed
  809. now all is already set correctly the first time
  810. under EXTDEBUG try -gp to skip all other firstpasses
  811. it works !!
  812. * small bug fixes
  813. - for smallsets with -dTESTSMALLSET
  814. - some warnings removed (by correcting code !)
  815. Revision 1.1 1998/05/23 01:20:56 peter
  816. + aktasmmode, aktoptprocessor, aktoutputformat
  817. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  818. + $LIBNAME to set the library name where the unit will be put in
  819. * splitted cgi386 a bit (codeseg to large for bp7)
  820. * nasm, tasm works again. nasm moved to ag386nsm.pas
  821. }