ag386att.pas 33 KB

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