ag386int.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  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. {$ifdef NO_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 NO_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 NO_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.33 1999-04-17 22:17:05 pierre
  759. * ifdef USE_OP3 released (changed into ifndef NO_OP3)
  760. * SHRD and SHLD first operand (ATT syntax) can only be CL reg or immediate const
  761. Revision 1.32 1999/04/16 11:49:39 peter
  762. + tempalloc
  763. + -at to show temp alloc info in .s file
  764. Revision 1.31 1999/04/16 10:00:55 pierre
  765. + ifdef USE_OP3 code :
  766. added all missing op_... constructors for tai386 needed
  767. for SHRD,SHLD and IMUL code in assembler readers
  768. (check in tests/tbs0123.pp)
  769. Revision 1.30 1999/03/29 16:05:43 peter
  770. * optimizer working for ag386bin
  771. Revision 1.29 1999/03/02 02:56:10 peter
  772. + stabs support for binary writers
  773. * more fixes and missing updates from the previous commit :(
  774. Revision 1.28 1999/03/01 15:46:16 peter
  775. * ag386bin finally make cycles correct
  776. * prefixes are now also normal opcodes
  777. Revision 1.27 1999/02/26 00:48:13 peter
  778. * assembler writers fixed for ag386bin
  779. Revision 1.26 1999/02/25 21:02:18 peter
  780. * ag386bin updates
  781. + coff writer
  782. Revision 1.25 1999/02/22 02:14:59 peter
  783. * updates for ag386bin
  784. Revision 1.24 1998/12/20 16:21:22 peter
  785. * smartlinking doesn't crash anymore
  786. Revision 1.23 1998/12/16 00:27:17 peter
  787. * removed some obsolete version checks
  788. Revision 1.22 1998/12/01 11:19:38 peter
  789. * fixed range problem with in [tasmop]
  790. Revision 1.21 1998/11/30 09:42:55 pierre
  791. * some range check bugs fixed (still not working !)
  792. + added DLL writing support for win32 (also accepts variables)
  793. + TempAnsi for code that could be used for Temporary ansi strings
  794. handling
  795. Revision 1.20 1998/11/17 00:26:09 peter
  796. * fixed for $H+
  797. Revision 1.19 1998/11/16 12:38:05 jonas
  798. + readded ait_marker support
  799. Revision 1.18 1998/11/12 11:19:33 pierre
  800. * fix for first line of function break
  801. Revision 1.17 1998/10/12 12:20:40 pierre
  802. + added tai_const_symbol_offset
  803. for r : pointer = @var.field;
  804. * better message for different arg names on implementation
  805. of function
  806. Revision 1.16 1998/10/06 17:16:33 pierre
  807. * some memory leaks fixed (thanks to Peter for heaptrc !)
  808. Revision 1.15 1998/10/01 20:19:06 jonas
  809. + ait_marker support
  810. Revision 1.14 1998/09/20 17:11:21 jonas
  811. * released REGALLOC
  812. Revision 1.13 1998/08/10 15:49:38 peter
  813. * small fixes for 0.99.5
  814. Revision 1.12 1998/08/08 10:19:17 florian
  815. * small fixes to write the extended type correct
  816. Revision 1.11 1998/06/05 17:46:02 peter
  817. * tp doesn't like comp() typecast
  818. Revision 1.10 1998/05/25 17:11:36 pierre
  819. * firstpasscount bug fixed
  820. now all is already set correctly the first time
  821. under EXTDEBUG try -gp to skip all other firstpasses
  822. it works !!
  823. * small bug fixes
  824. - for smallsets with -dTESTSMALLSET
  825. - some warnings removed (by correcting code !)
  826. Revision 1.9 1998/05/23 01:20:55 peter
  827. + aktasmmode, aktoptprocessor, aktoutputformat
  828. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  829. + $LIBNAME to set the library name where the unit will be put in
  830. * splitted cgi386 a bit (codeseg to large for bp7)
  831. * nasm, tasm works again. nasm moved to ag386nsm.pas
  832. Revision 1.8 1998/05/06 18:36:53 peter
  833. * tai_section extended with code,data,bss sections and enumerated type
  834. * ident 'compiled by FPC' moved to pmodules
  835. * small fix for smartlink
  836. Revision 1.7 1998/05/06 08:38:32 pierre
  837. * better position info with UseTokenInfo
  838. UseTokenInfo greatly simplified
  839. + added check for changed tree after first time firstpass
  840. (if we could remove all the cases were it happen
  841. we could skip all firstpass if firstpasscount > 1)
  842. Only with ExtDebug
  843. Revision 1.6 1998/05/04 17:54:24 peter
  844. + smartlinking works (only case jumptable left todo)
  845. * redesign of systems.pas to support assemblers and linkers
  846. + Unitname is now also in the PPU-file, increased version to 14
  847. Revision 1.5 1998/05/01 07:43:52 florian
  848. + basics for rtti implemented
  849. + switch $m (generate rtti for published sections)
  850. Revision 1.4 1998/04/29 10:33:41 pierre
  851. + added some code for ansistring (not complete nor working yet)
  852. * corrected operator overloading
  853. * corrected nasm output
  854. + started inline procedures
  855. + added starstarn : use ** for exponentiation (^ gave problems)
  856. + started UseTokenInfo cond to get accurate positions
  857. Revision 1.3 1998/04/08 16:58:01 pierre
  858. * several bugfixes
  859. ADD ADC and AND are also sign extended
  860. nasm output OK (program still crashes at end
  861. and creates wrong assembler files !!)
  862. procsym types sym in tdef removed !!
  863. Revision 1.2 1998/04/08 11:34:17 peter
  864. * nasm works (linux only tested)
  865. }