ag386int.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  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_regdealloc :;
  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. s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),0,
  635. pai386(hp)^.opsize,pai386(hp)^.opcode,true)+','+s;
  636. s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),0,
  637. pai386(hp)^.opsize,pai386(hp)^.opcode,false)+','+s;
  638. end
  639. else
  640. if pai386(hp)^.op2t<>top_none then
  641. s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,0,pai386(hp)^.opsize,
  642. pai386(hp)^.opcode,true)+','+s;
  643. end;
  644. s:=#9+s;
  645. end
  646. else
  647. begin
  648. { check if string instruction }
  649. { long form, otherwise may give range check errors }
  650. { in turbo pascal... }
  651. if ((pai386(hp)^.opcode = A_CMPS) or
  652. (pai386(hp)^.opcode = A_INS) or
  653. (pai386(hp)^.opcode = A_OUTS) or
  654. (pai386(hp)^.opcode = A_SCAS) or
  655. (pai386(hp)^.opcode = A_STOS) or
  656. (pai386(hp)^.opcode = A_MOVS) or
  657. (pai386(hp)^.opcode = A_LODS) or
  658. (pai386(hp)^.opcode = A_XLAT)) then
  659. Begin
  660. case pai386(hp)^.opsize of
  661. S_B: suffix:='b';
  662. S_W: suffix:='w';
  663. S_L: suffix:='d';
  664. else
  665. Message(assem_f_invalid_suffix_intel);
  666. end;
  667. end;
  668. s:='';
  669. end;
  670. AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^.opcode]+suffix+s);
  671. {$endif AG386BIN}
  672. end;
  673. {$ifdef GDB}
  674. ait_stabn,
  675. ait_stabs,
  676. ait_force_line,
  677. ait_stab_function_name : ;
  678. {$endif GDB}
  679. ait_cut : begin
  680. { only reset buffer if nothing has changed }
  681. if AsmSize=AsmStartSize then
  682. AsmClear
  683. else
  684. begin
  685. if LastSec<>sec_none then
  686. AsmWriteLn('_'+ait_section2masmstr[LastSec]+#9#9'ENDS');
  687. AsmLn;
  688. AsmWriteLn(#9'END');
  689. AsmClose;
  690. DoAssemble;
  691. if pai_cut(hp)^.EndName then
  692. IsEndFile:=true;
  693. AsmCreate;
  694. end;
  695. { avoid empty files }
  696. while assigned(hp^.next) and (pai(hp^.next)^.typ in [ait_cut,ait_section,ait_comment]) do
  697. begin
  698. if pai(hp^.next)^.typ=ait_section then
  699. begin
  700. lastsec:=pai_section(hp^.next)^.sec;
  701. end;
  702. hp:=pai(hp^.next);
  703. end;
  704. AsmWriteLn(#9'.386p');
  705. AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
  706. if lastsec<>sec_none then
  707. AsmWriteLn('_'+ait_section2masmstr[lastsec]+#9#9+
  708. 'SEGMENT'#9'PARA PUBLIC USE32 '''+
  709. ait_section2masmstr[lastsec]+'''');
  710. AsmStartSize:=AsmSize;
  711. end;
  712. ait_marker: ;
  713. else
  714. internalerror(10000);
  715. end;
  716. hp:=pai(hp^.next);
  717. end;
  718. end;
  719. procedure ti386intasmlist.WriteAsmList;
  720. begin
  721. {$ifdef EXTDEBUG}
  722. if assigned(current_module^.mainsource) then
  723. comment(v_info,'Start writing intel-styled assembler output for '+current_module^.mainsource^);
  724. {$endif}
  725. LastSec:=sec_none;
  726. AsmWriteLn(#9'.386p');
  727. AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
  728. AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
  729. AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
  730. AsmLn;
  731. countlabelref:=false;
  732. WriteTree(externals);
  733. { INTEL ASM doesn't support stabs
  734. WriteTree(debuglist);}
  735. WriteTree(codesegment);
  736. WriteTree(datasegment);
  737. WriteTree(consts);
  738. WriteTree(rttilist);
  739. WriteTree(bsssegment);
  740. countlabelref:=true;
  741. AsmWriteLn(#9'END');
  742. AsmLn;
  743. {$ifdef EXTDEBUG}
  744. if assigned(current_module^.mainsource) then
  745. comment(v_info,'Done writing intel-styled assembler output for '+current_module^.mainsource^);
  746. {$endif EXTDEBUG}
  747. end;
  748. end.
  749. {
  750. $Log$
  751. Revision 1.30 1999-03-29 16:05:43 peter
  752. * optimizer working for ag386bin
  753. Revision 1.29 1999/03/02 02:56:10 peter
  754. + stabs support for binary writers
  755. * more fixes and missing updates from the previous commit :(
  756. Revision 1.28 1999/03/01 15:46:16 peter
  757. * ag386bin finally make cycles correct
  758. * prefixes are now also normal opcodes
  759. Revision 1.27 1999/02/26 00:48:13 peter
  760. * assembler writers fixed for ag386bin
  761. Revision 1.26 1999/02/25 21:02:18 peter
  762. * ag386bin updates
  763. + coff writer
  764. Revision 1.25 1999/02/22 02:14:59 peter
  765. * updates for ag386bin
  766. Revision 1.24 1998/12/20 16:21:22 peter
  767. * smartlinking doesn't crash anymore
  768. Revision 1.23 1998/12/16 00:27:17 peter
  769. * removed some obsolete version checks
  770. Revision 1.22 1998/12/01 11:19:38 peter
  771. * fixed range problem with in [tasmop]
  772. Revision 1.21 1998/11/30 09:42:55 pierre
  773. * some range check bugs fixed (still not working !)
  774. + added DLL writing support for win32 (also accepts variables)
  775. + TempAnsi for code that could be used for Temporary ansi strings
  776. handling
  777. Revision 1.20 1998/11/17 00:26:09 peter
  778. * fixed for $H+
  779. Revision 1.19 1998/11/16 12:38:05 jonas
  780. + readded ait_marker support
  781. Revision 1.18 1998/11/12 11:19:33 pierre
  782. * fix for first line of function break
  783. Revision 1.17 1998/10/12 12:20:40 pierre
  784. + added tai_const_symbol_offset
  785. for r : pointer = @var.field;
  786. * better message for different arg names on implementation
  787. of function
  788. Revision 1.16 1998/10/06 17:16:33 pierre
  789. * some memory leaks fixed (thanks to Peter for heaptrc !)
  790. Revision 1.15 1998/10/01 20:19:06 jonas
  791. + ait_marker support
  792. Revision 1.14 1998/09/20 17:11:21 jonas
  793. * released REGALLOC
  794. Revision 1.13 1998/08/10 15:49:38 peter
  795. * small fixes for 0.99.5
  796. Revision 1.12 1998/08/08 10:19:17 florian
  797. * small fixes to write the extended type correct
  798. Revision 1.11 1998/06/05 17:46:02 peter
  799. * tp doesn't like comp() typecast
  800. Revision 1.10 1998/05/25 17:11:36 pierre
  801. * firstpasscount bug fixed
  802. now all is already set correctly the first time
  803. under EXTDEBUG try -gp to skip all other firstpasses
  804. it works !!
  805. * small bug fixes
  806. - for smallsets with -dTESTSMALLSET
  807. - some warnings removed (by correcting code !)
  808. Revision 1.9 1998/05/23 01:20:55 peter
  809. + aktasmmode, aktoptprocessor, aktoutputformat
  810. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  811. + $LIBNAME to set the library name where the unit will be put in
  812. * splitted cgi386 a bit (codeseg to large for bp7)
  813. * nasm, tasm works again. nasm moved to ag386nsm.pas
  814. Revision 1.8 1998/05/06 18:36:53 peter
  815. * tai_section extended with code,data,bss sections and enumerated type
  816. * ident 'compiled by FPC' moved to pmodules
  817. * small fix for smartlink
  818. Revision 1.7 1998/05/06 08:38:32 pierre
  819. * better position info with UseTokenInfo
  820. UseTokenInfo greatly simplified
  821. + added check for changed tree after first time firstpass
  822. (if we could remove all the cases were it happen
  823. we could skip all firstpass if firstpasscount > 1)
  824. Only with ExtDebug
  825. Revision 1.6 1998/05/04 17:54:24 peter
  826. + smartlinking works (only case jumptable left todo)
  827. * redesign of systems.pas to support assemblers and linkers
  828. + Unitname is now also in the PPU-file, increased version to 14
  829. Revision 1.5 1998/05/01 07:43:52 florian
  830. + basics for rtti implemented
  831. + switch $m (generate rtti for published sections)
  832. Revision 1.4 1998/04/29 10:33:41 pierre
  833. + added some code for ansistring (not complete nor working yet)
  834. * corrected operator overloading
  835. * corrected nasm output
  836. + started inline procedures
  837. + added starstarn : use ** for exponentiation (^ gave problems)
  838. + started UseTokenInfo cond to get accurate positions
  839. Revision 1.3 1998/04/08 16:58:01 pierre
  840. * several bugfixes
  841. ADD ADC and AND are also sign extended
  842. nasm output OK (program still crashes at end
  843. and creates wrong assembler files !!)
  844. procsym types sym in tdef removed !!
  845. Revision 1.2 1998/04/08 11:34:17 peter
  846. * nasm works (linux only tested)
  847. }