ag386att.pas 30 KB

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