ag386cof.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. {
  2. $Id$
  3. Copyright (c) 1996-98 by the FPC development team
  4. This unit implements an asmoutput class for i386 coff
  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 ag386cof;
  22. interface
  23. uses cobjects,aasm,assemble;
  24. type
  25. pi386coffasmlist=^ti386coffasmlist;
  26. ti386coffasmlist=object(tasmlist)
  27. procedure WriteTree(p:paasmoutput);virtual;
  28. procedure WriteAsmList;virtual;
  29. {$ifdef GDB}
  30. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  31. {$endif}
  32. end;
  33. implementation
  34. uses
  35. dos,globtype,globals,systems,i386,
  36. strings,files,verbose
  37. {$ifdef GDB}
  38. ,gdb
  39. {$endif GDB}
  40. ;
  41. const
  42. line_length = 70;
  43. var
  44. {$ifdef GDB}
  45. n_line : byte; { different types of source lines }
  46. linecount,
  47. includecount : longint;
  48. funcname : pchar;
  49. stabslastfileinfo : tfileposinfo;
  50. {$endif}
  51. lastsec : tsection; { last section type written }
  52. lastsecidx : longint;
  53. lastfileinfo : tfileposinfo;
  54. infile,
  55. lastinfile : pinputfile;
  56. function double2str(d : double) : string;
  57. var
  58. hs : string;
  59. begin
  60. str(d,hs);
  61. { replace space with + }
  62. if hs[1]=' ' then
  63. hs[1]:='+';
  64. double2str:='0d'+hs
  65. end;
  66. function extended2str(e : extended) : string;
  67. var
  68. hs : string;
  69. begin
  70. str(e,hs);
  71. { replace space with + }
  72. if hs[1]=' ' then
  73. hs[1]:='+';
  74. extended2str:='0d'+hs
  75. end;
  76. function comp2str(d : bestreal) : string;
  77. type
  78. pdouble = ^double;
  79. var
  80. c : comp;
  81. dd : pdouble;
  82. begin
  83. {$ifdef TP}
  84. c:=d;
  85. {$else}
  86. c:=comp(d);
  87. {$endif}
  88. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  89. comp2str:=double2str(dd^);
  90. end;
  91. function getreferencestring(const ref : treference) : string;
  92. var
  93. s : string;
  94. begin
  95. if ref.isintvalue then
  96. s:='$'+tostr(ref.offset)
  97. else
  98. begin
  99. with ref do
  100. begin
  101. { have we a segment prefix ? }
  102. { These are probably not correctly handled under GAS }
  103. { should be replaced by coding the segment override }
  104. { directly! - DJGPP FAQ }
  105. if segment<>R_DEFAULT_SEG then
  106. s:=att_reg2str[segment]+':'
  107. else
  108. s:='';
  109. if assigned(symbol) then
  110. s:=s+symbol^;
  111. if offset<0 then
  112. s:=s+tostr(offset)
  113. else
  114. if (offset>0) then
  115. begin
  116. if assigned(symbol) then
  117. s:=s+'+'+tostr(offset)
  118. else
  119. s:=s+tostr(offset);
  120. end;
  121. if (index<>R_NO) and (base=R_NO) then
  122. Begin
  123. s:=s+'(,'+att_reg2str[index];
  124. if scalefactor<>0 then
  125. s:=s+','+tostr(scalefactor)+')'
  126. else
  127. s:=s+')';
  128. end
  129. else
  130. if (index=R_NO) and (base<>R_NO) then
  131. s:=s+'('+att_reg2str[base]+')'
  132. else
  133. if (index<>R_NO) and (base<>R_NO) then
  134. Begin
  135. s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
  136. if scalefactor<>0 then
  137. s:=s+','+tostr(scalefactor)+')'
  138. else
  139. s := s+')';
  140. end;
  141. end;
  142. end;
  143. getreferencestring:=s;
  144. end;
  145. function getopstr(t : byte;o : pointer) : string;
  146. var
  147. hs : string;
  148. begin
  149. case t of
  150. top_reg : getopstr:=att_reg2str[tregister(o)];
  151. top_ref : getopstr:=getreferencestring(preference(o)^);
  152. top_const : getopstr:='$'+tostr(longint(o));
  153. top_symbol : begin
  154. hs:='$'+strpas(pchar(pcsymbol(o)^.symbol));
  155. if pcsymbol(o)^.offset>0 then
  156. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  157. else
  158. if pcsymbol(o)^.offset<0 then
  159. hs:=hs+tostr(pcsymbol(o)^.offset);
  160. getopstr:=hs;
  161. end;
  162. else
  163. internalerror(10001);
  164. end;
  165. end;
  166. function getopstr_jmp(t : byte;o : pointer) : string;
  167. var
  168. hs : string;
  169. begin
  170. case t of
  171. top_reg : getopstr_jmp:=att_reg2str[tregister(o)];
  172. top_ref : getopstr_jmp:='*'+getreferencestring(preference(o)^);
  173. top_const : getopstr_jmp:=tostr(longint(o));
  174. top_symbol : begin
  175. hs:=strpas(pchar(pcsymbol(o)^.symbol));
  176. if pcsymbol(o)^.offset>0 then
  177. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  178. else
  179. if pcsymbol(o)^.offset<0 then
  180. hs:=hs+tostr(pcsymbol(o)^.offset);
  181. getopstr_jmp:=hs;
  182. end;
  183. else
  184. internalerror(10001);
  185. end;
  186. end;
  187. {****************************************************************************
  188. TI386ATTASMOUTPUT
  189. ****************************************************************************}
  190. const
  191. ait_const2str : array[ait_const_32bit..ait_const_8bit] of string[8]=
  192. (#9'.long'#9,#9'.short'#9,#9'.byte'#9);
  193. function ait_section2str(s:tsection;idx:longint):string;
  194. begin
  195. case s of
  196. sec_code : ait_section2str:='.text';
  197. sec_data : ait_section2str:='.data';
  198. sec_bss : if target_info.target=target_i386_Win32 then
  199. ait_section2str:='.section .bss'
  200. else
  201. ait_section2str:='.bss';
  202. sec_idata : ait_section2str:='.section .idata$'+tostr(idx);
  203. sec_edata : ait_section2str:='.section .edata';
  204. else
  205. ait_section2str:='';
  206. end;
  207. {$ifdef GDB}
  208. { this is needed for line info in data }
  209. funcname:=nil;
  210. case s of
  211. sec_code : n_line:=n_textline;
  212. sec_data : n_line:=n_dataline;
  213. sec_bss : n_line:=n_bssline;
  214. else
  215. n_line:=n_dataline;
  216. end;
  217. {$endif GDB}
  218. LastSec:=s;
  219. LastSecIdx:=idx;
  220. end;
  221. {$ifdef GDB}
  222. procedure ti386attasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  223. var
  224. curr_n : byte;
  225. begin
  226. if not (cs_debuginfo in aktmoduleswitches) then
  227. exit;
  228. { file changed ? (must be before line info) }
  229. if (fileinfo.fileindex<>0) and
  230. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  231. begin
  232. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  233. if includecount=0 then
  234. curr_n:=n_sourcefile
  235. else
  236. curr_n:=n_includefile;
  237. if (infile^.path^<>'') then
  238. begin
  239. AsmWriteLn(#9'.stabs "'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+
  240. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  241. end;
  242. AsmWriteLn(#9'.stabs "'+lower(FixFileName(infile^.name^))+'",'+
  243. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  244. AsmWriteLn('Ltext'+ToStr(IncludeCount)+':');
  245. inc(includecount);
  246. end;
  247. { line changed ? }
  248. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  249. begin
  250. if (n_line=n_textline) and assigned(funcname) and
  251. (target_os.use_function_relative_addresses) then
  252. begin
  253. AsmWriteLn(target_asm.labelprefix+'l'+tostr(linecount)+':');
  254. AsmWrite(#9'.stabn '+tostr(n_line)+',0,'+tostr(fileinfo.line)+','+
  255. target_asm.labelprefix+'l'+tostr(linecount)+' - ');
  256. AsmWritePChar(FuncName);
  257. AsmLn;
  258. inc(linecount);
  259. end
  260. else
  261. AsmWriteLn(#9'.stabd'#9+tostr(n_line)+',0,'+tostr(fileinfo.line));
  262. end;
  263. stabslastfileinfo:=fileinfo;
  264. end;
  265. {$endif GDB}
  266. function getops(p:pai386;var optyp1,optyp2,optyp3:longint):longint;
  267. function doop(ot:longint;op:pointer):longint;
  268. begin
  269. case ot of
  270. top_reg :
  271. begin
  272. doop:=reg_2_type[tregister(op)];
  273. end;
  274. else
  275. internalerror(191918);
  276. end;
  277. end;
  278. var
  279. ops,opx : longint;
  280. begin
  281. ops:=0;
  282. optyp1:=0;
  283. optyp2:=0;
  284. optyp3:=0;
  285. with p^ do
  286. begin
  287. if opxt=0 then
  288. exit;
  289. optyp1:=doop(opx and $f,op1);
  290. optyp2:=doop((opx shr 4) and $f,op2);
  291. end;
  292. getops:=ops;
  293. end;
  294. procedure ti386coffasmlist.WriteTree(p:paasmoutput);
  295. type
  296. twowords=record
  297. word1,word2:word;
  298. end;
  299. textendedarray = array[0..9] of byte; { last longint will be and $ffff }
  300. var
  301. ch : char;
  302. hp : pai;
  303. consttyp : tait;
  304. s : string;
  305. found : boolean;
  306. i,pos,l : longint;
  307. e : extended;
  308. calljmp,
  309. do_line : boolean;
  310. instruc : tasmop;
  311. insops : longint;
  312. fits : boolean;
  313. optyp1,
  314. optyp2,
  315. optyp3 : longint;
  316. begin
  317. if not assigned(p) then
  318. exit;
  319. do_line:=(cs_debuginfo in aktmoduleswitches) or (cs_asm_source in aktglobalswitches);
  320. hp:=pai(p^.first);
  321. while assigned(hp) do
  322. begin
  323. if do_line then
  324. begin
  325. { I think it is better to write stabs before source line PM }
  326. {$ifdef GDB}
  327. { write stabs }
  328. if cs_debuginfo in aktmoduleswitches then
  329. begin
  330. if not (hp^.typ in [ait_external,ait_regalloc, ait_regdealloc,ait_stabn,ait_stabs,
  331. ait_label,ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  332. begin
  333. WriteFileLineInfo(hp^.fileinfo);
  334. end;
  335. end;
  336. {$endif GDB}
  337. { load infile }
  338. if lastfileinfo.fileindex<>hp^.fileinfo.fileindex then
  339. begin
  340. infile:=current_module^.sourcefiles^.get_file(hp^.fileinfo.fileindex);
  341. { open only if needed !! }
  342. if (cs_asm_source in aktglobalswitches) then
  343. infile^.open;
  344. { avoid unnecessary reopens of the same file !! }
  345. lastfileinfo.fileindex:=hp^.fileinfo.fileindex;
  346. { be sure to change line !! }
  347. lastfileinfo.line:=-1;
  348. end;
  349. { write source }
  350. if (cs_asm_source in aktglobalswitches) and
  351. not (hp^.typ in [ait_external,ait_stabn,ait_stabs,ait_section,
  352. ait_label,ait_cut,ait_align,ait_stab_function_name]) then
  353. begin
  354. if (infile<>lastinfile) and assigned(lastinfile) then
  355. begin
  356. AsmWriteLn(target_asm.comment+'['+infile^.name^+']');
  357. lastinfile^.close;
  358. end;
  359. if (hp^.fileinfo.line<>lastfileinfo.line) and
  360. (hp^.fileinfo.line<infile^.maxlinebuf) then
  361. begin
  362. if infile^.linebuf^[hp^.fileinfo.line]>=0 then
  363. AsmWriteLn(target_asm.comment+'['+tostr(hp^.fileinfo.line)+'] '+
  364. trimspace(infile^.GetLineStr(hp^.fileinfo.line)));
  365. { set it to a negative value !
  366. to make that is has been read already !! PM }
  367. infile^.linebuf^[hp^.fileinfo.line]:=-infile^.linebuf^[hp^.fileinfo.line]-1;
  368. end;
  369. lastfileinfo:=hp^.fileinfo;
  370. lastinfile:=infile;
  371. end;
  372. end;
  373. case hp^.typ of
  374. ait_external : ; { external is ignored }
  375. ait_comment : Begin
  376. AsmWrite(target_asm.comment);
  377. AsmWritePChar(pai_asm_comment(hp)^.str);
  378. AsmLn;
  379. End;
  380. {$ifdef DRegAlloc}
  381. ait_regalloc : AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+' allocated');
  382. ait_regdealloc : AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+' released');
  383. {$Else DRegAlloc}
  384. ait_regalloc, ait_regdealloc:;
  385. {$endif DRegAlloc}
  386. ait_align : begin
  387. { Fix Align bytes for Go32 which uses empty bits }
  388. l:=pai_align(hp)^.aligntype;
  389. if (target_info.target in [target_i386_GO32V1,target_i386_GO32V2]) then
  390. begin
  391. i:=0;
  392. while l>1 do
  393. begin
  394. l:=l shr 1;
  395. inc(i);
  396. end;
  397. l:=i;
  398. end;
  399. { use correct align opcode }
  400. AsmWrite(#9'.align '+tostr(l));
  401. if pai_align(hp)^.use_op then
  402. AsmWrite(','+tostr(pai_align(hp)^.op));
  403. AsmLn;
  404. end;
  405. ait_section : begin
  406. if pai_section(hp)^.sec<>sec_none then
  407. begin
  408. AsmLn;
  409. AsmWriteLn(ait_section2str(pai_section(hp)^.sec,pai_section(hp)^.idataidx));
  410. end;
  411. end;
  412. ait_datablock : begin
  413. if pai_datablock(hp)^.is_global then
  414. AsmWrite(#9'.comm'#9)
  415. else
  416. AsmWrite(#9'.lcomm'#9);
  417. AsmWritePChar(pai_datablock(hp)^.name);
  418. AsmWriteLn(','+tostr(pai_datablock(hp)^.size));
  419. end;
  420. ait_const_32bit,
  421. ait_const_16bit,
  422. ait_const_8bit : begin
  423. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  424. consttyp:=hp^.typ;
  425. l:=0;
  426. repeat
  427. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  428. if found then
  429. begin
  430. hp:=Pai(hp^.next);
  431. s:=','+tostr(pai_const(hp)^.value);
  432. AsmWrite(s);
  433. inc(l,length(s));
  434. end;
  435. until (not found) or (l>line_length);
  436. AsmLn;
  437. end;
  438. ait_const_symbol : begin
  439. AsmWrite(#9'.long'#9);
  440. AsmWritePChar(pchar(pai_const(hp)^.value));
  441. AsmLn;
  442. end;
  443. ait_const_symbol_offset : begin
  444. AsmWrite(#9'.long'#9);
  445. AsmWritePChar(pai_const_symbol_offset(hp)^.name);
  446. if pai_const_symbol_offset(hp)^.offset>0 then
  447. AsmWrite('+'+tostr(pai_const_symbol_offset(hp)^.offset))
  448. else if pai_const_symbol_offset(hp)^.offset<0 then
  449. AsmWrite(tostr(pai_const_symbol_offset(hp)^.offset));
  450. AsmLn;
  451. end;
  452. ait_const_rva : begin
  453. AsmWrite(#9'.rva'#9);
  454. AsmWritePChar(pchar(pai_const(hp)^.value));
  455. AsmLn;
  456. end;
  457. ait_real_64bit : AsmWriteLn(#9'.double'#9+double2str(pai_double(hp)^.value));
  458. ait_real_32bit : AsmWriteLn(#9'.single'#9+double2str(pai_single(hp)^.value));
  459. ait_real_extended : begin
  460. {$ifdef EXTDEBUG}
  461. AsmWriteLn('# workaround for Extended '+extended2str(pai_extended(hp)^.value));
  462. {$endif}
  463. { Make sure e is a extended type, bestreal could be
  464. a different type (bestreal) !! (PFV) }
  465. e:=pai_extended(hp)^.value;
  466. AsmWrite(#9'.byte'#9);
  467. for i:=0 to 9 do
  468. begin
  469. if i<>0 then
  470. AsmWrite(',');
  471. AsmWrite(tostr(textendedarray(e)[i]));
  472. end;
  473. AsmLn;
  474. end;
  475. ait_comp : begin
  476. { comp type is difficult to write so use double }
  477. AsmWriteLn(#9'.double'#9+comp2str(pai_comp(hp)^.value));
  478. end;
  479. ait_direct : begin
  480. AsmWritePChar(pai_direct(hp)^.str);
  481. AsmLn;
  482. {$IfDef GDB}
  483. if strpos(pai_direct(hp)^.str,'.data')<>nil then
  484. n_line:=n_dataline
  485. else if strpos(pai_direct(hp)^.str,'.text')<>nil then
  486. n_line:=n_textline
  487. else if strpos(pai_direct(hp)^.str,'.bss')<>nil then
  488. n_line:=n_bssline;
  489. {$endif GDB}
  490. end;
  491. ait_string : begin
  492. pos:=0;
  493. for i:=1 to pai_string(hp)^.len do
  494. begin
  495. if pos=0 then
  496. begin
  497. AsmWrite(#9'.ascii'#9'"');
  498. pos:=20;
  499. end;
  500. ch:=pai_string(hp)^.str[i-1];
  501. case ch of
  502. #0, {This can't be done by range, because a bug in FPC}
  503. #1..#31,
  504. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  505. '"' : s:='\"';
  506. '\' : s:='\\';
  507. else
  508. s:=ch;
  509. end;
  510. AsmWrite(s);
  511. inc(pos,length(s));
  512. if (pos>line_length) or (i=pai_string(hp)^.len) then
  513. begin
  514. AsmWriteLn('"');
  515. pos:=0;
  516. end;
  517. end;
  518. end;
  519. ait_label : begin
  520. if (pai_label(hp)^.l^.is_used) then
  521. begin
  522. if pai_label(hp)^.l^.is_data and (cs_smartlink in aktmoduleswitches) then
  523. AsmWriteLn('.globl'#9+lab2str(pai_label(hp)^.l));
  524. AsmWriteLn(lab2str(pai_label(hp)^.l)+':');
  525. end;
  526. end;
  527. ait_labeled_instruction : begin
  528. AsmWriteLn(#9+att_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab));
  529. end;
  530. ait_symbol : begin
  531. if pai_symbol(hp)^.is_global then
  532. begin
  533. AsmWrite('.globl'#9);
  534. AsmWritePChar(pai_symbol(hp)^.name);
  535. AsmLn;
  536. end;
  537. if target_info.target=target_i386_linux then
  538. begin
  539. AsmWrite(#9'.type'#9);
  540. AsmWritePChar(pai_symbol(hp)^.name);
  541. if assigned(pai(hp^.next)) and
  542. (pai(hp^.next)^.typ in [ait_const_symbol,ait_const_symbol_offset,
  543. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  544. ait_real_64bit,ait_real_32bit,ait_real_extended,ait_comp]) then
  545. AsmWriteLn(',@object')
  546. else
  547. AsmWriteLn(',@function');
  548. end;
  549. AsmWritePChar(pai_symbol(hp)^.name);
  550. AsmWriteLn(':');
  551. end;
  552. ait_instruction :
  553. begin { writes an instruction, highly table driven }
  554. { get local info }
  555. instruc:=pai386(hp)^._operator;
  556. insops:=getops(pai386(hp),optyp1,optyp2,optyp3);
  557. { get the correct instruction from the it table }
  558. if itcache^[instruc]<>-1 then
  559. i:=itcache^[instruc]
  560. else
  561. i:=0;
  562. fits:=false;
  563. while (not fits) do
  564. begin
  565. if (it[i].i=instruc) and (itcache^[instruc]=-1) then
  566. itcache^[instruc]:=i;
  567. if (it[i].i=instruc) and (it[i].ops=insops) then
  568. begin
  569. { first fit }
  570. case insops of
  571. 0 : begin
  572. fits:=true;
  573. break;
  574. end;
  575. 1 : Begin
  576. if (optyp1 and it[i].o1)<>0 then
  577. Begin
  578. fits:=true;
  579. break;
  580. end;
  581. { I consider sign-extended 8bit value to }
  582. { be equal to immediate 8bit therefore }
  583. { convert... }
  584. if (optyp1 = ao_imm8) then
  585. Begin
  586. { check if this is a simple sign extend. }
  587. if (it[i].o1<>ao_imm8s) then
  588. Begin
  589. fits:=true;
  590. break;
  591. end;
  592. end;
  593. end;
  594. 2 : if ((optyp1 and it[i].o1)<>0) and
  595. ((optyp2 and it[i].o2)<>0) then
  596. Begin
  597. fits:=true;
  598. break;
  599. end
  600. { if the operands can be swaped }
  601. { then swap them }
  602. else if ((it[i].m and af_d)<>0) and
  603. ((optyp1 and it[i].o2)<>0) and
  604. ((optyp2 and it[i].o1)<>0) then
  605. begin
  606. fits:=true;
  607. break;
  608. end;
  609. 3 : if ((optyp1 and it[i].o1)<>0) and
  610. ((optyp2 and it[i].o2)<>0) and
  611. ((optyp3 and it[i].o3)<>0) then
  612. Begin
  613. fits:=true;
  614. break;
  615. end;
  616. end; { end case }
  617. end;
  618. if it[i].i=A_NONE then
  619. InternalError(191919);
  620. end;
  621. { Old Writer code }
  622. if (pai386(hp)^._operator=A_PUSH) and
  623. (pai386(hp)^.size=S_W) and
  624. (pai386(hp)^.op1t=top_const) then
  625. begin
  626. {$ifdef EXTDEBUG}
  627. AsmWriteLn('# workaround for pushw'#9+tostr(longint(pai386(hp)^.op1)));
  628. {$endif}
  629. AsmWriteLn(#9'.byte 0x66,0x68');
  630. AsmWriteLn(#9'.word '+tostr(longint(pai386(hp)^.op1)));
  631. end
  632. else
  633. begin
  634. calljmp:=(pai386(hp)^._operator=A_CALL) or (pai386(hp)^._operator=A_JMP);
  635. { call maybe not translated to calll }
  636. if calljmp then
  637. s:=#9+att_op2str[pai386(hp)^._operator]
  638. else
  639. s:=#9+att_op2str[pai386(hp)^._operator]+att_opsize2str[pai386(hp)^.size];
  640. { process operands }
  641. if pai386(hp)^.op1t<>top_none then
  642. begin
  643. { call and jmp need an extra handling }
  644. { this code is only called if jmp isn't a labeled instruction }
  645. if calljmp then
  646. s:=s+#9+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
  647. else
  648. begin
  649. s:=s+#9+getopstr(pai386(hp)^.op1t,pai386(hp)^.op1);
  650. if pai386(hp)^.op3t<>top_none then
  651. begin
  652. if pai386(hp)^.op2t<>top_none then
  653. s:=s+','+getopstr(pai386(hp)^.op2t,
  654. pointer(longint(twowords(pai386(hp)^.op2).word1)));
  655. s:=s+','+getopstr(pai386(hp)^.op3t,
  656. pointer(longint(twowords(pai386(hp)^.op2).word2)));
  657. end
  658. else
  659. if pai386(hp)^.op2t<>top_none then
  660. s:=s+','+getopstr(pai386(hp)^.op2t,pai386(hp)^.op2);
  661. end;
  662. end;
  663. AsmWriteLn(s);
  664. end;
  665. end;
  666. {$ifdef GDB}
  667. ait_stabs : begin
  668. AsmWrite(#9'.stabs ');
  669. AsmWritePChar(pai_stabs(hp)^.str);
  670. AsmLn;
  671. end;
  672. ait_stabn : begin
  673. AsmWrite(#9'.stabn ');
  674. AsmWritePChar(pai_stabn(hp)^.str);
  675. AsmLn;
  676. end;
  677. ait_force_line : begin
  678. stabslastfileinfo.line:=0;
  679. end;
  680. ait_stab_function_name:
  681. funcname:=pai_stab_function_name(hp)^.str;
  682. {$endif GDB}
  683. ait_cut : begin
  684. { only reset buffer if nothing has changed }
  685. if AsmSize=AsmStartSize then
  686. AsmClear
  687. else
  688. begin
  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. lastsecidx:=pai_section(hp^.next)^.idataidx;
  702. end;
  703. hp:=pai(hp^.next);
  704. end;
  705. {$ifdef GDB}
  706. { force write of filename }
  707. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  708. includecount:=0;
  709. funcname:=nil;
  710. WriteFileLineInfo(hp^.fileinfo);
  711. {$endif GDB}
  712. if lastsec<>sec_none then
  713. AsmWriteLn(ait_section2str(lastsec,lastsecidx));
  714. AsmStartSize:=AsmSize;
  715. end;
  716. ait_marker : ;
  717. else
  718. internalerror(10000);
  719. end;
  720. hp:=pai(hp^.next);
  721. end;
  722. end;
  723. procedure ti386coffasmlist.WriteAsmList;
  724. var
  725. p:dirstr;
  726. n:namestr;
  727. e:extstr;
  728. {$ifdef GDB}
  729. fileinfo : tfileposinfo;
  730. {$endif GDB}
  731. begin
  732. {$ifdef EXTDEBUG}
  733. if assigned(current_module^.mainsource) then
  734. Comment(v_info,'Start writing att-styled assembler output for '+current_module^.mainsource^);
  735. {$endif}
  736. LastSec:=sec_none;
  737. {$ifdef GDB}
  738. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  739. {$endif GDB}
  740. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  741. LastInfile:=nil;
  742. if assigned(current_module^.mainsource) then
  743. fsplit(current_module^.mainsource^,p,n,e)
  744. else
  745. begin
  746. p:=inputdir;
  747. n:=inputfile;
  748. e:=inputextension;
  749. end;
  750. { to get symify to work }
  751. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  752. {$ifdef GDB}
  753. n_line:=n_bssline;
  754. funcname:=nil;
  755. linecount:=1;
  756. includecount:=0;
  757. fileinfo.fileindex:=1;
  758. fileinfo.line:=1;
  759. { Write main file }
  760. WriteFileLineInfo(fileinfo);
  761. {$endif GDB}
  762. AsmStartSize:=AsmSize;
  763. countlabelref:=false;
  764. If (cs_debuginfo in aktmoduleswitches) then
  765. WriteTree(debuglist);
  766. WriteTree(codesegment);
  767. WriteTree(datasegment);
  768. WriteTree(consts);
  769. WriteTree(rttilist);
  770. WriteTree(bsssegment);
  771. Writetree(importssection);
  772. Writetree(exportssection);
  773. Writetree(resourcesection);
  774. countlabelref:=true;
  775. AsmLn;
  776. {$ifdef EXTDEBUG}
  777. if assigned(current_module^.mainsource) then
  778. comment(v_info,'Done writing att-styled assembler output for '+current_module^.mainsource^);
  779. {$endif EXTDEBUG}
  780. end;
  781. end.
  782. {
  783. $Log$
  784. Revision 1.1 1999-01-10 15:37:51 peter
  785. * moved some tables from ra386*.pas -> i386.pas
  786. + start of coff writer
  787. * renamed asmutils unit to rautils
  788. }