aggas.pas 33 KB

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