aggas.pas 33 KB

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