aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/amd64/hipe_amd64_registers.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe/amd64/hipe_amd64_registers.erl')
-rw-r--r--lib/hipe/amd64/hipe_amd64_registers.erl288
1 files changed, 288 insertions, 0 deletions
diff --git a/lib/hipe/amd64/hipe_amd64_registers.erl b/lib/hipe/amd64/hipe_amd64_registers.erl
new file mode 100644
index 0000000000..4c49eeb00a
--- /dev/null
+++ b/lib/hipe/amd64/hipe_amd64_registers.erl
@@ -0,0 +1,288 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-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_amd64_registers).
+
+-export([
+ all_precoloured/0,
+ allocatable/0,
+ allocatable_sse2/0,
+ allocatable_x87/0,
+ arg/1,
+ args/1,
+ call_clobbered/0,
+ fcalls/0,
+ float_size/0,
+ first_virtual/0,
+ heap_limit/0,
+ is_arg/1,
+ is_fixed/1,
+ is_precoloured/1,
+ is_precoloured_sse2/1,
+ is_precoloured_x87/1,
+ live_at_return/0,
+ nr_args/0,
+ proc_offset/1,
+ proc_pointer/0,
+ rax/0,
+ rcx/0,
+ ret/1,
+ sp/0,
+ sp_limit_offset/0,
+ reg_name/1,
+ alignment/0,
+ tailcall_clobbered/0,
+ temp0/0,
+ temp1/0,
+ %% fixed/0,
+ wordsize/0
+ ]).
+
+-include("../rtl/hipe_literals.hrl").
+
+-ifdef(AMD64_HP_IN_REGISTER).
+-export([heap_pointer/0]).
+-endif.
+
+-ifdef(AMD64_FCALLS_IN_REGISTER).
+fcalls_offset() -> false.
+-else.
+fcalls_offset() -> ?P_FCALLS.
+-define(AMD64_FCALLS_REGISTER,16).
+-endif.
+
+-ifdef(AMD64_HEAP_LIMIT_IN_REGISTER).
+heap_limit_offset() -> false.
+-else.
+-define(AMD64_HEAP_LIMIT_REGISTER, 17).
+heap_limit_offset() -> ?P_HP_LIMIT.
+-endif.
+
+
+-define(RAX, 0).
+-define(RCX, 1).
+-define(RDX, 2).
+-define(RBX, 3).
+-define(RSP, 4).
+-define(RBP, 5).
+-define(RSI, 6).
+-define(RDI, 7).
+-define(R8 , 8).
+-define(R9 , 9).
+-define(R10, 10).
+-define(R11, 11).
+-define(R12, 12).
+-define(R13, 13).
+-define(R14, 14).
+-define(R15, 15).
+-define(FCALLS, ?AMD64_FCALLS_REGISTER).
+-define(HEAP_LIMIT, ?AMD64_HEAP_LIMIT_REGISTER).
+-define(LAST_PRECOLOURED, 17).
+
+-define(ARG0, ?RSI).
+-define(ARG1, ?RDX).
+-define(ARG2, ?RCX).
+-define(ARG3, ?R8).
+-define(ARG4, ?R9).
+-define(ARG5, ?RDI).
+
+-define(TEMP0, ?R14).
+-define(TEMP1, ?R13).
+
+-define(PROC_POINTER, ?RBP).
+
+reg_name(R) ->
+ case R of
+ ?RAX -> "%rax";
+ ?RCX -> "%rcx";
+ ?RDX -> "%rdx";
+ ?RBX -> "%rbx";
+ ?RSP -> "%rsp";
+ ?RBP -> "%rbp";
+ ?RSI -> "%rsi";
+ ?RDI -> "%rdi";
+ ?FCALLS -> "%fcalls";
+ ?HEAP_LIMIT -> "%hplim";
+ Other -> "%r" ++ integer_to_list(Other)
+ end.
+
+alignment() -> 8.
+
+float_size() -> 8.
+
+first_virtual() -> ?LAST_PRECOLOURED + 1.
+
+is_precoloured(X) -> X =< ?LAST_PRECOLOURED.
+
+is_precoloured_sse2(X) -> X =< 15.
+
+is_precoloured_x87(X) -> X =< 6.
+
+all_precoloured() ->
+ [?RAX,
+ ?RCX,
+ ?RDX,
+ ?RBX,
+ ?RSP,
+ ?RBP,
+ ?RSI,
+ ?RDI,
+ ?R8 ,
+ ?R9 ,
+ ?R10,
+ ?R11,
+ ?R12,
+ ?R13,
+ ?R14,
+ ?R15,
+ ?FCALLS,
+ ?HEAP_LIMIT].
+
+rax() -> ?RAX.
+rcx() -> ?RCX.
+temp0() -> ?TEMP0.
+temp1() -> ?TEMP1.
+sp() -> ?RSP.
+proc_pointer() -> ?PROC_POINTER.
+fcalls() -> ?FCALLS.
+heap_limit() -> ?HEAP_LIMIT.
+
+
+-ifdef(AMD64_HP_IN_REGISTER).
+-define(HEAP_POINTER, ?AMD64_HEAP_POINTER).
+heap_pointer() -> ?HEAP_POINTER.
+-define(LIST_HP_LIVE_AT_RETURN,[{?HEAP_POINTER,untagged}]).
+is_heap_pointer(?HEAP_POINTER) -> true;
+is_heap_pointer(_) -> false.
+%% -define(LIST_HP_FIXED,[?HEAP_POINTER]).
+
+-else.
+-define(HEAP_POINTER, -1).
+is_heap_pointer(_) -> false.
+%% -define(LIST_HP_FIXED,[]).
+-define(LIST_HP_LIVE_AT_RETURN,[]).
+-endif.
+
+proc_offset(?FCALLS) -> fcalls_offset();
+proc_offset(?HEAP_LIMIT) -> heap_limit_offset();
+proc_offset(_) -> false.
+
+sp_limit_offset() -> ?P_NSP_LIMIT.
+
+is_fixed(?RSP) -> true;
+is_fixed(?PROC_POINTER) -> true;
+is_fixed(?FCALLS) -> true;
+is_fixed(?HEAP_LIMIT) -> true;
+is_fixed(R) -> is_heap_pointer(R).
+
+%% fixed() ->
+%% [?ESP, ?PROC_POINTER, ?FCALLS, ?HEAP_LIMIT | ?LIST_HP_FIXED].
+
+allocatable() ->
+ [?RDX, ?RCX, ?RBX, ?RAX, ?RSI, ?RDI,
+ ?R8 , ?R9 , ?R10, ?R11, ?R12, ?R13, ?R14, ?R15]
+ -- [?FCALLS, ?HEAP_POINTER, ?HEAP_LIMIT].
+
+allocatable_sse2() ->
+ [00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15]. %% xmm0 - xmm15
+
+allocatable_x87() ->
+ [0,1,2,3,4,5,6].
+
+nr_args() -> ?AMD64_NR_ARG_REGS.
+
+arg(N) ->
+ if N < ?AMD64_NR_ARG_REGS ->
+ case N of
+ 0 -> ?ARG0;
+ 1 -> ?ARG1;
+ 2 -> ?ARG2;
+ 3 -> ?ARG3;
+ 4 -> ?ARG4;
+ 5 -> ?ARG5;
+ _ -> exit({?MODULE, arg, N})
+ end;
+ true ->
+ exit({?MODULE, arg, N})
+ end.
+
+is_arg(R) ->
+ case R of
+ ?ARG0 -> ?AMD64_NR_ARG_REGS > 0;
+ ?ARG1 -> ?AMD64_NR_ARG_REGS > 1;
+ ?ARG2 -> ?AMD64_NR_ARG_REGS > 2;
+ ?ARG3 -> ?AMD64_NR_ARG_REGS > 3;
+ ?ARG4 -> ?AMD64_NR_ARG_REGS > 4;
+ ?ARG5 -> ?AMD64_NR_ARG_REGS > 5;
+ _ -> false
+ end.
+
+args(Arity) when is_integer(Arity), Arity >= 0 ->
+ N = erlang:min(Arity, ?AMD64_NR_ARG_REGS),
+ args(N-1, []).
+
+args(I, Rest) when I < 0 -> Rest;
+args(I, Rest) -> args(I-1, [arg(I) | Rest]).
+
+ret(N) ->
+ case N of
+ 0 -> ?RAX;
+ _ -> exit({?MODULE, ret, N})
+ end.
+
+call_clobbered() ->
+ [{?RAX,tagged},{?RAX,untagged}, % does the RA strip the type or not?
+ {?RDX,tagged},{?RDX,untagged},
+ {?RCX,tagged},{?RCX,untagged},
+ {?RBX,tagged},{?RBX,untagged},
+ {?RDI,tagged},{?RDI,untagged},
+ {?RSI,tagged},{?RSI,untagged},
+ {?R8 ,tagged},{?R8 ,untagged},
+ {?R9 ,tagged},{?R9 ,untagged},
+ {?R10,tagged},{?R10,untagged},
+ {?R11,tagged},{?R11,untagged},
+ {?R12,tagged},{?R12,untagged},
+ {?R13,tagged},{?R13,untagged},
+ {?R14,tagged},{?R14,untagged},
+ {?R15,tagged},{?R15,untagged}
+ | fp_call_clobbered()]
+ --
+ [{?FCALLS,tagged},{?FCALLS,untagged},
+ {?HEAP_POINTER,tagged},{?HEAP_POINTER,untagged},
+ {?HEAP_LIMIT,tagged},{?HEAP_LIMIT,untagged}
+ ].
+
+fp_call_clobbered() -> %% sse2 since it has more registers than x87
+ [{Reg,double} || Reg <- allocatable_sse2()].
+
+tailcall_clobbered() -> % tailcall crapola needs two temps
+ [{?TEMP0,tagged},{?TEMP0,untagged},
+ {?TEMP1,tagged},{?TEMP1,untagged}
+ | fp_call_clobbered()].
+
+live_at_return() ->
+ [{?RSP,untagged}
+ ,{?PROC_POINTER,untagged}
+ ,{?FCALLS,untagged}
+ ,{?HEAP_LIMIT,untagged}
+ | ?LIST_HP_LIVE_AT_RETURN
+ ].
+
+wordsize() -> 8.