cpugas.pas 9.6 KB

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