ag386int.pas 34 KB

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