X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpowerpc%2Fdarwin%2Fmd-abi.c;h=bfb092b398ba61512cdc816031cc568b9c1dc880;hb=fa3fb41985bc911b5300f144b740159ac0c1eea0;hp=f1014a833c2174f6935b6ee037eba5632c3b2552;hpb=3067ba59a0bc2e157a9d53354374586e81b5dfd3;p=cacao.git diff --git a/src/vm/jit/powerpc/darwin/md-abi.c b/src/vm/jit/powerpc/darwin/md-abi.c index f1014a833..bfb092b39 100644 --- a/src/vm/jit/powerpc/darwin/md-abi.c +++ b/src/vm/jit/powerpc/darwin/md-abi.c @@ -1,9 +1,7 @@ -/* src/vm/jit/powerpc/darwin/md-abi.c - functions for PowerPC Darwin ABI +/* src/vm/jit/powerpc/darwin/md-abi.c - PowerPC Darwin ABI - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -19,57 +17,272 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at - - Authors: Christian Thalinger - - Changes: Christian Ullrich +*/ - $Id: md-abi.c 2872 2005-06-29 12:42:19Z christian $ -*/ +#include "config.h" +#include -#include "vm/jit/powerpc/types.h" #include "vm/jit/powerpc/darwin/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" +#include "vm/jit/abi.h" +#include "vm/jit/stack.h" + + +/* register descripton arrays *************************************************/ + +int nregdescint[] = { + /* zero, sp, t0, a0/v0, a0/v1, a2, a3, a4, */ + REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, + + /* a5, a6, a7, itmp1, itmp2, pv, s0, s1, */ + REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, + + /*itmp3, t1, t2, t3, t4, t5, t6, t7, */ + REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, + + /* s2, s3, s4, s5, s6, s7, s8, s9, */ + REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, + + REG_END +}; + +const char *abi_registers_integer_name[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +}; + +const int abi_registers_integer_argument[] = { + 3, /* a0 */ + 4, /* a1 */ + 5, /* a2 */ + 6, /* a3 */ + 7, /* a4 */ + 8, /* a5 */ + 9, /* a6 */ + 10, /* a7 */ +}; + +const int abi_registers_integer_saved[] = { + 14, /* s0 */ + 15, /* s1 */ + 24, /* s2 */ + 25, /* s3 */ + 26, /* s4 */ + 27, /* s5 */ + 28, /* s6 */ + 29, /* s7 */ + 30, /* s8 */ + 31, /* s9 */ +}; + +const int abi_registers_integer_temporary[] = { + 2, /* t0 */ + 17, /* t1 */ + 18, /* t2 */ + 19, /* t3 */ + 20, /* t4 */ + 21, /* t5 */ + 22, /* t6 */ + 23, /* t7 */ +}; + + +int nregdescfloat[] = { + /*ftmp3, fa0/v0, fa1, fa2, fa3, fa4, fa5, fa6, */ + REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, + + /* fa7, fa8, fa9, fa10, fa11, fa12, fs0, fs1, */ + REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV, + + /*ftmp1, ftmp2, ft0, ft1, ft2, ft3, ft4, ft5, */ + REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, + + /* fs2, fs3, fs4, fs5, fs6, fs7, fs8, fs9 */ + REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, + + REG_END +}; + +const int abi_registers_float_argument[] = { + 1, /* fa0 */ + 2, /* fa1 */ + 3, /* fa2 */ + 4, /* fa3 */ + 5, /* fa4 */ + 6, /* fa5 */ + 7, /* fa6 */ + 8, /* fa7 */ + 9, /* fa8 */ + 10, /* fa9 */ + 11, /* fa10 */ + 12, /* fa11 */ + 13, /* fa12 */ +}; + +const int abi_registers_float_saved[] = { + 14, /* fs0 */ + 15, /* fs1 */ + 24, /* fs2 */ + 25, /* fs3 */ + 26, /* fs4 */ + 27, /* fs5 */ + 28, /* fs6 */ + 29, /* fs7 */ + 30, /* fs8 */ + 31, /* fs9 */ +}; + +const int abi_registers_float_temporary[] = { + 17, /* ft5 */ + 18, /* ft6 */ + 19, /* ft7 */ + 20, /* ft8 */ + 21, /* ft9 */ + 22, /* ft10 */ + 23, /* ft11 */ +}; -/* md_param_alloc ************************************************************** - Allocate Arguments to Stackslots according the Calling Conventions +/* md_param_alloc ************************************************************** ---- in -md->paramcount: Number of arguments for this method -md->paramtypes[].type: Argument types + Allocate Arguments to Stackslots according the Calling Conventions ---- out -md->params[].inmemory: Argument spilled on stack -md->params[].regoff: Stack offset or rd->arg[int|flt]regs index -md->memuse: Stackslots needed for argument spilling -md->argintreguse: max number of integer arguments used -md->argfltreguse: max number of float arguments used + --- in + md->paramcount: Number of arguments for this method + md->paramtypes[].type: Argument types + + --- out + md->params[].inmemory: Argument spilled on stack + md->params[].regoff: Stack offset or rd->arg[int|flt]regs index + md->memuse: Stackslots needed for argument spilling + md->argintreguse: max number of integer arguments used + md->argfltreguse: max number of float arguments used *******************************************************************************/ void md_param_alloc(methoddesc *md) { paramdesc *pd; - s4 i; - s4 iarg; - s4 farg; - s4 stacksize; + int i; + int iarg; + int farg; + int stacksize; + + /* set default values */ + + iarg = 0; + farg = 0; + stacksize = LA_SIZE_IN_POINTERS; + + /* get params field of methoddesc */ + + pd = md->params; + + for (i = 0; i < md->paramcount; i++, pd++) { + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_ADR: + if (iarg < INT_ARG_CNT) { + pd->inmemory = false; + pd->index = iarg; + pd->regoff = abi_registers_integer_argument[iarg]; + iarg++; + } + else { + pd->inmemory = true; + pd->index = stacksize; + pd->regoff = stacksize * 8; + stacksize++; + } + break; + + case TYPE_LNG: + if (iarg < INT_ARG_CNT - 1) { + pd->inmemory = false; + pd->index = PACK_REGS(iarg + 1, iarg); + pd->regoff = + PACK_REGS(abi_registers_integer_argument[iarg + 1], + abi_registers_integer_argument[iarg]); + iarg += 2; + } + else { + pd->inmemory = true; + pd->index = stacksize; + pd->regoff = stacksize * 8; + iarg = INT_ARG_CNT; + stacksize++; + } + break; + + case TYPE_FLT: + case TYPE_DBL: + if (farg < FLT_ARG_CNT) { + pd->inmemory = false; + pd->index = farg; + pd->regoff = abi_registers_float_argument[farg]; + farg++; + } + else { + pd->inmemory = true; + pd->index = stacksize; + pd->regoff = stacksize * 8; + stacksize++; + } + break; + } + } + + + /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */ + /* argument register usage has to be regarded, too */ + + if (IS_INT_LNG_TYPE(md->returntype.type)) { + if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1)) + iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1; + } + else { + if (IS_FLT_DBL_TYPE(md->returntype.type)) + if (farg < 1) + farg = 1; + } + + /* fill register and stack usage */ + + md->argintreguse = iarg; + md->argfltreguse = farg; + md->memuse = stacksize; +} + + +/* md_param_alloc_native ******************************************************* + + Pre-allocate arguments according the native ABI. + +*******************************************************************************/ + +void md_param_alloc_native(methoddesc *md) +{ + paramdesc *pd; + int i; + int iarg; + int farg; + int stacksize; /* set default values */ - iarg = 0; - farg = 0; - stacksize = LA_WORD_SIZE; + iarg = 0; + farg = 0; + stacksize = LA_SIZE_IN_POINTERS; /* get params field of methoddesc */ @@ -81,48 +294,56 @@ void md_param_alloc(methoddesc *md) case TYPE_ADR: if (iarg < INT_ARG_CNT) { pd->inmemory = false; - pd->regoff = iarg; /* rd->arg[int|flt]regs index !! */ + pd->regoff = abi_registers_integer_argument[iarg]; iarg++; - } else { + } + else { pd->inmemory = true; - pd->regoff = stacksize; + pd->regoff = stacksize * 4; } stacksize++; break; + case TYPE_LNG: if (iarg < INT_ARG_CNT - 1) { pd->inmemory = false; - /* rd->arg[int|flt]regs index !! */ - pd->regoff = PACK_REGS(iarg + 1, iarg); + pd->regoff = + PACK_REGS(abi_registers_integer_argument[iarg + 1], + abi_registers_integer_argument[iarg]); iarg += 2; - } else { + } + else { pd->inmemory = true; - pd->regoff = stacksize; - iarg = INT_ARG_CNT; + pd->regoff = stacksize * 4; + iarg = INT_ARG_CNT; } stacksize += 2; break; + case TYPE_FLT: if (farg < FLT_ARG_CNT) { pd->inmemory = false; - pd->regoff = farg; /* rd->arg[int|flt]regs index !! */ - iarg++; /* skip 1 integer argument register */ + pd->regoff = abi_registers_float_argument[farg]; + iarg++; /* skip 1 integer argument register */ farg++; - } else { + } + else { pd->inmemory = true; - pd->regoff = stacksize; + pd->regoff = stacksize * 4; } stacksize++; break; + case TYPE_DBL: if (farg < FLT_ARG_CNT) { pd->inmemory = false; - pd->regoff = farg; /* rd->arg[int|flt]regs index !! */ - iarg += 2; /* skip 2 integer argument registers */ + pd->regoff = abi_registers_float_argument[farg]; + iarg += 2; /* skip 2 integer argument registers */ farg++; - } else { + } + else { pd->inmemory = true; - pd->regoff = stacksize; + pd->regoff = stacksize * 4; } stacksize += 2; break; @@ -132,70 +353,97 @@ void md_param_alloc(methoddesc *md) /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */ /* argument register usage has to be regarded, too */ + if (IS_INT_LNG_TYPE(md->returntype.type)) { if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1)) iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1; - } else { + } + else { if (IS_FLT_DBL_TYPE(md->returntype.type)) if (farg < 1) farg = 1; } /* fill register and stack usage */ + md->argintreguse = iarg; md->argfltreguse = farg; - md->memuse = stacksize; + md->memuse = stacksize; } + /* md_return_alloc ************************************************************* - Precolor the Java Stackelement containing the Return Value, if possible. - (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00 for float/double) + Precolor the Java Stackelement containing the Return Value, if + possible. (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00 + for float/double) ---- in -m: Methodinfo of current method -return_type: Return Type of the Method (TYPE_INT.. TYPE_ADR) - TYPE_VOID is not allowed! -stackslot: Java Stackslot to contain the Return Value + --- in + jd: jitdata of the current method + stackslot: Java Stackslot to contain the Return Value + + --- out + if precoloring was possible: + VAR(stackslot->varnum)->flags = PREALLOC + ->regoff = [REG_RESULT|REG_FRESULT] + rd->arg[flt|int]reguse set to a value according the register usage ---- out -if precoloring was possible: -stackslot->varkind =ARGVAR - ->varnum =-1 - ->flags =0 - ->regoff =[REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT] -rd->arg[flt|int]reguse set to a value according the register usage - + NOTE: Do not pass a LOCALVAR in stackslot->varnum. *******************************************************************************/ -void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type, - stackptr stackslot) { - /* In Leafmethods Local Vars holding parameters are precolored to their */ - /* argument register -> so leafmethods with paramcount > 0 could already */ - /* use R3 == a00! */ - if (!m->isleafmethod || (m->paramcount == 0)) { - /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has not */ - /* to survive method invokations */ + +void md_return_alloc(jitdata *jd, stackelement_t* stackslot) +{ + methodinfo *m; + codeinfo *code; + registerdata *rd; + methoddesc *md; + + /* get required compiler data */ + + m = jd->m; + code = jd->code; + rd = jd->rd; + + md = m->parseddesc; + + /* In Leafmethods Local Vars holding parameters are precolored to + their argument register -> so leafmethods with paramcount > 0 + could already use R3 == a00! */ + + if (!code_is_leafmethod(code) || (md->paramcount == 0)) { + /* Only precolor the stackslot, if it is not a SAVEDVAR <-> + has not to survive method invokations. */ + if (!(stackslot->flags & SAVEDVAR)) { - stackslot->varkind = ARGVAR; - stackslot->varnum = -1; - stackslot->flags = 0; - if ( IS_INT_LNG_TYPE(return_type) ) { - if (IS_2_WORD_TYPE(return_type)) { - if (rd->argintreguse < 1) rd->argintreguse = 1; - stackslot->regoff = REG_RESULT; - } else { - if (rd->argintreguse < 2) rd->argintreguse = 2; - stackslot->regoff = PACK_REGS(REG_RESULT2, REG_RESULT); + + VAR(stackslot->varnum)->flags = PREALLOC; + + if (IS_INT_LNG_TYPE(md->returntype.type)) { + if (!IS_2_WORD_TYPE(md->returntype.type)) { + if (rd->argintreguse < 1) + rd->argintreguse = 1; + + VAR(stackslot->varnum)->vv.regoff = REG_RESULT; + } + else { + if (rd->argintreguse < 2) + rd->argintreguse = 2; + + VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED; } - } else { /* float/double */ - if (rd->argfltreguse < 1) rd->argfltreguse = 1; - stackslot->regoff = REG_FRESULT; + } + else { + if (rd->argfltreguse < 1) + rd->argfltreguse = 1; + + VAR(stackslot->varnum)->vv.regoff = REG_FRESULT; } } } } + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where @@ -207,4 +455,5 @@ void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type, * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */