ag386int.pas 34 KB

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