ag386int.pas 35 KB

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