aggas.pas 32 KB

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