aggas.pas 29 KB

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