aggas.pas 33 KB

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