ag386att.pas 30 KB

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