Merged revisions 7693-7700 via svnmerge from
[cacao.git] / src / vm / jit / mips / md-abi.c
1 /* src/vm/jit/mips/md-abi.c - functions for MIPS 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 7699 2007-04-13 10:42:05Z twisti $
26
27 */
28
29
30 #include "config.h"
31 #include "vm/types.h"
32
33 #include "vm/jit/mips/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 #if SIZEOF_VOID_P == 8
45
46 /* MIPS64 */
47
48 s4 nregdescint[] = {
49         REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
50         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
51         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
52         REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
53         REG_END
54 };
55
56 const char *abi_registers_integer_name[] = {
57         "zero",  "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3",
58         "a4",    "a5",    "a6",    "a7",    "t0",    "t1",    "t2",    "t3",
59         "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7",
60         "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra"
61 };
62
63
64 s4 nregdescfloat[] = {
65         /*  fv0,   ftmp1,   ftmp2,   ftmp3,     ft0,     ft1,     ft2,     ft3,   */
66         REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
67
68         /*  ft4,     ft5,     ft6,     ft7,     fa0,     fa1,     fa2,     fa3,   */
69         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
70
71         /*  fa4,     fa5,     fa6,     fa7,     ft8,     ft9,    ft10,    ft11,   */
72         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
73
74         /*  fs0,    ft12,     fs1,    ft13,     fs2,    ft14,     fs3     ft15    */
75         REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
76
77         REG_END
78 };
79
80 #else /* SIZEOF_VOID_P == 8 */
81
82 /* MIPS32 */
83
84 s4 nregdescint[] = {
85         /* zero,   itmp1,      v0,      v1,      a0,      a1,      a2,      a3,   */
86         REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
87
88         /*   t0,      t1,      t2,      t3,      t4,      t5,      t6,      t7,   */
89         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
90
91         /*   s0,      s1,      s2,      s3,      s4,      s5,      s6,      s7,   */
92         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
93
94         /*itmp2,   itmp3, k0(sys), k1(sys),      gp,      sp,      pv,      ra    */
95         REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
96
97         REG_END
98 };
99
100 const char *abi_registers_integer_name[] = {
101         "zero",  "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3",
102         "a4",    "a5",    "a6",    "a7",    "t0",    "t1",    "t2",    "t3",
103         "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7",
104         "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra"
105 };
106
107
108 #if !defined(ENABLE_SOFT_FLOAT)
109
110 s4 nregdescfloat[] = {
111         /*  fv0,            ftmp1,            ftmp2,            ftmp3,            */
112         REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
113
114         /*  ft0,              ft1,              fa0,              fa1,            */
115         REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
116
117         /*  ft2,              ft3,              fs0,              fs1,            */
118         REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
119
120         /*  fs2,              fs3,              fs4,              fs5             */
121         REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
122
123         REG_END
124 };
125
126 #else /* !defined(ENABLE_SOFT_FLOAT) */
127
128 s4 nregdescfloat[] = {
129         REG_END
130 };
131
132 #endif /* !defined(ENABLE_SOFT_FLOAT) */
133
134 #endif /* SIZEOF_VOID_P == 8 */
135
136
137 /* md_param_alloc **************************************************************
138
139    Pre-allocate arguments according to the internal JIT ABI.
140
141 *******************************************************************************/
142
143 void md_param_alloc(methoddesc *md)
144 {
145         paramdesc *pd;
146         s4         i;
147         s4         reguse;
148         s4         stacksize;
149 #if SIZEOF_VOID_P == 4 && !defined(ENABLE_SOFT_FLOAT)
150         s4         t;
151         bool       a0_is_float;
152 #endif
153
154         /* set default values */
155
156         reguse = 0;
157         stacksize = 0;
158 #if SIZEOF_VOID_P == 4 && !defined(ENABLE_SOFT_FLOAT)
159         a0_is_float = false;
160 #endif
161
162         /* get params field of methoddesc */
163
164         pd = md->params;
165
166         for (i = 0; i < md->paramcount; i++, pd++) {
167 #if SIZEOF_VOID_P == 8
168
169                 switch (md->paramtypes[i].type) {
170                 case TYPE_INT:
171                 case TYPE_ADR:
172                 case TYPE_LNG:
173                         if (i < INT_ARG_CNT) {
174                                 pd->inmemory = false;
175                                 pd->regoff   = reguse;
176                                 reguse++;
177                                 md->argintreguse = reguse;
178                         }
179                         else {
180                                 pd->inmemory = true;
181                                 pd->regoff   = stacksize;
182                                 stacksize++;
183                         }
184                         break;
185                 case TYPE_FLT:
186                 case TYPE_DBL:
187                         if (i < FLT_ARG_CNT) {
188                                 pd->inmemory = false;
189                                 pd->regoff   = reguse;
190                                 reguse++;
191                                 md->argfltreguse = reguse;
192                         }
193                         else {
194                                 pd->inmemory = true;
195                                 pd->regoff   = stacksize;
196                                 stacksize++;
197                         }
198                         break;
199                 }
200
201                 /* register type is the same as java type */
202
203                 pd->type = md->paramtypes[i].type;
204
205 #else /* SIZEOF_VOID_P == 8 */
206
207 #if !defined(ENABLE_SOFT_FLOAT)
208
209 #define ALIGN_2_WORD(s)    ((s) & 1) ? ++(s) : (s)
210
211                 t = md->paramtypes[i].type;
212
213                 if (IS_FLT_DBL_TYPE(t) &&
214                         ((i == 0) ||
215                          ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
216                         if (IS_2_WORD_TYPE(t)) {
217                                 pd->type = TYPE_DBL;
218                                 pd->regoff = reguse;
219                                 reguse++;
220                                 stacksize += 2;
221                         }
222                         else {
223                                 pd->type = TYPE_FLT;
224                                 pd->regoff = reguse;
225                                 reguse++;
226                                 stacksize++;
227                         }
228                         md->argfltreguse = reguse;
229                         a0_is_float = true;
230                 }
231                 else {
232                         if (IS_2_WORD_TYPE(t)) {
233                                 ALIGN_2_WORD(reguse);
234                                 pd->type = TYPE_LNG;
235
236                                 if (reguse < INT_ARG_CNT) {
237                                         pd->inmemory = false;
238 # if WORDS_BIGENDIAN == 1
239                                         pd->regoff   = PACK_REGS(reguse + 1, reguse);
240 # else
241                                         pd->regoff   = PACK_REGS(reguse, reguse + 1);
242 # endif
243                                         reguse += 2;
244                                         md->argintreguse = reguse;
245                                 }
246                                 else {
247                                         pd->inmemory = true;
248                                         pd->regoff   = ALIGN_2_WORD(stacksize);
249                                 }
250                                 stacksize += 2;
251                         }
252                         else {
253                                 pd->type = TYPE_INT;
254
255                                 if (reguse < INT_ARG_CNT) {
256                                         pd->inmemory = false;
257                                         pd->regoff = reguse;
258                                         reguse++;
259                                         md->argintreguse = reguse;
260                                 }
261                                 else {
262                                         pd->inmemory = true;
263                                         pd->regoff = stacksize;
264                                 }
265                                 stacksize++;
266                         }
267                 }
268
269 #else /* !defined(ENABLE_SOFT_FLOAT) */
270 #error never actually tested!
271
272                 switch (md->paramtypes[i].type) {
273                 case TYPE_INT:
274                 case TYPE_ADR:
275                 case TYPE_FLT:
276                         pd->type = TYPE_INT;
277
278                         if (i < INT_ARG_CNT) {
279                                 pd->inmemory = false;
280                                 pd->regoff   = reguse;
281                                 reguse++;
282                                 md->argintreguse = reguse;
283                         }
284                         else {
285                                 pd->inmemory = true;
286                                 pd->regoff   = stacksize;
287                         }
288                         stacksize++;
289                         break;
290                 case TYPE_LNG:
291                 case TYPE_DBL:
292                         pd->type = TYPE_LNG;
293
294                         if (i < INT_ARG_CNT) {
295                                 pd->inmemory = false;
296 #if WORDS_BIGENDIAN == 1
297                                 pd->regoff   = PACK_REGS(reguse + 1, reguse);
298 #else
299                                 pd->regoff   = PACK_REGS(reguse, reguse + 1);
300 #endif
301                                 reguse += 2;
302                                 md->argintreguse = reguse;
303                         }
304                         else {
305                                 pd->inmemory = true;
306                                 pd->regoff   = stacksize;
307                         }
308                         stacksize += 2;
309                         break;
310                 }
311
312
313 #endif /* !defined(ENABLE_SOFT_FLOAT) */
314
315 #endif /* SIZEOF_VOID_P == 8 */
316         }
317
318         /* fill register and stack usage */
319
320         md->memuse = stacksize;
321 }
322
323
324 /* md_param_alloc_native *******************************************************
325
326    Pre-allocate arguments according the native ABI.
327
328 *******************************************************************************/
329
330 void md_param_alloc_native(methoddesc *md)
331 {
332         /* On MIPS we use the same ABI for JIT method calls as for native
333            method calls. */
334
335         md_param_alloc(md);
336 }
337
338
339 /* md_return_alloc *************************************************************
340
341    Precolor the Java Stackelement containing the Return Value. Since
342    mips has a dedicated return register (not an reused arg or reserved
343    reg), this is striaghtforward possible, as long, as this
344    stackelement does not have to survive a method invokation
345    (SAVEDVAR)
346
347    --- in
348    jd:                      jitdata of the current method
349    stackslot:               Java Stackslot to contain the Return Value
350    
351    --- out
352    if precoloring was possible:
353    VAR(stackslot->varnum)->flags       = PREALLOC
354                                      ->regoff      = [REG_RESULT|REG_FRESULT]
355
356 *******************************************************************************/
357
358 void md_return_alloc(jitdata *jd, stackptr stackslot)
359 {
360         methodinfo *m;
361         methoddesc *md;
362
363         /* get required compiler data */
364
365         m = jd->m;
366
367         md = m->parseddesc;
368
369         /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
370            not to survive method invokations. */
371
372         if (!(stackslot->flags & SAVEDVAR)) {
373                 VAR(stackslot->varnum)->flags = PREALLOC;
374
375                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
376 #if SIZEOF_VOID_P == 4
377                         if (IS_2_WORD_TYPE(md->returntype.type))
378                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
379                         else
380 #endif
381                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
382                 }
383                 else
384                         VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
385         }
386 }
387
388
389 /*
390  * These are local overrides for various environment variables in Emacs.
391  * Please do not remove this and leave it at the end of the file, where
392  * Emacs will automagically detect them.
393  * ---------------------------------------------------------------------
394  * Local variables:
395  * mode: c
396  * indent-tabs-mode: t
397  * c-basic-offset: 4
398  * tab-width: 4
399  * End:
400  */