ag386att.pas 31 KB

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