cgcpu.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the code generator for the SPARC
  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 cgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,parabase,
  22. cgbase,cgutils,cgobj,
  23. {$ifndef SPARC64}
  24. cg64f32,
  25. {$endif SPARC64}
  26. aasmbase,aasmtai,aasmdata,aasmcpu,
  27. cpubase,cpuinfo,
  28. node,symconst,SymType,symdef,
  29. rgcpu,
  30. cgsparc;
  31. type
  32. TCGSparc=class(TCGSparcGen)
  33. procedure a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize; reg1,reg2 : tregister);override;
  34. procedure a_load_const_reg(list : TAsmList; size : TCGSize; a : tcgint; reg : TRegister);override;
  35. end;
  36. TCg64Sparc=class(tcg64f32)
  37. private
  38. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
  39. public
  40. procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
  41. procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
  42. procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  43. procedure a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);override;
  44. procedure a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);override;
  45. procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
  46. procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
  47. procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  48. procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  49. end;
  50. procedure create_codegen;
  51. implementation
  52. uses
  53. verbose,
  54. systems;
  55. procedure TCGSparc.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  56. var
  57. instr : taicpu;
  58. begin
  59. if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
  60. ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
  61. (fromsize <> tosize)) or
  62. { needs to mask out the sign in the top 16 bits }
  63. ((fromsize = OS_S8) and
  64. (tosize = OS_16)) then
  65. case tosize of
  66. OS_8 :
  67. list.concat(taicpu.op_reg_const_reg(A_AND,reg1,$ff,reg2));
  68. OS_16 :
  69. begin
  70. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
  71. list.concat(taicpu.op_reg_const_reg(A_SRL,reg2,16,reg2));
  72. end;
  73. OS_32,
  74. OS_S32 :
  75. begin
  76. instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
  77. list.Concat(instr);
  78. { Notify the register allocator that we have written a move instruction so
  79. it can try to eliminate it. }
  80. add_move_instruction(instr);
  81. end;
  82. OS_S8 :
  83. begin
  84. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
  85. list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
  86. end;
  87. OS_S16 :
  88. begin
  89. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
  90. list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
  91. end;
  92. else
  93. internalerror(2002090901);
  94. end
  95. else
  96. begin
  97. instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
  98. list.Concat(instr);
  99. { Notify the register allocator that we have written a move instruction so
  100. it can try to eliminate it. }
  101. add_move_instruction(instr);
  102. end;
  103. end;
  104. procedure TCGSparc.a_load_const_reg(list : TAsmList;size : TCGSize;a : tcgint;reg : TRegister);
  105. begin
  106. { we don't use the set instruction here because it could be evalutated to two
  107. instructions which would cause problems with the delay slot (FK) }
  108. if (a=0) then
  109. list.concat(taicpu.op_reg(A_CLR,reg))
  110. else if (a>=simm13lo) and (a<=simm13hi) then
  111. list.concat(taicpu.op_const_reg(A_MOV,a,reg))
  112. else
  113. begin
  114. list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg));
  115. if (aint(a) and aint($3ff))<>0 then
  116. list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
  117. end;
  118. end;
  119. {****************************************************************************
  120. TCG64Sparc
  121. ****************************************************************************}
  122. procedure tcg64sparc.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
  123. var
  124. tmpref: treference;
  125. begin
  126. { Override this function to prevent loading the reference twice }
  127. tmpref:=ref;
  128. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  129. inc(tmpref.offset,4);
  130. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
  131. end;
  132. procedure tcg64sparc.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  133. var
  134. tmpref: treference;
  135. begin
  136. { Override this function to prevent loading the reference twice }
  137. tmpref:=ref;
  138. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  139. inc(tmpref.offset,4);
  140. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  141. end;
  142. procedure tcg64sparc.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  143. var
  144. hreg64 : tregister64;
  145. begin
  146. { Override this function to prevent loading the reference twice.
  147. Use here some extra registers, but those are optimized away by the RA }
  148. hreg64.reglo:=cg.GetIntRegister(list,OS_32);
  149. hreg64.reghi:=cg.GetIntRegister(list,OS_32);
  150. a_load64_ref_reg(list,r,hreg64);
  151. a_load64_reg_cgpara(list,hreg64,paraloc);
  152. end;
  153. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
  154. begin
  155. case op of
  156. OP_ADD :
  157. begin
  158. op1:=A_ADDCC;
  159. if checkoverflow then
  160. op2:=A_ADDXCC
  161. else
  162. op2:=A_ADDX;
  163. end;
  164. OP_SUB :
  165. begin
  166. op1:=A_SUBCC;
  167. if checkoverflow then
  168. op2:=A_SUBXCC
  169. else
  170. op2:=A_SUBX;
  171. end;
  172. OP_XOR :
  173. begin
  174. op1:=A_XOR;
  175. op2:=A_XOR;
  176. end;
  177. OP_OR :
  178. begin
  179. op1:=A_OR;
  180. op2:=A_OR;
  181. end;
  182. OP_AND :
  183. begin
  184. op1:=A_AND;
  185. op2:=A_AND;
  186. end;
  187. else
  188. internalerror(200203241);
  189. end;
  190. end;
  191. procedure TCg64Sparc.a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);
  192. begin
  193. case op of
  194. OP_NEG :
  195. begin
  196. { Use the simple code: y=0-z }
  197. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
  198. list.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,regsrc.reghi,regdst.reghi));
  199. end;
  200. OP_NOT :
  201. begin
  202. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
  203. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
  204. end;
  205. else
  206. a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
  207. end;
  208. end;
  209. procedure TCg64Sparc.a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);
  210. begin
  211. a_op64_const_reg_reg(list,op,size,value,regdst,regdst);
  212. end;
  213. procedure tcg64sparc.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
  214. var
  215. l : tlocation;
  216. begin
  217. a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,l);
  218. end;
  219. procedure tcg64sparc.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
  220. var
  221. l : tlocation;
  222. begin
  223. a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,l);
  224. end;
  225. procedure tcg64sparc.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  226. var
  227. op1,op2:TAsmOp;
  228. begin
  229. case op of
  230. OP_NEG,
  231. OP_NOT :
  232. internalerror(200306017);
  233. OP_AND,OP_OR,OP_XOR:
  234. begin
  235. cg.a_op_const_reg_reg(list,op,OS_INT,tcgint(lo(value)),regsrc.reglo,regdst.reglo);
  236. cg.a_op_const_reg_reg(list,op,OS_INT,tcgint(hi(value)),regsrc.reghi,regdst.reghi);
  237. end;
  238. else
  239. get_64bit_ops(op,op1,op2,setflags);
  240. tcgsparc(cg).handle_reg_const_reg(list,op1,regsrc.reglo,tcgint(lo(value)),regdst.reglo);
  241. tcgsparc(cg).handle_reg_const_reg(list,op2,regsrc.reghi,tcgint(hi(value)),regdst.reghi);
  242. end;
  243. end;
  244. procedure tcg64sparc.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  245. var
  246. op1,op2:TAsmOp;
  247. begin
  248. case op of
  249. OP_NEG,
  250. OP_NOT :
  251. internalerror(200306017);
  252. end;
  253. get_64bit_ops(op,op1,op2,setflags);
  254. list.concat(taicpu.op_reg_reg_reg(op1,regsrc2.reglo,regsrc1.reglo,regdst.reglo));
  255. list.concat(taicpu.op_reg_reg_reg(op2,regsrc2.reghi,regsrc1.reghi,regdst.reghi));
  256. end;
  257. procedure create_codegen;
  258. begin
  259. cg:=TCgSparc.Create;
  260. if target_info.system=system_sparc_linux then
  261. TCgSparc(cg).use_unlimited_pic_mode:=true
  262. else
  263. TCgSparc(cg).use_unlimited_pic_mode:=false;
  264. cg64:=TCg64Sparc.Create;
  265. end;
  266. end.