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 8012 2007-06-05 10:14:29Z 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 (i < INT_ARG_CNT) {
285 pd->inmemory = false;
286 pd->regoff = abi_registers_integer_argument[reguse];
288 md->argintreguse = reguse;
292 pd->regoff = stacksize;
298 if (i < FLT_ARG_CNT) {
299 pd->inmemory = false;
300 pd->regoff = abi_registers_float_argument[reguse];
302 md->argfltreguse = reguse;
306 pd->regoff = stacksize;
312 /* register type is the same as java type */
314 pd->type = md->paramtypes[i].type;
317 #else /* SIZEOF_VOID_P == 8 */
319 # if !defined(ENABLE_SOFT_FLOAT)
321 /* Set stacksize to 2, as 4 32-bit argument registers can be
323 /* XXX maybe this should be done in stack.c? */
327 for (i = 0; i < md->paramcount; i++, pd++) {
328 switch (md->paramtypes[i].type) {
331 if (reguse < INT_ARG_CNT) {
332 pd->inmemory = false;
333 pd->regoff = abi_registers_integer_argument[reguse];
335 md->argintreguse = reguse;
339 pd->regoff = stacksize;
347 if (reguse < INT_ARG_CNT) {
348 pd->inmemory = false;
349 # if WORDS_BIGENDIAN == 1
351 PACK_REGS(abi_registers_integer_argument[reguse + 1],
352 abi_registers_integer_argument[reguse]);
355 PACK_REGS(abi_registers_integer_argument[reguse],
356 abi_registers_integer_argument[reguse + 1]);
359 md->argintreguse = reguse;
363 pd->regoff = stacksize;
370 if (reguse < FLT_ARG_CNT) {
371 pd->inmemory = false;
372 pd->regoff = abi_registers_float_argument[reguse];
374 md->argfltreguse = reguse;
378 pd->regoff = stacksize;
384 /* register type is the same as java type */
386 pd->type = md->paramtypes[i].type;
389 # else /* !defined(ENABLE_SOFT_FLOAT) */
390 # error never actually tested!
392 for (i = 0; i < md->paramcount; i++, pd++) {
393 switch (md->paramtypes[i].type) {
399 if (reguse < INT_ARG_CNT) {
400 pd->inmemory = false;
401 pd->regoff = abi_registers_integer_argument[reguse];
403 md->argintreguse = reguse;
407 pd->regoff = stacksize;
416 if (reguse < INT_ARG_CNT) {
417 pd->inmemory = false;
418 # if WORDS_BIGENDIAN == 1
420 PACK_REGS(abi_registers_integer_argument[reguse + 1],
421 abi_registers_integer_argument[reguse]);
424 PACK_REGS(abi_registers_integer_argument[reguse],
425 abi_registers_integer_argument[reguse + 1]);
428 md->argintreguse = reguse;
432 pd->regoff = stacksize;
439 # endif /* !defined(ENABLE_SOFT_FLOAT) */
440 #endif /* SIZEOF_VOID_P == 8 */
442 /* fill register and stack usage */
444 md->memuse = stacksize;
448 /* md_param_alloc_native *******************************************************
450 Pre-allocate arguments according the native ABI.
452 *******************************************************************************/
454 void md_param_alloc_native(methoddesc *md)
456 #if SIZEOF_VOID_P == 8
458 /* On MIPS n64 we use the same ABI for JIT method calls as for
459 native method calls. */
463 #else /* SIZEOF_VOID_P == 8 */
469 # if !defined(ENABLE_SOFT_FLOAT)
474 /* set default values */
478 # if !defined(ENABLE_SOFT_FLOAT)
482 /* get params field of methoddesc */
486 # if !defined(ENABLE_SOFT_FLOAT)
488 for (i = 0; i < md->paramcount; i++, pd++) {
489 t = md->paramtypes[i].type;
491 if (IS_FLT_DBL_TYPE(t) &&
493 ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
494 if (IS_2_WORD_TYPE(t)) {
496 pd->regoff = abi_registers_float_argument[reguse];
502 pd->regoff = abi_registers_float_argument[reguse];
506 md->argfltreguse = reguse;
510 if (IS_2_WORD_TYPE(t)) {
514 if (reguse < INT_ARG_CNT) {
515 pd->inmemory = false;
516 # if WORDS_BIGENDIAN == 1
518 PACK_REGS(abi_registers_integer_argument[reguse + 1],
519 abi_registers_integer_argument[reguse]);
522 PACK_REGS(abi_registers_integer_argument[reguse],
523 abi_registers_integer_argument[reguse + 1]);
526 md->argintreguse = reguse;
532 pd->regoff = stacksize;
539 if (reguse < INT_ARG_CNT) {
540 pd->inmemory = false;
541 pd->regoff = abi_registers_integer_argument[reguse];
543 md->argintreguse = reguse;
547 pd->regoff = stacksize;
554 # else /* !defined(ENABLE_SOFT_FLOAT) */
555 # error never actually tested!
557 for (i = 0; i < md->paramcount; i++, pd++) {
558 switch (md->paramtypes[i].type) {
564 if (i < INT_ARG_CNT) {
565 pd->inmemory = false;
566 pd->regoff = abi_registers_integer_argument[reguse];
568 md->argintreguse = reguse;
572 pd->regoff = stacksize;
580 if (i < INT_ARG_CNT) {
581 pd->inmemory = false;
582 # if WORDS_BIGENDIAN == 1
584 PACK_REGS(abi_registers_integer_argument[reguse + 1],
585 abi_registers_integer_argument[reguse]);
588 PACK_REGS(abi_registers_integer_argument[reguse],
589 abi_registers_integer_argument[reguse + 1]);
592 md->argintreguse = reguse;
596 pd->regoff = stacksize;
603 # endif /* !defined(ENABLE_SOFT_FLOAT) */
605 /* fill register and stack usage */
607 md->memuse = stacksize;
609 #endif /* SIZEOF_VOID_P == 8 */
613 /* md_return_alloc *************************************************************
615 Precolor the Java Stackelement containing the Return Value. Since
616 mips has a dedicated return register (not an reused arg or reserved
617 reg), this is striaghtforward possible, as long, as this
618 stackelement does not have to survive a method invokation
622 jd: jitdata of the current method
623 stackslot: Java Stackslot to contain the Return Value
626 if precoloring was possible:
627 VAR(stackslot->varnum)->flags = PREALLOC
628 ->regoff = [REG_RESULT|REG_FRESULT]
630 *******************************************************************************/
632 void md_return_alloc(jitdata *jd, stackptr stackslot)
637 /* get required compiler data */
643 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
644 not to survive method invokations. */
646 if (!(stackslot->flags & SAVEDVAR)) {
647 VAR(stackslot->varnum)->flags = PREALLOC;
649 if (IS_INT_LNG_TYPE(md->returntype.type)) {
650 #if SIZEOF_VOID_P == 4
651 if (IS_2_WORD_TYPE(md->returntype.type))
652 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
655 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
658 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
664 * These are local overrides for various environment variables in Emacs.
665 * Please do not remove this and leave it at the end of the file, where
666 * Emacs will automagically detect them.
667 * ---------------------------------------------------------------------
670 * indent-tabs-mode: t