ag386att.pas 31 KB

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