From: christian Date: Thu, 7 Sep 2006 13:29:05 +0000 (+0000) Subject: Unified variables changes for common/i386. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=add35c29eddac8e51219ba6410234e89e23fa796 Unified variables changes for common/i386. --HG-- branch : unified_variables --- diff --git a/.hgtags b/.hgtags index cbc17eaed..734924606 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,4 @@ a7d9b1655845c526636a510594214c32d3a120ea cacao-0_93-release f0bbc765d01fd58f0c42e25de02f059c2f9a9598 cacao-0.95 31f9c3186dded73dab4ed3f519c1cc28940c98dd cacao-0.96 ae597ed07b16e08575c39f88b93004049f663b2b new_instruction_format_branch_point +d19da1d8ff91d76df914b1d2455d6faaec4fbcdf unified_variables_branch_point diff --git a/src/vm/jit/allocator/simplereg.c b/src/vm/jit/allocator/simplereg.c index 042082fe6..499204dd4 100644 --- a/src/vm/jit/allocator/simplereg.c +++ b/src/vm/jit/allocator/simplereg.c @@ -32,7 +32,7 @@ Michael Starzinger Edwin Steiner - $Id: simplereg.c 5343 2006-09-05 21:20:33Z twisti $ + $Id: simplereg.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -80,16 +80,21 @@ bool new_regalloc(jitdata *jd) allocate_scratch_registers and setting it back to the original value before calling local_regalloc. */ + printf("------- rd->memuse bef %d\n",jd->rd->memuse); + interface_regalloc(jd); + printf("------- rd->memuse int %d\n",jd->rd->memuse); new_allocate_scratch_registers(jd); + printf("------- rd->memuse scr %d\n",jd->rd->memuse); local_regalloc(jd); + printf("------- rd->memuse loc %d\n",jd->rd->memuse); /* everthing's ok */ return true; } - +#if defined(NEW_VAR) /* interface_regalloc ********************************************************** Allocates registers for all interface variables. @@ -104,7 +109,7 @@ static void interface_regalloc(jitdata *jd) int s, t, tt, saved; int intalloc, fltalloc; /* Remember allocated Register/Memory offset */ - /* in case a more vars are packed into this interface slot */ + /* in case more vars are packed into this interface slot */ varinfo *v; int intregsneeded = 0; int memneeded = 0; @@ -145,16 +150,21 @@ static void interface_regalloc(jitdata *jd) for (s = 0; s < cd->maxstack; s++) { intalloc = -1; fltalloc = -1; - saved = (rd->interfaces[s][TYPE_INT].flags | - rd->interfaces[s][TYPE_LNG].flags | - rd->interfaces[s][TYPE_FLT].flags | - rd->interfaces[s][TYPE_DBL].flags | - rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR; - + + saved = 0; + + for (tt = 0; tt <=4; tt++) { + if ((t = jd->interface_map[s * 5 + TYPE_INT]) != UNUSED) { + saved |= (jd->var[t].flags & SAVEDVAR); + } + } + for (tt = 0; tt <= 4; tt++) { t = typeloop[tt]; - v = &rd->interfaces[s][t]; - if (v->type >= 0) { + if (jd->interface_map[s * 5 + t] == UNUSED) + continue; + + v = &(jd->var[jd->interface_map[s * 5 + t]]); #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif @@ -181,9 +191,8 @@ static void interface_regalloc(jitdata *jd) if (IS_FLT_DBL_TYPE(t)) { if (fltalloc >= 0) { /* Reuse memory slot(s)/register(s) for shared interface slots */ - v->flags |= rd->interfaces[s][fltalloc].flags - & INMEMORY; - v->regoff = rd->interfaces[s][fltalloc].regoff; + v->flags |= jd->var[fltalloc].flags & INMEMORY; + v->regoff = jd->var[fltalloc].regoff; } else if (rd->argfltreguse < FLT_ARG_CNT) { v->regoff = rd->argfltregs[rd->argfltreguse++]; } else if (rd->tmpfltreguse > 0) { @@ -200,7 +209,7 @@ static void interface_regalloc(jitdata *jd) v->regoff = rd->memuse; rd->memuse += memneeded + 1; } - fltalloc = t; + fltalloc = jd->interface_map[s * 5 + t]; } else { /* !IS_FLT_DBL_TYPE(t) */ #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) /* @@ -219,18 +228,17 @@ static void interface_regalloc(jitdata *jd) #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */ if (intalloc >= 0) { /* Reuse memory slot(s)/register(s) for shared interface slots */ - v->flags |= - rd->interfaces[s][intalloc].flags - & INMEMORY; + v->flags |= jd->var[intalloc].flags + & INMEMORY; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) if (!(v->flags & INMEMORY) - && IS_2_WORD_TYPE(intalloc)) + && IS_2_WORD_TYPE(jd->var[intalloc].type)) v->regoff = GET_LOW_REG( - rd->interfaces[s][intalloc].regoff); + jd->var[intalloc].regoff); else #endif v->regoff = - rd->interfaces[s][intalloc].regoff; + jd->var[intalloc].regoff; } else if (rd->argintreguse + intregsneeded < INT_ARG_CNT) { @@ -282,7 +290,7 @@ static void interface_regalloc(jitdata *jd) rd->memuse += memneeded + 1; } - intalloc = t; + intalloc = jd->interface_map[s * 5 + t]; } /* if (IS_FLT_DBL_TYPE(t)) */ } } else { /* (saved) */ @@ -301,12 +309,12 @@ static void interface_regalloc(jitdata *jd) { if (IS_FLT_DBL_TYPE(t)) { if (fltalloc >= 0) { - v->flags |= rd->interfaces[s][fltalloc].flags - & INMEMORY; - v->regoff = rd->interfaces[s][fltalloc].regoff; + v->flags |= jd->var[fltalloc].flags & INMEMORY; + v->regoff = jd->var[fltalloc].regoff; } else if (rd->savfltreguse > 0) { - v->regoff = rd->savfltregs[--rd->savfltreguse]; + v->regoff = + rd->savfltregs[--rd->savfltreguse]; } else { v->flags |= INMEMORY; @@ -318,7 +326,7 @@ static void interface_regalloc(jitdata *jd) v->regoff = rd->memuse; rd->memuse += memneeded + 1; } - fltalloc = t; + fltalloc = jd->interface_map[s * 5 + t]; } else { /* IS_INT_LNG */ #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) @@ -338,18 +346,18 @@ static void interface_regalloc(jitdata *jd) #endif { if (intalloc >= 0) { - v->flags |= - rd->interfaces[s][intalloc].flags & INMEMORY; + v->flags |= jd->var[intalloc].flags + & INMEMORY; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) if (!(v->flags & INMEMORY) - && IS_2_WORD_TYPE(intalloc)) + && IS_2_WORD_TYPE(jd->var[intalloc].type)) v->regoff = GET_LOW_REG( - rd->interfaces[s][intalloc].regoff); + jd->var[intalloc].regoff); else #endif v->regoff = - rd->interfaces[s][intalloc].regoff; + jd->var[intalloc].regoff; } else { if (rd->savintreguse > intregsneeded) { rd->savintreguse -= intregsneeded + 1; @@ -378,34 +386,32 @@ static void interface_regalloc(jitdata *jd) } /* if (IS_FLT_DBL_TYPE(t) else */ } /* if (IS_ADR_TYPE(t)) else */ } /* if (saved) else */ - } /* if (type >= 0) */ + /* if (type >= 0) */ } /* for t */ } /* for s */ } +#else +/* interface_regalloc ********************************************************** - -/* local_regalloc ************************************************************** - - Allocates registers for all local variables. + Allocates registers for all interface variables. *******************************************************************************/ -static void local_regalloc(jitdata *jd) +static void interface_regalloc(jitdata *jd) { methodinfo *m; codegendata *cd; registerdata *rd; - int p, s, t, tt; - int intalloc, fltalloc; + int s, t, tt, saved; + int intalloc, fltalloc; /* Remember allocated Register/Memory offset */ + /* in case a more vars are packed into this interface slot */ varinfo *v; - int intregsneeded = 0; - int memneeded = 0; + int intregsneeded = 0; + int memneeded = 0; + /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */ + /* on HAS_4BYTE_STACKSLOT architectures */ int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR }; - int fargcnt, iargcnt; -#ifdef HAS_ADDRESS_REGISTER_FILE - int aargcnt; -#endif /* get required compiler data */ @@ -413,774 +419,2267 @@ static void local_regalloc(jitdata *jd) cd = jd->cd; rd = jd->rd; - if (jd->isleafmethod) { - methoddesc *md = m->parseddesc; + /* rd->memuse was already set in stack.c to allocate stack space + for passing arguments to called methods. */ - iargcnt = rd->argintreguse; - fargcnt = rd->argfltreguse; +#if defined(__I386__) + if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */ + if (rd->memuse < 1) + rd->memuse = 1; + } +#endif + + if (jd->isleafmethod) { + /* Reserve argument register, which will be used for Locals acting */ + /* as Parameters */ + if (rd->argintreguse < m->parseddesc->argintreguse) + rd->argintreguse = m->parseddesc->argintreguse; + if (rd->argfltreguse < m->parseddesc->argfltreguse) + rd->argfltreguse = m->parseddesc->argfltreguse; #ifdef HAS_ADDRESS_REGISTER_FILE - aargcnt = rd->argadrreguse; + if (rd->argadrreguse < m->parseddesc->argadrreguse) + rd->argadrreguse = m->parseddesc->argadrreguse; #endif - for (p = 0, s = 0; s < cd->maxlocals; s++, p++) { - intalloc = -1; fltalloc = -1; - for (tt = 0; tt <= 4; tt++) { - t = typeloop[tt]; - v = &rd->locals[s][t]; - if (v->type < 0) - continue; + } + for (s = 0; s < cd->maxstack; s++) { + intalloc = -1; fltalloc = -1; + saved = (rd->interfaces[s][TYPE_INT].flags | + rd->interfaces[s][TYPE_LNG].flags | + rd->interfaces[s][TYPE_FLT].flags | + rd->interfaces[s][TYPE_DBL].flags | + rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR; + + for (tt = 0; tt <= 4; tt++) { + t = typeloop[tt]; + v = &rd->interfaces[s][t]; + if (v->type >= 0) { #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif #if defined(HAS_4BYTE_STACKSLOT) memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif - - /* - * The order of - * - * #ifdef HAS_ADDRESS_REGISTER_FILE - * if (IS_ADR_TYPE) { - * ... - * } else - * #endif - * if (IS_FLT_DBL) { - * ... - * } else { / int & lng - * ... - * } - * - * must not to be changed! - */ - -#ifdef HAS_ADDRESS_REGISTER_FILE - if (IS_ADR_TYPE(t)) { - if ((p < md->paramcount) && !md->params[p].inmemory) { - v->flags = 0; - v->regoff = rd->argadrregs[md->params[p].regoff]; - } - else if (rd->tmpadrreguse > 0) { - v->flags = 0; - v->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; - } - /* use unused argument registers as local registers */ - else if ((p >= md->paramcount) && - (aargcnt < ADR_ARG_CNT)) { - v->flags = 0; - v->regoff = rd->argadrregs[aargcnt++]; - } - else if (rd->savadrreguse > 0) { - v->flags = 0; - v->regoff = rd->savadrregs[--rd->savadrreguse]; - } - else { - v->flags |= INMEMORY; - v->regoff = rd->memuse++; - } - } else { -#endif - if (IS_FLT_DBL_TYPE(t)) { - if (fltalloc >= 0) { - v->flags = rd->locals[s][fltalloc].flags; - v->regoff = rd->locals[s][fltalloc].regoff; - } -#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) - /* We can only use float arguments as local variables, - * if we do not pass them in integer registers. */ - else if ((p < md->paramcount) && - !md->params[p].inmemory) { - v->flags = 0; - v->regoff = rd->argfltregs[md->params[p].regoff]; - } -#endif - else if (rd->tmpfltreguse > 0) { - v->flags = 0; - v->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; - } - /* use unused argument registers as local registers */ - else if ((p >= md->paramcount) && - (fargcnt < FLT_ARG_CNT)) { - v->flags = 0; - v->regoff = rd->argfltregs[fargcnt]; - fargcnt++; - } - else if (rd->savfltreguse > 0) { - v->flags = 0; - v->regoff = rd->savfltregs[--rd->savfltreguse]; - } - else { - v->flags = INMEMORY; + if (!saved) { +#if defined(HAS_ADDRESS_REGISTER_FILE) + if (IS_ADR_TYPE(t)) { + if (!jd->isleafmethod + &&(rd->argadrreguse < ADR_ARG_CNT)) { + v->regoff = rd->argadrregs[rd->argadrreguse++]; + } else if (rd->tmpadrreguse > 0) { + v->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; + } else if (rd->savadrreguse > 0) { + v->regoff = rd->savadrregs[--rd->savadrreguse]; + } else { + v->flags |= INMEMORY; + v->regoff = rd->memuse++; + } + } else /* !IS_ADR_TYPE */ +#endif /* defined(HAS_ADDRESS_REGISTER_FILE) */ + { + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + /* Reuse memory slot(s)/register(s) for shared interface slots */ + v->flags |= rd->interfaces[s][fltalloc].flags + & INMEMORY; + v->regoff = rd->interfaces[s][fltalloc].regoff; + } else if (rd->argfltreguse < FLT_ARG_CNT) { + v->regoff = rd->argfltregs[rd->argfltreguse++]; + } else if (rd->tmpfltreguse > 0) { + v->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; + } else if (rd->savfltreguse > 0) { + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } else { + v->flags |= INMEMORY; #if defined(ALIGN_DOUBLES_IN_MEMORY) - /* Align doubles in Memory */ - if ( (memneeded) && (rd->memuse & 1)) - rd->memuse++; + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; #endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } - fltalloc = t; - - } else { + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + fltalloc = t; + } else { /* !IS_FLT_DBL_TYPE(t) */ #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - /* - * for i386 put all longs in memory - */ - if (IS_2_WORD_TYPE(t)) { - v->flags = INMEMORY; + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags |= INMEMORY; #if defined(ALIGN_LONGS_IN_MEMORY) - /* Align longs in Memory */ - if (rd->memuse & 1) - rd->memuse++; -#endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } else + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; #endif - { - if (intalloc >= 0) { - v->flags = rd->locals[s][intalloc].flags; -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (!(v->flags & INMEMORY) - && IS_2_WORD_TYPE(intalloc)) - v->regoff = GET_LOW_REG( - rd->locals[s][intalloc].regoff); - else -#endif - v->regoff = rd->locals[s][intalloc].regoff; - } - else if ((p < md->paramcount) && - !md->params[p].inmemory) { - v->flags = 0; + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else +#endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */ + if (intalloc >= 0) { + /* Reuse memory slot(s)/register(s) for shared interface slots */ + v->flags |= + rd->interfaces[s][intalloc].flags + & INMEMORY; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (IS_2_WORD_TYPE(t)) - v->regoff = PACK_REGS( - rd->argintregs[GET_LOW_REG(md->params[p].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]); + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(intalloc)) + v->regoff = GET_LOW_REG( + rd->interfaces[s][intalloc].regoff); else #endif - v->regoff = - rd->argintregs[md->params[p].regoff]; - } - else if (rd->tmpintreguse > intregsneeded) { - rd->tmpintreguse -= intregsneeded + 1; - v->flags = 0; + v->regoff = + rd->interfaces[s][intalloc].regoff; + } else + if (rd->argintreguse + intregsneeded + < INT_ARG_CNT) { #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - v->regoff = PACK_REGS( - rd->tmpintregs[rd->tmpintreguse], - rd->tmpintregs[rd->tmpintreguse + 1]); - else + if (intregsneeded) + v->regoff=PACK_REGS( + rd->argintregs[rd->argintreguse], + rd->argintregs[rd->argintreguse + 1]); + else #endif - v->regoff = - rd->tmpintregs[rd->tmpintreguse]; - } - /* - * use unused argument registers as local registers - */ - else if ((p >= m->parseddesc->paramcount) && - (iargcnt + intregsneeded < INT_ARG_CNT)) { - v->flags = 0; + v->regoff = + rd->argintregs[rd->argintreguse]; + rd->argintreguse += intregsneeded + 1; + } + else if (rd->tmpintreguse > intregsneeded) { + rd->tmpintreguse -= intregsneeded + 1; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - v->regoff=PACK_REGS( - rd->argintregs[iargcnt], - rd->argintregs[iargcnt + 1]); - else + if (intregsneeded) + v->regoff=PACK_REGS( + rd->tmpintregs[rd->tmpintreguse], + rd->tmpintregs[rd->tmpintreguse + 1]); + else #endif - v->regoff = rd->argintregs[iargcnt]; - iargcnt += intregsneeded + 1; - } - else if (rd->savintreguse > intregsneeded) { - rd->savintreguse -= intregsneeded + 1; - v->flags = 0; + v->regoff = + rd->tmpintregs[rd->tmpintreguse]; + } + else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; + v->regoff = + rd->savintregs[rd->savintreguse]; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - v->regoff = PACK_REGS( - rd->savintregs[rd->savintreguse], - rd->savintregs[rd->savintreguse + 1]); - else + if (intregsneeded) + v->regoff=PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else #endif - v->regoff =rd->savintregs[rd->savintreguse]; - } - else { - v->flags = INMEMORY; + v->regoff = + rd->savintregs[rd->savintreguse]; + } + else { + v->flags |= INMEMORY; #if defined(ALIGN_LONGS_IN_MEMORY) - /* Align longs in Memory */ - if ( (memneeded) && (rd->memuse & 1)) - rd->memuse++; -#endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } - } - intalloc = t; - } -#ifdef HAS_ADDRESS_REGISTER_FILE - } + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; #endif - } /* for (tt=0;...) */ - - /* If the current parameter is a 2-word type, the next local slot */ - /* is skipped. */ - - if (p < md->paramcount) - if (IS_2_WORD_TYPE(md->paramtypes[p].type)) - s++; - } - return; - } - - for (s = 0; s < cd->maxlocals; s++) { - intalloc = -1; fltalloc = -1; - for (tt=0; tt<=4; tt++) { - t = typeloop[tt]; - v = &rd->locals[s][t]; + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } - if (v->type >= 0) { -#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS - intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; -#endif -#if defined(HAS_4BYTE_STACKSLOT) - memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; -#endif + intalloc = t; + } /* if (IS_FLT_DBL_TYPE(t)) */ + } + } else { /* (saved) */ +/* now the same like above, but without a chance to take a temporary register */ #ifdef HAS_ADDRESS_REGISTER_FILE - if ( IS_ADR_TYPE(t) ) { - if (rd->savadrreguse > 0) { - v->flags = 0; - v->regoff = rd->savadrregs[--rd->savadrreguse]; - } - else { - v->flags = INMEMORY; - v->regoff = rd->memuse++; - } - } else { + if (IS_ADR_TYPE(t)) { + if (rd->savadrreguse > 0) { + v->regoff = rd->savadrregs[--rd->savadrreguse]; + } + else { + v->flags |= INMEMORY; + v->regoff = rd->memuse++; + } + } else #endif - if (IS_FLT_DBL_TYPE(t)) { - if (fltalloc >= 0) { - v->flags = rd->locals[s][fltalloc].flags; - v->regoff = rd->locals[s][fltalloc].regoff; - } - else if (rd->savfltreguse > 0) { - v->flags = 0; - v->regoff = rd->savfltregs[--rd->savfltreguse]; - } - else { - v->flags = INMEMORY; + { + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + v->flags |= rd->interfaces[s][fltalloc].flags + & INMEMORY; + v->regoff = rd->interfaces[s][fltalloc].regoff; + } else + if (rd->savfltreguse > 0) { + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } + else { + v->flags |= INMEMORY; #if defined(ALIGN_DOUBLES_IN_MEMORY) - /* Align doubles in Memory */ - if ( (memneeded) && (rd->memuse & 1)) - rd->memuse++; + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; #endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } - fltalloc = t; - } - else { + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + fltalloc = t; + } + else { /* IS_INT_LNG */ #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - /* - * for i386 put all longs in memory - */ - if (IS_2_WORD_TYPE(t)) { - v->flags = INMEMORY; + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags |= INMEMORY; #if defined(ALIGN_LONGS_IN_MEMORY) - /* Align longs in Memory */ - if (rd->memuse & 1) - rd->memuse++; + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; #endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } else { + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else #endif - if (intalloc >= 0) { - v->flags = rd->locals[s][intalloc].flags; + { + if (intalloc >= 0) { + v->flags |= + rd->interfaces[s][intalloc].flags & INMEMORY; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (!(v->flags & INMEMORY) - && IS_2_WORD_TYPE(intalloc)) - v->regoff = GET_LOW_REG( - rd->locals[s][intalloc].regoff); - else + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(intalloc)) + v->regoff = + GET_LOW_REG( + rd->interfaces[s][intalloc].regoff); + else #endif - v->regoff = rd->locals[s][intalloc].regoff; - } - else if (rd->savintreguse > intregsneeded) { - rd->savintreguse -= intregsneeded+1; - v->flags = 0; + v->regoff = + rd->interfaces[s][intalloc].regoff; + } else { + if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - v->regoff = PACK_REGS( - rd->savintregs[rd->savintreguse], - rd->savintregs[rd->savintreguse + 1]); - else + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else #endif - v->regoff =rd->savintregs[rd->savintreguse]; - } - else { - v->flags = INMEMORY; + v->regoff = + rd->savintregs[rd->savintreguse]; + } else { + v->flags |= INMEMORY; #if defined(ALIGN_LONGS_IN_MEMORY) - /* Align longs in Memory */ - if ( (memneeded) && (rd->memuse & 1)) - rd->memuse++; -#endif - v->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } -#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - } -#endif - intalloc = t; - } -#ifdef HAS_ADDRESS_REGISTER_FILE - } + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; #endif - - } - } - } + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + } + intalloc = t; + } + } /* if (IS_FLT_DBL_TYPE(t) else */ + } /* if (IS_ADR_TYPE(t)) else */ + } /* if (saved) else */ + } /* if (type >= 0) */ + } /* for t */ + } /* for s */ } +#endif /* defined(NEW_VAR) */ -static void reg_init_temp(methodinfo *m, registerdata *rd) + +#if defined(NEW_VAR) +/* local_regalloc ************************************************************** + + Allocates registers for all local variables. + +*******************************************************************************/ + +static void local_regalloc(jitdata *jd) { - rd->freememtop = 0; -#if defined(HAS_4BYTE_STACKSLOT) - rd->freememtop_2 = 0; -#endif + methodinfo *m; + codegendata *cd; + registerdata *rd; - rd->freetmpinttop = 0; - rd->freesavinttop = 0; - rd->freetmpflttop = 0; - rd->freesavflttop = 0; + int p, s, t, tt,lm; + int intalloc, fltalloc; + varinfo *v; + int intregsneeded = 0; + int memneeded = 0; + int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR }; + int fargcnt, iargcnt; #ifdef HAS_ADDRESS_REGISTER_FILE - rd->freetmpadrtop = 0; - rd->freesavadrtop = 0; + int aargcnt; #endif - rd->freearginttop = 0; - rd->freeargflttop = 0; -#ifdef HAS_ADDRESS_REGISTER_FILE - rd->freeargadrtop = 0; -#endif -} + /* get required compiler data */ + m = jd->m; + cd = jd->cd; + rd = jd->rd; -#define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s) + if (jd->isleafmethod) { + methoddesc *md = m->parseddesc; -static void reg_new_temp_func(registerdata *rd, stackptr s) -{ - s4 intregsneeded; - s4 memneeded; - s4 tryagain; + iargcnt = rd->argintreguse; + fargcnt = rd->argfltreguse; +#ifdef HAS_ADDRESS_REGISTER_FILE + aargcnt = rd->argadrreguse; +#endif + for (p = 0, s = 0; s < cd->maxlocals; s++, p++) { + intalloc = -1; fltalloc = -1; + for (tt = 0; tt <= 4; tt++) { + t = typeloop[tt]; + lm = jd->local_map[s * 5 + t]; + if (lm == UNUSED) + continue; - /* Try to allocate a saved register if there is no temporary one */ - /* available. This is what happens during the second run. */ - tryagain = (s->flags & SAVEDVAR) ? 1 : 2; + v = &(jd->var[lm]); -#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS - intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; -#else - intregsneeded = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif #if defined(HAS_4BYTE_STACKSLOT) - memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; -#else - memneeded = 0; + memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif - for(; tryagain; --tryagain) { - if (tryagain == 1) { - if (!(s->flags & SAVEDVAR)) - s->flags |= SAVEDTMP; + /* + * The order of + * + * #ifdef HAS_ADDRESS_REGISTER_FILE + * if (IS_ADR_TYPE) { + * ... + * } else + * #endif + * if (IS_FLT_DBL) { + * ... + * } else { / int & lng + * ... + * } + * + * must not to be changed! + */ + #ifdef HAS_ADDRESS_REGISTER_FILE - if (IS_ADR_TYPE(s->type)) { - if (rd->freesavadrtop > 0) { - s->regoff = rd->freesavadrregs[--rd->freesavadrtop]; - return; - } else if (rd->savadrreguse > 0) { - s->regoff = rd->savadrregs[--rd->savadrreguse]; - return; - } - } else -#endif - { - if (IS_FLT_DBL_TYPE(s->type)) { - if (rd->freesavflttop > 0) { - s->regoff = rd->freesavfltregs[--rd->freesavflttop]; - return; - } else if (rd->savfltreguse > 0) { - s->regoff = rd->savfltregs[--rd->savfltreguse]; - return; + if (IS_ADR_TYPE(t)) { + if ((p < md->paramcount) && !md->params[p].inmemory) { + v->flags = 0; + v->regoff = rd->argadrregs[md->params[p].regoff]; + } + else if (rd->tmpadrreguse > 0) { + v->flags = 0; + v->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; + } + /* use unused argument registers as local registers */ + else if ((p >= md->paramcount) && + (aargcnt < ADR_ARG_CNT)) { + v->flags = 0; + v->regoff = rd->argadrregs[aargcnt++]; + } + else if (rd->savadrreguse > 0) { + v->flags = 0; + v->regoff = rd->savadrregs[--rd->savadrreguse]; } + else { + v->flags |= INMEMORY; + v->regoff = rd->memuse++; + } } else { -#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - /* - * for i386 put all longs in memory - */ - if (!IS_2_WORD_TYPE(s->type)) #endif - { - if (rd->freesavinttop > intregsneeded) { - rd->freesavinttop -= intregsneeded + 1; -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->freesavintregs[rd->freesavinttop], - rd->freesavintregs[rd->freesavinttop + 1]); - else + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + v->flags = jd->var[fltalloc].flags; + v->regoff = jd->var[fltalloc].regoff; + } +#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) + /* We can only use float arguments as local variables, + * if we do not pass them in integer registers. */ + else if ((p < md->paramcount) && + !md->params[p].inmemory) { + v->flags = 0; + v->regoff = rd->argfltregs[md->params[p].regoff]; + } #endif - s->regoff = - rd->freesavintregs[rd->freesavinttop]; - return; - } else if (rd->savintreguse > intregsneeded) { - rd->savintreguse -= intregsneeded + 1; -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->savintregs[rd->savintreguse], - rd->savintregs[rd->savintreguse + 1]); - else + else if (rd->tmpfltreguse > 0) { + v->flags = 0; + v->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; + } + /* use unused argument registers as local registers */ + else if ((p >= md->paramcount) && + (fargcnt < FLT_ARG_CNT)) { + v->flags = 0; + v->regoff = rd->argfltregs[fargcnt]; + fargcnt++; + } + else if (rd->savfltreguse > 0) { + v->flags = 0; + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_DOUBLES_IN_MEMORY) + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; #endif - s->regoff = rd->savintregs[rd->savintreguse]; - return; + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; } - } - } - } - } else { /* tryagain == 2 */ -#ifdef HAS_ADDRESS_REGISTER_FILE - if (IS_ADR_TYPE(s->type)) { - if (rd->freetmpadrtop > 0) { - s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop]; - return; - } else if (rd->tmpadrreguse > 0) { - s->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; - return; - } - } else -#endif - { - if (IS_FLT_DBL_TYPE(s->type)) { - if (rd->freeargflttop > 0) { - s->regoff = rd->freeargfltregs[--rd->freeargflttop]; - s->flags |= TMPARG; - return; - } else if (rd->argfltreguse < FLT_ARG_CNT) { - s->regoff = rd->argfltregs[rd->argfltreguse++]; - s->flags |= TMPARG; - return; - } else if (rd->freetmpflttop > 0) { - s->regoff = rd->freetmpfltregs[--rd->freetmpflttop]; - return; - } else if (rd->tmpfltreguse > 0) { - s->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; - return; - } + fltalloc = jd->local_map[s * 5 + t]; - } else { + } else { #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - /* - * for i386 put all longs in memory - */ - if (!IS_2_WORD_TYPE(s->type)) + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; #endif - { - if (rd->freearginttop > intregsneeded) { - rd->freearginttop -= intregsneeded + 1; - s->flags |= TMPARG; + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else +#endif + { + if (intalloc >= 0) { + v->flags = jd->var[intalloc].flags; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->freeargintregs[rd->freearginttop], - rd->freeargintregs[rd->freearginttop + 1]); - else + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(jd->var[intalloc].type)) + v->regoff = GET_LOW_REG( + jd->var[intalloc].regoff); + else #endif - s->regoff = - rd->freeargintregs[rd->freearginttop]; - return; - } else if (rd->argintreguse - < INT_ARG_CNT - intregsneeded) { + v->regoff = jd->var[intalloc].regoff; + } + else if ((p < md->paramcount) && + !md->params[p].inmemory) { + v->flags = 0; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->argintregs[rd->argintreguse], - rd->argintregs[rd->argintreguse + 1]); - else + if (IS_2_WORD_TYPE(t)) + v->regoff = PACK_REGS( + rd->argintregs[GET_LOW_REG(md->params[p].regoff)], + rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]); + else #endif - s->regoff = rd->argintregs[rd->argintreguse]; - s->flags |= TMPARG; - rd->argintreguse += intregsneeded + 1; - return; - } else if (rd->freetmpinttop > intregsneeded) { - rd->freetmpinttop -= intregsneeded + 1; + v->regoff = + rd->argintregs[md->params[p].regoff]; + } + else if (rd->tmpintreguse > intregsneeded) { + rd->tmpintreguse -= intregsneeded + 1; + v->flags = 0; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->freetmpintregs[rd->freetmpinttop], - rd->freetmpintregs[rd->freetmpinttop + 1]); - else + if (intregsneeded) + v->regoff = PACK_REGS( + rd->tmpintregs[rd->tmpintreguse], + rd->tmpintregs[rd->tmpintreguse + 1]); + else #endif - s->regoff = rd->freetmpintregs[rd->freetmpinttop]; - return; - } else if (rd->tmpintreguse > intregsneeded) { - rd->tmpintreguse -= intregsneeded + 1; + v->regoff = + rd->tmpintregs[rd->tmpintreguse]; + } + /* + * use unused argument registers as local registers + */ + else if ((p >= m->parseddesc->paramcount) && + (iargcnt + intregsneeded < INT_ARG_CNT)) { + v->flags = 0; #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) - s->regoff = PACK_REGS( - rd->tmpintregs[rd->tmpintreguse], - rd->tmpintregs[rd->tmpintreguse + 1]); - else + if (intregsneeded) + v->regoff=PACK_REGS( + rd->argintregs[iargcnt], + rd->argintregs[iargcnt + 1]); + else #endif - s->regoff = rd->tmpintregs[rd->tmpintreguse]; - return; + v->regoff = rd->argintregs[iargcnt]; + iargcnt += intregsneeded + 1; + } + else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + v->regoff =rd->savintregs[rd->savintreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } } - } /* if (!IS_2_WORD_TYPE(s->type)) */ - } /* if (IS_FLT_DBL_TYPE(s->type)) */ - } /* if (IS_ADR_TYPE(s->type)) */ - } /* if (tryagain == 1) else */ - } /* for(; tryagain; --tryagain) */ + intalloc = jd->local_map[s * 5 + t]; + } +#ifdef HAS_ADDRESS_REGISTER_FILE + } +#endif + } /* for (tt=0;...) */ -#if defined(HAS_4BYTE_STACKSLOT) - if ((memneeded == 1) && (rd->freememtop_2 > 0)) { - rd->freememtop_2--; - s->regoff = rd->freemem_2[rd->freememtop_2]; - } else -#endif /*defined(HAS_4BYTE_STACKSLOT) */ - if ((memneeded == 0) && (rd->freememtop > 0)) { - rd->freememtop--;; - s->regoff = rd->freemem[rd->freememtop]; - } else { -#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) - /* align 2 Word Types */ - if ((memneeded) && ((rd->memuse & 1) == 1)) { - /* Put patched memory slot on freemem */ - rd->freemem[rd->freememtop++] = rd->memuse; - rd->memuse++; - } -#endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */ - s->regoff = rd->memuse; - rd->memuse += memneeded + 1; - } - s->flags |= INMEMORY; -} + /* If the current parameter is a 2-word type, the next local slot */ + /* is skipped. */ + if (p < md->paramcount) + if (IS_2_WORD_TYPE(md->paramtypes[p].type)) + s++; + } + return; + } -#define reg_free_temp(rd,s) if (((s)->varkind == TEMPVAR) && (!((s)->flags & STCOPY))) reg_free_temp_func(rd, (s)) + for (s = 0; s < cd->maxlocals; s++) { + intalloc = -1; fltalloc = -1; + for (tt=0; tt<=4; tt++) { + t = typeloop[tt]; -/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */ -/* alive using this reg/memory location */ + lm = jd->local_map[s * 5 + t]; + if (lm == UNUSED) + continue; -static void reg_free_temp_func(registerdata *rd, stackptr s) -{ - s4 intregsneeded; - s4 memneeded; + v = &(jd->var[lm]); -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; -#else - intregsneeded = 0; +#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS + intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; #endif - #if defined(HAS_4BYTE_STACKSLOT) - memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; -#else - memneeded = 0; + memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; +#endif +#ifdef HAS_ADDRESS_REGISTER_FILE + if ( IS_ADR_TYPE(t) ) { + if (rd->savadrreguse > 0) { + v->flags = 0; + v->regoff = rd->savadrregs[--rd->savadrreguse]; + } + else { + v->flags = INMEMORY; + v->regoff = rd->memuse++; + } + } else { +#endif + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + v->flags = jd->var[fltalloc].flags; + v->regoff = jd->var[fltalloc].regoff; + } + else if (rd->savfltreguse > 0) { + v->flags = 0; + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_DOUBLES_IN_MEMORY) + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + fltalloc = jd->local_map[s * 5 + t]; + } + else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else { #endif + if (intalloc >= 0) { + v->flags = jd->var[intalloc].flags; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(jd->var[intalloc].type)) + v->regoff = GET_LOW_REG( + jd->var[intalloc].regoff); + else +#endif + v->regoff = jd->var[intalloc].regoff; + } + else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded+1; + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + v->regoff =rd->savintregs[rd->savintreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + } +#endif + intalloc = jd->local_map[s * 5 + t]; + } +#ifdef HAS_ADDRESS_REGISTER_FILE + } +#endif + + } + } +} +#else +/* local_regalloc ************************************************************** + + Allocates registers for all local variables. + +*******************************************************************************/ + +static void local_regalloc(jitdata *jd) +{ + methodinfo *m; + codegendata *cd; + registerdata *rd; + + int p, s, t, tt; + int intalloc, fltalloc; + varinfo *v; + int intregsneeded = 0; + int memneeded = 0; + int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR }; + int fargcnt, iargcnt; +#ifdef HAS_ADDRESS_REGISTER_FILE + int aargcnt; +#endif + + /* get required compiler data */ + + m = jd->m; + cd = jd->cd; + rd = jd->rd; + + if (jd->isleafmethod) { + methoddesc *md = m->parseddesc; + + iargcnt = rd->argintreguse; + fargcnt = rd->argfltreguse; +#ifdef HAS_ADDRESS_REGISTER_FILE + aargcnt = rd->argadrreguse; +#endif + for (p = 0, s = 0; s < cd->maxlocals; s++, p++) { + intalloc = -1; fltalloc = -1; + for (tt = 0; tt <= 4; tt++) { + t = typeloop[tt]; + v = &rd->locals[s][t]; + + if (v->type < 0) + continue; + +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; +#endif +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; +#endif + + /* + * The order of + * + * #ifdef HAS_ADDRESS_REGISTER_FILE + * if (IS_ADR_TYPE) { + * ... + * } else + * #endif + * if (IS_FLT_DBL) { + * ... + * } else { / int & lng + * ... + * } + * + * must not to be changed! + */ + +#ifdef HAS_ADDRESS_REGISTER_FILE + if (IS_ADR_TYPE(t)) { + if ((p < md->paramcount) && !md->params[p].inmemory) { + v->flags = 0; + v->regoff = rd->argadrregs[md->params[p].regoff]; + } + else if (rd->tmpadrreguse > 0) { + v->flags = 0; + v->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; + } + /* use unused argument registers as local registers */ + else if ((p >= md->paramcount) && + (aargcnt < ADR_ARG_CNT)) { + v->flags = 0; + v->regoff = rd->argadrregs[aargcnt++]; + } + else if (rd->savadrreguse > 0) { + v->flags = 0; + v->regoff = rd->savadrregs[--rd->savadrreguse]; + } + else { + v->flags |= INMEMORY; + v->regoff = rd->memuse++; + } + } else { +#endif + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + v->flags = rd->locals[s][fltalloc].flags; + v->regoff = rd->locals[s][fltalloc].regoff; + } +#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) + /* We can only use float arguments as local variables, + * if we do not pass them in integer registers. */ + else if ((p < md->paramcount) && + !md->params[p].inmemory) { + v->flags = 0; + v->regoff = rd->argfltregs[md->params[p].regoff]; + } +#endif + else if (rd->tmpfltreguse > 0) { + v->flags = 0; + v->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; + } + /* use unused argument registers as local registers */ + else if ((p >= md->paramcount) && + (fargcnt < FLT_ARG_CNT)) { + v->flags = 0; + v->regoff = rd->argfltregs[fargcnt]; + fargcnt++; + } + else if (rd->savfltreguse > 0) { + v->flags = 0; + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_DOUBLES_IN_MEMORY) + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + fltalloc = t; + + } else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else +#endif + { + if (intalloc >= 0) { + v->flags = rd->locals[s][intalloc].flags; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(intalloc)) + v->regoff = GET_LOW_REG( + rd->locals[s][intalloc].regoff); + else +#endif + v->regoff = rd->locals[s][intalloc].regoff; + } + else if ((p < md->paramcount) && + !md->params[p].inmemory) { + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (IS_2_WORD_TYPE(t)) + v->regoff = PACK_REGS( + rd->argintregs[GET_LOW_REG(md->params[p].regoff)], + rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]); + else +#endif + v->regoff = + rd->argintregs[md->params[p].regoff]; + } + else if (rd->tmpintreguse > intregsneeded) { + rd->tmpintreguse -= intregsneeded + 1; + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->tmpintregs[rd->tmpintreguse], + rd->tmpintregs[rd->tmpintreguse + 1]); + else +#endif + v->regoff = + rd->tmpintregs[rd->tmpintreguse]; + } + /* + * use unused argument registers as local registers + */ + else if ((p >= m->parseddesc->paramcount) && + (iargcnt + intregsneeded < INT_ARG_CNT)) { + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff=PACK_REGS( + rd->argintregs[iargcnt], + rd->argintregs[iargcnt + 1]); + else +#endif + v->regoff = rd->argintregs[iargcnt]; + iargcnt += intregsneeded + 1; + } + else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + v->regoff =rd->savintregs[rd->savintreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + } + intalloc = t; + } +#ifdef HAS_ADDRESS_REGISTER_FILE + } +#endif + } /* for (tt=0;...) */ + + /* If the current parameter is a 2-word type, the next local slot */ + /* is skipped. */ + + if (p < md->paramcount) + if (IS_2_WORD_TYPE(md->paramtypes[p].type)) + s++; + } + return; + } + + for (s = 0; s < cd->maxlocals; s++) { + intalloc = -1; fltalloc = -1; + for (tt=0; tt<=4; tt++) { + t = typeloop[tt]; + v = &rd->locals[s][t]; + + if (v->type >= 0) { +#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS + intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; +#endif +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0; +#endif +#ifdef HAS_ADDRESS_REGISTER_FILE + if ( IS_ADR_TYPE(t) ) { + if (rd->savadrreguse > 0) { + v->flags = 0; + v->regoff = rd->savadrregs[--rd->savadrreguse]; + } + else { + v->flags = INMEMORY; + v->regoff = rd->memuse++; + } + } else { +#endif + if (IS_FLT_DBL_TYPE(t)) { + if (fltalloc >= 0) { + v->flags = rd->locals[s][fltalloc].flags; + v->regoff = rd->locals[s][fltalloc].regoff; + } + else if (rd->savfltreguse > 0) { + v->flags = 0; + v->regoff = rd->savfltregs[--rd->savfltreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_DOUBLES_IN_MEMORY) + /* Align doubles in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + fltalloc = t; + } + else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (IS_2_WORD_TYPE(t)) { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if (rd->memuse & 1) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } else { +#endif + if (intalloc >= 0) { + v->flags = rd->locals[s][intalloc].flags; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (!(v->flags & INMEMORY) + && IS_2_WORD_TYPE(intalloc)) + v->regoff = GET_LOW_REG( + rd->locals[s][intalloc].regoff); + else +#endif + v->regoff = rd->locals[s][intalloc].regoff; + } + else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded+1; + v->flags = 0; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + v->regoff =rd->savintregs[rd->savintreguse]; + } + else { + v->flags = INMEMORY; +#if defined(ALIGN_LONGS_IN_MEMORY) + /* Align longs in Memory */ + if ( (memneeded) && (rd->memuse & 1)) + rd->memuse++; +#endif + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + } +#endif + intalloc = t; + } +#ifdef HAS_ADDRESS_REGISTER_FILE + } +#endif + + } + } + } +} +#endif /* defined(NEW_VAR) */ + +static void reg_init_temp(methodinfo *m, registerdata *rd) +{ + rd->freememtop = 0; +#if defined(HAS_4BYTE_STACKSLOT) + rd->freememtop_2 = 0; +#endif + + rd->freetmpinttop = 0; + rd->freesavinttop = 0; + rd->freetmpflttop = 0; + rd->freesavflttop = 0; +#ifdef HAS_ADDRESS_REGISTER_FILE + rd->freetmpadrtop = 0; + rd->freesavadrtop = 0; +#endif + + rd->freearginttop = 0; + rd->freeargflttop = 0; +#ifdef HAS_ADDRESS_REGISTER_FILE + rd->freeargadrtop = 0; +#endif +} + +#if defined(NEW_VAR) + +#define reg_new_temp(jd,index) \ + if ( (index >= jd->localcount) \ + && (!(jd->var[index].flags & OUTVAR)) \ + && (!(jd->var[index].flags & PREALLOC)) ) \ + reg_new_temp_func(jd, index) + +static void reg_new_temp_func(jitdata *jd, s4 index) +{ + s4 intregsneeded; + s4 memneeded; + s4 tryagain; + registerdata *rd; + varinfo *v; + + rd = jd->rd; + v = &(jd->var[index]); + + /* Try to allocate a saved register if there is no temporary one */ + /* available. This is what happens during the second run. */ + tryagain = (v->flags & SAVEDVAR) ? 1 : 2; + +#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS + intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0; +#else + intregsneeded = 0; +#endif +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0; +#else + memneeded = 0; +#endif + + for(; tryagain; --tryagain) { + if (tryagain == 1) { + if (!(v->flags & SAVEDVAR)) + v->flags |= SAVEDTMP; +#ifdef HAS_ADDRESS_REGISTER_FILE + if (IS_ADR_TYPE(v->type)) { + if (rd->freesavadrtop > 0) { + v->regoff = rd->freesavadrregs[--rd->freesavadrtop]; + return; + } else if (rd->savadrreguse > 0) { + v->regoff = rd->savadrregs[--rd->savadrreguse]; + return; + } + } else +#endif + { + if (IS_FLT_DBL_TYPE(v->type)) { + if (rd->freesavflttop > 0) { + v->regoff = rd->freesavfltregs[--rd->freesavflttop]; + return; + } else if (rd->savfltreguse > 0) { + v->regoff = rd->savfltregs[--rd->savfltreguse]; + return; + } + } else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (!IS_2_WORD_TYPE(v->type)) +#endif + { + if (rd->freesavinttop > intregsneeded) { + rd->freesavinttop -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->freesavintregs[rd->freesavinttop], + rd->freesavintregs[rd->freesavinttop + 1]); + else +#endif + v->regoff = + rd->freesavintregs[rd->freesavinttop]; + return; + } else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + v->regoff = rd->savintregs[rd->savintreguse]; + return; + } + } + } + } + } else { /* tryagain == 2 */ +#ifdef HAS_ADDRESS_REGISTER_FILE + if (IS_ADR_TYPE(v->type)) { + if (rd->freetmpadrtop > 0) { + v->regoff = rd->freetmpadrregs[--rd->freetmpadrtop]; + return; + } else if (rd->tmpadrreguse > 0) { + v->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; + return; + } + } else +#endif + { + if (IS_FLT_DBL_TYPE(v->type)) { + if (rd->freeargflttop > 0) { + v->regoff = rd->freeargfltregs[--rd->freeargflttop]; + v->flags |= TMPARG; + return; + } else if (rd->argfltreguse < FLT_ARG_CNT) { + v->regoff = rd->argfltregs[rd->argfltreguse++]; + v->flags |= TMPARG; + return; + } else if (rd->freetmpflttop > 0) { + v->regoff = rd->freetmpfltregs[--rd->freetmpflttop]; + return; + } else if (rd->tmpfltreguse > 0) { + v->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; + return; + } + + } else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (!IS_2_WORD_TYPE(v->type)) +#endif + { + if (rd->freearginttop > intregsneeded) { + rd->freearginttop -= intregsneeded + 1; + v->flags |= TMPARG; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->freeargintregs[rd->freearginttop], + rd->freeargintregs[rd->freearginttop + 1]); + else +#endif + v->regoff = + rd->freeargintregs[rd->freearginttop]; + return; + } else if (rd->argintreguse + < INT_ARG_CNT - intregsneeded) { +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->argintregs[rd->argintreguse], + rd->argintregs[rd->argintreguse + 1]); + else +#endif + v->regoff = rd->argintregs[rd->argintreguse]; + v->flags |= TMPARG; + rd->argintreguse += intregsneeded + 1; + return; + } else if (rd->freetmpinttop > intregsneeded) { + rd->freetmpinttop -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->freetmpintregs[rd->freetmpinttop], + rd->freetmpintregs[rd->freetmpinttop + 1]); + else +#endif + v->regoff = rd->freetmpintregs[rd->freetmpinttop]; + return; + } else if (rd->tmpintreguse > intregsneeded) { + rd->tmpintreguse -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + v->regoff = PACK_REGS( + rd->tmpintregs[rd->tmpintreguse], + rd->tmpintregs[rd->tmpintreguse + 1]); + else +#endif + v->regoff = rd->tmpintregs[rd->tmpintreguse]; + return; + } + } /* if (!IS_2_WORD_TYPE(s->type)) */ + } /* if (IS_FLT_DBL_TYPE(s->type)) */ + } /* if (IS_ADR_TYPE(s->type)) */ + } /* if (tryagain == 1) else */ + } /* for(; tryagain; --tryagain) */ + +#if defined(HAS_4BYTE_STACKSLOT) + if ((memneeded == 1) && (rd->freememtop_2 > 0)) { + rd->freememtop_2--; + v->regoff = rd->freemem_2[rd->freememtop_2]; + } else +#endif /*defined(HAS_4BYTE_STACKSLOT) */ + if ((memneeded == 0) && (rd->freememtop > 0)) { + rd->freememtop--;; + v->regoff = rd->freemem[rd->freememtop]; + } else { +#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) + /* align 2 Word Types */ + if ((memneeded) && ((rd->memuse & 1) == 1)) { + /* Put patched memory slot on freemem */ + rd->freemem[rd->freememtop++] = rd->memuse; + rd->memuse++; + } +#endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */ + v->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + v->flags |= INMEMORY; +} +#else +#define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s) + +static void reg_new_temp_func(registerdata *rd, stackptr s) +{ + s4 intregsneeded; + s4 memneeded; + s4 tryagain; + + /* Try to allocate a saved register if there is no temporary one */ + /* available. This is what happens during the second run. */ + tryagain = (s->flags & SAVEDVAR) ? 1 : 2; + +#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS + intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; +#else + intregsneeded = 0; +#endif +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; +#else + memneeded = 0; +#endif + + for(; tryagain; --tryagain) { + if (tryagain == 1) { + if (!(s->flags & SAVEDVAR)) + s->flags |= SAVEDTMP; +#ifdef HAS_ADDRESS_REGISTER_FILE + if (IS_ADR_TYPE(s->type)) { + if (rd->freesavadrtop > 0) { + s->regoff = rd->freesavadrregs[--rd->freesavadrtop]; + return; + } else if (rd->savadrreguse > 0) { + s->regoff = rd->savadrregs[--rd->savadrreguse]; + return; + } + } else +#endif + { + if (IS_FLT_DBL_TYPE(s->type)) { + if (rd->freesavflttop > 0) { + s->regoff = rd->freesavfltregs[--rd->freesavflttop]; + return; + } else if (rd->savfltreguse > 0) { + s->regoff = rd->savfltregs[--rd->savfltreguse]; + return; + } + } else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (!IS_2_WORD_TYPE(s->type)) +#endif + { + if (rd->freesavinttop > intregsneeded) { + rd->freesavinttop -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->freesavintregs[rd->freesavinttop], + rd->freesavintregs[rd->freesavinttop + 1]); + else +#endif + s->regoff = + rd->freesavintregs[rd->freesavinttop]; + return; + } else if (rd->savintreguse > intregsneeded) { + rd->savintreguse -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->savintregs[rd->savintreguse], + rd->savintregs[rd->savintreguse + 1]); + else +#endif + s->regoff = rd->savintregs[rd->savintreguse]; + return; + } + } + } + } + } else { /* tryagain == 2 */ +#ifdef HAS_ADDRESS_REGISTER_FILE + if (IS_ADR_TYPE(s->type)) { + if (rd->freetmpadrtop > 0) { + s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop]; + return; + } else if (rd->tmpadrreguse > 0) { + s->regoff = rd->tmpadrregs[--rd->tmpadrreguse]; + return; + } + } else +#endif + { + if (IS_FLT_DBL_TYPE(s->type)) { + if (rd->freeargflttop > 0) { + s->regoff = rd->freeargfltregs[--rd->freeargflttop]; + s->flags |= TMPARG; + return; + } else if (rd->argfltreguse < FLT_ARG_CNT) { + s->regoff = rd->argfltregs[rd->argfltreguse++]; + s->flags |= TMPARG; + return; + } else if (rd->freetmpflttop > 0) { + s->regoff = rd->freetmpfltregs[--rd->freetmpflttop]; + return; + } else if (rd->tmpfltreguse > 0) { + s->regoff = rd->tmpfltregs[--rd->tmpfltreguse]; + return; + } + + } else { +#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + /* + * for i386 put all longs in memory + */ + if (!IS_2_WORD_TYPE(s->type)) +#endif + { + if (rd->freearginttop > intregsneeded) { + rd->freearginttop -= intregsneeded + 1; + s->flags |= TMPARG; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->freeargintregs[rd->freearginttop], + rd->freeargintregs[rd->freearginttop + 1]); + else +#endif + s->regoff = + rd->freeargintregs[rd->freearginttop]; + return; + } else if (rd->argintreguse + < INT_ARG_CNT - intregsneeded) { +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->argintregs[rd->argintreguse], + rd->argintregs[rd->argintreguse + 1]); + else +#endif + s->regoff = rd->argintregs[rd->argintreguse]; + s->flags |= TMPARG; + rd->argintreguse += intregsneeded + 1; + return; + } else if (rd->freetmpinttop > intregsneeded) { + rd->freetmpinttop -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->freetmpintregs[rd->freetmpinttop], + rd->freetmpintregs[rd->freetmpinttop + 1]); + else +#endif + s->regoff = rd->freetmpintregs[rd->freetmpinttop]; + return; + } else if (rd->tmpintreguse > intregsneeded) { + rd->tmpintreguse -= intregsneeded + 1; +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) + s->regoff = PACK_REGS( + rd->tmpintregs[rd->tmpintreguse], + rd->tmpintregs[rd->tmpintreguse + 1]); + else +#endif + s->regoff = rd->tmpintregs[rd->tmpintreguse]; + return; + } + } /* if (!IS_2_WORD_TYPE(s->type)) */ + } /* if (IS_FLT_DBL_TYPE(s->type)) */ + } /* if (IS_ADR_TYPE(s->type)) */ + } /* if (tryagain == 1) else */ + } /* for(; tryagain; --tryagain) */ + +#if defined(HAS_4BYTE_STACKSLOT) + if ((memneeded == 1) && (rd->freememtop_2 > 0)) { + rd->freememtop_2--; + s->regoff = rd->freemem_2[rd->freememtop_2]; + } else +#endif /*defined(HAS_4BYTE_STACKSLOT) */ + if ((memneeded == 0) && (rd->freememtop > 0)) { + rd->freememtop--;; + s->regoff = rd->freemem[rd->freememtop]; + } else { +#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) + /* align 2 Word Types */ + if ((memneeded) && ((rd->memuse & 1) == 1)) { + /* Put patched memory slot on freemem */ + rd->freemem[rd->freememtop++] = rd->memuse; + rd->memuse++; + } +#endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */ + s->regoff = rd->memuse; + rd->memuse += memneeded + 1; + } + s->flags |= INMEMORY; +} +#endif + +#if defined(NEW_VAR) +#define reg_free_temp(jd,index) \ + if ((index > jd->localcount) \ + && (!(jd->var[index].flags & OUTVAR)) \ + && (!(jd->var[index].flags & STCOPY)) \ + && (!(jd->var[index].flags & PREALLOC)) ) \ + reg_free_temp_func(jd, index) + +/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */ +/* alive using this reg/memory location */ + +static void reg_free_temp_func(jitdata *jd, s4 index) +{ + s4 intregsneeded; + s4 memneeded; + registerdata *rd; + varinfo *v; + + rd = jd->rd; + v = &(jd->var[index]); + + +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0; +#else + intregsneeded = 0; +#endif + +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0; +#else + memneeded = 0; +#endif + + if (v->flags & INMEMORY) { +#if defined(HAS_4BYTE_STACKSLOT) + if (memneeded > 0) { + rd->freemem_2[rd->freememtop_2] = v->regoff; + rd->freememtop_2++; + } else +#endif + { + rd->freemem[rd->freememtop] = v->regoff; + rd->freememtop++; + } + +#ifdef HAS_ADDRESS_REGISTER_FILE + } else if (IS_ADR_TYPE(v->type)) { + if (v->flags & (SAVEDVAR | SAVEDTMP)) { +/* v->flags &= ~SAVEDTMP; */ + rd->freesavadrregs[rd->freesavadrtop++] = v->regoff; + } else + rd->freetmpadrregs[rd->freetmpadrtop++] = v->regoff; +#endif + } else if (IS_FLT_DBL_TYPE(v->type)) { + if (v->flags & (SAVEDVAR | SAVEDTMP)) { +/* v->flags &= ~SAVEDTMP; */ + rd->freesavfltregs[rd->freesavflttop++] = v->regoff; + } else if (v->flags & TMPARG) { +/* v->flags &= ~TMPARG; */ + rd->freeargfltregs[rd->freeargflttop++] = v->regoff; + } else + rd->freetmpfltregs[rd->freetmpflttop++] = v->regoff; + } else { /* IS_INT_LNG_TYPE */ + if (v->flags & (SAVEDVAR | SAVEDTMP)) { +/* v->flags &= ~SAVEDTMP; */ +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freesavintregs[rd->freesavinttop] = + GET_LOW_REG(v->regoff); + rd->freesavintregs[rd->freesavinttop + 1] = + GET_HIGH_REG(v->regoff); + } else +#endif + rd->freesavintregs[rd->freesavinttop] = v->regoff; + rd->freesavinttop += intregsneeded + 1; + + } else if (v->flags & TMPARG) { +/* s->flags &= ~TMPARG; */ +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freeargintregs[rd->freearginttop] = + GET_LOW_REG(v->regoff); + rd->freeargintregs[rd->freearginttop + 1] = + GET_HIGH_REG(v->regoff); + } else +#endif + rd->freeargintregs[rd->freearginttop] = v->regoff; + rd->freearginttop += intregsneeded + 1; + } else { +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freetmpintregs[rd->freetmpinttop] = + GET_LOW_REG(s->regoff); + rd->freetmpintregs[rd->freetmpinttop + 1] = + GET_HIGH_REG(s->regoff); + } else +#endif + rd->freetmpintregs[rd->freetmpinttop] = v->regoff; + rd->freetmpinttop += intregsneeded + 1; + } + } +} + +#else +#define reg_free_temp(rd,s) if (((s)->varkind == TEMPVAR) && (!((s)->flags & STCOPY))) reg_free_temp_func(rd, (s)) + +/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */ +/* alive using this reg/memory location */ + +static void reg_free_temp_func(registerdata *rd, stackptr s) +{ + s4 intregsneeded; + s4 memneeded; + +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; +#else + intregsneeded = 0; +#endif + +#if defined(HAS_4BYTE_STACKSLOT) + memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0; +#else + memneeded = 0; +#endif + + if (s->flags & INMEMORY) { +#if defined(HAS_4BYTE_STACKSLOT) + if (memneeded > 0) { + rd->freemem_2[rd->freememtop_2] = s->regoff; + rd->freememtop_2++; + } else +#endif + { + rd->freemem[rd->freememtop] = s->regoff; + rd->freememtop++; + } + +#ifdef HAS_ADDRESS_REGISTER_FILE + } else if (IS_ADR_TYPE(s->type)) { + if (s->flags & (SAVEDVAR | SAVEDTMP)) { +/* s->flags &= ~SAVEDTMP; */ + rd->freesavadrregs[rd->freesavadrtop++] = s->regoff; + } else + rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff; +#endif + } else if (IS_FLT_DBL_TYPE(s->type)) { + if (s->flags & (SAVEDVAR | SAVEDTMP)) { +/* s->flags &= ~SAVEDTMP; */ + rd->freesavfltregs[rd->freesavflttop++] = s->regoff; + } else if (s->flags & TMPARG) { +/* s->flags &= ~TMPARG; */ + rd->freeargfltregs[rd->freeargflttop++] = s->regoff; + } else + rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff; + } else { /* IS_INT_LNG_TYPE */ + if (s->flags & (SAVEDVAR | SAVEDTMP)) { +/* s->flags &= ~SAVEDTMP; */ +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freesavintregs[rd->freesavinttop] = + GET_LOW_REG(s->regoff); + rd->freesavintregs[rd->freesavinttop + 1] = + GET_HIGH_REG(s->regoff); + } else +#endif + rd->freesavintregs[rd->freesavinttop] = s->regoff; + rd->freesavinttop += intregsneeded + 1; + + } else if (s->flags & TMPARG) { +/* s->flags &= ~TMPARG; */ +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freeargintregs[rd->freearginttop] = + GET_LOW_REG(s->regoff); + rd->freeargintregs[rd->freearginttop + 1] = + GET_HIGH_REG(s->regoff); + } else +#endif + rd->freeargintregs[rd->freearginttop] = s->regoff; + rd->freearginttop += intregsneeded + 1; + } else { +#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) + if (intregsneeded) { + rd->freetmpintregs[rd->freetmpinttop] = + GET_LOW_REG(s->regoff); + rd->freetmpintregs[rd->freetmpinttop + 1] = + GET_HIGH_REG(s->regoff); + } else +#endif + rd->freetmpintregs[rd->freetmpinttop] = s->regoff; + rd->freetmpinttop += intregsneeded + 1; + } + } +} + +#endif + +#if !defined(NEW_VAR) +static bool reg_alloc_dup(stackptr src, stackptr dst) { + /* only copy TEMPVARS, do not mess with STACKVAR, */ + /* LOCALVAR, or ARGVAR */ + if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) { + /* can not allocate a REG_TMP to a REG_SAV Slot */ + if (src->flags & INMEMORY) { + dst->regoff = src->regoff; + dst->flags |= INMEMORY; + return true; + } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) { + dst->regoff = src->regoff; + dst->flags |= src->flags & SAVEDTMP; + dst->flags |= src->flags & TMPARG; + return true; +#if 0 + } else if ((dst->flags & SAVEDVAR) == 0) { + /* can only use a REG_SAV as REG_TMP! */ + dst->regoff = src->regoff; + dst->flags |= src->flags & TMPARG; + dst->flags |= SAVEDTMP; + return true; +#endif + } + } + /* no copy possible - allocate a new reg/memory location*/ + return false; +} + + +/* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */ +static void new_reg_mark_copy(registerdata *rd, stackptr *dupslots, + int nin, int nout, int nthrough) +{ + s4 src_regoff[4]; + s4 src_flags[4]; + stackptr dst_stackslots[6]; + int s_bottom, d_bottom, i, j, slots; + bool found; + stackptr sp; + stackptr *argp; + registerdata *rd; + + rd = jd->rd; + + assert(nin <= 4 && (nout + nthrough) <= 6); + + /* remember all different Registers/Memory Location of used TEMPVAR */ + /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */ + /* flag of the last (deepest) occurence */ + slots = nin; + argp = dupslots + slots; + for (s_bottom = 4; slots--; ) { + sp = *--argp; + if (sp->varkind == TEMPVAR) { + found = false; + for (i = 3; i >= s_bottom; i--) { + if ((src_regoff[i] == sp->regoff) && + ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) + { + src_flags[i] &= (~STCOPY | (sp->flags & STCOPY)); + found = true; + } + } + if (!found) { + s_bottom--; + src_regoff[s_bottom] = sp->regoff; + src_flags[s_bottom] = sp->flags; + } + } + } + + /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */ + /* have to be from the "lowest" upwards, and the stackelements list is */ + /* linked from only top downwards */ + + slots = nthrough + nout; + argp = dupslots + nin + nout; + for (d_bottom = 6; slots--; ) { + sp = *--argp; + if (sp->varkind == TEMPVAR) { + d_bottom--; + dst_stackslots[d_bottom] = sp; + } + } + + /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */ + /* corresponding src stackslot was marked STCOPY*/ + /* if the correspondig STCOPY from the src stackslot was not set, do not */ + /* mark the lowest occurence at dst stackslots */ + /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */ + /* stacklots, so they are not freed afterwards */ + for (i = d_bottom; i < 6; i++) { + for (j = s_bottom; j < 4; j++) { + if ( (src_regoff[j] == dst_stackslots[i]->regoff) && + ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) + { + if (src_flags[j] & STCOPY) { + dst_stackslots[i]->flags |= STCOPY; + } + else { + src_flags[j] |= STCOPY; + dst_stackslots[i]->flags &= ~STCOPY; + } + /* do not free reg/mem of src Stackslot */ + src_flags[j] |= STKEEP; + } + } + } + + /* free all reg/mem of src stack, which where not marked with STKEEP */ + for (j=s_bottom; j < 4; j++) { + if ((src_flags[j] & STKEEP)==0) { + /* free, if STCOPY of src stackslot is not set */ + /* STCOPY is already checked in reg_free_temp macro! */ + slots = nin; + argp = dupslots + slots; + while (--slots) { + sp = *--argp; + if ((src_regoff[j] == sp->regoff) && + ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) + { + reg_free_temp(rd, sp); + } + } + } + } +} +#endif + +#if defined(NEW_VAR) +/* allocate_scratch_registers ************************************************** + + Allocate temporary (non-interface, non-local) registers. + +*******************************************************************************/ + +static void new_allocate_scratch_registers(jitdata *jd) +{ + methodinfo *m; + registerdata *rd; + s4 i; + s4 len; + instruction *iptr; + basicblock *bptr; + builtintable_entry *bte; + methoddesc *md; + s4 *argp; + + /* get required compiler data */ + + m = jd->m; + rd = jd->rd; + + /* initialize temp registers */ + + reg_init_temp(m, rd); + + bptr = jd->new_basicblocks; + + while (bptr != NULL) { + if (bptr->flags >= BBREACHED) { + iptr = bptr->iinstr; + len = bptr->icount; + + while (--len >= 0) { + switch (iptr->opc) { + + /* pop 0 push 0 */ + + case ICMD_NOP: + case ICMD_CHECKNULL: + case ICMD_IINC: + case ICMD_JSR: + case ICMD_RET: + case ICMD_RETURN: + case ICMD_GOTO: + case ICMD_PUTSTATICCONST: + case ICMD_INLINE_START: + case ICMD_INLINE_END: + case ICMD_INLINE_GOTO: + break; + + /* pop 0 push 1 const */ + + case ICMD_ICONST: + case ICMD_LCONST: + case ICMD_FCONST: + case ICMD_DCONST: + case ICMD_ACONST: + + /* pop 0 push 1 load */ + + case ICMD_ILOAD: + case ICMD_LLOAD: + case ICMD_FLOAD: + case ICMD_DLOAD: + case ICMD_ALOAD: + reg_new_temp(jd, iptr->dst.varindex); + break; + + /* pop 2 push 1 */ + + case ICMD_IALOAD: + case ICMD_LALOAD: + case ICMD_FALOAD: + case ICMD_DALOAD: + case ICMD_AALOAD: + + case ICMD_BALOAD: + case ICMD_CALOAD: + case ICMD_SALOAD: + reg_free_temp(jd, iptr->sx.s23.s2.varindex); + reg_free_temp(jd, iptr->s1.varindex); + reg_new_temp(jd, iptr->dst.varindex); + break; + + /* pop 3 push 0 */ + + case ICMD_IASTORE: + case ICMD_LASTORE: + case ICMD_FASTORE: + case ICMD_DASTORE: + case ICMD_AASTORE: + + case ICMD_BASTORE: + case ICMD_CASTORE: + case ICMD_SASTORE: + reg_free_temp(jd, iptr->sx.s23.s3.varindex); + reg_free_temp(jd, iptr->sx.s23.s2.varindex); + reg_free_temp(jd, iptr->s1.varindex); + break; + + /* pop 1 push 0 store */ + + case ICMD_ISTORE: + case ICMD_LSTORE: + case ICMD_FSTORE: + case ICMD_DSTORE: + case ICMD_ASTORE: + + /* pop 1 push 0 */ + + case ICMD_POP: + + case ICMD_IRETURN: + case ICMD_LRETURN: + case ICMD_FRETURN: + case ICMD_DRETURN: + case ICMD_ARETURN: + + case ICMD_ATHROW: + + case ICMD_PUTSTATIC: + case ICMD_PUTFIELDCONST: + + /* pop 1 push 0 branch */ + + case ICMD_IFNULL: + case ICMD_IFNONNULL: + + case ICMD_IFEQ: + case ICMD_IFNE: + case ICMD_IFLT: + case ICMD_IFGE: + case ICMD_IFGT: + case ICMD_IFLE: + + case ICMD_IF_LEQ: + case ICMD_IF_LNE: + case ICMD_IF_LLT: + case ICMD_IF_LGE: + case ICMD_IF_LGT: + case ICMD_IF_LLE: + + /* pop 1 push 0 table branch */ + + case ICMD_TABLESWITCH: + case ICMD_LOOKUPSWITCH: + + case ICMD_MONITORENTER: + case ICMD_MONITOREXIT: + reg_free_temp(jd, iptr->s1.varindex); + break; + + /* pop 2 push 0 branch */ + + case ICMD_IF_ICMPEQ: + case ICMD_IF_ICMPNE: + case ICMD_IF_ICMPLT: + case ICMD_IF_ICMPGE: + case ICMD_IF_ICMPGT: + case ICMD_IF_ICMPLE: + + case ICMD_IF_LCMPEQ: + case ICMD_IF_LCMPNE: + case ICMD_IF_LCMPLT: + case ICMD_IF_LCMPGE: + case ICMD_IF_LCMPGT: + case ICMD_IF_LCMPLE: + + case ICMD_IF_FCMPEQ: + case ICMD_IF_FCMPNE: + + case ICMD_IF_FCMPL_LT: + case ICMD_IF_FCMPL_GE: + case ICMD_IF_FCMPL_GT: + case ICMD_IF_FCMPL_LE: + + case ICMD_IF_FCMPG_LT: + case ICMD_IF_FCMPG_GE: + case ICMD_IF_FCMPG_GT: + case ICMD_IF_FCMPG_LE: + + case ICMD_IF_DCMPEQ: + case ICMD_IF_DCMPNE: + + case ICMD_IF_DCMPL_LT: + case ICMD_IF_DCMPL_GE: + case ICMD_IF_DCMPL_GT: + case ICMD_IF_DCMPL_LE: + + case ICMD_IF_DCMPG_LT: + case ICMD_IF_DCMPG_GE: + case ICMD_IF_DCMPG_GT: + case ICMD_IF_DCMPG_LE: + + case ICMD_IF_ACMPEQ: + case ICMD_IF_ACMPNE: + + /* pop 2 push 0 */ + + case ICMD_POP2: + + case ICMD_PUTFIELD: + + case ICMD_IASTORECONST: + case ICMD_LASTORECONST: + case ICMD_AASTORECONST: + case ICMD_BASTORECONST: + case ICMD_CASTORECONST: + case ICMD_SASTORECONST: + reg_free_temp(jd, iptr->sx.s23.s2.varindex); + reg_free_temp(jd, iptr->s1.varindex); + break; + + /* pop 0 push 1 dup */ + + case ICMD_DUP: + /* src === dst->prev (identical Stackslot Element) */ + /* src --> dst (copied value, take same reg/mem) */ + +/* if (!reg_alloc_dup(iptr->s1.varindex, iptr->dst.varindex)) { */ + reg_new_temp(jd, iptr->dst.varindex); +/* } else { */ +/* iptr->dst.varindex->flags |= STCOPY; */ +/* } */ + break; + + /* pop 0 push 2 dup */ + + case ICMD_DUP2: + /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */ + /* src === dst->prev->prev (identical Stackslot Element) */ + /* src->prev --> dst->prev (copied value, take same reg/mem) */ + /* src --> dst (copied value, take same reg/mem) */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+1]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 2); */ + break; + + /* pop 2 push 3 dup */ + + case ICMD_DUP_X1: + /* src->prev --> dst->prev (copied value, take same reg/mem) */ + /* src --> dst (copied value, take same reg/mem) */ + /* src --> dst->prev->prev (copied value, take same reg/mem) */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+2])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+2]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+1]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 3, 0); */ + break; + + /* pop 3 push 4 dup */ + + case ICMD_DUP_X2: + /* src->prev->prev --> dst->prev->prev */ + /* src->prev --> dst->prev */ + /* src --> dst */ + /* src --> dst->prev->prev->prev */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+3])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+3]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+2])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+2]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+1]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 4, 0); */ + break; + + /* pop 3 push 5 dup */ + + case ICMD_DUP2_X1: + /* src->prev->prev --> dst->prev->prev */ + /* src->prev --> dst->prev */ + /* src --> dst */ + /* src->prev --> dst->prev->prev->prev->prev */ + /* src --> dst->prev->prev->prev */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+1]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+4])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+4]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+3])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+3]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+2])) */ + reg_new_temp(jd, iptr->dst.dupslots[3+2]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 5, 0); */ + break; + + /* pop 4 push 6 dup */ + + case ICMD_DUP2_X2: + /* src->prev->prev->prev --> dst->prev->prev->prev */ + /* src->prev->prev --> dst->prev->prev */ + /* src->prev --> dst->prev */ + /* src --> dst */ + /* src->prev --> dst->prev->prev->prev->prev->prev */ + /* src --> dst->prev->prev->prev->prev */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+1]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+5])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+5]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+4])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+4]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[4+3])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+3]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[4+2])) */ + reg_new_temp(jd, iptr->dst.dupslots[4+2]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 4, 6, 0); */ + break; + + /* pop 2 push 2 swap */ + + case ICMD_SWAP: + /* src --> dst->prev (copy) */ + /* src->prev --> dst (copy) */ + +/* if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+0]); +/* if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1])) */ + reg_new_temp(jd, iptr->dst.dupslots[2+1]); +/* new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 0); */ + break; + + /* pop 2 push 1 */ + + case ICMD_IADD: + case ICMD_ISUB: + case ICMD_IMUL: + case ICMD_IDIV: + case ICMD_IREM: + + case ICMD_ISHL: + case ICMD_ISHR: + case ICMD_IUSHR: + case ICMD_IAND: + case ICMD_IOR: + case ICMD_IXOR: + + case ICMD_LADD: + case ICMD_LSUB: + case ICMD_LMUL: + case ICMD_LDIV: + case ICMD_LREM: + + case ICMD_LOR: + case ICMD_LAND: + case ICMD_LXOR: + + case ICMD_LSHL: + case ICMD_LSHR: + case ICMD_LUSHR: + + case ICMD_FADD: + case ICMD_FSUB: + case ICMD_FMUL: + case ICMD_FDIV: + case ICMD_FREM: + + case ICMD_DADD: + case ICMD_DSUB: + case ICMD_DMUL: + case ICMD_DDIV: + case ICMD_DREM: + + case ICMD_LCMP: + case ICMD_FCMPL: + case ICMD_FCMPG: + case ICMD_DCMPL: + case ICMD_DCMPG: + reg_free_temp(jd, iptr->sx.s23.s2.varindex); + reg_free_temp(jd, iptr->s1.varindex); + reg_new_temp(jd, iptr->dst.varindex); + break; + + /* pop 1 push 1 */ + + case ICMD_IADDCONST: + case ICMD_ISUBCONST: + case ICMD_IMULCONST: + case ICMD_IMULPOW2: + case ICMD_IDIVPOW2: + case ICMD_IREMPOW2: + case ICMD_IANDCONST: + case ICMD_IORCONST: + case ICMD_IXORCONST: + case ICMD_ISHLCONST: + case ICMD_ISHRCONST: + case ICMD_IUSHRCONST: + + case ICMD_LADDCONST: + case ICMD_LSUBCONST: + case ICMD_LMULCONST: + case ICMD_LMULPOW2: + case ICMD_LDIVPOW2: + case ICMD_LREMPOW2: + case ICMD_LANDCONST: + case ICMD_LORCONST: + case ICMD_LXORCONST: + case ICMD_LSHLCONST: + case ICMD_LSHRCONST: + case ICMD_LUSHRCONST: + + case ICMD_INEG: + case ICMD_INT2BYTE: + case ICMD_INT2CHAR: + case ICMD_INT2SHORT: + case ICMD_LNEG: + case ICMD_FNEG: + case ICMD_DNEG: - if (s->flags & INMEMORY) { -#if defined(HAS_4BYTE_STACKSLOT) - if (memneeded > 0) { - rd->freemem_2[rd->freememtop_2] = s->regoff; - rd->freememtop_2++; - } else -#endif - { - rd->freemem[rd->freememtop] = s->regoff; - rd->freememtop++; - } + case ICMD_I2L: + case ICMD_I2F: + case ICMD_I2D: + case ICMD_L2I: + case ICMD_L2F: + case ICMD_L2D: + case ICMD_F2I: + case ICMD_F2L: + case ICMD_F2D: + case ICMD_D2I: + case ICMD_D2L: + case ICMD_D2F: -#ifdef HAS_ADDRESS_REGISTER_FILE - } else if (IS_ADR_TYPE(s->type)) { - if (s->flags & (SAVEDVAR | SAVEDTMP)) { -/* s->flags &= ~SAVEDTMP; */ - rd->freesavadrregs[rd->freesavadrtop++] = s->regoff; - } else - rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff; -#endif - } else if (IS_FLT_DBL_TYPE(s->type)) { - if (s->flags & (SAVEDVAR | SAVEDTMP)) { -/* s->flags &= ~SAVEDTMP; */ - rd->freesavfltregs[rd->freesavflttop++] = s->regoff; - } else if (s->flags & TMPARG) { -/* s->flags &= ~TMPARG; */ - rd->freeargfltregs[rd->freeargflttop++] = s->regoff; - } else - rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff; - } else { /* IS_INT_LNG_TYPE */ - if (s->flags & (SAVEDVAR | SAVEDTMP)) { -/* s->flags &= ~SAVEDTMP; */ -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) { - rd->freesavintregs[rd->freesavinttop] = - GET_LOW_REG(s->regoff); - rd->freesavintregs[rd->freesavinttop + 1] = - GET_HIGH_REG(s->regoff); - } else -#endif - rd->freesavintregs[rd->freesavinttop] = s->regoff; - rd->freesavinttop += intregsneeded + 1; + case ICMD_CHECKCAST: - } else if (s->flags & TMPARG) { -/* s->flags &= ~TMPARG; */ -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) { - rd->freeargintregs[rd->freearginttop] = - GET_LOW_REG(s->regoff); - rd->freeargintregs[rd->freearginttop + 1] = - GET_HIGH_REG(s->regoff); - } else -#endif - rd->freeargintregs[rd->freearginttop] = s->regoff; - rd->freearginttop += intregsneeded + 1; - } else { -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (intregsneeded) { - rd->freetmpintregs[rd->freetmpinttop] = - GET_LOW_REG(s->regoff); - rd->freetmpintregs[rd->freetmpinttop + 1] = - GET_HIGH_REG(s->regoff); - } else -#endif - rd->freetmpintregs[rd->freetmpinttop] = s->regoff; - rd->freetmpinttop += intregsneeded + 1; - } - } -} + case ICMD_ARRAYLENGTH: + case ICMD_INSTANCEOF: -static bool reg_alloc_dup(stackptr src, stackptr dst) { - /* only copy TEMPVARS, do not mess with STACKVAR, */ - /* LOCALVAR, or ARGVAR */ - if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) { - /* can not allocate a REG_TMP to a REG_SAV Slot */ - if (src->flags & INMEMORY) { - dst->regoff = src->regoff; - dst->flags |= INMEMORY; - return true; - } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) { - dst->regoff = src->regoff; - dst->flags |= src->flags & SAVEDTMP; - dst->flags |= src->flags & TMPARG; - return true; -#if 0 - } else if ((dst->flags & SAVEDVAR) == 0) { - /* can only use a REG_SAV as REG_TMP! */ - dst->regoff = src->regoff; - dst->flags |= src->flags & TMPARG; - dst->flags |= SAVEDTMP; - return true; -#endif - } - } - /* no copy possible - allocate a new reg/memory location*/ - return false; -} + case ICMD_NEWARRAY: + case ICMD_ANEWARRAY: -/* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */ -static void new_reg_mark_copy(registerdata *rd, stackptr *dupslots, - int nin, int nout, int nthrough) -{ - s4 src_regoff[4]; - s4 src_flags[4]; - stackptr dst_stackslots[6]; - int s_bottom, d_bottom, i, j, slots; - bool found; - stackptr sp; - stackptr *argp; + case ICMD_GETFIELD: + reg_free_temp(jd, iptr->s1.varindex); + reg_new_temp(jd, iptr->dst.varindex); + break; - assert(nin <= 4 && (nout + nthrough) <= 6); + /* pop 0 push 1 */ + + case ICMD_GETSTATIC: - /* remember all different Registers/Memory Location of used TEMPVAR */ - /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */ - /* flag of the last (deepest) occurence */ - slots = nin; - argp = dupslots + slots; - for (s_bottom = 4; slots--; ) { - sp = *--argp; - if (sp->varkind == TEMPVAR) { - found = false; - for (i = 3; i >= s_bottom; i--) { - if ((src_regoff[i] == sp->regoff) && - ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) - { - src_flags[i] &= (~STCOPY | (sp->flags & STCOPY)); - found = true; - } - } - if (!found) { - s_bottom--; - src_regoff[s_bottom] = sp->regoff; - src_flags[s_bottom] = sp->flags; - } - } - } + case ICMD_NEW: + reg_new_temp(jd, iptr->dst.varindex); + break; - /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */ - /* have to be from the "lowest" upwards, and the stackelements list is */ - /* linked from only top downwards */ - - slots = nthrough + nout; - argp = dupslots + nin + nout; - for (d_bottom = 6; slots--; ) { - sp = *--argp; - if (sp->varkind == TEMPVAR) { - d_bottom--; - dst_stackslots[d_bottom] = sp; - } - } + /* pop many push any */ + + case ICMD_INVOKESTATIC: + case ICMD_INVOKESPECIAL: + case ICMD_INVOKEVIRTUAL: + case ICMD_INVOKEINTERFACE: + INSTRUCTION_GET_METHODDESC(iptr,md); + i = md->paramcount; + argp = iptr->sx.s23.s2.args; + while (--i >= 0) { + reg_free_temp(jd, *argp); + argp++; + } + if (md->returntype.type != TYPE_VOID) + reg_new_temp(jd, iptr->dst.varindex); + break; - /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */ - /* corresponding src stackslot was marked STCOPY*/ - /* if the correspondig STCOPY from the src stackslot was not set, do not */ - /* mark the lowest occurence at dst stackslots */ - /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */ - /* stacklots, so they are not freed afterwards */ - for (i = d_bottom; i < 6; i++) { - for (j = s_bottom; j < 4; j++) { - if ( (src_regoff[j] == dst_stackslots[i]->regoff) && - ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) - { - if (src_flags[j] & STCOPY) { - dst_stackslots[i]->flags |= STCOPY; - } - else { - src_flags[j] |= STCOPY; - dst_stackslots[i]->flags &= ~STCOPY; - } - /* do not free reg/mem of src Stackslot */ - src_flags[j] |= STKEEP; - } - } - } + case ICMD_BUILTIN: + bte = iptr->sx.s23.s3.bte; + md = bte->md; + i = md->paramcount; + argp = iptr->sx.s23.s2.args; + while (--i >= 0) { + reg_free_temp(jd, *argp); + argp++; + } + if (md->returntype.type != TYPE_VOID) + reg_new_temp(jd, iptr->dst.varindex); + break; - /* free all reg/mem of src stack, which where not marked with STKEEP */ - for (j=s_bottom; j < 4; j++) { - if ((src_flags[j] & STKEEP)==0) { - /* free, if STCOPY of src stackslot is not set */ - /* STCOPY is already checked in reg_free_temp macro! */ - slots = nin; - argp = dupslots + slots; - while (--slots) { - sp = *--argp; - if ((src_regoff[j] == sp->regoff) && - ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) - { - reg_free_temp(rd, sp); - } - } - } - } -} + case ICMD_MULTIANEWARRAY: + i = iptr->s1.argcount; + argp = iptr->sx.s23.s2.args; + while (--i >= 0) { + reg_free_temp(jd, *argp); + argp++; + } + reg_new_temp(jd, iptr->dst.varindex); + break; + default: + *exceptionptr = + new_internalerror("Unknown ICMD %d during register allocation", + iptr->opc); + return; + } /* switch */ + iptr++; + } /* while instructions */ + } /* if */ + bptr = bptr->next; + } /* while blocks */ +} +#else /* allocate_scratch_registers ************************************************** Allocate temporary (non-interface, non-local) registers. @@ -1692,7 +3191,7 @@ static void new_allocate_scratch_registers(jitdata *jd) bptr = bptr->next; } /* while blocks */ } - +#endif #if defined(ENABLE_STATISTICS) void reg_make_statistics(jitdata *jd) diff --git a/src/vm/jit/codegen-common.c b/src/vm/jit/codegen-common.c index f756f8cf8..e21f4a2c5 100644 --- a/src/vm/jit/codegen-common.c +++ b/src/vm/jit/codegen-common.c @@ -48,7 +48,7 @@ memory. All functions writing values into the data area return the offset relative the begin of the code area (start of procedure). - $Id: codegen-common.c 5332 2006-09-05 19:38:28Z twisti $ + $Id: codegen-common.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -1090,7 +1090,42 @@ void removenativestub(u1 *stub) *******************************************************************************/ -s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum) +#if defined(NEW_VAR) +s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum) +{ + +#if 0 + /* Do we have to generate a conditional move? Yes, then always + return the temporary register. The real register is identified + during the store. */ + + if (opcode & ICMD_CONDITION_MASK) + return tempregnum; +#endif + + if (!(v->flags & INMEMORY)) { +#if defined(__ARM__) && defined(__ARMEL__) + if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT)) + return(PACK_REGS(GET_LOW_REG(var->regoff), + GET_HIGH_REG(tempregnum))); +#endif +#if defined(__ARM__) && defined(__ARMEB__) + if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT)) + return(PACK_REGS(GET_LOW_REG(tempregnum), + GET_HIGH_REG(var->regoff))); +#endif + return(v->regoff); + } + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + count_spills_read++; +#endif + + return tempregnum; +} +#else +s4 codegen_reg_of_var(u2 opcode, stackptr v, s4 tempregnum) { varinfo *var; @@ -1156,6 +1191,8 @@ s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum) return tempregnum; } +#endif + /* codegen_reg_of_dst ********************************************************** @@ -1175,52 +1212,21 @@ s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum) s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum) { - varinfo *var; - stackptr v = iptr->dst.var; - registerdata *rd = jd->rd; - - switch (v->varkind) { - case TEMPVAR: - if (!(v->flags & INMEMORY)) - return(v->regoff); - break; + varinfo *v = &jd->var[iptr->dst.varindex]; - case STACKVAR: - var = &(rd->interfaces[v->varnum][v->type]); - v->regoff = var->regoff; - if (!(var->flags & INMEMORY)) - return(var->regoff); - break; - - case LOCALVAR: - var = &(rd->locals[v->varnum][v->type]); - v->regoff = var->regoff; - if (!(var->flags & INMEMORY)) { -#if defined(__ARM__) && defined(__ARMEL__) - if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(var->regoff) == REG_SPLIT)) - return(PACK_REGS(GET_LOW_REG(var->regoff), GET_HIGH_REG(tempregnum))); -#endif -#if defined(__ARM__) && defined(__ARMEB__) - if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(var->regoff) == REG_SPLIT)) - return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(var->regoff))); -#endif - return(var->regoff); - } - break; - - case ARGVAR: - if (!(v->flags & INMEMORY)) { + if (!(v->flags & INMEMORY)) { + #if defined(__ARM__) && defined(__ARMEL__) - if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT)) - return(PACK_REGS(GET_LOW_REG(v->regoff), GET_HIGH_REG(tempregnum))); + if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT)) + return(PACK_REGS(GET_LOW_REG(v->regoff), + GET_HIGH_REG(tempregnum))); #endif #if defined(__ARM__) && defined(__ARMEB__) - if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT)) - return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(v->regoff))); + if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT)) + return(PACK_REGS(GET_LOW_REG(tempregnum), + GET_HIGH_REG(v->regoff))); #endif - return(v->regoff); - } - break; + return (v->regoff); } #if defined(ENABLE_STATISTICS) @@ -1228,6 +1234,8 @@ s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum) count_spills_read++; #endif + /* Not necessary anymore - either v is inmemory or not. Setting again */ + /* won't change anything */ v->flags |= INMEMORY; return tempregnum; diff --git a/src/vm/jit/codegen-common.h b/src/vm/jit/codegen-common.h index e5c1ca498..81fb1d447 100644 --- a/src/vm/jit/codegen-common.h +++ b/src/vm/jit/codegen-common.h @@ -29,7 +29,7 @@ Changes: Christian Ullrich Edwin Steiner - $Id: codegen-common.h 5332 2006-09-05 19:38:28Z twisti $ + $Id: codegen-common.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -198,7 +198,11 @@ u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *md); void removecompilerstub(u1 *stub); void removenativestub(u1 *stub); +#if defined(NEW_VAR) +s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum); +#else s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum); +#endif s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum); #if defined(ENABLE_THREADS) diff --git a/src/vm/jit/emit.h b/src/vm/jit/emit.h index 0670257c1..1a880917c 100644 --- a/src/vm/jit/emit.h +++ b/src/vm/jit/emit.h @@ -61,7 +61,7 @@ /* code generation functions **************************************************/ -s4 emit_load(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg); +s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg); s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg); @@ -76,15 +76,15 @@ s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg); #endif -void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d); +void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); void emit_store_dst(jitdata *jd, instruction *iptr, s4 d); #if SIZEOF_VOID_P == 4 -void emit_store_low(jitdata *jd, instruction *iptr, stackptr dst, s4 d); -void emit_store_high(jitdata *jd, instruction *iptr, stackptr dst, s4 d); +void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); +void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); #endif -void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst); +void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst); void emit_iconst(codegendata *cd, s4 d, s4 value); void emit_lconst(codegendata *cd, s4 d, s8 value); diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 4a6eecc02..ca2c8dd54 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -31,7 +31,7 @@ Christian Ullrich Edwin Steiner - $Id: codegen.c 5401 2006-09-07 12:52:31Z twisti $ + $Id: codegen.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -96,6 +96,4027 @@ void codegen_insert_phi_moves(codegendata *cd, registerdata *rd, lsradata *ls, basicblock *bptr); #endif +#if defined(NEW_VAR) +bool codegen(jitdata *jd) +{ + methodinfo *m; + codeinfo *code; + codegendata *cd; + registerdata *rd; + s4 len, s1, s2, s3, d, disp; + varinfo *var, *var1; + basicblock *bptr; + instruction *iptr; + exceptiontable *ex; + u2 currentline; + methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ + builtintable_entry *bte; + methoddesc *md; + rplpoint *replacementpoint; + s4 fieldtype; + s4 varindex; +#if defined(ENABLE_SSA) + lsradata *ls; + bool last_cmd_was_goto; + + last_cmd_was_goto = false; + ls = jd->ls; +#endif + + /* get required compiler data */ + + m = jd->m; + code = jd->code; + cd = jd->cd; + rd = jd->rd; + + /* prevent compiler warnings */ + + d = 0; + currentline = 0; + lm = NULL; + bte = NULL; + s2 = 0; + + { + s4 i, p, t, l; + s4 savedregs_num = 0; + s4 stack_off = 0; + + /* space to save used callee saved registers */ + + savedregs_num += (INT_SAV_CNT - rd->savintreguse); + + /* float register are saved on 2 4-byte stackslots */ + savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2; + + cd->stackframesize = rd->memuse + savedregs_num; + + +#if defined(ENABLE_THREADS) + /* space to save argument of monitor_enter */ + + if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + /* reserve 2 slots for long/double return values for monitorexit */ + + if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) + cd->stackframesize += 2; + else + cd->stackframesize++; + } +#endif + + /* create method header */ + + /* Keep stack of non-leaf functions 16-byte aligned. */ + + if (!jd->isleafmethod) + cd->stackframesize |= 0x3; + + (void) dseg_addaddress(cd, code); /* CodeinfoPointer */ + (void) dseg_adds4(cd, cd->stackframesize * 4); /* FrameSize */ + +#if defined(ENABLE_THREADS) + /* IsSync contains the offset relative to the stack pointer for the + argument of monitor_exit used in the exception handler. Since the + offset could be zero and give a wrong meaning of the flag it is + offset by one. + */ + + if (checksync && (m->flags & ACC_SYNCHRONIZED)) + (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */ + else +#endif + (void) dseg_adds4(cd, 0); /* IsSync */ + + (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */ + (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ + (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ + + /* adds a reference for the length of the line number counter. We don't + know the size yet, since we evaluate the information during code + generation, to save one additional iteration over the whole + instructions. During code optimization the position could have changed + to the information gotten from the class file */ + (void) dseg_addlinenumbertablesize(cd); + + (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */ + + /* create exception table */ + + for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) { + dseg_addtarget(cd, ex->start); + dseg_addtarget(cd, ex->end); + dseg_addtarget(cd, ex->handler); + (void) dseg_addaddress(cd, ex->catchtype.cls); + } + + /* generate method profiling code */ + + if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { + /* count frequency */ + + M_MOV_IMM(code, REG_ITMP3); + M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency)); + } + + /* create stack frame (if necessary) */ + + if (cd->stackframesize) + M_ASUB_IMM(cd->stackframesize * 4, REG_SP); + + /* save return address and used callee saved registers */ + + p = cd->stackframesize; + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_AST(rd->savintregs[i], REG_SP, p * 4); + } + for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { + p-=2; emit_fld_reg(cd, rd->savfltregs[i]); emit_fstpl_membase(cd, REG_SP, p * 4); + } + + /* take arguments out of register or stack frame */ + + md = m->parseddesc; + + stack_off = 0; + for (p = 0, l = 0; p < md->paramcount; p++) { + t = md->paramtypes[p].type; +#if defined(ENABLE_SSA) + if ( ls != NULL ) { + l = ls->local_0[p]; + } +#endif + var = &(jd->var[jd->local_map[l * 5 + t]]); + l++; + if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */ + l++; + if (var->type < 0) + continue; + s1 = md->params[p].regoff; + + if (IS_INT_LNG_TYPE(t)) { /* integer args */ + if (!md->params[p].inmemory) { /* register arguments */ + log_text("integer register argument"); + assert(0); + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ + /* rd->argintregs[md->params[p].regoff -> var->regoff */ + } + else { /* reg arg -> spilled */ + /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */ + } + } + else { /* stack arguments */ + if (!(var->flags & INMEMORY)) { /* stack arg -> register */ + emit_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, var->regoff); + /* + 4 for return address */ + } + else { /* stack arg -> spilled */ + if (!IS_2_WORD_TYPE(t)) { +#if defined(ENABLE_SSA) + /* no copy avoiding by now possible with SSA */ + if (ls != NULL) { + emit_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, + REG_ITMP1); + emit_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); + } + else +#endif /*defined(ENABLE_SSA)*/ + /* reuse Stackslotand avoid copying */ + var->regoff = cd->stackframesize + s1 + 1; + + } + else { +#if defined(ENABLE_SSA) + /* no copy avoiding by now possible with SSA */ + if (ls != NULL) { + emit_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, + REG_ITMP1); + emit_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); + emit_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4 + 4, + REG_ITMP1); + emit_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4); + } + else +#endif /*defined(ENABLE_SSA)*/ + /* reuse Stackslotand avoid copying */ + var->regoff = cd->stackframesize + s1 + 1; + } + } + } + } + else { /* floating args */ + if (!md->params[p].inmemory) { /* register arguments */ + log_text("There are no float argument registers!"); + assert(0); + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ + /* rd->argfltregs[md->params[p].regoff -> var->regoff */ + } else { /* reg arg -> spilled */ + /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */ + } + + } + else { /* stack arguments */ + if (!(var->flags & INMEMORY)) { /* stack-arg -> register */ + if (t == TYPE_FLT) { + emit_flds_membase( + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4); + assert(0); +/* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */ + + } + else { + emit_fldl_membase( + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4); + assert(0); +/* emit_fstp_reg(cd, var->regoff + fpu_st_offset); */ + } + + } else { /* stack-arg -> spilled */ +#if defined(ENABLE_SSA) + /* no copy avoiding by now possible with SSA */ + if (ls != NULL) { + emit_mov_membase_reg( + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4, REG_ITMP1); + emit_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); + if (t == TYPE_FLT) { + emit_flds_membase( + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4); + emit_fstps_membase(cd, REG_SP, var->regoff * 4); + } + else { + emit_fldl_membase( + cd, REG_SP, (cd->stackframesize + s1) * 4 + 4); + emit_fstpl_membase(cd, REG_SP, var->regoff * 4); + } + } + else +#endif /*defined(ENABLE_SSA)*/ + /* reuse Stackslotand avoid copying */ + var->regoff = cd->stackframesize + s1 + 1; + } + } + } + } /* end for */ + + /* call monitorenter function */ + +#if defined(ENABLE_THREADS) + if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + s1 = rd->memuse; + + if (m->flags & ACC_STATIC) { + M_MOV_IMM(&m->class->object.header, REG_ITMP1); + } + else { + M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 4 + 4); + M_TEST(REG_ITMP1); + M_BEQ(0); + codegen_add_nullpointerexception_ref(cd); + } + + M_AST(REG_ITMP1, REG_SP, s1 * 4); + M_AST(REG_ITMP1, REG_SP, 0 * 4); + M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3); + M_CALL(REG_ITMP3); + } +#endif + +#if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) + emit_verbosecall_enter(jd); +#endif + + } + +#if defined(ENABLE_SSA) + /* with SSA Header is Basic Block 0 - insert phi Moves if necessary */ + if ( ls != NULL) + codegen_insert_phi_moves(cd, rd, ls, ls->basicblocks[0]); +#endif + + /* end of header generation */ + + replacementpoint = jd->code->rplpoints; + + /* walk through all basic blocks */ + for (bptr = jd->new_basicblocks; bptr != NULL; bptr = bptr->next) { + + bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase); + + if (bptr->flags >= BBREACHED) { + + /* branch resolving */ + + branchref *brefs; + for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) { + gen_resolvebranch(cd->mcodebase + brefs->branchpos, + brefs->branchpos, + bptr->mpc); + } + +#if 0 + /* handle replacement points */ + + if (bptr->bitflags & BBFLAG_REPLACEMENT) { + replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */ + + replacementpoint++; + + assert(cd->lastmcodeptr <= cd->mcodeptr); + cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */ + } +#endif + + /* copy interface registers to their destination */ + + len = bptr->indepth; + MCODECHECK(512); + +#if 0 + /* generate basic block profiling code */ + + if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { + /* count frequency */ + + M_MOV_IMM(code->bbfrequency, REG_ITMP3); + M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->nr * 4); + } +#endif + +#if defined(ENABLE_LSRA) || defined(ENABLE_SSA) +# if defined(ENABLE_LSRA) && !defined(ENABLE_SSA) + if (opt_lsra) { +# endif +# if defined(ENABLE_SSA) + if (ls != NULL) { + last_cmd_was_goto = false; +# endif + if (len > 0) { + len--; + src = bptr->invars[len]; + if (bptr->type != BBTYPE_STD) { + if (!IS_2_WORD_TYPE(src->type)) { + if (bptr->type == BBTYPE_SBR) { + if (!(src->flags & INMEMORY)) + d = src->regoff; + else + d = REG_ITMP1; + emit_pop_reg(cd, d); + emit_store(jd, NULL, src, d); + } else if (bptr->type == BBTYPE_EXH) { + if (!(src->flags & INMEMORY)) + d = src->regoff; + else + d = REG_ITMP1; + M_INTMOVE(REG_ITMP1, d); + emit_store(jd, NULL, src, d); + } + + } else { + log_text("copy interface registers(EXH, SBR): longs have to be in memory (begin 1)"); + assert(0); + } + } + } + + } else +#endif /* defined(ENABLE_LSRA) || defined(ENABLE_SSA) */ + { + while (len) { + len--; + varindex = bptr->invars[len]; + var = &(jd->var[varindex]); + if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) { + if (!IS_2_WORD_TYPE(var->type)) { + if (bptr->type == BBTYPE_SBR) { + d = codegen_reg_of_var(0, var, REG_ITMP1); + emit_pop_reg(cd, d); + emit_store(jd, NULL, var, d); + + } else if (bptr->type == BBTYPE_EXH) { + d = codegen_reg_of_var(0, var, REG_ITMP1); + M_INTMOVE(REG_ITMP1, d); + emit_store(jd, NULL, var, d); + } + } else { + log_text("copy interface registers: longs have to be in \ + memory (begin 1)"); + assert(0); + } + + } else { + printf("block %i var %i\n",bptr->nr, varindex); + assert((var->flags & OUTVAR)); + /* will be done directly in simplereg lateron */ + /* for now codegen_reg_of_var has to be called here to */ + /* set the regoff and flags for all bptr->invars[] */ + d = codegen_reg_of_var(0, var, REG_ITMP1); + + } + } + } + + /* walk through all instructions */ + + len = bptr->icount; + currentline = 0; + + for (iptr = bptr->iinstr; len > 0; len--, iptr++) { + if (iptr->line != currentline) { + dseg_addlinenumber(cd, iptr->line); + currentline = iptr->line; + } + + MCODECHECK(1024); /* 1kB should be enough */ + + switch (iptr->opc) { + case ICMD_INLINE_START: +#if 0 + { + insinfo_inline *insinfo = (insinfo_inline *) iptr->target; +#if defined(ENABLE_THREADS) + if (insinfo->synchronize) { + /* add monitor enter code */ + if (insinfo->method->flags & ACC_STATIC) { + M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1); + M_AST(REG_ITMP1, REG_SP, 0 * 4); + } + else { + /* nullpointer check must have been performed before */ + /* (XXX not done, yet) */ + var = &(rd->locals[insinfo->synclocal][TYPE_ADR]); + if (var->flags & INMEMORY) { + emit_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP1); + M_AST(REG_ITMP1, REG_SP, 0 * 4); + } + else { + M_AST(var->regoff, REG_SP, 0 * 4); + } + } + + M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3); + M_CALL(REG_ITMP3); + } +#endif + dseg_addlinenumber_inline_start(cd, iptr); + } +#endif + break; + + case ICMD_INLINE_END: +#if 0 + { + insinfo_inline *insinfo = (insinfo_inline *) iptr->target; + + dseg_addlinenumber_inline_end(cd, iptr); + dseg_addlinenumber(cd, iptr->line); + +#if defined(ENABLE_THREADS) + if (insinfo->synchronize) { + /* add monitor exit code */ + if (insinfo->method->flags & ACC_STATIC) { + M_MOV_IMM(&insinfo->method->class->object.header, REG_ITMP1); + M_AST(REG_ITMP1, REG_SP, 0 * 4); + } + else { + var = &(rd->locals[insinfo->synclocal][TYPE_ADR]); + if (var->flags & INMEMORY) { + M_ALD(REG_ITMP1, REG_SP, var->regoff * 4); + M_AST(REG_ITMP1, REG_SP, 0 * 4); + } + else { + M_AST(var->regoff, REG_SP, 0 * 4); + } + } + + M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3); + M_CALL(REG_ITMP3); + } +#endif + } +#endif + break; + + case ICMD_NOP: /* ... ==> ... */ + break; + + case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_TEST(s1); + M_BEQ(0); + codegen_add_nullpointerexception_ref(cd); + break; + + /* constant operations ************************************************/ + + case ICMD_ICONST: /* ... ==> ..., constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + ICONST(d, iptr->sx.val.i); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LCONST: /* ... ==> ..., constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + LCONST(d, iptr->sx.val.l); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FCONST: /* ... ==> ..., constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + if (iptr->sx.val.f == 0.0) { + emit_fldz(cd); + + /* -0.0 */ + if (iptr->sx.val.i == 0x80000000) { + emit_fchs(cd); + } + + } else if (iptr->sx.val.f == 1.0) { + emit_fld1(cd); + + } else if (iptr->sx.val.f == 2.0) { + emit_fld1(cd); + emit_fld1(cd); + emit_faddp(cd); + + } else { + disp = dseg_addfloat(cd, iptr->sx.val.f); + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + emit_flds_membase(cd, REG_ITMP1, disp); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DCONST: /* ... ==> ..., constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + if (iptr->sx.val.d == 0.0) { + emit_fldz(cd); + + /* -0.0 */ + if (iptr->sx.val.l == 0x8000000000000000LL) { + emit_fchs(cd); + } + + } else if (iptr->sx.val.d == 1.0) { + emit_fld1(cd); + + } else if (iptr->sx.val.d == 2.0) { + emit_fld1(cd); + emit_fld1(cd); + emit_faddp(cd); + + } else { + disp = dseg_adddouble(cd, iptr->sx.val.d); + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + emit_fldl_membase(cd, REG_ITMP1, disp); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ACONST: /* ... ==> ..., constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + codegen_addpatchref(cd, PATCHER_aconst, + iptr->sx.val.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + M_MOV_IMM(NULL, d); + + } else { + if (iptr->sx.val.anyptr == NULL) + M_CLR(d); + else + M_MOV_IMM(iptr->sx.val.anyptr, d); + } + emit_store_dst(jd, iptr, d); + break; + + + /* load/store operations **********************************************/ + + case ICMD_ILOAD: /* ... ==> ..., content of local variable */ + case ICMD_ALOAD: /* op1 = local variable */ + + if ( iptr->dst.varindex == iptr->s1.varindex) + break; + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + + s1 = emit_load_s1(jd, iptr, d); + M_INTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_LLOAD: /* ... ==> ..., content of local variable */ + /* s1.localindex = local variable */ + + if ( iptr->dst.varindex == iptr->s1.varindex) + break; + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_INTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_FLOAD: + case ICMD_DLOAD: /* ... ==> ..., content of local variable */ + /* s1.localindex = local variable */ + + if ( iptr->dst.varindex == iptr->s1.varindex) + break; + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + M_FLTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + + break; + + + case ICMD_ISTORE: /* ..., value ==> ... */ + case ICMD_ASTORE: /* op1 = local variable */ + + if ( iptr->s1.varindex == iptr->dst.varindex) + break; + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + + M_INTMOVE(s1,d); + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_LSTORE: /* ..., value ==> ... */ + /* dst.localindex = local variable */ + + if ( iptr->dst.varindex == iptr->dst.varindex) + break; + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_INTMOVE(s1,d); + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_FSTORE: /* ..., value ==> ... */ + /* dst.localindex = local variable */ + + if ( iptr->dst.varindex == iptr->s1.varindex) + break; + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + M_FLTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_DSTORE: /* ..., value ==> ... */ + /* dst.localindex = local variable */ + + if ( iptr->dst.varindex == iptr->s1.varindex) + break; + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + M_FLTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + + break; + + + /* pop/dup/swap operations ********************************************/ + + /* attention: double and longs are only one entry in CACAO ICMDs */ + + case ICMD_POP: /* ..., value ==> ... */ + case ICMD_POP2: /* ..., value, value ==> ... */ + break; + + case ICMD_DUP: /* ..., a ==> ..., a, a */ + + M_COPY(iptr->s1.varindex, iptr->dst.varindex); + break; + + case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */ + + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+2]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]); + M_COPY(iptr->dst.dupslots[2+2], iptr->dst.dupslots[2+0]); + break; + + case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */ + + M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+3]); + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+2]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+1]); + M_COPY(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]); + break; + + case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */ + + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+1]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+0]); + break; + + case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */ + + M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+4]); + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+3]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+2]); + M_COPY(iptr->dst.dupslots[3+4], iptr->dst.dupslots[3+1]); + M_COPY(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]); + break; + + case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */ + + M_COPY(iptr->dst.dupslots[ 3], iptr->dst.dupslots[4+5]); + M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[4+4]); + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[4+3]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[4+2]); + M_COPY(iptr->dst.dupslots[4+5], iptr->dst.dupslots[4+1]); + M_COPY(iptr->dst.dupslots[4+4], iptr->dst.dupslots[4+0]); + break; + + case ICMD_SWAP: /* ..., a, b ==> ..., b, a */ + + M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+0]); + M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]); + break; + + +#if 0 + case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */ + + M_COPY(src, iptr->dst); + M_COPY(src->prev, iptr->dst->prev); +#if defined(ENABLE_SSA) + if ((ls==NULL) || (iptr->dst->varkind != TEMPVAR) || + (ls->lifetime[-iptr->dst->varnum-1].type != -1)) { +#endif + M_COPY(iptr->dst, iptr->dst->prev->prev); +#if defined(ENABLE_SSA) + } else { + M_COPY(src, iptr->dst->prev->prev); + } +#endif + break; + + case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */ + + M_COPY(src, iptr->dst); + M_COPY(src->prev, iptr->dst->prev); + M_COPY(src->prev->prev, iptr->dst->prev->prev); +#if defined(ENABLE_SSA) + if ((ls==NULL) || (iptr->dst->varkind != TEMPVAR) || + (ls->lifetime[-iptr->dst->varnum-1].type != -1)) { +#endif + M_COPY(iptr->dst, iptr->dst->prev->prev->prev); +#if defined(ENABLE_SSA) + } else { + M_COPY(src, iptr->dst->prev->prev->prev); + } +#endif + break; +#endif + + /* integer operations *************************************************/ + + case ICMD_INEG: /* ..., value ==> ..., - value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_NEG(d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LNEG: /* ..., value ==> ..., - value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_NEG(GET_LOW_REG(d)); + M_IADDC_IMM(0, GET_HIGH_REG(d)); + M_NEG(GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_I2L: /* ..., value ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, EAX); + d = codegen_reg_of_dst(jd, iptr, EAX_EDX_PACKED); + M_INTMOVE(s1, EAX); + M_CLTD; + M_LNGMOVE(EAX_EDX_PACKED, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_L2I: /* ..., value ==> ..., value */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_INT2BYTE: /* ..., value ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_SLL_IMM(24, d); + M_SRA_IMM(24, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_INT2CHAR: /* ..., value ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_CZEXT(s1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_INT2SHORT: /* ..., value ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SSEXT(s1, d); + emit_store_dst(jd, iptr, d); + break; + + + case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s2 == d) + M_IADD(s1, d); + else { + M_INTMOVE(s1, d); + M_IADD(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_IADD_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_INTMOVE(s1, GET_LOW_REG(d)); + M_IADD(s2, GET_LOW_REG(d)); + /* don't use REG_ITMP1 */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_IADDC(s2, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_IADD_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_IADDC_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (s2 == d) { + M_INTMOVE(s1, REG_ITMP1); + M_ISUB(s2, REG_ITMP1); + M_INTMOVE(REG_ITMP1, d); + } + else { + M_INTMOVE(s1, d); + M_ISUB(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_ISUB_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if (s2 == GET_LOW_REG(d)) { + M_INTMOVE(s1, REG_ITMP1); + M_ISUB(s2, REG_ITMP1); + M_INTMOVE(REG_ITMP1, GET_LOW_REG(d)); + } + else { + M_INTMOVE(s1, GET_LOW_REG(d)); + M_ISUB(s2, GET_LOW_REG(d)); + } + /* don't use REG_ITMP1 */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + if (s2 == GET_HIGH_REG(d)) { + M_INTMOVE(s1, REG_ITMP2); + M_ISUBB(s2, REG_ITMP2); + M_INTMOVE(REG_ITMP2, GET_HIGH_REG(d)); + } + else { + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_ISUBB(s2, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_ISUB_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_ISUBB_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s2 == d) + M_IMUL(s1, d); + else { + M_INTMOVE(s1, d); + M_IMUL(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_IMUL_IMM(s1, iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_low(jd, iptr, EDX); + d = codegen_reg_of_dst(jd, iptr, EAX_EDX_PACKED); + + M_INTMOVE(s1, REG_ITMP2); + M_IMUL(s2, REG_ITMP2); + + s1 = emit_load_s1_low(jd, iptr, EAX); + s2 = emit_load_s2_high(jd, iptr, EDX); + M_INTMOVE(s2, EDX); + M_IMUL(s1, EDX); + M_IADD(EDX, REG_ITMP2); + + s1 = emit_load_s1_low(jd, iptr, EAX); + s2 = emit_load_s2_low(jd, iptr, EDX); + M_INTMOVE(s1, EAX); + M_MUL(s2); + M_INTMOVE(EAX, GET_LOW_REG(d)); + M_IADD(REG_ITMP2, GET_HIGH_REG(d)); + + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, EAX_EDX_PACKED); + ICONST(EAX, iptr->sx.val.l); + M_MUL(s1); + M_IMUL_IMM(s1, iptr->sx.val.l >> 32, REG_ITMP2); + M_IADD(REG_ITMP2, EDX); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + M_IMUL_IMM(s1, iptr->sx.val.l, REG_ITMP2); + M_IADD(REG_ITMP2, EDX); + M_LNGMOVE(EAX_EDX_PACKED, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ + + s1 = emit_load_s1(jd, iptr, EAX); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, EAX); + + if (checknull) { + M_TEST(s2); + M_BEQ(0); + codegen_add_arithmeticexception_ref(cd); + } + + M_INTMOVE(s1, EAX); /* we need the first operand in EAX */ + + /* check as described in jvm spec */ + + M_CMP_IMM(0x80000000, EAX); + M_BNE(3 + 6); + M_CMP_IMM(-1, s2); + M_BEQ(1 + 2); + M_CLTD; + M_IDIV(s2); + + M_INTMOVE(EAX, d); /* if INMEMORY then d is already EAX */ + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */ + + s1 = emit_load_s1(jd, iptr, EAX); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, EDX); + + if (checknull) { + M_TEST(s2); + M_BEQ(0); + codegen_add_arithmeticexception_ref(cd); + } + + M_INTMOVE(s1, EAX); /* we need the first operand in EAX */ + + /* check as described in jvm spec */ + + M_CMP_IMM(0x80000000, EAX); + M_BNE(2 + 3 + 6); + M_CLR(EDX); + M_CMP_IMM(-1, s2); + M_BEQ(1 + 2); + M_CLTD; + M_IDIV(s2); + + M_INTMOVE(EDX, d); /* if INMEMORY then d is already EDX */ + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ + + /* TODO: optimize for `/ 2' */ + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_TEST(d); + M_BNS(6); + M_IADD_IMM32((1 << iptr->sx.val.i) - 1, d);/* 32-bit for jump off */ + M_SRA_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s1 == d) { + M_MOV(s1, REG_ITMP1); + s1 = REG_ITMP1; + } + M_INTMOVE(s1, d); + M_AND_IMM(iptr->sx.val.i, d); + M_TEST(s1); + M_BGE(2 + 2 + 6 + 2); + M_MOV(s1, d); /* don't use M_INTMOVE, so we know the jump offset */ + M_NEG(d); + M_AND_IMM32(iptr->sx.val.i, d); /* use 32-bit for jump offset */ + M_NEG(d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ + case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */ + + s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + + M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3); + M_OR(GET_HIGH_REG(s2), REG_ITMP3); + M_BEQ(0); + codegen_add_arithmeticexception_ref(cd); + + bte = iptr->sx.s23.s3.bte; + md = bte->md; + + M_LST(s2, REG_SP, 2 * 4); + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_LST(s1, REG_SP, 0 * 4); + + M_MOV_IMM(bte->fp, REG_ITMP3); + M_CALL(REG_ITMP3); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(s1, d); + M_TEST(GET_HIGH_REG(d)); + M_BNS(6 + 3); + M_IADD_IMM32((1 << iptr->sx.val.i) - 1, GET_LOW_REG(d)); + M_IADDC_IMM(0, GET_HIGH_REG(d)); + M_SRLD_IMM(iptr->sx.val.i, GET_HIGH_REG(d), GET_LOW_REG(d)); + M_SRA_IMM(iptr->sx.val.i, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + +#if 0 + case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */ + /* sx.val.l = constant */ + + d = codegen_reg_of_dst(jd, iptr, REG_NULL); + if (iptr->dst.var->flags & INMEMORY) { + if (iptr->s1.var->flags & INMEMORY) { + /* Alpha algorithm */ + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, iptr->s1.var->regoff * 4); + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, iptr->s1.var->regoff * 4 + 4); + + disp += 2; + disp += 3; + disp += 2; + + /* TODO: hmm, don't know if this is always correct */ + disp += 2; + CALCIMMEDIATEBYTES(disp, iptr->sx.val.l & 0x00000000ffffffff); + disp += 2; + CALCIMMEDIATEBYTES(disp, iptr->sx.val.l >> 32); + + disp += 2; + disp += 3; + disp += 2; + + emit_mov_membase_reg(cd, REG_SP, iptr->s1.var->regoff * 4, REG_ITMP1); + emit_mov_membase_reg(cd, REG_SP, iptr->s1.var->regoff * 4 + 4, REG_ITMP2); + + emit_alu_imm_reg(cd, ALU_AND, iptr->sx.val.l, REG_ITMP1); + emit_alu_imm_reg(cd, ALU_AND, iptr->sx.val.l >> 32, REG_ITMP2); + emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, iptr->s1.var->regoff * 4 + 4); + emit_jcc(cd, CC_GE, disp); + + emit_mov_membase_reg(cd, REG_SP, iptr->s1.var->regoff * 4, REG_ITMP1); + emit_mov_membase_reg(cd, REG_SP, iptr->s1.var->regoff * 4 + 4, REG_ITMP2); + + emit_neg_reg(cd, REG_ITMP1); + emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2); + emit_neg_reg(cd, REG_ITMP2); + + emit_alu_imm_reg(cd, ALU_AND, iptr->sx.val.l, REG_ITMP1); + emit_alu_imm_reg(cd, ALU_AND, iptr->sx.val.l >> 32, REG_ITMP2); + + emit_neg_reg(cd, REG_ITMP1); + emit_alu_imm_reg(cd, ALU_ADC, 0, REG_ITMP2); + emit_neg_reg(cd, REG_ITMP2); + + emit_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst.var->regoff * 4); + emit_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst.var->regoff * 4 + 4); + } + } + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(s1, d); + M_AND_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_AND_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + M_TEST(GET_LOW_REG(s1)); + M_BGE(0); + M_LNGMOVE(s1, d); + break; +#endif + + case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s2, ECX); /* s2 may be equal to d */ + M_INTMOVE(s1, d); + M_SLL(d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_SLL_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s2, ECX); /* s2 may be equal to d */ + M_INTMOVE(s1, d); + M_SRA(d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_SRA_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s2, ECX); /* s2 may be equal to d */ + M_INTMOVE(s1, d); + M_SRL(d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_SRL_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP13_PACKED); + s2 = emit_load_s2(jd, iptr, ECX); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED); + M_LNGMOVE(s1, d); + M_INTMOVE(s2, ECX); + M_TEST_IMM(32, ECX); + M_BEQ(2 + 2); + M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d)); + M_CLR(GET_LOW_REG(d)); + M_SLLD(GET_LOW_REG(d), GET_HIGH_REG(d)); + M_SLL(GET_LOW_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + if (iptr->sx.val.i & 0x20) { + M_MOV(GET_LOW_REG(d), GET_HIGH_REG(d)); + M_CLR(GET_LOW_REG(d)); + M_SLLD_IMM(iptr->sx.val.i & 0x3f, GET_LOW_REG(d), + GET_HIGH_REG(d)); + } + else { + M_SLLD_IMM(iptr->sx.val.i & 0x3f, GET_LOW_REG(d), + GET_HIGH_REG(d)); + M_SLL_IMM(iptr->sx.val.i & 0x3f, GET_LOW_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP13_PACKED); + s2 = emit_load_s2(jd, iptr, ECX); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED); + M_LNGMOVE(s1, d); + M_INTMOVE(s2, ECX); + M_TEST_IMM(32, ECX); + M_BEQ(2 + 3); + M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_SRA_IMM(31, GET_HIGH_REG(d)); + M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_SRA(GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + if (iptr->sx.val.i & 0x20) { + M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_SRA_IMM(31, GET_HIGH_REG(d)); + M_SRLD_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d), + GET_LOW_REG(d)); + } + else { + M_SRLD_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d), + GET_LOW_REG(d)); + M_SRA_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP13_PACKED); + s2 = emit_load_s2(jd, iptr, ECX); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED); + M_LNGMOVE(s1, d); + M_INTMOVE(s2, ECX); + M_TEST_IMM(32, ECX); + M_BEQ(2 + 2); + M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_CLR(GET_HIGH_REG(d)); + M_SRLD(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_SRL(GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + if (iptr->sx.val.i & 0x20) { + M_MOV(GET_HIGH_REG(d), GET_LOW_REG(d)); + M_CLR(GET_HIGH_REG(d)); + M_SRLD_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d), + GET_LOW_REG(d)); + } + else { + M_SRLD_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d), + GET_LOW_REG(d)); + M_SRL_IMM(iptr->sx.val.i & 0x3f, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s2 == d) + M_AND(s1, d); + else { + M_INTMOVE(s1, d); + M_AND(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_AND_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if (s2 == GET_LOW_REG(d)) + M_AND(s1, GET_LOW_REG(d)); + else { + M_INTMOVE(s1, GET_LOW_REG(d)); + M_AND(s2, GET_LOW_REG(d)); + } + /* REG_ITMP1 probably contains low 32-bit of destination */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + if (s2 == GET_HIGH_REG(d)) + M_AND(s1, GET_HIGH_REG(d)); + else { + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_AND(s2, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_AND_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_AND_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s2 == d) + M_OR(s1, d); + else { + M_INTMOVE(s1, d); + M_OR(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IORCONST: /* ..., value ==> ..., value | constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_OR_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if (s2 == GET_LOW_REG(d)) + M_OR(s1, GET_LOW_REG(d)); + else { + M_INTMOVE(s1, GET_LOW_REG(d)); + M_OR(s2, GET_LOW_REG(d)); + } + /* REG_ITMP1 probably contains low 32-bit of destination */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + if (s2 == GET_HIGH_REG(d)) + M_OR(s1, GET_HIGH_REG(d)); + else { + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_OR(s2, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LORCONST: /* ..., value ==> ..., value | constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_OR_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_OR_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s2 == d) + M_XOR(s1, d); + else { + M_INTMOVE(s1, d); + M_XOR(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */ + /* sx.val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); + M_XOR_IMM(iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if (s2 == GET_LOW_REG(d)) + M_XOR(s1, GET_LOW_REG(d)); + else { + M_INTMOVE(s1, GET_LOW_REG(d)); + M_XOR(s2, GET_LOW_REG(d)); + } + /* REG_ITMP1 probably contains low 32-bit of destination */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + if (s2 == GET_HIGH_REG(d)) + M_XOR(s1, GET_HIGH_REG(d)); + else { + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_XOR(s2, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */ + /* sx.val.l = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_LNGMOVE(s1, d); + M_XOR_IMM(iptr->sx.val.l, GET_LOW_REG(d)); + M_XOR_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(d)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IINC: /* ..., value ==> ..., value + constant */ + /* s1.localindex = variable, sx.val.i = constant*/ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + + /* `inc reg' is slower on p4's (regarding to ia32 + optimization reference manual and benchmarks) and as + fast on athlon's. */ + + M_INTMOVE(s1, d); + M_IADD_IMM(iptr->sx.val.i, d); + + emit_store_dst(jd, iptr, d); + + break; + + + /* floating operations ************************************************/ + + case ICMD_FNEG: /* ..., value ==> ..., - value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + emit_fchs(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DNEG: /* ..., value ==> ..., - value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + emit_fchs(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_faddp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_faddp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fsubp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fsubp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fmulp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fmulp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fdivp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + emit_fdivp(cd); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */ + + /* exchanged to skip fxch */ + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); +/* emit_fxch(cd); */ + emit_fprem(cd); + emit_wait(cd); + emit_fnstsw(cd); + emit_sahf(cd); + emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6)); + emit_store_dst(jd, iptr, d); + emit_ffree_reg(cd, 0); + emit_fincstp(cd); + break; + + case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */ + + /* exchanged to skip fxch */ + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); +/* emit_fxch(cd); */ + emit_fprem(cd); + emit_wait(cd); + emit_fnstsw(cd); + emit_sahf(cd); + emit_jcc(cd, CC_P, -(2 + 1 + 2 + 1 + 6)); + emit_store_dst(jd, iptr, d); + emit_ffree_reg(cd, 0); + emit_fincstp(cd); + break; + + case ICMD_I2F: /* ..., value ==> ..., (float) value */ + case ICMD_I2D: /* ..., value ==> ..., (double) value */ + + var = &(jd->var[iptr->s1.varindex]); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + if (var->flags & INMEMORY) { + emit_fildl_membase(cd, REG_SP, var->regoff * 4); + } else { + disp = dseg_adds4(cd, 0); + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + emit_mov_reg_membase(cd, var->regoff, REG_ITMP1, disp); + emit_fildl_membase(cd, REG_ITMP1, disp); + } + + emit_store_dst(jd, iptr, d); + break; + + case ICMD_L2F: /* ..., value ==> ..., (float) value */ + case ICMD_L2D: /* ..., value ==> ..., (double) value */ + + var = &(jd->var[iptr->s1.varindex]); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + if (var->flags & INMEMORY) { + emit_fildll_membase(cd, REG_SP, var->regoff * 4); + + } else { + log_text("L2F: longs have to be in memory"); + assert(0); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_F2I: /* ..., value ==> ..., (int) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_NULL); + + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + + /* Round to zero, 53-bit mode, exception masked */ + disp = dseg_adds4(cd, 0x0e7f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + var = &(jd->var[iptr->dst.varindex]); + var1 = &(jd->var[iptr->s1.varindex]); + + if (var->flags & INMEMORY) { + emit_fistpl_membase(cd, REG_SP, var->regoff * 4); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, + REG_SP, var->regoff * 4); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + + } else { + disp = dseg_adds4(cd, 0); + emit_fistpl_membase(cd, REG_ITMP1, disp); + emit_mov_membase_reg(cd, REG_ITMP1, disp, var->regoff); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, var->regoff); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + ((REG_RESULT == var->regoff) ? 0 : 2); + } + + emit_jcc(cd, CC_NE, disp); + + /* XXX: change this when we use registers */ + emit_flds_membase(cd, REG_SP, var1->regoff * 4); + emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1); + emit_call_reg(cd, REG_ITMP1); + + if (var->flags & INMEMORY) { + emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->regoff * 4); + + } else { + M_INTMOVE(REG_RESULT, var->regoff); + } + break; + + case ICMD_D2I: /* ..., value ==> ..., (int) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_NULL); + + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + + /* Round to zero, 53-bit mode, exception masked */ + disp = dseg_adds4(cd, 0x0e7f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + var = &(jd->var[iptr->dst.varindex]); + var1 = &(jd->var[iptr->s1.varindex]); + + if (var->flags & INMEMORY) { + emit_fistpl_membase(cd, REG_SP, var->regoff * 4); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, + REG_SP, var->regoff * 4); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + + } else { + disp = dseg_adds4(cd, 0); + emit_fistpl_membase(cd, REG_ITMP1, disp); + emit_mov_membase_reg(cd, REG_ITMP1, disp, var->regoff); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_reg(cd, ALU_CMP, 0x80000000, var->regoff); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + ((REG_RESULT == var->regoff) ? 0 : 2); + } + + emit_jcc(cd, CC_NE, disp); + + /* XXX: change this when we use registers */ + emit_fldl_membase(cd, REG_SP, var1->regoff * 4); + emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1); + emit_call_reg(cd, REG_ITMP1); + + if (var->flags & INMEMORY) { + emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->regoff * 4); + } else { + M_INTMOVE(REG_RESULT, var->regoff); + } + break; + + case ICMD_F2L: /* ..., value ==> ..., (long) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_NULL); + + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + + /* Round to zero, 53-bit mode, exception masked */ + disp = dseg_adds4(cd, 0x0e7f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + var = &(jd->var[iptr->dst.varindex]); + var1 = &(jd->var[iptr->s1.varindex]); + + if (var->flags & INMEMORY) { + emit_fistpll_membase(cd, REG_SP, var->regoff * 4); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, + REG_SP, var->regoff * 4 + 4); + + disp = 6 + 4; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2; + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4 + 4); + + emit_jcc(cd, CC_NE, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0, + REG_SP, var->regoff * 4); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + + emit_jcc(cd, CC_NE, disp); + + /* XXX: change this when we use registers */ + emit_flds_membase(cd, REG_SP, var1->regoff * 4); + emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1); + emit_call_reg(cd, REG_ITMP1); + emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->regoff * 4); + emit_mov_reg_membase(cd, REG_RESULT2, + REG_SP, var->regoff * 4 + 4); + + } else { + log_text("F2L: longs have to be in memory"); + assert(0); + } + break; + + case ICMD_D2L: /* ..., value ==> ..., (long) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_NULL); + + emit_mov_imm_reg(cd, 0, REG_ITMP1); + dseg_adddata(cd); + + /* Round to zero, 53-bit mode, exception masked */ + disp = dseg_adds4(cd, 0x0e7f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + var = &(jd->var[iptr->dst.varindex]); + var1 = &(jd->var[iptr->s1.varindex]); + + if (var->flags & INMEMORY) { + emit_fistpll_membase(cd, REG_SP, var->regoff * 4); + + /* Round to nearest, 53-bit mode, exceptions masked */ + disp = dseg_adds4(cd, 0x027f); + emit_fldcw_membase(cd, REG_ITMP1, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0x80000000, + REG_SP, var->regoff * 4 + 4); + + disp = 6 + 4; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2; + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + disp += 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4 + 4); + + emit_jcc(cd, CC_NE, disp); + + emit_alu_imm_membase(cd, ALU_CMP, 0, REG_SP, var->regoff * 4); + + disp = 3; + CALCOFFSETBYTES(disp, REG_SP, var1->regoff * 4); + disp += 5 + 2 + 3; + CALCOFFSETBYTES(disp, REG_SP, var->regoff * 4); + + emit_jcc(cd, CC_NE, disp); + + /* XXX: change this when we use registers */ + emit_fldl_membase(cd, REG_SP, var1->regoff * 4); + emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1); + emit_call_reg(cd, REG_ITMP1); + emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->regoff * 4); + emit_mov_reg_membase(cd, REG_RESULT2, + REG_SP, var->regoff * 4 + 4); + + } else { + log_text("D2L: longs have to be in memory"); + assert(0); + } + break; + + case ICMD_F2D: /* ..., value ==> ..., (double) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + /* nothing to do */ + emit_store_dst(jd, iptr, d); + break; + + case ICMD_D2F: /* ..., value ==> ..., (float) value */ + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + /* nothing to do */ + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */ + case ICMD_DCMPL: + + /* exchanged to skip fxch */ + s2 = emit_load_s1(jd, iptr, REG_FTMP1); + s1 = emit_load_s2(jd, iptr, REG_FTMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); +/* emit_fxch(cd); */ + emit_fucompp(cd); + emit_fnstsw(cd); + emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */ + emit_jcc(cd, CC_E, 6); + emit_alu_imm_reg(cd, ALU_AND, 0x000000ff, EAX); + emit_sahf(cd); + emit_mov_imm_reg(cd, 0, d); /* does not affect flags */ + emit_jcc(cd, CC_E, 6 + 3 + 5 + 3); + emit_jcc(cd, CC_B, 3 + 5); + emit_alu_imm_reg(cd, ALU_SUB, 1, d); + emit_jmp_imm(cd, 3); + emit_alu_imm_reg(cd, ALU_ADD, 1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ + case ICMD_DCMPG: + + /* exchanged to skip fxch */ + s2 = emit_load_s1(jd, iptr, REG_FTMP1); + s1 = emit_load_s2(jd, iptr, REG_FTMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); +/* emit_fxch(cd); */ + emit_fucompp(cd); + emit_fnstsw(cd); + emit_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */ + emit_jcc(cd, CC_E, 3); + emit_movb_imm_reg(cd, 1, REG_AH); + emit_sahf(cd); + emit_mov_imm_reg(cd, 0, d); /* does not affect flags */ + emit_jcc(cd, CC_E, 6 + 3 + 5 + 3); + emit_jcc(cd, CC_B, 3 + 5); + emit_alu_imm_reg(cd, ALU_SUB, 1, d); + emit_jmp_imm(cd, 3); + emit_alu_imm_reg(cd, ALU_ADD, 1, d); + emit_store_dst(jd, iptr, d); + break; + + + /* memory operations **************************************************/ + + case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + gen_nullptr_check(s1); + M_ILD(d, s1, OFFSET(java_arrayheader, size)); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), + s1, s2, 0, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), + s1, s2, 1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), + s1, s2, 1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), + s1, s2, 2, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + + var = &(jd->var[iptr->dst.varindex]); + + assert(var->flags & INMEMORY); + emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), + s1, s2, 3, REG_ITMP3); + emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, var->regoff * 4); + emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, + s1, s2, 3, REG_ITMP3); + emit_mov_reg_membase(cd, REG_ITMP3, REG_SP, var->regoff * 4 + 4); + break; + + case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2,3); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), + s1, s2, 2, d); + emit_store_dst(jd, iptr, d); + break; + + + case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + if (s3 >= EBP) { + /* because EBP, ESI, EDI have no xH and xL nibbles */ + M_INTMOVE(s3, REG_ITMP3); + s3 = REG_ITMP3; + } + emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), + s1, s2, 0); + break; + + case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), + s1, s2, 1); + break; + + case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), + s1, s2, 1); + break; + + case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), + s1, s2, 2); + break; + + case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + + var = &(jd->var[iptr->sx.s23.s3.varindex]); + + assert(var->flags & INMEMORY); + emit_mov_membase_reg(cd, REG_SP, var->regoff * 4, REG_ITMP3); + emit_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + , s1, s2, 3); + emit_mov_membase_reg(cd, REG_SP, var->regoff * 4 + 4, REG_ITMP3); + emit_mov_reg_memindex(cd, REG_ITMP3, + OFFSET(java_longarray, data[0]) + 4, s1, s2, 3); + break; + + case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_FTMP1); + emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2,2); + break; + + case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_FTMP1); + emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), + s1, s2, 3); + break; + + case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + + M_AST(s1, REG_SP, 0 * 4); + M_AST(s3, REG_SP, 1 * 4); + M_MOV_IMM(BUILTIN_canstore, REG_ITMP1); + M_CALL(REG_ITMP1); + M_TEST(REG_RESULT); + M_BEQ(0); + codegen_add_arraystoreexception_ref(cd); + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + s3 = emit_load_s3(jd, iptr, REG_ITMP3); + emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), + s1, s2, 2); + break; + + case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, + OFFSET(java_bytearray, data[0]), s1, s2, 0); + break; + + case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, + OFFSET(java_chararray, data[0]), s1, s2, 1); + break; + + case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, + OFFSET(java_shortarray, data[0]), s1, s2, 1); + break; + + case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_mov_imm_memindex(cd, iptr->sx.s23.s3.constval, + OFFSET(java_intarray, data[0]), s1, s2, 2); + break; + + case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_mov_imm_memindex(cd, + (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), + OFFSET(java_longarray, data[0]), s1, s2, 3); + emit_mov_imm_memindex(cd, + ((s4)iptr->sx.s23.s3.constval) >> 31, + OFFSET(java_longarray, data[0]) + 4, s1, s2, 3); + break; + + case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + if (INSTRUCTION_MUST_CHECK(iptr)) { + gen_nullptr_check(s1); + gen_bound_check; + } + emit_mov_imm_memindex(cd, 0, + OFFSET(java_objectarray, data[0]), s1, s2, 2); + break; + + + case ICMD_GETSTATIC: /* ... ==> ..., value */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + + codegen_addpatchref(cd, PATCHER_get_putstatic, + iptr->sx.s23.s3.uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + disp = (ptrint) &(fi->value); + } + + M_MOV_IMM(disp, REG_ITMP1); + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_ILD(d, REG_ITMP1, 0); + break; + case TYPE_LNG: + d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED); + M_LLD(d, REG_ITMP1, 0); + break; + case TYPE_FLT: + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_FLD(d, REG_ITMP1, 0); + break; + case TYPE_DBL: + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_DLD(d, REG_ITMP1, 0); + break; + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_PUTSTATIC: /* ..., value ==> ... */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + + codegen_addpatchref(cd, PATCHER_get_putstatic, + iptr->sx.s23.s3.uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + disp = (ptrint) &(fi->value); + } + + M_MOV_IMM(disp, REG_ITMP1); + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + s1 = emit_load_s1(jd, iptr, REG_ITMP2); + M_IST(s1, REG_ITMP1, 0); + break; + case TYPE_LNG: + s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED); + M_LST(s1, REG_ITMP1, 0); + break; + case TYPE_FLT: + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + emit_fstps_membase(cd, REG_ITMP1, 0); + break; + case TYPE_DBL: + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + emit_fstpl_membase(cd, REG_ITMP1, 0); + break; + } + break; + + case ICMD_PUTSTATICCONST: /* ... ==> ... */ + /* val = value (in current instruction) */ + /* following NOP) */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + + codegen_addpatchref(cd, PATCHER_get_putstatic, + uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + disp = (ptrint) &(fi->value); + } + + M_MOV_IMM(disp, REG_ITMP1); + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0); + break; + case TYPE_LNG: + M_IST_IMM(iptr->sx.s23.s2.constval & 0xffffffff, REG_ITMP1, 0); + M_IST_IMM(((s4)iptr->sx.s23.s2.constval) >> 31, REG_ITMP1, 4); + break; + default: + assert(0); + } + break; + + case ICMD_GETFIELD: /* .., objectref. ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + gen_nullptr_check(s1); + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + + codegen_addpatchref(cd, PATCHER_getfield, + iptr->sx.s23.s3.uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + disp = fi->offset; + } + + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_ILD32(d, s1, disp); + break; + case TYPE_LNG: + d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED); + M_LLD32(d, s1, disp); + break; + case TYPE_FLT: + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_FLD32(d, s1, disp); + break; + case TYPE_DBL: + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_DLD32(d, s1, disp); + break; + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + gen_nullptr_check(s1); + + /* must be done here because of code patching */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + } + + if (!IS_FLT_DBL_TYPE(fieldtype)) { + if (IS_2_WORD_TYPE(fieldtype)) + s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED); + else + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + } + else + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + codegen_addpatchref(cd, PATCHER_putfield, uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + disp = fi->offset; + } + + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + M_IST32(s2, s1, disp); + break; + case TYPE_LNG: + M_LST32(s2, s1, disp); + break; + case TYPE_FLT: + emit_fstps_membase32(cd, s1, disp); + break; + case TYPE_DBL: + emit_fstpl_membase32(cd, s1, disp); + break; + } + break; + + case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */ + /* val = value (in current instruction) */ + /* following NOP) */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + gen_nullptr_check(s1); + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + unresolved_field *uf = iptr->sx.s23.s3.uf; + + fieldtype = uf->fieldref->parseddesc.fd->type; + + codegen_addpatchref(cd, PATCHER_putfieldconst, + uf, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else + { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + disp = fi->offset; + } + + + switch (fieldtype) { + case TYPE_INT: + case TYPE_ADR: + M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp); + break; + case TYPE_LNG: + M_IST32_IMM(iptr->sx.s23.s2.constval & 0xffffffff, s1, disp); + M_IST32_IMM(((s4)iptr->sx.s23.s2.constval) >> 31, s1, disp + 4); + break; + default: + assert(0); + } + break; + + + /* branch operations **************************************************/ + + case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, REG_ITMP1_XPTR); + +#ifdef ENABLE_VERIFIER + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + codegen_addpatchref(cd, PATCHER_athrow_areturn, + iptr->sx.s23.s2.uc, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } +#endif /* ENABLE_VERIFIER */ + + M_CALL_IMM(0); /* passing exception pc */ + M_POP(REG_ITMP2_XPC); + + M_MOV_IMM(asm_handle_exception, REG_ITMP3); + M_JMP(REG_ITMP3); + break; + + case ICMD_INLINE_GOTO: +#if 0 + M_COPY(src, iptr->dst.var); +#endif + /* FALLTHROUGH! */ + + case ICMD_GOTO: /* ... ==> ... */ + +#if defined(ENABLE_SSA) + if ( ls != NULL ) { + last_cmd_was_goto = true; + /* In case of a Goto phimoves have to be inserted before the */ + /* jump */ + codegen_insert_phi_moves(cd, rd, ls, bptr); + } +#endif + M_JMP_IMM(0); + codegen_addreference(cd, iptr->dst.block); + ALIGNCODENOP; + break; + + case ICMD_JSR: /* ... ==> ... */ + + M_CALL_IMM(0); + codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block); + break; + + case ICMD_RET: /* ... ==> ... */ + /* s1.localindex = local variable */ + + var = &(jd->var[iptr->s1.varindex]); + if (var->flags & INMEMORY) { + M_ALD(REG_ITMP1, REG_SP, var->regoff * 4); + M_JMP(REG_ITMP1); + } + else + M_JMP(var->regoff); + break; + + case ICMD_IFNULL: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_TEST(s1); + M_BEQ(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFNONNULL: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_TEST(s1); + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFEQ: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BEQ(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFLT: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFLE: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BLE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFNE: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFGT: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IFGE: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_CMP_IMM(iptr->sx.val.i, s1); + M_BGE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LEQ: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + if (iptr->sx.val.l == 0) { + M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1); + M_OR(GET_HIGH_REG(s1), REG_ITMP1); + } + else { + M_LNGMOVE(s1, REG_ITMP12_PACKED); + M_XOR_IMM(iptr->sx.val.l, REG_ITMP1); + M_XOR_IMM(iptr->sx.val.l >> 32, REG_ITMP2); + M_OR(REG_ITMP2, REG_ITMP1); + } + M_BEQ(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LLT: /* ..., value ==> ... */ + + if (iptr->sx.val.l == 0) { + /* If high 32-bit are less than zero, then the 64-bits + are too. */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + M_CMP_IMM(0, s1); + M_BLT(0); + } + else { + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1)); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + M_BGT(6 + 6); + M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1)); + M_BB(0); + } + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LLE: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1)); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + M_BGT(6 + 6); + M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1)); + M_BBE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LNE: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + if (iptr->sx.val.l == 0) { + M_INTMOVE(GET_LOW_REG(s1), REG_ITMP1); + M_OR(GET_HIGH_REG(s1), REG_ITMP1); + } + else { + M_LNGMOVE(s1, REG_ITMP12_PACKED); + M_XOR_IMM(iptr->sx.val.l, REG_ITMP1); + M_XOR_IMM(iptr->sx.val.l >> 32, REG_ITMP2); + M_OR(REG_ITMP2, REG_ITMP1); + } + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LGT: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1)); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + M_BLT(6 + 6); + M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1)); + M_BA(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LGE: /* ..., value ==> ... */ + + if (iptr->sx.val.l == 0) { + /* If high 32-bit are greater equal zero, then the + 64-bits are too. */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + M_CMP_IMM(0, s1); + M_BGE(0); + } + else { + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1)); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + M_BLT(6 + 6); + M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1)); + M_BAE(0); + } + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ + case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BEQ(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, REG_ITMP1); + M_XOR(s2, REG_ITMP1); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + M_INTMOVE(s1, REG_ITMP2); + M_XOR(s2, REG_ITMP2); + M_OR(REG_ITMP1, REG_ITMP2); + M_BEQ(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ + case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, REG_ITMP1); + M_XOR(s2, REG_ITMP1); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + M_INTMOVE(s1, REG_ITMP2); + M_XOR(s2, REG_ITMP2); + M_OR(REG_ITMP1, REG_ITMP2); + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_BGT(2 + 6); + M_CMP(s2, s1); + M_BB(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_BLT(2 + 6); + M_CMP(s2, s1); + M_BA(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BLE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_BGT(2 + 6); + M_CMP(s2, s1); + M_BBE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BGE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s2, s1); + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_BLT(2 + 6); + M_CMP(s2, s1); + M_BAE(0); + codegen_addreference(cd, iptr->dst.block); + break; + + + case ICMD_IRETURN: /* ..., retvalue ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_RESULT); + M_INTMOVE(s1, REG_RESULT); + goto nowperformreturn; + + case ICMD_LRETURN: /* ..., retvalue ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(s1, REG_RESULT_PACKED); + goto nowperformreturn; + + case ICMD_ARETURN: /* ..., retvalue ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_RESULT); + M_INTMOVE(s1, REG_RESULT); + +#ifdef ENABLE_VERIFIER + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + codegen_addpatchref(cd, PATCHER_athrow_areturn, + iptr->sx.s23.s2.uc, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } +#endif /* ENABLE_VERIFIER */ + goto nowperformreturn; + + case ICMD_FRETURN: /* ..., retvalue ==> ... */ + case ICMD_DRETURN: + + s1 = emit_load_s1(jd, iptr, REG_FRESULT); + goto nowperformreturn; + + case ICMD_RETURN: /* ... ==> ... */ + +nowperformreturn: + { + s4 i, p; + + p = cd->stackframesize; + +#if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) + emit_verbosecall_exit(jd); +#endif + +#if defined(ENABLE_THREADS) + if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + M_ALD(REG_ITMP2, REG_SP, rd->memuse * 4); + + /* we need to save the proper return value */ + switch (iptr->opc) { + case ICMD_IRETURN: + case ICMD_ARETURN: + M_IST(REG_RESULT, REG_SP, rd->memuse * 4); + break; + + case ICMD_LRETURN: + M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4); + break; + + case ICMD_FRETURN: + emit_fstps_membase(cd, REG_SP, rd->memuse * 4); + break; + + case ICMD_DRETURN: + emit_fstpl_membase(cd, REG_SP, rd->memuse * 4); + break; + } + + M_AST(REG_ITMP2, REG_SP, 0); + M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3); + M_CALL(REG_ITMP3); + + /* and now restore the proper return value */ + switch (iptr->opc) { + case ICMD_IRETURN: + case ICMD_ARETURN: + M_ILD(REG_RESULT, REG_SP, rd->memuse * 4); + break; + + case ICMD_LRETURN: + M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 4); + break; + + case ICMD_FRETURN: + emit_flds_membase(cd, REG_SP, rd->memuse * 4); + break; + + case ICMD_DRETURN: + emit_fldl_membase(cd, REG_SP, rd->memuse * 4); + break; + } + } +#endif + + /* restore saved registers */ + + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_ALD(rd->savintregs[i], REG_SP, p * 4); + } + + for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { + p--; + emit_fldl_membase(cd, REG_SP, p * 4); + if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) { + assert(0); +/* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */ + } else { + assert(0); +/* emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */ + } + } + + /* deallocate stack */ + + if (cd->stackframesize) + M_AADD_IMM(cd->stackframesize * 4, REG_SP); + + emit_ret(cd); + } + break; + + + case ICMD_TABLESWITCH: /* ..., index ==> ... */ + { + s4 i, l; + branch_target_t *table; + + table = iptr->dst.table; + + l = iptr->sx.s23.s2.tablelow; + i = iptr->sx.s23.s3.tablehigh; + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, REG_ITMP1); + + if (l != 0) + M_ISUB_IMM(l, REG_ITMP1); + + i = i - l + 1; + + /* range check */ + M_CMP_IMM(i - 1, REG_ITMP1); + M_BA(0); + + codegen_addreference(cd, table[0].block); /* default target */ + + /* build jump table top down and use address of lowest entry */ + + table += i; + + while (--i >= 0) { + dseg_addtarget(cd, table->block); + --table; + } + + /* length of dataseg after last dseg_addtarget is used + by load */ + + M_MOV_IMM(0, REG_ITMP2); + dseg_adddata(cd); + emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1); + M_JMP(REG_ITMP1); + } + break; + + + case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ + { + s4 i; + lookup_target_t *lookup; + + lookup = iptr->dst.lookup; + + i = iptr->sx.s23.s2.lookupcount; + + MCODECHECK((i<<2)+8); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + + while (--i >= 0) { + M_CMP_IMM(lookup->value, s1); + M_BEQ(0); + codegen_addreference(cd, lookup->target.block); + lookup++; + } + + M_JMP_IMM(0); + + codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block); + } + break; + + case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + + bte = iptr->sx.s23.s3.bte; + md = bte->md; + goto gen_method; + + case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ + + case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ + case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ + case ICMD_INVOKEINTERFACE: + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + md = iptr->sx.s23.s3.um->methodref->parseddesc.md; + lm = NULL; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + md = lm->parseddesc; + } + +gen_method: + s3 = md->paramcount; + + MCODECHECK((s3 << 1) + 64); + + /* copy arguments to registers or stack location */ + + for (s3 = s3 - 1; s3 >= 0; s3--) { + s1 = iptr->sx.s23.s2.args[s3]; + var1 = &(jd->var[s1]); + + /* Already Preallocated (ARGVAR) ? */ + if (var1->flags & PREALLOC) + continue; + if (IS_INT_LNG_TYPE(var1->type)) { + if (!md->params[s3].inmemory) { + log_text("No integer argument registers available!"); + assert(0); + + } else { + if (IS_2_WORD_TYPE(var1->type)) { + d = emit_load(jd, iptr, var1, REG_ITMP12_PACKED); + M_LST(d, REG_SP, md->params[s3].regoff * 4); + } else { + d = emit_load(jd, iptr, var1, REG_ITMP1); + M_IST(d, REG_SP, md->params[s3].regoff * 4); + } + } + + } else { + if (!md->params[s3].inmemory) { + s1 = rd->argfltregs[md->params[s3].regoff]; + d = emit_load(jd, iptr, var1, s1); + M_FLTMOVE(d, s1); + + } else { + d = emit_load(jd, iptr, var1, REG_FTMP1); + if (IS_2_WORD_TYPE(var1->type)) + M_DST(d, REG_SP, md->params[s3].regoff * 4); + else + M_FST(d, REG_SP, md->params[s3].regoff * 4); + } + } + } /* end of for */ + + switch (iptr->opc) { + case ICMD_BUILTIN: + disp = (ptrint) bte->fp; + d = md->returntype.type; + + M_MOV_IMM(disp, REG_ITMP1); + M_CALL(REG_ITMP1); + + + if (INSTRUCTION_MUST_CHECK(iptr)) { + M_TEST(REG_RESULT); + M_BEQ(0); + codegen_add_fillinstacktrace_ref(cd); + } + break; + + case ICMD_INVOKESPECIAL: + M_ALD(REG_ITMP1, REG_SP, 0); + M_TEST(REG_ITMP1); + M_BEQ(0); + codegen_add_nullpointerexception_ref(cd); + + /* fall through */ + + case ICMD_INVOKESTATIC: + if (lm == NULL) { + unresolved_method *um = iptr->sx.s23.s3.um; + + codegen_addpatchref(cd, PATCHER_invokestatic_special, + um, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + d = md->returntype.type; + } + else { + disp = (ptrint) lm->stubroutine; + d = lm->parseddesc->returntype.type; + } + + M_MOV_IMM(disp, REG_ITMP2); + M_CALL(REG_ITMP2); + break; + + case ICMD_INVOKEVIRTUAL: + M_ALD(REG_ITMP1, REG_SP, 0 * 4); + gen_nullptr_check(REG_ITMP1); + + if (lm == NULL) { + unresolved_method *um = iptr->sx.s23.s3.um; + + codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + s1 = 0; + d = md->returntype.type; + } + else { + s1 = OFFSET(vftbl_t, table[0]) + + sizeof(methodptr) * lm->vftblindex; + d = md->returntype.type; + } + + M_ALD(REG_METHODPTR, REG_ITMP1, + OFFSET(java_objectheader, vftbl)); + M_ALD32(REG_ITMP3, REG_METHODPTR, s1); + M_CALL(REG_ITMP3); + break; + + case ICMD_INVOKEINTERFACE: + M_ALD(REG_ITMP1, REG_SP, 0 * 4); + gen_nullptr_check(REG_ITMP1); + + if (lm == NULL) { + unresolved_method *um = iptr->sx.s23.s3.um; + + codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + s1 = 0; + s2 = 0; + d = md->returntype.type; + } + else { + s1 = OFFSET(vftbl_t, interfacetable[0]) - + sizeof(methodptr) * lm->class->index; + + s2 = sizeof(methodptr) * (lm - lm->class->methods); + + d = md->returntype.type; + } + + M_ALD(REG_METHODPTR, REG_ITMP1, + OFFSET(java_objectheader, vftbl)); + M_ALD32(REG_METHODPTR, REG_METHODPTR, s1); + M_ALD32(REG_ITMP3, REG_METHODPTR, s2); + M_CALL(REG_ITMP3); + break; + } + + /* d contains return type */ + + if (d != TYPE_VOID) { +#if defined(ENABLE_SSA) + if ((ls == NULL) || (iptr->dst->varkind != TEMPVAR) || + (ls->lifetime[-iptr->dst->varnum-1].type != -1)) + /* a "living" stackslot */ +#endif + { + if (IS_INT_LNG_TYPE(d)) { + if (IS_2_WORD_TYPE(d)) { + s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(REG_RESULT_PACKED, s1); + } + else { + s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); + M_INTMOVE(REG_RESULT, s1); + } + } + else { + s1 = codegen_reg_of_dst(jd, iptr, REG_NULL); + } + emit_store_dst(jd, iptr, s1); + } + } + break; + + + case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ + /* val.a: (classinfo*) superclass */ + + /* superclass is an interface: + * + * OK if ((sub == NULL) || + * (sub->vftbl->interfacetablelength > super->index) && + * (sub->vftbl->interfacetable[-super->index] != NULL)); + * + * superclass is a class: + * + * OK if ((sub == NULL) || (0 + * <= (sub->vftbl->baseval - super->vftbl->baseval) <= + * super->vftbl->diffval)); + */ + + if (!(iptr->flags.bits & INS_FLAG_ARRAY)) { + /* object type cast-check */ + + classinfo *super; + vftbl_t *supervftbl; + s4 superindex; + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + super = NULL; + superindex = 0; + supervftbl = NULL; + } + else { + super = iptr->sx.s23.s3.c.cls; + superindex = super->index; + supervftbl = super->vftbl; + } + +#if defined(ENABLE_THREADS) + codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); +#endif + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + + /* calculate interface checkcast code size */ + + s2 = 2; /* mov_membase_reg */ + CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl)); + + s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ + + 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ + + 2 /* test */ + 6 /* jcc */); + + if (!super) + s2 += (opt_showdisassemble ? 5 : 0); + + /* calculate class checkcast code size */ + + s3 = 2; /* mov_membase_reg */ + CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl)); + + s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */; + +#if 0 + if (s1 != REG_ITMP1) { + a += 2; + CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval)); + + a += 2; + CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval)); + + a += 2; + + } else +#endif + { + s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ + + 5 /* mov_imm_reg */ + 2 /* mov_membase_reg */); + CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval)); + } + + s3 += 2 /* cmp */ + 6 /* jcc */; + + if (super == NULL) + s3 += (opt_showdisassemble ? 5 : 0); + + /* if class is not resolved, check which code to call */ + + if (super == NULL) { + M_TEST(s1); + M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3); + + codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + M_MOV_IMM(0, REG_ITMP2); /* super->flags */ + M_AND_IMM32(ACC_INTERFACE, REG_ITMP2); + M_BEQ(s2 + 5); + } + + /* interface checkcast code */ + + if ((super == NULL) || (super->flags & ACC_INTERFACE)) { + if (super != NULL) { + M_TEST(s1); + M_BEQ(s2); + } + + M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); + + if (super == NULL) { + codegen_addpatchref(cd, + PATCHER_checkcast_instanceof_interface, + iptr->sx.s23.s3.c.ref, + 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + M_ILD32(REG_ITMP3, + REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); + M_ISUB_IMM32(superindex, REG_ITMP3); + M_TEST(REG_ITMP3); + M_BLE(0); + codegen_add_classcastexception_ref(cd, s1); + M_ALD32(REG_ITMP3, REG_ITMP2, + OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)); + M_TEST(REG_ITMP3); + M_BEQ(0); + codegen_add_classcastexception_ref(cd, s1); + + if (super == NULL) + M_JMP_IMM(s3); + } + + /* class checkcast code */ + + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { + if (super != NULL) { + M_TEST(s1); + M_BEQ(s3); + } + + M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); + + if (super == NULL) { + codegen_addpatchref(cd, PATCHER_checkcast_class, + iptr->sx.s23.s3.c.ref, + 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + M_MOV_IMM(supervftbl, REG_ITMP3); +#if defined(ENABLE_THREADS) + codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); +#endif + M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); + + /* if (s1 != REG_ITMP1) { */ + /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */ + /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */ + /* #if defined(ENABLE_THREADS) */ + /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */ + /* #endif */ + /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */ + + /* } else { */ + M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); + M_ISUB(REG_ITMP3, REG_ITMP2); + M_MOV_IMM(supervftbl, REG_ITMP3); + M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); +#if defined(ENABLE_THREADS) + codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); +#endif + /* } */ + + M_CMP(REG_ITMP3, REG_ITMP2); + M_BA(0); /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */ + codegen_add_classcastexception_ref(cd, s1); + } + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + } + else { + /* array type cast-check */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP2); + M_AST(s1, REG_SP, 0 * 4); + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + M_AST_IMM(iptr->sx.s23.s3.c.cls, REG_SP, 1 * 4); + M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3); + M_CALL(REG_ITMP3); + + s1 = emit_load_s1(jd, iptr, REG_ITMP2); + M_TEST(REG_RESULT); + M_BEQ(0); + codegen_add_classcastexception_ref(cd, s1); + + d = codegen_reg_of_dst(jd, iptr, s1); + } + + M_INTMOVE(s1, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */ + /* val.a: (classinfo*) superclass */ + + /* superclass is an interface: + * + * return (sub != NULL) && + * (sub->vftbl->interfacetablelength > super->index) && + * (sub->vftbl->interfacetable[-super->index] != NULL); + * + * superclass is a class: + * + * return ((sub != NULL) && (0 + * <= (sub->vftbl->baseval - super->vftbl->baseval) <= + * super->vftbl->diffvall)); + */ + + { + classinfo *super; + vftbl_t *supervftbl; + s4 superindex; + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + super = NULL; + superindex = 0; + supervftbl = NULL; + + } else { + super = iptr->sx.s23.s3.c.cls; + superindex = super->index; + supervftbl = super->vftbl; + } + +#if defined(ENABLE_THREADS) + codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); +#endif + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s1 == d) { + M_INTMOVE(s1, REG_ITMP1); + s1 = REG_ITMP1; + } + + /* calculate interface instanceof code size */ + + s2 = 2; /* mov_membase_reg */ + CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl)); + + s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ + + 2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ + + 2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */); + + if (!super) + s2 += (opt_showdisassemble ? 5 : 0); + + /* calculate class instanceof code size */ + + s3 = 2; /* mov_membase_reg */ + CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl)); + s3 += 5; /* mov_imm_reg */ + s3 += 2; + CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval)); + s3 += 2; + CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval)); + s3 += 2; + CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval)); + + s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ + + 2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */); + + if (!super) + s3 += (opt_showdisassemble ? 5 : 0); + + M_CLR(d); + + /* if class is not resolved, check which code to call */ + + if (!super) { + M_TEST(s1); + M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3); + + codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + M_MOV_IMM(0, REG_ITMP3); /* super->flags */ + M_AND_IMM32(ACC_INTERFACE, REG_ITMP3); + M_BEQ(s2 + 5); + } + + /* interface instanceof code */ + + if (!super || (super->flags & ACC_INTERFACE)) { + if (super) { + M_TEST(s1); + M_BEQ(s2); + } + + M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); + + if (!super) { + codegen_addpatchref(cd, + PATCHER_checkcast_instanceof_interface, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + M_ILD32(REG_ITMP3, + REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); + M_ISUB_IMM32(superindex, REG_ITMP3); + M_TEST(REG_ITMP3); + + disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ + + 6 /* jcc */ + 5 /* mov_imm_reg */); + + M_BLE(disp); + M_ALD32(REG_ITMP1, REG_ITMP1, + OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)); + M_TEST(REG_ITMP1); +/* emit_setcc_reg(cd, CC_A, d); */ +/* emit_jcc(cd, CC_BE, 5); */ + M_BEQ(5); + M_MOV_IMM(1, d); + + if (!super) + M_JMP_IMM(s3); + } + + /* class instanceof code */ + + if (!super || !(super->flags & ACC_INTERFACE)) { + if (super) { + M_TEST(s1); + M_BEQ(s3); + } + + M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); + + if (!super) { + codegen_addpatchref(cd, PATCHER_instanceof_class, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + } + + M_MOV_IMM(supervftbl, REG_ITMP2); +#if defined(ENABLE_THREADS) + codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); +#endif + M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval)); + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); +#if defined(ENABLE_THREADS) + codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); +#endif + M_ISUB(REG_ITMP2, REG_ITMP1); + M_CLR(d); /* may be REG_ITMP2 */ + M_CMP(REG_ITMP3, REG_ITMP1); + M_BA(5); + M_MOV_IMM(1, d); + } + emit_store_dst(jd, iptr, d); + } + break; + + break; + + case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */ + + /* check for negative sizes and copy sizes to stack if necessary */ + + MCODECHECK((iptr->s1.argcount << 1) + 64); + + for (s1 = iptr->s1.argcount; --s1 >= 0; ) { + /* copy SAVEDVAR sizes to stack */ + s3 = iptr->sx.s23.s2.args[s1]; + var1 = &(jd->var[s3]); + + /* Already Preallocated (ARGVAR) ? */ + if (!(var1->flags & PREALLOC)) { + if (var1->flags & INMEMORY) { + M_ILD(REG_ITMP1, REG_SP, var1->regoff * 4); + M_IST(REG_ITMP1, REG_SP, (s1 + 3) * 4); + } + else + M_IST(var1->regoff, REG_SP, (s1 + 3) * 4); + } + } + + /* is a patcher function set? */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + codegen_addpatchref(cd, PATCHER_builtin_multianewarray, + iptr->sx.s23.s3.c.ref, 0); + + if (opt_showdisassemble) { + M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; + } + + disp = 0; + + } + else + disp = (ptrint) iptr->sx.s23.s3.c.cls; + + /* a0 = dimension count */ + + M_IST_IMM(iptr->s1.argcount, REG_SP, 0 * 4); + + /* a1 = arraydescriptor */ + + M_IST_IMM(disp, REG_SP, 1 * 4); + + /* a2 = pointer to dimensions = stack pointer */ + + M_MOV(REG_SP, REG_ITMP1); + M_AADD_IMM(3 * 4, REG_ITMP1); + M_AST(REG_ITMP1, REG_SP, 2 * 4); + + M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1); + M_CALL(REG_ITMP1); + + /* check for exception before result assignment */ + + M_TEST(REG_RESULT); + M_BEQ(0); + codegen_add_fillinstacktrace_ref(cd); + + s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); + M_INTMOVE(REG_RESULT, s1); + emit_store_dst(jd, iptr, s1); + break; + + default: + *exceptionptr = + new_internalerror("Unknown ICMD %d", iptr->opc); + return false; + } /* switch */ + + } /* for instruction */ + + /* copy values to interface registers */ + + len = bptr->outdepth; + MCODECHECK(64+len); +#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA) + if (!opt_lsra) +#endif +#if defined(ENABLE_SSA) + if ( ls != NULL ) { + /* by edge splitting, in Blocks with phi moves there can only */ + /* be a goto as last command, no other Jump/Branch Command */ + if (!last_cmd_was_goto) + codegen_insert_phi_moves(cd, rd, ls, bptr); + } + +#endif + + /* At the end of a basic block we may have to append some nops, + because the patcher stub calling code might be longer than the + actual instruction. So codepatching does not change the + following block unintentionally. */ + + if (cd->mcodeptr < cd->lastmcodeptr) { + while (cd->mcodeptr < cd->lastmcodeptr) { + M_NOP; + } + } + + } /* if (bptr -> flags >= BBREACHED) */ + } /* for basic block */ + + dseg_createlinenumbertable(cd); + + + /* generate exception and patcher stubs */ + + emit_exception_stubs(jd); + emit_patcher_stubs(jd); +#if 0 + emit_replacement_stubs(jd); +#endif + + codegen_finish(jd); + + /* everything's ok */ + + return true; +} +#else bool codegen(jitdata *jd) { methodinfo *m; @@ -4191,6 +8212,7 @@ gen_method: return true; } +#endif /* defined(NEW_VAR) */ #if defined(ENABLE_SSA) void codegen_insert_phi_moves(codegendata *cd, registerdata *rd, lsradata *ls, basicblock *bptr) { diff --git a/src/vm/jit/i386/codegen.h b/src/vm/jit/i386/codegen.h index 6515cc9a1..434e4264e 100644 --- a/src/vm/jit/i386/codegen.h +++ b/src/vm/jit/i386/codegen.h @@ -29,7 +29,7 @@ Changes: - $Id: codegen.h 5352 2006-09-05 22:51:48Z christian $ + $Id: codegen.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -146,7 +146,7 @@ #define M_COPY(from,to) _M_COPY((from),(to)); #endif -#define _M_COPY(s,d) emit_copy(jd, iptr, (s), (d)) +#define _M_COPY(s,d) emit_copy(jd, iptr, &(jd->var[(s)]), &(jd->var[(d)])) #define ICONST(d,c) \ do { \ diff --git a/src/vm/jit/i386/emit.c b/src/vm/jit/i386/emit.c index 46feebf6c..fbc38dcb7 100644 --- a/src/vm/jit/i386/emit.c +++ b/src/vm/jit/i386/emit.c @@ -28,7 +28,7 @@ Changes: - $Id: emit.c 5401 2006-09-07 12:52:31Z twisti $ + $Id: emit.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -62,7 +62,7 @@ *******************************************************************************/ -inline s4 emit_load(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg) +inline s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; s4 disp; @@ -105,7 +105,7 @@ inline s4 emit_load(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg) *******************************************************************************/ -inline s4 emit_load_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg) +inline s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src,s4 tempreg) { codegendata *cd; s4 disp; @@ -140,7 +140,7 @@ inline s4 emit_load_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg *******************************************************************************/ -inline s4 emit_load_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg) +inline s4 emit_load_high(jitdata *jd, instruction *iptr,varinfo *src,s4 tempreg) { codegendata *cd; s4 disp; @@ -176,12 +176,12 @@ inline s4 emit_load_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempre s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->s1.var; + src = &(jd->var[iptr->s1.varindex]); reg = emit_load(jd, iptr, src, tempreg); @@ -197,12 +197,12 @@ s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->sx.s23.s2.var; + src = &(jd->var[iptr->sx.s23.s2.varindex]); reg = emit_load(jd, iptr, src, tempreg); @@ -218,12 +218,12 @@ s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->sx.s23.s3.var; + src = &(jd->var[iptr->sx.s23.s3.varindex]); reg = emit_load(jd, iptr, src, tempreg); @@ -240,13 +240,13 @@ s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->s1.var; + src = &(jd->var[iptr->s1.varindex]); reg = emit_load_low(jd, iptr, src, tempreg); @@ -265,12 +265,12 @@ s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->sx.s23.s2.var; + src = &(jd->var[iptr->sx.s23.s2.varindex]); reg = emit_load_low(jd, iptr, src, tempreg); @@ -287,12 +287,12 @@ s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->s1.var; + src = &(jd->var[iptr->s1.varindex]); reg = emit_load_high(jd, iptr, src, tempreg); @@ -309,12 +309,12 @@ s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg) s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg) { - stackptr src; + varinfo *src; s4 reg; /* get required compiler data */ - src = iptr->sx.s23.s2.var; + src = &(jd->var[iptr->sx.s23.s2.varindex]); reg = emit_load_high(jd, iptr, src, tempreg); @@ -328,7 +328,7 @@ s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg) *******************************************************************************/ -inline void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d) +inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; @@ -362,7 +362,7 @@ inline void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d) *******************************************************************************/ -inline void emit_store_low(jitdata *jd, instruction *iptr, stackptr dst, s4 d) +inline void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; @@ -386,7 +386,7 @@ inline void emit_store_low(jitdata *jd, instruction *iptr, stackptr dst, s4 d) *******************************************************************************/ -inline void emit_store_high(jitdata *jd, instruction *iptr, stackptr dst, s4 d) +inline void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; @@ -413,9 +413,9 @@ inline void emit_store_high(jitdata *jd, instruction *iptr, stackptr dst, s4 d) void emit_store_dst(jitdata *jd, instruction *iptr, s4 d) { - stackptr dst; + varinfo *dst; - dst = iptr->dst.var; + dst = &(jd->var[iptr->dst.varindex]); emit_store(jd, iptr, dst, d); } @@ -427,16 +427,14 @@ void emit_store_dst(jitdata *jd, instruction *iptr, s4 d) *******************************************************************************/ -void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst) +void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) { codegendata *cd; - registerdata *rd; s4 s1, d; /* get required compiler data */ cd = jd->cd; - rd = jd->rd; if ((src->regoff != dst->regoff) || ((src->flags ^ dst->flags) & INMEMORY)) { @@ -447,9 +445,9 @@ void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst) if (IS_INMEMORY(src->flags)) { if (IS_LNG_TYPE(src->type)) - d = codegen_reg_of_var(rd, iptr->opc, dst, REG_ITMP12_PACKED); + d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED); else - d = codegen_reg_of_var(rd, iptr->opc, dst, REG_ITMP1); + d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1); s1 = emit_load(jd, iptr, src, d); } @@ -459,7 +457,7 @@ void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst) else s1 = emit_load(jd, iptr, src, REG_ITMP1); - d = codegen_reg_of_var(rd, iptr->opc, dst, s1); + d = codegen_reg_of_var(iptr->opc, dst, s1); } if (s1 != d) { diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index 8e0706526..8b4235c39 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -31,7 +31,7 @@ Christian Thalinger Christian Ullrich - $Id: jit.c 5343 2006-09-05 21:20:33Z twisti $ + $Id: jit.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -1327,8 +1327,10 @@ u1 *jit_compile(methodinfo *m) jd->flags = JITDATA_FLAG_PARSE; +#if defined(ENABLE_VERIFY) if (opt_verify) jd->flags |= JITDATA_FLAG_VERIFY; +#endif if (opt_prof) jd->flags |= JITDATA_FLAG_INSTRUMENT; @@ -1613,6 +1615,7 @@ static u1 *jit_compile_intern(jitdata *jd) DEBUG_JIT_COMPILEVERBOSE("Typechecking: "); /* call typecheck pass */ +#if !defined(NEW_VAR) if (!typecheck(jd)) { DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: "); @@ -1620,6 +1623,7 @@ static u1 *jit_compile_intern(jitdata *jd) } DEBUG_JIT_COMPILEVERBOSE("Typechecking done: "); +#endif } #endif RT_TIMING_GET_TIME(time_typecheck); diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index a8d0277b6..9418bbca5 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -30,7 +30,7 @@ Changes: Christian Thalinger Edwin Steiner - $Id: jit.h 5392 2006-09-07 09:40:25Z twisti $ + $Id: jit.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -38,6 +38,8 @@ #ifndef _JIT_H #define _JIT_H +#define NEW_VAR + /* forward typedefs ***********************************************************/ typedef struct jitdata jitdata; @@ -117,18 +119,19 @@ struct jitdata { #if defined(NEW_VAR) varinfo *var; - int vartop; + s4 vartop; - int varcount; - int localcount; - int *local_map; /* internal structure to rename(de-coallesc) locals */ - /* and keep the coalescing info for simplereg. */ - /* local_map[local_index * 5 + local_type] = new_index in */ - /* rd->var or LOCAL_UNUSED */ + s4 varcount; + s4 localcount; + s4 *local_map; /* internal structure to rename(de-coallesc) locals */ + /* and keep the coalescing info for simplereg. */ + /* local_map[local_index * 5 + local_type] = */ + /* new_index in rd->var or LOCAL_UNUSED */ + s4 *interface_map; /* like local_map for interfaces */ #endif }; -#define LOCAL_UNUSED -1 +#define UNUSED -1 #define JITDATA_FLAG_PARSE 0x00000001 #define JITDATA_FLAG_VERIFY 0x00000002 @@ -180,6 +183,9 @@ struct jitdata { /* using the same register/memory location */ #define STKEEP 32 /* to prevent reg_mark_copy to free this */ /* stackslot */ +#define PREALLOC 64 /* preallocated var like for ARGVARS. Used */ + /* with the new var system */ +#define OUTVAR 128 /* STACKVR flag for new var system */ #define IS_SAVEDVAR(x) ((x) & SAVEDVAR) #define IS_INMEMORY(x) ((x) & INMEMORY) @@ -287,7 +293,7 @@ typedef union { /*** dst operand ***/ typedef union { -#if defined(VAR_NEW) +#if defined(NEW_VAR) s4 varindex; #else stackptr var; @@ -297,7 +303,11 @@ typedef union { branch_target_t *table; /* for TABLESWITCH */ lookup_target_t *lookup; /* for LOOKUPSWITCH */ s4 insindex; /* used between parse and stack */ +#if defined(NEW_VAR) + s4 *dupslots; /* for SWAP, DUP* except DUP */ +#else stackptr *dupslots; /* for SWAP, DUP* except DUP */ +#endif } dst_operand_t; /*** flags (32 bits) ***/ @@ -438,9 +448,14 @@ struct basicblock { s4 icount; /* number of intermediate code instructions */ s4 mpc; /* machine code pc at start of block */ stackptr instack; /* stack at begin of basic block */ - stackptr *invars; /* array of in-variables at begin of block */ stackptr outstack; /* stack at end of basic block */ +#if defined(NEW_VAR) + s4 *invars; /* array of in-variables at begin of block */ + s4 *outvars; /* array of out-variables at end of block */ +#else + stackptr *invars; /* array of in-variables at begin of block */ stackptr *outvars; /* array of out-variables at end of block */ +#endif s4 indepth; /* stack depth at begin of basic block */ s4 outdepth; /* stack depth end of basic block */ diff --git a/src/vm/jit/parse.c b/src/vm/jit/parse.c index cf6e800f7..d855e2e9c 100644 --- a/src/vm/jit/parse.c +++ b/src/vm/jit/parse.c @@ -31,7 +31,7 @@ Joseph Wenninger Christian Thalinger - $Id: parse.c 5375 2006-09-06 16:01:23Z edwin $ + $Id: parse.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -389,7 +389,6 @@ fetch_opcode: INSTRUCTIONS_CHECK(1); /* translate this bytecode instruction */ - switch (opcode) { case JAVA_NOP: @@ -1506,11 +1505,11 @@ invoke_method: /* iterate over local_map[0..m->maxlocals*5] and set all existing */ /* index,type pairs (localmap[index*5+type]==1) to an unique value */ /* -> == new local var index */ - for(i = 0; i < (m->maxlocals * 5); i++, mapptr++) { + for(i = 0; i < (cd->maxlocals * 5); i++, mapptr++) { if (*mapptr) *mapptr = nlocals++; else - *mapptr = LOCAL_UNUSED; + *mapptr = UNUSED; } jd->localcount = nlocals; @@ -1520,8 +1519,15 @@ invoke_method: jd->varcount = nlocals + s_count + jd->new_basicblockcount * m->maxstack; /* out-stacks */ - jd->var_top = nlocals; + jd->vartop = nlocals; jd->var = DMNEW(varinfo, jd->varcount); + m->maxlocals = nlocals; + cd->maxlocals = nlocals; + + /* set types of all Locals in jd->var */ + for(mapptr = local_map, i = 0; i < (cd->maxlocals * 5); i++, mapptr++) + if (*mapptr != UNUSED) + jd->var[*mapptr].type = i%5; } #endif diff --git a/src/vm/jit/parse.h b/src/vm/jit/parse.h index 2a461cba4..6f247a5a0 100644 --- a/src/vm/jit/parse.h +++ b/src/vm/jit/parse.h @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: parse.h 5375 2006-09-06 16:01:23Z edwin $ + $Id: parse.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -221,7 +221,7 @@ # define LOCALTYPE_USED(index,type) \ do { \ - local_map[index * 5 +type] = 1; \ + local_map[(index) * 5 + (type)] = 1; \ } while (0) #else # define OP_LOCALINDEX(o,index) \ @@ -234,7 +234,7 @@ iptr->s1.localindex = (index); \ iptr->sx.val.i = (v); \ PINC - +#error 333 # define LOCALTYPE_USED(index,type) #endif /* defined(NEW_VAR) */ diff --git a/src/vm/jit/reg.c b/src/vm/jit/reg.c index 53898c091..cb6407d9a 100644 --- a/src/vm/jit/reg.c +++ b/src/vm/jit/reg.c @@ -32,7 +32,7 @@ Michael Starzinger Edwin Steiner - $Id: reg.c 5231 2006-08-11 10:13:28Z twisti $ + $Id: reg.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -62,7 +62,9 @@ void reg_setup(jitdata *jd) methodinfo *m; registerdata *rd; s4 i; +#if !defined(NEW_VAR) varinfo5 *v; +#endif /* get required compiler data */ @@ -198,6 +200,7 @@ void reg_setup(jitdata *jd) #if defined(HAS_4BYTE_STACKSLOT) rd->freemem_2 = DMNEW(s4, m->maxstack); #endif +#if !defined(NEW_VAR) rd->locals = DMNEW(varinfo5, m->maxlocals); rd->interfaces = DMNEW(varinfo5, m->maxstack); for (v = rd->locals, i = m->maxlocals; i > 0; v++, i--) { @@ -232,6 +235,7 @@ void reg_setup(jitdata *jd) v[0][TYPE_DBL].regoff = 0; v[0][TYPE_ADR].regoff = 0; } +#endif #if defined(SPECIALMEMUSE) # if defined(__DARWIN__) diff --git a/src/vm/jit/reg.h b/src/vm/jit/reg.h index c0f36cc1e..4042789f9 100644 --- a/src/vm/jit/reg.h +++ b/src/vm/jit/reg.h @@ -29,7 +29,7 @@ Changes: Christian Ullrich Edwin Steiner - $Id: reg.h 4710 2006-03-30 10:23:11Z twisti $ + $Id: reg.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -63,10 +63,10 @@ typedef struct varinfo varinfo5[5]; struct registerdata { +#if !defined(NEW_VAR) varinfo5 *locals; varinfo5 *interfaces; - - +#endif int intreg_ret; /* register to return integer values */ int fltreg_ret; /* register for return float values */ diff --git a/src/vm/jit/replace.c b/src/vm/jit/replace.c index de1a99891..060203db7 100644 --- a/src/vm/jit/replace.c +++ b/src/vm/jit/replace.c @@ -82,6 +82,7 @@ bool replace_create_replacement_points(jitdata *jd) { +#if 0 codeinfo *code; registerdata *rd; basicblock *bptr; @@ -242,6 +243,7 @@ bool replace_create_replacement_points(jitdata *jd) /* everything alright */ return true; +#endif } /* replace_free_replacement_points ********************************************* diff --git a/src/vm/jit/show.c b/src/vm/jit/show.c index b1549e4e3..937bf4613 100644 --- a/src/vm/jit/show.c +++ b/src/vm/jit/show.c @@ -68,7 +68,7 @@ static java_objectheader *show_global_lock; /* forward declarations *******************************************************/ #if !defined(NDEBUG) -static void new_show_variable_array(jitdata *jd, stackptr *vars, int n, int stage); +static void new_show_variable_array(jitdata *jd, s4 *vars, int n, int stage); #endif @@ -185,37 +185,38 @@ void new_show_method(jitdata *jd, int stage) printf(" %3d: ", i); #if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) - for (j = TYPE_INT; j <= TYPE_ADR; j++) { +/* for (j = TYPE_INT; j <= TYPE_ADR; j++) { */ # if defined(ENABLE_INTRP) if (!opt_intrp) { # endif - if (rd->locals[i][j].type >= 0) { - printf(" (%s) ", jit_type[j]); +/* if (rd->locals[i][j].type >= 0) { */ + printf(" (%s) ", jit_type[jd->var[i].type]); if (stage >= SHOW_REGS) { - if (rd->locals[i][j].flags & INMEMORY) - printf("m%2d", rd->locals[i][j].regoff); + if (jd->var[i].flags & INMEMORY) + printf("m%2d", jd->var[i].regoff); # ifdef HAS_ADDRESS_REGISTER_FILE - else if (j == TYPE_ADR) - printf("r%02d", rd->locals[i][j].regoff); + else if (jd->var[i].type == TYPE_ADR) + printf("r%02d", jd->var[i].regoff); # endif - else if ((j == TYPE_FLT) || (j == TYPE_DBL)) - printf("f%02d", rd->locals[i][j].regoff); + else if ((jd->var[i].type == TYPE_FLT) || + (jd->var[i].type == TYPE_DBL)) + printf("f%02d", jd->var[i].regoff); else { # if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) if (IS_2_WORD_TYPE(j)) printf(" %3s/%3s", - regs[GET_LOW_REG(rd->locals[i][j].regoff)], - regs[GET_HIGH_REG(rd->locals[i][j].regoff)]); + regs[GET_LOW_REG(jd->var[i].regoff)], + regs[GET_HIGH_REG(jd->var[i].regoff)]); else # endif - printf("%3s", regs[rd->locals[i][j].regoff]); + printf("%3s", regs[jd->var[i].regoff]); } } - } +/* } */ # if defined(ENABLE_INTRP) } # endif - } +/* } */ #endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */ printf("\n"); @@ -223,90 +224,36 @@ void new_show_method(jitdata *jd, int stage) printf("\n"); } - if (stage >= SHOW_STACK && rd) { -#if defined(ENABLE_LSRA) || defined(ENABLE_SSA) - if (!opt_lsra) { -#endif -#if defined(ENABLE_INTRP) - if (!opt_intrp) { -#endif - printf("Interface Table:\n"); - for (i = 0; i < cd->maxstack; i++) { - if ((rd->interfaces[i][0].type >= 0) || - (rd->interfaces[i][1].type >= 0) || - (rd->interfaces[i][2].type >= 0) || - (rd->interfaces[i][3].type >= 0) || - (rd->interfaces[i][4].type >= 0)) { - printf(" %3d: ", i); - -#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) -# if defined(ENABLE_INTRP) - if (!opt_intrp) { -# endif - for (j = TYPE_INT; j <= TYPE_ADR; j++) { - if (rd->interfaces[i][j].type >= 0) { - printf(" (%s) ", jit_type[j]); - if (stage >= SHOW_REGS) { - if (rd->interfaces[i][j].flags & SAVEDVAR) { - if (rd->interfaces[i][j].flags & INMEMORY) - printf("M%2d", rd->interfaces[i][j].regoff); -#ifdef HAS_ADDRESS_REGISTER_FILE - else if (j == TYPE_ADR) - printf("R%02d", rd->interfaces[i][j].regoff); -#endif - else if ((j == TYPE_FLT) || (j == TYPE_DBL)) - printf("F%02d", rd->interfaces[i][j].regoff); - else { -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (IS_2_WORD_TYPE(j)) - printf(" %3s/%3s", - regs[GET_LOW_REG(rd->interfaces[i][j].regoff)], - regs[GET_HIGH_REG(rd->interfaces[i][j].regoff)]); - else -#endif - printf("%3s",regs[rd->interfaces[i][j].regoff]); - } - } - else { - if (rd->interfaces[i][j].flags & INMEMORY) - printf("m%2d", rd->interfaces[i][j].regoff); -#ifdef HAS_ADDRESS_REGISTER_FILE - else if (j == TYPE_ADR) - printf("r%02d", rd->interfaces[i][j].regoff); -#endif - else if ((j == TYPE_FLT) || (j == TYPE_DBL)) - printf("f%02d", rd->interfaces[i][j].regoff); - else { -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (IS_2_WORD_TYPE(j)) - printf(" %3s/%3s", - regs[GET_LOW_REG(rd->interfaces[i][j].regoff)], - regs[GET_HIGH_REG(rd->interfaces[i][j].regoff)]); - else -#endif - printf("%3s",regs[rd->interfaces[i][j].regoff]); - } - } - } - } - } - printf("\n"); -# if defined(ENABLE_INTRP) - } -# endif -#endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */ - + if (cd->maxlocals > 0) { + for (i = 0; i < 5; i++) { + printf("%5s ",jit_type[i]); + for (j = 0; j < cd->maxlocals; j++) + printf("%3i ",jd->local_map[j*5+i]); + printf("\n"); } + printf("\n"); } - printf("\n"); -#if defined(ENABLE_INTRP) + printf("Interface Table:(In/Outvars)\n"); + if (cd->maxstack > 0) { + bool exist = false; + s4 *mapptr = jd->interface_map; + + /* look if there exist IN/OUTVARS */ + if (mapptr != NULL) { + for (i = 0; (i < (5 * cd->maxstack)) && !exist; i++, mapptr++) + exist = (*mapptr != UNUSED); + + if (exist) + for (i = 0; i < 5; i++) { + printf("%5s ",jit_type[i]); + for (j = 0; j < cd->maxstack; j++) + printf("%3i ",jd->interface_map[j*5+i]); + printf("\n"); + } + printf("\n"); } -#endif -#if defined(ENABLE_LSRA) || defined(ENABLE_SSA) - } -#endif - } /* if >= SHOW_STACK */ + } if (code->rplpoints) { printf("Replacement Points:\n"); @@ -552,196 +499,125 @@ void new_show_basicblock(jitdata *jd, basicblock *bptr, int stage) } #define SHOW_STACKVAR(sp) \ - new_show_stackvar(jd, (sp), stage) + new_show_stackvar(jd, (sp), stage) #define SHOW_S1(iptr) \ if (stage >= SHOW_STACK) { \ - SHOW_STACKVAR(iptr->s1.var); \ + SHOW_STACKVAR(iptr->s1.varindex); \ } #define SHOW_S2(iptr) \ if (stage >= SHOW_STACK) { \ - SHOW_STACKVAR(iptr->sx.s23.s2.var); \ + SHOW_STACKVAR(iptr->sx.s23.s2.varindex); \ } #define SHOW_S3(iptr) \ - if (stage >= SHOW_STACK) { \ - SHOW_STACKVAR(iptr->sx.s23.s3.var); \ - } + if (stage >= SHOW_STACK) { \ + SHOW_STACKVAR(iptr->sx.s23.s3.varindex); \ + } #define SHOW_DST(iptr) \ - if (stage >= SHOW_STACK) { \ - printf("=> "); \ - SHOW_STACKVAR(iptr->dst.var); \ - } + if (stage >= SHOW_STACK) { \ + printf("=> "); \ + SHOW_STACKVAR(iptr->dst.varindex); \ + } #define SHOW_S1_LOCAL(iptr) \ - if (stage >= SHOW_STACK) { \ - printf("L%d ", iptr->s1.localindex); \ - } + if (stage >= SHOW_STACK) { \ + printf("L%d ", iptr->s1.varindex); \ + } #define SHOW_DST_LOCAL(iptr) \ - if (stage >= SHOW_STACK) { \ - printf("=> L%d ", iptr->dst.localindex); \ - } + if (stage >= SHOW_STACK) { \ + printf("=> L%d ", iptr->dst.varindex); \ + } -static void new_show_stackvar(jitdata *jd, stackptr sp, int stage) +static void new_show_stackvar(jitdata *jd, s4 index, int stage) { char type; + varinfo *sp; + + sp = &(jd->var[index]); switch (sp->type) { - case TYPE_INT: type = 'i'; break; - case TYPE_LNG: type = 'l'; break; - case TYPE_FLT: type = 'f'; break; - case TYPE_DBL: type = 'd'; break; - case TYPE_ADR: type = 'a'; break; - default: type = '?'; + case TYPE_INT: type = 'i'; break; + case TYPE_LNG: type = 'l'; break; + case TYPE_FLT: type = 'f'; break; + case TYPE_DBL: type = 'd'; break; + case TYPE_ADR: type = 'a'; break; + default: type = '?'; } - +#if 0 switch (sp->varkind) { - case TEMPVAR: printf("T%c%d", type, (int) (sp - jd->new_stack)); break; - case LOCALVAR: printf("L%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; - case STACKVAR: printf("I%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; - case ARGVAR: printf("A%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; - default: printf("?%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; + case TEMPVAR: printf("T%c%d", type, (int) (sp - jd->new_stack)); break; + case LOCALVAR: printf("L%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; + case STACKVAR: printf("I%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; + case ARGVAR: printf("A%c%d(T%d)", type, sp->varnum, (int) (sp - jd->new_stack)); break; + default: printf("?%c%d", type, index); break; } +#endif + + if (sp->flags & PREALLOC) + printf("A"); + else if (sp->flags & OUTVAR) + printf("I"); + else if (index < jd->localcount) + printf("L"); + else printf("T"); + printf("%c%d", type, index); if (stage >= SHOW_REGS) { putchar('('); - if (sp->flags & SAVEDVAR) { - switch (sp->varkind) { - case TEMPVAR: - if (sp->flags & INMEMORY) - printf("M%02d", sp->regoff); + if (sp->flags & INMEMORY) + printf("M%02d", sp->regoff); #ifdef HAS_ADDRESS_REGISTER_FILE - else if (sp->type == TYPE_ADR) - printf("R%02d", sp->regoff); + else if (sp->type == TYPE_ADR) + printf("R%02d", sp->regoff); #endif - else if (IS_FLT_DBL_TYPE(sp->type)) - printf("F%02d", sp->regoff); - else { + else if (IS_FLT_DBL_TYPE(sp->type)) + printf("F%02d", sp->regoff); + else { #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (IS_2_WORD_TYPE(sp->type)) { + if (IS_2_WORD_TYPE(sp->type)) { # if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) # if defined(ENABLE_INTRP) - if (opt_intrp) - printf("%3d/%3d", GET_LOW_REG(sp->regoff), - GET_HIGH_REG(sp->regoff)); - else + if (opt_intrp) + printf("%3d/%3d", GET_LOW_REG(sp->regoff), + GET_HIGH_REG(sp->regoff)); + else # endif - printf("%3s/%3s", regs[GET_LOW_REG(sp->regoff)], - regs[GET_HIGH_REG(sp->regoff)]); + printf("%3s/%3s", regs[GET_LOW_REG(sp->regoff)], + regs[GET_HIGH_REG(sp->regoff)]); # else - printf("%3d/%3d", GET_LOW_REG(sp->regoff), - GET_HIGH_REG(sp->regoff)); + printf("%3d/%3d", GET_LOW_REG(sp->regoff), + GET_HIGH_REG(sp->regoff)); # endif - } - else + } + else #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */ - { + { #if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) # if defined(ENABLE_INTRP) - if (opt_intrp) - printf("%3d", sp->regoff); - else -# endif - printf("%3s", regs[sp->regoff]); -#else - printf("%3d", sp->regoff); -#endif - } - } - break; - case STACKVAR: - printf("I%02d", sp->varnum); - break; - case LOCALVAR: - printf("L%02d", sp->varnum); - break; - case ARGVAR: - if (sp->varnum == -1) { - /* Return Value */ - /* varkind ARGVAR "misused for this special case */ - printf(" V0"); - } - else /* "normal" Argvar */ - printf("A%02d", sp->varnum); - break; - default: - printf("!xx {kind=%d, num=%d}", sp->varkind, sp->varnum); - } - } - else { /* not SAVEDVAR */ - switch (sp->varkind) { - case TEMPVAR: - if (sp->flags & INMEMORY) - printf("m%02d", sp->regoff); -#ifdef HAS_ADDRESS_REGISTER_FILE - else if (sp->type == TYPE_ADR) - printf("r%02d", sp->regoff); -#endif - else if (IS_FLT_DBL_TYPE(sp->type)) - printf("f%02d", sp->regoff); - else { -#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) - if (IS_2_WORD_TYPE(sp->type)) { -# if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) -# if defined(ENABLE_INTRP) - if (opt_intrp) - printf("%3d/%3d", GET_LOW_REG(sp->regoff), - GET_HIGH_REG(sp->regoff)); - else -# endif - printf("%3s/%3s", regs[GET_LOW_REG(sp->regoff)], - regs[GET_HIGH_REG(sp->regoff)]); -# else - printf("%3d/%3d", GET_LOW_REG(sp->regoff), - GET_HIGH_REG(sp->regoff)); -# endif - } + if (opt_intrp) + printf("%3d", sp->regoff); else -#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */ - { -#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) -# if defined(ENABLE_INTRP) - if (opt_intrp) - printf("%3d", sp->regoff); - else # endif - printf("%3s", regs[sp->regoff]); + printf("%3s", regs[sp->regoff]); #else - printf("%3d", sp->regoff); + printf("%3d", sp->regoff); #endif - } } - break; - case STACKVAR: - printf("i%02d", sp->varnum); - break; - case LOCALVAR: - printf("l%02d", sp->varnum); - break; - case ARGVAR: - if (sp->varnum == -1) { - /* Return Value */ - /* varkind ARGVAR "misused for this special case */ - printf(" v0"); - } - else /* "normal" Argvar */ - printf("a%02d", sp->varnum); - break; - default: - printf("?xx {kind=%d, num=%d}", sp->varkind, sp->varnum); - } } + putchar(')'); } putchar(' '); + fflush(stdout); } -static void new_show_variable_array(jitdata *jd, stackptr *vars, int n, int stage) +static void new_show_variable_array(jitdata *jd, s4 *vars, int n, int stage) { int i; @@ -760,7 +636,7 @@ void new_show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage) branch_target_t *table; lookup_target_t *lookup; constant_FMIref *fmiref; - stackptr *argp; + s4 *argp; s4 i; /* get the opcode and the condition */ @@ -1245,8 +1121,8 @@ void new_show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage) break; case ICMD_DUP: - case ICMD_COPY: - case ICMD_MOVE: +/* case ICMD_COPY: */ +/* case ICMD_MOVE: */ SHOW_S1(iptr); SHOW_DST(iptr); break; @@ -1326,6 +1202,7 @@ void new_show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage) break; } + fflush(stdout); } #endif /* !defined(NDEBUG) */ diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index 4959c114c..6fc4d1e4d 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -30,7 +30,7 @@ Christian Thalinger Christian Ullrich - $Id: stack.c 5385 2006-09-06 21:40:50Z twisti $ + $Id: stack.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -144,15 +144,65 @@ bool stack_init(void) *******************************************************************************/ #if defined(NEW_VAR) -#define GET_NEW_INDEX(new_varindex) \ +#define GET_NEW_INDEX(new_varindex) \ do { \ assert(jd->vartop < jd->varcount); \ (new_varindex) = (jd->vartop)++; \ - } while(0) + } while (0) -/* not implemented now, can be used to reuse varindices */ +/* not implemented now, can be used to reuse varindices */ +/* pay attention to not release a localvar once implementing it! */ #define RELEASE_INDEX(varindex) +/* with the new vars setting an OUTVAR is not as trivial as changing */ +/* the varkind before. If varindex was a localvar, a new TEMPVAR has */ +/* to be created for the slot and the OUTVAR flag set */ +#define SET_OUTVAR(sp) \ + do { \ + if (IS_LOCALVAR((sp))) { \ + GET_NEW_INDEX(new_index); \ + sp->varnum = new_index; \ + sp->flags = 0; \ + } \ + SET_OUTVAR_BY_INDEX((sp)->varnum); \ + } while(0) + +#define SET_OUTVAR_BY_INDEX(index) \ + do { \ + assert(index >= jd->localcount); \ + jd->var[(index)].flags |=OUTVAR; \ + } while (0); + + +#define SET_TEMPVAR(sp) \ + do { \ + if ( IS_LOCALVAR( (sp) ) ) { \ + GET_NEW_INDEX(new_index); \ + (sp)->varnum = new_index; \ + jd->var[(sp)->varnum].flags = copy->flags; \ + } \ + jd->var[(sp)->varnum].flags &= ~(OUTVAR | PREALLOC); \ + } while (0); + +#define SET_PREALLOC(sp) \ + do { \ + assert(!IS_LOCALVAR((sp))); \ + jd->var[(sp)->varnum].flags |= PREALLOC; \ + } while (0); + +#define IS_OUTVAR(sp) \ + (jd->var[(sp)->varnum].flags & OUTVAR) + +#define IS_PREALLOC(sp) \ + (jd->var[(sp)->varnum].flags & PREALLOC) + +#define IS_TEMPVAR(sp) \ + ( (jd->var[(sp)->varnum].flags & (OUTVAR | PREALLOC) \ + && (((sp)->varnum < jd->localcount)) == 0) ) + +#define IS_LOCALVAR(sp) \ + ((sp)->varnum < jd->localcount) + #define CLR_S1 \ (iptr->s1.varindex = -1) @@ -201,10 +251,10 @@ bool stack_init(void) #define CLR_DST \ (iptr->dst.varindex = -1) -#define DST(typed, varindex) \ +#define DST(typed, index) \ do { \ - NEWSTACKn((varindex)); \ - iptr->dst.varindex = (varindex); \ + NEWSTACKn((typed),(index)); \ + iptr->dst.varindex = (index); \ } while (0) #define DST_LOCALVAR(typed, index) \ @@ -238,7 +288,7 @@ bool stack_init(void) do { \ POP_S1(type1); \ GET_NEW_INDEX(new_index); \ - DST(typed, new_index; \ + DST(typed, new_index); \ } while (0) #define OP2_1(type1, type2, typed) \ @@ -545,6 +595,12 @@ bool new_stack_analyse(jitdata *jd) #endif #if defined(NEW_VAR) + /* init jd->interface_map */ + + jd->interface_map = DMNEW(s4, m->maxstack * 5); + for (i = 0; i < m->maxstack * 5; i++) + jd->interface_map[i] = UNUSED; + last_store_boundary = DMNEW(stackptr, jd->localcount); #else last_store_boundary = DMNEW(stackptr , cd->maxlocals); @@ -572,7 +628,10 @@ bool new_stack_analyse(jitdata *jd) GET_NEW_INDEX(new_index); bptr->invars = DMNEW(s4, 1); bptr->invars[0] = new_index; - NEWSTACK(TYPE_ADR, STACKVAR,new_index); + NEWSTACK(TYPE_ADR, STACKVAR, new_index); + + jd->interface_map[0 * 5 + TYPE_ADR] = new_index; + SET_OUTVAR_BY_INDEX(new_index); #else bptr->invars = DMNEW(stackptr, 1); bptr->invars[0] = new; @@ -600,7 +659,11 @@ bool new_stack_analyse(jitdata *jd) while (--b_count >= 0) { #if defined(STACK_VERBOSE) - printf("ANALYZING BLOCK L%03d\n", bptr->nr); + printf("----\nANALYZING BLOCK L%03d ", bptr->nr); + if (bptr->type == BBTYPE_EXH) printf("EXH\n"); + else if (bptr->type == BBTYPE_SBR) printf("SBR\n"); + else printf("STD\n"); + #endif if (bptr->flags == BBDELETED) { @@ -661,14 +724,31 @@ bool new_stack_analyse(jitdata *jd) /* XXX store the start of the block's stack representation */ bptr->stack = new; +#if defined(STACK_VERBOSE) + printf("INVARS\n"); + for( copy = bptr->instack; copy; copy = copy->prev ) { + printf("%2d(%d", copy->varnum, copy->type); + if (IS_OUTVAR(copy)) + printf("S"); + if (IS_PREALLOC(copy)) + printf("A"); + printf(") "); + } + printf("\n"); +#endif /* iterate over ICMDs ****************************************/ while (--len >= 0) { #if defined(STACK_VERBOSE) new_show_icmd(jd, iptr, false, SHOW_PARSE); printf("\n"); for( copy = curstack; copy; copy = copy->prev ) { - printf("%d ", copy->type); + printf("%2d(%d", copy->varnum, copy->type); + if (IS_OUTVAR(copy)) + printf("S"); + if (IS_PREALLOC(copy)) + printf("A"); + printf(") "); } printf("\n"); #endif @@ -1569,12 +1649,12 @@ normal_ACONST: i = stackdepth - 1; while (copy) { if ((copy->varkind == LOCALVAR) && - (copy->varnum == iptr->s1.localindex)) + (copy->varnum == iptr->s1.varindex)) { copy->varkind = TEMPVAR; #if defined(NEW_VAR) - GET_NEW_INDEX(new_index); - copy->varnum = new_index; + assert(IS_LOCALVAR(copy)); + SET_TEMPVAR(copy); #else copy->varnum = i; #endif @@ -1602,7 +1682,7 @@ normal_ACONST: i = opcode - ICMD_ISTORE; /* type */ #if defined(NEW_VAR) j = iptr->dst.varindex = - jd->local_map[iptr->dst.varindex * 5 + 1]: + jd->local_map[iptr->dst.varindex * 5 + i]; #else j = iptr->dst.localindex; /* index */ @@ -1635,8 +1715,8 @@ normal_ACONST: { copy->varkind = TEMPVAR; #if defined(NEW_VAR) - GET_NEW_INDEX(new_index); - copy->varnum = new_index; + assert(IS_LOCALVAR(copy)); + SET_TEMPVAR(copy); #else copy->varnum = i; #endif @@ -1647,7 +1727,7 @@ normal_ACONST: /* if the variable is already coalesced, don't bother */ - if (curstack->varkind == STACKVAR + if (IS_OUTVAR(curstack) || (curstack->varkind == LOCALVAR && curstack->varnum != j)) goto store_tail; @@ -1662,7 +1742,7 @@ normal_ACONST: if (curstack < last_pei_boundary) goto assume_conflict; - /* there is no non-consuming USE while curstack is live */ + /*there is no non-consuming USE while curstack is live*/ if (curstack < last_dup_boundary) goto assume_conflict; @@ -1677,8 +1757,12 @@ normal_ACONST: /* coalesce the temporary variable with Lj */ #if defined(NEW_VAR) - assert(currstack->varkind == TEMPVAR); - RELEASE_INDEX(curstack->varnum); + assert( (CURKIND == TEMPVAR) || (CURKIND == UNDEFVAR)); + assert(!IS_LOCALVAR(curstack)); + assert(!IS_OUTVAR(curstack)); + assert(!IS_PREALLOC(curstack)); + + RELEASE_INDEX(curstack); #endif curstack->varkind = LOCALVAR; curstack->varnum = j; @@ -1691,8 +1775,8 @@ assume_conflict: { curstack->varkind = TEMPVAR; #if defined(NEW_VAR) - GET_NEW_INDEX(new_index); - curstack->varnum = new_index; + assert(IS_LOCALVAR(curstack)); + SET_TEMPVAR(curstack); #else curstack->varnum = stackdepth-1; #endif @@ -1727,6 +1811,13 @@ store_tail: copy = curstack; while (copy) { +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= SAVEDVAR; + /* in case copy->varnum is/will be a LOCALVAR */ + /* once and set back to a non LOCALVAR */ + /* the correct SAVEDVAR flag has to be */ + /* remembered in copy->flags, too */ +#endif copy->flags |= SAVEDVAR; copy = copy->prev; } @@ -1968,6 +2059,19 @@ icmd_DUP: goto throw_stack_category_error; } #endif +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(s4, 2 + 2); + /* XXX live through */ + iptr->dst.dupslots[0] = curstack->prev->varnum; + /* XXX live through */ + iptr->dst.dupslots[1] = curstack->varnum; + copy = curstack; + + DUP_SLOT(copy->prev); + iptr->dst.dupslots[2+0] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[2+1] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 2 + 2); iptr->dst.dupslots[0] = curstack->prev; /* XXX live through */ iptr->dst.dupslots[1] = curstack; /* XXX live through */ @@ -1976,6 +2080,7 @@ icmd_DUP: iptr->dst.dupslots[2+0] = curstack; DUP_SLOT(iptr->dst.dupslots[1]); iptr->dst.dupslots[2+1] = curstack; +#endif last_dup_boundary = new; stackdepth += 2; } @@ -1994,6 +2099,20 @@ icmd_DUP: #endif icmd_DUP_X1: +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(int, 2 + 3); + iptr->dst.dupslots[0] = curstack->prev->varnum; + iptr->dst.dupslots[1] = curstack->varnum; + copy = curstack; + POPANY; POPANY; + + DUP_SLOT(copy); + iptr->dst.dupslots[2+0] = curstack->varnum; + DUP_SLOT(copy->prev); + iptr->dst.dupslots[2+1] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[2+2] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 2 + 3); iptr->dst.dupslots[0] = curstack->prev; iptr->dst.dupslots[1] = curstack; @@ -2005,6 +2124,7 @@ icmd_DUP_X1: iptr->dst.dupslots[2+1] = curstack; DUP_SLOT(iptr->dst.dupslots[1]); iptr->dst.dupslots[2+2] = curstack; +#endif last_dup_boundary = new; stackdepth++; break; @@ -2034,6 +2154,25 @@ icmd_DUP_X1: #endif icmd_DUP2_X1: +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(s4, 3 + 5); + iptr->dst.dupslots[0] =curstack->prev->prev->varnum; + iptr->dst.dupslots[1] = curstack->prev->varnum; + iptr->dst.dupslots[2] = curstack->varnum; + copy = curstack; + POPANY; POPANY; POPANY; + + DUP_SLOT(copy->prev); + iptr->dst.dupslots[3+0] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[3+1] = curstack->varnum; + DUP_SLOT(copy->prev->prev); + iptr->dst.dupslots[3+2] = curstack->varnum; + DUP_SLOT(copy->prev); + iptr->dst.dupslots[3+3] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[3+4] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 3 + 5); iptr->dst.dupslots[0] = curstack->prev->prev; iptr->dst.dupslots[1] = curstack->prev; @@ -2050,6 +2189,7 @@ icmd_DUP2_X1: iptr->dst.dupslots[3+3] = curstack; DUP_SLOT(iptr->dst.dupslots[2]); iptr->dst.dupslots[3+4] = curstack; +#endif last_dup_boundary = new; stackdepth += 2; } @@ -2081,6 +2221,23 @@ icmd_DUP2_X1: } #endif icmd_DUP_X2: +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(s4, 3 + 4); + iptr->dst.dupslots[0] =curstack->prev->prev->varnum; + iptr->dst.dupslots[1] = curstack->prev->varnum; + iptr->dst.dupslots[2] = curstack->varnum; + copy = curstack; + POPANY; POPANY; POPANY; + + DUP_SLOT(copy); + iptr->dst.dupslots[3+0] = curstack->varnum; + DUP_SLOT(copy->prev->prev); + iptr->dst.dupslots[3+1] = curstack->varnum; + DUP_SLOT(copy->prev); + iptr->dst.dupslots[3+2] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[3+3] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 3 + 4); iptr->dst.dupslots[0] = curstack->prev->prev; iptr->dst.dupslots[1] = curstack->prev; @@ -2095,6 +2252,7 @@ icmd_DUP_X2: iptr->dst.dupslots[3+2] = curstack; DUP_SLOT(iptr->dst.dupslots[2]); iptr->dst.dupslots[3+3] = curstack; +#endif last_dup_boundary = new; stackdepth++; } @@ -2147,6 +2305,31 @@ icmd_DUP_X2: goto throw_stack_category_error; } #endif + +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(s4, 4 + 6); + iptr->dst.dupslots[0] = + curstack->prev->prev->prev->varnum; + iptr->dst.dupslots[1] = + curstack->prev->prev->varnum; + iptr->dst.dupslots[2] = curstack->prev->varnum; + iptr->dst.dupslots[3] = curstack->varnum; + copy = curstack; + POPANY; POPANY; POPANY; POPANY; + + DUP_SLOT(copy->prev); + iptr->dst.dupslots[4+0] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[4+1] = curstack->varnum; + DUP_SLOT(copy->prev->prev->prev); + iptr->dst.dupslots[4+2] = curstack->varnum; + DUP_SLOT(copy->prev->prev); + iptr->dst.dupslots[4+3] = curstack->varnum; + DUP_SLOT(copy->prev); + iptr->dst.dupslots[4+4] = curstack->varnum; + DUP_SLOT(copy); + iptr->dst.dupslots[4+5] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 4 + 6); iptr->dst.dupslots[0] = curstack->prev->prev->prev; iptr->dst.dupslots[1] = curstack->prev->prev; @@ -2166,6 +2349,7 @@ icmd_DUP_X2: iptr->dst.dupslots[4+4] = curstack; DUP_SLOT(iptr->dst.dupslots[3]); iptr->dst.dupslots[4+5] = curstack; +#endif last_dup_boundary = new; stackdepth += 2; } @@ -2182,6 +2366,19 @@ icmd_DUP_X2: goto throw_stack_category_error; } #endif + +#if defined(NEW_VAR) + iptr->dst.dupslots = DMNEW(s4, 2 + 2); + iptr->dst.dupslots[0] = curstack->prev->varnum; + iptr->dst.dupslots[1] = curstack->varnum; + copy = curstack; + POPANY; POPANY; + + DUP_SLOT(copy); + iptr->dst.dupslots[2+0] = curstack->varnum; + DUP_SLOT(copy->prev); + iptr->dst.dupslots[2+1] = curstack->varnum; +#else iptr->dst.dupslots = DMNEW(stackptr, 2 + 2); iptr->dst.dupslots[0] = curstack->prev; iptr->dst.dupslots[1] = curstack; @@ -2191,6 +2388,7 @@ icmd_DUP_X2: iptr->dst.dupslots[2+0] = curstack; DUP_SLOT(iptr->dst.dupslots[0]); iptr->dst.dupslots[2+1] = curstack; +#endif last_dup_boundary = new; break; @@ -2212,6 +2410,9 @@ icmd_DUP_X2: copy = curstack; while (copy) { +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= SAVEDVAR; +#endif copy->flags |= SAVEDVAR; copy = copy->prev; } @@ -2249,6 +2450,9 @@ icmd_DUP_X2: copy = curstack; while (copy) { +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= SAVEDVAR; +#endif copy->flags |= SAVEDVAR; copy = copy->prev; } @@ -2602,6 +2806,9 @@ normal_DCMPG: copy = curstack; while (copy) { +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= SAVEDVAR; +#endif copy->flags |= SAVEDVAR; copy = copy->prev; } @@ -2702,57 +2909,111 @@ icmd_BUILTIN: /* XXX optimize for <= 2 args */ /* XXX not for ICMD_BUILTIN */ iptr->s1.argcount = stackdepth; +#if defined(NEW_VAR) + iptr->sx.s23.s2.args = DMNEW(s4, stackdepth); +#else iptr->sx.s23.s2.args = DMNEW(stackptr, stackdepth); +#endif copy = curstack; for (i-- ; i >= 0; i--) { +#if defined(NEW_VAR) + iptr->sx.s23.s2.args[i] = copy->varnum; +#else iptr->sx.s23.s2.args[i] = copy; +#endif - /* do not change STACKVARs to ARGVAR -> - won't help anyway */ + /* do not change STACKVARs or LOCALVARS to ARGVAR*/ + /* -> won't help anyway */ +#if defined(NEW_VAR) + if (!(IS_OUTVAR(copy) || IS_LOCALVAR(copy))) { +#else if (copy->varkind != STACKVAR) { +#endif #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) - /* If we pass float arguments in integer argument registers, we - * are not allowed to precolor them here. Floats have to be moved - * to this regs explicitly in codegen(). - * Only arguments that are passed by stack anyway can be precolored - * (michi 2005/07/24) */ + /* If we pass float arguments in integer argument registers, we + * are not allowed to precolor them here. Floats have to be moved + * to this regs explicitly in codegen(). + * Only arguments that are passed by stack anyway can be precolored + * (michi 2005/07/24) */ +# if defined(NEW_VAR) + if (!(jd->var[copy->varnum].flags & SAVEDVAR) && + (!IS_FLT_DBL_TYPE(copy->type) + || md->params[i].inmemory)) { +# else /* defined(NEW_VAR) */ if (!(copy->flags & SAVEDVAR) && - (!IS_FLT_DBL_TYPE(copy->type) || md->params[i].inmemory)) { + (!IS_FLT_DBL_TYPE(copy->type) + || md->params[i].inmemory)) { +# endif /* defined(NEW_VAR) */ +#else +# if defined(NEW_VAR) + if (!(jd->var[copy->varnum].flags & SAVEDVAR)) { #else if (!(copy->flags & SAVEDVAR)) { #endif +#endif + +#if defined(NEW_VAR) + SET_PREALLOC(copy); +#else copy->varkind = ARGVAR; copy->varnum = i; +#endif #if defined(ENABLE_INTRP) if (!opt_intrp) { #endif if (md->params[i].inmemory) { +#if defined(NEW_VAR) + jd->var[copy->varnum].regoff = + md->params[i].regoff; + jd->var[copy->varnum].flags |= + INMEMORY; +#else copy->flags = INMEMORY; copy->regoff = md->params[i].regoff; +#endif } else { +#if !defined(NEW_VAR) copy->flags = 0; +#endif if (IS_FLT_DBL_TYPE(copy->type)) { #if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS) assert(0); /* XXX is this assert ok? */ #else +#if defined(NEW_VAR) + jd->var[copy->varnum].regoff = + rd->argfltregs[md->params[i].regoff]; +#else copy->regoff = - rd->argfltregs[md->params[i].regoff]; + rd->argfltregs[md->params[i].regoff]; +#endif #endif /* SUPPORT_PASS_FLOATARGS_IN_INTREGS */ } else { #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS) if (IS_2_WORD_TYPE(copy->type)) - copy->regoff = PACK_REGS( - rd->argintregs[GET_LOW_REG(md->params[i].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]); +#if defined(NEW_VAR) + jd->var[copy->varnum].regoff = + PACK_REGS( rd->argintregs[GET_LOW_REG(md->params[i].regoff)], + rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]); + +#else + copy->regoff = PACK_REGS( + rd->argintregs[GET_LOW_REG(md->params[i].regoff)], + rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]); +#endif else #endif /* SUPPORT_COMBINE_INTEGER_REGISTERS */ - copy->regoff = - rd->argintregs[md->params[i].regoff]; +#if defined(NEW_VAR) + jd->var[copy->varnum].regoff = + rd->argintregs[md->params[i].regoff]; +#else + copy->regoff = + rd->argintregs[md->params[i].regoff]; +#endif } } #if defined(ENABLE_INTRP) @@ -2763,14 +3024,20 @@ icmd_BUILTIN: copy = copy->prev; } - /* deal with live-through stack slots "under" the arguments */ + /* deal with live-through stack slots "under" the */ + /* arguments */ /* XXX not for ICMD_BUILTIN */ i = md->paramcount; while (copy) { +#if defined(NEW_VAR) + iptr->sx.s23.s2.args[i++] = copy->varnum; + jd->var[copy->varnum].flags |= SAVEDVAR; +#else iptr->sx.s23.s2.args[i++] = copy; copy->flags |= SAVEDVAR; +#endif copy = copy->prev; } @@ -2786,7 +3053,12 @@ icmd_BUILTIN: /* push the return value */ if (md->returntype.type != TYPE_VOID) { +#if defined(NEW_VAR) + GET_NEW_INDEX(new_index); + DST(md->returntype.type, new_index); +#else DST(md->returntype.type, stackdepth); +#endif stackdepth++; } break; @@ -2806,11 +3078,15 @@ icmd_BUILTIN: REQUIRE(i); +#if defined(NEW_VAR) + iptr->sx.s23.s2.args = DMNEW(s4, i); +#else iptr->sx.s23.s2.args = DMNEW(stackptr, i); +#endif #if defined(SPECIALMEMUSE) # if defined(__DARWIN__) - if (rd->memuse < (i + INT_ARG_CNT + LA_SIZE_IN_POINTERS)) + if (rd->memuse < (i + INT_ARG_CNT +LA_SIZE_IN_POINTERS)) rd->memuse = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT; # else if (rd->memuse < (i + LA_SIZE_IN_POINTERS + 3)) @@ -2830,11 +3106,39 @@ icmd_BUILTIN: #endif copy = curstack; while (--i >= 0) { - /* check INT type here? Currently typecheck does this. */ + /* check INT type here? Currently typecheck does this. */ +#if defined(NEW_VAR) + iptr->sx.s23.s2.args[i] = copy->varnum; + if (!(jd->var[copy->varnum].flags & SAVEDVAR) + && (!IS_OUTVAR(copy)) + && (!IS_LOCALVAR(copy)) ) { +#else iptr->sx.s23.s2.args[i] = copy; if (!(copy->flags & SAVEDVAR) && (copy->varkind != STACKVAR)) { +#endif copy->varkind = ARGVAR; +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= + INMEMORY & PREALLOC; +#if defined(SPECIALMEMUSE) +# if defined(__DARWIN__) + jd->var[copy->varnum].regoff = i + + LA_SIZE_IN_POINTERS + INT_ARG_CNT; +# else + jd->var[copy->varnum].regoff = i + + LA_SIZE_IN_POINTERS + 3; +# endif +#else +# if defined(__I386__) + jd->var[copy->varnum].regoff = i + 3; +# elif defined(__MIPS__) && SIZEOF_VOID_P == 4 + jd->var[copy->varnum].regoff = i + 2; +# else + jd->var[copy->varnum].regoff = i; +# endif /* defined(__I386__) */ +#endif /* defined(SPECIALMEMUSE) */ +#else /* defined(NEW_VAR) */ copy->varnum = i + INT_ARG_CNT; copy->flags |= INMEMORY; #if defined(SPECIALMEMUSE) @@ -2852,11 +3156,17 @@ icmd_BUILTIN: copy->regoff = i; # endif /* defined(__I386__) */ #endif /* defined(SPECIALMEMUSE) */ + +#endif /* defined(NEW_VAR) */ } copy = copy->prev; } while (copy) { +#if defined(NEW_VAR) + jd->var[copy->varnum].flags |= SAVEDVAR; +#else copy->flags |= SAVEDVAR; +#endif copy = copy->prev; } @@ -2865,7 +3175,12 @@ icmd_BUILTIN: while (--i >= 0) { POPANY; } +#if defined(NEW_VAR) + GET_NEW_INDEX(new_index); + DST(TYPE_ADR, new_index); +#else DST(TYPE_ADR, stackdepth); +#endif stackdepth++; break; @@ -2883,22 +3198,48 @@ icmd_BUILTIN: bptr->outstack = curstack; bptr->outdepth = stackdepth; +#if defined(NEW_VAR) + bptr->outvars = DMNEW(s4, stackdepth); + for (i = stackdepth, copy = curstack; i--; copy = copy->prev) + bptr->outvars[i] = copy->varnum; +#else bptr->outvars = DMNEW(stackptr, stackdepth); for (i = stackdepth, copy = curstack; i--; copy = copy->prev) bptr->outvars[i] = copy; +#endif /* stack slots at basic block end become interfaces */ i = stackdepth - 1; for (copy = curstack; copy; i--, copy = copy->prev) { - if ((copy->varkind == STACKVAR) && (copy->varnum > i)) { #if defined(NEW_VAR) - /* with the new vars rd->interfaces will be removed */ - /* and all in and outvars have to be STACKVARS! */ - /* in the moment i.e. SWAP with in and out vars */ - /* an unresolvable conflict */ - assert(0); -#endif + /* with the new vars rd->interfaces will be removed */ + /* and all in and outvars have to be STACKVARS! */ + /* in the moment i.e. SWAP with in and out vars can */ + /* create an unresolvable conflict */ + + j = jd->interface_map[i * 5 + copy->type]; + if (j == UNUSED) { + /* no interface var until now for this depth and */ + /* type */ + + SET_OUTVAR(copy); + + if (! IS_LOCALVAR(copy) ) + jd->var[j].flags |= jd->var[copy->varnum].flags; + jd->interface_map[i*5 + copy->type] = copy->varnum; + } + else if (j != copy->varnum) { + /* release copy->varnum and take already existing */ + /* interface var */ + RELEASE_INDEX(copy); + + if (! IS_LOCALVAR(copy) ) + jd->var[j].flags |= jd->var[copy->varnum].flags; + copy->varnum = jd->interface_map[i*5 + copy->type]; + } /* else <-> if (j == copy->varnum) --> nothing todo! */ +#else + if ((copy->varkind == STACKVAR) && (copy->varnum > i)) { copy->varkind = TEMPVAR; } else { copy->varkind = STACKVAR; @@ -2908,10 +3249,11 @@ icmd_BUILTIN: rd->interfaces[i][copy->type].type = copy->type; rd->interfaces[i][copy->type].flags |= copy->flags; ); +#endif } /* check if interface slots at basic block begin must be saved */ - +#if !defined(NEW_VAR) IF_NO_INTRP( i = bptr->indepth - 1; for (copy = bptr->instack; copy; i--, copy = copy->prev) { @@ -2922,8 +3264,21 @@ icmd_BUILTIN: } } ); +#endif - } /* if */ +#if defined(STACK_VERBOSE) + printf("OUTVARS\n"); + for( copy = bptr->outstack; copy; copy = copy->prev ) { + printf("%2d(%d", copy->varnum, copy->type); + if (IS_OUTVAR(copy)) + printf("S"); + if (IS_PREALLOC(copy)) + printf("A"); + printf(") "); + } + printf("\n"); +#endif + } /* if */ else superblockend = true; diff --git a/src/vm/jit/stack.h b/src/vm/jit/stack.h index b18d2b44e..abcbf59ff 100644 --- a/src/vm/jit/stack.h +++ b/src/vm/jit/stack.h @@ -28,7 +28,7 @@ Changes: Christian Ullrich - $Id: stack.h 5375 2006-09-06 16:01:23Z edwin $ + $Id: stack.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -138,6 +138,8 @@ new->varkind = (v); \ new->varnum = (n); \ curstack = new; \ + jd->var[(n)].type = (s); \ + jd->var[(n)].flags = 0; \ new++; \ } while (0) @@ -226,7 +228,7 @@ copy->flags=0;\ copy->varkind=STACKVAR;\ copy->varnum=s->varnum;\ - assert(s->varkind == STACKVAR); \ + SET_OUTVAR(s); \ s=s->prev;\ }\ copy->prev=NULL;\ @@ -282,9 +284,11 @@ (b)->flags = BBREACHED; \ (b)->instack = (c); \ (b)->indepth = stackdepth; \ - (b)->invars = DMNEW(stackptr, stackdepth); \ - for (locali = stackdepth; locali--; (c) = (c)->prev) \ - (b)->invars[locali] = (c); \ + (b)->invars = DMNEW(s4, stackdepth); \ + for (locali = stackdepth; locali--; (c) = (c)->prev) { \ + (b)->invars[locali] = (c)->varnum; \ + SET_OUTVAR((c)); \ + } \ } else { \ stackptr s = curstack; \ stackptr t = (b)->instack; \ diff --git a/src/vm/jit/verify/typecheck.c b/src/vm/jit/verify/typecheck.c index 0f88a5b02..29772a19d 100644 --- a/src/vm/jit/verify/typecheck.c +++ b/src/vm/jit/verify/typecheck.c @@ -28,7 +28,7 @@ Changes: Christian Thalinger - $Id: typecheck.c 5332 2006-09-05 19:38:28Z twisti $ + $Id: typecheck.c 5404 2006-09-07 13:29:05Z christian $ */ @@ -184,7 +184,7 @@ of the typeinfo of the stack slot. #include "vm/resolve.h" #include "vm/exceptions.h" - +#if !defined(NEW_VAR) /****************************************************************************/ /* DEBUG HELPERS */ /****************************************************************************/ @@ -2835,7 +2835,7 @@ bool typecheck(jitdata *jd) LOGimp("exiting typecheck"); return true; } - +#endif /* !defined(NEW_VAR) */ #endif /* ENABLE_VERIFIER */ /* diff --git a/tests/regression/Makefile.am b/tests/regression/Makefile.am index b45d6a1cd..e2bbd45db 100644 --- a/tests/regression/Makefile.am +++ b/tests/regression/Makefile.am @@ -28,7 +28,7 @@ ## ## Changes: ## -## $Id: Makefile.am 5015 2006-06-06 13:13:46Z twisti $ +## $Id: Makefile.am 5404 2006-09-07 13:29:05Z christian $ ## Process this file with automake to produce Makefile.in @@ -88,7 +88,7 @@ build: @$(JAVAC) -d . $(SOURCE_FILES) $(SIMPLE_JAVA_TESTS): - @echo -n "$@: " + @echo -nowarn -n "$@: " @$(JAVA) $(JAVAFLAGS) $@ diff --git a/tests/regression/codepatching/Makefile.am b/tests/regression/codepatching/Makefile.am index 0714fcd0f..6513cbb63 100644 --- a/tests/regression/codepatching/Makefile.am +++ b/tests/regression/codepatching/Makefile.am @@ -28,7 +28,7 @@ ## ## Changes: ## -## $Id: Makefile.am 5015 2006-06-06 13:13:46Z twisti $ +## $Id: Makefile.am 5404 2006-09-07 13:29:05Z christian $ ## Process this file with automake to produce Makefile.in @@ -135,7 +135,7 @@ check: build @$(JAVA) $(JAVAFLAGS) test build: - @$(JAVAC) -d . $(SOURCE_FILES) + @$(JAVAC) -nowarn -d . $(SOURCE_FILES) remove: $(RM) $(CLASSES) diff --git a/tests/regression/native/Makefile.am b/tests/regression/native/Makefile.am index 08cafa056..53ed06c45 100644 --- a/tests/regression/native/Makefile.am +++ b/tests/regression/native/Makefile.am @@ -28,7 +28,7 @@ ## ## Changes: ## -## $Id: Makefile.am 5015 2006-06-06 13:13:46Z twisti $ +## $Id: Makefile.am 5404 2006-09-07 13:29:05Z christian $ ## Process this file with automake to produce Makefile.in @@ -67,7 +67,7 @@ TESTNAMES = \ check: $(TESTNAMES) $(TESTNAMES) $(NOTESTNAMES): - @$(JAVAC) -d . $(srcdir)/$@.java + @$(JAVAC) -nowarn -d . $(srcdir)/$@.java @$(JAVAH) $@ @$(CC) -shared $(AM_CPPFLAGS) $(CFLAGS) $(srcdir)/$@.c -o lib$@.so -fPIC @$(SHELL) $(srcdir)/../Test.sh "$(JAVA) $(JAVAFLAGS)" $@ $(srcdir)