cpugas.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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,
  22. aasmtai,aasmdata,aasmcpu,assemble,aggas;
  23. type
  24. TGasSPARC=class(TGnuAssembler)
  25. constructor create(smart: boolean); override;
  26. end;
  27. TSPARCInstrWriter=class(TCPUInstrWriter)
  28. procedure WriteInstruction(hp:Tai);override;
  29. end;
  30. implementation
  31. uses
  32. cutils,systems,
  33. verbose,itcpugas,cgbase,cgutils;
  34. {****************************************************************************}
  35. { GNU PPC Assembler writer }
  36. {****************************************************************************}
  37. constructor TGasSPARC.create(smart: boolean);
  38. begin
  39. inherited create(smart);
  40. InstrWriter := TSPARCInstrWriter.create(self);
  41. end;
  42. function GetReferenceString(var ref:TReference):string;
  43. begin
  44. GetReferenceString:='';
  45. with ref do
  46. begin
  47. if (base=NR_NO) and (index=NR_NO) then
  48. begin
  49. if assigned(symbol) then
  50. GetReferenceString:=symbol.name;
  51. if offset>0 then
  52. GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
  53. else if offset<0 then
  54. GetReferenceString:=GetReferenceString+ToStr(offset);
  55. case refaddr of
  56. addr_high:
  57. GetReferenceString:='%hi('+GetReferenceString+')';
  58. addr_low:
  59. GetReferenceString:='%lo('+GetReferenceString+')';
  60. end;
  61. end
  62. else
  63. begin
  64. {$ifdef extdebug}
  65. if assigned(symbol) and
  66. not(refaddr in [addr_pic,addr_low]) then
  67. internalerror(2003052601);
  68. {$endif extdebug}
  69. if base<>NR_NO then
  70. GetReferenceString:=GetReferenceString+gas_regname(base);
  71. if index=NR_NO then
  72. begin
  73. { if (Offset<simm13lo) or (Offset>simm13hi) then
  74. internalerror(2003053008); }
  75. if offset>0 then
  76. GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
  77. else if offset<0 then
  78. GetReferenceString:=GetReferenceString+ToStr(offset);
  79. {
  80. else if (offset=0) and not(assigned(symbol)) then
  81. GetReferenceString:=GetReferenceString+ToStr(offset);
  82. }
  83. if assigned(symbol) then
  84. begin
  85. if refaddr=addr_low then
  86. GetReferenceString:='%lo('+symbol.name+')+'+GetReferenceString
  87. else
  88. GetReferenceString:=symbol.name+'+'+GetReferenceString;
  89. end;
  90. end
  91. else
  92. begin
  93. {$ifdef extdebug}
  94. if (Offset<>0) or assigned(symbol) then
  95. internalerror(2003052603);
  96. {$endif extdebug}
  97. GetReferenceString:=GetReferenceString+'+'+gas_regname(index);
  98. end;
  99. end;
  100. end;
  101. end;
  102. function getopstr(const Oper:TOper):string;
  103. begin
  104. with Oper do
  105. case typ of
  106. top_reg:
  107. getopstr:=gas_regname(reg);
  108. top_const:
  109. getopstr:=tostr(longint(val));
  110. top_ref:
  111. if (oper.ref^.refaddr in [addr_no,addr_pic]) or ((oper.ref^.refaddr=addr_low) and ((oper.ref^.base<>NR_NO) or
  112. (oper.ref^.index<>NR_NO))) then
  113. getopstr:='['+getreferencestring(ref^)+']'
  114. else
  115. getopstr:=getreferencestring(ref^);
  116. else
  117. internalerror(10001);
  118. end;
  119. end;
  120. procedure TSPARCInstrWriter.WriteInstruction(hp:Tai);
  121. var
  122. Op:TAsmOp;
  123. s:String;
  124. i:Integer;
  125. begin
  126. if hp.typ<>ait_instruction then
  127. exit;
  128. op:=taicpu(hp).opcode;
  129. { translate pseudoops, this should be move to a separate pass later, so it's done before
  130. peephole optimization }
  131. case op of
  132. A_FABSd:
  133. begin
  134. if (taicpu(hp).ops<>2) or
  135. (taicpu(hp).oper[0]^.typ<>top_reg) or
  136. (taicpu(hp).oper[1]^.typ<>top_reg) then
  137. internalerror(200401045);
  138. { FABSs %f<even>,%f<even> }
  139. s:=#9+std_op2str[A_FABSs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
  140. owner.AsmWriteLn(s);
  141. { FMOVs %f<odd>,%f<odd> }
  142. inc(taicpu(hp).oper[0]^.reg);
  143. inc(taicpu(hp).oper[1]^.reg);
  144. s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
  145. dec(taicpu(hp).oper[0]^.reg);
  146. dec(taicpu(hp).oper[1]^.reg);
  147. owner.AsmWriteLn(s);
  148. end;
  149. A_FMOVd:
  150. begin
  151. if (taicpu(hp).ops<>2) or
  152. (taicpu(hp).oper[0]^.typ<>top_reg) or
  153. (taicpu(hp).oper[1]^.typ<>top_reg) then
  154. internalerror(200401045);
  155. { FMOVs %f<even>,%f<even> }
  156. s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
  157. owner.AsmWriteLn(s);
  158. { FMOVs %f<odd>,%f<odd> }
  159. inc(taicpu(hp).oper[0]^.reg);
  160. inc(taicpu(hp).oper[1]^.reg);
  161. s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
  162. dec(taicpu(hp).oper[0]^.reg);
  163. dec(taicpu(hp).oper[1]^.reg);
  164. owner.AsmWriteLn(s);
  165. end
  166. else
  167. begin
  168. { call maybe not translated to call }
  169. s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition];
  170. if taicpu(hp).delayslot_annulled then
  171. s:=s+',a';
  172. if taicpu(hp).ops>0 then
  173. begin
  174. s:=s+#9+getopstr(taicpu(hp).oper[0]^);
  175. for i:=1 to taicpu(hp).ops-1 do
  176. s:=s+','+getopstr(taicpu(hp).oper[i]^);
  177. end;
  178. owner.AsmWriteLn(s);
  179. end;
  180. end;
  181. end;
  182. const
  183. as_sparc_as_info : tasminfo =
  184. (
  185. id : as_gas;
  186. idtxt : 'AS';
  187. asmbin : 'as';
  188. {$ifdef FPC_SPARC_V8_ONLY}
  189. asmcmd : '-o $OBJ $ASM';
  190. {$else}
  191. asmcmd : '-Av9 -o $OBJ $ASM';
  192. {$endif}
  193. supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
  194. flags : [af_allowdirect,af_needar,af_smartlink_sections];
  195. labelprefix : '.L';
  196. comment : '# ';
  197. );
  198. as_sparc_gas_info : tasminfo =
  199. (
  200. id : as_ggas;
  201. idtxt : 'GAS';
  202. asmbin : 'gas';
  203. asmcmd : '-Av9 -o $OBJ $ASM';
  204. supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
  205. flags : [af_allowdirect,af_needar,af_smartlink_sections];
  206. labelprefix : '.L';
  207. comment : '# ';
  208. );
  209. begin
  210. RegisterAssembler(as_SPARC_as_info,TGasSPARC);
  211. RegisterAssembler(as_SPARC_gas_info,TGasSPARC);
  212. end.