aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/sparc/hipe_sparc_registers.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/sparc/hipe_sparc_registers.erl')
-rw-r--r--lib/hipe/sparc/hipe_sparc_registers.erl291
1 files changed, 291 insertions, 0 deletions
diff --git a/lib/hipe/sparc/hipe_sparc_registers.erl b/lib/hipe/sparc/hipe_sparc_registers.erl
new file mode 100644
index 0000000000..adb01a65ca
--- /dev/null
+++ b/lib/hipe/sparc/hipe_sparc_registers.erl
@@ -0,0 +1,291 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-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_registers).
+
+-export([reg_name_gpr/1,
+ reg_name_fpr/1,
+ first_virtual/0,
+ is_precoloured_gpr/1,
+ is_precoloured_fpr/1,
+ all_precoloured/0, % for coalescing ra
+ return_value/0,
+ temp1/0,
+ temp2/0,
+ temp3/0,
+ heap_pointer/0,
+ stack_pointer/0,
+ proc_pointer/0,
+ return_address/0,
+ g0/0,
+ %% heap_limit/0,
+ %% fcalls/0,
+ allocatable_gpr/0, % for coalescing ra
+ allocatable_fpr/0,
+ is_fixed/1, % for graph_coloring ra
+ nr_args/0,
+ arg/1,
+ args/1,
+ is_arg/1, % for linear_scan ra
+ call_clobbered/0,
+ tailcall_clobbered/0,
+ live_at_return/0
+ ]).
+
+-include("../rtl/hipe_literals.hrl").
+
+-define(G0, 0).
+-define(G1, 1).
+-define(G2, 2).
+-define(G3, 3).
+-define(G4, 4).
+-define(G5, 5).
+-define(G6, 6).
+-define(G7, 7).
+-define(O0, 8).
+-define(O1, 9).
+-define(O2, 10).
+-define(O3, 11).
+-define(O4, 12).
+-define(O5, 13).
+-define(O6, 14).
+-define(O7, 15).
+-define(L0, 16).
+-define(L1, 17).
+-define(L2, 18).
+-define(L3, 19).
+-define(L4, 20).
+-define(L5, 21).
+-define(L6, 22).
+-define(L7, 23).
+-define(I0, 24).
+-define(I1, 25).
+-define(I2, 26).
+-define(I3, 27).
+-define(I4, 28).
+-define(I5, 29).
+-define(I6, 30).
+-define(I7, 31).
+-define(LAST_PRECOLOURED,31). % must handle both GRP and FPR ranges
+
+-define(ARG0, ?O1).
+-define(ARG1, ?O2).
+-define(ARG2, ?O3).
+-define(ARG3, ?O4).
+-define(ARG4, ?O5).
+-define(ARG5, ?O0).
+
+-define(TEMP1, ?I3). % stores RA around inc_stack calls, must be C calleE-save
+-define(TEMP2, ?I4).
+-define(TEMP3, ?I5).
+
+-define(RETURN_VALUE, ?O0).
+-define(HEAP_POINTER, ?I2).
+-define(STACK_POINTER, ?I1).
+-define(PROC_POINTER, ?I0).
+
+reg_name_gpr(R) ->
+ case R of
+ ?G0 -> "%g0";
+ ?G1 -> "%g1";
+ ?G2 -> "%g2";
+ ?G3 -> "%g3";
+ ?G4 -> "%g4";
+ ?G5 -> "%g5";
+ ?G6 -> "%g6";
+ ?G7 -> "%g7";
+ ?O0 -> "%o0";
+ ?O1 -> "%o1";
+ ?O2 -> "%o2";
+ ?O3 -> "%o3";
+ ?O4 -> "%o4";
+ ?O5 -> "%o5";
+ ?O6 -> "%sp";
+ ?O7 -> "%o7";
+ ?L0 -> "%l0";
+ ?L1 -> "%l1";
+ ?L2 -> "%l2";
+ ?L3 -> "%l3";
+ ?L4 -> "%l4";
+ ?L5 -> "%l5";
+ ?L6 -> "%l6";
+ ?L7 -> "%l7";
+ ?I0 -> "%i0";
+ ?I1 -> "%i1";
+ ?I2 -> "%i2";
+ ?I3 -> "%i3";
+ ?I4 -> "%i4";
+ ?I5 -> "%i5";
+ ?I6 -> "%fp";
+ ?I7 -> "%i7";
+ %% to handle code before regalloc:
+ _ -> "%r" ++ integer_to_list(R)
+ end.
+
+reg_name_fpr(R) -> [$f | integer_to_list(2*R)].
+
+%%% Must handle both GPR and FPR ranges.
+first_virtual() -> ?LAST_PRECOLOURED + 1.
+
+%%% These two tests have the same implementation, but that's
+%%% not something we should cast in stone in the interface.
+is_precoloured_gpr(R) -> R =< ?LAST_PRECOLOURED.
+is_precoloured_fpr(R) -> R =< ?LAST_PRECOLOURED.
+
+all_precoloured() ->
+ %% <%g6, %g7, %o6, %i6> should be skipped as they are unused.
+ %% Unfortunately, gaps in the list of precoloured registers
+ %% cause the graph_color register allocator to create bogus
+ %% assignments for those "registers", which in turn causes
+ %% the "precoloured reg must map to itself" sanity check in
+ %% the frame module to signal errors.
+ [?G0, ?G1, ?G2, ?G3, ?G4, ?G5, ?G6, ?G7,
+ ?O0, ?O1, ?O2, ?O3, ?O4, ?O5, ?O6, ?O7,
+ ?L0, ?L1, ?L2, ?L3, ?L4, ?L5, ?L6, ?L7,
+ ?I0, ?I1, ?I2, ?I3, ?I4, ?I5, ?I6, ?I7].
+
+return_value() -> ?RETURN_VALUE.
+
+temp1() -> ?TEMP1.
+temp2() -> ?TEMP2.
+temp3() -> ?TEMP3.
+
+heap_pointer() -> ?HEAP_POINTER.
+
+stack_pointer() -> ?STACK_POINTER.
+
+proc_pointer() -> ?PROC_POINTER.
+
+return_address() -> ?O7.
+
+g0() -> ?G0.
+
+allocatable_gpr() ->
+ %% %g0 is not writable
+ %% %g6, %g7, %o6, and %i6 are reserved for C
+ %% %i0, %i1, and %i2 are fixed global registers
+ %% %i4 may be used by the frame module for large load/store offsets
+ [ ?G1, ?G2, ?G3, ?G4, ?G5,
+ ?O0, ?O1, ?O2, ?O3, ?O4, ?O5, ?O7,
+ ?L0, ?L1, ?L2, ?L3, ?L4, ?L5, ?L6, ?L7,
+ ?I3, ?I5, ?I7].
+
+allocatable_fpr() ->
+ %% We expose 16 virtual fp regs, 0-15, corresponding to the
+ %% f0/f2/f4/.../f28/f30 double-precision hardware fp regs.
+ %% The mapping is done by reg_name_fpr/1 and the assembler.
+ %% We ignore f32/.../f60 since they cannot be used in loads
+ %% or stores for non 8-byte aligned addresses.
+ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].
+
+%% Needed for hipe_graph_coloring_regalloc.
+%% Presumably true for Reg in AllPrecoloured \ Allocatable.
+is_fixed(Reg) ->
+ case Reg of
+ ?HEAP_POINTER -> true;
+ ?STACK_POINTER -> true;
+ ?PROC_POINTER -> true;
+ %% The following cases are required for linear scan:
+ %% it gets confused if it sees a register which is
+ %% neither allocatable nor global (fixed or one of
+ %% the scratch registers set aside for linear scan).
+ ?G0 -> true;
+ ?G6 -> true;
+ ?G7 -> true;
+ ?O6 -> true;
+ ?I6 -> true;
+ _ -> false
+ end.
+
+nr_args() -> ?SPARC_NR_ARG_REGS.
+
+args(Arity) when is_integer(Arity) ->
+ N = erlang:min(Arity, ?SPARC_NR_ARG_REGS),
+ args(N-1, []).
+
+args(I, Rest) when is_integer(I), I < 0 -> Rest;
+args(I, Rest) -> args(I-1, [arg(I) | Rest]).
+
+arg(N) ->
+ if N < ?SPARC_NR_ARG_REGS ->
+ case N of
+ 0 -> ?ARG0;
+ 1 -> ?ARG1;
+ 2 -> ?ARG2;
+ 3 -> ?ARG3;
+ 4 -> ?ARG4;
+ 5 -> ?ARG5
+ end
+ end.
+
+is_arg(R) ->
+ case R of
+ ?ARG0 -> ?SPARC_NR_ARG_REGS > 0;
+ ?ARG1 -> ?SPARC_NR_ARG_REGS > 1;
+ ?ARG2 -> ?SPARC_NR_ARG_REGS > 2;
+ ?ARG3 -> ?SPARC_NR_ARG_REGS > 3;
+ ?ARG4 -> ?SPARC_NR_ARG_REGS > 4;
+ ?ARG5 -> ?SPARC_NR_ARG_REGS > 5;
+ _ -> false
+ end.
+
+call_clobbered() -> % does the RA strip the type or not?
+ [%% ?G0 is the non-allocatable constant zero
+ {?G1,tagged},{?G1,untagged},
+ {?G2,tagged},{?G2,untagged},
+ {?G3,tagged},{?G3,untagged},
+ {?G4,tagged},{?G4,untagged},
+ {?G5,tagged},{?G5,untagged},
+ %% ?G6 is reserved for C
+ %% ?G7 is reserved for C
+ {?O0,tagged},{?O0,untagged},
+ {?O1,tagged},{?O1,untagged},
+ {?O2,tagged},{?O2,untagged},
+ {?O3,tagged},{?O3,untagged},
+ {?O4,tagged},{?O4,untagged},
+ {?O5,tagged},{?O5,untagged},
+ %% ?O6 is reserved for C
+ {?O7,tagged},{?O7,untagged},
+ {?L0,tagged},{?L0,untagged},
+ {?L1,tagged},{?L1,untagged},
+ {?L2,tagged},{?L2,untagged},
+ {?L3,tagged},{?L3,untagged},
+ {?L4,tagged},{?L4,untagged},
+ {?L5,tagged},{?L5,untagged},
+ {?L6,tagged},{?L6,untagged},
+ {?L7,tagged},{?L7,untagged},
+ %% ?I0 is fixed (P)
+ %% ?I1 is fixed (NSP)
+ %% ?I2 is fixed (HP)
+ {?I3,tagged},{?I3,untagged},
+ {?I4,tagged},{?I4,untagged},
+ {?I5,tagged},{?I5,untagged},
+ %% ?I6 is reserved for C
+ {?I7,tagged},{?I7,untagged}
+ ].
+
+tailcall_clobbered() -> % tailcall crapola needs one temp
+ [{?TEMP1,tagged},{?TEMP1,untagged}].
+
+live_at_return() ->
+ [{?HEAP_POINTER,untagged},
+ {?STACK_POINTER,untagged},
+ {?PROC_POINTER,untagged}
+ ].