ag386int.pas 34 KB

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