* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / reg.c
1 /* src/vm/jit/reg.c - register allocator setup
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28
29    Changes: Stefan Ring
30             Christian Thalinger
31                         Christian Ullrich
32             Michael Starzinger
33
34    $Id: reg.c 4357 2006-01-22 23:33:38Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42
43 #include "vm/types.h"
44
45 #include "arch.h"
46 #include "md-abi.h"
47
48 #include "mm/memory.h"
49 #include "vm/jit/reg.h"
50
51
52 /* reg_setup *******************************************************************
53
54    TODO
55
56 *******************************************************************************/
57
58 void reg_setup(methodinfo *m, registerdata *rd, t_inlining_globals *id)
59 {
60         s4 i;
61         varinfo5 *v;
62         
63         /* setup the integer register table */
64
65 #if defined(__ARM__)
66         /* On ARM longs can be split across argument regs and stack. This is
67          * signed by setting the HIGH_REG to INT_ARG_CNT in md_param_alloc().
68          * Here we make sure it resolves to a special dummy reg (REG_SPLIT). */
69         rd->argintregs = DMNEW(s4, INT_ARG_CNT + 1);
70         rd->argintregs[INT_ARG_CNT] = REG_SPLIT;
71 #else
72         rd->argintregs = DMNEW(s4, INT_ARG_CNT);
73 #endif
74         rd->tmpintregs = DMNEW(s4, INT_TMP_CNT);
75         rd->savintregs = DMNEW(s4, INT_SAV_CNT);
76         rd->freeargintregs = DMNEW(s4, INT_ARG_CNT);
77         rd->freetmpintregs = DMNEW(s4, INT_TMP_CNT);
78         rd->freesavintregs = DMNEW(s4, INT_SAV_CNT);
79
80         rd->argintreguse = 0;
81         rd->tmpintreguse = 0;
82         rd->savintreguse = 0;
83
84         for (i = 0; i < INT_REG_CNT; i++) {
85                 switch (nregdescint[i]) {
86                 case REG_RET:
87                         rd->intreg_ret = i; 
88                         break;
89                 case REG_SAV:
90                         rd->savintregs[rd->savintreguse++] = i;
91                         break;
92                 case REG_TMP:
93                         rd->tmpintregs[rd->tmpintreguse++] = i; 
94                         break;
95                 case REG_ARG:
96                         rd->argintregs[rd->argintreguse++] = i;
97                         break;
98                 }
99         }
100         assert(rd->savintreguse == INT_SAV_CNT);
101         assert(rd->tmpintreguse == INT_TMP_CNT);
102         assert(rd->argintreguse == INT_ARG_CNT);
103
104 #if defined(__X86_64__)
105         /* 
106          * on x86_64 the argument registers are not in ascending order 
107          * a00 (%rdi) <-> a03 (%rcx) and a01 (%rsi) <-> a02 (%rdx)
108          */
109         i = rd->argintregs[3];
110         rd->argintregs[3] = rd->argintregs[0];
111         rd->argintregs[0] = i;
112
113         i = rd->argintregs[2];
114         rd->argintregs[2] = rd->argintregs[1];
115         rd->argintregs[1] = i;
116 #endif
117                 
118 #ifdef HAS_ADDRESS_REGISTER_FILE
119         /* setup the address register table */
120
121         rd->argadrregs = DMNEW(s4, ADR_ARG_CNT);
122         rd->tmpadrregs = DMNEW(s4, ADR_TMP_CNT);
123         rd->savadrregs = DMNEW(s4, ADR_SAV_CNT);
124         rd->freeargadrregs = DMNEW(s4, ADR_ARG_CNT);
125         rd->freetmpadrregs = DMNEW(s4, ADR_TMP_CNT);
126         rd->freesavadrregs = DMNEW(s4, ADR_SAV_CNT);
127
128         rd->adrreg_argnum = 0;
129         rd->argadrreguse = 0;
130         rd->tmpadrreguse = 0;
131         rd->savadrreguse = 0;
132
133         for (i = 0; i < ADR_REG_CNT; i++) {
134                 switch (nregdescadr[i]) {
135                 case REG_RET:
136                         rd->adrreg_ret = i; 
137                         break;
138                 case REG_SAV:
139                         rd->savadrregs[rd->savadrreguse++] = i;
140                         break;
141                 case REG_TMP:
142                         rd->tmpadrregs[rd->tmpadrreguse++] = i; 
143                         break;
144                 case REG_ARG:
145                         rd->argadrregs[rd->argadrreguse++] = i;
146                         break;
147                 }
148         }
149         assert(rd->savadrreguse == ADR_SAV_CNT);
150         assert(rd->tmpadrreguse == ADR_TMP_CNT);
151         assert(rd->argadrreguse == ADR_ARG_CNT);
152 #endif
153                 
154         /* setup the float register table */
155
156         rd->argfltregs = DMNEW(s4, FLT_ARG_CNT);
157         rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
158         rd->savfltregs = DMNEW(s4, FLT_SAV_CNT);
159         rd->freeargfltregs = DMNEW(s4, FLT_ARG_CNT);
160         rd->freetmpfltregs = DMNEW(s4, FLT_TMP_CNT);
161         rd->freesavfltregs = DMNEW(s4, FLT_SAV_CNT);
162
163         rd->argfltreguse = 0;
164         rd->tmpfltreguse = 0;
165         rd->savfltreguse = 0;
166
167         for (i = 0; i < FLT_REG_CNT; i++) {
168                 switch (nregdescfloat[i]) {
169                 case REG_RET:
170                         rd->fltreg_ret = i;
171                         break;
172                 case REG_SAV:
173                         rd->savfltregs[rd->savfltreguse++] = i;
174                         break;
175                 case REG_TMP:
176                         rd->tmpfltregs[rd->tmpfltreguse++] = i;
177                         break;
178                 case REG_ARG:
179                         rd->argfltregs[rd->argfltreguse++] = i;
180                         break;
181                 }
182         }
183         assert(rd->savfltreguse == FLT_SAV_CNT);
184         assert(rd->tmpfltreguse == FLT_TMP_CNT);
185         assert(rd->argfltreguse == FLT_ARG_CNT);
186
187
188         rd->freemem    = DMNEW(s4, id->cummaxstack);
189 #if defined(HAS_4BYTE_STACKSLOT)
190         rd->freemem_2  = DMNEW(s4, id->cummaxstack);
191 #endif
192         rd->locals     = DMNEW(varinfo5, id->cumlocals);
193         rd->interfaces = DMNEW(varinfo5, id->cummaxstack);
194         for (v = rd->locals, i = id->cumlocals; i > 0; v++, i--) {
195                 v[0][TYPE_INT].type = -1;
196                 v[0][TYPE_LNG].type = -1;
197                 v[0][TYPE_FLT].type = -1;
198                 v[0][TYPE_DBL].type = -1;
199                 v[0][TYPE_ADR].type = -1;
200         }
201
202         for (v = rd->interfaces, i = id->cummaxstack; i > 0; v++, i--) {
203                 v[0][TYPE_INT].type = -1;
204                 v[0][TYPE_INT].flags = 0;
205                 v[0][TYPE_LNG].type = -1;
206                 v[0][TYPE_LNG].flags = 0;
207                 v[0][TYPE_FLT].type = -1;
208                 v[0][TYPE_FLT].flags = 0;
209                 v[0][TYPE_DBL].type = -1;
210                 v[0][TYPE_DBL].flags = 0;
211                 v[0][TYPE_ADR].type = -1;
212                 v[0][TYPE_ADR].flags = 0;
213         }
214
215 #if defined(SPECIALMEMUSE)
216 # if defined(__DARWIN__)
217         /* 6*4=24 byte linkage area + 8*4=32 byte minimum parameter Area */
218         rd->memuse = LA_WORD_SIZE + INT_ARG_CNT; 
219 # else
220         rd->memuse = LA_WORD_SIZE;
221 # endif
222 #else
223         rd->memuse = 0; /* init to zero -> analyse_stack will set it to a higher  */
224                         /* value, if appropriate */
225 #endif
226
227         /* Set rd->argxxxreguse to XXX_ARG_CNBT to not use unused argument        */
228         /* registers as temp registers  */
229 #if defined(HAS_ADDRESS_REGISTER_FILE)
230         rd->argadrreguse = 0;
231 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
232         rd->argintreguse = 0;
233         rd->argfltreguse = 0;
234 }
235
236
237 /*
238  * These are local overrides for various environment variables in Emacs.
239  * Please do not remove this and leave it at the end of the file, where
240  * Emacs will automagically detect them.
241  * ---------------------------------------------------------------------
242  * Local variables:
243  * mode: c
244  * indent-tabs-mode: t
245  * c-basic-offset: 4
246  * tab-width: 4
247  * End:
248  */