diff options
Diffstat (limited to 'lib/hipe/sparc/hipe_sparc_registers.erl')
-rw-r--r-- | lib/hipe/sparc/hipe_sparc_registers.erl | 291 |
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} + ]. |