1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14 15-module(hipe_sparc). 16-export([ 17 mk_temp/2, 18 mk_new_temp/1, 19 mk_new_nonallocatable_temp/1, 20 is_temp/1, 21 temp_reg/1, 22 temp_type/1, 23 temp_is_allocatable/1, 24 temp_is_precoloured/1, 25 26 mk_g0/0, 27 mk_ra/0, 28 mk_rv/0, 29 mk_sp/0, 30 mk_temp1/0, 31 mk_temp2/0, 32 33 mk_simm13/1, 34 mk_uimm5/1, 35 36 mk_mfa/3, 37 38 mk_prim/1, 39 is_prim/1, 40 prim_prim/1, 41 42 mk_sdesc/4, 43 44 mk_alu/4, 45 mk_mov/2, 46 mk_load/6, 47 48 mk_bp/3, 49 mk_b_label/1, 50 51 %% mk_br/4, 52 53 mk_call_rec/3, 54 55 mk_call_tail/2, 56 57 mk_comment/1, 58 59 mk_label/1, 60 is_label/1, 61 label_label/1, 62 63 mk_jmp/3, 64 mk_jmpl/2, 65 66 mk_pseudo_bp/4, 67 negate_cond/1, 68 69 %% mk_pseudo_br/5, 70 %% negate_rcond/1, 71 72 mk_pseudo_call/4, 73 pseudo_call_contlab/1, 74 pseudo_call_funv/1, 75 pseudo_call_linkage/1, 76 pseudo_call_sdesc/1, 77 78 mk_pseudo_call_prepare/1, 79 pseudo_call_prepare_nrstkargs/1, 80 81 mk_pseudo_move/2, 82 is_pseudo_move/1, 83 pseudo_move_dst/1, 84 pseudo_move_src/1, 85 86 mk_pseudo_ret/0, 87 88 mk_pseudo_set/2, 89 90 mk_pseudo_spill_move/3, 91 is_pseudo_spill_move/1, 92 93 mk_pseudo_tailcall/4, 94 pseudo_tailcall_funv/1, 95 pseudo_tailcall_linkage/1, 96 pseudo_tailcall_stkargs/1, 97 98 mk_pseudo_tailcall_prepare/0, 99 100 mk_rdy/1, 101 102 %% mk_sethi/2, 103 mk_nop/0, 104 mk_set/2, 105 mk_set/3, 106 mk_addi/4, 107 108 mk_store/4, 109 mk_store/6, 110 111 mk_fp_binary/4, 112 113 mk_fp_unary/3, 114 115 mk_pseudo_fload/4, 116 mk_fload/4, 117 118 mk_pseudo_fmove/2, 119 is_pseudo_fmove/1, 120 pseudo_fmove_src/1, 121 pseudo_fmove_dst/1, 122 123 mk_pseudo_spill_fmove/3, 124 is_pseudo_spill_fmove/1, 125 126 mk_pseudo_fstore/3, 127 mk_fstore/4, 128 129 mk_defun/8, 130 defun_code/1, 131 defun_data/1, 132 defun_formals/1, 133 defun_is_closure/1, 134 defun_is_leaf/1, 135 defun_mfa/1, 136 defun_var_range/1 137 ]). 138 139-include("hipe_sparc.hrl"). 140 141mk_temp(Reg, Type, Allocatable) -> 142 #sparc_temp{reg=Reg, type=Type, allocatable=Allocatable}. 143mk_temp(Reg, Type) -> mk_temp(Reg, Type, true). 144mk_new_temp(Type, Allocatable) -> 145 mk_temp(hipe_gensym:get_next_var(sparc), Type, Allocatable). 146mk_new_temp(Type) -> mk_new_temp(Type, true). 147mk_new_nonallocatable_temp(Type) -> mk_new_temp(Type, false). 148is_temp(X) -> case X of #sparc_temp{} -> true; _ -> false end. 149temp_reg(#sparc_temp{reg=Reg}) -> Reg. 150temp_type(#sparc_temp{type=Type}) -> Type. 151temp_is_allocatable(#sparc_temp{allocatable=A}) -> A. 152temp_is_precoloured(#sparc_temp{reg=Reg,type=Type}) -> 153 case Type of 154 %% 'double' -> hipe_sparc_registers:is_precoloured_fpr(Reg); 155 _ -> hipe_sparc_registers:is_precoloured_gpr(Reg) 156 end. 157 158mk_g0() -> mk_temp(hipe_sparc_registers:g0(), 'untagged'). 159mk_ra() -> mk_temp(hipe_sparc_registers:return_address(), 'untagged'). 160mk_rv() -> mk_temp(hipe_sparc_registers:return_value(), 'tagged'). 161mk_sp() -> mk_temp(hipe_sparc_registers:stack_pointer(), 'untagged'). 162mk_temp1() -> mk_temp(hipe_sparc_registers:temp1(), 'untagged'). 163mk_temp2() -> mk_temp(hipe_sparc_registers:temp2(), 'untagged'). 164 165mk_simm13(Value) -> #sparc_simm13{value=Value}. 166mk_uimm5(Value) -> #sparc_uimm5{value=Value}. 167mk_uimm22(Value) -> #sparc_uimm22{value=Value}. 168 169mk_mfa(M, F, A) -> #sparc_mfa{m=M, f=F, a=A}. 170 171mk_prim(Prim) -> #sparc_prim{prim=Prim}. 172is_prim(X) -> case X of #sparc_prim{} -> true; _ -> false end. 173prim_prim(#sparc_prim{prim=Prim}) -> Prim. 174 175mk_sdesc(ExnLab, FSize, Arity, Live) -> 176 #sparc_sdesc{exnlab=ExnLab, fsize=FSize, arity=Arity, live=Live}. 177 178mk_alu(AluOp, Src1, Src2, Dst) -> 179 #alu{aluop=AluOp, src1=Src1, src2=Src2, dst=Dst}. 180mk_mov(Src, Dst) -> mk_alu('or', mk_g0(), Src, Dst). 181 182mk_bp(Cond, Label, Pred) -> #bp{'cond'=Cond, label=Label, pred=Pred}. 183mk_b_label(Label) -> mk_bp('a', Label, 1.0). 184 185-ifdef(notdef). % XXX: only for sparc64, alas 186mk_br(RCond, Src, Label, Pred) -> 187 #br{rcond=RCond, src=Src, label=Label, pred=Pred}. 188-endif. 189 190mk_call_rec(Fun, SDesc, Linkage) -> 191 #call_rec{'fun'=Fun, sdesc=SDesc, linkage=Linkage}. 192 193mk_call_tail(Fun, Linkage) -> #call_tail{'fun'=Fun, linkage=Linkage}. 194 195mk_comment(Term) -> #comment{term=Term}. 196 197mk_label(Label) -> #label{label=Label}. 198is_label(I) -> case I of #label{} -> true; _ -> false end. 199label_label(#label{label=Label}) -> Label. 200 201mk_jmp(Src1, Src2, Labels) -> #jmp{src1=Src1, src2=Src2, labels=Labels}. 202 203mk_jmpl(Src, SDesc) -> #jmpl{src=Src, sdesc=SDesc}. 204 205mk_pseudo_bp(Cond, TrueLab, FalseLab, Pred) -> 206 if Pred >= 0.5 -> 207 mk_pseudo_bp_simple(negate_cond(Cond), FalseLab, 208 TrueLab, 1.0-Pred); 209 true -> 210 mk_pseudo_bp_simple(Cond, TrueLab, FalseLab, Pred) 211 end. 212 213mk_pseudo_bp_simple(Cond, TrueLab, FalseLab, Pred) when Pred =< 0.5 -> 214 #pseudo_bp{'cond'=Cond, true_label=TrueLab, 215 false_label=FalseLab, pred=Pred}. 216 217negate_cond(Cond) -> 218 case Cond of 219 'l' -> 'ge'; % <, >= 220 'ge' -> 'l'; % >=, < 221 'g' -> 'le'; % >, <= 222 'le' -> 'g'; % <=, > 223 'e' -> 'ne'; % ==, != 224 'ne' -> 'e'; % !=, == 225 'gu' -> 'leu'; % >u, <=u 226 'leu'-> 'gu'; % <=u, >u 227 'geu'-> 'lu'; % >=u, <u 228 'lu' -> 'geu'; % <u, >=u 229 'vs' -> 'vc'; % overflow, not_overflow 230 'vc' -> 'vs' % not_overflow, overflow 231 end. 232 233-ifdef(notdef). % XXX: only for sparc64, alas 234mk_pseudo_br(RCond, Src, TrueLab, FalseLab, Pred) -> 235 if Pred >= 0.5 -> 236 mk_pseudo_br_simple(negate_rcond(RCond), Src, FalseLab, 237 TrueLab, 1.0-Pred); 238 true -> 239 mk_pseudo_br_simple(RCond, Src, TrueLab, FalseLab, Pred) 240 end. 241 242mk_pseudo_br_simple(RCond, Src, TrueLab, FalseLab, Pred) when Pred =< 0.5 -> 243 #pseudo_br{rcond=RCond, src=Src, true_label=TrueLab, 244 false_label=FalseLab, pred=Pred}. 245 246negate_rcond(RCond) -> 247 case RCond of 248 'z' -> 'nz'; % ==, != 249 'nz' -> 'z'; % !=, == 250 'gz' -> 'lez'; % >, <= 251 'lez' -> 'gz'; % <=, > 252 'gez' -> 'lz'; % >=, < 253 'lz' -> 'gez' % <, >= 254 end. 255-endif. 256 257mk_pseudo_call(FunV, SDesc, ContLab, Linkage) -> 258 #pseudo_call{funv=FunV, sdesc=SDesc, contlab=ContLab, linkage=Linkage}. 259pseudo_call_funv(#pseudo_call{funv=FunV}) -> FunV. 260pseudo_call_contlab(#pseudo_call{contlab=ContLab}) -> ContLab. 261pseudo_call_linkage(#pseudo_call{linkage=Linkage}) -> Linkage. 262pseudo_call_sdesc(#pseudo_call{sdesc=SDesc}) -> SDesc. 263 264mk_pseudo_call_prepare(NrStkArgs) -> 265 #pseudo_call_prepare{nrstkargs=NrStkArgs}. 266pseudo_call_prepare_nrstkargs(#pseudo_call_prepare{nrstkargs=NrStkArgs}) -> 267 NrStkArgs. 268 269mk_pseudo_move(Src, Dst) -> #pseudo_move{src=Src, dst=Dst}. 270is_pseudo_move(I) -> case I of #pseudo_move{} -> true; _ -> false end. 271pseudo_move_dst(#pseudo_move{dst=Dst}) -> Dst. 272pseudo_move_src(#pseudo_move{src=Src}) -> Src. 273 274mk_pseudo_ret() -> #pseudo_ret{}. 275 276mk_pseudo_set(Imm, Dst) -> #pseudo_set{imm=Imm, dst=Dst}. 277 278mk_pseudo_spill_move(Src, Temp, Dst) -> 279 #pseudo_spill_move{src=Src, temp=Temp, dst=Dst}. 280is_pseudo_spill_move(I) -> is_record(I, pseudo_spill_move). 281 282mk_pseudo_tailcall(FunV, Arity, StkArgs, Linkage) -> 283 #pseudo_tailcall{funv=FunV, arity=Arity, stkargs=StkArgs, linkage=Linkage}. 284pseudo_tailcall_funv(#pseudo_tailcall{funv=FunV}) -> FunV. 285pseudo_tailcall_linkage(#pseudo_tailcall{linkage=Linkage}) -> Linkage. 286pseudo_tailcall_stkargs(#pseudo_tailcall{stkargs=StkArgs}) -> StkArgs. 287 288mk_pseudo_tailcall_prepare() -> #pseudo_tailcall_prepare{}. 289 290mk_rdy(Dst) -> #rdy{dst=Dst}. 291 292mk_sethi(UImm22, Dst) -> #sethi{uimm22=UImm22, dst=Dst}. 293mk_nop() -> mk_sethi(mk_uimm22(0), mk_g0()). 294 295%%% Load an integer constant into a register. 296mk_set(Value, Dst) -> mk_set(Value, Dst, []). 297 298mk_set(Value, Dst, Tail) -> 299 if -4096 =< Value, Value < 4096 -> 300 [mk_alu('or', mk_g0(), mk_simm13(Value), Dst) | Tail]; 301 true -> 302 Hi22 = mk_uimm22((Value bsr 10) band 16#003FFFFF), 303 case (Value band 16#3FF) of 304 0 -> 305 [mk_sethi(Hi22, Dst) | Tail]; 306 Lo10 -> 307 [mk_sethi(Hi22, Dst), 308 mk_alu('or', Dst, mk_simm13(Lo10), Dst) | 309 Tail] 310 end 311 end. 312 313%%% Add an integer constant. Dst may equal Src, 314%%% in which case temp2 may be clobbered. 315mk_addi(Src, Value, Dst, Tail) -> 316 if -4096 =< Value, Value < 4096 -> 317 [mk_alu('add', Src, mk_simm13(Value), Dst) | Tail]; 318 true -> 319 Tmp = 320 begin 321 DstReg = temp_reg(Dst), 322 SrcReg = temp_reg(Src), 323 if DstReg =:= SrcReg -> mk_temp2(); 324 true -> Dst 325 end 326 end, 327 mk_set(Value, Tmp, [mk_alu('add', Src, Tmp, Dst) | Tail]) 328 end. 329 330mk_store(StOp, Src, Base, Disp) -> 331 #store{stop=StOp, src=Src, base=Base, disp=Disp}. 332 333mk_store(StOp, Src, Base, Offset, Scratch, Rest) when is_integer(Offset) -> 334 if -4096 =< Offset, Offset < 4096 -> 335 [mk_store(StOp, Src, Base, mk_simm13(Offset)) | Rest]; 336 true -> 337 Index = mk_scratch(Scratch), 338 mk_set(Offset, Index, [mk_store(StOp, Src, Base, Index) | Rest]) 339 end. 340 341mk_load(LdOp, Base, Disp, Dst) -> 342 mk_alu(LdOp, Base, Disp, Dst). 343 344mk_load(LdOp, Base, Offset, Dst, Scratch, Rest) when is_integer(Offset) -> 345 if -4096 =< Offset, Offset < 4096 -> 346 [mk_load(LdOp, Base, mk_simm13(Offset), Dst) | Rest]; 347 true -> 348 Index = 349 begin 350 DstReg = temp_reg(Dst), 351 BaseReg = temp_reg(Base), 352 if DstReg =/= BaseReg -> Dst; 353 true -> mk_scratch(Scratch) 354 end 355 end, 356 mk_set(Offset, Index, [mk_load(LdOp, Base, Index, Dst) | Rest]) 357 end. 358 359mk_scratch(Scratch) -> 360 case Scratch of 361 'temp2' -> mk_temp2(); 362 'new' -> mk_new_temp('untagged') 363 end. 364 365mk_fp_binary(FpBinOp, Src1, Src2, Dst) -> 366 #fp_binary{fp_binop=FpBinOp, src1=Src1, src2=Src2, dst=Dst}. 367 368mk_fp_unary(FpUnOp, Src, Dst) -> #fp_unary{fp_unop=FpUnOp, src=Src, dst=Dst}. 369 370mk_pseudo_fload(Base, Disp, Dst, IsSingle) -> 371 #pseudo_fload{base=Base, disp=Disp, dst=Dst, is_single=IsSingle}. 372 373mk_fload(Base, Disp, Dst, Scratch) when is_integer(Disp) -> 374 if -4096 =< Disp, Disp < (4096-4) -> 375 [mk_pseudo_fload(Base, mk_simm13(Disp), Dst, false)]; 376 true -> 377 Tmp = mk_scratch(Scratch), 378 mk_set(Disp, Tmp, 379 [mk_alu('add', Tmp, Base, Tmp), 380 mk_pseudo_fload(Tmp, mk_simm13(0), Dst, false)]) 381 end. 382 383mk_pseudo_fmove(Src, Dst) -> #pseudo_fmove{src=Src, dst=Dst}. 384is_pseudo_fmove(I) -> case I of #pseudo_fmove{} -> true; _ -> false end. 385pseudo_fmove_src(#pseudo_fmove{src=Src}) -> Src. 386pseudo_fmove_dst(#pseudo_fmove{dst=Dst}) -> Dst. 387 388mk_pseudo_spill_fmove(Src, Temp, Dst) -> 389 #pseudo_spill_fmove{src=Src, temp=Temp, dst=Dst}. 390is_pseudo_spill_fmove(I) -> is_record(I, pseudo_spill_fmove). 391 392mk_pseudo_fstore(Src, Base, Disp) -> 393 #pseudo_fstore{src=Src, base=Base, disp=Disp}. 394 395mk_fstore(Src, Base, Disp, Scratch) when is_integer(Disp) -> 396 if -4096 =< Disp, Disp < (4096-4) -> 397 [mk_pseudo_fstore(Src, Base, hipe_sparc:mk_simm13(Disp))]; 398 true -> 399 Tmp = mk_scratch(Scratch), 400 mk_set(Disp, Tmp, 401 [mk_alu('add', Tmp, Base, Tmp), 402 mk_pseudo_fstore(Src, Tmp, mk_simm13(0))]) 403 end. 404 405mk_defun(MFA, Formals, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) -> 406 #defun{mfa=MFA, formals=Formals, code=Code, data=Data, 407 isclosure=IsClosure, isleaf=IsLeaf, 408 var_range=VarRange, label_range=LabelRange}. 409defun_code(#defun{code=Code}) -> Code. 410defun_data(#defun{data=Data}) -> Data. 411defun_formals(#defun{formals=Formals}) -> Formals. 412defun_is_closure(#defun{isclosure=IsClosure}) -> IsClosure. 413defun_is_leaf(#defun{isleaf=IsLeaf}) -> IsLeaf. 414defun_mfa(#defun{mfa=MFA}) -> MFA. 415defun_var_range(#defun{var_range=VarRange}) -> VarRange. 416