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
34 #include "vm/jit/mips/md-abi.h"
36 #include "mm/memory.h"
38 #include "vm/global.h"
40 #include "vm/jit/abi.h"
42 #include "vmcore/descriptor.h"
43 #include "vmcore/method.h"
46 /* register descripton array **************************************************/
48 #if SIZEOF_VOID_P == 8
53 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
54 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
55 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
56 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
60 const char *abi_registers_integer_name[] = {
61 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
62 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
63 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
64 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
67 const s4 abi_registers_integer_argument[] = {
78 const s4 abi_registers_integer_saved[] = {
89 const s4 abi_registers_integer_temporary[] = {
98 s4 nregdescfloat[] = {
99 /* fv0, ftmp1, ftmp2, ftmp3, ft0, ft1, ft2, ft3, */
100 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
102 /* ft4, ft5, ft6, ft7, fa0, fa1, fa2, fa3, */
103 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
105 /* fa4, fa5, fa6, fa7, ft8, ft9, ft10, ft11, */
106 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
108 /* fs0, ft12, fs1, ft13, fs2, ft14, fs3 ft15 */
109 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
114 const s4 abi_registers_float_argument[] = {
125 const s4 abi_registers_float_saved[] = {
132 const s4 abi_registers_float_temporary[] = {
151 #else /* SIZEOF_VOID_P == 8 */
156 /* zero, itmp1, v0, v1, a0, a1, a2, a3, */
157 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
159 /* t0, t1, t2, t3, t4, t5, t6, t7, */
160 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
162 /* s0, s1, s2, s3, s4, s5, s6, s7, */
163 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
165 /*itmp2, itmp3, k0(sys), k1(sys), gp, sp, pv, ra */
166 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
171 const char *abi_registers_integer_name[] = {
172 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
173 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
174 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
175 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
178 const s4 abi_registers_integer_argument[] = {
185 const s4 abi_registers_integer_saved[] = {
196 const s4 abi_registers_integer_temporary[] = {
208 #if !defined(ENABLE_SOFT_FLOAT)
210 s4 nregdescfloat[] = {
211 /* fv0, ftmp1, ftmp2, ftmp3, */
212 REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
214 /* ft0, ft1, fa0, fa1, */
215 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
217 /* ft2, ft3, fs0, fs1, */
218 REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
220 /* fs2, fs3, fs4, fs5 */
221 REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
226 const s4 abi_registers_float_argument[] = {
231 const s4 abi_registers_float_saved[] = {
240 const s4 abi_registers_float_temporary[] = {
248 #else /* !defined(ENABLE_SOFT_FLOAT) */
250 s4 nregdescfloat[] = {
254 #endif /* !defined(ENABLE_SOFT_FLOAT) */
256 #endif /* SIZEOF_VOID_P == 8 */
259 /* md_param_alloc **************************************************************
261 Pre-allocate arguments according to the internal JIT ABI.
263 *******************************************************************************/
265 void md_param_alloc(methoddesc *md)
272 /* set default values */
277 /* get params field of methoddesc */
281 #if SIZEOF_VOID_P == 8
283 for (i = 0; i < md->paramcount; i++, pd++) {
284 switch (md->paramtypes[i].type) {
288 if (reguse < INT_ARG_CNT) {
289 pd->inmemory = false;
290 pd->regoff = abi_registers_integer_argument[reguse];
292 md->argintreguse = reguse;
296 pd->regoff = stacksize * 8;
303 if (reguse < FLT_ARG_CNT) {
304 pd->inmemory = false;
305 pd->regoff = abi_registers_float_argument[reguse];
307 md->argfltreguse = reguse;
311 pd->regoff = stacksize * 8;
317 /* register type is the same as java type */
319 pd->type = md->paramtypes[i].type;
322 #else /* SIZEOF_VOID_P == 8 */
324 # if !defined(ENABLE_SOFT_FLOAT)
326 /* Set stacksize to 2, as 4 32-bit argument registers can be
328 /* XXX maybe this should be done in stack.c? */
332 for (i = 0; i < md->paramcount; i++, pd++) {
333 switch (md->paramtypes[i].type) {
336 if (reguse < INT_ARG_CNT) {
337 pd->inmemory = false;
339 pd->regoff = abi_registers_integer_argument[reguse];
341 md->argintreguse = reguse;
345 pd->index = stacksize;
346 pd->regoff = stacksize * 8;
354 if (reguse < INT_ARG_CNT) {
355 pd->inmemory = false;
356 # if WORDS_BIGENDIAN == 1
357 pd->index = PACK_REGS(reguse + 1, reguse);
359 PACK_REGS(abi_registers_integer_argument[reguse + 1],
360 abi_registers_integer_argument[reguse]);
362 pd->index = PACK_REGS(reguse, reguse + 1);
364 PACK_REGS(abi_registers_integer_argument[reguse],
365 abi_registers_integer_argument[reguse + 1]);
368 md->argintreguse = reguse;
372 pd->index = stacksize;
373 pd->regoff = stacksize * 8;
380 if (reguse < FLT_ARG_CNT) {
381 pd->inmemory = false;
383 pd->regoff = abi_registers_float_argument[reguse];
385 md->argfltreguse = reguse;
389 pd->index = stacksize;
390 pd->regoff = stacksize * 8;
396 /* register type is the same as java type */
398 pd->type = md->paramtypes[i].type;
401 # else /* !defined(ENABLE_SOFT_FLOAT) */
402 # error never actually tested!
404 for (i = 0; i < md->paramcount; i++, pd++) {
405 switch (md->paramtypes[i].type) {
411 if (reguse < INT_ARG_CNT) {
412 pd->inmemory = false;
413 pd->regoff = abi_registers_integer_argument[reguse];
415 md->argintreguse = reguse;
419 pd->regoff = stacksize * 8;
428 if (reguse < INT_ARG_CNT) {
429 pd->inmemory = false;
430 # if WORDS_BIGENDIAN == 1
432 PACK_REGS(abi_registers_integer_argument[reguse + 1],
433 abi_registers_integer_argument[reguse]);
436 PACK_REGS(abi_registers_integer_argument[reguse],
437 abi_registers_integer_argument[reguse + 1]);
440 md->argintreguse = reguse;
444 pd->regoff = stacksize * 8;
451 # endif /* !defined(ENABLE_SOFT_FLOAT) */
452 #endif /* SIZEOF_VOID_P == 8 */
454 /* fill register and stack usage */
456 md->memuse = stacksize;
460 /* md_param_alloc_native *******************************************************
462 Pre-allocate arguments according the native ABI.
464 *******************************************************************************/
466 void md_param_alloc_native(methoddesc *md)
468 #if SIZEOF_VOID_P == 8
470 /* On MIPS n64 we use the same ABI for JIT method calls as for
471 native method calls. */
475 #else /* SIZEOF_VOID_P == 8 */
481 # if !defined(ENABLE_SOFT_FLOAT)
486 /* set default values */
490 # if !defined(ENABLE_SOFT_FLOAT)
494 /* get params field of methoddesc */
498 # if !defined(ENABLE_SOFT_FLOAT)
500 for (i = 0; i < md->paramcount; i++, pd++) {
501 t = md->paramtypes[i].type;
503 if (IS_FLT_DBL_TYPE(t) &&
505 ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
506 if (IS_2_WORD_TYPE(t)) {
508 pd->regoff = abi_registers_float_argument[reguse];
514 pd->regoff = abi_registers_float_argument[reguse];
518 md->argfltreguse = reguse;
522 if (IS_2_WORD_TYPE(t)) {
526 if (reguse < INT_ARG_CNT) {
527 pd->inmemory = false;
528 # if WORDS_BIGENDIAN == 1
530 PACK_REGS(abi_registers_integer_argument[reguse + 1],
531 abi_registers_integer_argument[reguse]);
534 PACK_REGS(abi_registers_integer_argument[reguse],
535 abi_registers_integer_argument[reguse + 1]);
538 md->argintreguse = reguse;
544 pd->regoff = stacksize * 4;
551 if (reguse < INT_ARG_CNT) {
552 pd->inmemory = false;
553 pd->regoff = abi_registers_integer_argument[reguse];
555 md->argintreguse = reguse;
559 pd->regoff = stacksize * 4;
566 # else /* !defined(ENABLE_SOFT_FLOAT) */
567 # error never actually tested!
569 for (i = 0; i < md->paramcount; i++, pd++) {
570 switch (md->paramtypes[i].type) {
576 if (i < INT_ARG_CNT) {
577 pd->inmemory = false;
578 pd->regoff = abi_registers_integer_argument[reguse];
580 md->argintreguse = reguse;
584 pd->regoff = stacksize * 4;
592 if (i < INT_ARG_CNT) {
593 pd->inmemory = false;
594 # if WORDS_BIGENDIAN == 1
596 PACK_REGS(abi_registers_integer_argument[reguse + 1],
597 abi_registers_integer_argument[reguse]);
600 PACK_REGS(abi_registers_integer_argument[reguse],
601 abi_registers_integer_argument[reguse + 1]);
604 md->argintreguse = reguse;
608 pd->regoff = stacksize * 4;
615 # endif /* !defined(ENABLE_SOFT_FLOAT) */
617 /* fill register and stack usage */
619 md->memuse = stacksize;
621 #endif /* SIZEOF_VOID_P == 8 */
625 /* md_return_alloc *************************************************************
627 Precolor the Java Stackelement containing the Return Value. Since
628 mips has a dedicated return register (not an reused arg or reserved
629 reg), this is striaghtforward possible, as long, as this
630 stackelement does not have to survive a method invokation
634 jd: jitdata of the current method
635 stackslot: Java Stackslot to contain the Return Value
638 if precoloring was possible:
639 VAR(stackslot->varnum)->flags = PREALLOC
640 ->regoff = [REG_RESULT|REG_FRESULT]
642 *******************************************************************************/
644 void md_return_alloc(jitdata *jd, stackptr stackslot)
649 /* get required compiler data */
655 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
656 not to survive method invokations. */
658 if (!(stackslot->flags & SAVEDVAR)) {
659 VAR(stackslot->varnum)->flags = PREALLOC;
661 if (IS_INT_LNG_TYPE(md->returntype.type)) {
662 #if SIZEOF_VOID_P == 4
663 if (IS_2_WORD_TYPE(md->returntype.type))
664 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
667 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
670 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
676 * These are local overrides for various environment variables in Emacs.
677 * Please do not remove this and leave it at the end of the file, where
678 * Emacs will automagically detect them.
679 * ---------------------------------------------------------------------
682 * indent-tabs-mode: t