aggas.pas 34 KB

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