aggas.pas 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  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. consttyp : taitype;
  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. case tai_const(hp).consttype of
  496. {$ifndef cpu64bit}
  497. aitconst_128bit :
  498. begin
  499. internalerror(200404291);
  500. end;
  501. aitconst_64bit :
  502. begin
  503. if assigned(tai_const(hp).sym) then
  504. internalerror(200404292);
  505. AsmWrite(ait_const2str[aitconst_32bit]);
  506. if target_info.endian = endian_little then
  507. begin
  508. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  509. AsmWrite(',');
  510. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  511. end
  512. else
  513. begin
  514. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  515. AsmWrite(',');
  516. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  517. end;
  518. AsmLn;
  519. end;
  520. {$endif cpu64bit}
  521. aitconst_uleb128bit,
  522. aitconst_sleb128bit,
  523. {$ifdef cpu64bit}
  524. aitconst_128bit,
  525. aitconst_64bit,
  526. {$endif cpu64bit}
  527. aitconst_32bit,
  528. aitconst_16bit,
  529. aitconst_8bit,
  530. aitconst_rva_symbol,
  531. aitconst_indirect_symbol :
  532. begin
  533. if (target_info.system in [system_powerpc_darwin,system_i386_darwin]) and
  534. (tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) then
  535. begin
  536. AsmWrite(ait_const2str[aitconst_8bit]);
  537. case tai_const(hp).consttype of
  538. aitconst_uleb128bit:
  539. WriteDecodedUleb128(aword(tai_const(hp).value));
  540. aitconst_sleb128bit:
  541. WriteDecodedSleb128(aint(tai_const(hp).value));
  542. end
  543. end
  544. else
  545. begin
  546. AsmWrite(ait_const2str[tai_const(hp).consttype]);
  547. consttyp:=hp.typ;
  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<>consttyp) or
  579. assigned(tai_const(hp.next).sym) then
  580. break;
  581. hp:=tai(hp.next);
  582. AsmWrite(',');
  583. until false;
  584. if (t <> '') then
  585. begin
  586. AsmLn;
  587. AsmWrite(t);
  588. end;
  589. end;
  590. AsmLn;
  591. end;
  592. end;
  593. end;
  594. {$ifdef cpuextended}
  595. ait_real_80bit :
  596. begin
  597. if do_line then
  598. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
  599. { Make sure e is a extended type, bestreal could be
  600. a different type (bestreal) !! (PFV) }
  601. e:=tai_real_80bit(hp).value;
  602. AsmWrite(#9'.byte'#9);
  603. for i:=0 to 9 do
  604. begin
  605. if i<>0 then
  606. AsmWrite(',');
  607. AsmWrite(tostr(t80bitarray(e)[i]));
  608. end;
  609. AsmLn;
  610. end;
  611. {$endif cpuextended}
  612. ait_real_64bit :
  613. begin
  614. if do_line then
  615. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  616. d:=tai_real_64bit(hp).value;
  617. { swap the values to correct endian if required }
  618. if source_info.endian <> target_info.endian then
  619. swap64bitarray(t64bitarray(d));
  620. AsmWrite(#9'.byte'#9);
  621. {$ifdef arm}
  622. { on a real arm cpu, it's already hi/lo swapped }
  623. {$ifndef cpuarm}
  624. if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
  625. begin
  626. for i:=4 to 7 do
  627. begin
  628. if i<>4 then
  629. AsmWrite(',');
  630. AsmWrite(tostr(t64bitarray(d)[i]));
  631. end;
  632. for i:=0 to 3 do
  633. begin
  634. AsmWrite(',');
  635. AsmWrite(tostr(t64bitarray(d)[i]));
  636. end;
  637. end
  638. else
  639. {$endif cpuarm}
  640. {$endif arm}
  641. begin
  642. for i:=0 to 7 do
  643. begin
  644. if i<>0 then
  645. AsmWrite(',');
  646. AsmWrite(tostr(t64bitarray(d)[i]));
  647. end;
  648. end;
  649. AsmLn;
  650. end;
  651. ait_real_32bit :
  652. begin
  653. if do_line then
  654. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  655. sin:=tai_real_32bit(hp).value;
  656. { swap the values to correct endian if required }
  657. if source_info.endian <> target_info.endian then
  658. swap32bitarray(t32bitarray(sin));
  659. AsmWrite(#9'.byte'#9);
  660. for i:=0 to 3 do
  661. begin
  662. if i<>0 then
  663. AsmWrite(',');
  664. AsmWrite(tostr(t32bitarray(sin)[i]));
  665. end;
  666. AsmLn;
  667. end;
  668. ait_comp_64bit :
  669. begin
  670. if do_line then
  671. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
  672. AsmWrite(#9'.byte'#9);
  673. {$ifdef FPC}
  674. co:=comp(tai_comp_64bit(hp).value);
  675. {$else}
  676. co:=tai_comp_64bit(hp).value;
  677. {$endif}
  678. { swap the values to correct endian if required }
  679. if source_info.endian <> target_info.endian then
  680. swap64bitarray(t64bitarray(co));
  681. for i:=0 to 7 do
  682. begin
  683. if i<>0 then
  684. AsmWrite(',');
  685. AsmWrite(tostr(t64bitarray(co)[i]));
  686. end;
  687. AsmLn;
  688. end;
  689. ait_string :
  690. begin
  691. pos:=0;
  692. for i:=1 to tai_string(hp).len do
  693. begin
  694. if pos=0 then
  695. begin
  696. AsmWrite(#9'.ascii'#9'"');
  697. pos:=20;
  698. end;
  699. ch:=tai_string(hp).str[i-1];
  700. case ch of
  701. #0, {This can't be done by range, because a bug in FPC}
  702. #1..#31,
  703. #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
  704. '"' : s:='\"';
  705. '\' : s:='\\';
  706. else
  707. s:=ch;
  708. end;
  709. AsmWrite(s);
  710. inc(pos,length(s));
  711. if (pos>line_length) or (i=tai_string(hp).len) then
  712. begin
  713. AsmWriteLn('"');
  714. pos:=0;
  715. end;
  716. end;
  717. end;
  718. ait_label :
  719. begin
  720. if (tai_label(hp).l.is_used) then
  721. begin
  722. if tai_label(hp).l.defbind=AB_GLOBAL then
  723. begin
  724. AsmWrite('.globl'#9);
  725. AsmWriteLn(tai_label(hp).l.name);
  726. end;
  727. AsmWrite(tai_label(hp).l.name);
  728. AsmWriteLn(':');
  729. end;
  730. end;
  731. ait_symbol :
  732. begin
  733. if tai_symbol(hp).is_global then
  734. begin
  735. AsmWrite('.globl'#9);
  736. AsmWriteLn(tai_symbol(hp).sym.name);
  737. end;
  738. if (target_info.system = system_powerpc64_linux) and
  739. (tai_symbol(hp).sym.typ = AT_FUNCTION) then
  740. begin
  741. AsmWriteLn('.section "opd", "aw"');
  742. AsmWriteLn('.align 3');
  743. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  744. AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
  745. AsmWriteLn('.previous');
  746. AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
  747. AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
  748. AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
  749. { the dotted name is the name of the actual function entry }
  750. AsmWrite('.');
  751. end
  752. else
  753. begin
  754. if (target_info.system <> system_arm_linux) then
  755. begin
  756. sepChar := '@';
  757. end
  758. else
  759. begin
  760. sepChar := '#';
  761. end;
  762. if (tf_needs_symbol_type in target_info.flags) then
  763. begin
  764. AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
  765. if (needsObject(tai_symbol(hp))) then
  766. begin
  767. AsmWriteLn(',' + sepChar + 'object');
  768. end
  769. else
  770. begin
  771. AsmWriteLn(',' + sepChar + 'function');
  772. end;
  773. end;
  774. if (tf_needs_symbol_size in target_info.flags) and (tai_symbol(hp).sym.size > 0) then begin
  775. AsmWriteLn(#9'.size'#9 + tai_symbol(hp).sym.name + ', ' + tostr(tai_symbol(hp).sym.size));
  776. end;
  777. end;
  778. AsmWriteLn(tai_symbol(hp).sym.name + ':');
  779. end;
  780. ait_symbol_end :
  781. begin
  782. if tf_needs_symbol_size in target_info.flags then
  783. begin
  784. s:=target_asm.labelprefix+'e'+tostr(symendcount);
  785. inc(symendcount);
  786. AsmWriteLn(s+':');
  787. AsmWrite(#9'.size'#9);
  788. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  789. AsmWrite('.');
  790. AsmWrite(tai_symbol_end(hp).sym.name);
  791. AsmWrite(', '+s+' - ');
  792. if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
  793. AsmWrite('.');
  794. AsmWriteLn(tai_symbol_end(hp).sym.name);
  795. end;
  796. end;
  797. ait_instruction :
  798. begin
  799. WriteInstruction(hp);
  800. end;
  801. ait_stab :
  802. begin
  803. if assigned(tai_stab(hp).str) then
  804. begin
  805. AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
  806. AsmWritePChar(tai_stab(hp).str);
  807. AsmLn;
  808. end;
  809. end;
  810. ait_file :
  811. begin
  812. AsmWrite(#9'.file '+tostr(tai_file(hp).idx)+' "');
  813. AsmWritePChar(tai_file(hp).str);
  814. AsmWrite('"');
  815. AsmLn;
  816. end;
  817. ait_loc :
  818. begin
  819. AsmWrite(#9'.loc '+tostr(tai_loc(hp).fileidx)+' '+tostr(tai_loc(hp).line)+' '+tostr(tai_loc(hp).column));
  820. AsmLn;
  821. end;
  822. ait_force_line,
  823. ait_function_name : ;
  824. ait_cutobject :
  825. begin
  826. if SmartAsm then
  827. begin
  828. { only reset buffer if nothing has changed }
  829. if AsmSize=AsmStartSize then
  830. AsmClear
  831. else
  832. begin
  833. AsmClose;
  834. DoAssemble;
  835. AsmCreate(tai_cutobject(hp).place);
  836. end;
  837. { avoid empty files }
  838. while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
  839. begin
  840. if tai(hp.next).typ=ait_section then
  841. CurrSecType:=tai_section(hp.next).sectype;
  842. hp:=tai(hp.next);
  843. end;
  844. if CurrSecType<>sec_none then
  845. WriteSection(CurrSecType,'');
  846. AsmStartSize:=AsmSize;
  847. end;
  848. end;
  849. ait_marker :
  850. if tai_marker(hp).kind=InlineStart then
  851. inc(InlineLevel)
  852. else if tai_marker(hp).kind=InlineEnd then
  853. dec(InlineLevel);
  854. ait_directive :
  855. begin
  856. AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
  857. if assigned(tai_directive(hp).name) then
  858. AsmWrite(tai_directive(hp).name^);
  859. AsmLn;
  860. end;
  861. else
  862. internalerror(2006012201);
  863. end;
  864. hp:=tai(hp.next);
  865. end;
  866. end;
  867. procedure TGNUAssembler.WriteExtraHeader;
  868. begin
  869. end;
  870. procedure TGNUAssembler.WriteAsmList;
  871. var
  872. p:dirstr;
  873. n:namestr;
  874. e:extstr;
  875. hal : tasmlist;
  876. begin
  877. {$ifdef EXTDEBUG}
  878. if assigned(current_module.mainsource) then
  879. Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
  880. {$endif}
  881. CurrSecType:=sec_none;
  882. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  883. LastInfile:=nil;
  884. if assigned(current_module.mainsource) then
  885. {$IFDEF USE_SYSUTILS}
  886. begin
  887. p := SplitPath(current_module.mainsource^);
  888. n := SplitName(current_module.mainsource^);
  889. e := SplitExtension(current_module.mainsource^);
  890. end
  891. {$ELSE USE_SYSUTILS}
  892. fsplit(current_module.mainsource^,p,n,e)
  893. {$ENDIF USE_SYSUTILS}
  894. else
  895. begin
  896. p:=inputdir;
  897. n:=inputfile;
  898. e:=inputextension;
  899. end;
  900. { to get symify to work }
  901. AsmWriteLn(#9'.file "'+FixFileName(n+e)+'"');
  902. WriteExtraHeader;
  903. AsmStartSize:=AsmSize;
  904. symendcount:=0;
  905. for hal:=low(Tasmlist) to high(Tasmlist) do
  906. begin
  907. AsmWriteLn(target_asm.comment+'Begin asmlist '+TasmlistStr[hal]);
  908. writetree(asmlist[hal]);
  909. AsmWriteLn(target_asm.comment+'End asmlist '+TasmlistStr[hal]);
  910. end;
  911. AsmLn;
  912. {$ifdef EXTDEBUG}
  913. if assigned(current_module.mainsource) then
  914. Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
  915. {$endif EXTDEBUG}
  916. end;
  917. end.