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

📄 hipe_rtl_to_ppc.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 3 页
字号:
%%% -*- erlang-indent-level: 2 -*-%%% $Id$%%%%%% The PowerPC instruction set is quite irregular.%%% The following quirks must be handled by the translation:%%%%%% - The instruction names are different for reg/reg and reg/imm%%%   source operands. For some operations, completely different%%%   instructions handle the reg/reg and reg/imm cases.%%% - The name of an arithmetic instruction depends on whether any%%%   condition codes are to be set or not. Overflow is treated%%%   separately from other conditions.%%% - Some combinations or RTL ALU operations, source operand shapes,%%%   and requested conditions have no direct correspondence in the%%%   PowerPC instruction set.%%% - The tagging of immediate operands as simm16 or uimm16 depends%%%   on the actual instruction.%%% - Conditional branches have no unsigned conditions. Instead there%%%   are signed and unsigned versions of the compare instruction.%%% - The arithmetic overflow flag XER[SO] is sticky: once set it%%%   remains set until explicitly cleared.-module(hipe_rtl_to_ppc).-export([translate/1]).-include("../rtl/hipe_rtl.hrl").translate(RTL) ->  hipe_gensym:init(ppc),  hipe_gensym:set_var(ppc, hipe_ppc_registers:first_virtual()),  hipe_gensym:set_label(ppc, hipe_gensym:get_label(rtl)),  Map0 = vmap_empty(),  {Formals, Map1} = conv_formals(hipe_rtl:rtl_params(RTL), Map0),  OldData = hipe_rtl:rtl_data(RTL),  {Code0, NewData} = conv_insn_list(hipe_rtl:rtl_code(RTL), Map1, OldData),  {RegFormals, _} = split_args(Formals),  Code =    case RegFormals of      [] -> Code0;      _ -> [hipe_ppc:mk_label(hipe_gensym:get_next_label(ppc)) |	    move_formals(RegFormals, Code0)]    end,  IsClosure = hipe_rtl:rtl_is_closure(RTL),  IsLeaf = hipe_rtl:rtl_is_leaf(RTL),  hipe_ppc:mk_defun(conv_mfa(hipe_rtl:rtl_fun(RTL)),		    Formals,		    IsClosure,		    IsLeaf,		    Code,		    NewData,		    [], 		    []).conv_insn_list([H|T], Map, Data) ->  {NewH, NewMap, NewData1} = conv_insn(H, Map, Data),  %% io:format("~w \n  ==>\n ~w\n- - - - - - - - -\n",[H,NewH]),  {NewT, NewData2} = conv_insn_list(T, NewMap, NewData1),  {NewH ++ NewT, NewData2};conv_insn_list([], _, Data) ->  {[], Data}.conv_insn(I, Map, Data) ->  case I of    #alu{} -> conv_alu(I, Map, Data);    #alub{} -> conv_alub(I, Map, Data);    #branch{} -> conv_branch(I, Map, Data);    #call{} -> conv_call(I, Map, Data);    #comment{} -> conv_comment(I, Map, Data);    #enter{} -> conv_enter(I, Map, Data);    #goto{} -> conv_goto(I, Map, Data);    #label{} -> conv_label(I, Map, Data);    #load{} -> conv_load(I, Map, Data);    #load_address{} -> conv_load_address(I, Map, Data);    #load_atom{} -> conv_load_atom(I, Map, Data);    #move{} -> conv_move(I, Map, Data);    #return{} -> conv_return(I, Map, Data);    #store{} -> conv_store(I, Map, Data);    #switch{} -> conv_switch(I, Map, Data);    #fconv{} -> conv_fconv(I, Map, Data);    #fmove{} -> conv_fmove(I, Map, Data);    #fload{} -> conv_fload(I, Map, Data);    #fstore{} -> conv_fstore(I, Map, Data);    #fp{} -> conv_fp_binary(I, Map, Data);    #fp_unop{} -> conv_fp_unary(I, Map, Data);    _ -> exit({?MODULE,conv_insn,I})  end.conv_fconv(I, Map, Data) ->  %% Dst := (double)Src, where Dst is FP reg and Src is int reg  {Dst, Map0} = conv_fpreg(hipe_rtl:fconv_dst(I), Map),  {Src, Map1} = conv_src(hipe_rtl:fconv_src(I), Map0), % exclude imm src  I2 = mk_fconv(Dst, Src),  {I2, Map1, Data}.mk_fconv(Dst, Src) ->  CSP = hipe_ppc:mk_temp(1, 'untagged'),  R0 = hipe_ppc:mk_temp(0, 'untagged'),  RTmp1 = hipe_ppc:mk_new_temp('untagged'),  RTmp2 = hipe_ppc:mk_new_temp('untagged'),  RTmp3 = hipe_ppc:mk_new_temp('untagged'),  FTmp1 = hipe_ppc:mk_new_temp('double'),  FTmp2 = hipe_ppc:mk_new_temp('double'),  [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}),   hipe_ppc:mk_lfd(FTmp1, 0, RTmp1),   hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)),   hipe_ppc:mk_store('stw', RTmp2, 28, CSP),   hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)),   hipe_ppc:mk_store('stw', RTmp3, 24, CSP),   hipe_ppc:mk_lfd(FTmp2, 24, CSP),   hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)].conv_fmove(I, Map, Data) ->  %% Dst := Src, where both Dst and Src are FP regs  {Dst, Map0} = conv_fpreg(hipe_rtl:fmove_dst(I), Map),  {Src, Map1} = conv_fpreg(hipe_rtl:fmove_src(I), Map0),  I2 = mk_fmove(Dst, Src),  {I2, Map1, Data}.mk_fmove(Dst, Src) ->  [hipe_ppc:mk_pseudo_fmove(Dst, Src)].conv_fload(I, Map, Data) ->  %% Dst := MEM[Base+Off], where Dst is FP reg  {Dst, Map0} = conv_fpreg(hipe_rtl:fload_dst(I), Map),  {Base1, Map1} = conv_src(hipe_rtl:fload_src(I), Map0),  {Base2, Map2} = conv_src(hipe_rtl:fload_offset(I), Map1),  I2 = mk_fload(Dst, Base1, Base2),  {I2, Map2, Data}.mk_fload(Dst, Base1, Base2) ->  case hipe_ppc:is_temp(Base1) of    true ->      case hipe_ppc:is_temp(Base2) of	true ->	  mk_fload_rr(Dst, Base1, Base2);	_ ->	  mk_fload_ri(Dst, Base1, Base2)      end;    _ ->      case hipe_ppc:is_temp(Base2) of	true ->	  mk_fload_ri(Dst, Base2, Base1);	_ ->	  mk_fload_ii(Dst, Base1, Base2)      end  end.mk_fload_ii(Dst, Base1, Base2) ->  io:format("~w: RTL fload with two immediates\n", [?MODULE]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Base1,	mk_fload_ri(Dst, Tmp, Base2)).mk_fload_ri(Dst, Base, Disp) ->  hipe_ppc:mk_fload(Dst, Disp, Base, 'new').mk_fload_rr(Dst, Base1, Base2) ->  [hipe_ppc:mk_lfdx(Dst, Base1, Base2)].conv_fstore(I, Map, Data) ->  %% MEM[Base+Off] := Src, where Src is FP reg  {Base1, Map0} = conv_dst(hipe_rtl:fstore_base(I), Map),  {Src, Map1} = conv_fpreg(hipe_rtl:fstore_src(I), Map0),  {Base2, Map2} = conv_src(hipe_rtl:fstore_offset(I), Map1),  I2 = mk_fstore(Src, Base1, Base2),  {I2, Map2, Data}.mk_fstore(Src, Base1, Base2) ->  case hipe_ppc:is_temp(Base2) of    true ->      mk_fstore_rr(Src, Base1, Base2);    _ ->      mk_fstore_ri(Src, Base1, Base2)  end.mk_fstore_ri(Src, Base, Disp) ->  hipe_ppc:mk_fstore(Src, Disp, Base, 'new').mk_fstore_rr(Src, Base1, Base2) ->  [hipe_ppc:mk_stfdx(Src, Base1, Base2)].conv_fp_binary(I, Map, Data) ->  {Dst, Map0} = conv_fpreg(hipe_rtl:fp_dst(I), Map),  {Src1, Map1} = conv_fpreg(hipe_rtl:fp_src1(I), Map0),  {Src2, Map2} = conv_fpreg(hipe_rtl:fp_src2(I), Map1),  RtlFpOp = hipe_rtl:fp_op(I),  I2 = mk_fp_binary(Dst, Src1, RtlFpOp, Src2),  {I2, Map2, Data}.mk_fp_binary(Dst, Src1, RtlFpOp, Src2) ->  FpBinOp =    case RtlFpOp of      'fadd' -> 'fadd';      'fdiv' -> 'fdiv';      'fmul' -> 'fmul';      'fsub' -> 'fsub'    end,  [hipe_ppc:mk_fp_binary(FpBinOp, Dst, Src1, Src2)].conv_fp_unary(I, Map, Data) ->  {Dst, Map0} = conv_fpreg(hipe_rtl:fp_unop_dst(I), Map),  {Src, Map1} = conv_fpreg(hipe_rtl:fp_unop_src(I), Map0),  RtlFpUnOp = hipe_rtl:fp_unop_op(I),  I2 = mk_fp_unary(Dst, Src, RtlFpUnOp),  {I2, Map1, Data}.mk_fp_unary(Dst, Src, RtlFpUnOp) ->  FpUnOp =    case RtlFpUnOp of      'fchs' -> 'fneg'    end,  [hipe_ppc:mk_fp_unary(FpUnOp, Dst, Src)].conv_alu(I, Map, Data) ->  %% dst = src1 aluop src2  {Dst, Map0} = conv_dst(hipe_rtl:alu_dst(I), Map),  {Src1, Map1} = conv_src(hipe_rtl:alu_src1(I), Map0),  {Src2, Map2} = conv_src(hipe_rtl:alu_src2(I), Map1),  RtlAluOp = hipe_rtl:alu_op(I),  I2 = mk_alu(Dst, Src1, RtlAluOp, Src2),  {I2, Map2, Data}.mk_alu(Dst, Src1, RtlAluOp, Src2) ->  case hipe_ppc:is_temp(Src1) of    true ->      case hipe_ppc:is_temp(Src2) of	true ->	  mk_alu_rr(Dst, Src1, RtlAluOp, Src2);	_ ->	  mk_alu_ri(Dst, Src1, RtlAluOp, Src2)      end;    _ ->      case hipe_ppc:is_temp(Src2) of	true ->	  mk_alu_ir(Dst, Src1, RtlAluOp, Src2);	_ ->	  mk_alu_ii(Dst, Src1, RtlAluOp, Src2)      end  end.mk_alu_ii(Dst, Src1, RtlAluOp, Src2) ->  io:format("~w: RTL alu with two immediates (~w ~w ~w)\n",	    [?MODULE, Src1, RtlAluOp, Src2]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Src1,	mk_alu_ri(Dst, Tmp, RtlAluOp, Src2)).mk_alu_ir(Dst, Src1, RtlAluOp, Src2) ->  case rtl_aluop_commutes(RtlAluOp) of    true ->      mk_alu_ri(Dst, Src2, RtlAluOp, Src1);    _ ->      Tmp = new_untagged_temp(),      mk_li(Tmp, Src1,	    mk_alu_rr(Dst, Tmp, RtlAluOp, Src2))  end.mk_alu_ri(Dst, Src1, RtlAluOp, Src2) ->  case RtlAluOp of    'sub' ->	% there is no 'subi'      mk_alu_ri_addi(Dst, Src1, -Src2);    'add' ->	% 'addi' has a 16-bit simm operand      mk_alu_ri_addi(Dst, Src1, Src2);    'mul' ->	% 'mulli' has a 16-bit simm operand      mk_alu_ri_simm16(Dst, Src1, RtlAluOp, 'mulli', 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_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2)      end;    'or' ->	% 'ori' has a 16-bit uimm operand      mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'ori', Src2);    'xor' ->	% 'xori' has a 16-bit uimm operand      mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'xori', Src2);    _ ->	% shift ops have 5-bit uimm operands      mk_alu_ri_shift(Dst, Src1, RtlAluOp, Src2)  end.rlwinm_mask(Imm) ->  Res1 = rlwinm_mask2(Imm),  case Res1 of    {_MB,_ME} -> Res1;    [] ->      case rlwinm_mask2(bnot Imm) of	{MB,ME} -> {ME+1,MB-1};	[] -> []      end  end.rlwinm_mask2(Imm) ->  case Imm band 16#ffffffff of    0 -> [];    Word ->      MB = lsb_log2(Word),	% first 1 bit      case bnot(Word bsr MB) band 16#ffffffff of	0 -> []; % Imm was all-bits-one XXX: we should handle this	Word1 ->	  ME1 = lsb_log2(Word1),% first 0 bit after the 1s	  case Word bsr (MB+ME1) of	    0 ->	      ME = MB+ME1-1,	% last 1 bit	      {31-ME, 31-MB};	% convert to PPC sick and twisted bit numbers	    _ ->	      []	  end      end  end.lsb_log2(Word) -> % PRE: Word =/= 0  bitN_log2(Word band -Word, 0).bitN_log2(BitN, ShiftN) ->  if BitN > 16#ffff ->      bitN_log2(BitN bsr 16, ShiftN + 16);     true ->      ShiftN + hweight16(BitN - 1)  end.hweight16(Word) -> % PRE: 0 <= Word <= 16#ffff  Res1 = (Word band 16#5555) + ((Word bsr 1) band 16#5555),  Res2 = (Res1 band 16#3333) + ((Res1 bsr 2) band 16#3333),  Res3 = (Res2 band 16#0F0F) + ((Res2 bsr 4) band 16#0F0F),         (Res3 band 16#00FF) + ((Res3 bsr 8) band 16#00FF).mk_alu_ri_addi(Dst, Src1, Src2) ->  mk_alu_ri_simm16(Dst, Src1, 'add', 'addi', Src2).mk_alu_ri_simm16(Dst, Src1, RtlAluOp, AluOp, Src2) ->  if is_integer(Src2), -32768 =< Src2, Src2 < 32768 ->      [hipe_ppc:mk_alu(AluOp, Dst, Src1,		       hipe_ppc:mk_simm16(Src2))];     true ->      mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)  end.mk_alu_ri_bitop(Dst, Src1, RtlAluOp, AluOp, Src2) ->  if is_integer(Src2), 0 =< Src2, Src2 < 65536 ->      [hipe_ppc:mk_alu(AluOp, Dst, Src1,		       hipe_ppc:mk_uimm16(Src2))];     true ->      mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)  end.mk_alu_ri_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 ->      mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)  end.mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) ->  Tmp = new_untagged_temp(),  mk_li(Tmp, Src2,	mk_alu_rr(Dst, Src1, RtlAluOp, Tmp)).mk_alu_rr(Dst, Src1, RtlAluOp, Src2) ->  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_alub(I, Map, Data) ->  %% dst = src1 aluop src2; if COND goto label  {Dst, Map0} = conv_dst(hipe_rtl:alub_dst(I), Map),  {Src1, Map1} = conv_src(hipe_rtl:alub_src1(I), Map0),  {Src2, Map2} = conv_src(hipe_rtl:alub_src2(I), Map1),  BCond = conv_alub_cond(hipe_rtl:alub_cond(I)),  I2 = mk_pseudo_bc(BCond,		    hipe_rtl:alub_true_label(I),		    hipe_rtl:alub_false_label(I),		    hipe_rtl:alub_pred(I)),  RtlAluOp = hipe_rtl:alub_op(I),  I1 = mk_alub(Dst, Src1, RtlAluOp, Src2, BCond),  {I1 ++ I2, Map2, Data}.

⌨️ 快捷键说明

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