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

📄 hipe_x86_x87.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 2 页
字号:
    case ?HIPE_X86_REGISTERS:is_precoloured(Reg) of      true ->	Temp = hipe_x86:mk_new_temp('untagged'),	{[hipe_x86:mk_move(Src,Temp)], Temp};      _ ->	{[], Src}    end,  {PushOp, [_|NewMap0]} = push(NewSrc, Map),  %% We want Dst in the map rather than NewSrc.  NewMap = [Dst|NewMap0],  case length(PushOp) of    1 -> %% No popping of memory object on fpstack      {Move++[hipe_x86:mk_fp_unop(fild, NewSrc)], NewMap};    _ -> %% H contains pop instructions. Must be kept!      Head = butlast(PushOp),      {Move ++ Head ++ [hipe_x86:mk_fp_unop(fild, NewSrc)], NewMap}  end.do_fp_unop(I = #fp_unop{arg=Arg, op=fchs}, Liveout, Map) ->  %% This is fchs, the only operation without a  %% popping version. Needs special handling.  case is_liveOut(Arg, Liveout) of    true ->      {SwitchIns, NewMap} = switch_first(Arg, Map),      {SwitchIns ++ [I#fp_unop{arg=[]}], NewMap};    false ->      %% Don't need to keep this instruction!      %% However, we may need to pop Src from the stack.      case in_map(Arg, Map) of	true ->	  {SwitchInsn, NewMap0} = switch_first(Arg, Map),	  NewMap = pop(NewMap0),	  {SwitchInsn ++ pop_insn(), NewMap};	_ ->	  {[],Map}      end  end.do_fp_binop(#fp_binop{src=Src, dst=Dst, op=Op},       LiveOut, Map) ->  case {is_liveOut(Src, LiveOut), is_liveOut(Dst, LiveOut)} of    {true, true} ->      keep_both(Op, Src, Dst, Map);    {true, false} ->      keep_src(Op, Src, Dst, Map);    {false, true} ->      keep_dst(Op, Src, Dst, Map);    {false, false} ->      %% Both Dst and Src are popped.      keep_none(Op, Src, Dst, Map)  end.keep_both(Op, Src, Dst, Map) ->  %% Keep both Dst and Src if it is there.  {SwitchInsn, NewMap} = switch_first(Dst, Map),  NewSrc = get_new_opnd(Src, NewMap),  Insn = format_fp_binop(Op, NewSrc, mk_st(0)),  {SwitchInsn++Insn, NewMap}.keep_src(Op, Src, Dst, Map) ->  %% Pop Dst but keep Src in stack if it is there.  {SwitchInsn, NewMap0} = switch_first(Dst, Map),  NewSrc = get_new_opnd(Src, NewMap0),  NewMap = pop(NewMap0),  Insn = format_fp_binop(Op, NewSrc, mk_st(0)),  {SwitchInsn ++ Insn ++ pop_insn(), NewMap}.keep_dst(Op, Src, Dst, Map) ->  %% Keep Dst but pop Src.  %% Dst must be in stack.  DstInMap = in_map(Dst, Map),  SrcInMap = in_map(Src, Map),  case SrcInMap of    true ->      case DstInMap of	true ->	  %% Src must be popped. If Dst is on top of the stack we can	  %% alter the operation rather than shuffle the stack.	  {SwitchInsn, Insn, NewMap} =	    if hd(Map) =:= Dst ->		NewOp = mk_op_pop(reverse_op(Op)),		NewDst = get_new_opnd(Src, Map),		TmpMap = lists:map(fun(X) ->				     if X =:= Src -> Dst; true -> X end				   end, Map),		{[], format_fp_binop(NewOp, mk_st(0), NewDst), pop(TmpMap)};	       true ->		{SwitchInsn1, NewMap0} = switch_first(Src, Map),		NewDst = get_new_opnd(Dst,NewMap0),		NewOp = mk_op_pop(Op),		{SwitchInsn1,format_fp_binop(NewOp, mk_st(0), NewDst), pop(NewMap0)}	    end,	  {SwitchInsn ++ Insn, NewMap};	_ ->	  %% Src is on the stack, but Dst isn't. Use memory command to avoid	  %% unnecessary loading instructions.	  {SwitchInsn, NewMap0} = switch_first(Src, Map),	  NewOp = reverse_op(Op),	  NewMap = [Dst] ++ tl(NewMap0),	  Insn = format_fp_binop(NewOp, Dst, mk_st(0)),	  {SwitchInsn ++ Insn, NewMap}      end;    _ ->      %% Src isn't in the map so it doesn't have to be popped.      {SwitchInsn, NewMap} = switch_first(Dst, Map),      {SwitchInsn ++ [#fp_unop{arg=Src,op=Op}], NewMap}  end.keep_none(Op, Src, Dst, Map) ->  %% Dst must be on stack.  {PushInsn, NewMap0} =     case in_map(Dst, Map) of      true -> {[], Map};      _ -> push(Dst, Map)    end,  case in_map(Src, NewMap0) of    true ->      %% Src must be popped.      {SwitchInsn1, NewMap1} = switch_first(Src, NewMap0),      NewOp = mk_op_pop(Op),      NewDst = get_new_opnd(Dst,NewMap1),      NewMap2 = pop(NewMap1),      %% Then Dst has to be popped.      {PopInsn,NewMap} = pop_member(Dst,NewMap2),      Insn = format_fp_binop(NewOp, mk_st(0), NewDst),      {PushInsn ++ SwitchInsn1 ++ Insn ++ PopInsn, NewMap};    _ ->      %% Src isn't in the map so it doesn't have to be popped.      {SwitchInsn, NewMap1} = switch_first(Dst, NewMap0),      NewMap = pop(NewMap1),      {SwitchInsn ++ [#fp_unop{arg=Src,op=Op}] ++ pop_insn(), NewMap}  end.format_fp_binop(Op, Src=#x86_temp{}, Dst=#x86_fpreg{reg=Reg}) ->  %% Handle that st(0) is sometimes implicit.  if Reg =:= 0 -> [hipe_x86:mk_fp_unop(Op, Src)];     true -> [hipe_x86:mk_fp_binop(Op, Src, Dst)]  end;format_fp_binop(Op, Src, Dst) ->  [hipe_x86:mk_fp_binop(Op, Src, Dst)].in_map(X, Map) ->  lists:member(X, Map).push_list(L, Map) ->  push_list(L, Map, []).push_list([H|T], Map, Acc) ->  {Insn, NewMap} = push(H,Map),  push_list(T, NewMap, Acc++Insn);push_list([], Map, Acc) ->  {Acc, Map}.push(X, Map0) ->  {PopInsn, Map} =     if length(Map0) > 7 -> pop_a_temp(Map0);       true -> {[], Map0}    end,  NewX = get_new_opnd(X,Map),  NewMap = [X | Map],  PushOp = [hipe_x86:mk_fp_unop(fld, NewX)],  {PopInsn ++ PushOp, NewMap}.pop([_|Map]) ->  Map.pop_insn() ->  [hipe_x86:mk_fp_unop('fstp',mk_st(0))].pop_dead(Dead, Map) ->  Dead0 = [X || X <- Map, lists:member(X,Dead)],  pop_dead(Dead0, Map, []).pop_dead([D|Dead], Map, Code) ->  {I, NewMap0} = switch_first(D, Map),  NewMap = pop(NewMap0),  Store = case D of	    #x86_temp{} -> [hipe_x86:mk_fp_unop('fstp', D)];	    _ -> pop_insn()	  end,  pop_dead(Dead, NewMap, Code++I++Store);pop_dead([], Map, Code) ->  {Code,Map}.pop_all(Map) ->  {Code, _} = pop_dead(Map, Map),  Code.pop_member(Member, Map) ->  {Head,[_|T]} = lists:splitwith(fun(X)->X/=Member end,Map),  {[hipe_x86:mk_fp_unop('fstp', mk_st(get_pos(Member, Map, 0)))],   Head++T}.pop_a_temp(Map) ->  Temp = find_a_temp(Map),  {SwitchInsn, NewMap0} = switch_first(Temp, Map),  NewMap = pop(NewMap0),  {SwitchInsn ++ [hipe_x86:mk_fp_unop('fstp', Temp)], NewMap}.find_a_temp([H = #x86_temp{}|_]) ->  H;find_a_temp([_|T]) ->  find_a_temp(T);find_a_temp([]) ->  ?EXIT({noTempOnFPStack,{}}).switch_first(X, Map = [H|_]) ->  Pos = get_pos(X, Map, 0),  case Pos of    0 ->       {[], Map};    notFound ->      push(X, Map);    _ ->	          {[_|Head], [_|Tail]} = lists:splitwith(fun(Y)->Y/=X end, Map),      NewMap = [X|Head] ++ [H|Tail],      Ins = hipe_x86:mk_fp_unop(fxch, mk_st(Pos)),      {[Ins], NewMap}  end;switch_first(X, Map) ->  push(X, Map).get_pos(X, [H|T], Pos) ->  if X =:= H -> Pos;     true -> get_pos(X, T, Pos+1)  end;get_pos(_, [], _) ->  notFound.get_new_opnd(X, Map) ->  I = get_pos(X, Map, 0),  case I of    notFound ->      %% The operand is probably a spilled float.      X;    _ ->      mk_st(I)  end.is_fp(#x86_fpreg{}) ->  true;is_fp(#x86_mem{type=Type}) ->  Type =:= 'double';is_fp(#x86_temp{type=Type}) ->  Type =:= 'double'.handle_insn(I) ->  case I of    #fmove{} -> true;    #fp_unop{} -> true;    #fp_binop{} -> true;    #pseudo_call{}->true;%%    #ret{}-> true;    _ -> false  end.is_liveOut(X, LiveOut) ->  ordsets:is_element(X, LiveOut).mk_st(X) ->  hipe_x86:mk_fpreg(X, false).reverse_op(Op) ->  case Op of    'fsub' -> 'fsubr';    'fdiv' -> 'fdivr';    'fsubr'-> 'fsub';    'fdivr' -> 'fdiv';    _ -> Op  end.mk_op_pop(Op) ->  case Op of    'fadd'-> 'faddp';    'fdiv' -> 'fdivp';    'fdivr' -> 'fdivrp';    'fmul' -> 'fmulp';    'fsub' -> 'fsubp';    'fsubr' -> 'fsubrp';    _ -> ?EXIT({operandHasNoPopVariant,{Op}})  end.butlast([X|Xs]) -> butlast(Xs,X).butlast([],_) -> [];butlast([X|Xs],Y) -> [Y|butlast(Xs,X)].%%pp_insn(Op, Src, Dst) ->%%  pp([hipe_x86:mk_fp_binop(Op, Src, Dst)]).%%pp([I|Ins]) ->%%  hipe_x86_pp:pp_insn(I),%%  pp(Ins);%%pp([]) ->%%  [].pseudo_pop(Map) when length(Map) > 0 ->  Dst = hipe_x86:mk_new_temp('double'),  pseudo_pop(Dst, length(Map), []);pseudo_pop(_) ->  [].pseudo_pop(Dst, St, Acc) when St > 1 ->%% Store all members of the stack to a single temporary to force %% any floating point overflow exceptions to occur even though we%% don't have overflow for the extended double precision in the x87.  pseudo_pop(Dst, St-1, 	     [hipe_x86:mk_fp_unop('fxch', mk_st(St-1)),	      hipe_x86:mk_fp_unop('fst', Dst),	      hipe_x86:mk_fp_unop('fxch', mk_st(St-1))	      |Acc]);pseudo_pop(Dst, _St, Acc) ->  [hipe_x86:mk_fp_unop('fst', Dst)|Acc].

⌨️ 快捷键说明

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