ag386int.pas 34 KB

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