aggas.pas 34 KB

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