aggas.pas 33 KB

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