aggas.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. {
  2. Copyright (c) 1998-2004 by the Free Pascal team
  3. This unit implements generic GNU assembler (v2.8 or later)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { Base unit for writing GNU assembler output.
  18. }
  19. unit aggas;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. {$IFDEF USE_SYSUTILS}
  24. SysUtils,
  25. {$ELSE USE_SYSUTILS}
  26. dos,
  27. {$ENDIF USE_SYSUTILS}
  28. cclasses,
  29. globals,
  30. aasmbase,aasmtai,aasmcpu,
  31. assemble;
  32. type
  33. {# This is a derived class which is used to write
  34. GAS styled assembler.
  35. The WriteInstruction() method must be overriden
  36. to write a single instruction to the assembler
  37. file.
  38. }
  39. TGNUAssembler=class(texternalassembler)
  40. protected
  41. function sectionname(atype:tasmsectiontype;const aname:string):string;virtual;
  42. procedure WriteSection(atype:tasmsectiontype;const aname:string);
  43. procedure WriteExtraHeader;virtual;
  44. procedure WriteInstruction(hp: tai); virtual; abstract;
  45. public
  46. procedure WriteTree(p:TAAsmoutput);override;
  47. procedure WriteAsmList;override;
  48. end;
  49. implementation
  50. uses
  51. cutils,globtype,systems,
  52. fmodule,finput,verbose,
  53. itcpugas
  54. ;
  55. const
  56. line_length = 70;
  57. var
  58. CurrSecType : TAsmSectionType; { last section type written }
  59. lastfileinfo : tfileposinfo;
  60. infile,
  61. lastinfile : tinputfile;
  62. symendcount : longint;
  63. type
  64. {$ifdef cpuextended}
  65. t80bitarray = array[0..9] of byte;
  66. {$endif cpuextended}
  67. t64bitarray = array[0..7] of byte;
  68. t32bitarray = array[0..3] of byte;
  69. {****************************************************************************}
  70. { Support routines }
  71. {****************************************************************************}
  72. function fixline(s:string):string;
  73. {
  74. return s with all leading and ending spaces and tabs removed
  75. }
  76. var
  77. i,j,k : integer;
  78. begin
  79. i:=length(s);
  80. while (i>0) and (s[i] in [#9,' ']) do
  81. dec(i);
  82. j:=1;
  83. while (j<i) and (s[j] in [#9,' ']) do
  84. inc(j);
  85. for k:=j to i do
  86. if s[k] in [#0..#31,#127..#255] then
  87. s[k]:='.';
  88. fixline:=Copy(s,j,i-j+1);
  89. end;
  90. function single2str(d : single) : string;
  91. var
  92. hs : string;
  93. begin
  94. str(d,hs);
  95. { replace space with + }
  96. if hs[1]=' ' then
  97. hs[1]:='+';
  98. single2str:='0d'+hs
  99. end;
  100. function double2str(d : double) : string;
  101. var
  102. hs : string;
  103. begin
  104. str(d,hs);
  105. { replace space with + }
  106. if hs[1]=' ' then
  107. hs[1]:='+';
  108. double2str:='0d'+hs
  109. end;
  110. function extended2str(e : extended) : string;
  111. var
  112. hs : string;
  113. begin
  114. str(e,hs);
  115. { replace space with + }
  116. if hs[1]=' ' then
  117. hs[1]:='+';
  118. extended2str:='0d'+hs
  119. end;
  120. { convert floating point values }
  121. { to correct endian }
  122. procedure swap64bitarray(var t: t64bitarray);
  123. var
  124. b: byte;
  125. begin
  126. b:= t[7];
  127. t[7] := t[0];
  128. t[0] := b;
  129. b := t[6];
  130. t[6] := t[1];
  131. t[1] := b;
  132. b:= t[5];
  133. t[5] := t[2];
  134. t[2] := b;
  135. b:= t[4];
  136. t[4] := t[3];
  137. t[3] := b;
  138. end;
  139. procedure swap32bitarray(var t: t32bitarray);
  140. var
  141. b: byte;
  142. begin
  143. b:= t[1];
  144. t[1]:= t[2];
  145. t[2]:= b;
  146. b:= t[0];
  147. t[0]:= t[3];
  148. t[3]:= b;
  149. end;
  150. const
  151. ait_const2str : array[ait_const_128bit..ait_const_indirect_symbol] of string[20]=(
  152. #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
  153. #9'.sleb128'#9,#9'.uleb128'#9,
  154. #9'.rva'#9,#9'.indirect_symbol'#9
  155. );
  156. {****************************************************************************}
  157. { GNU Assembler writer }
  158. {****************************************************************************}
  159. function TGNUAssembler.sectionname(atype:tasmsectiontype;const aname:string):string;
  160. const
  161. secnames : array[tasmsectiontype] of string[12] = ('',
  162. {$warning TODO .rodata not yet working}
  163. '.text','.data','.data','.bss','.threadvar',
  164. 'common',
  165. '.note',
  166. '__TEXT', { stubs }
  167. '.stab','.stabstr',
  168. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  169. '.eh_frame',
  170. '.debug_frame',
  171. 'fpc.resptrs'
  172. );
  173. secnames_pic : array[tasmsectiontype] of string[12] = ('',
  174. '.text','.data.rel','.data.rel','.bss','.threadvar',
  175. 'common',
  176. '.note',
  177. '__TEXT', { stubs }
  178. '.stab','.stabstr',
  179. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  180. '.eh_frame',
  181. '.debug_frame',
  182. 'fpc.resptrs'
  183. );
  184. var
  185. secname : string;
  186. begin
  187. if cs_create_pic in aktmoduleswitches then
  188. secname:=secnames_pic[atype]
  189. else
  190. secname:=secnames[atype];
  191. if use_smartlink_section and
  192. (aname<>'') then
  193. result:=secname+'.'+aname
  194. else
  195. result:=secname;
  196. end;
  197. procedure TGNUAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
  198. var
  199. s : string;
  200. begin
  201. AsmLn;
  202. case target_info.system of
  203. system_i386_OS2,
  204. system_i386_EMX : ;
  205. system_powerpc_darwin :
  206. begin
  207. if atype=sec_stub then
  208. AsmWrite('.section ');
  209. end;
  210. else
  211. AsmWrite('.section ');
  212. end;
  213. s:=sectionname(atype,aname);
  214. AsmWrite(s);
  215. case atype of
  216. sec_fpc :
  217. AsmWrite(', "a", @progbits');
  218. sec_stub :
  219. begin
  220. if target_info.system=system_powerpc_darwin then
  221. AsmWrite(',__symbol_stub1,symbol_stubs,pure_instructions,16');
  222. end;
  223. end;
  224. AsmLn;
  225. CurrSecType:=atype;
  226. end;
  227. procedure TGNUAssembler.WriteTree(p:TAAsmoutput);
  228. function needsObject(hp : tai_symbol) : boolean;
  229. begin
  230. needsObject :=
  231. (
  232. assigned(hp.next) and
  233. (tai_symbol(hp.next).typ in [ait_const_rva_symbol,
  234. ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_datablock,
  235. ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit])
  236. ) or
  237. (hp.sym.typ=AT_DATA);
  238. end;
  239. var
  240. ch : char;
  241. hp : tai;
  242. hp1 : tailineinfo;
  243. consttyp : taitype;
  244. s : string;
  245. i,pos,l : longint;
  246. InlineLevel : longint;
  247. last_align : longint;
  248. co : comp;
  249. sin : single;
  250. d : double;
  251. {$ifdef cpuextended}
  252. e : extended;
  253. {$endif cpuextended}
  254. do_line : boolean;
  255. sepChar : char;
  256. begin
  257. if not assigned(p) then
  258. exit;
  259. last_align := 2;
  260. InlineLevel:=0;
  261. { lineinfo is only needed for al_procedures (PFV) }
  262. do_line:=(cs_asm_source in aktglobalswitches) or
  263. ((cs_lineinfo in aktmoduleswitches)
  264. and (p=asmlist[al_procedures]));
  265. hp:=tai(p.first);
  266. while assigned(hp) do
  267. begin
  268. if not(hp.typ in SkipLineInfo) then
  269. begin
  270. hp1 := hp as tailineinfo;
  271. aktfilepos:=hp1.fileinfo;
  272. { no line info for inlined code }
  273. if do_line and (inlinelevel=0) then
  274. begin
  275. { load infile }
  276. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  277. begin
  278. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  279. if assigned(infile) then
  280. begin
  281. { open only if needed !! }
  282. if (cs_asm_source in aktglobalswitches) then
  283. infile.open;
  284. end;
  285. { avoid unnecessary reopens of the same file !! }
  286. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  287. { be sure to change line !! }
  288. lastfileinfo.line:=-1;
  289. end;
  290. { write source }
  291. if (cs_asm_source in aktglobalswitches) and
  292. assigned(infile) then
  293. begin
  294. if (infile<>lastinfile) then
  295. begin
  296. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  297. if assigned(lastinfile) then
  298. lastinfile.close;
  299. end;
  300. if (hp1.fileinfo.line<>lastfileinfo.line) and
  301. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  302. begin
  303. if (hp1.fileinfo.line<>0) and
  304. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  305. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  306. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  307. { set it to a negative value !
  308. to make that is has been read already !! PM }
  309. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  310. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  311. end;
  312. end;
  313. lastfileinfo:=hp1.fileinfo;
  314. lastinfile:=infile;
  315. end;
  316. end;
  317. case hp.typ of
  318. ait_comment :
  319. Begin
  320. AsmWrite(target_asm.comment);
  321. AsmWritePChar(tai_comment(hp).str);
  322. AsmLn;
  323. End;
  324. ait_regalloc :
  325. begin
  326. if (cs_asm_regalloc in aktglobalswitches) then
  327. begin
  328. AsmWrite(#9+target_asm.comment+'Register ');
  329. repeat
  330. AsmWrite(gas_regname(Tai_regalloc(hp).reg));
  331. if (hp.next=nil) or
  332. (tai(hp.next).typ<>ait_regalloc) or
  333. (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
  334. break;
  335. hp:=tai(hp.next);
  336. AsmWrite(',');
  337. until false;
  338. AsmWrite(' ');
  339. AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
  340. end;
  341. end;
  342. ait_tempalloc :
  343. begin
  344. if (cs_asm_tempalloc in aktglobalswitches) then
  345. begin
  346. {$ifdef EXTDEBUG}
  347. if assigned(tai_tempalloc(hp).problem) then
  348. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  349. tostr(tai_tempalloc(hp).tempsize)+' '+tai_tempalloc(hp).problem^)
  350. else
  351. {$endif EXTDEBUG}
  352. AsmWriteLn(target_asm.comment+'Temp '+tostr(tai_tempalloc(hp).temppos)+','+
  353. tostr(tai_tempalloc(hp).tempsize)+' '+tempallocstr[tai_tempalloc(hp).allocation]);
  354. end;
  355. end;
  356. ait_align :
  357. begin
  358. if tai_align(hp).aligntype>1 then
  359. begin
  360. if target_info.system <> system_powerpc_darwin then
  361. begin
  362. AsmWrite(#9'.balign '+tostr(tai_align(hp).aligntype));
  363. if tai_align(hp).use_op then
  364. AsmWrite(','+tostr(tai_align(hp).fillop))
  365. end
  366. else
  367. begin
  368. { darwin as only supports .align }
  369. if not ispowerof2(tai_align(hp).aligntype,i) then
  370. internalerror(2003010305);
  371. AsmWrite(#9'.align '+tostr(i));
  372. last_align := i;
  373. end;
  374. AsmLn;
  375. end;
  376. end;
  377. ait_section :
  378. begin
  379. if tai_section(hp).sectype<>sec_none then
  380. WriteSection(tai_section(hp).sectype,tai_section(hp).name^)
  381. else
  382. begin
  383. {$ifdef EXTDEBUG}
  384. AsmWrite(target_asm.comment);
  385. AsmWriteln(' sec_none');
  386. {$endif EXTDEBUG}
  387. end;
  388. end;
  389. ait_datablock :
  390. begin
  391. if target_info.system=system_powerpc_darwin then
  392. begin
  393. {On Mac OS X you can't have common symbols in a shared
  394. library, since those are in the TEXT section and the text section is
  395. read-only in shared libraries (so it can be shared among different
  396. processes). The alternate code creates some kind of common symbols in
  397. the data segment. The generic code no longer uses common symbols, but
  398. this doesn't work on Mac OS X as well.}
  399. if tai_datablock(hp).is_global then
  400. begin
  401. asmwrite('.globl ');
  402. asmwriteln(tai_datablock(hp).sym.name);
  403. asmwriteln('.data');
  404. asmwrite('.zerofill __DATA, __common, ');
  405. asmwrite(tai_datablock(hp).sym.name);
  406. asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
  407. if not(CurrSecType in [sec_data,sec_none]) then
  408. writesection(CurrSecType,'');
  409. end
  410. else
  411. begin
  412. asmwrite(#9'.lcomm'#9);
  413. asmwrite(tai_datablock(hp).sym.name);
  414. asmwrite(','+tostr(tai_datablock(hp).size));
  415. asmwrite(','+tostr(last_align));
  416. asmwriteln('');
  417. end
  418. end
  419. else
  420. begin
  421. if Tai_datablock(hp).is_global then
  422. begin
  423. asmwrite(#9'.globl ');
  424. asmwriteln(Tai_datablock(hp).sym.name);
  425. end;
  426. asmwriteln(#9'.type '+Tai_datablock(hp).sym.name+',@object');
  427. asmwriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
  428. asmwrite(Tai_datablock(hp).sym.name);
  429. asmwriteln(':');
  430. asmwriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
  431. end;
  432. end;
  433. {$ifndef cpu64bit}
  434. ait_const_128bit :
  435. begin
  436. internalerror(200404291);
  437. end;
  438. ait_const_64bit :
  439. begin
  440. if assigned(tai_const(hp).sym) then
  441. internalerror(200404292);
  442. AsmWrite(ait_const2str[ait_const_32bit]);
  443. if target_info.endian = endian_little then
  444. begin
  445. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  446. AsmWrite(',');
  447. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  448. end
  449. else
  450. begin
  451. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  452. AsmWrite(',');
  453. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  454. end;
  455. AsmLn;
  456. end;
  457. {$endif cpu64bit}
  458. ait_const_uleb128bit,
  459. ait_const_sleb128bit,
  460. {$ifdef cpu64bit}
  461. ait_const_128bit,
  462. ait_const_64bit,
  463. {$endif cpu64bit}
  464. ait_const_32bit,
  465. ait_const_16bit,
  466. ait_const_8bit,
  467. ait_const_rva_symbol,
  468. ait_const_indirect_symbol :
  469. begin
  470. AsmWrite(ait_const2str[hp.typ]);
  471. consttyp:=hp.typ;
  472. l:=0;
  473. repeat
  474. if assigned(tai_const(hp).sym) then
  475. begin
  476. if assigned(tai_const(hp).endsym) then
  477. s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
  478. else
  479. s:=tai_const(hp).sym.name;
  480. if tai_const(hp).value<>0 then
  481. s:=s+tostr_with_plus(tai_const(hp).value);
  482. end
  483. else
  484. s:=tostr(tai_const(hp).value);
  485. AsmWrite(s);
  486. inc(l,length(s));
  487. { Values with symbols are written on a single line to improve
  488. reading of the .s file (PFV) }
  489. if assigned(tai_const(hp).sym) or
  490. not(CurrSecType in [sec_data,sec_rodata]) or
  491. (l>line_length) or
  492. (hp.next=nil) or
  493. (tai(hp.next).typ<>consttyp) or
  494. assigned(tai_const(hp.next).sym) then
  495. break;
  496. hp:=tai(hp.next);
  497. AsmWrite(',');
  498. until false;
  499. AsmLn;
  500. end;
  501. {$ifdef cpuextended}
  502. ait_real_80bit :
  503. begin
  504. if do_line then
  505. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  506. { Make sure e is a extended type, bestreal could be
  507. a different type (bestreal) !! (PFV) }
  508. e:=tai_real_80bit(hp).value;
  509. AsmWrite(#9'.byte'#9);
  510. for i:=0 to 9 do
  511. begin
  512. if i<>0 then
  513. AsmWrite(',');
  514. AsmWrite(tostr(t80bitarray(e)[i]));
  515. end;
  516. AsmLn;
  517. end;
  518. {$endif cpuextended}
  519. ait_real_64bit :
  520. begin
  521. if do_line then
  522. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  523. d:=tai_real_64bit(hp).value;
  524. { swap the values to correct endian if required }
  525. if source_info.endian <> target_info.endian then
  526. swap64bitarray(t64bitarray(d));
  527. AsmWrite(#9'.byte'#9);
  528. {$ifdef arm}
  529. { on a real arm cpu, it's already hi/lo swapped }
  530. {$ifndef cpuarm}
  531. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  532. begin
  533. for i:=4 to 7 do
  534. begin
  535. if i<>4 then
  536. AsmWrite(',');
  537. AsmWrite(tostr(t64bitarray(d)[i]));
  538. end;
  539. for i:=0 to 3 do
  540. begin
  541. AsmWrite(',');
  542. AsmWrite(tostr(t64bitarray(d)[i]));
  543. end;
  544. end
  545. else
  546. {$endif cpuarm}
  547. {$endif arm}
  548. begin
  549. for i:=0 to 7 do
  550. begin
  551. if i<>0 then
  552. AsmWrite(',');
  553. AsmWrite(tostr(t64bitarray(d)[i]));
  554. end;
  555. end;
  556. AsmLn;
  557. end;
  558. ait_real_32bit :
  559. begin
  560. if do_line then
  561. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  562. sin:=tai_real_32bit(hp).value;
  563. { swap the values to correct endian if required }
  564. if source_info.endian <> target_info.endian then
  565. swap32bitarray(t32bitarray(sin));
  566. AsmWrite(#9'.byte'#9);
  567. for i:=0 to 3 do
  568. begin
  569. if i<>0 then
  570. AsmWrite(',');
  571. AsmWrite(tostr(t32bitarray(sin)[i]));
  572. end;
  573. AsmLn;
  574. end;
  575. ait_comp_64bit :
  576. begin
  577. if do_line then
  578. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  579. AsmWrite(#9'.byte'#9);
  580. {$ifdef FPC}
  581. co:=comp(tai_comp_64bit(hp).value);
  582. {$else}
  583. co:=tai_comp_64bit(hp).value;
  584. {$endif}
  585. { swap the values to correct endian if required }
  586. if source_info.endian <> target_info.endian then
  587. swap64bitarray(t64bitarray(co));
  588. for i:=0 to 7 do
  589. begin
  590. if i<>0 then
  591. AsmWrite(',');
  592. AsmWrite(tostr(t64bitarray(co)[i]));
  593. end;
  594. AsmLn;
  595. end;
  596. ait_string :
  597. begin
  598. pos:=0;
  599. for i:=1 to tai_string(hp).len do
  600. begin
  601. if pos=0 then
  602. begin
  603. AsmWrite(#9'.ascii'#9'"');
  604. pos:=20;
  605. end;
  606. ch:=tai_string(hp).str[i-1];
  607. case ch of
  608. #0, {This can't be done by range, because a bug in FPC}
  609. #1..#31,
  610. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  611. '"' : s:='\"';
  612. '\' : s:='\\';
  613. else
  614. s:=ch;
  615. end;
  616. AsmWrite(s);
  617. inc(pos,length(s));
  618. if (pos>line_length) or (i=tai_string(hp).len) then
  619. begin
  620. AsmWriteLn('"');
  621. pos:=0;
  622. end;
  623. end;
  624. end;
  625. ait_label :
  626. begin
  627. if (tai_label(hp).l.is_used) then
  628. begin
  629. if tai_label(hp).l.defbind=AB_GLOBAL then
  630. begin
  631. AsmWrite('.globl'#9);
  632. AsmWriteLn(tai_label(hp).l.name);
  633. end;
  634. AsmWrite(tai_label(hp).l.name);
  635. AsmWriteLn(':');
  636. end;
  637. end;
  638. ait_symbol :
  639. begin
  640. if tai_symbol(hp).is_global then
  641. begin
  642. AsmWrite('.globl'#9);
  643. AsmWriteLn(tai_symbol(hp).sym.name);
  644. end;
  645. if (target_info.system = system_powerpc64_linux) and
  646. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  647. begin
  648. AsmWriteLn('.section "opd", "aw"');
  649. AsmWriteLn('.align 3');
  650. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  651. AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  652. AsmWriteLn('.previous');
  653. AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  654. AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  655. AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  656. { the dotted name is the name of the actual function }
  657. AsmWrite('.');
  658. end
  659. else
  660. begin
  661. if (target_info.system <> system_arm_linux) then
  662. begin
  663. sepChar := '@';
  664. end
  665. else
  666. begin
  667. sepChar := '#';
  668. end;
  669. if (tf_needs_symbol_type in target_info.flags) then
  670. begin
  671. AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  672. if (needsObject(tai_symbol(hp))) then
  673. begin
  674. AsmWriteLn(',' + sepChar + 'object');
  675. end
  676. else
  677. begin
  678. AsmWriteLn(',' + sepChar + 'function');
  679. end;
  680. end;
  681. if (tf_needs_symbol_size in target_info.flags) and (tai_symbol(hp).sym.size > 0) then begin
  682. AsmWriteLn(#9'.size'#9 + tai_symbol(hp).sym.name + ', ' + tostr(tai_symbol(hp).sym.size));
  683. end;
  684. end;
  685. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  686. end;
  687. ait_symbol_end :
  688. begin
  689. if tf_needs_symbol_size in target_info.flags then
  690. begin
  691. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  692. inc(symendcount);
  693. AsmWriteLn(s+':');
  694. AsmWrite(#9'.size'#9);
  695. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  696. begin
  697. AsmWrite('.');
  698. end;
  699. AsmWrite(tai_symbol_end(hp).sym.name);
  700. AsmWrite(', '+s+' - ');
  701. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  702. begin
  703. AsmWrite('.');
  704. end;
  705. AsmWriteLn(tai_symbol_end(hp).sym.name);
  706. end;
  707. end;
  708. ait_instruction :
  709. begin
  710. WriteInstruction(hp);
  711. end;
  712. ait_stab :
  713. begin
  714. if assigned(tai_stab(hp).str) then
  715. begin
  716. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  717. AsmWritePChar(tai_stab(hp).str);
  718. AsmLn;
  719. end;
  720. end;
  721. ait_force_line,
  722. ait_function_name : ;
  723. ait_cutobject :
  724. begin
  725. if SmartAsm then
  726. begin
  727. { only reset buffer if nothing has changed }
  728. if AsmSize=AsmStartSize then
  729. AsmClear
  730. else
  731. begin
  732. AsmClose;
  733. DoAssemble;
  734. AsmCreate(tai_cutobject(hp).place);
  735. end;
  736. { avoid empty files }
  737. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  738. begin
  739. if tai(hp.next).typ=ait_section then
  740. CurrSecType:=tai_section(hp.next).sectype;
  741. hp:=tai(hp.next);
  742. end;
  743. if CurrSecType<>sec_none then
  744. WriteSection(CurrSecType,'');
  745. AsmStartSize:=AsmSize;
  746. end;
  747. end;
  748. ait_marker :
  749. if tai_marker(hp).kind=InlineStart then
  750. inc(InlineLevel)
  751. else if tai_marker(hp).kind=InlineEnd then
  752. dec(InlineLevel);
  753. ait_directive :
  754. begin
  755. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  756. if assigned(tai_directive(hp).name) then
  757. AsmWrite(tai_directive(hp).name^);
  758. AsmLn;
  759. end;
  760. else
  761. internalerror(10000);
  762. end;
  763. hp:=tai(hp.next);
  764. end;
  765. end;
  766. procedure TGNUAssembler.WriteExtraHeader;
  767. begin
  768. end;
  769. procedure TGNUAssembler.WriteAsmList;
  770. var
  771. p:dirstr;
  772. n:namestr;
  773. e:extstr;
  774. hal : tasmlist;
  775. begin
  776. {$ifdef EXTDEBUG}
  777. if assigned(current_module.mainsource) then
  778. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  779. {$endif}
  780. CurrSecType:=sec_none;
  781. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  782. LastInfile:=nil;
  783. if assigned(current_module.mainsource) then
  784. {$IFDEF USE_SYSUTILS}
  785. begin
  786. p := SplitPath(current_module.mainsource^);
  787. n := SplitName(current_module.mainsource^);
  788. e := SplitExtension(current_module.mainsource^);
  789. end
  790. {$ELSE USE_SYSUTILS}
  791. fsplit(current_module.mainsource^,p,n,e)
  792. {$ENDIF USE_SYSUTILS}
  793. else
  794. begin
  795. p:=inputdir;
  796. n:=inputfile;
  797. e:=inputextension;
  798. end;
  799. { to get symify to work }
  800. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  801. WriteExtraHeader;
  802. AsmStartSize:=AsmSize;
  803. symendcount:=0;
  804. for hal:=low(Tasmlist) to high(Tasmlist) do
  805. begin
  806. AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
  807. writetree(asmlist[hal]);
  808. AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
  809. end;
  810. AsmLn;
  811. {$ifdef EXTDEBUG}
  812. if assigned(current_module.mainsource) then
  813. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  814. {$endif EXTDEBUG}
  815. end;
  816. end.