aggas.pas 34 KB

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