ag386att.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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) or
  268. (cs_gdb_lineinfo in aktglobalswitches)) then
  269. exit;
  270. { file changed ? (must be before line info) }
  271. if (fileinfo.fileindex<>0) and
  272. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  273. begin
  274. infile:=current_module^.sourcefiles^.get_file(fileinfo.fileindex);
  275. if assigned(infile) then
  276. begin
  277. if includecount=0 then
  278. curr_n:=n_sourcefile
  279. else
  280. curr_n:=n_includefile;
  281. if (infile^.path^<>'') then
  282. begin
  283. AsmWriteLn(#9'.stabs "'+lower(BsToSlash(FixPath(infile^.path^,false)))+'",'+
  284. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  285. end;
  286. AsmWriteLn(#9'.stabs "'+lower(FixFileName(infile^.name^))+'",'+
  287. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  288. AsmWriteLn('Ltext'+ToStr(IncludeCount)+':');
  289. inc(includecount);
  290. end;
  291. end;
  292. { line changed ? }
  293. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  294. begin
  295. if (n_line=n_textline) and assigned(funcname) and
  296. (target_os.use_function_relative_addresses) then
  297. begin
  298. AsmWriteLn(target_asm.labelprefix+'l'+tostr(linecount)+':');
  299. AsmWrite(#9'.stabn '+tostr(n_line)+',0,'+tostr(fileinfo.line)+','+
  300. target_asm.labelprefix+'l'+tostr(linecount)+' - ');
  301. AsmWritePChar(FuncName);
  302. AsmLn;
  303. inc(linecount);
  304. end
  305. else
  306. AsmWriteLn(#9'.stabd'#9+tostr(n_line)+',0,'+tostr(fileinfo.line));
  307. end;
  308. stabslastfileinfo:=fileinfo;
  309. end;
  310. procedure ti386attasmlist.WriteFileEndInfo;
  311. begin
  312. if not ((cs_debuginfo in aktmoduleswitches) or
  313. (cs_gdb_lineinfo in aktglobalswitches)) then
  314. exit;
  315. AsmLn;
  316. AsmWriteLn(ait_section2str(sec_code));
  317. AsmWriteLn(#9'.stabs "",'+tostr(n_sourcefile)+',0,0,Letext');
  318. AsmWriteLn('Letext:');
  319. end;
  320. {$endif GDB}
  321. procedure ti386attasmlist.WriteTree(p:paasmoutput);
  322. const
  323. allocstr : array[boolean] of string[10]=(' released',' allocated');
  324. nolinetai =[ait_label,
  325. ait_regalloc,ait_tempalloc,
  326. ait_stabn,ait_stabs,ait_section,
  327. ait_cut,ait_marker,ait_align,ait_stab_function_name];
  328. type
  329. t80bitarray = array[0..9] of byte;
  330. t64bitarray = array[0..7] of byte;
  331. t32bitarray = array[0..3] of byte;
  332. var
  333. ch : char;
  334. hp : pai;
  335. consttyp : tait;
  336. s : string;
  337. found : boolean;
  338. i,pos,l : longint;
  339. InlineLevel : longint;
  340. co : comp;
  341. sin : single;
  342. d : double;
  343. e : extended;
  344. op : tasmop;
  345. calljmp,
  346. do_line : boolean;
  347. sep : char;
  348. begin
  349. if not assigned(p) then
  350. exit;
  351. InlineLevel:=0;
  352. { lineinfo is only needed for codesegment (PFV) }
  353. do_line:=(cs_asm_source in aktglobalswitches) or
  354. ((cs_lineinfo in aktmoduleswitches)
  355. and (p=codesegment));
  356. hp:=pai(p^.first);
  357. while assigned(hp) do
  358. begin
  359. aktfilepos:=hp^.fileinfo;
  360. if not(hp^.typ in nolinetai) then
  361. begin
  362. {$ifdef GDB}
  363. { write stabs }
  364. if (cs_debuginfo in aktmoduleswitches) or
  365. (cs_gdb_lineinfo in aktglobalswitches) then
  366. WriteFileLineInfo(hp^.fileinfo);
  367. {$endif GDB}
  368. if do_line then
  369. begin
  370. { load infile }
  371. if lastfileinfo.fileindex<>hp^.fileinfo.fileindex then
  372. begin
  373. infile:=current_module^.sourcefiles^.get_file(hp^.fileinfo.fileindex);
  374. if assigned(infile) then
  375. begin
  376. { open only if needed !! }
  377. if (cs_asm_source in aktglobalswitches) then
  378. infile^.open;
  379. end;
  380. { avoid unnecessary reopens of the same file !! }
  381. lastfileinfo.fileindex:=hp^.fileinfo.fileindex;
  382. { be sure to change line !! }
  383. lastfileinfo.line:=-1;
  384. end;
  385. { write source }
  386. if (cs_asm_source in aktglobalswitches) and
  387. assigned(infile) then
  388. begin
  389. if (infile<>lastinfile) then
  390. begin
  391. AsmWriteLn(target_asm.comment+'['+infile^.name^+']');
  392. if assigned(lastinfile) then
  393. lastinfile^.close;
  394. end;
  395. if (hp^.fileinfo.line<>lastfileinfo.line) and
  396. ((hp^.fileinfo.line<infile^.maxlinebuf) or (InlineLevel>0)) then
  397. begin
  398. if (hp^.fileinfo.line<>0) and
  399. ((infile^.linebuf^[hp^.fileinfo.line]>=0) or (InlineLevel>0)) then
  400. AsmWriteLn(target_asm.comment+'['+tostr(hp^.fileinfo.line)+'] '+
  401. fixline(infile^.GetLineStr(hp^.fileinfo.line)));
  402. { set it to a negative value !
  403. to make that is has been read already !! PM }
  404. if (infile^.linebuf^[hp^.fileinfo.line]>=0) then
  405. infile^.linebuf^[hp^.fileinfo.line]:=-infile^.linebuf^[hp^.fileinfo.line]-1;
  406. end;
  407. end;
  408. {$ifdef LINEINFO}
  409. { lineinfo }
  410. if (cs_lineinfo in aktmoduleswitches) then
  411. begin
  412. if (infile<>lastinfile) then
  413. begin
  414. lineinfolist^.concat(new(pai_const(init_8bit
  415. end
  416. else
  417. begin
  418. end;
  419. end;
  420. {$endif LINEINFO}
  421. lastfileinfo:=hp^.fileinfo;
  422. lastinfile:=infile;
  423. end;
  424. end;
  425. case hp^.typ of
  426. ait_comment :
  427. Begin
  428. AsmWrite(target_asm.comment);
  429. AsmWritePChar(pai_asm_comment(hp)^.str);
  430. AsmLn;
  431. End;
  432. ait_regalloc :
  433. begin
  434. if (cs_asm_regalloc in aktglobalswitches) then
  435. AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+
  436. allocstr[pairegalloc(hp)^.allocation]);
  437. end;
  438. ait_tempalloc :
  439. begin
  440. if (cs_asm_tempalloc in aktglobalswitches) then
  441. AsmWriteLn(target_asm.comment+'Temp '+tostr(paitempalloc(hp)^.temppos)+','+
  442. tostr(paitempalloc(hp)^.tempsize)+allocstr[paitempalloc(hp)^.allocation]);
  443. end;
  444. ait_align :
  445. begin
  446. AsmWrite(#9'.balign '+tostr(pai_align(hp)^.aligntype));
  447. if pai_align(hp)^.use_op then
  448. AsmWrite(','+tostr(pai_align(hp)^.fillop));
  449. AsmLn;
  450. end;
  451. ait_section :
  452. begin
  453. if pai_section(hp)^.sec<>sec_none then
  454. begin
  455. AsmLn;
  456. AsmWriteLn(ait_section2str(pai_section(hp)^.sec));
  457. {$ifdef GDB}
  458. lastfileinfo.line:=-1;
  459. {$endif GDB}
  460. end;
  461. end;
  462. ait_datablock :
  463. begin
  464. if pai_datablock(hp)^.is_global then
  465. AsmWrite(#9'.comm'#9)
  466. else
  467. AsmWrite(#9'.lcomm'#9);
  468. AsmWrite(pai_datablock(hp)^.sym^.name);
  469. AsmWriteLn(','+tostr(pai_datablock(hp)^.size));
  470. end;
  471. ait_const_32bit,
  472. ait_const_16bit,
  473. ait_const_8bit :
  474. begin
  475. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  476. consttyp:=hp^.typ;
  477. l:=0;
  478. repeat
  479. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  480. if found then
  481. begin
  482. hp:=Pai(hp^.next);
  483. s:=','+tostr(pai_const(hp)^.value);
  484. AsmWrite(s);
  485. inc(l,length(s));
  486. end;
  487. until (not found) or (l>line_length);
  488. AsmLn;
  489. end;
  490. ait_const_symbol :
  491. begin
  492. AsmWrite(#9'.long'#9+pai_const_symbol(hp)^.sym^.name);
  493. if pai_const_symbol(hp)^.offset>0 then
  494. AsmWrite('+'+tostr(pai_const_symbol(hp)^.offset))
  495. else if pai_const_symbol(hp)^.offset<0 then
  496. AsmWrite(tostr(pai_const_symbol(hp)^.offset));
  497. AsmLn;
  498. end;
  499. ait_const_rva :
  500. AsmWriteLn(#9'.rva'#9+pai_const_symbol(hp)^.sym^.name);
  501. ait_real_80bit :
  502. begin
  503. if do_line then
  504. AsmWriteLn(target_asm.comment+extended2str(pai_real_80bit(hp)^.value));
  505. { Make sure e is a extended type, bestreal could be
  506. a different type (bestreal) !! (PFV) }
  507. e:=pai_real_80bit(hp)^.value;
  508. AsmWrite(#9'.byte'#9);
  509. for i:=0 to 9 do
  510. begin
  511. if i<>0 then
  512. AsmWrite(',');
  513. AsmWrite(tostr(t80bitarray(e)[i]));
  514. end;
  515. AsmLn;
  516. end;
  517. ait_real_64bit :
  518. begin
  519. if do_line then
  520. AsmWriteLn(target_asm.comment+double2str(pai_real_64bit(hp)^.value));
  521. d:=pai_real_64bit(hp)^.value;
  522. AsmWrite(#9'.byte'#9);
  523. for i:=0 to 7 do
  524. begin
  525. if i<>0 then
  526. AsmWrite(',');
  527. AsmWrite(tostr(t64bitarray(d)[i]));
  528. end;
  529. AsmLn;
  530. end;
  531. ait_real_32bit :
  532. begin
  533. if do_line then
  534. AsmWriteLn(target_asm.comment+single2str(pai_real_32bit(hp)^.value));
  535. sin:=pai_real_32bit(hp)^.value;
  536. AsmWrite(#9'.byte'#9);
  537. for i:=0 to 3 do
  538. begin
  539. if i<>0 then
  540. AsmWrite(',');
  541. AsmWrite(tostr(t32bitarray(sin)[i]));
  542. end;
  543. AsmLn;
  544. end;
  545. ait_comp_64bit :
  546. begin
  547. if do_line then
  548. AsmWriteLn(target_asm.comment+comp2str(pai_comp_64bit(hp)^.value));
  549. AsmWrite(#9'.byte'#9);
  550. {$ifdef FPC}
  551. co:=comp(pai_comp_64bit(hp)^.value);
  552. {$else}
  553. co:=pai_comp_64bit(hp)^.value;
  554. {$endif}
  555. for i:=0 to 7 do
  556. begin
  557. if i<>0 then
  558. AsmWrite(',');
  559. AsmWrite(tostr(t64bitarray(co)[i]));
  560. end;
  561. AsmLn;
  562. end;
  563. ait_direct :
  564. begin
  565. AsmWritePChar(pai_direct(hp)^.str);
  566. AsmLn;
  567. {$IfDef GDB}
  568. if strpos(pai_direct(hp)^.str,'.data')<>nil then
  569. n_line:=n_dataline
  570. else if strpos(pai_direct(hp)^.str,'.text')<>nil then
  571. n_line:=n_textline
  572. else if strpos(pai_direct(hp)^.str,'.bss')<>nil then
  573. n_line:=n_bssline;
  574. {$endif GDB}
  575. end;
  576. ait_string :
  577. begin
  578. pos:=0;
  579. for i:=1 to pai_string(hp)^.len do
  580. begin
  581. if pos=0 then
  582. begin
  583. AsmWrite(#9'.ascii'#9'"');
  584. pos:=20;
  585. end;
  586. ch:=pai_string(hp)^.str[i-1];
  587. case ch of
  588. #0, {This can't be done by range, because a bug in FPC}
  589. #1..#31,
  590. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  591. '"' : s:='\"';
  592. '\' : s:='\\';
  593. else
  594. s:=ch;
  595. end;
  596. AsmWrite(s);
  597. inc(pos,length(s));
  598. if (pos>line_length) or (i=pai_string(hp)^.len) then
  599. begin
  600. AsmWriteLn('"');
  601. pos:=0;
  602. end;
  603. end;
  604. end;
  605. ait_label :
  606. begin
  607. if (pai_label(hp)^.l^.is_used) then
  608. begin
  609. if pai_label(hp)^.l^.typ=AS_GLOBAL then
  610. begin
  611. AsmWrite('.globl'#9);
  612. AsmWriteLn(pai_label(hp)^.l^.name);
  613. end;
  614. AsmWrite(pai_label(hp)^.l^.name);
  615. AsmWriteLn(':');
  616. end;
  617. end;
  618. ait_symbol :
  619. begin
  620. if pai_symbol(hp)^.is_global then
  621. begin
  622. AsmWrite('.globl'#9);
  623. AsmWriteLn(pai_symbol(hp)^.sym^.name);
  624. end;
  625. if target_info.target=target_i386_linux then
  626. begin
  627. AsmWrite(#9'.type'#9);
  628. AsmWrite(pai_symbol(hp)^.sym^.name);
  629. if assigned(pai(hp^.next)) and
  630. (pai(hp^.next)^.typ in [ait_const_symbol,ait_const_rva,
  631. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  632. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  633. AsmWriteLn(',@object')
  634. else
  635. AsmWriteLn(',@function');
  636. if pai_symbol(hp)^.sym^.size>0 then
  637. begin
  638. AsmWrite(#9'.size'#9);
  639. AsmWrite(pai_symbol(hp)^.sym^.name);
  640. AsmWrite(', ');
  641. AsmWriteLn(tostr(pai_symbol(hp)^.sym^.size));
  642. end;
  643. end;
  644. AsmWrite(pai_symbol(hp)^.sym^.name);
  645. AsmWriteLn(':');
  646. end;
  647. ait_symbol_end :
  648. begin
  649. if target_info.target=target_i386_linux then
  650. begin
  651. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  652. inc(symendcount);
  653. AsmWriteLn(s+':');
  654. AsmWrite(#9'.size'#9);
  655. AsmWrite(pai_symbol(hp)^.sym^.name);
  656. AsmWrite(', '+s+' - ');
  657. AsmWriteLn(pai_symbol(hp)^.sym^.name);
  658. end;
  659. end;
  660. ait_instruction :
  661. begin
  662. op:=paicpu(hp)^.opcode;
  663. calljmp:=is_calljmp(op);
  664. { call maybe not translated to call }
  665. s:=#9+att_op2str[op]+cond2str[paicpu(hp)^.condition];
  666. { suffix needed ? fnstsw,fldcw don't support suffixes
  667. with binutils 2.9.5 under linux }
  668. if (not calljmp) and
  669. (att_needsuffix[op]<>AttSufNONE) and
  670. (op<>A_FNSTSW) and (op<>A_FSTSW) and
  671. (op<>A_FNSTCW) and (op<>A_FSTCW) and
  672. (op<>A_FLDCW) and
  673. not(
  674. (paicpu(hp)^.oper[0].typ=top_reg) and
  675. (paicpu(hp)^.oper[0].reg in [R_ST..R_ST7])
  676. ) then
  677. s:=s+att_opsize2str[paicpu(hp)^.opsize];
  678. { process operands }
  679. if paicpu(hp)^.ops<>0 then
  680. begin
  681. { call and jmp need an extra handling }
  682. { this code is only called if jmp isn't a labeled instruction }
  683. { quick hack to overcome a problem with manglednames=255 chars }
  684. if calljmp then
  685. begin
  686. AsmWrite(s+#9);
  687. s:=+getopstr_jmp(paicpu(hp)^.oper[0]);
  688. end
  689. else
  690. begin
  691. for i:=0 to paicpu(hp)^.ops-1 do
  692. begin
  693. if i=0 then
  694. sep:=#9
  695. else
  696. sep:=',';
  697. s:=s+sep+getopstr(paicpu(hp)^.oper[i])
  698. end;
  699. end;
  700. end;
  701. AsmWriteLn(s);
  702. end;
  703. {$ifdef GDB}
  704. ait_stabs :
  705. begin
  706. AsmWrite(#9'.stabs ');
  707. AsmWritePChar(pai_stabs(hp)^.str);
  708. AsmLn;
  709. end;
  710. ait_stabn :
  711. begin
  712. AsmWrite(#9'.stabn ');
  713. AsmWritePChar(pai_stabn(hp)^.str);
  714. AsmLn;
  715. end;
  716. ait_force_line :
  717. stabslastfileinfo.line:=0;
  718. ait_stab_function_name:
  719. funcname:=pai_stab_function_name(hp)^.str;
  720. {$endif GDB}
  721. ait_cut :
  722. begin
  723. if SmartAsm then
  724. begin
  725. { only reset buffer if nothing has changed }
  726. if AsmSize=AsmStartSize then
  727. AsmClear
  728. else
  729. begin
  730. AsmClose;
  731. DoAssemble;
  732. AsmCreate(pai_cut(hp)^.place);
  733. end;
  734. { avoid empty files }
  735. while assigned(hp^.next) and (pai(hp^.next)^.typ in [ait_cut,ait_section,ait_comment]) do
  736. begin
  737. if pai(hp^.next)^.typ=ait_section then
  738. lastsec:=pai_section(hp^.next)^.sec;
  739. hp:=pai(hp^.next);
  740. end;
  741. {$ifdef GDB}
  742. { force write of filename }
  743. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  744. includecount:=0;
  745. funcname:=nil;
  746. WriteFileLineInfo(hp^.fileinfo);
  747. {$endif GDB}
  748. if lastsec<>sec_none then
  749. AsmWriteLn(ait_section2str(lastsec));
  750. AsmStartSize:=AsmSize;
  751. end;
  752. end;
  753. ait_marker :
  754. if pai_marker(hp)^.kind=InlineStart then
  755. inc(InlineLevel)
  756. else if pai_marker(hp)^.kind=InlineEnd then
  757. dec(InlineLevel);
  758. else
  759. internalerror(10000);
  760. end;
  761. hp:=pai(hp^.next);
  762. end;
  763. end;
  764. procedure ti386attasmlist.WriteAsmList;
  765. var
  766. p:dirstr;
  767. n:namestr;
  768. e:extstr;
  769. {$ifdef GDB}
  770. fileinfo : tfileposinfo;
  771. {$endif GDB}
  772. begin
  773. {$ifdef EXTDEBUG}
  774. if assigned(current_module^.mainsource) then
  775. Comment(v_info,'Start writing att-styled assembler output for '+current_module^.mainsource^);
  776. {$endif}
  777. LastSec:=sec_none;
  778. {$ifdef GDB}
  779. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  780. {$endif GDB}
  781. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  782. LastInfile:=nil;
  783. if assigned(current_module^.mainsource) then
  784. fsplit(current_module^.mainsource^,p,n,e)
  785. else
  786. begin
  787. p:=inputdir;
  788. n:=inputfile;
  789. e:=inputextension;
  790. end;
  791. { to get symify to work }
  792. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  793. {$ifdef GDB}
  794. n_line:=n_bssline;
  795. funcname:=nil;
  796. linecount:=1;
  797. includecount:=0;
  798. fileinfo.fileindex:=1;
  799. fileinfo.line:=1;
  800. { Write main file }
  801. WriteFileLineInfo(fileinfo);
  802. {$endif GDB}
  803. AsmStartSize:=AsmSize;
  804. symendcount:=0;
  805. countlabelref:=false;
  806. If (cs_debuginfo in aktmoduleswitches) then
  807. WriteTree(debuglist);
  808. WriteTree(codesegment);
  809. WriteTree(datasegment);
  810. WriteTree(consts);
  811. WriteTree(rttilist);
  812. Writetree(resourcestringlist);
  813. WriteTree(bsssegment);
  814. Writetree(importssection);
  815. { exports are written by DLLTOOL
  816. if we use it so don't insert it twice (PM) }
  817. if not UseDeffileForExport and assigned(exportssection) then
  818. Writetree(exportssection);
  819. Writetree(resourcesection);
  820. {$ifdef GDB}
  821. WriteFileEndInfo;
  822. {$ENDIF}
  823. countlabelref:=true;
  824. AsmLn;
  825. {$ifdef EXTDEBUG}
  826. if assigned(current_module^.mainsource) then
  827. comment(v_info,'Done writing att-styled assembler output for '+current_module^.mainsource^);
  828. {$endif EXTDEBUG}
  829. end;
  830. end.
  831. {
  832. $Log$
  833. Revision 1.33 2000-04-12 12:42:28 pierre
  834. * fix the -g-l option
  835. Revision 1.32 2000/04/06 07:04:50 pierre
  836. + generate line stabs if cs_gdb_lineinfo is aktglobalswitches
  837. Revision 1.31 2000/04/01 14:18:03 peter
  838. * don't write suffix for fldcw
  839. Revision 1.30 2000/02/29 23:56:49 pierre
  840. * write source line again for inline procs
  841. Revision 1.29 2000/02/20 21:20:28 marco
  842. * Put some call under Ifdef GDB, so that compiling without -dGDB works
  843. Revision 1.28 2000/02/18 21:54:07 pierre
  844. * avoid LeText if no stabs info
  845. Revision 1.27 2000/02/18 12:31:07 pierre
  846. * Reset file name to empty at end of code section
  847. Revision 1.26 2000/02/09 13:22:42 peter
  848. * log truncated
  849. Revision 1.25 2000/02/07 17:51:20 peter
  850. * quick hack for fnstsww which is not supported under linux as
  851. Revision 1.24 2000/01/28 09:41:39 peter
  852. * fixed fpu suffix parsing for att reader
  853. Revision 1.23 2000/01/07 01:14:18 peter
  854. * updated copyright to 2000
  855. Revision 1.22 1999/12/18 20:00:33 florian
  856. * Bug reported by Marco fixed: Intel assembler reader: fld qword ptr x
  857. was read as fldq x but it must be fldl x
  858. Revision 1.21 1999/12/08 10:39:59 pierre
  859. + allow use of unit var in exports of DLL for win32
  860. by using direct export writing by default instead of use of DEFFILE
  861. that does not allow assembler labels that do not
  862. start with an underscore.
  863. Use -WD to force use of Deffile for Win32 DLL
  864. Revision 1.20 1999/11/06 14:34:16 peter
  865. * truncated log to 20 revs
  866. Revision 1.19 1999/11/02 15:06:56 peter
  867. * import library fixes for win32
  868. * alignment works again
  869. Revision 1.18 1999/10/27 16:11:28 peter
  870. * insns.dat is used to generate all i386*.inc files
  871. Revision 1.17 1999/09/27 23:36:33 peter
  872. * fixed -al with macro's
  873. Revision 1.16 1999/09/21 20:53:21 florian
  874. * fixed 1/s problem from mailing list
  875. Revision 1.15 1999/09/19 20:55:11 florian
  876. * fixed calls to procedures with manglednames=255 chars
  877. (taking the address of such a procedure would still cause a problem!)
  878. Revision 1.14 1999/09/10 18:48:00 florian
  879. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  880. * most things for stored properties fixed
  881. Revision 1.13 1999/09/02 17:07:38 florian
  882. * problems with -Or fixed: tdef.isfpuregable was wrong!
  883. Revision 1.12 1999/08/25 16:03:46 peter
  884. * symbol name is now written using separate asmwrite() calls to overcome
  885. > 255 char strings
  886. Revision 1.11 1999/08/25 11:59:32 jonas
  887. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  888. Revision 1.10 1999/08/13 15:44:57 peter
  889. * first things to include lineinfo in the executable
  890. Revision 1.9 1999/08/10 12:26:20 pierre
  891. * avoid double .edata section if using DLLTOOL
  892. Revision 1.8 1999/08/04 00:22:34 florian
  893. * renamed i386asm and i386base to cpuasm and cpubase
  894. Revision 1.7 1999/07/30 12:26:07 peter
  895. * write .size only for linux
  896. Revision 1.6 1999/07/29 20:53:56 peter
  897. * write .size also
  898. }