* src/vm/jit/intrp/peephole.c: Updated to current codebase.
[cacao.git] / src / vm / jit / arm / md-abi.c
1 /* src/vm/jit/arm/md-abi.c - functions for arm ABI
2
3    Copyright (C) 1996-2005, 2006, 2007 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    $Id: md-abi.c 7356 2007-02-14 11:00:28Z twisti $
26
27 */
28
29
30 #include "config.h"
31 #include "vm/types.h"
32
33 #include "vm/jit/arm/md-abi.h"
34
35 #include "vm/global.h"
36
37 #include "vm/jit/abi.h"
38
39 #include "vmcore/descriptor.h"
40
41
42 /* register descripton array **************************************************/
43
44 s4 nregdescint[] = {
45         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
46         REG_SAV, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
47         REG_END
48 };
49
50 const char *abi_registers_integer_name[] = {
51         "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4",
52         "v5", "t3", "t1", "t2", "ip", "sp", "lr", "pc",
53 };
54
55
56 #if defined(ENABLE_SOFTFLOAT)
57 s4 nregdescfloat[] = {
58         REG_RES, REG_RES, REG_RES, REG_RES,
59         REG_RES, REG_RES, REG_RES, REG_RES,
60         REG_END
61 };
62 #else
63 /* TODO: FPA register usage conventions */
64 s4 nregdescfloat[] = {
65         REG_TMP, REG_TMP, REG_TMP, REG_TMP,
66         REG_TMP, REG_TMP, REG_RES, REG_RES,
67         REG_END
68 };
69 #endif /* defined(ENABLE_SOFTFLOAT) */
70
71
72 /* md_param_alloc **************************************************************
73
74    Allocate Arguments to Stackslots according the Calling Conventions
75
76    --- in:
77    md->paramcount:           Number of arguments for this method
78    md->paramtypes[].type:    Argument types
79
80    --- out:
81    md->params[].inmemory:    Argument spilled on stack
82    md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
83    md->memuse:               Stackslots needed for argument spilling
84    md->argintreguse:         max number of integer arguments used
85    md->argfltreguse:         max number of float arguments used
86
87 *******************************************************************************/
88
89 void md_param_alloc(methoddesc *md)
90 {
91         paramdesc *pd;
92         s4         i;
93         s4         reguse;
94         s4         stacksize;
95
96         /* set default values */
97         reguse = 0;
98         stacksize = 0;
99
100         /* get params field of methoddesc */
101         pd = md->params;
102
103         for (i = 0; i < md->paramcount; i++, pd++) {
104                 switch (md->paramtypes[i].type) {
105                 case TYPE_INT:
106                 case TYPE_ADR:
107                 case TYPE_FLT:
108                         if (reguse < INT_ARG_CNT) {
109                                 pd->inmemory = false;
110                                 pd->regoff = reguse;
111                                 reguse++;
112                         }
113                         else {
114                                 pd->inmemory = true;
115                                 pd->regoff = stacksize;
116                                 stacksize++;
117                         }
118                         break;
119
120                 case TYPE_LNG:
121                 case TYPE_DBL:
122                         if (reguse+1 < INT_ARG_CNT) {
123                                 pd->inmemory = false;
124 #if defined(__ARMEL__)
125                                 pd->regoff = PACK_REGS(reguse, reguse+1);
126 #else
127                                 pd->regoff = PACK_REGS(reguse+1, reguse);
128 #endif
129                                 reguse += 2;
130                         }
131                         else if (reguse < INT_ARG_CNT) {
132                                 pd->inmemory = false;
133 #if defined(__ARMEL__)
134                                 pd->regoff = PACK_REGS(reguse, INT_ARG_CNT);
135 #else
136                                 pd->regoff = PACK_REGS(INT_ARG_CNT, reguse);
137 #endif
138                                 reguse++;
139                                 stacksize++;
140                         }
141                         else {
142                                 pd->inmemory = true;
143                                 pd->regoff = stacksize;
144                                 stacksize += 2;
145                         }
146                         break;
147                 }
148         }
149
150         /* Since R0/R1 (==A0/A1) are used for passing return values, this
151            argument register usage has to be regarded, too. */
152
153         if (md->returntype.type != TYPE_VOID) {
154                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
155                         if (reguse < 1)
156                                 reguse = 1;
157                 }
158                 else {
159                         if (reguse < 2)
160                                 reguse = 2;
161                 }
162         }
163
164         /* fill register and stack usage */
165
166         md->argintreguse = reguse;
167         md->argfltreguse = 0;
168         md->memuse       = stacksize;
169 }
170
171
172 /* md_param_alloc_native *******************************************************
173
174    Pre-allocate arguments according the native ABI.
175
176 *******************************************************************************/
177
178 #define ALIGN_2(a)    do { if ((a) & 0x1) (a)++; } while (0)
179
180 void md_param_alloc_native(methoddesc *md)
181 {
182         paramdesc *pd;
183         s4         i;
184         s4         reguse;
185         s4         stacksize;
186
187         /* set default values */
188
189         reguse    = 0;
190         stacksize = 0;
191
192         /* get params field of methoddesc */
193
194         pd = md->params;
195
196         for (i = 0; i < md->paramcount; i++, pd++) {
197                 switch (md->paramtypes[i].type) {
198                 case TYPE_INT:
199                 case TYPE_ADR:
200                 case TYPE_FLT:
201                         if (reguse < INT_ARG_CNT) {
202                                 pd->inmemory = false;
203                                 pd->regoff   = reguse;
204                                 reguse++;
205                         }
206                         else {
207                                 pd->inmemory = true;
208                                 pd->regoff   = stacksize;
209                                 stacksize++;
210                         }
211                         break;
212
213                 case TYPE_LNG:
214                 case TYPE_DBL:
215                         if (reguse < (INT_ARG_CNT - 1)) {
216 #if defined(__ARM_EABI__)
217                                 ALIGN_2(reguse);
218 #endif
219                                 pd->inmemory = false;
220 #if defined(__ARMEL__)
221                                 pd->regoff   = PACK_REGS(reguse, reguse + 1);
222 #else
223                                 pd->regoff   = PACK_REGS(reguse + 1, reguse);
224 #endif
225                                 reguse += 2;
226                         }
227 #if !defined(__ARM_EABI__)
228                         else if (reguse < INT_ARG_CNT) {
229                                 pd->inmemory = false;
230 # if defined(__ARMEL__)
231                                 pd->regoff   = PACK_REGS(reguse, INT_ARG_CNT);
232 # else
233                                 pd->regoff   = PACK_REGS(INT_ARG_CNT, reguse);
234 # endif
235                                 reguse++;
236                                 stacksize++;
237                         }
238 #endif
239                         else {
240 #if defined(__ARM_EABI__)
241                                 ALIGN_2(stacksize);
242 #endif
243                                 pd->inmemory  = true;
244                                 pd->regoff    = stacksize;
245                                 reguse        = INT_ARG_CNT;
246                                 stacksize    += 2;
247                         }
248                         break;
249                 }
250         }
251
252         /* Since R0/R1 (==A0/A1) are used for passing return values, this
253            argument register usage has to be regarded, too. */
254
255         if (md->returntype.type != TYPE_VOID) {
256                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
257                         if (reguse < 1)
258                                 reguse = 1;
259                 }
260                 else {
261                         if (reguse < 2)
262                                 reguse = 2;
263                 }
264         }
265
266         /* fill register and stack usage */
267
268         md->argintreguse = reguse;
269         md->argfltreguse = 0;
270         md->memuse       = stacksize;
271 }
272
273
274 /* md_return_alloc *************************************************************
275
276    Precolor the Java Stackelement containing the Return Value, if possible.
277
278    --- in
279    m:                       Methodinfo of current method
280    return_type:             Return Type of the Method (TYPE_INT.. TYPE_ADR)
281                             TYPE_VOID is not allowed!
282    stackslot:               Java Stackslot to contain the Return Value
283
284    --- out
285    if precoloring was possible:
286    VAR(stackslot->varnum)->flags = PREALLOC
287    VAR(stackslot->varnum)->vv.regoff = [REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
288    rd->arg[flt|int]reguse   set to a value according the register usage
289
290 *******************************************************************************/
291
292 void md_return_alloc(jitdata *jd, stackptr stackslot)
293 {
294         methodinfo   *m;
295         registerdata *rd;
296         methoddesc   *md;
297
298         /* get required compiler data */
299
300         m  = jd->m;
301         rd = jd->rd;
302
303         md = m->parseddesc;
304
305         /* In Leafmethods Local Vars holding parameters are precolored to
306            their argument register -> so leafmethods with paramcount > 0
307            could already use R0 == a00! */
308
309         if (!jd->isleafmethod || (md->paramcount == 0)) {
310                 /* Only precolor the stackslot, if it is not a SAVEDVAR <->
311                    has not to survive method invokations. */
312
313                 if (!(stackslot->flags & SAVEDVAR)) {
314 #if !defined(ENABLE_SOFTFLOAT)
315                         /* Stackelements containing float or double values
316                            (TYPE_FLT | TYPE_DBL) cannot be precolored, because we
317                            use integer register to pass return values. (floats:
318                            R0, doubles: R0/R1) */
319
320                         if (!IS_FLT_DBL_TYPE(md->returntype.type)) {
321 #endif
322
323                                 VAR(stackslot->varnum)->flags = PREALLOC;
324
325                                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
326                                         if (rd->argintreguse < 1)
327                                                 rd->argintreguse = 1;
328
329                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
330                                 }
331                                 else {
332                                         if (rd->argintreguse < 2)
333                                                 rd->argintreguse = 2;
334
335                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
336                                 }
337
338 #if !defined(ENABLE_SOFTFLOAT)
339                         }
340 #endif
341                 }
342         }
343 }
344
345
346 /*
347  * These are local overrides for various environment variables in Emacs.
348  * Please do not remove this and leave it at the end of the file, where
349  * Emacs will automagically detect them.
350  * ---------------------------------------------------------------------
351  * Local variables:
352  * mode: c
353  * indent-tabs-mode: t
354  * c-basic-offset: 4
355  * tab-width: 4
356  * End:
357  */