⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hipe_rtl_to_ppc.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 3 页
字号:
conv_alub_cond(Cond) ->	% only signed  case Cond of    eq	-> 'eq';    ne	-> 'ne';    gt	-> 'gt';    ge	-> 'ge';    lt	-> 'lt';    le	-> 'le';    overflow -> 'so';    not_overflow -> 'ns';    _	-> exit({?MODULE,conv_alub_cond,Cond})  end.mk_alub(Dst, Src1, RtlAluOp, Src2, BCond) ->  case hipe_ppc:is_temp(Src1) of    true ->      case hipe_ppc:is_temp(Src2) of	true ->	  mk_alub_rr(Dst, Src1, RtlAluOp, Src2, BCond);	_ ->	  mk_alub_ri(Dst, Src1, RtlAluOp, Src2, BCond)      end;    _ ->      case hipe_ppc:is_temp(Src2) of	true ->	  mk_alub_ir(Dst, Src1, RtlAluOp, Src2, BCond);	_ ->	  mk_alub_ii(Dst, Src1, RtlAluOp, Src2, BCond)      end  end.mk_alub_ii(Dst, Src1, RtlAluOp, Src2, BCond) ->  io:format("~w: RTL alub with two immediates\n", [?MODULE]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Src1,	mk_alub_ri(Dst, Tmp, RtlAluOp, Src2, BCond)).mk_alub_ir(Dst, Src1, RtlAluOp, Src2, BCond) ->  case rtl_aluop_commutes(RtlAluOp) of    true ->      mk_alub_ri(Dst, Src2, RtlAluOp, Src1, BCond);    _ ->      Tmp = new_untagged_temp(),      mk_li(Tmp, Src1,	    mk_alub_rr(Dst, Tmp, RtlAluOp, Src2, BCond))  end.mk_alub_ri(Dst, Src1, RtlAluOp, Src2, BCond) ->  true = is_integer(Src2),  case BCond of    'so' -> mk_alub_ri_OE(Dst, Src1, RtlAluOp, Src2);    'ns' -> mk_alub_ri_OE(Dst, Src1, RtlAluOp, Src2);    _ -> mk_alub_ri_Rc(Dst, Src1, RtlAluOp, Src2)  end.mk_alub_ri_OE(Dst, Src1, RtlAluOp, Src2) ->  %% Only 'add', 'sub', and 'mul' apply here, and 'sub' becomes 'add'.  %% 'add' and 'mul' have no immediate+Rc+OE forms.  %% Rewrite to reg/reg form. Sigh.  Tmp = new_untagged_temp(),  mk_li(Tmp, Src2,	mk_alub_rr_OE(Dst, Src1, RtlAluOp, Tmp)).mk_alub_ri_Rc(Dst, Src1, RtlAluOp, Src2) ->  case RtlAluOp of    'sub' ->	% there is no 'subi.'      mk_alub_ri_Rc_addi(Dst, Src1, -Src2);    'add' ->	% 'addic.' has a 16-bit simm operand      mk_alub_ri_Rc_addi(Dst, Src1, Src2);    'mul' ->	% there is no 'mulli.'      mk_alub_ri_Rc_rr(Dst, Src1, 'mullw.', Src2);    'or' ->	% there is no 'ori.'      mk_alub_ri_Rc_rr(Dst, Src1, 'or.', Src2);    'xor' ->	% there is no 'xori.'      mk_alub_ri_Rc_rr(Dst, Src1, 'xor.', Src2);    'and' ->	% 'andi.' has a 16-bit uimm operand      case rlwinm_mask(Src2) of	{MB,ME} ->	  [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)];	_ ->	  mk_alub_ri_Rc_andi(Dst, Src1, Src2)      end;    _ ->	% shift ops have 5-bit uimm operands      mk_alub_ri_Rc_shift(Dst, Src1, RtlAluOp, Src2)  end.mk_alub_ri_Rc_addi(Dst, Src1, Src2) ->  if is_integer(Src2), -32768 =< Src2, Src2 < 32768 ->      [hipe_ppc:mk_alu('addic.', Dst, Src1,		       hipe_ppc:mk_simm16(Src2))];     true ->      mk_alub_ri_Rc_rr(Dst, Src1, 'add.', Src2)  end.mk_alub_ri_Rc_andi(Dst, Src1, Src2) ->  if Src2 < 65536, Src2 >= 0 ->      [hipe_ppc:mk_alu('andi.', Dst, Src1,		       hipe_ppc:mk_uimm16(Src2))];     true ->      mk_alub_ri_Rc_rr(Dst, Src1, 'and.', Src2)  end.mk_alub_ri_Rc_shift(Dst, Src1, RtlAluOp, Src2) ->  if Src2 < 32, Src2 >= 0 ->      AluOp =	case RtlAluOp of	  'sll' -> 'slwi.'; % alias for rlwinm.	  'srl' -> 'srwi.'; % alias for rlwinm.	  'sra' -> 'srawi.'	end,      [hipe_ppc:mk_alu(AluOp, Dst, Src1,		       hipe_ppc:mk_uimm16(Src2))];     true ->      AluOp =	case RtlAluOp of	  'sll' -> 'slw.';	  'srl' -> 'srw.';	  'sra' -> 'sraw.'	end,      mk_alub_ri_Rc_rr(Dst, Src1, AluOp, Src2)  end.mk_alub_ri_Rc_rr(Dst, Src1, AluOp, Src2) ->  Tmp = new_untagged_temp(),  mk_li(Tmp, Src2,	[hipe_ppc:mk_alu(AluOp, Dst, Src1, Tmp)]).mk_alub_rr(Dst, Src1, RtlAluOp, Src2, BCond) ->  case BCond of    'so' -> mk_alub_rr_OE(Dst, Src1, RtlAluOp, Src2);    'ns' -> mk_alub_rr_OE(Dst, Src1, RtlAluOp, Src2);    _ -> mk_alub_rr_Rc(Dst, Src1, RtlAluOp, Src2)  end.mk_alub_rr_OE(Dst, Src1, RtlAluOp, Src2) ->  case RtlAluOp of    'sub' -> % PPC weirdness      [hipe_ppc:mk_alu('subfo.', Dst, Src2, Src1)];    'add' ->      [hipe_ppc:mk_alu('addo.', Dst, Src1, Src2)];    'mul' ->      [hipe_ppc:mk_alu('mullwo.', Dst, Src1, Src2)]      %% fail for or, and, xor, sll, srl, sra  end.mk_alub_rr_Rc(Dst, Src1, RtlAluOp, Src2) ->  %% XXX: identical to mk_alu_rr/4, except for the '.' in the instruction names  case RtlAluOp of    'sub' -> % PPC weirdness      [hipe_ppc:mk_alu('subf.', Dst, Src2, Src1)];    _ ->      AluOp =	case RtlAluOp of	  'add' -> 'add.';	  'mul' -> 'mullw.';	  'or'  -> 'or.';	  'and' -> 'and.';	  'xor' -> 'xor.';	  'sll' -> 'slw.';	  'srl' -> 'srw.';	  'sra' -> 'sraw.'	end,      [hipe_ppc:mk_alu(AluOp, Dst, Src1, Src2)]  end.conv_branch(I, Map, Data) ->  %% <unused> = src1 - src2; if COND goto label  {Src1, Map0} = conv_src(hipe_rtl:branch_src1(I), Map),  {Src2, Map1} = conv_src(hipe_rtl:branch_src2(I), Map0),  {BCond,Sign} = conv_branch_cond(hipe_rtl:branch_cond(I)),  I2 = mk_branch(Src1, BCond, Sign, Src2,		 hipe_rtl:branch_true_label(I),		 hipe_rtl:branch_false_label(I),		 hipe_rtl:branch_pred(I)),  {I2, Map1, Data}.conv_branch_cond(Cond) -> % may be unsigned  case Cond of    gtu -> {'gt', 'unsigned'};    geu -> {'ge', 'unsigned'};    ltu -> {'lt', 'unsigned'};    leu -> {'le', 'unsigned'};    _   -> {conv_alub_cond(Cond), 'signed'}  end.    mk_branch(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->  case hipe_ppc:is_temp(Src1) of    true ->      case hipe_ppc:is_temp(Src2) of	true ->	  mk_branch_rr(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred);	_ ->	  mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred)      end;    _ ->      case hipe_ppc:is_temp(Src2) of	true ->	  NewBCond = commute_bcond(BCond),	  mk_branch_ri(Src2, NewBCond, Sign, Src1, TrueLab, FalseLab, Pred);	_ ->	  mk_branch_ii(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred)      end  end.commute_bcond(BCond) ->	% if x BCond y, then y commute_bcond(BCond) x  case BCond of    'eq' -> 'eq';	% ==, ==    'ne' -> 'ne';	% !=, !=    'gt' -> 'lt';	% >, <    'ge' -> 'le';	% >=, <=    'lt' -> 'gt';	% <, >    'le' -> 'ge';	% <=, >=    %% so/ns: n/a    _ -> exit({?MODULE,commute_bcond,BCond})  end.mk_branch_ii(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->  io:format("~w: RTL branch with two immediates\n", [?MODULE]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Src1,	mk_branch_ri(Tmp, BCond, Sign, Src2,		     TrueLab, FalseLab, Pred)).mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->  {FixSrc2,NewSrc2,CmpOp} =    case Sign of      'signed' ->	if is_integer(Src2), -32768 =< Src2, Src2 < 32768 ->	    {[], hipe_ppc:mk_simm16(Src2), 'cmpi'};	   true ->	    Tmp = new_untagged_temp(),	    {mk_li(Tmp, Src2), Tmp, 'cmp'}	end;      'unsigned' ->	if is_integer(Src2), 0 =< Src2, Src2 < 65536 ->	    {[], hipe_ppc:mk_uimm16(Src2), 'cmpli'};	   true ->	    Tmp = new_untagged_temp(),	    {mk_li(Tmp, Src2), Tmp, 'cmpl'}	end    end,  FixSrc2 ++    mk_cmp_bc(CmpOp, Src1, NewSrc2, BCond, TrueLab, FalseLab, Pred).mk_branch_rr(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->  CmpOp =    case Sign of      'signed' -> 'cmp';      'unsigned' -> 'cmpl'    end,  mk_cmp_bc(CmpOp, Src1, Src2, BCond, TrueLab, FalseLab, Pred).mk_cmp_bc(CmpOp, Src1, Src2, BCond, TrueLab, FalseLab, Pred) ->  [hipe_ppc:mk_cmp(CmpOp, Src1, Src2) |   mk_pseudo_bc(BCond, TrueLab, FalseLab, Pred)].conv_call(I, Map, Data) ->  {Args, Map0} = conv_src_list(hipe_rtl:call_arglist(I), Map),  {Dsts, Map1} = conv_dst_list(hipe_rtl:call_dstlist(I), Map0),  {Fun, Map2} = conv_fun(hipe_rtl:call_fun(I), Map1),  ContLab = hipe_rtl:call_continuation(I),  ExnLab = hipe_rtl:call_fail(I),  Linkage = hipe_rtl:call_type(I),  I2 = mk_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage),  {I2, Map2, Data}.mk_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage) ->  case hipe_ppc:is_prim(Fun) of    true ->      mk_primop_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage);    false ->      mk_general_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage)  end.mk_primop_call(Dsts, Prim, Args, ContLab, ExnLab, Linkage) ->  case hipe_ppc:prim_prim(Prim) of    'extsh' ->      mk_extsh_call(Dsts, Args, ContLab, ExnLab, Linkage);    'lhbrx' ->      mk_lhbrx_call(Dsts, Args, ContLab, ExnLab, Linkage);    'lwbrx' ->      mk_lwbrx_call(Dsts, Args, ContLab, ExnLab, Linkage);    _ ->      mk_general_call(Dsts, Prim, Args, ContLab, ExnLab, Linkage)  end.mk_extsh_call([Dst], [Src], [], [], not_remote) ->  true = hipe_ppc:is_temp(Src),  [hipe_ppc:mk_unary('extsh', Dst, Src)].mk_lhbrx_call(Dsts, [Base,Offset], [], [], not_remote) ->  case Dsts of    [Dst] -> mk_loadx('lhbrx', Dst, Base, Offset);    [] -> [] % result unused, cancel the operation  end.mk_lwbrx_call([Dst], [Base,Offset], [], [], not_remote) ->  mk_loadx('lwbrx', Dst, Base, Offset).mk_loadx(LdxOp, Dst, Base, Offset) ->  true = hipe_ppc:is_temp(Base),  {FixOff,NewOff} =    case hipe_ppc:is_temp(Offset) of      true -> {[], Offset};      false ->	Tmp = new_untagged_temp(),	{mk_li(Tmp, Offset), Tmp}    end,  FixOff ++ [hipe_ppc:mk_loadx(LdxOp, Dst, Base, NewOff)].mk_general_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage) ->  %% The backend does not support pseudo_calls without a  %% continuation label, so we make sure each call has one.  {RealContLab, Tail} =    case mk_call_results(Dsts) of      [] ->	%% Avoid consing up a dummy basic block if the moves list	%% is empty, as is typical for calls to suspend/0.	%% This should be subsumed by a general "optimise the CFG"	%% module, and could probably be removed.	case ContLab of	  [] ->	    NewContLab = hipe_gensym:get_next_label(ppc),	    {NewContLab, [hipe_ppc:mk_label(NewContLab)]};	  _ ->	    {ContLab, []}	end;      Moves ->	%% Change the call to continue at a new basic block.	%% In this block move the result registers to the Dsts,	%% then continue at the call's original continuation.	NewContLab = hipe_gensym:get_next_label(ppc),	case ContLab of	  [] ->	    %% This is just a fallthrough	    %% No jump back after the moves.	    {NewContLab,	     [hipe_ppc:mk_label(NewContLab) |	      Moves]};	  _ ->	    %% The call has a continuation. Jump to it.	    {NewContLab,	     [hipe_ppc:mk_label(NewContLab) |	      Moves ++	      [hipe_ppc:mk_b_label(ContLab)]]}	end    end,  SDesc = hipe_ppc:mk_sdesc(ExnLab, 0, length(Args), {}),  {FixFunC,FunC} = fix_func(Fun),  CallInsn = hipe_ppc:mk_pseudo_call(FunC, SDesc, RealContLab, Linkage),  {RegArgs,StkArgs} = split_args(Args),  FixFunC ++    mk_push_args(StkArgs, move_actuals(RegArgs, [CallInsn | Tail])).mk_call_results([]) ->  [];mk_call_results([Dst]) ->  RV = hipe_ppc:mk_temp(hipe_ppc_registers:return_value(), 'tagged'),  [hipe_ppc:mk_pseudo_move(Dst, RV)];mk_call_results(Dsts) ->  exit({?MODULE,mk_call_results,Dsts}).fix_func(Fun) ->  case hipe_ppc:is_temp(Fun) of    true -> {[hipe_ppc:mk_mtspr('ctr', Fun)], 'ctr'};    _ -> {[], Fun}  end.mk_push_args(StkArgs, Tail) ->  case length(StkArgs) of    0 ->      Tail;    NrStkArgs ->      [hipe_ppc:mk_pseudo_call_prepare(NrStkArgs) |       mk_store_args(StkArgs, NrStkArgs * word_size(), Tail)]  end.  mk_store_args([Arg|Args], PrevOffset, Tail) ->  Offset = PrevOffset - word_size(),  {Src,FixSrc} =    case hipe_ppc:is_temp(Arg) of      true ->	{Arg, []};      _ ->	Tmp = new_tagged_temp(),	{Tmp, mk_li(Tmp, Arg)}    end,  Store = hipe_ppc:mk_store('stw', Src, Offset, mk_sp()),  mk_store_args(Args, Offset, FixSrc ++ [Store | Tail]);mk_store_args([], _, Tail) ->  Tail.conv_comment(I, Map, Data) ->  I2 = [hipe_ppc:mk_comment(hipe_rtl:comment_text(I))],  {I2, Map, Data}.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -