1%%% Licensed under the Apache License, Version 2.0 (the "License");
2%%% you may not use this file except in compliance with the License.
3%%% You may obtain a copy of the License at
4%%%
5%%%     http://www.apache.org/licenses/LICENSE-2.0
6%%%
7%%% Unless required by applicable law or agreed to in writing, software
8%%% distributed under the License is distributed on an "AS IS" BASIS,
9%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10%%% See the License for the specific language governing permissions and
11%%% limitations under the License.
12%%%
13%%% TODO:
14%%% - Do we need a pseudo reg for the condition codes?
15
16-module(hipe_x86_registers).
17
18-export([reg_name/1,
19	 first_virtual/0,
20	 is_precoloured/1,
21	 is_precoloured_x87/1,
22	 all_precoloured/0,
23	 eax/0,
24	 ecx/0,
25	 temp0/0,
26	 temp1/0,
27	 sp/0,
28	 proc_pointer/0,
29	 heap_limit/0,
30	 fcalls/0,
31	 proc_offset/1,
32	 sp_limit_offset/0,
33	 is_fixed/1,
34	 %% fixed/0,
35	 allocatable/0,
36	 allocatable_x87/0,
37	 nr_args/0,
38	 arg/1,
39	 is_arg/1,
40	 args/1,
41	 nr_rets/0,
42	 ret/1,
43	 call_clobbered/0,
44	 tailcall_clobbered/0,
45	 live_at_return/0,
46	 float_size/0,
47	 wordsize/0,
48	 alignment/0]).
49
50-include("../rtl/hipe_literals.hrl").
51
52-ifdef(X86_HP_IN_ESI).
53-export([heap_pointer/0]).
54-endif.
55
56-define(EAX, 0).
57-define(ECX, 1).
58-define(EDX, 2).
59-define(EBX, 3).
60-define(ESP, 4).
61-define(EBP, 5).
62-define(ESI, 6).
63-define(EDI, 7).
64-define(FCALLS, 8).		% proc field alias
65-define(HEAP_LIMIT, 9).		% proc field alias
66-define(LAST_PRECOLOURED, 9).
67
68-define(ARG0, ?EAX).
69-define(ARG1, ?EDX).
70-define(ARG2, ?ECX).
71-define(ARG3, ?EBX).
72-define(ARG4, ?EDI).
73
74-define(RET0, ?EAX).
75-define(RET1, ?EDX).
76-define(RET2, ?ECX).
77-define(RET3, ?EBX).
78-define(RET4, ?EDI).
79
80-define(TEMP0, ?EBX).	% XXX: was EAX
81-define(TEMP1, ?EDI).	% XXX: was EDX then EDI
82
83-define(PROC_POINTER, ?EBP).
84
85reg_name(R) ->
86    case R of
87	?EAX -> "%eax";
88	?ECX -> "%ecx";
89	?EDX -> "%edx";
90	?EBX -> "%ebx";
91	?ESP -> "%esp";
92	?EBP -> "%ebp";
93	?ESI -> "%esi";
94	?EDI -> "%edi";
95	?FCALLS -> "%fcalls";
96	?HEAP_LIMIT -> "%hplim";
97	Other -> "%r" ++ integer_to_list(Other)
98    end.
99
100first_virtual() -> ?LAST_PRECOLOURED + 1.
101
102is_precoloured(X) -> X =< ?LAST_PRECOLOURED.
103
104is_precoloured_x87(X) -> X =< 6.
105
106all_precoloured() ->
107    [?EAX,
108     ?ECX,
109     ?EDX,
110     ?EBX,
111     ?ESP,
112     ?EBP,
113     ?ESI,
114     ?EDI,
115     ?FCALLS,
116     ?HEAP_LIMIT].
117
118eax() -> ?EAX.
119ecx() -> ?ECX.
120temp0() -> ?TEMP0.
121temp1() -> ?TEMP1.
122sp() -> ?ESP.
123proc_pointer() -> ?PROC_POINTER.
124fcalls() -> ?FCALLS.
125heap_limit() -> ?HEAP_LIMIT.
126
127-ifdef(X86_HP_IN_ESI).
128-define(ESI_IS_FIXED,1).
129-define(HEAP_POINTER, ?ESI).
130heap_pointer() -> ?HEAP_POINTER.
131is_heap_pointer(?HEAP_POINTER) -> true;
132is_heap_pointer(_) -> false.
133-define(LIST_HP_FIXED,[?HEAP_POINTER]).
134-define(LIST_HP_LIVE_AT_RETURN,[{?HEAP_POINTER,untagged}]).
135-else.
136is_heap_pointer(_) -> false.
137-define(LIST_HP_FIXED,[]).
138-define(LIST_HP_LIVE_AT_RETURN,[]).
139-endif.
140
141-ifdef(ESI_IS_FIXED).
142-define(LIST_ESI_ALLOCATABLE,[]).
143-define(LIST_ESI_CALL_CLOBBERED,[]).
144-else.
145-define(LIST_ESI_ALLOCATABLE,[?ESI]).
146-define(LIST_ESI_CALL_CLOBBERED,[{?ESI,tagged},{?ESI,untagged}]).
147-endif.
148
149proc_offset(?FCALLS) -> ?P_FCALLS;
150proc_offset(?HEAP_LIMIT) -> ?P_HP_LIMIT;
151proc_offset(_) -> false.
152
153sp_limit_offset() -> ?P_NSP_LIMIT.
154
155is_fixed(?ESP) -> true;
156is_fixed(?PROC_POINTER) -> true;
157is_fixed(?FCALLS) -> true;
158is_fixed(?HEAP_LIMIT) -> true;
159is_fixed(R) -> is_heap_pointer(R).
160
161%% fixed() ->
162%%     [?ESP, ?PROC_POINTER, ?FCALLS, ?HEAP_LIMIT | ?LIST_HP_FIXED].
163
164allocatable() ->
165    [?EDX, ?ECX, ?EBX, ?EAX, ?EDI| ?LIST_ESI_ALLOCATABLE].
166
167allocatable_x87() ->
168    [0,1,2,3,4,5,6].
169
170nr_args() -> ?X86_NR_ARG_REGS.
171
172arg(N) ->
173    if N < ?X86_NR_ARG_REGS ->
174	    case N of
175		0 -> ?ARG0;
176		1 -> ?ARG1;
177		2 -> ?ARG2;
178		3 -> ?ARG3;
179		4 -> ?ARG4;
180		_ -> exit({?MODULE, arg, N})
181	    end;
182       true ->
183	    exit({?MODULE, arg, N})
184    end.
185
186is_arg(R) ->
187    case R of
188	?ARG0 -> ?X86_NR_ARG_REGS > 0;
189	?ARG1 -> ?X86_NR_ARG_REGS > 1;
190	?ARG2 -> ?X86_NR_ARG_REGS > 2;
191	?ARG3 -> ?X86_NR_ARG_REGS > 3;
192	?ARG4 -> ?X86_NR_ARG_REGS > 4;
193	_ -> false
194    end.
195
196args(Arity) when is_integer(Arity), Arity >= 0 ->
197    N = erlang:min(Arity, ?X86_NR_ARG_REGS),
198    args(N-1, []).
199
200args(I, Rest) when I < 0 -> Rest;
201args(I, Rest) -> args(I-1, [arg(I) | Rest]).
202
203nr_rets() -> ?X86_NR_RET_REGS.
204
205ret(N) ->
206    if N < ?X86_NR_RET_REGS ->
207	    case N of
208		0 -> ?RET0;
209		1 -> ?RET1;
210		2 -> ?RET2;
211		3 -> ?RET3;
212		4 -> ?RET4;
213		_ -> exit({?MODULE, ret, N})
214	    end;
215       true ->
216	    exit({?MODULE, ret, N})
217    end.
218
219%% Note: the fact that (allocatable() UNION allocatable_x87()) is a subset of
220%% call_clobbered() is hard-coded in hipe_x86_defuse:insn_defs_all/1
221call_clobbered() ->
222    [{?EAX,tagged},{?EAX,untagged},	% does the RA strip the type or not?
223     {?EDX,tagged},{?EDX,untagged},
224     {?ECX,tagged},{?ECX,untagged},
225     {?EBX,tagged},{?EBX,untagged},
226     {?EDI,tagged},{?EDI,untagged}
227     | ?LIST_ESI_CALL_CLOBBERED] ++ all_x87_pseudos().
228
229tailcall_clobbered() ->		% tailcall crapola needs two temps
230    [{?TEMP0,tagged},{?TEMP0,untagged},
231     {?TEMP1,tagged},{?TEMP1,untagged}] ++ all_x87_pseudos().
232
233all_x87_pseudos() ->
234  [{0,double}, {1,double}, {2,double}, {3,double},
235   {4,double}, {5,double}, {6,double}].
236
237live_at_return() ->
238    [{?ESP,untagged}
239     ,{?PROC_POINTER,untagged}
240     ,{?FCALLS,untagged}
241     ,{?HEAP_LIMIT,untagged}
242     | ?LIST_HP_LIVE_AT_RETURN
243    ].
244
245alignment() -> 4.
246
247float_size() -> 8.
248
249wordsize() -> 4.
250