1 /* src/vm/jit/mips/md-abi.c - functions for MIPS ABI
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
8 This file is part of CACAO.
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.
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.
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
25 $Id: md-abi.c 8123 2007-06-20 23:50:55Z michi $
36 #include "vm/jit/mips/md-abi.h"
38 #include "mm/memory.h"
40 #include "vm/global.h"
42 #include "vm/jit/abi.h"
44 #include "vmcore/descriptor.h"
45 #include "vmcore/method.h"
48 /* register descripton array **************************************************/
50 #if SIZEOF_VOID_P == 8
55 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
56 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
57 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
58 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
62 const char *abi_registers_integer_name[] = {
63 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
64 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
65 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
66 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
69 const s4 abi_registers_integer_argument[] = {
80 const s4 abi_registers_integer_saved[] = {
91 const s4 abi_registers_integer_temporary[] = {
100 s4 nregdescfloat[] = {
101 /* fv0, ftmp1, ftmp2, ftmp3, ft0, ft1, ft2, ft3, */
102 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
104 /* ft4, ft5, ft6, ft7, fa0, fa1, fa2, fa3, */
105 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
107 /* fa4, fa5, fa6, fa7, ft8, ft9, ft10, ft11, */
108 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
110 /* fs0, ft12, fs1, ft13, fs2, ft14, fs3 ft15 */
111 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
116 const s4 abi_registers_float_argument[] = {
127 const s4 abi_registers_float_saved[] = {
134 const s4 abi_registers_float_temporary[] = {
153 #else /* SIZEOF_VOID_P == 8 */
158 /* zero, itmp1, v0, v1, a0, a1, a2, a3, */
159 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
161 /* t0, t1, t2, t3, t4, t5, t6, t7, */
162 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
164 /* s0, s1, s2, s3, s4, s5, s6, s7, */
165 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
167 /*itmp2, itmp3, k0(sys), k1(sys), gp, sp, pv, ra */
168 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
173 const char *abi_registers_integer_name[] = {
174 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
175 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
176 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
177 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
180 const s4 abi_registers_integer_argument[] = {
187 const s4 abi_registers_integer_saved[] = {
198 const s4 abi_registers_integer_temporary[] = {
210 #if !defined(ENABLE_SOFT_FLOAT)
212 s4 nregdescfloat[] = {
213 /* fv0, ftmp1, ftmp2, ftmp3, */
214 REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
216 /* ft0, ft1, fa0, fa1, */
217 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
219 /* ft2, ft3, fs0, fs1, */
220 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
222 /* fs2, fs3, fs4, fs5 */
223 REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
228 const s4 abi_registers_float_argument[] = {
233 const s4 abi_registers_float_saved[] = {
242 const s4 abi_registers_float_temporary[] = {
250 #else /* !defined(ENABLE_SOFT_FLOAT) */
252 s4 nregdescfloat[] = {
256 #endif /* !defined(ENABLE_SOFT_FLOAT) */
258 #endif /* SIZEOF_VOID_P == 8 */
261 /* md_param_alloc **************************************************************
263 Pre-allocate arguments according to the internal JIT ABI.
265 *******************************************************************************/
267 void md_param_alloc(methoddesc *md)
274 /* set default values */
279 /* get params field of methoddesc */
283 #if SIZEOF_VOID_P == 8
285 for (i = 0; i < md->paramcount; i++, pd++) {
286 switch (md->paramtypes[i].type) {
290 if (reguse < INT_ARG_CNT) {
291 pd->inmemory = false;
292 pd->regoff = abi_registers_integer_argument[reguse];
294 md->argintreguse = reguse;
298 pd->regoff = stacksize * 8;
305 if (reguse < FLT_ARG_CNT) {
306 pd->inmemory = false;
307 pd->regoff = abi_registers_float_argument[reguse];
309 md->argfltreguse = reguse;
313 pd->regoff = stacksize * 8;
319 /* register type is the same as java type */
321 pd->type = md->paramtypes[i].type;
324 #else /* SIZEOF_VOID_P == 8 */
326 # if !defined(ENABLE_SOFT_FLOAT)
328 /* Set stacksize to 2, as 4 32-bit argument registers can be
330 /* XXX maybe this should be done in stack.c? */
334 for (i = 0; i < md->paramcount; i++, pd++) {
335 switch (md->paramtypes[i].type) {
338 if (reguse < INT_ARG_CNT) {
339 pd->inmemory = false;
341 pd->regoff = abi_registers_integer_argument[reguse];
343 md->argintreguse = reguse;
347 pd->index = stacksize;
348 pd->regoff = stacksize * 8;
356 if (reguse < INT_ARG_CNT) {
357 pd->inmemory = false;
358 # if WORDS_BIGENDIAN == 1
359 pd->index = PACK_REGS(reguse + 1, reguse);
361 PACK_REGS(abi_registers_integer_argument[reguse + 1],
362 abi_registers_integer_argument[reguse]);
364 pd->index = PACK_REGS(reguse, reguse + 1);
366 PACK_REGS(abi_registers_integer_argument[reguse],
367 abi_registers_integer_argument[reguse + 1]);
370 md->argintreguse = reguse;
374 pd->index = stacksize;
375 pd->regoff = stacksize * 8;
382 if (reguse < FLT_ARG_CNT) {
383 pd->inmemory = false;
385 pd->regoff = abi_registers_float_argument[reguse];
387 md->argfltreguse = reguse;
391 pd->index = stacksize;
392 pd->regoff = stacksize * 8;
398 /* register type is the same as java type */
400 pd->type = md->paramtypes[i].type;
403 # else /* !defined(ENABLE_SOFT_FLOAT) */
404 # error never actually tested!
406 for (i = 0; i < md->paramcount; i++, pd++) {
407 switch (md->paramtypes[i].type) {
413 if (reguse < INT_ARG_CNT) {
414 pd->inmemory = false;
415 pd->regoff = abi_registers_integer_argument[reguse];
417 md->argintreguse = reguse;
421 pd->regoff = stacksize * 8;
430 if (reguse < INT_ARG_CNT) {
431 pd->inmemory = false;
432 # if WORDS_BIGENDIAN == 1
434 PACK_REGS(abi_registers_integer_argument[reguse + 1],
435 abi_registers_integer_argument[reguse]);
438 PACK_REGS(abi_registers_integer_argument[reguse],
439 abi_registers_integer_argument[reguse + 1]);
442 md->argintreguse = reguse;
446 pd->regoff = stacksize * 8;
453 # endif /* !defined(ENABLE_SOFT_FLOAT) */
454 #endif /* SIZEOF_VOID_P == 8 */
456 /* fill register and stack usage */
458 md->memuse = stacksize;
462 /* md_param_alloc_native *******************************************************
464 Pre-allocate arguments according the native ABI.
466 *******************************************************************************/
468 void md_param_alloc_native(methoddesc *md)
470 #if SIZEOF_VOID_P == 8
472 /* On MIPS n64 we use the same ABI for JIT method calls as for
473 native method calls. */
477 #else /* SIZEOF_VOID_P == 8 */
483 # if !defined(ENABLE_SOFT_FLOAT)
488 /* set default values */
492 # if !defined(ENABLE_SOFT_FLOAT)
496 /* get params field of methoddesc */
500 # if !defined(ENABLE_SOFT_FLOAT)
502 for (i = 0; i < md->paramcount; i++, pd++) {
503 t = md->paramtypes[i].type;
505 if (IS_FLT_DBL_TYPE(t) &&
507 ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
508 if (IS_2_WORD_TYPE(t)) {
510 pd->regoff = abi_registers_float_argument[reguse];
516 pd->regoff = abi_registers_float_argument[reguse];
520 md->argfltreguse = reguse;
524 if (IS_2_WORD_TYPE(t)) {
528 if (reguse < INT_ARG_CNT) {
529 pd->inmemory = false;
530 # if WORDS_BIGENDIAN == 1
532 PACK_REGS(abi_registers_integer_argument[reguse + 1],
533 abi_registers_integer_argument[reguse]);
536 PACK_REGS(abi_registers_integer_argument[reguse],
537 abi_registers_integer_argument[reguse + 1]);
540 md->argintreguse = reguse;
546 pd->regoff = stacksize * 4;
553 if (reguse < INT_ARG_CNT) {
554 pd->inmemory = false;
555 pd->regoff = abi_registers_integer_argument[reguse];
557 md->argintreguse = reguse;
561 pd->regoff = stacksize * 4;
568 # else /* !defined(ENABLE_SOFT_FLOAT) */
569 # error never actually tested!
571 for (i = 0; i < md->paramcount; i++, pd++) {
572 switch (md->paramtypes[i].type) {
578 if (i < INT_ARG_CNT) {
579 pd->inmemory = false;
580 pd->regoff = abi_registers_integer_argument[reguse];
582 md->argintreguse = reguse;
586 pd->regoff = stacksize * 4;
594 if (i < INT_ARG_CNT) {
595 pd->inmemory = false;
596 # if WORDS_BIGENDIAN == 1
598 PACK_REGS(abi_registers_integer_argument[reguse + 1],
599 abi_registers_integer_argument[reguse]);
602 PACK_REGS(abi_registers_integer_argument[reguse],
603 abi_registers_integer_argument[reguse + 1]);
606 md->argintreguse = reguse;
610 pd->regoff = stacksize * 4;
617 # endif /* !defined(ENABLE_SOFT_FLOAT) */
619 /* fill register and stack usage */
621 md->memuse = stacksize;
623 #endif /* SIZEOF_VOID_P == 8 */
627 /* md_return_alloc *************************************************************
629 Precolor the Java Stackelement containing the Return Value. Since
630 mips has a dedicated return register (not an reused arg or reserved
631 reg), this is striaghtforward possible, as long, as this
632 stackelement does not have to survive a method invokation
636 jd: jitdata of the current method
637 stackslot: Java Stackslot to contain the Return Value
640 if precoloring was possible:
641 VAR(stackslot->varnum)->flags = PREALLOC
642 ->regoff = [REG_RESULT|REG_FRESULT]
644 *******************************************************************************/
646 void md_return_alloc(jitdata *jd, stackptr stackslot)
651 /* get required compiler data */
657 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
658 not to survive method invokations. */
660 if (!(stackslot->flags & SAVEDVAR)) {
661 VAR(stackslot->varnum)->flags = PREALLOC;
663 if (IS_INT_LNG_TYPE(md->returntype.type)) {
664 #if SIZEOF_VOID_P == 4
665 if (IS_2_WORD_TYPE(md->returntype.type))
666 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
669 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
672 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
678 * These are local overrides for various environment variables in Emacs.
679 * Please do not remove this and leave it at the end of the file, where
680 * Emacs will automagically detect them.
681 * ---------------------------------------------------------------------
684 * indent-tabs-mode: t