ag386att.pas 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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. unit ag386att;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cclasses,
  23. globals,
  24. aasm,assemble;
  25. type
  26. T386ATTAssembler=class(texternalassembler)
  27. procedure WriteTree(p:TAAsmoutput);override;
  28. procedure WriteAsmList;override;
  29. {$ifdef GDB}
  30. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  31. procedure WriteFileEndInfo;
  32. {$endif}
  33. end;
  34. implementation
  35. uses
  36. {$ifdef Delphi}
  37. sysutils,
  38. dmisc,
  39. {$else Delphi}
  40. strings,
  41. dos,
  42. {$endif Delphi}
  43. cutils,globtype,systems,
  44. fmodule,finput,verbose,cpubase,cpuasm
  45. {$ifdef GDB}
  46. ,gdb
  47. {$endif GDB}
  48. ;
  49. const
  50. line_length = 70;
  51. var
  52. {$ifdef GDB}
  53. n_line : byte; { different types of source lines }
  54. linecount,
  55. includecount : longint;
  56. funcname : pchar;
  57. stabslastfileinfo : tfileposinfo;
  58. {$endif}
  59. lastsec : tsection; { last section type written }
  60. lastfileinfo : tfileposinfo;
  61. infile,
  62. lastinfile : tinputfile;
  63. symendcount : longint;
  64. function fixline(s:string):string;
  65. {
  66. return s with all leading and ending spaces and tabs removed
  67. }
  68. var
  69. i,j,k : longint;
  70. begin
  71. i:=length(s);
  72. while (i>0) and (s[i] in [#9,' ']) do
  73. dec(i);
  74. j:=1;
  75. while (j<i) and (s[j] in [#9,' ']) do
  76. inc(j);
  77. for k:=j to i do
  78. if s[k] in [#0..#31,#127..#255] then
  79. s[k]:='.';
  80. fixline:=Copy(s,j,i-j+1);
  81. end;
  82. function single2str(d : single) : string;
  83. var
  84. hs : string;
  85. begin
  86. str(d,hs);
  87. { replace space with + }
  88. if hs[1]=' ' then
  89. hs[1]:='+';
  90. single2str:='0d'+hs
  91. end;
  92. function double2str(d : double) : string;
  93. var
  94. hs : string;
  95. begin
  96. str(d,hs);
  97. { replace space with + }
  98. if hs[1]=' ' then
  99. hs[1]:='+';
  100. double2str:='0d'+hs
  101. end;
  102. function extended2str(e : extended) : string;
  103. var
  104. hs : string;
  105. begin
  106. str(e,hs);
  107. { replace space with + }
  108. if hs[1]=' ' then
  109. hs[1]:='+';
  110. extended2str:='0d'+hs
  111. end;
  112. type
  113. pdouble = ^double;
  114. function comp2str(d : bestreal) : string;
  115. var
  116. c : comp;
  117. dd : pdouble;
  118. begin
  119. {$ifdef FPC}
  120. c:=comp(d);
  121. {$else}
  122. c:=d;
  123. {$endif}
  124. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  125. comp2str:=double2str(dd^);
  126. end;
  127. function getreferencestring(var ref : treference) : string;
  128. var
  129. s : string;
  130. begin
  131. if ref.is_immediate then
  132. begin
  133. internalerror(1000101);
  134. exit;
  135. end
  136. else
  137. begin
  138. with ref do
  139. begin
  140. inc(offset,offsetfixup);
  141. offsetfixup:=0;
  142. { have we a segment prefix ? }
  143. { These are probably not correctly handled under GAS }
  144. { should be replaced by coding the segment override }
  145. { directly! - DJGPP FAQ }
  146. if segment<>R_NO then
  147. s:=att_reg2str[segment]+':'
  148. else
  149. s:='';
  150. if assigned(symbol) then
  151. s:=s+symbol.name;
  152. if offset<0 then
  153. s:=s+tostr(offset)
  154. else
  155. if (offset>0) then
  156. begin
  157. if assigned(symbol) then
  158. s:=s+'+'+tostr(offset)
  159. else
  160. s:=s+tostr(offset);
  161. end
  162. else if (index=R_NO) and (base=R_NO) and not assigned(symbol) then
  163. s:=s+'0';
  164. if (index<>R_NO) and (base=R_NO) then
  165. begin
  166. s:=s+'(,'+att_reg2str[index];
  167. if scalefactor<>0 then
  168. s:=s+','+tostr(scalefactor)+')'
  169. else
  170. s:=s+')';
  171. end
  172. else
  173. if (index=R_NO) and (base<>R_NO) then
  174. s:=s+'('+att_reg2str[base]+')'
  175. else
  176. if (index<>R_NO) and (base<>R_NO) then
  177. begin
  178. s:=s+'('+att_reg2str[base]+','+att_reg2str[index];
  179. if scalefactor<>0 then
  180. s:=s+','+tostr(scalefactor)+')'
  181. else
  182. s := s+')';
  183. end;
  184. end;
  185. end;
  186. getreferencestring:=s;
  187. end;
  188. function getopstr(const o:toper) : string;
  189. var
  190. hs : string;
  191. begin
  192. case o.typ of
  193. top_reg :
  194. getopstr:=att_reg2str[o.reg];
  195. top_ref :
  196. getopstr:=getreferencestring(o.ref^);
  197. top_const :
  198. getopstr:='$'+tostr(o.val);
  199. top_symbol :
  200. begin
  201. if assigned(o.sym) then
  202. hs:='$'+o.sym.name
  203. else
  204. hs:='$';
  205. if o.symofs>0 then
  206. hs:=hs+'+'+tostr(o.symofs)
  207. else
  208. if o.symofs<0 then
  209. hs:=hs+tostr(o.symofs)
  210. else
  211. if not(assigned(o.sym)) then
  212. hs:=hs+'0';
  213. getopstr:=hs;
  214. end;
  215. else
  216. internalerror(10001);
  217. end;
  218. end;
  219. function getopstr_jmp(const o:toper) : string;
  220. var
  221. hs : string;
  222. begin
  223. case o.typ of
  224. top_reg :
  225. getopstr_jmp:='*'+att_reg2str[o.reg];
  226. top_ref :
  227. getopstr_jmp:='*'+getreferencestring(o.ref^);
  228. top_const :
  229. getopstr_jmp:=tostr(o.val);
  230. top_symbol :
  231. begin
  232. hs:=o.sym.name;
  233. if o.symofs>0 then
  234. hs:=hs+'+'+tostr(o.symofs)
  235. else
  236. if o.symofs<0 then
  237. hs:=hs+tostr(o.symofs);
  238. getopstr_jmp:=hs;
  239. end;
  240. else
  241. internalerror(10001);
  242. end;
  243. end;
  244. {****************************************************************************
  245. TI386ATTASMOUTPUT
  246. ****************************************************************************}
  247. const
  248. ait_const2str : array[ait_const_32bit..ait_const_8bit] of string[8]=
  249. (#9'.long'#9,#9'.short'#9,#9'.byte'#9);
  250. function ait_section2str(s:tsection):string;
  251. begin
  252. ait_section2str:=target_asm.secnames[s];
  253. {$ifdef GDB}
  254. { this is needed for line info in data }
  255. funcname:=nil;
  256. case s of
  257. sec_code : n_line:=n_textline;
  258. sec_data : n_line:=n_dataline;
  259. sec_bss : n_line:=n_bssline;
  260. else n_line:=n_dataline;
  261. end;
  262. {$endif GDB}
  263. LastSec:=s;
  264. end;
  265. {$ifdef GDB}
  266. procedure T386ATTAssembler.WriteFileLineInfo(var fileinfo : tfileposinfo);
  267. var
  268. curr_n : byte;
  269. begin
  270. if not ((cs_debuginfo in aktmoduleswitches) or
  271. (cs_gdb_lineinfo in aktglobalswitches)) then
  272. exit;
  273. { file changed ? (must be before line info) }
  274. if (fileinfo.fileindex<>0) and
  275. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  276. begin
  277. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  278. if assigned(infile) then
  279. begin
  280. if includecount=0 then
  281. curr_n:=n_sourcefile
  282. else
  283. curr_n:=n_includefile;
  284. if (infile.path^<>'') then
  285. begin
  286. AsmWriteLn(#9'.stabs "'+lower(BsToSlash(FixPath(infile.path^,false)))+'",'+
  287. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  288. end;
  289. AsmWriteLn(#9'.stabs "'+lower(FixFileName(infile.name^))+'",'+
  290. tostr(curr_n)+',0,0,'+'Ltext'+ToStr(IncludeCount));
  291. AsmWriteLn('Ltext'+ToStr(IncludeCount)+':');
  292. inc(includecount);
  293. end;
  294. end;
  295. { line changed ? }
  296. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  297. begin
  298. if (n_line=n_textline) and assigned(funcname) and
  299. (target_info.use_function_relative_addresses) then
  300. begin
  301. AsmWriteLn(target_asm.labelprefix+'l'+tostr(linecount)+':');
  302. AsmWrite(#9'.stabn '+tostr(n_line)+',0,'+tostr(fileinfo.line)+','+
  303. target_asm.labelprefix+'l'+tostr(linecount)+' - ');
  304. AsmWritePChar(FuncName);
  305. AsmLn;
  306. inc(linecount);
  307. end
  308. else
  309. AsmWriteLn(#9'.stabd'#9+tostr(n_line)+',0,'+tostr(fileinfo.line));
  310. end;
  311. stabslastfileinfo:=fileinfo;
  312. end;
  313. procedure T386ATTAssembler.WriteFileEndInfo;
  314. begin
  315. if not ((cs_debuginfo in aktmoduleswitches) or
  316. (cs_gdb_lineinfo in aktglobalswitches)) then
  317. exit;
  318. AsmLn;
  319. AsmWriteLn(ait_section2str(sec_code));
  320. AsmWriteLn(#9'.stabs "",'+tostr(n_sourcefile)+',0,0,Letext');
  321. AsmWriteLn('Letext:');
  322. end;
  323. {$endif GDB}
  324. procedure T386ATTAssembler.WriteTree(p:TAAsmoutput);
  325. const
  326. allocstr : array[boolean] of string[10]=(' released',' allocated');
  327. nolinetai =[ait_label,
  328. ait_regalloc,ait_tempalloc,
  329. ait_stabn,ait_stabs,ait_section,
  330. ait_cut,ait_marker,ait_align,ait_stab_function_name];
  331. type
  332. t80bitarray = array[0..9] of byte;
  333. t64bitarray = array[0..7] of byte;
  334. t32bitarray = array[0..3] of byte;
  335. var
  336. ch : char;
  337. hp : tai;
  338. consttyp : tait;
  339. s : string;
  340. found : boolean;
  341. i,pos,l : longint;
  342. InlineLevel : longint;
  343. co : comp;
  344. sin : single;
  345. d : double;
  346. e : extended;
  347. op : tasmop;
  348. calljmp,
  349. do_line : boolean;
  350. sep : char;
  351. begin
  352. if not assigned(p) then
  353. exit;
  354. InlineLevel:=0;
  355. { lineinfo is only needed for codesegment (PFV) }
  356. do_line:=(cs_asm_source in aktglobalswitches) or
  357. ((cs_lineinfo in aktmoduleswitches)
  358. and (p=codesegment));
  359. hp:=tai(p.first);
  360. while assigned(hp) do
  361. begin
  362. aktfilepos:=hp.fileinfo;
  363. if not(hp.typ in nolinetai) then
  364. begin
  365. {$ifdef GDB}
  366. { write stabs }
  367. if (cs_debuginfo in aktmoduleswitches) or
  368. (cs_gdb_lineinfo in aktglobalswitches) then
  369. WriteFileLineInfo(hp.fileinfo);
  370. {$endif GDB}
  371. if do_line then
  372. begin
  373. { load infile }
  374. if lastfileinfo.fileindex<>hp.fileinfo.fileindex then
  375. begin
  376. infile:=current_module.sourcefiles.get_file(hp.fileinfo.fileindex);
  377. if assigned(infile) then
  378. begin
  379. { open only if needed !! }
  380. if (cs_asm_source in aktglobalswitches) then
  381. infile.open;
  382. end;
  383. { avoid unnecessary reopens of the same file !! }
  384. lastfileinfo.fileindex:=hp.fileinfo.fileindex;
  385. { be sure to change line !! }
  386. lastfileinfo.line:=-1;
  387. end;
  388. { write source }
  389. if (cs_asm_source in aktglobalswitches) and
  390. assigned(infile) then
  391. begin
  392. if (infile<>lastinfile) then
  393. begin
  394. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  395. if assigned(lastinfile) then
  396. lastinfile.close;
  397. end;
  398. if (hp.fileinfo.line<>lastfileinfo.line) and
  399. ((hp.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  400. begin
  401. if (hp.fileinfo.line<>0) and
  402. ((infile.linebuf^[hp.fileinfo.line]>=0) or (InlineLevel>0)) then
  403. AsmWriteLn(target_asm.comment+'['+tostr(hp.fileinfo.line)+'] '+
  404. fixline(infile.GetLineStr(hp.fileinfo.line)));
  405. { set it to a negative value !
  406. to make that is has been read already !! PM }
  407. if (infile.linebuf^[hp.fileinfo.line]>=0) then
  408. infile.linebuf^[hp.fileinfo.line]:=-infile.linebuf^[hp.fileinfo.line]-1;
  409. end;
  410. end;
  411. lastfileinfo:=hp.fileinfo;
  412. lastinfile:=infile;
  413. end;
  414. end;
  415. case hp.typ of
  416. ait_comment :
  417. Begin
  418. AsmWrite(target_asm.comment);
  419. AsmWritePChar(tai_asm_comment(hp).str);
  420. AsmLn;
  421. End;
  422. ait_regalloc :
  423. begin
  424. if (cs_asm_regalloc in aktglobalswitches) then
  425. AsmWriteLn(target_asm.comment+'Register '+att_reg2str[tairegalloc(hp).reg]+
  426. allocstr[tairegalloc(hp).allocation]);
  427. end;
  428. ait_tempalloc :
  429. begin
  430. if (cs_asm_tempalloc in aktglobalswitches) then
  431. AsmWriteLn(target_asm.comment+'Temp '+tostr(taitempalloc(hp).temppos)+','+
  432. tostr(taitempalloc(hp).tempsize)+allocstr[taitempalloc(hp).allocation]);
  433. end;
  434. ait_align :
  435. begin
  436. AsmWrite(#9'.balign '+tostr(tai_align(hp).aligntype));
  437. if tai_align(hp).use_op then
  438. AsmWrite(','+tostr(tai_align(hp).fillop));
  439. AsmLn;
  440. end;
  441. ait_section :
  442. begin
  443. if tai_section(hp).sec<>sec_none then
  444. begin
  445. AsmLn;
  446. AsmWriteLn(ait_section2str(tai_section(hp).sec));
  447. {$ifdef GDB}
  448. lastfileinfo.line:=-1;
  449. {$endif GDB}
  450. end;
  451. end;
  452. ait_datablock :
  453. begin
  454. if tai_datablock(hp).is_global then
  455. AsmWrite(#9'.comm'#9)
  456. else
  457. AsmWrite(#9'.lcomm'#9);
  458. AsmWrite(tai_datablock(hp).sym.name);
  459. AsmWriteLn(','+tostr(tai_datablock(hp).size));
  460. end;
  461. ait_const_32bit,
  462. ait_const_16bit,
  463. ait_const_8bit :
  464. begin
  465. AsmWrite(ait_const2str[hp.typ]+tostr(tai_const(hp).value));
  466. consttyp:=hp.typ;
  467. l:=0;
  468. repeat
  469. found:=(not (tai(hp.next)=nil)) and (tai(hp.next).typ=consttyp);
  470. if found then
  471. begin
  472. hp:=tai(hp.next);
  473. s:=','+tostr(tai_const(hp).value);
  474. AsmWrite(s);
  475. inc(l,length(s));
  476. end;
  477. until (not found) or (l>line_length);
  478. AsmLn;
  479. end;
  480. ait_const_symbol :
  481. begin
  482. AsmWrite(#9'.long'#9+tai_const_symbol(hp).sym.name);
  483. if tai_const_symbol(hp).offset>0 then
  484. AsmWrite('+'+tostr(tai_const_symbol(hp).offset))
  485. else if tai_const_symbol(hp).offset<0 then
  486. AsmWrite(tostr(tai_const_symbol(hp).offset));
  487. AsmLn;
  488. end;
  489. ait_const_rva :
  490. AsmWriteLn(#9'.rva'#9+tai_const_symbol(hp).sym.name);
  491. ait_real_80bit :
  492. begin
  493. if do_line then
  494. AsmWriteLn(target_asm.comment+extended2str(tai_real_80bit(hp).value));
  495. { Make sure e is a extended type, bestreal could be
  496. a different type (bestreal) !! (PFV) }
  497. e:=tai_real_80bit(hp).value;
  498. AsmWrite(#9'.byte'#9);
  499. for i:=0 to 9 do
  500. begin
  501. if i<>0 then
  502. AsmWrite(',');
  503. AsmWrite(tostr(t80bitarray(e)[i]));
  504. end;
  505. AsmLn;
  506. end;
  507. ait_real_64bit :
  508. begin
  509. if do_line then
  510. AsmWriteLn(target_asm.comment+double2str(tai_real_64bit(hp).value));
  511. d:=tai_real_64bit(hp).value;
  512. AsmWrite(#9'.byte'#9);
  513. for i:=0 to 7 do
  514. begin
  515. if i<>0 then
  516. AsmWrite(',');
  517. AsmWrite(tostr(t64bitarray(d)[i]));
  518. end;
  519. AsmLn;
  520. end;
  521. ait_real_32bit :
  522. begin
  523. if do_line then
  524. AsmWriteLn(target_asm.comment+single2str(tai_real_32bit(hp).value));
  525. sin:=tai_real_32bit(hp).value;
  526. AsmWrite(#9'.byte'#9);
  527. for i:=0 to 3 do
  528. begin
  529. if i<>0 then
  530. AsmWrite(',');
  531. AsmWrite(tostr(t32bitarray(sin)[i]));
  532. end;
  533. AsmLn;
  534. end;
  535. ait_comp_64bit :
  536. begin
  537. if do_line then
  538. AsmWriteLn(target_asm.comment+comp2str(tai_comp_64bit(hp).value));
  539. AsmWrite(#9'.byte'#9);
  540. {$ifdef FPC}
  541. co:=comp(tai_comp_64bit(hp).value);
  542. {$else}
  543. co:=tai_comp_64bit(hp).value;
  544. {$endif}
  545. for i:=0 to 7 do
  546. begin
  547. if i<>0 then
  548. AsmWrite(',');
  549. AsmWrite(tostr(t64bitarray(co)[i]));
  550. end;
  551. AsmLn;
  552. end;
  553. ait_direct :
  554. begin
  555. AsmWritePChar(tai_direct(hp).str);
  556. AsmLn;
  557. {$IfDef GDB}
  558. if strpos(tai_direct(hp).str,'.data')<>nil then
  559. n_line:=n_dataline
  560. else if strpos(tai_direct(hp).str,'.text')<>nil then
  561. n_line:=n_textline
  562. else if strpos(tai_direct(hp).str,'.bss')<>nil then
  563. n_line:=n_bssline;
  564. {$endif GDB}
  565. end;
  566. ait_string :
  567. begin
  568. pos:=0;
  569. for i:=1 to tai_string(hp).len do
  570. begin
  571. if pos=0 then
  572. begin
  573. AsmWrite(#9'.ascii'#9'"');
  574. pos:=20;
  575. end;
  576. ch:=tai_string(hp).str[i-1];
  577. case ch of
  578. #0, {This can't be done by range, because a bug in FPC}
  579. #1..#31,
  580. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  581. '"' : s:='\"';
  582. '\' : s:='\\';
  583. else
  584. s:=ch;
  585. end;
  586. AsmWrite(s);
  587. inc(pos,length(s));
  588. if (pos>line_length) or (i=tai_string(hp).len) then
  589. begin
  590. AsmWriteLn('"');
  591. pos:=0;
  592. end;
  593. end;
  594. end;
  595. ait_label :
  596. begin
  597. if (tai_label(hp).l.is_used) then
  598. begin
  599. if tai_label(hp).l.defbind=AB_GLOBAL then
  600. begin
  601. AsmWrite('.globl'#9);
  602. AsmWriteLn(tai_label(hp).l.name);
  603. end;
  604. AsmWrite(tai_label(hp).l.name);
  605. AsmWriteLn(':');
  606. end;
  607. end;
  608. ait_symbol :
  609. begin
  610. if tai_symbol(hp).is_global then
  611. begin
  612. AsmWrite('.globl'#9);
  613. AsmWriteLn(tai_symbol(hp).sym.name);
  614. end;
  615. if target_info.target=target_i386_linux then
  616. begin
  617. AsmWrite(#9'.type'#9);
  618. AsmWrite(tai_symbol(hp).sym.name);
  619. if assigned(tai(hp.next)) and
  620. (tai(hp.next).typ in [ait_const_symbol,ait_const_rva,
  621. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  622. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit]) then
  623. AsmWriteLn(',@object')
  624. else
  625. AsmWriteLn(',@function');
  626. if tai_symbol(hp).sym.size>0 then
  627. begin
  628. AsmWrite(#9'.size'#9);
  629. AsmWrite(tai_symbol(hp).sym.name);
  630. AsmWrite(', ');
  631. AsmWriteLn(tostr(tai_symbol(hp).sym.size));
  632. end;
  633. end;
  634. AsmWrite(tai_symbol(hp).sym.name);
  635. AsmWriteLn(':');
  636. end;
  637. ait_symbol_end :
  638. begin
  639. if target_info.target=target_i386_linux then
  640. begin
  641. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  642. inc(symendcount);
  643. AsmWriteLn(s+':');
  644. AsmWrite(#9'.size'#9);
  645. AsmWrite(tai_symbol(hp).sym.name);
  646. AsmWrite(', '+s+' - ');
  647. AsmWriteLn(tai_symbol(hp).sym.name);
  648. end;
  649. end;
  650. ait_instruction :
  651. begin
  652. taicpu(hp).SetOperandOrder(op_att);
  653. op:=taicpu(hp).opcode;
  654. calljmp:=is_calljmp(op);
  655. { call maybe not translated to call }
  656. s:=#9+att_op2str[op]+cond2str[taicpu(hp).condition];
  657. { suffix needed ? fnstsw,fldcw don't support suffixes
  658. with binutils 2.9.5 under linux }
  659. if (not calljmp) and
  660. (att_needsuffix[op]<>AttSufNONE) and
  661. (op<>A_FNSTSW) and (op<>A_FSTSW) and
  662. (op<>A_FNSTCW) and (op<>A_FSTCW) and
  663. (op<>A_FLDCW) and
  664. not(
  665. (taicpu(hp).oper[0].typ=top_reg) and
  666. (taicpu(hp).oper[0].reg in [R_ST..R_ST7])
  667. ) then
  668. s:=s+att_opsize2str[taicpu(hp).opsize];
  669. { process operands }
  670. if taicpu(hp).ops<>0 then
  671. begin
  672. { call and jmp need an extra handling }
  673. { this code is only called if jmp isn't a labeled instruction }
  674. { quick hack to overcome a problem with manglednames=255 chars }
  675. if calljmp then
  676. begin
  677. AsmWrite(s+#9);
  678. s:=getopstr_jmp(taicpu(hp).oper[0]);
  679. end
  680. else
  681. begin
  682. for i:=0 to taicpu(hp).ops-1 do
  683. begin
  684. if i=0 then
  685. sep:=#9
  686. else
  687. sep:=',';
  688. s:=s+sep+getopstr(taicpu(hp).oper[i])
  689. end;
  690. end;
  691. end;
  692. AsmWriteLn(s);
  693. end;
  694. {$ifdef GDB}
  695. ait_stabs :
  696. begin
  697. AsmWrite(#9'.stabs ');
  698. AsmWritePChar(tai_stabs(hp).str);
  699. AsmLn;
  700. end;
  701. ait_stabn :
  702. begin
  703. AsmWrite(#9'.stabn ');
  704. AsmWritePChar(tai_stabn(hp).str);
  705. AsmLn;
  706. end;
  707. ait_force_line :
  708. stabslastfileinfo.line:=0;
  709. ait_stab_function_name:
  710. funcname:=tai_stab_function_name(hp).str;
  711. {$endif GDB}
  712. ait_cut :
  713. begin
  714. if SmartAsm then
  715. begin
  716. { only reset buffer if nothing has changed }
  717. if AsmSize=AsmStartSize then
  718. AsmClear
  719. else
  720. begin
  721. AsmClose;
  722. DoAssemble;
  723. AsmCreate(tai_cut(hp).place);
  724. end;
  725. { avoid empty files }
  726. while assigned(hp.next) and (tai(hp.next).typ in [ait_cut,ait_section,ait_comment]) do
  727. begin
  728. if tai(hp.next).typ=ait_section then
  729. lastsec:=tai_section(hp.next).sec;
  730. hp:=tai(hp.next);
  731. end;
  732. {$ifdef GDB}
  733. { force write of filename }
  734. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  735. includecount:=0;
  736. funcname:=nil;
  737. WriteFileLineInfo(hp.fileinfo);
  738. {$endif GDB}
  739. if lastsec<>sec_none then
  740. AsmWriteLn(ait_section2str(lastsec));
  741. AsmStartSize:=AsmSize;
  742. end;
  743. end;
  744. ait_marker :
  745. if tai_marker(hp).kind=InlineStart then
  746. inc(InlineLevel)
  747. else if tai_marker(hp).kind=InlineEnd then
  748. dec(InlineLevel);
  749. else
  750. internalerror(10000);
  751. end;
  752. hp:=tai(hp.next);
  753. end;
  754. end;
  755. procedure T386ATTAssembler.WriteAsmList;
  756. var
  757. p:dirstr;
  758. n:namestr;
  759. e:extstr;
  760. {$ifdef GDB}
  761. fileinfo : tfileposinfo;
  762. {$endif GDB}
  763. begin
  764. {$ifdef EXTDEBUG}
  765. if assigned(current_module.mainsource) then
  766. Comment(v_info,'Start writing att-styled assembler output for '+current_module.mainsource^);
  767. {$endif}
  768. LastSec:=sec_none;
  769. {$ifdef GDB}
  770. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  771. {$endif GDB}
  772. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  773. LastInfile:=nil;
  774. if assigned(current_module.mainsource) then
  775. fsplit(current_module.mainsource^,p,n,e)
  776. else
  777. begin
  778. p:=inputdir;
  779. n:=inputfile;
  780. e:=inputextension;
  781. end;
  782. { to get symify to work }
  783. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  784. {$ifdef GDB}
  785. n_line:=n_bssline;
  786. funcname:=nil;
  787. linecount:=1;
  788. includecount:=0;
  789. fileinfo.fileindex:=1;
  790. fileinfo.line:=1;
  791. { Write main file }
  792. WriteFileLineInfo(fileinfo);
  793. {$endif GDB}
  794. AsmStartSize:=AsmSize;
  795. symendcount:=0;
  796. countlabelref:=false;
  797. If (cs_debuginfo in aktmoduleswitches) then
  798. WriteTree(debuglist);
  799. WriteTree(codesegment);
  800. WriteTree(datasegment);
  801. WriteTree(consts);
  802. WriteTree(rttilist);
  803. Writetree(resourcestringlist);
  804. WriteTree(bsssegment);
  805. Writetree(importssection);
  806. { exports are written by DLLTOOL
  807. if we use it so don't insert it twice (PM) }
  808. if not UseDeffileForExport and assigned(exportssection) then
  809. Writetree(exportssection);
  810. Writetree(resourcesection);
  811. {$ifdef GDB}
  812. WriteFileEndInfo;
  813. {$ENDIF}
  814. countlabelref:=true;
  815. AsmLn;
  816. {$ifdef EXTDEBUG}
  817. if assigned(current_module.mainsource) then
  818. comment(v_info,'Done writing att-styled assembler output for '+current_module.mainsource^);
  819. {$endif EXTDEBUG}
  820. end;
  821. {*****************************************************************************
  822. Initialize
  823. *****************************************************************************}
  824. const
  825. as_i386_as_info : tasminfo =
  826. (
  827. id : as_i386_as;
  828. idtxt : 'AS';
  829. asmbin : 'as';
  830. asmcmd : '-o $OBJ $ASM';
  831. supported_target : target_any;
  832. outputbinary: false;
  833. allowdirect : true;
  834. externals : false;
  835. needar : true;
  836. labelprefix_only_inside_procedure : false;
  837. labelprefix : '.L';
  838. comment : '# ';
  839. secnames : ('',
  840. '.text','.data','.bss',
  841. '','','','','','',
  842. '.stab','.stabstr')
  843. );
  844. as_i386_as_aout_info : tasminfo =
  845. (
  846. id : as_i386_as_aout;
  847. idtxt : 'AS_AOUT';
  848. asmbin : 'as';
  849. asmcmd : '-o $OBJ $ASM';
  850. supported_target : target_i386_os2;
  851. outputbinary: false;
  852. allowdirect : true;
  853. externals : false;
  854. needar : true;
  855. labelprefix_only_inside_procedure : false;
  856. labelprefix : 'L';
  857. comment : '# ';
  858. secnames : ('',
  859. '.text','.data','.bss',
  860. '','','','','','',
  861. '.stab','.stabstr')
  862. );
  863. as_i386_asw_info : tasminfo =
  864. (
  865. id : as_i386_asw;
  866. idtxt : 'ASW';
  867. asmbin : 'asw';
  868. asmcmd : '-o $OBJ $ASM';
  869. supported_target : target_i386_win32;
  870. outputbinary: false;
  871. allowdirect : true;
  872. externals : false;
  873. needar : true;
  874. labelprefix_only_inside_procedure : false;
  875. labelprefix : '.L';
  876. comment : '# ';
  877. secnames : ('',
  878. '.text','.data','.section .bss',
  879. '.section .idata$2','.section .idata$4','.section .idata$5',
  880. '.section .idata$6','.section .idata$7','.section .edata',
  881. '.stab','.stabstr')
  882. );
  883. initialization
  884. RegisterAssembler(as_i386_as_info,T386ATTAssembler);
  885. RegisterAssembler(as_i386_as_aout_info,T386ATTAssembler);
  886. RegisterAssembler(as_i386_asw_info,T386ATTAssembler);
  887. end.
  888. {
  889. $Log$
  890. Revision 1.9 2001-05-06 17:13:23 jonas
  891. * completed incomplete typed constant records
  892. Revision 1.8 2001/04/21 15:33:03 peter
  893. * stupid bug, finalization to initialization renaming
  894. Revision 1.7 2001/04/21 12:09:00 peter
  895. * fixed bug 1472 (merged)
  896. Revision 1.6 2001/04/18 22:02:00 peter
  897. * registration of targets and assemblers
  898. Revision 1.5 2001/04/13 01:22:17 peter
  899. * symtable change to classes
  900. * range check generation and errors fixed, make cycle DEBUG=1 works
  901. * memory leaks fixed
  902. Revision 1.4 2001/03/05 21:39:11 peter
  903. * changed to class with common TAssembler also for internal assembler
  904. Revision 1.3 2001/01/13 20:24:24 peter
  905. * fixed operand order that got mixed up for external writers after
  906. my previous assembler block valid instruction check
  907. Revision 1.2 2000/12/25 00:07:31 peter
  908. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  909. tlinkedlist objects)
  910. Revision 1.1 2000/11/30 22:18:48 florian
  911. * moved to i386
  912. Revision 1.6 2000/09/24 15:06:10 peter
  913. * use defines.inc
  914. Revision 1.5 2000/08/27 16:11:49 peter
  915. * moved some util functions from globals,cobjects to cutils
  916. * splitted files into finput,fmodule
  917. Revision 1.4 2000/08/20 17:38:21 peter
  918. * smartlinking fixed for linux (merged)
  919. Revision 1.3 2000/07/13 12:08:24 michael
  920. + patched to 1.1.0 with former 1.09patch from peter
  921. Revision 1.2 2000/07/13 11:32:28 michael
  922. + removed logs
  923. }