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 8013 2007-06-05 10:19:09Z twisti $
33 #include "vm/jit/mips/md-abi.h"
35 #include "vm/global.h"
37 #include "vm/jit/abi.h"
39 #include "vmcore/descriptor.h"
42 /* register descripton array **************************************************/
44 #if SIZEOF_VOID_P == 8
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,
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"
63 const s4 abi_registers_integer_argument[] = {
74 const s4 abi_registers_integer_saved[] = {
85 const s4 abi_registers_integer_temporary[] = {
94 s4 nregdescfloat[] = {
95 /* fv0, ftmp1, ftmp2, ftmp3, ft0, ft1, ft2, ft3, */
96 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
98 /* ft4, ft5, ft6, ft7, fa0, fa1, fa2, fa3, */
99 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
101 /* fa4, fa5, fa6, fa7, ft8, ft9, ft10, ft11, */
102 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
104 /* fs0, ft12, fs1, ft13, fs2, ft14, fs3 ft15 */
105 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
110 const s4 abi_registers_float_argument[] = {
121 const s4 abi_registers_float_saved[] = {
128 const s4 abi_registers_float_temporary[] = {
147 #else /* SIZEOF_VOID_P == 8 */
152 /* zero, itmp1, v0, v1, a0, a1, a2, a3, */
153 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
155 /* t0, t1, t2, t3, t4, t5, t6, t7, */
156 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
158 /* s0, s1, s2, s3, s4, s5, s6, s7, */
159 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
161 /*itmp2, itmp3, k0(sys), k1(sys), gp, sp, pv, ra */
162 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
167 const char *abi_registers_integer_name[] = {
168 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
169 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
170 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
171 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
174 const s4 abi_registers_integer_argument[] = {
181 const s4 abi_registers_integer_saved[] = {
192 const s4 abi_registers_integer_temporary[] = {
204 #if !defined(ENABLE_SOFT_FLOAT)
206 s4 nregdescfloat[] = {
207 /* fv0, ftmp1, ftmp2, ftmp3, */
208 REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
210 /* ft0, ft1, fa0, fa1, */
211 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
213 /* ft2, ft3, fs0, fs1, */
214 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
216 /* fs2, fs3, fs4, fs5 */
217 REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
222 const s4 abi_registers_float_argument[] = {
227 const s4 abi_registers_float_saved[] = {
236 const s4 abi_registers_float_temporary[] = {
244 #else /* !defined(ENABLE_SOFT_FLOAT) */
246 s4 nregdescfloat[] = {
250 #endif /* !defined(ENABLE_SOFT_FLOAT) */
252 #endif /* SIZEOF_VOID_P == 8 */
255 /* md_param_alloc **************************************************************
257 Pre-allocate arguments according to the internal JIT ABI.
259 *******************************************************************************/
261 void md_param_alloc(methoddesc *md)
268 /* set default values */
273 /* get params field of methoddesc */
277 #if SIZEOF_VOID_P == 8
279 for (i = 0; i < md->paramcount; i++, pd++) {
280 switch (md->paramtypes[i].type) {
284 if (reguse < INT_ARG_CNT) {
285 pd->inmemory = false;
286 pd->regoff = abi_registers_integer_argument[reguse];
288 md->argintreguse = reguse;
292 pd->regoff = stacksize;
299 if (reguse < FLT_ARG_CNT) {
300 pd->inmemory = false;
301 pd->regoff = abi_registers_float_argument[reguse];
303 md->argfltreguse = reguse;
307 pd->regoff = stacksize;
313 /* register type is the same as java type */
315 pd->type = md->paramtypes[i].type;
318 #else /* SIZEOF_VOID_P == 8 */
320 # if !defined(ENABLE_SOFT_FLOAT)
322 /* Set stacksize to 2, as 4 32-bit argument registers can be
324 /* XXX maybe this should be done in stack.c? */
328 for (i = 0; i < md->paramcount; i++, pd++) {
329 switch (md->paramtypes[i].type) {
332 if (reguse < INT_ARG_CNT) {
333 pd->inmemory = false;
334 pd->regoff = abi_registers_integer_argument[reguse];
336 md->argintreguse = reguse;
340 pd->regoff = stacksize;
348 if (reguse < INT_ARG_CNT) {
349 pd->inmemory = false;
350 # if WORDS_BIGENDIAN == 1
352 PACK_REGS(abi_registers_integer_argument[reguse + 1],
353 abi_registers_integer_argument[reguse]);
356 PACK_REGS(abi_registers_integer_argument[reguse],
357 abi_registers_integer_argument[reguse + 1]);
360 md->argintreguse = reguse;
364 pd->regoff = stacksize;
371 if (reguse < FLT_ARG_CNT) {
372 pd->inmemory = false;
373 pd->regoff = abi_registers_float_argument[reguse];
375 md->argfltreguse = reguse;
379 pd->regoff = stacksize;
385 /* register type is the same as java type */
387 pd->type = md->paramtypes[i].type;
390 # else /* !defined(ENABLE_SOFT_FLOAT) */
391 # error never actually tested!
393 for (i = 0; i < md->paramcount; i++, pd++) {
394 switch (md->paramtypes[i].type) {
400 if (reguse < INT_ARG_CNT) {
401 pd->inmemory = false;
402 pd->regoff = abi_registers_integer_argument[reguse];
404 md->argintreguse = reguse;
408 pd->regoff = stacksize;
417 if (reguse < INT_ARG_CNT) {
418 pd->inmemory = false;
419 # if WORDS_BIGENDIAN == 1
421 PACK_REGS(abi_registers_integer_argument[reguse + 1],
422 abi_registers_integer_argument[reguse]);
425 PACK_REGS(abi_registers_integer_argument[reguse],
426 abi_registers_integer_argument[reguse + 1]);
429 md->argintreguse = reguse;
433 pd->regoff = stacksize;
440 # endif /* !defined(ENABLE_SOFT_FLOAT) */
441 #endif /* SIZEOF_VOID_P == 8 */
443 /* fill register and stack usage */
445 md->memuse = stacksize;
449 /* md_param_alloc_native *******************************************************
451 Pre-allocate arguments according the native ABI.
453 *******************************************************************************/
455 void md_param_alloc_native(methoddesc *md)
457 #if SIZEOF_VOID_P == 8
459 /* On MIPS n64 we use the same ABI for JIT method calls as for
460 native method calls. */
464 #else /* SIZEOF_VOID_P == 8 */
470 # if !defined(ENABLE_SOFT_FLOAT)
475 /* set default values */
479 # if !defined(ENABLE_SOFT_FLOAT)
483 /* get params field of methoddesc */
487 # if !defined(ENABLE_SOFT_FLOAT)
489 for (i = 0; i < md->paramcount; i++, pd++) {
490 t = md->paramtypes[i].type;
492 if (IS_FLT_DBL_TYPE(t) &&
494 ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
495 if (IS_2_WORD_TYPE(t)) {
497 pd->regoff = abi_registers_float_argument[reguse];
503 pd->regoff = abi_registers_float_argument[reguse];
507 md->argfltreguse = reguse;
511 if (IS_2_WORD_TYPE(t)) {
515 if (reguse < INT_ARG_CNT) {
516 pd->inmemory = false;
517 # if WORDS_BIGENDIAN == 1
519 PACK_REGS(abi_registers_integer_argument[reguse + 1],
520 abi_registers_integer_argument[reguse]);
523 PACK_REGS(abi_registers_integer_argument[reguse],
524 abi_registers_integer_argument[reguse + 1]);
527 md->argintreguse = reguse;
533 pd->regoff = stacksize;
540 if (reguse < INT_ARG_CNT) {
541 pd->inmemory = false;
542 pd->regoff = abi_registers_integer_argument[reguse];
544 md->argintreguse = reguse;
548 pd->regoff = stacksize;
555 # else /* !defined(ENABLE_SOFT_FLOAT) */
556 # error never actually tested!
558 for (i = 0; i < md->paramcount; i++, pd++) {
559 switch (md->paramtypes[i].type) {
565 if (i < INT_ARG_CNT) {
566 pd->inmemory = false;
567 pd->regoff = abi_registers_integer_argument[reguse];
569 md->argintreguse = reguse;
573 pd->regoff = stacksize;
581 if (i < INT_ARG_CNT) {
582 pd->inmemory = false;
583 # if WORDS_BIGENDIAN == 1
585 PACK_REGS(abi_registers_integer_argument[reguse + 1],
586 abi_registers_integer_argument[reguse]);
589 PACK_REGS(abi_registers_integer_argument[reguse],
590 abi_registers_integer_argument[reguse + 1]);
593 md->argintreguse = reguse;
597 pd->regoff = stacksize;
604 # endif /* !defined(ENABLE_SOFT_FLOAT) */
606 /* fill register and stack usage */
608 md->memuse = stacksize;
610 #endif /* SIZEOF_VOID_P == 8 */
614 /* md_return_alloc *************************************************************
616 Precolor the Java Stackelement containing the Return Value. Since
617 mips has a dedicated return register (not an reused arg or reserved
618 reg), this is striaghtforward possible, as long, as this
619 stackelement does not have to survive a method invokation
623 jd: jitdata of the current method
624 stackslot: Java Stackslot to contain the Return Value
627 if precoloring was possible:
628 VAR(stackslot->varnum)->flags = PREALLOC
629 ->regoff = [REG_RESULT|REG_FRESULT]
631 *******************************************************************************/
633 void md_return_alloc(jitdata *jd, stackptr stackslot)
638 /* get required compiler data */
644 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
645 not to survive method invokations. */
647 if (!(stackslot->flags & SAVEDVAR)) {
648 VAR(stackslot->varnum)->flags = PREALLOC;
650 if (IS_INT_LNG_TYPE(md->returntype.type)) {
651 #if SIZEOF_VOID_P == 4
652 if (IS_2_WORD_TYPE(md->returntype.type))
653 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
656 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
659 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
665 * These are local overrides for various environment variables in Emacs.
666 * Please do not remove this and leave it at the end of the file, where
667 * Emacs will automagically detect them.
668 * ---------------------------------------------------------------------
671 * indent-tabs-mode: t