aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/sparc/hipe_sparc_defuse.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/sparc/hipe_sparc_defuse.erl')
-rw-r--r--lib/hipe/sparc/hipe_sparc_defuse.erl143
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/hipe/sparc/hipe_sparc_defuse.erl b/lib/hipe/sparc/hipe_sparc_defuse.erl
new file mode 100644
index 0000000000..d59ad436b5
--- /dev/null
+++ b/lib/hipe/sparc/hipe_sparc_defuse.erl
@@ -0,0 +1,143 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(hipe_sparc_defuse).
+-export([insn_def_all/1, insn_use_all/1]).
+-export([insn_def_gpr/1, insn_use_gpr/1]).
+-export([insn_def_fpr/1, insn_use_fpr/1]).
+-include("hipe_sparc.hrl").
+
+%%%
+%%% Defs and uses for both general-purpose and floating-point registers.
+%%% This is needed for the frame module, alas.
+%%%
+insn_def_all(I) ->
+ addtemps(insn_def_fpr(I), insn_def_gpr(I)).
+
+insn_use_all(I) ->
+ addtemps(insn_use_fpr(I), insn_use_gpr(I)).
+
+%%%
+%%% Defs and uses for general-purpose (integer) registers only.
+%%%
+insn_def_gpr(I) ->
+ case I of
+ #alu{dst=Dst} -> [Dst];
+ %% #jmpl{} -> [hipe_sparc:mk_ra()]; % XXX: can jmpl occur this early?
+ #pseudo_call{} -> call_clobbered_gpr();
+ #pseudo_move{dst=Dst} -> [Dst];
+ #pseudo_set{dst=Dst} -> [Dst];
+ #pseudo_tailcall_prepare{} -> tailcall_clobbered_gpr();
+ #rdy{dst=Dst} -> [Dst];
+ #sethi{dst=Dst} -> [Dst];
+ _ -> []
+ end.
+
+call_clobbered_gpr() ->
+ [hipe_sparc:mk_temp(R, T)
+ || {R,T} <- hipe_sparc_registers:call_clobbered() ++ all_fp_pseudos()].
+
+all_fp_pseudos() -> []. % XXX: for now
+
+tailcall_clobbered_gpr() ->
+ [hipe_sparc:mk_temp(R, T)
+ || {R,T} <- hipe_sparc_registers:tailcall_clobbered() ++ all_fp_pseudos()].
+
+insn_use_gpr(I) ->
+ case I of
+ #alu{src1=Src1,src2=Src2} -> addsrc(Src2, [Src1]);
+ %% #br{src=Src} -> [Src]; % XXX: can br occur this early?
+ #jmp{src1=Src1,src2=Src2} -> addsrc(Src2, [Src1]);
+ %% #jmpl{src=Src} -> [Src]; % XXX: can jmpl occur this early?
+ %% #pseudo_br{src=Src} -> [Src];
+ #pseudo_call{funv=FunV,sdesc=#sparc_sdesc{arity=Arity}} ->
+ funv_use(FunV, arity_use_gpr(Arity));
+ #pseudo_move{src=Src} -> [Src];
+ #pseudo_ret{} -> [hipe_sparc:mk_rv()];
+ #pseudo_tailcall{funv=FunV,arity=Arity,stkargs=StkArgs} ->
+ addsrcs(StkArgs, addtemps(tailcall_clobbered_gpr(), funv_use(FunV, arity_use_gpr(Arity))));
+ #store{src=Src,base=Base,disp=Disp} ->
+ addtemp(Src, addsrc(Disp, [Base]));
+ #pseudo_fload{base=Base} -> [Base];
+ #pseudo_fstore{base=Base} -> [Base];
+ _ -> []
+ end.
+
+arity_use_gpr(Arity) ->
+ [hipe_sparc:mk_temp(R, 'tagged')
+ || R <- hipe_sparc_registers:args(Arity)].
+
+funv_use(FunV, Set) ->
+ case FunV of
+ #sparc_temp{} -> addtemp(FunV, Set);
+ _ -> Set
+ end.
+
+addsrcs([Arg|Args], Set) ->
+ addsrcs(Args, addsrc(Arg, Set));
+addsrcs([], Set) ->
+ Set.
+
+addsrc(Src, Set) ->
+ case Src of
+ #sparc_temp{} -> addtemp(Src, Set);
+ _ -> Set
+ end.
+
+%%%
+%%% Defs and uses for floating-point registers only.
+%%%
+insn_def_fpr(I) ->
+ case I of
+ #pseudo_call{} -> call_clobbered_fpr();
+ #fp_binary{dst=Dst} -> [Dst];
+ #fp_unary{dst=Dst} -> [Dst];
+ #pseudo_fload{dst=Dst} -> [Dst];
+ #pseudo_fmove{dst=Dst} -> [Dst];
+ _ -> []
+ end.
+
+call_clobbered_fpr() ->
+ [hipe_sparc:mk_temp(R, 'double') || R <- hipe_sparc_registers:allocatable_fpr()].
+
+insn_use_fpr(I) ->
+ case I of
+ #fp_binary{src1=Src1,src2=Src2} -> addtemp(Src1, [Src2]);
+ #fp_unary{src=Src} -> [Src];
+ #pseudo_fmove{src=Src} -> [Src];
+ #pseudo_fstore{src=Src} -> [Src];
+ _ -> []
+ end.
+
+%%%
+%%% Auxiliary operations on sets of temps
+%%% These sets are small. No point using gb_trees, right?
+%%%
+
+addtemps([Arg|Args], Set) ->
+ addtemps(Args, addtemp(Arg, Set));
+addtemps([], Set) ->
+ Set.
+
+addtemp(Temp, Set) ->
+ case lists:member(Temp, Set) of
+ false -> [Temp|Set];
+ _ -> Set
+ end.