1 /* src/vm/jit/mips/md-abi.c - functions for MIPS ABI
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #include "vm/jit/mips/md-abi.h"
35 #include "mm/memory.hpp"
37 #include "vm/descriptor.hpp"
38 #include "vm/global.h"
39 #include "vm/method.hpp"
41 #include "vm/jit/abi.h"
42 #include "vm/jit/stack.h"
45 /* register descripton array **************************************************/
47 #if SIZEOF_VOID_P == 8
52 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
53 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
54 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
55 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
59 const char *abi_registers_integer_name[] = {
60 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
61 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
62 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
63 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
66 const s4 abi_registers_integer_argument[] = {
77 const s4 abi_registers_integer_saved[] = {
88 const s4 abi_registers_integer_temporary[] = {
97 s4 nregdescfloat[] = {
98 /* fv0, ftmp1, ftmp2, ftmp3, ft0, ft1, ft2, ft3, */
99 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
101 /* ft4, ft5, ft6, ft7, fa0, fa1, fa2, fa3, */
102 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
104 /* fa4, fa5, fa6, fa7, ft8, ft9, ft10, ft11, */
105 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
107 /* fs0, ft12, fs1, ft13, fs2, ft14, fs3 ft15 */
108 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
113 const s4 abi_registers_float_argument[] = {
124 const s4 abi_registers_float_saved[] = {
131 const s4 abi_registers_float_temporary[] = {
150 #else /* SIZEOF_VOID_P == 8 */
155 /* zero, itmp1, v0, v1, a0, a1, a2, a3, */
156 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
158 /* t0, t1, t2, t3, t4, t5, t6, t7, */
159 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
161 /* s0, s1, s2, s3, s4, s5, s6, s7, */
162 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
164 /*itmp2, itmp3, k0(sys), k1(sys), gp, sp, pv, ra */
165 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
170 const char *abi_registers_integer_name[] = {
171 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
172 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
173 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
174 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
177 const s4 abi_registers_integer_argument[] = {
184 const s4 abi_registers_integer_saved[] = {
195 const s4 abi_registers_integer_temporary[] = {
207 #if !defined(ENABLE_SOFT_FLOAT)
209 s4 nregdescfloat[] = {
210 /* fv0, ftmp1, ftmp2, ftmp3, */
211 REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
213 /* ft0, ft1, fa0, fa1, */
214 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
216 /* ft2, ft3, fs0, fs1, */
217 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
219 /* fs2, fs3, fs4, fs5 */
220 REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
225 const s4 abi_registers_float_argument[] = {
230 const s4 abi_registers_float_saved[] = {
239 const s4 abi_registers_float_temporary[] = {
247 #else /* !defined(ENABLE_SOFT_FLOAT) */
249 s4 nregdescfloat[] = {
253 #endif /* !defined(ENABLE_SOFT_FLOAT) */
255 #endif /* SIZEOF_VOID_P == 8 */
258 /* md_param_alloc **************************************************************
260 Pre-allocate arguments according to the internal JIT ABI.
262 *******************************************************************************/
264 void md_param_alloc(methoddesc *md)
271 /* set default values */
276 /* get params field of methoddesc */
280 #if SIZEOF_VOID_P == 8
282 for (i = 0; i < md->paramcount; i++, pd++) {
283 switch (md->paramtypes[i].type) {
287 if (reguse < INT_ARG_CNT) {
288 pd->inmemory = false;
289 pd->regoff = abi_registers_integer_argument[reguse];
291 md->argintreguse = reguse;
295 pd->regoff = stacksize * 8;
302 if (reguse < FLT_ARG_CNT) {
303 pd->inmemory = false;
304 pd->regoff = abi_registers_float_argument[reguse];
306 md->argfltreguse = reguse;
310 pd->regoff = stacksize * 8;
316 /* register type is the same as java type */
318 pd->type = md->paramtypes[i].type;
321 #else /* SIZEOF_VOID_P == 8 */
323 # if !defined(ENABLE_SOFT_FLOAT)
325 /* Set stacksize to 2, as 4 32-bit argument registers can be
327 /* XXX maybe this should be done in stack.c? */
331 for (i = 0; i < md->paramcount; i++, pd++) {
332 switch (md->paramtypes[i].type) {
335 if (reguse < INT_ARG_CNT) {
336 pd->inmemory = false;
338 pd->regoff = abi_registers_integer_argument[reguse];
340 md->argintreguse = reguse;
344 pd->index = stacksize;
345 pd->regoff = stacksize * 8;
353 if (reguse < INT_ARG_CNT) {
354 pd->inmemory = false;
355 # if WORDS_BIGENDIAN == 1
356 pd->index = PACK_REGS(reguse + 1, reguse);
358 PACK_REGS(abi_registers_integer_argument[reguse + 1],
359 abi_registers_integer_argument[reguse]);
361 pd->index = PACK_REGS(reguse, reguse + 1);
363 PACK_REGS(abi_registers_integer_argument[reguse],
364 abi_registers_integer_argument[reguse + 1]);
367 md->argintreguse = reguse;
371 pd->index = stacksize;
372 pd->regoff = stacksize * 8;
379 if (reguse < FLT_ARG_CNT) {
380 pd->inmemory = false;
382 pd->regoff = abi_registers_float_argument[reguse];
384 md->argfltreguse = reguse;
388 pd->index = stacksize;
389 pd->regoff = stacksize * 8;
395 /* register type is the same as java type */
397 pd->type = md->paramtypes[i].type;
400 # else /* !defined(ENABLE_SOFT_FLOAT) */
401 # error never actually tested!
403 for (i = 0; i < md->paramcount; i++, pd++) {
404 switch (md->paramtypes[i].type) {
410 if (reguse < INT_ARG_CNT) {
411 pd->inmemory = false;
412 pd->regoff = abi_registers_integer_argument[reguse];
414 md->argintreguse = reguse;
418 pd->regoff = stacksize * 8;
427 if (reguse < INT_ARG_CNT) {
428 pd->inmemory = false;
429 # if WORDS_BIGENDIAN == 1
431 PACK_REGS(abi_registers_integer_argument[reguse + 1],
432 abi_registers_integer_argument[reguse]);
435 PACK_REGS(abi_registers_integer_argument[reguse],
436 abi_registers_integer_argument[reguse + 1]);
439 md->argintreguse = reguse;
443 pd->regoff = stacksize * 8;
450 # endif /* !defined(ENABLE_SOFT_FLOAT) */
451 #endif /* SIZEOF_VOID_P == 8 */
453 /* fill register and stack usage */
455 md->memuse = stacksize;
459 /* md_param_alloc_native *******************************************************
461 Pre-allocate arguments according the native ABI.
463 *******************************************************************************/
465 void md_param_alloc_native(methoddesc *md)
467 #if SIZEOF_VOID_P == 8
469 /* On MIPS n64 we use the same ABI for JIT method calls as for
470 native method calls. */
474 #else /* SIZEOF_VOID_P == 8 */
480 # if !defined(ENABLE_SOFT_FLOAT)
485 /* set default values */
489 # if !defined(ENABLE_SOFT_FLOAT)
493 /* get params field of methoddesc */
497 # if !defined(ENABLE_SOFT_FLOAT)
499 for (i = 0; i < md->paramcount; i++, pd++) {
500 t = md->paramtypes[i].type;
502 if (IS_FLT_DBL_TYPE(t) &&
504 ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
505 if (IS_2_WORD_TYPE(t)) {
507 pd->regoff = abi_registers_float_argument[reguse];
513 pd->regoff = abi_registers_float_argument[reguse];
517 md->argfltreguse = reguse;
521 if (IS_2_WORD_TYPE(t)) {
525 if (reguse < INT_ARG_CNT) {
526 pd->inmemory = false;
527 # if WORDS_BIGENDIAN == 1
529 PACK_REGS(abi_registers_integer_argument[reguse + 1],
530 abi_registers_integer_argument[reguse]);
533 PACK_REGS(abi_registers_integer_argument[reguse],
534 abi_registers_integer_argument[reguse + 1]);
537 md->argintreguse = reguse;
543 pd->regoff = stacksize * 4;
550 if (reguse < INT_ARG_CNT) {
551 pd->inmemory = false;
552 pd->regoff = abi_registers_integer_argument[reguse];
554 md->argintreguse = reguse;
558 pd->regoff = stacksize * 4;
565 # else /* !defined(ENABLE_SOFT_FLOAT) */
566 # error never actually tested!
568 for (i = 0; i < md->paramcount; i++, pd++) {
569 switch (md->paramtypes[i].type) {
575 if (i < INT_ARG_CNT) {
576 pd->inmemory = false;
577 pd->regoff = abi_registers_integer_argument[reguse];
579 md->argintreguse = reguse;
583 pd->regoff = stacksize * 4;
591 if (i < INT_ARG_CNT) {
592 pd->inmemory = false;
593 # if WORDS_BIGENDIAN == 1
595 PACK_REGS(abi_registers_integer_argument[reguse + 1],
596 abi_registers_integer_argument[reguse]);
599 PACK_REGS(abi_registers_integer_argument[reguse],
600 abi_registers_integer_argument[reguse + 1]);
603 md->argintreguse = reguse;
607 pd->regoff = stacksize * 4;
614 # endif /* !defined(ENABLE_SOFT_FLOAT) */
616 /* fill register and stack usage */
618 md->memuse = stacksize;
620 #endif /* SIZEOF_VOID_P == 8 */
624 /* md_return_alloc *************************************************************
626 Precolor the Java Stackelement containing the Return Value. Since
627 mips has a dedicated return register (not an reused arg or reserved
628 reg), this is striaghtforward possible, as long, as this
629 stackelement does not have to survive a method invokation
633 jd: jitdata of the current method
634 stackslot: Java Stackslot to contain the Return Value
637 if precoloring was possible:
638 VAR(stackslot->varnum)->flags = PREALLOC
639 ->regoff = [REG_RESULT|REG_FRESULT]
641 *******************************************************************************/
643 void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
648 /* get required compiler data */
654 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
655 not to survive method invokations. */
657 if (!(stackslot->flags & SAVEDVAR)) {
658 VAR(stackslot->varnum)->flags = PREALLOC;
660 if (IS_INT_LNG_TYPE(md->returntype.type)) {
661 #if SIZEOF_VOID_P == 4
662 if (IS_2_WORD_TYPE(md->returntype.type))
663 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
666 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
669 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
675 * These are local overrides for various environment variables in Emacs.
676 * Please do not remove this and leave it at the end of the file, where
677 * Emacs will automagically detect them.
678 * ---------------------------------------------------------------------
681 * indent-tabs-mode: t