ag386int.pas 35 KB

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