cpugas.pas 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. {
  2. Copyright (c) 1999-2003 by Florian Klaempfl
  3. This unit implements an asmoutput class for SPARC AT&T syntax
  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. unit cpugas;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cpubase,systems,
  22. aasmtai,aasmdata,aasmcpu,assemble,aggas,
  23. cgutils,globtype;
  24. type
  25. TGasSPARC=class(TGnuAssembler)
  26. constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
  27. {# Constructs the command line for calling the assembler }
  28. function MakeCmdLine: TCmdStr; override;
  29. end;
  30. TSPARCInstrWriter=class(TCPUInstrWriter)
  31. procedure WriteInstruction(hp:Tai);override;
  32. function GetReferenceString(var ref : TReference):string;
  33. function getopstr(const Oper:TOper):string;
  34. end;
  35. implementation
  36. uses
  37. cutils,globals,cpuinfo,procinfo,
  38. verbose,itcpugas,cgbase;
  39. {****************************************************************************}
  40. { GNU PPC Assembler writer }
  41. {****************************************************************************}
  42. constructor TGasSPARC.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
  43. begin
  44. inherited;
  45. InstrWriter := TSPARCInstrWriter.create(self);
  46. end;
  47. function TGasSPARC.MakeCmdLine: TCmdStr;
  48. begin
  49. result := Inherited MakeCmdLine;
  50. { ARCH selection }
  51. // Note for casual readers: gas (GNU as) uses -Av7, -Av8, -Av9 etc. on SPARC,
  52. // rather than variants of the -m option used by most other CPUs. Solaris as
  53. // uses -xarch=v7, -xarch=v8 etc., that form is not supported here since there
  54. // are probably other incompatibilties between the GNU and Solaris binutils
  55. // that need to be reviewed.
  56. //
  57. // v9 is required as the default since the RTL started using membar at 2.2.2.
  58. case current_settings.cputype of
  59. {$ifdef SPARC}
  60. cpu_SPARC_V7: Replace(result,'$ARCH','-Av7');
  61. cpu_SPARC_V8: Replace(result,'$ARCH','-Av8');
  62. {$endif SPARC}
  63. cpu_SPARC_V9: Replace(result,'$ARCH','-Av9');
  64. else
  65. Replace(result,'$ARCH','-Av9')
  66. end
  67. end;
  68. function TSPARCInstrWriter.GetReferenceString(var ref:TReference):string;
  69. begin
  70. result:='';
  71. if assigned(ref.symbol) then
  72. begin
  73. result:=ref.symbol.name;
  74. if assigned(ref.relsymbol) then
  75. result:=result+'-'+ref.relsymbol.name;
  76. end;
  77. if (ref.offset<0) then
  78. result:=result+tostr(ref.offset)
  79. else if (ref.offset>0) then
  80. begin
  81. if assigned(ref.symbol) then
  82. result:=result+'+';
  83. result:=result+tostr(ref.offset);
  84. end
  85. { asmreader appears to treat literal numbers as references }
  86. else if (ref.symbol=nil) and (ref.base=NR_NO) and (ref.index=NR_NO) then
  87. result:='0';
  88. case ref.refaddr of
  89. addr_high:
  90. result:='%hi('+result+')';
  91. addr_low:
  92. result:='%lo('+result+')';
  93. end;
  94. if assigned(ref.symbol) or (ref.offset<>0) then
  95. begin
  96. if (ref.base<>NR_NO) then
  97. begin
  98. if (ref.index<>NR_NO) then
  99. InternalError(2013013001);
  100. if (result[1]='-') then
  101. result:=gas_regname(ref.base)+result
  102. else
  103. result:=gas_regname(ref.base)+'+'+result;
  104. end
  105. else if (ref.index<>NR_NO) then
  106. InternalError(2013122501);
  107. end
  108. else
  109. begin
  110. if (ref.base<>NR_NO) then
  111. begin
  112. result:=gas_regname(ref.base);
  113. if (ref.index<>NR_NO) then
  114. result:=result+'+'+gas_regname(ref.index);
  115. end
  116. else if (ref.index<>NR_NO) then
  117. result:=gas_regname(ref.index);
  118. end;
  119. end;
  120. function TSPARCInstrWriter.getopstr(const Oper:TOper):string;
  121. begin
  122. with Oper do
  123. case typ of
  124. top_reg:
  125. getopstr:=gas_regname(reg);
  126. top_const:
  127. getopstr:=tostr(longint(val));
  128. top_ref:
  129. if (oper.ref^.refaddr in [addr_no,addr_pic]) or
  130. ((oper.ref^.refaddr=addr_low) and ((oper.ref^.base<>NR_NO) or
  131. (oper.ref^.index<>NR_NO))) then
  132. getopstr:='['+getreferencestring(ref^)+']'
  133. else
  134. getopstr:=getreferencestring(ref^);
  135. else
  136. internalerror(10001);
  137. end;
  138. end;
  139. procedure TSPARCInstrWriter.WriteInstruction(hp:Tai);
  140. procedure writePseudoInstruction(opc: TAsmOp);
  141. begin
  142. if (taicpu(hp).ops<>2) or
  143. (taicpu(hp).oper[0]^.typ<>top_reg) or
  144. (taicpu(hp).oper[1]^.typ<>top_reg) then
  145. internalerror(200401045);
  146. { Fxxxs %f<even>,%f<even> }
  147. owner.writer.AsmWriteln(#9+std_op2str[opc]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^));
  148. { FMOVs %f<odd>,%f<odd> }
  149. inc(taicpu(hp).oper[0]^.reg);
  150. inc(taicpu(hp).oper[1]^.reg);
  151. owner.writer.AsmWriteln(#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^));
  152. dec(taicpu(hp).oper[0]^.reg);
  153. dec(taicpu(hp).oper[1]^.reg);
  154. end;
  155. var
  156. Op:TAsmOp;
  157. s:String;
  158. i:Integer;
  159. begin
  160. if hp.typ<>ait_instruction then
  161. exit;
  162. op:=taicpu(hp).opcode;
  163. if (op=A_Bxx) and (taicpu(hp).condition in floatAsmConds) then
  164. op:=A_FBxx;
  165. { translate pseudoops, this should be move to a separate pass later, so it's done before
  166. peephole optimization }
  167. case op of
  168. A_FABSd:
  169. writePseudoInstruction(A_FABSs);
  170. A_FMOVd:
  171. writePseudoInstruction(A_FMOVs);
  172. A_FNEGd:
  173. writePseudoInstruction(A_FNEGs);
  174. else
  175. begin
  176. { call maybe not translated to call }
  177. s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition];
  178. if taicpu(hp).delayslot_annulled then
  179. s:=s+',a';
  180. if taicpu(hp).ops>0 then
  181. begin
  182. s:=s+#9+getopstr(taicpu(hp).oper[0]^);
  183. for i:=1 to taicpu(hp).ops-1 do
  184. s:=s+','+getopstr(taicpu(hp).oper[i]^);
  185. end;
  186. owner.writer.AsmWriteLn(s);
  187. end;
  188. end;
  189. end;
  190. const
  191. as_sparc_as_info : tasminfo =
  192. (
  193. id : as_gas;
  194. idtxt : 'AS';
  195. asmbin : 'as';
  196. {$ifdef FPC_SPARC_V8_ONLY}
  197. asmcmd : '$PIC -o $OBJ $EXTRAOPT $ASM';
  198. {$else}
  199. asmcmd : '$ARCH $PIC -32 -o $OBJ $EXTRAOPT $ASM';
  200. {$endif}
  201. supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
  202. flags : [af_needar,af_smartlink_sections];
  203. labelprefix : '.L';
  204. comment : '# ';
  205. dollarsign: '$';
  206. );
  207. as_sparc_gas_info : tasminfo =
  208. (
  209. id : as_ggas;
  210. idtxt : 'GAS';
  211. asmbin : 'gas';
  212. asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM';
  213. supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
  214. flags : [af_needar,af_smartlink_sections];
  215. labelprefix : '.L';
  216. comment : '# ';
  217. dollarsign: '$';
  218. );
  219. as_sparc64_as_info : tasminfo =
  220. (
  221. id : as_gas;
  222. idtxt : 'AS';
  223. asmbin : 'as';
  224. {$ifdef FPC_SPARC_V8_ONLY}
  225. asmcmd : '$PIC -o $OBJ $EXTRAOPT $ASM';
  226. {$else}
  227. asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM';
  228. {$endif}
  229. supported_targets : [system_sparc64_linux];
  230. flags : [af_needar,af_smartlink_sections];
  231. labelprefix : '.L';
  232. comment : '# ';
  233. dollarsign: '$';
  234. );
  235. as_sparc64_gas_info : tasminfo =
  236. (
  237. id : as_ggas;
  238. idtxt : 'GAS';
  239. asmbin : 'gas';
  240. asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM';
  241. supported_targets : [system_sparc64_linux];
  242. flags : [af_needar,af_smartlink_sections];
  243. labelprefix : '.L';
  244. comment : '# ';
  245. dollarsign: '$';
  246. );
  247. begin
  248. {$ifdef SPARC}
  249. RegisterAssembler(as_SPARC_as_info,TGasSPARC);
  250. RegisterAssembler(as_SPARC_gas_info,TGasSPARC);
  251. {$else SPARC}
  252. RegisterAssembler(as_SPARC64_as_info,TGasSPARC);
  253. RegisterAssembler(as_SPARC64_gas_info,TGasSPARC);
  254. {$endif SPARC}
  255. end.