ag386att.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This unit implements an asmoutput class for i386 AT&T syntax
  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 ag386att;
  22. interface
  23. uses cobjects,aasm,assemble;
  24. type
  25. pi386attasmlist=^ti386attasmlist;
  26. ti386attasmlist=object(tasmlist)
  27. procedure WriteTree(p:paasmoutput);virtual;
  28. procedure WriteAsmList;virtual;
  29. {$ifdef GDB}
  30. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  31. procedure WriteFileEndInfo;
  32. {$endif}
  33. end;
  34. implementation
  35. uses
  36. {$ifdef Delphi}
  37. dmisc,
  38. {$else Delphi}
  39. dos,
  40. {$endif Delphi}
  41. strings,
  42. globtype,globals,systems,
  43. files,verbose,cpubase,cpuasm
  44. {$ifdef GDB}
  45. ,gdb
  46. {$endif GDB}
  47. ;
  48. const
  49. line_length = 70;
  50. var
  51. {$ifdef GDB}
  52. n_line : byte; { different types of source lines }
  53. linecount,
  54. includecount : longint;
  55. funcname : pchar;
  56. stabslastfileinfo : tfileposinfo;
  57. {$endif}
  58. lastsec : tsection; { last section type written }
  59. lastfileinfo : tfileposinfo;
  60. infile,
  61. lastinfile : pinputfile;
  62. symendcount : longint;
  63. function fixline(s:string):string;
  64. {
  65. return s with all leading and ending spaces and tabs removed
  66. }
  67. var
  68. i,j,k : longint;
  69. begin
  70. i:=length(s);
  71. while (i>0) and (s[i] in [#9,' ']) do
  72. dec(i);
  73. j:=1;
  74. while (j<i) and (s[j] in [#9,' ']) do
  75. inc(j);
  76. for k:=j to i do
  77. if s[k] in [#0..#31,#127..#255] then
  78. s[k]:='.';
  79. fixline:=Copy(s,j,i-j+1);
  80. end;
  81. function single2str(d : single) : string;
  82. var
  83. hs : string;
  84. begin
  85. str(d,hs);
  86. { replace space with + }
  87. if hs[1]=' ' then
  88. hs[1]:='+';
  89. single2str:='0d'+hs
  90. end;
  91. function double2str(d : double) : string;
  92. var
  93. hs : string;
  94. begin
  95. str(d,hs);
  96. { replace space with + }
  97. if hs[1]=' ' then
  98. hs[1]:='+';
  99. double2str:='0d'+hs
  100. end;
  101. function extended2str(e : extended) : string;
  102. var
  103. hs : string;
  104. begin
  105. str(e,hs);
  106. { replace space with + }
  107. if hs[1]=' ' then
  108. hs[1]:='+';
  109. extended2str:='0d'+hs
  110. end;
  111. type
  112. pdouble = ^double;
  113. function comp2str(d : bestreal) : string;
  114. var
  115. c : comp;
  116. dd : pdouble;
  117. begin
  118. {$ifdef FPC}
  119. c:=comp(d);
  120. {$else}
  121. c:=d;
  122. {$endif}
  123. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  124. comp2str:=double2str(dd^);
  125. end;
  126. function getreferencestring(var ref : treference) : string;
  127. var
  128. s : string;
  129. begin
  130. if ref.is_immediate then
  131. begin
  132. internalerror(1000101);
  133. exit;
  134. end
  135. else
  136. begin
  137. with ref do
  138. begin
  139. inc(offset,offsetfixup);
  140. offsetfixup:=0;
  141. { have we a segment prefix ? }
  142. { These are probably not correctly handled under GAS }
  143. { should be replaced by coding the segment override }
  144. { directly! - DJGPP FAQ }
  145. if segment<>R_NO then
  146. s:=att_reg2str[segment]+':'
  147. else
  148. s:='';
  149. if assigned(symbol) then
  150. s:=s+symbol^.name;
  151. if offset<0 then
  152. s:=s+tostr(offset)
  153. else
  154. if (offset>0) then
  155. begin
  156. if assigned(symbol) then
  157. s:=s+'+'+tostr(offset)
  158. else
  159. s:=s+tostr(offset);
  160. end;
  161. if (index<>R_NO) and (base=R_NO) then
  162. Begin
  163. s:=s+'(,'+att_reg2str[index];
  164. if scalefactor<>0 then
  165. s:=s+','+tostr(scalefactor)+')'
  166. else
  167. s:=s+')';
  168. end
  169. else
  170. if (index=R_NO) and (base<>R_NO) then
  171. s:=s+'('+att_reg2str[base]+')'
  172. else
  173. if (index<>R_NO) and (base<>R_NO) then
  174. Begin
  175. s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
  176. if scalefactor<>0 then
  177. s:=s+','+tostr(scalefactor)+')'
  178. else
  179. s := s+')';
  180. end;
  181. end;
  182. end;
  183. getreferencestring:=s;
  184. end;
  185. function getopstr(const o:toper) : string;
  186. var
  187. hs : string;
  188. begin
  189. case o.typ of
  190. top_reg :
  191. getopstr:=att_reg2str[o.reg];
  192. top_ref :
  193. getopstr:=getreferencestring(o.ref^);
  194. top_const :
  195. getopstr:='$'+tostr(o.val);
  196. top_symbol :
  197. begin
  198. if assigned(o.sym) then
  199. hs:='$'+o.sym^.name
  200. else
  201. hs:='$';
  202. if o.symofs>0 then
  203. hs:=hs+'+'+tostr(o.symofs)
  204. else
  205. if o.symofs<0 then
  206. hs:=hs+tostr(o.symofs)
  207. else
  208. if not(assigned(o.sym)) then
  209. hs:=hs+'0';
  210. getopstr:=hs;
  211. end;
  212. else
  213. internalerror(10001);
  214. end;
  215. end;
  216. function getopstr_jmp(const o:toper) : string;
  217. var
  218. hs : string;
  219. begin
  220. case o.typ of
  221. top_reg :
  222. getopstr_jmp:='*'+att_reg2str[o.reg];
  223. top_ref :
  224. getopstr_jmp:='*'+getreferencestring(o.ref^);
  225. top_const :
  226. getopstr_jmp:=tostr(o.val);
  227. top_symbol :
  228. begin
  229. hs:=o.sym^.name;
  230. if o.symofs>0 then
  231. hs:=hs+'+'+tostr(o.symofs)
  232. else
  233. if o.symofs<0 then
  234. hs:=hs+tostr(o.symofs);
  235. getopstr_jmp:=hs;
  236. end;
  237. else
  238. internalerror(10001);
  239. end;
  240. end;
  241. {****************************************************************************
  242. TI386ATTASMOUTPUT
  243. ****************************************************************************}
  244. const
  245. ait_const2str : array[ait_const_32bit..ait_const_8bit] of string[8]=
  246. (#9'.long'#9,#9'.short'#9,#9'.byte'#9);
  247. function ait_section2str(s:tsection):string;
  248. begin
  249. ait_section2str:=target_asm.secnames[s];
  250. {$ifdef GDB}
  251. { this is needed for line info in data }
  252. funcname:=nil;
  253. case s of
  254. sec_code : n_line:=n_textline;
  255. sec_data : n_line:=n_dataline;
  256. sec_bss : n_line:=n_bssline;
  257. else n_line:=n_dataline;
  258. end;
  259. {$endif GDB}
  260. LastSec:=s;
  261. end;
  262. {$ifdef GDB}
  263. procedure ti386attasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  264. var
  265. curr_n : byte;
  266. begin
  267. if not (cs_debuginfo in aktmoduleswitches) then
  268. exit;
  269. { file changed ? (must be before line info) }
  270. if (fileinfo.fileindex<>0) and
  271. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  272. begin
  273. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  274. if assigned(infile) then
  275. begin
  276. if includecount=0 then
  277. curr_n:=n_sourcefile
  278. else
  279. curr_n:=n_includefile;
  280. if (infile^.path^<>'') then
  281. begin
  282. AsmWriteLn(#9'.stabs "'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+
  283. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  284. end;
  285. AsmWriteLn(#9'.stabs "'+lower(FixFileName(infile^.name^))+'",'+
  286. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  287. AsmWriteLn('Ltext'+ToStr(IncludeCount)+':');
  288. inc(includecount);
  289. end;
  290. end;
  291. { line changed ? }
  292. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  293. begin
  294. if (n_line=n_textline) and assigned(funcname) and
  295. (target_os.use_function_relative_addresses) then
  296. begin
  297. AsmWriteLn(target_asm.labelprefix+'l'+tostr(linecount)+':');
  298. AsmWrite(#9'.stabn '+tostr(n_line)+',0,'+tostr(fileinfo.line)+','+
  299. target_asm.labelprefix+'l'+tostr(linecount)+' - ');
  300. AsmWritePChar(FuncName);
  301. AsmLn;
  302. inc(linecount);
  303. end
  304. else
  305. AsmWriteLn(#9'.stabd'#9+tostr(n_line)+',0,'+tostr(fileinfo.line));
  306. end;
  307. stabslastfileinfo:=fileinfo;
  308. end;
  309. procedure ti386attasmlist.WriteFileEndInfo;
  310. begin
  311. if not (cs_debuginfo in aktmoduleswitches) then
  312. exit;
  313. AsmLn;
  314. AsmWriteLn(ait_section2str(sec_code));
  315. AsmWriteLn(#9'.stabs "",'+tostr(n_sourcefile)+',0,0,Letext');
  316. AsmWriteLn('Letext:');
  317. end;
  318. {$endif GDB}
  319. procedure ti386attasmlist.WriteTree(p:paasmoutput);
  320. const
  321. allocstr : array[boolean] of string[10]=(' released',' allocated');
  322. nolinetai =[ait_label,
  323. ait_regalloc,ait_tempalloc,
  324. ait_stabn,ait_stabs,ait_section,
  325. ait_cut,ait_marker,ait_align,ait_stab_function_name];
  326. type
  327. t80bitarray = array[0..9] of byte;
  328. t64bitarray = array[0..7] of byte;
  329. t32bitarray = array[0..3] of byte;
  330. var
  331. ch : char;
  332. hp : pai;
  333. consttyp : tait;
  334. s : string;
  335. found : boolean;
  336. i,pos,l : longint;
  337. co : comp;
  338. sin : single;
  339. d : double;
  340. e : extended;
  341. op : tasmop;
  342. calljmp,
  343. do_line : boolean;
  344. sep : char;
  345. begin
  346. if not assigned(p) then
  347. exit;
  348. { lineinfo is only needed for codesegment (PFV) }
  349. do_line:=(cs_asm_source in aktglobalswitches) or
  350. ((cs_lineinfo in aktmoduleswitches) and (p=codesegment));
  351. hp:=pai(p^.first);
  352. while assigned(hp) do
  353. begin
  354. aktfilepos:=hp^.fileinfo;
  355. if not(hp^.typ in nolinetai) then
  356. begin
  357. {$ifdef GDB}
  358. { write stabs }
  359. if cs_debuginfo in aktmoduleswitches then
  360. WriteFileLineInfo(hp^.fileinfo);
  361. {$endif GDB}
  362. if do_line then
  363. begin
  364. { load infile }
  365. if lastfileinfo.fileindex<>hp^.fileinfo.fileindex then
  366. begin
  367. infile:=current_module^.sourcefiles^.get_file(hp^.fileinfo.fileindex);
  368. if assigned(infile) then
  369. begin
  370. { open only if needed !! }
  371. if (cs_asm_source in aktglobalswitches) then
  372. infile^.open;
  373. end;
  374. { avoid unnecessary reopens of the same file !! }
  375. lastfileinfo.fileindex:=hp^.fileinfo.fileindex;
  376. { be sure to change line !! }
  377. lastfileinfo.line:=-1;
  378. end;
  379. { write source }
  380. if (cs_asm_source in aktglobalswitches) and
  381. assigned(infile) then
  382. begin
  383. if (infile<>lastinfile) then
  384. begin
  385. AsmWriteLn(target_asm.comment+'['+infile^.name^+']');
  386. if assigned(lastinfile) then
  387. lastinfile^.close;
  388. end;
  389. if (hp^.fileinfo.line<>lastfileinfo.line) and
  390. (hp^.fileinfo.line<infile^.maxlinebuf) then
  391. begin
  392. if (hp^.fileinfo.line<>0) and
  393. (infile^.linebuf^[hp^.fileinfo.line]>=0) then
  394. AsmWriteLn(target_asm.comment+'['+tostr(hp^.fileinfo.line)+'] '+
  395. fixline(infile^.GetLineStr(hp^.fileinfo.line)));
  396. { set it to a negative value !
  397. to make that is has been read already !! PM }
  398. infile^.linebuf^[hp^.fileinfo.line]:=-infile^.linebuf^[hp^.fileinfo.line]-1;
  399. end;
  400. end;
  401. {$ifdef LINEINFO}
  402. { lineinfo }
  403. if (cs_lineinfo in aktmoduleswitches) then
  404. begin
  405. if (infile<>lastinfile) then
  406. begin
  407. lineinfolist^.concat(new(pai_const(init_8bit
  408. end
  409. else
  410. begin
  411. end;
  412. end;
  413. {$endif LINEINFO}
  414. lastfileinfo:=hp^.fileinfo;
  415. lastinfile:=infile;
  416. end;
  417. end;
  418. case hp^.typ of
  419. ait_comment :
  420. Begin
  421. AsmWrite(target_asm.comment);
  422. AsmWritePChar(pai_asm_comment(hp)^.str);
  423. AsmLn;
  424. End;
  425. ait_regalloc :
  426. begin
  427. if (cs_asm_regalloc in aktglobalswitches) then
  428. AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+
  429. allocstr[pairegalloc(hp)^.allocation]);
  430. end;
  431. ait_tempalloc :
  432. begin
  433. if (cs_asm_tempalloc in aktglobalswitches) then
  434. AsmWriteLn(target_asm.comment+'Temp '+tostr(paitempalloc(hp)^.temppos)+','+
  435. tostr(paitempalloc(hp)^.tempsize)+allocstr[paitempalloc(hp)^.allocation]);
  436. end;
  437. ait_align :
  438. begin
  439. AsmWrite(#9'.balign '+tostr(pai_align(hp)^.aligntype));
  440. if pai_align(hp)^.use_op then
  441. AsmWrite(','+tostr(pai_align(hp)^.fillop));
  442. AsmLn;
  443. end;
  444. ait_section :
  445. begin
  446. if pai_section(hp)^.sec<>sec_none then
  447. begin
  448. AsmLn;
  449. AsmWriteLn(ait_section2str(pai_section(hp)^.sec));
  450. {$ifdef GDB}
  451. lastfileinfo.line:=-1;
  452. {$endif GDB}
  453. end;
  454. end;
  455. ait_datablock :
  456. begin
  457. if pai_datablock(hp)^.is_global then
  458. AsmWrite(#9'.comm'#9)
  459. else
  460. AsmWrite(#9'.lcomm'#9);
  461. AsmWrite(pai_datablock(hp)^.sym^.name);
  462. AsmWriteLn(','+tostr(pai_datablock(hp)^.size));
  463. end;
  464. ait_const_32bit,
  465. ait_const_16bit,
  466. ait_const_8bit :
  467. begin
  468. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  469. consttyp:=hp^.typ;
  470. l:=0;
  471. repeat
  472. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  473. if found then
  474. begin
  475. hp:=Pai(hp^.next);
  476. s:=','+tostr(pai_const(hp)^.value);
  477. AsmWrite(s);
  478. inc(l,length(s));
  479. end;
  480. until (not found) or (l>line_length);
  481. AsmLn;
  482. end;
  483. ait_const_symbol :
  484. begin
  485. AsmWrite(#9'.long'#9+pai_const_symbol(hp)^.sym^.name);
  486. if pai_const_symbol(hp)^.offset>0 then
  487. AsmWrite('+'+tostr(pai_const_symbol(hp)^.offset))
  488. else if pai_const_symbol(hp)^.offset<0 then
  489. AsmWrite(tostr(pai_const_symbol(hp)^.offset));
  490. AsmLn;
  491. end;
  492. ait_const_rva :
  493. AsmWriteLn(#9'.rva'#9+pai_const_symbol(hp)^.sym^.name);
  494. ait_real_80bit :
  495. begin
  496. if do_line then
  497. AsmWriteLn(target_asm.comment+extended2str(pai_real_80bit(hp)^.value));
  498. { Make sure e is a extended type, bestreal could be
  499. a different type (bestreal) !! (PFV) }
  500. e:=pai_real_80bit(hp)^.value;
  501. AsmWrite(#9'.byte'#9);
  502. for i:=0 to 9 do
  503. begin
  504. if i<>0 then
  505. AsmWrite(',');
  506. AsmWrite(tostr(t80bitarray(e)[i]));
  507. end;
  508. AsmLn;
  509. end;
  510. ait_real_64bit :
  511. begin
  512. if do_line then
  513. AsmWriteLn(target_asm.comment+double2str(pai_real_64bit(hp)^.value));
  514. d:=pai_real_64bit(hp)^.value;
  515. AsmWrite(#9'.byte'#9);
  516. for i:=0 to 7 do
  517. begin
  518. if i<>0 then
  519. AsmWrite(',');
  520. AsmWrite(tostr(t64bitarray(d)[i]));
  521. end;
  522. AsmLn;
  523. end;
  524. ait_real_32bit :
  525. begin
  526. if do_line then
  527. AsmWriteLn(target_asm.comment+single2str(pai_real_32bit(hp)^.value));
  528. sin:=pai_real_32bit(hp)^.value;
  529. AsmWrite(#9'.byte'#9);
  530. for i:=0 to 3 do
  531. begin
  532. if i<>0 then
  533. AsmWrite(',');
  534. AsmWrite(tostr(t32bitarray(sin)[i]));
  535. end;
  536. AsmLn;
  537. end;
  538. ait_comp_64bit :
  539. begin
  540. if do_line then
  541. AsmWriteLn(target_asm.comment+comp2str(pai_comp_64bit(hp)^.value));
  542. AsmWrite(#9'.byte'#9);
  543. {$ifdef FPC}
  544. co:=comp(pai_comp_64bit(hp)^.value);
  545. {$else}
  546. co:=pai_comp_64bit(hp)^.value;
  547. {$endif}
  548. for i:=0 to 7 do
  549. begin
  550. if i<>0 then
  551. AsmWrite(',');
  552. AsmWrite(tostr(t64bitarray(co)[i]));
  553. end;
  554. AsmLn;
  555. end;
  556. ait_direct :
  557. begin
  558. AsmWritePChar(pai_direct(hp)^.str);
  559. AsmLn;
  560. {$IfDef GDB}
  561. if strpos(pai_direct(hp)^.str,'.data')<>nil then
  562. n_line:=n_dataline
  563. else if strpos(pai_direct(hp)^.str,'.text')<>nil then
  564. n_line:=n_textline
  565. else if strpos(pai_direct(hp)^.str,'.bss')<>nil then
  566. n_line:=n_bssline;
  567. {$endif GDB}
  568. end;
  569. ait_string :
  570. begin
  571. pos:=0;
  572. for i:=1 to pai_string(hp)^.len do
  573. begin
  574. if pos=0 then
  575. begin
  576. AsmWrite(#9'.ascii'#9'"');
  577. pos:=20;
  578. end;
  579. ch:=pai_string(hp)^.str[i-1];
  580. case ch of
  581. #0, {This can't be done by range, because a bug in FPC}
  582. #1..#31,
  583. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  584. '"' : s:='\"';
  585. '\' : s:='\\';
  586. else
  587. s:=ch;
  588. end;
  589. AsmWrite(s);
  590. inc(pos,length(s));
  591. if (pos>line_length) or (i=pai_string(hp)^.len) then
  592. begin
  593. AsmWriteLn('"');
  594. pos:=0;
  595. end;
  596. end;
  597. end;
  598. ait_label :
  599. begin
  600. if (pai_label(hp)^.l^.is_used) then
  601. begin
  602. if pai_label(hp)^.l^.typ=AS_GLOBAL then
  603. begin
  604. AsmWrite('.globl'#9);
  605. AsmWriteLn(pai_label(hp)^.l^.name);
  606. end;
  607. AsmWrite(pai_label(hp)^.l^.name);
  608. AsmWriteLn(':');
  609. end;
  610. end;
  611. ait_symbol :
  612. begin
  613. if pai_symbol(hp)^.is_global then
  614. begin
  615. AsmWrite('.globl'#9);
  616. AsmWriteLn(pai_symbol(hp)^.sym^.name);
  617. end;
  618. if target_info.target=target_i386_linux then
  619. begin
  620. AsmWrite(#9'.type'#9);
  621. AsmWrite(pai_symbol(hp)^.sym^.name);
  622. if assigned(pai(hp^.next)) and
  623. (pai(hp^.next)^.typ in [ait_const_symbol,ait_const_rva,
  624. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  625. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  626. AsmWriteLn(',@object')
  627. else
  628. AsmWriteLn(',@function');
  629. if pai_symbol(hp)^.sym^.size>0 then
  630. begin
  631. AsmWrite(#9'.size'#9);
  632. AsmWrite(pai_symbol(hp)^.sym^.name);
  633. AsmWrite(', ');
  634. AsmWriteLn(tostr(pai_symbol(hp)^.sym^.size));
  635. end;
  636. end;
  637. AsmWrite(pai_symbol(hp)^.sym^.name);
  638. AsmWriteLn(':');
  639. end;
  640. ait_symbol_end :
  641. begin
  642. if target_info.target=target_i386_linux then
  643. begin
  644. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  645. inc(symendcount);
  646. AsmWriteLn(s+':');
  647. AsmWrite(#9'.size'#9);
  648. AsmWrite(pai_symbol(hp)^.sym^.name);
  649. AsmWrite(', '+s+' - ');
  650. AsmWriteLn(pai_symbol(hp)^.sym^.name);
  651. end;
  652. end;
  653. ait_instruction :
  654. begin
  655. op:=paicpu(hp)^.opcode;
  656. calljmp:=is_calljmp(op);
  657. { call maybe not translated to call }
  658. s:=#9+att_op2str[op]+cond2str[paicpu(hp)^.condition];
  659. if (not calljmp) and
  660. (att_needsuffix[op]<>AttSufNONE) and
  661. (op<>A_FNSTSW) and
  662. not(
  663. (paicpu(hp)^.oper[0].typ=top_reg) and
  664. (paicpu(hp)^.oper[0].reg in [R_ST..R_ST7])
  665. ) then
  666. s:=s+att_opsize2str[paicpu(hp)^.opsize];
  667. { process operands }
  668. if paicpu(hp)^.ops<>0 then
  669. begin
  670. { call and jmp need an extra handling }
  671. { this code is only called if jmp isn't a labeled instruction }
  672. { quick hack to overcome a problem with manglednames=255 chars }
  673. if calljmp then
  674. begin
  675. AsmWrite(s+#9);
  676. s:=+getopstr_jmp(paicpu(hp)^.oper[0]);
  677. end
  678. else
  679. begin
  680. for i:=0 to paicpu(hp)^.ops-1 do
  681. begin
  682. if i=0 then
  683. sep:=#9
  684. else
  685. sep:=',';
  686. s:=s+sep+getopstr(paicpu(hp)^.oper[i])
  687. end;
  688. end;
  689. end;
  690. AsmWriteLn(s);
  691. end;
  692. {$ifdef GDB}
  693. ait_stabs :
  694. begin
  695. AsmWrite(#9'.stabs ');
  696. AsmWritePChar(pai_stabs(hp)^.str);
  697. AsmLn;
  698. end;
  699. ait_stabn :
  700. begin
  701. AsmWrite(#9'.stabn ');
  702. AsmWritePChar(pai_stabn(hp)^.str);
  703. AsmLn;
  704. end;
  705. ait_force_line :
  706. stabslastfileinfo.line:=0;
  707. ait_stab_function_name:
  708. funcname:=pai_stab_function_name(hp)^.str;
  709. {$endif GDB}
  710. ait_cut :
  711. begin
  712. if SmartAsm then
  713. begin
  714. { only reset buffer if nothing has changed }
  715. if AsmSize=AsmStartSize then
  716. AsmClear
  717. else
  718. begin
  719. AsmClose;
  720. DoAssemble;
  721. AsmCreate(pai_cut(hp)^.place);
  722. end;
  723. { avoid empty files }
  724. while assigned(hp^.next) and (pai(hp^.next)^.typ in [ait_cut,ait_section,ait_comment]) do
  725. begin
  726. if pai(hp^.next)^.typ=ait_section then
  727. lastsec:=pai_section(hp^.next)^.sec;
  728. hp:=pai(hp^.next);
  729. end;
  730. {$ifdef GDB}
  731. { force write of filename }
  732. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  733. includecount:=0;
  734. funcname:=nil;
  735. WriteFileLineInfo(hp^.fileinfo);
  736. {$endif GDB}
  737. if lastsec<>sec_none then
  738. AsmWriteLn(ait_section2str(lastsec));
  739. AsmStartSize:=AsmSize;
  740. end;
  741. end;
  742. ait_marker :
  743. ;
  744. else
  745. internalerror(10000);
  746. end;
  747. hp:=pai(hp^.next);
  748. end;
  749. end;
  750. procedure ti386attasmlist.WriteAsmList;
  751. var
  752. p:dirstr;
  753. n:namestr;
  754. e:extstr;
  755. {$ifdef GDB}
  756. fileinfo : tfileposinfo;
  757. {$endif GDB}
  758. begin
  759. {$ifdef EXTDEBUG}
  760. if assigned(current_module^.mainsource) then
  761. Comment(v_info,'Start writing att-styled assembler output for '+current_module^.mainsource^);
  762. {$endif}
  763. LastSec:=sec_none;
  764. {$ifdef GDB}
  765. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  766. {$endif GDB}
  767. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  768. LastInfile:=nil;
  769. if assigned(current_module^.mainsource) then
  770. fsplit(current_module^.mainsource^,p,n,e)
  771. else
  772. begin
  773. p:=inputdir;
  774. n:=inputfile;
  775. e:=inputextension;
  776. end;
  777. { to get symify to work }
  778. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  779. {$ifdef GDB}
  780. n_line:=n_bssline;
  781. funcname:=nil;
  782. linecount:=1;
  783. includecount:=0;
  784. fileinfo.fileindex:=1;
  785. fileinfo.line:=1;
  786. { Write main file }
  787. WriteFileLineInfo(fileinfo);
  788. {$endif GDB}
  789. AsmStartSize:=AsmSize;
  790. symendcount:=0;
  791. countlabelref:=false;
  792. If (cs_debuginfo in aktmoduleswitches) then
  793. WriteTree(debuglist);
  794. WriteTree(codesegment);
  795. WriteTree(datasegment);
  796. WriteTree(consts);
  797. WriteTree(rttilist);
  798. Writetree(resourcestringlist);
  799. WriteTree(bsssegment);
  800. Writetree(importssection);
  801. { exports are written by DLLTOOL
  802. if we use it so don't insert it twice (PM) }
  803. if not UseDeffileForExport and assigned(exportssection) then
  804. Writetree(exportssection);
  805. Writetree(resourcesection);
  806. {$ifdef GDB}
  807. WriteFileEndInfo;
  808. {$ENDIF}
  809. countlabelref:=true;
  810. AsmLn;
  811. {$ifdef EXTDEBUG}
  812. if assigned(current_module^.mainsource) then
  813. comment(v_info,'Done writing att-styled assembler output for '+current_module^.mainsource^);
  814. {$endif EXTDEBUG}
  815. end;
  816. end.
  817. {
  818. $Log$
  819. Revision 1.29 2000-02-20 21:20:28 marco
  820. * Put some call under Ifdef GDB, so that compiling without -dGDB works
  821. Revision 1.28 2000/02/18 21:54:07 pierre
  822. * avoid LeText if no stabs info
  823. Revision 1.27 2000/02/18 12:31:07 pierre
  824. * Reset file name to empty at end of code section
  825. Revision 1.26 2000/02/09 13:22:42 peter
  826. * log truncated
  827. Revision 1.25 2000/02/07 17:51:20 peter
  828. * quick hack for fnstsww which is not supported under linux as
  829. Revision 1.24 2000/01/28 09:41:39 peter
  830. * fixed fpu suffix parsing for att reader
  831. Revision 1.23 2000/01/07 01:14:18 peter
  832. * updated copyright to 2000
  833. Revision 1.22 1999/12/18 20:00:33 florian
  834. * Bug reported by Marco fixed: Intel assembler reader: fld qword ptr x
  835. was read as fldq x but it must be fldl x
  836. Revision 1.21 1999/12/08 10:39:59 pierre
  837. + allow use of unit var in exports of DLL for win32
  838. by using direct export writing by default instead of use of DEFFILE
  839. that does not allow assembler labels that do not
  840. start with an underscore.
  841. Use -WD to force use of Deffile for Win32 DLL
  842. Revision 1.20 1999/11/06 14:34:16 peter
  843. * truncated log to 20 revs
  844. Revision 1.19 1999/11/02 15:06:56 peter
  845. * import library fixes for win32
  846. * alignment works again
  847. Revision 1.18 1999/10/27 16:11:28 peter
  848. * insns.dat is used to generate all i386*.inc files
  849. Revision 1.17 1999/09/27 23:36:33 peter
  850. * fixed -al with macro's
  851. Revision 1.16 1999/09/21 20:53:21 florian
  852. * fixed 1/s problem from mailing list
  853. Revision 1.15 1999/09/19 20:55:11 florian
  854. * fixed calls to procedures with manglednames=255 chars
  855. (taking the address of such a procedure would still cause a problem!)
  856. Revision 1.14 1999/09/10 18:48:00 florian
  857. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  858. * most things for stored properties fixed
  859. Revision 1.13 1999/09/02 17:07:38 florian
  860. * problems with -Or fixed: tdef.isfpuregable was wrong!
  861. Revision 1.12 1999/08/25 16:03:46 peter
  862. * symbol name is now written using separate asmwrite() calls to overcome
  863. > 255 char strings
  864. Revision 1.11 1999/08/25 11:59:32 jonas
  865. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  866. Revision 1.10 1999/08/13 15:44:57 peter
  867. * first things to include lineinfo in the executable
  868. Revision 1.9 1999/08/10 12:26:20 pierre
  869. * avoid double .edata section if using DLLTOOL
  870. Revision 1.8 1999/08/04 00:22:34 florian
  871. * renamed i386asm and i386base to cpuasm and cpubase
  872. Revision 1.7 1999/07/30 12:26:07 peter
  873. * write .size only for linux
  874. Revision 1.6 1999/07/29 20:53:56 peter
  875. * write .size also
  876. }