* src/vm/jit/mips/md-abi.c (regs): Renamed to
[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 7351 2007-02-13 21:32:36Z 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                         } else {
179                                 pd->inmemory = true;
180                                 pd->regoff = stacksize;
181                                 stacksize++;
182                         }
183                         break;
184                 case TYPE_FLT:
185                 case TYPE_DBL:
186                         if (i < FLT_ARG_CNT) {
187                                 pd->inmemory = false;
188                                 pd->regoff = reguse;
189                                 reguse++;
190                                 md->argfltreguse = reguse;
191                         } else {
192                                 pd->inmemory = true;
193                                 pd->regoff = stacksize;
194                                 stacksize++;
195                         }
196                         break;
197                 }
198
199                 /* register type is the same as java type */
200
201                 pd->type = md->paramtypes[i].type;
202
203 #else /* SIZEOF_VOID_P == 8 */
204
205 #if !defined(ENABLE_SOFT_FLOAT)
206
207 #define ALIGN_2_WORD(s)    ((s) & 1) ? ++(s) : (s)
208
209                 t = md->paramtypes[i].type;
210
211                 if (IS_FLT_DBL_TYPE(t) &&
212                         ((i == 0) ||
213                          ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
214                         if (IS_2_WORD_TYPE(t)) {
215                                 pd->type = TYPE_DBL;
216                                 pd->regoff = reguse;
217                                 reguse++;
218                                 stacksize += 2;
219                         }
220                         else {
221                                 pd->type = TYPE_FLT;
222                                 pd->regoff = reguse;
223                                 reguse++;
224                                 stacksize++;
225                         }
226                         md->argfltreguse = reguse;
227                         a0_is_float = true;
228                 }
229                 else {
230                         if (IS_2_WORD_TYPE(t)) {
231                                 ALIGN_2_WORD(reguse);
232                                 pd->type = TYPE_LNG;
233
234                                 if (reguse < INT_ARG_CNT) {
235                                         pd->inmemory = false;
236 # if WORDS_BIGENDIAN == 1
237                                         pd->regoff = PACK_REGS(reguse + 1, reguse);
238 # else
239                                         pd->regoff = PACK_REGS(reguse, reguse + 1);
240 # endif
241                                         reguse += 2;
242                                         md->argintreguse = reguse;
243                                 }
244                                 else {
245                                         pd->inmemory = true;
246                                         pd->regoff = ALIGN_2_WORD(stacksize);
247                                 }
248                                 stacksize += 2;
249                         }
250                         else {
251                                 pd->type = TYPE_INT;
252
253                                 if (reguse < INT_ARG_CNT) {
254                                         pd->inmemory = false;
255                                         pd->regoff = reguse;
256                                         reguse++;
257                                         md->argintreguse = reguse;
258                                 }
259                                 else {
260                                         pd->inmemory = true;
261                                         pd->regoff = stacksize;
262                                 }
263                                 stacksize++;
264                         }
265                 }
266
267 #else /* !defined(ENABLE_SOFT_FLOAT) */
268 #error never actually tested!
269
270                 switch (md->paramtypes[i].type) {
271                 case TYPE_INT:
272                 case TYPE_ADR:
273                 case TYPE_FLT:
274                         pd->type = TYPE_INT;
275
276                         if (i < INT_ARG_CNT) {
277                                 pd->inmemory = false;
278                                 pd->regoff = reguse;
279                                 reguse++;
280                                 md->argintreguse = reguse;
281                         } else {
282                                 pd->inmemory = true;
283                                 pd->regoff = stacksize;
284                         }
285                         stacksize++;
286                         break;
287                 case TYPE_LNG:
288                 case TYPE_DBL:
289                         pd->type = TYPE_LNG;
290
291                         if (i < INT_ARG_CNT) {
292                                 pd->inmemory = false;
293 #if WORDS_BIGENDIAN == 1
294                                 pd->regoff = PACK_REGS(reguse + 1, reguse);
295 #else
296                                 pd->regoff = PACK_REGS(reguse, reguse + 1);
297 #endif
298                                 reguse += 2;
299                                 md->argintreguse = reguse;
300                         } else {
301                                 pd->inmemory = true;
302                                 pd->regoff = stacksize;
303                         }
304                         stacksize += 2;
305                         break;
306                 }
307
308
309 #endif /* !defined(ENABLE_SOFT_FLOAT) */
310
311 #endif /* SIZEOF_VOID_P == 8 */
312         }
313
314         /* fill register and stack usage */
315
316         md->memuse = stacksize;
317 }
318
319
320 /* md_param_alloc_native *******************************************************
321
322    Pre-allocate arguments according the native ABI.
323
324 *******************************************************************************/
325
326 void md_param_alloc_native(methoddesc *md)
327 {
328         /* On MIPS we use the same ABI for JIT method calls as for native
329            method calls. */
330
331         md_param_alloc(md);
332 }
333
334
335 /* md_return_alloc *************************************************************
336
337    Precolor the Java Stackelement containing the Return Value. Since
338    mips has a dedicated return register (not an reused arg or reserved
339    reg), this is striaghtforward possible, as long, as this
340    stackelement does not have to survive a method invokation
341    (SAVEDVAR)
342
343    --- in
344    jd:                      jitdata of the current method
345    stackslot:               Java Stackslot to contain the Return Value
346    
347    --- out
348    if precoloring was possible:
349    VAR(stackslot->varnum)->flags       = PREALLOC
350                                      ->regoff      = [REG_RESULT|REG_FRESULT]
351
352 *******************************************************************************/
353
354 void md_return_alloc(jitdata *jd, stackptr stackslot)
355 {
356         methodinfo *m;
357         methoddesc *md;
358
359         /* get required compiler data */
360
361         m = jd->m;
362
363         md = m->parseddesc;
364
365         /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
366            not to survive method invokations. */
367
368         if (!(stackslot->flags & SAVEDVAR)) {
369                 VAR(stackslot->varnum)->flags = PREALLOC;
370
371                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
372 #if SIZEOF_VOID_P == 4
373                         if (IS_2_WORD_TYPE(md->returntype.type))
374                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
375                         else
376 #endif
377                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
378                 }
379                 else
380                         VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
381         }
382 }
383
384
385 /*
386  * These are local overrides for various environment variables in Emacs.
387  * Please do not remove this and leave it at the end of the file, where
388  * Emacs will automagically detect them.
389  * ---------------------------------------------------------------------
390  * Local variables:
391  * mode: c
392  * indent-tabs-mode: t
393  * c-basic-offset: 4
394  * tab-width: 4
395  * End:
396  */