Merged revisions 7918-7939 via svnmerge from
[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 7932 2007-05-22 07:00:57Z michi $
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 const s4 abi_registers_integer_argument[] = {
56         0,  /* a0 */
57         1,  /* a1 */
58         2,  /* a2 */
59         3,  /* a3 */
60         REG_SPLIT,
61 };
62
63 const s4 abi_registers_integer_saved[] = {
64         4,  /* s0 */
65         5,  /* s1 */
66         6,  /* s2 */
67         7,  /* s3 */
68         8,  /* s4 */
69 };
70
71 const s4 abi_registers_integer_temporary[] = {
72         -1,
73 };
74
75
76 #if defined(ENABLE_SOFTFLOAT)
77 s4 nregdescfloat[] = {
78         REG_RES, REG_RES, REG_RES, REG_RES,
79         REG_RES, REG_RES, REG_RES, REG_RES,
80         REG_END
81 };
82 #else
83 /* TODO: FPA register usage conventions */
84 s4 nregdescfloat[] = {
85         REG_TMP, REG_TMP, REG_TMP, REG_TMP,
86         REG_TMP, REG_TMP, REG_RES, REG_RES,
87         REG_END
88 };
89 #endif /* defined(ENABLE_SOFTFLOAT) */
90
91 const s4 abi_registers_float_argument[] = {
92         -1,
93 };
94
95 const s4 abi_registers_float_saved[] = {
96         -1,
97 };
98
99 const s4 abi_registers_float_temporary[] = {
100 #if defined(ENABLE_SOFTFLOAT)
101         -1,
102 #else
103         0,  /* ft0 */
104         1,  /* ft1 */
105         2,  /* ft2 */
106         3,  /* ft3 */
107         4,  /* ft4 */
108         5,  /* ft5 */
109 #endif
110 };
111
112
113 /* md_param_alloc **************************************************************
114
115    Allocate Arguments to Stackslots according the Calling Conventions
116
117    --- in:
118    md->paramcount:           Number of arguments for this method
119    md->paramtypes[].type:    Argument types
120
121    --- out:
122    md->params[].inmemory:    Argument spilled on stack
123    md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
124    md->memuse:               Stackslots needed for argument spilling
125    md->argintreguse:         max number of integer arguments used
126    md->argfltreguse:         max number of float arguments used
127
128 *******************************************************************************/
129
130 void md_param_alloc(methoddesc *md)
131 {
132         paramdesc *pd;
133         s4         i;
134         s4         reguse;
135         s4         stacksize;
136
137         /* set default values */
138
139         reguse    = 0;
140         stacksize = 0;
141
142         /* get params field of methoddesc */
143
144         pd = md->params;
145
146         for (i = 0; i < md->paramcount; i++, pd++) {
147                 switch (md->paramtypes[i].type) {
148                 case TYPE_INT:
149                 case TYPE_ADR:
150                 case TYPE_FLT:
151                         if (reguse < INT_ARG_CNT) {
152                                 pd->inmemory = false;
153                                 pd->regoff   = abi_registers_integer_argument[reguse];
154                                 reguse++;
155                         }
156                         else {
157                                 pd->inmemory = true;
158                                 pd->regoff   = stacksize;
159                                 stacksize++;
160                         }
161                         break;
162
163                 case TYPE_LNG:
164                 case TYPE_DBL:
165                         /* interally we use the EABI */
166
167                         ALIGN_2(reguse);
168
169                         if (reguse < INT_ARG_CNT) {
170                                 pd->inmemory = false;
171 #if defined(__ARMEL__)
172                                 pd->regoff   =
173                                         PACK_REGS(abi_registers_integer_argument[reguse],
174                                                           abi_registers_integer_argument[reguse + 1]);
175 #else
176                                 pd->regoff   =
177                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
178                                                           abi_registers_integer_argument[reguse]);
179 #endif
180                                 reguse += 2;
181                         }
182                         else {
183
184                                 ALIGN_2(stacksize);
185
186                                 pd->inmemory  = true;
187                                 pd->regoff    = stacksize;
188                                 stacksize    += 2;
189                         }
190                         break;
191                 }
192         }
193
194         /* Since R0/R1 (==A0/A1) are used for passing return values, this
195            argument register usage has to be regarded, too. */
196
197         if (md->returntype.type != TYPE_VOID) {
198                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
199                         if (reguse < 1)
200                                 reguse = 1;
201                 }
202                 else {
203                         if (reguse < 2)
204                                 reguse = 2;
205                 }
206         }
207
208         /* fill register and stack usage */
209
210         md->argintreguse = reguse;
211         md->argfltreguse = 0;
212         md->memuse       = stacksize;
213 }
214
215
216 /* md_param_alloc_native *******************************************************
217
218    Pre-allocate arguments according the native ABI.
219
220 *******************************************************************************/
221
222 void md_param_alloc_native(methoddesc *md)
223 {
224         paramdesc *pd;
225         s4         i;
226         s4         reguse;
227         s4         stacksize;
228
229         /* set default values */
230
231         reguse    = 0;
232         stacksize = 0;
233
234         /* get params field of methoddesc */
235
236         pd = md->params;
237
238         for (i = 0; i < md->paramcount; i++, pd++) {
239                 switch (md->paramtypes[i].type) {
240                 case TYPE_INT:
241                 case TYPE_ADR:
242                 case TYPE_FLT:
243                         if (reguse < INT_ARG_CNT) {
244                                 pd->inmemory = false;
245                                 pd->regoff   = abi_registers_integer_argument[reguse];
246                                 reguse++;
247                         }
248                         else {
249                                 pd->inmemory = true;
250                                 pd->regoff   = stacksize;
251                                 stacksize++;
252                         }
253                         break;
254
255                 case TYPE_LNG:
256                 case TYPE_DBL:
257                         if (reguse < (INT_ARG_CNT - 1)) {
258 #if defined(__ARM_EABI__)
259                                 ALIGN_2(reguse);
260 #endif
261                                 pd->inmemory = false;
262 #if defined(__ARMEL__)
263                                 pd->regoff   =
264                                         PACK_REGS(abi_registers_integer_argument[reguse],
265                                                           abi_registers_integer_argument[reguse + 1]);
266 #else
267                                 pd->regoff   =
268                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
269                                                           abi_registers_integer_argument[reguse]);
270 #endif
271                                 reguse += 2;
272                         }
273 #if !defined(__ARM_EABI__)
274                         else if (reguse < INT_ARG_CNT) {
275                                 pd->inmemory = false;
276 # if defined(__ARMEL__)
277                                 pd->regoff   =
278                                         PACK_REGS(abi_registers_integer_argument[reguse],
279                                                           abi_registers_integer_argument[INT_ARG_CNT]);
280 # else
281                                 pd->regoff   =
282                                         PACK_REGS(abi_registers_integer_argument[INT_ARG_CNT],
283                                                           abi_registers_integer_argument[reguse]);
284 # endif
285                                 reguse++;
286                                 stacksize++;
287                         }
288 #endif
289                         else {
290 #if defined(__ARM_EABI__)
291                                 ALIGN_2(stacksize);
292 #endif
293                                 pd->inmemory  = true;
294                                 pd->regoff    = stacksize;
295                                 reguse        = INT_ARG_CNT;
296                                 stacksize    += 2;
297                         }
298                         break;
299                 }
300         }
301
302         /* Since R0/R1 (==A0/A1) are used for passing return values, this
303            argument register usage has to be regarded, too. */
304
305         if (md->returntype.type != TYPE_VOID) {
306                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
307                         if (reguse < 1)
308                                 reguse = 1;
309                 }
310                 else {
311                         if (reguse < 2)
312                                 reguse = 2;
313                 }
314         }
315
316         /* fill register and stack usage */
317
318         md->argintreguse = reguse;
319         md->argfltreguse = 0;
320         md->memuse       = stacksize;
321 }
322
323
324 /* md_return_alloc *************************************************************
325
326    Precolor the Java Stackelement containing the Return Value, if possible.
327
328    --- in
329    m:                       Methodinfo of current method
330    return_type:             Return Type of the Method (TYPE_INT.. TYPE_ADR)
331                             TYPE_VOID is not allowed!
332    stackslot:               Java Stackslot to contain the Return Value
333
334    --- out
335    if precoloring was possible:
336    VAR(stackslot->varnum)->flags = PREALLOC
337    VAR(stackslot->varnum)->vv.regoff = [REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
338    rd->arg[flt|int]reguse   set to a value according the register usage
339
340 *******************************************************************************/
341
342 void md_return_alloc(jitdata *jd, stackptr stackslot)
343 {
344         methodinfo   *m;
345         registerdata *rd;
346         methoddesc   *md;
347
348         /* get required compiler data */
349
350         m  = jd->m;
351         rd = jd->rd;
352
353         md = m->parseddesc;
354
355         /* In Leafmethods Local Vars holding parameters are precolored to
356            their argument register -> so leafmethods with paramcount > 0
357            could already use R0 == a00! */
358
359         if (!jd->isleafmethod || (md->paramcount == 0)) {
360                 /* Only precolor the stackslot, if it is not a SAVEDVAR <->
361                    has not to survive method invokations. */
362
363                 if (!(stackslot->flags & SAVEDVAR)) {
364 #if !defined(ENABLE_SOFTFLOAT)
365                         /* Stackelements containing float or double values
366                            (TYPE_FLT | TYPE_DBL) cannot be precolored, because we
367                            use integer register to pass return values. (floats:
368                            R0, doubles: R0/R1) */
369
370                         if (!IS_FLT_DBL_TYPE(md->returntype.type)) {
371 #endif
372
373                                 VAR(stackslot->varnum)->flags = PREALLOC;
374
375                                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
376                                         if (rd->argintreguse < 1)
377                                                 rd->argintreguse = 1;
378
379                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
380                                 }
381                                 else {
382                                         if (rd->argintreguse < 2)
383                                                 rd->argintreguse = 2;
384
385                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
386                                 }
387
388 #if !defined(ENABLE_SOFTFLOAT)
389                         }
390 #endif
391                 }
392         }
393 }
394
395
396 /*
397  * These are local overrides for various environment variables in Emacs.
398  * Please do not remove this and leave it at the end of the file, where
399  * Emacs will automagically detect them.
400  * ---------------------------------------------------------------------
401  * Local variables:
402  * mode: c
403  * indent-tabs-mode: t
404  * c-basic-offset: 4
405  * tab-width: 4
406  * End:
407  */