aggas.pas 33 KB

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