X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpowerpc%2Fcodegen.c;h=48a1ff2a46a129972b2d1c57ea3a17950654a88a;hb=2ab77f5d50859fe9849586d1be0382fb61856b8f;hp=0fa19e6808bcc67d7dbde91bb6603d1b5d05d468;hpb=01bf9b9d8ea9039f8d6c73410614d254498cf243;p=cacao.git diff --git a/src/vm/jit/powerpc/codegen.c b/src/vm/jit/powerpc/codegen.c index 0fa19e680..48a1ff2a4 100644 --- a/src/vm/jit/powerpc/codegen.c +++ b/src/vm/jit/powerpc/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -38,170 +36,57 @@ #include "vm/jit/powerpc/arch.h" #include "vm/jit/powerpc/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "native/localref.h" -#include "native/native.h" +#include "native/localref.hpp" +#include "native/native.hpp" -#include "threads/lock-common.h" +#include "threads/lock.hpp" -#include "vm/builtin.h" -#include "vm/exceptions.h" +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" -#include "vm/stringlocal.h" -#include "vm/vm.h" +#include "vm/loader.hpp" +#include "vm/options.h" +#include "vm/vm.hpp" #include "vm/jit/abi.h" #include "vm/jit/abi-asm.h" #include "vm/jit/asmpart.h" -#include "vm/jit/codegen-common.h" +#include "vm/jit/codegen-common.hpp" #include "vm/jit/dseg.h" -#include "vm/jit/emit-common.h" -#include "vm/jit/jit.h" -#include "vm/jit/md.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/jit.hpp" +#include "vm/jit/linenumbertable.hpp" #include "vm/jit/methodheader.h" -#include "vm/jit/parse.h" -#include "vm/jit/patcher-common.h" +#include "vm/jit/parse.hpp" +#include "vm/jit/patcher-common.hpp" #include "vm/jit/reg.h" -#include "vm/jit/replace.h" -#include "vm/jit/stacktrace.h" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.hpp" -#if defined(ENABLE_LSRA) -# include "vm/jit/allocator/lsra.h" -#endif - -#include "vmcore/loader.h" -#include "vmcore/options.h" - - -/* codegen ********************************************************************* - Generates machine code. - -*******************************************************************************/ - -bool codegen_emit(jitdata *jd) +/** + * Generates machine code for the method prolog. + */ +void codegen_emit_prolog(jitdata* jd) { - methodinfo *m; - codeinfo *code; - codegendata *cd; - registerdata *rd; - s4 len, s1, s2, s3, d, disp; - ptrint a; - varinfo *var; - basicblock *bptr; - instruction *iptr; - exception_entry *ex; - u2 currentline; - methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ - unresolved_method *um; - builtintable_entry *bte; - methoddesc *md; - fieldinfo *fi; - unresolved_field *uf; - s4 fieldtype; - s4 varindex; - - /* get required compiler data */ - - m = jd->m; - code = jd->code; - cd = jd->cd; - rd = jd->rd; - - /* prevent compiler warnings */ - - d = 0; - fieldtype = 0; - lm = NULL; - um = NULL; - uf = NULL; - bte = NULL; - - { - s4 i, p, t, l; - s4 savedregs_num; - - savedregs_num = 0; - - /* space to save used callee saved registers */ - - savedregs_num += (INT_SAV_CNT - rd->savintreguse); - savedregs_num += (FLT_SAV_CNT - rd->savfltreguse); - - cd->stackframesize = rd->memuse + savedregs_num; - -#if defined(ENABLE_THREADS) - /* Space to save argument of monitor_enter and Return Values to - survive monitor_exit. The stack position for the argument can - not be shared with place to save the return register on PPC, - since both values reside in R3. */ - - if (checksync && (m->flags & ACC_SYNCHRONIZED)) - cd->stackframesize += 2; -#endif - - /* create method header */ - - /* align stack to 16-bytes */ - - if (!jd->isleafmethod || JITDATA_HAS_FLAG_VERBOSECALL(jd)) - ALIGN_2(cd->stackframesize); - - else if (jd->isleafmethod && (cd->stackframesize == LA_SIZE_IN_POINTERS)) - cd->stackframesize = 0; - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* 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_add_unique_s4(cd, (rd->memuse + 1) * 8);/* IsSync */ - else -#endif - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ - - (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */ - (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ - (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ - - dseg_addlinenumbertablesize(cd); - - (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */ - - /* create exception table */ - - for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) { - dseg_add_target(cd, ex->start); - dseg_add_target(cd, ex->end); - dseg_add_target(cd, ex->handler); - (void) dseg_add_unique_address(cd, ex->catchtype.any); - } - -#if defined(ENABLE_PROFILING) - /* generate method profiling code */ - - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - - M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer); - M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency)); - M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2); - M_AST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency)); - -/* PROFILE_CYCLE_START; */ - } -#endif + varinfo* var; + methoddesc* md; + int32_t s1; + int32_t p, t, l; + int32_t varindex; + int i; + + // Get required compiler data. + methodinfo* m = jd->m; + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; /* create stack frame (if necessary) */ - if (!jd->isleafmethod) { + if (!code_is_leafmethod(code)) { M_MFLR(REG_ZERO); M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET); } @@ -277,7 +162,7 @@ bool codegen_emit(jitdata *jd) else { if (!md->params[p].inmemory) { if (!IS_INMEMORY(var->flags)) - M_FLTMOVE(s1, var->vv.regoff); + emit_fmove(cd, s1, var->vv.regoff); else M_DST(s1, REG_SP, var->vv.regoff); } @@ -296,217 +181,89 @@ bool codegen_emit(jitdata *jd) } } } +} -#if defined(ENABLE_THREADS) - /* call monitorenter function */ - - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - /* stack offset for monitor argument */ - - s1 = rd->memuse; - -# if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { - M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP); - - for (p = 0; p < INT_ARG_CNT; p++) - M_IST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8); - - for (p = 0; p < FLT_ARG_CNT; p++) - M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); - - s1 += LA_SIZE_IN_POINTERS + ARG_CNT; - } -# endif - - disp = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD(REG_ITMP3, REG_PV, disp); - M_MTCTR(REG_ITMP3); - /* get or test the lock object */ +/** + * Generates machine code for the method epilog. + */ +void codegen_emit_epilog(jitdata* jd) +{ + int32_t p; + int i; - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, &m->class->object.header); - M_ALD(REG_A0, REG_PV, disp); - } - else { - M_TST(REG_A0); - M_BNE(1); - M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER); - } + // Get required compiler data. + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; - M_AST(REG_A0, REG_SP, s1 * 8); - M_JSR; + p = cd->stackframesize; -# if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { - for (p = 0; p < INT_ARG_CNT; p++) - M_ILD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8); + /* restore return address */ - for (p = 0; p < FLT_ARG_CNT; p++) - M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); + if (!code_is_leafmethod(code)) { + /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD + may have a displacement overflow. */ - M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP); - } -# endif + M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET); + M_MTLR(REG_ITMP1); } -#endif /* defined(ENABLE_THREADS) */ - /* call trace function */ + /* restore saved registers */ - emit_verbosecall_enter(jd); + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_ILD(rd->savintregs[i], REG_SP, p * 8); + } + for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { + p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); } - /* end of header generation */ - - /* create replacement points */ - - REPLACEMENT_POINTS_INIT(cd, jd); - - /* walk through all basic blocks */ - - for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) { - - bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase); - - if (bptr->flags >= BBREACHED) { - /* branch resolving */ - - codegen_resolve_branchrefs(cd, bptr); - - /* handle replacement points */ - - REPLACEMENT_POINT_BLOCK_START(cd, bptr); - -#if defined(ENABLE_PROFILING) - /* generate basicblock profiling code */ - - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - - disp = dseg_add_address(cd, code->bbfrequency); - M_ALD(REG_ITMP2, REG_PV, disp); - M_ALD(REG_ITMP3, REG_ITMP2, bptr->nr * 4); - M_IADD_IMM(REG_ITMP3, 1, REG_ITMP3); - M_AST(REG_ITMP3, REG_ITMP2, bptr->nr * 4); - - /* if this is an exception handler, start profiling again */ - -/* if (bptr->type == BBTYPE_EXH) */ -/* PROFILE_CYCLE_START; */ - } -#endif - - /* copy interface registers to their destination */ - - len = bptr->indepth; - MCODECHECK(64+len); - -#if defined(ENABLE_LSRA) - if (opt_lsra) { - while (src != NULL) { - len--; - if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) { - /* d = reg_of_var(m, src, REG_ITMP1); */ - if (!IS_INMEMORY(src->flags)) - d = src->vv.regoff; - else - d = REG_ITMP1; - M_INTMOVE(REG_ITMP1, d); - emit_store(jd, NULL, src, d); - } - src = src->prev; - } - } else { -#endif - while (len > 0) { - len--; - var = VAR(bptr->invars[len]); - if ((len == bptr->indepth-1) && (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 { - assert((var->flags & INOUT)); - } - } - -#if defined(ENABLE_LSRA) - } -#endif - /* 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(64); /* an instruction usually needs < 64 words */ - - switch (iptr->opc) { - case ICMD_NOP: /* ... ==> ... */ - case ICMD_POP: /* ..., value ==> ... */ - case ICMD_POP2: /* ..., value, value ==> ... */ - break; - - case ICMD_INLINE_START: - - REPLACEMENT_POINT_INLINE_START(cd, iptr); - break; - - case ICMD_INLINE_BODY: - - REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - dseg_addlinenumber_inline_start(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; + /* deallocate stack */ - case ICMD_INLINE_END: + if (cd->stackframesize) + M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); - dseg_addlinenumber_inline_end(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; + M_RET; +} - case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - emit_nullpointer_check(cd, iptr, s1); - break; +/** + * Generates machine code for one ICMD. + */ +void codegen_emit_instruction(jitdata* jd, instruction* iptr) +{ + varinfo* var; + builtintable_entry* bte; + methodinfo* lm; // Local methodinfo for ICMD_INVOKE*. + unresolved_method* um; + fieldinfo* fi; + unresolved_field* uf; + int32_t fieldtype; + int32_t s1, s2, s3, d; + int32_t disp; + + // Get required compiler data. + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + + /* the big switch */ + switch (iptr->opc) { /* 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); - a = dseg_add_float(cd, iptr->sx.val.f); - M_FLD(d, REG_PV, a); + disp = dseg_add_float(cd, iptr->sx.val.f); + M_FLD(d, REG_PV, disp); emit_store_dst(jd, iptr, d); break; case ICMD_DCONST: /* ... ==> ..., constant */ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - a = dseg_add_double(cd, iptr->sx.val.d); - M_DLD(d, REG_PV, a); + disp = dseg_add_double(cd, iptr->sx.val.d); + M_DLD(d, REG_PV, disp); emit_store_dst(jd, iptr, d); break; @@ -530,30 +287,6 @@ bool codegen_emit(jitdata *jd) break; - /* load/store/copy/move operations ************************************/ - - case ICMD_ILOAD: /* ... ==> ..., content of local variable */ - case ICMD_ALOAD: /* s1 = local variable */ - case ICMD_LLOAD: - case ICMD_FLOAD: - case ICMD_DLOAD: - case ICMD_ISTORE: /* ..., value ==> ... */ - case ICMD_LSTORE: - case ICMD_FSTORE: - case ICMD_DSTORE: - case ICMD_COPY: - case ICMD_MOVE: - - emit_copy(jd, iptr); - break; - - case ICMD_ASTORE: - - if (!(iptr->flags.bits & INS_FLAG_RETADDR)) - emit_copy(jd, iptr); - break; - - /* integer operations *************************************************/ case ICMD_INEG: /* ..., value ==> ..., - value */ @@ -791,7 +524,7 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED); /* XXX TODO: only do this if arithmetic check is really done! */ - M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3); + M_IOR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3); /* XXX could be optimized */ emit_arithmetic_check(cd, iptr, REG_ITMP3); @@ -847,7 +580,7 @@ bool codegen_emit(jitdata *jd) 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); - M_AND_IMM(s2, 0x1f, REG_ITMP3); + M_IAND_IMM(s2, 0x1f, REG_ITMP3); M_SLL(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -866,7 +599,7 @@ bool codegen_emit(jitdata *jd) 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); - M_AND_IMM(s2, 0x1f, REG_ITMP3); + M_IAND_IMM(s2, 0x1f, REG_ITMP3); M_SRA(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -885,7 +618,7 @@ bool codegen_emit(jitdata *jd) 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); - M_AND_IMM(s2, 0x1f, REG_ITMP2); + M_IAND_IMM(s2, 0x1f, REG_ITMP2); M_SRL(s1, REG_ITMP2, d); emit_store_dst(jd, iptr, d); break; @@ -908,7 +641,7 @@ bool codegen_emit(jitdata *jd) 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); - M_AND(s1, s2, d); + M_IAND(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -918,7 +651,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) - M_AND_IMM(s1, iptr->sx.val.i, d); + M_IAND_IMM(s1, iptr->sx.val.i, d); /* else if (iptr->sx.val.i == 0xffffff) { M_RLWINM(s1, 0, 8, 31, d); @@ -926,7 +659,7 @@ bool codegen_emit(jitdata *jd) */ else { ICONST(REG_ITMP3, iptr->sx.val.i); - M_AND(s1, REG_ITMP3, d); + M_IAND(s1, REG_ITMP3, d); } emit_store_dst(jd, iptr, d); break; @@ -936,10 +669,10 @@ bool codegen_emit(jitdata *jd) 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_AND(s1, s2, GET_LOW_REG(d)); + M_IAND(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/ - M_AND(s1, s2, GET_HIGH_REG(d)); + M_IAND(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -950,18 +683,18 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); if ((s3 >= 0) && (s3 <= 65535)) - M_AND_IMM(s1, s3, GET_LOW_REG(d)); + M_IAND_IMM(s1, s3, GET_LOW_REG(d)); else { ICONST(REG_ITMP3, s3); - M_AND(s1, REG_ITMP3, GET_LOW_REG(d)); + M_IAND(s1, REG_ITMP3, GET_LOW_REG(d)); } s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s3 = iptr->sx.val.l >> 32; if ((s3 >= 0) && (s3 <= 65535)) - M_AND_IMM(s1, s3, GET_HIGH_REG(d)); + M_IAND_IMM(s1, s3, GET_HIGH_REG(d)); else { ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */ - M_AND(s1, REG_ITMP3, GET_HIGH_REG(d)); + M_IAND(s1, REG_ITMP3, GET_HIGH_REG(d)); } emit_store_dst(jd, iptr, d); break; @@ -976,7 +709,7 @@ bool codegen_emit(jitdata *jd) M_BGE(1 + 2*(iptr->sx.val.i >= 32768)); if (iptr->sx.val.i >= 32768) { M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2); - M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2); + M_IOR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2); M_IADD(s1, REG_ITMP2, REG_ITMP2); } else { @@ -997,7 +730,7 @@ bool codegen_emit(jitdata *jd) 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); - M_OR(s1, s2, d); + M_IOR(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -1007,10 +740,10 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) - M_OR_IMM(s1, iptr->sx.val.i, d); + M_IOR_IMM(s1, iptr->sx.val.i, d); else { ICONST(REG_ITMP3, iptr->sx.val.i); - M_OR(s1, REG_ITMP3, d); + M_IOR(s1, REG_ITMP3, d); } emit_store_dst(jd, iptr, d); break; @@ -1020,10 +753,10 @@ bool codegen_emit(jitdata *jd) 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_OR(s1, s2, GET_LOW_REG(d)); + M_IOR(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/ - M_OR(s1, s2, GET_HIGH_REG(d)); + M_IOR(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -1034,18 +767,18 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); if ((s3 >= 0) && (s3 <= 65535)) - M_OR_IMM(s1, s3, GET_LOW_REG(d)); + M_IOR_IMM(s1, s3, GET_LOW_REG(d)); else { ICONST(REG_ITMP3, s3); - M_OR(s1, REG_ITMP3, GET_LOW_REG(d)); + M_IOR(s1, REG_ITMP3, GET_LOW_REG(d)); } s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s3 = iptr->sx.val.l >> 32; if ((s3 >= 0) && (s3 <= 65535)) - M_OR_IMM(s1, s3, GET_HIGH_REG(d)); + M_IOR_IMM(s1, s3, GET_HIGH_REG(d)); else { ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */ - M_OR(s1, REG_ITMP3, GET_HIGH_REG(d)); + M_IOR(s1, REG_ITMP3, GET_HIGH_REG(d)); } emit_store_dst(jd, iptr, d); break; @@ -1230,7 +963,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); emit_store_dst(jd, iptr, d); break; @@ -1245,7 +978,6 @@ bool codegen_emit(jitdata *jd) case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ case ICMD_DCMPL: /* == => 0, < => 1, > => -1 */ - s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); @@ -1275,119 +1007,9 @@ bool codegen_emit(jitdata *jd) emit_store_dst(jd, iptr, d); break; - case ICMD_IF_FCMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPEQ: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - emit_beq(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPNE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPNE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - emit_bnan(cd, iptr->dst.block); - emit_bne(cd, iptr->dst.block); - break; - - - case ICMD_IF_FCMPL_LT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_LT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - emit_bnan(cd, iptr->dst.block); - emit_blt(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_GT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_GT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - emit_bgt(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_LE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_LE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - emit_bnan(cd, iptr->dst.block); - emit_ble(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_GE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_GE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - emit_bge(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_LT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_LT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - emit_blt(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_GT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_GT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - emit_bnan(cd, iptr->dst.block); - emit_bgt(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_LE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_LE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - emit_ble(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_GE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_GE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - emit_bnan(cd, iptr->dst.block); - emit_bge(cd, iptr->dst.block); - break; - /* memory operations **************************************************/ - case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - /* implicit null-pointer check */ - M_ILD(d, s1, OFFSET(java_array_t, size)); - emit_store_dst(jd, iptr, d); - break; - case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -1606,162 +1228,81 @@ bool codegen_emit(jitdata *jd) M_STWX(s3, s1, REG_ITMP2); break; - +#if 0 case ICMD_GETSTATIC: /* ... ==> ..., value */ + case TYPE_LNG: + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_ILD_INTERN(GET_LOW_REG(d), REG_ITMP1, 4);/* keep this order */ + M_ILD_INTERN(GET_HIGH_REG(d), REG_ITMP1, 0);/*keep this order */ + break; + break; +#endif + + case ICMD_GETFIELD: /* ... ==> ..., value */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, uf); + disp = 0; - patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, fi->value); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - patcher_add_patch_ref(jd, PATCHER_initialize_class, - fi->class, disp); - } + disp = fi->offset; + } - M_ALD(REG_ITMP1, REG_PV, disp); + /* implicit null-pointer check */ switch (fieldtype) { case TYPE_INT: d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ILD_INTERN(d, REG_ITMP1, 0); + M_ILD(d, s1, disp); break; case TYPE_LNG: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_ILD_INTERN(GET_LOW_REG(d), REG_ITMP1, 4);/* keep this order */ - M_ILD_INTERN(GET_HIGH_REG(d), REG_ITMP1, 0);/*keep this order */ + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if (GET_HIGH_REG(d) == s1) { + M_ILD(GET_LOW_REG(d), s1, disp + 4); + M_ILD(GET_HIGH_REG(d), s1, disp); + } + else { + M_ILD(GET_HIGH_REG(d), s1, disp); + M_ILD(GET_LOW_REG(d), s1, disp + 4); + } break; case TYPE_ADR: d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ALD_INTERN(d, REG_ITMP1, 0); + M_ALD(d, s1, disp); break; case TYPE_FLT: d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_FLD_INTERN(d, REG_ITMP1, 0); + M_FLD(d, s1, disp); break; case TYPE_DBL: d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_DLD_INTERN(d, REG_ITMP1, 0); + M_DLD(d, s1, disp); break; } emit_store_dst(jd, iptr, d); break; - case ICMD_PUTSTATIC: /* ..., value ==> ... */ + case ICMD_PUTFIELD: /* ..., value ==> ... */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, uf); - - patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); + disp = 0; } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, fi->value); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - patcher_add_patch_ref(jd, PATCHER_initialize_class, - fi->class, disp); - } - - M_ALD(REG_ITMP1, REG_PV, disp); - switch (fieldtype) { - case TYPE_INT: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_IST_INTERN(s1, REG_ITMP1, 0); - break; - case TYPE_LNG: - s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED); - M_LST_INTERN(s1, REG_ITMP1, 0); - break; - case TYPE_ADR: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_AST_INTERN(s1, REG_ITMP1, 0); - break; - case TYPE_FLT: - s1 = emit_load_s1(jd, iptr, REG_FTMP2); - M_FST_INTERN(s1, REG_ITMP1, 0); - break; - case TYPE_DBL: - s1 = emit_load_s1(jd, iptr, REG_FTMP2); - M_DST_INTERN(s1, REG_ITMP1, 0); - break; - } - break; - - - case ICMD_GETFIELD: /* ... ==> ..., value */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - disp = 0; - - patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = fi->offset; - } - - /* implicit null-pointer check */ - switch (fieldtype) { - case TYPE_INT: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ILD(d, s1, disp); - break; - case TYPE_LNG: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - if (GET_HIGH_REG(d) == s1) { - M_ILD(GET_LOW_REG(d), s1, disp + 4); - M_ILD(GET_HIGH_REG(d), s1, disp); - } - else { - M_ILD(GET_HIGH_REG(d), s1, disp); - M_ILD(GET_LOW_REG(d), s1, disp + 4); - } - break; - case TYPE_ADR: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ALD(d, s1, disp); - break; - case TYPE_FLT: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_FLD(d, s1, disp); - break; - case TYPE_DBL: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_DLD(d, s1, disp); - break; - } - emit_store_dst(jd, iptr, d); - break; - - case ICMD_PUTFIELD: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - disp = 0; - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = fi->offset; - } + disp = fi->offset; + } if (IS_INT_LNG_TYPE(fieldtype)) { if (IS_2_WORD_TYPE(fieldtype)) @@ -1801,45 +1342,20 @@ bool codegen_emit(jitdata *jd) 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)) { - unresolved_class *uc = iptr->sx.s23.s2.uc; - - patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); - } -#endif /* ENABLE_VERIFIER */ - disp = dseg_add_functionptr(cd, asm_handle_exception); M_ALD(REG_ITMP2, REG_PV, disp); M_MTCTR(REG_ITMP2); - if (jd->isleafmethod) + if (code_is_leafmethod(code)) M_MFLR(REG_ITMP3); /* save LR */ M_BL(0); /* get current PC */ M_MFLR(REG_ITMP2_XPC); - if (jd->isleafmethod) + if (code_is_leafmethod(code)) M_MTLR(REG_ITMP3); /* restore LR */ M_RTS; /* jump to CTR */ - ALIGNCODENOP; - break; - - case ICMD_GOTO: /* ... ==> ... */ - case ICMD_RET: /* ... ==> ... */ - - emit_br(cd, iptr->dst.block); - ALIGNCODENOP; - break; - - case ICMD_JSR: /* ... ==> ... */ - - emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); - ALIGNCODENOP; break; case ICMD_IFNULL: /* ..., value ==> ... */ @@ -1850,42 +1366,24 @@ bool codegen_emit(jitdata *jd) emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE); break; - case ICMD_IFLT: - case ICMD_IFLE: - case ICMD_IFNE: - case ICMD_IFGT: - case ICMD_IFGE: - case ICMD_IFEQ: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) - M_CMPI(s1, iptr->sx.val.i); - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE); - break; - - case ICMD_IF_LEQ: /* ..., value ==> ... */ s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); if (iptr->sx.val.l == 0) { - M_OR_TST(s1, s2, REG_ITMP3); + M_IOR_TST(s1, s2, REG_ITMP3); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_XOR_IMM(s2, 0, REG_ITMP2); M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } else { ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_XOR(s1, REG_ITMP3, REG_ITMP1); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_XOR(s2, REG_ITMP3, REG_ITMP2); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } emit_beq(cd, iptr->dst.block); break; @@ -1924,7 +1422,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); /* if (iptr->sx.val.l == 0) { */ -/* M_OR(s1, s2, REG_ITMP3); */ +/* M_IOR(s1, s2, REG_ITMP3); */ /* M_CMPI(REG_ITMP3, 0); */ /* } else */ @@ -1951,19 +1449,19 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); if (iptr->sx.val.l == 0) { - M_OR_TST(s1, s2, REG_ITMP3); + M_IOR_TST(s1, s2, REG_ITMP3); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_XOR_IMM(s2, 0, REG_ITMP2); M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } else { ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_XOR(s1, REG_ITMP3, REG_ITMP1); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_XOR(s2, REG_ITMP3, REG_ITMP2); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } emit_bne(cd, iptr->dst.block); break; @@ -1973,7 +1471,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); /* if (iptr->sx.val.l == 0) { */ -/* M_OR(s1, s2, REG_ITMP3); */ +/* M_IOR(s1, s2, REG_ITMP3); */ /* M_CMPI(REG_ITMP3, 0); */ /* } else */ @@ -2024,28 +1522,6 @@ bool codegen_emit(jitdata *jd) } break; - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPNE: - case ICMD_IF_ICMPLT: - case ICMD_IF_ICMPGT: - case ICMD_IF_ICMPLE: - case ICMD_IF_ICMPGE: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE); - break; - - case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */ - case ICMD_IF_ACMPNE: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE); - break; - case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); @@ -2127,130 +1603,6 @@ bool codegen_emit(jitdata *jd) emit_label(cd, BRANCH_LABEL_1); break; - case ICMD_IRETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT); - M_INTMOVE(s1, REG_RESULT); - goto nowperformreturn; - - case ICMD_ARETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT); - M_INTMOVE(s1, REG_RESULT); - -#ifdef ENABLE_VERIFIER - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - unresolved_class *uc = iptr->sx.s23.s2.uc; - - patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); - } -#endif /* ENABLE_VERIFIER */ - goto nowperformreturn; - - case ICMD_LRETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED); - M_LNGMOVE(s1, REG_RESULT_PACKED); - goto nowperformreturn; - - case ICMD_FRETURN: /* ..., retvalue ==> ... */ - case ICMD_DRETURN: - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_FRESULT); - M_FLTMOVE(s1, REG_FRESULT); - goto nowperformreturn; - - case ICMD_RETURN: /* ... ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - -nowperformreturn: - { - s4 i, p; - - p = cd->stackframesize; - - /* call trace function */ - - emit_verbosecall_exit(jd); - -#if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - disp = dseg_add_functionptr(cd, LOCK_monitor_exit); - M_ALD(REG_ITMP3, REG_PV, disp); - M_MTCTR(REG_ITMP3); - - /* we need to save the proper return value */ - - switch (iptr->opc) { - case ICMD_LRETURN: - M_IST(REG_RESULT2, REG_SP, rd->memuse * 8 + 8); - /* fall through */ - case ICMD_IRETURN: - case ICMD_ARETURN: - M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 4); - break; - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 4); - break; - } - - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - M_JSR; - - /* and now restore the proper return value */ - - switch (iptr->opc) { - case ICMD_LRETURN: - M_ILD(REG_RESULT2, REG_SP, rd->memuse * 8 + 8); - /* fall through */ - case ICMD_IRETURN: - case ICMD_ARETURN: - M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 4); - break; - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 4); - break; - } - } -#endif - - /* restore return address */ - - if (!jd->isleafmethod) { - /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD - may have a displacement overflow. */ - - M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET); - M_MTLR(REG_ITMP1); - } - - /* restore saved registers */ - - for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_ILD(rd->savintregs[i], REG_SP, p * 8); - } - for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { - p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); - } - - /* deallocate stack */ - - if (cd->stackframesize) - M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); - - M_RET; - ALIGNCODENOP; - } - break; - - case ICMD_TABLESWITCH: /* ..., index ==> ... */ { s4 i, l; @@ -2299,239 +1651,95 @@ nowperformreturn: 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) { - if ((lookup->value >= -32768) && (lookup->value <= 32767)) { - M_CMPI(s1, lookup->value); - } - else { - disp = dseg_add_s4(cd, lookup->value); - M_ILD(REG_ITMP2, REG_PV, disp); - M_CMP(s1, REG_ITMP2); - } - emit_beq(cd, lookup->target.block); - lookup++; - } - - emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); - ALIGNCODENOP; - break; - } - - case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + bte = iptr->sx.s23.s3.bte; + if (bte->stub == NULL) + disp = dseg_add_functionptr(cd, bte->fp); + else + disp = dseg_add_functionptr(cd, bte->stub); - REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr); + M_ALD(REG_PV, REG_PV, disp); /* pointer to built-in-function */ - bte = iptr->sx.s23.s3.bte; - md = bte->md; - goto gen_method; + /* generate the actual call */ - case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ + M_MTCTR(REG_PV); + M_JSR; + break; case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ - case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ - case ICMD_INVOKEINTERFACE: - - REPLACEMENT_POINT_INVOKE(cd, iptr); + emit_nullpointer_check(cd, iptr, REG_A0); + /* fall-through */ + case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - lm = NULL; um = iptr->sx.s23.s3.um; - md = um->methodref->parseddesc.md; + disp = dseg_add_unique_address(cd, um); + + patcher_add_patch_ref(jd, PATCHER_invokestatic_special, + um, disp); } else { lm = iptr->sx.s23.s3.fmiref->p.method; - um = NULL; - md = lm->parseddesc; + disp = dseg_add_address(cd, lm->stubroutine); } -gen_method: - s3 = md->paramcount; + M_ALD(REG_PV, REG_PV, disp); - MCODECHECK((s3 << 1) + 64); + /* generate the actual call */ - /* copy arguments to registers or stack location */ + M_MTCTR(REG_PV); + M_JSR; + break; - for (s3 = s3 - 1; s3 >= 0; s3--) { - var = VAR(iptr->sx.s23.s2.args[s3]); - d = md->params[s3].regoff; + case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); - /* Already Preallocated? */ - if (var->flags & PREALLOC) - continue; - - if (IS_INT_LNG_TYPE(var->type)) { - if (!md->params[s3].inmemory) { - if (IS_2_WORD_TYPE(var->type)) { - s1 = emit_load(jd, iptr, var, d); - M_LNGMOVE(s1, d); - } - else { - s1 = emit_load(jd, iptr, var, d); - M_INTMOVE(s1, d); - } - } - else { - if (IS_2_WORD_TYPE(var->type)) { - s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED); - M_LST(s1, REG_SP, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_ITMP1); - M_IST(s1, REG_SP, d); - } - } - } - else { - if (!md->params[s3].inmemory) { - s1 = emit_load(jd, iptr, var, d); - M_FLTMOVE(s1, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_FTMP1); - M_DST(s1, REG_SP, d); - } - } + s1 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, table[0]) + + sizeof(methodptr) * lm->vftblindex; } - switch (iptr->opc) { - case ICMD_BUILTIN: - if (bte->stub == NULL) - disp = dseg_add_functionptr(cd, bte->fp); - else - disp = dseg_add_functionptr(cd, bte->stub); - - M_ALD(REG_PV, REG_PV, disp); /* pointer to built-in-function */ - - /* generate the actual call */ - - M_MTCTR(REG_PV); - M_JSR; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_MFLR(REG_ITMP1); - M_LDA(REG_PV, REG_ITMP1, -disp); - - emit_exception_check(cd, iptr); - break; - - case ICMD_INVOKESPECIAL: - emit_nullpointer_check(cd, iptr, REG_A0); - /* fall-through */ - - case ICMD_INVOKESTATIC: - if (lm == NULL) { - disp = dseg_add_unique_address(cd, um); - - patcher_add_patch_ref(jd, PATCHER_invokestatic_special, - um, disp); - } - else - disp = dseg_add_address(cd, lm->stubroutine); - - M_ALD(REG_PV, REG_PV, disp); - - /* generate the actual call */ - - M_MTCTR(REG_PV); - M_JSR; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_MFLR(REG_ITMP1); - M_LDA(REG_PV, REG_ITMP1, -disp); - break; - - case ICMD_INVOKEVIRTUAL: - if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); - - s1 = 0; - } - else { - s1 = OFFSET(vftbl_t, table[0]) + - sizeof(methodptr) * lm->vftblindex; - } - - /* implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - M_ALD(REG_PV, REG_METHODPTR, s1); - - /* generate the actual call */ - - M_MTCTR(REG_PV); - M_JSR; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_MFLR(REG_ITMP1); - M_LDA(REG_PV, REG_ITMP1, -disp); - break; - - case ICMD_INVOKEINTERFACE: - if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); - - s1 = 0; - s2 = 0; - } - else { - s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr*) * lm->class->index; + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD(REG_PV, REG_METHODPTR, s1); - s2 = sizeof(methodptr) * (lm - lm->class->methods); - } + /* generate the actual call */ - /* implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - M_ALD(REG_METHODPTR, REG_METHODPTR, s1); - M_ALD(REG_PV, REG_METHODPTR, s2); + M_MTCTR(REG_PV); + M_JSR; + break; - /* generate the actual call */ + case ICMD_INVOKEINTERFACE: + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); - M_MTCTR(REG_PV); - M_JSR; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_MFLR(REG_ITMP1); - M_LDA(REG_PV, REG_ITMP1, -disp); - break; + s1 = 0; + s2 = 0; } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, interfacetable[0]) - + sizeof(methodptr*) * lm->clazz->index; - /* store return value */ + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); + } - d = md->returntype.type; + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD(REG_METHODPTR, REG_METHODPTR, s1); + M_ALD(REG_PV, REG_METHODPTR, s2); - if (d != TYPE_VOID) { - 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_FRESULT); - M_FLTMOVE(REG_FRESULT, s1); - } - emit_store_dst(jd, iptr, s1); - } - break; + /* generate the actual call */ + M_MTCTR(REG_PV); + M_JSR; + break; case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ @@ -2550,9 +1758,6 @@ gen_method: superindex = super->index; } - if ((super == NULL) || !(super->flags & ACC_INTERFACE)) - CODEGEN_CRITICAL_SECTION_NEW; - s1 = emit_load_s1(jd, iptr, REG_ITMP1); /* if class is not resolved, check which code to call */ @@ -2569,7 +1774,7 @@ gen_method: disp); M_ILD(REG_ITMP2, REG_PV, disp); - M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); + M_IAND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); emit_label_beq(cd, BRANCH_LABEL_2); } @@ -2624,29 +1829,53 @@ gen_method: } M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ALD(REG_ITMP3, REG_PV, disp); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_IADD(REG_ITMP1, REG_ITMP2, REG_ITMP1); + M_ALD(REG_ITMP1, REG_ITMP1, 0); + M_CMP(REG_ITMP1, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_6); /* good */ + + if (super == NULL) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_CMPI(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])); + emit_label_bne(cd, BRANCH_LABEL_10); /* throw */ + } - CODEGEN_CRITICAL_SECTION_START; - - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); - M_ALD(REG_ITMP2, REG_PV, disp); - if (s1 != REG_ITMP1) { - M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); - - CODEGEN_CRITICAL_SECTION_END; - - M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3); + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth)); + M_CMP(REG_ITMP1, REG_ITMP3); + emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */ + /* reload */ + M_ALD(REG_ITMP3, REG_PV, disp); + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + + M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1); + M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*4, REG_ITMP2); + M_LWZX(REG_ITMP1, REG_ITMP2, REG_ITMP1); + M_CMP(REG_ITMP1, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_7); /* good */ + + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); + M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException); + + emit_label(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_6); + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); } else { - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); - M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3); - M_ALD(REG_ITMP2, REG_PV, disp); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); - - CODEGEN_CRITICAL_SECTION_END; + M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset); + M_CMP(REG_ITMP2, REG_ITMP3); + emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP2, s1); } - M_CMPU(REG_ITMP3, REG_ITMP2); - emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1); if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -2705,9 +1934,6 @@ gen_method: superindex = super->index; } - if ((super == NULL) || !(super->flags & ACC_INTERFACE)) - CODEGEN_CRITICAL_SECTION_NEW; - s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -2716,12 +1942,11 @@ gen_method: s1 = REG_ITMP1; } - M_CLR(d); - /* if class is not resolved, check which code to call */ if (super == NULL) { M_TST(s1); + M_CLR(d); emit_label_beq(cd, BRANCH_LABEL_1); disp = dseg_add_unique_s4(cd, 0); /* super->flags */ @@ -2730,7 +1955,7 @@ gen_method: iptr->sx.s23.s3.c.ref, disp); M_ILD(REG_ITMP3, REG_PV, disp); - M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); + M_IAND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); emit_label_beq(cd, BRANCH_LABEL_2); } @@ -2738,25 +1963,31 @@ gen_method: if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { + /* If d == REG_ITMP2, then it's destroyed in check + code above. */ + if (d == REG_ITMP2) + M_CLR(d); + patcher_add_patch_ref(jd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); } else { M_TST(s1); + M_CLR(d); emit_label_beq(cd, BRANCH_LABEL_3); } M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); M_LDATST(REG_ITMP3, REG_ITMP3, -superindex); - M_BLE(4); + M_BLE(3); M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); - M_TST(REG_ITMP1); - M_BEQ(1); - M_IADD_IMM(REG_ZERO, 1, d); + + M_ADDIC(REG_ITMP1, -1, d); + M_SUBE(REG_ITMP1, d, d); if (super == NULL) emit_label_br(cd, BRANCH_LABEL_4); @@ -2780,25 +2011,65 @@ gen_method: disp = dseg_add_address(cd, super->vftbl); M_TST(s1); + M_CLR(d); emit_label_beq(cd, BRANCH_LABEL_5); } - M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); - M_ALD(REG_ITMP2, REG_PV, disp); + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ALD(REG_ITMP3, REG_PV, disp); - CODEGEN_CRITICAL_SECTION_START; + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_IADD(REG_ITMP1, REG_ITMP2, REG_ITMP1); + M_ALD(REG_ITMP1, REG_ITMP1, 0); + M_CMP(REG_ITMP1, REG_ITMP3); + emit_label_bne(cd, BRANCH_LABEL_8); + ICONST(d, 1); + emit_label_br(cd, BRANCH_LABEL_6); /* true */ + emit_label(cd, BRANCH_LABEL_8); - M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); + if (super == NULL) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_CMPI(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])); + emit_label_bne(cd, BRANCH_LABEL_10); /* false */ + } - CODEGEN_CRITICAL_SECTION_END; + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth)); + M_CMP(REG_ITMP1, REG_ITMP3); + emit_label_bgt(cd, BRANCH_LABEL_9); /* false */ + /* reload */ + M_ALD(REG_ITMP3, REG_PV, disp); + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + + M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1); + M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*4, REG_ITMP2); + M_LWZX(REG_ITMP1, REG_ITMP2, REG_ITMP1); + /* This seems to be the canonical sequence to emulate + * the Alpha instruction M_CMPEQ. */ + M_XOR(REG_ITMP1, REG_ITMP3, d); + M_CNTLZ(d, d); + M_RLWINM(d, 27, 5, 31, d); + + if (d == REG_ITMP2) + emit_label_br(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + if (d == REG_ITMP2) { + M_CLR(d); - M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); - M_CMPU(REG_ITMP1, REG_ITMP2); - M_CLR(d); - M_BGT(1); - M_IADD_IMM(REG_ZERO, 1, d); + emit_label(cd, BRANCH_LABEL_7); + } + emit_label(cd, BRANCH_LABEL_6); + } + else { + M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset); + M_XOR(REG_ITMP2, REG_ITMP3, d); + M_CNTLZ(d, d); + M_RLWINM(d, 27, 5, 31, d); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -2877,244 +2148,8 @@ gen_method: break; default: - exceptions_throw_internalerror("Unknown ICMD %d during code generation", - iptr->opc); - return false; + vm_abort("Unknown ICMD %d during code generation", iptr->opc); } /* switch */ - - } /* for instruction */ - - } /* if (bptr -> flags >= BBREACHED) */ - } /* for basic block */ - - dseg_createlinenumbertable(cd); - - /* generate traps */ - - emit_patcher_traps(jd); - - /* everything's ok */ - - return true; -} - - -/* codegen_emit_stub_compiler ************************************************** - - Emits a stub routine which calls the compiler. - -*******************************************************************************/ - -void codegen_emit_stub_compiler(jitdata *jd) -{ - methodinfo *m; - codegendata *cd; - - /* get required compiler data */ - - m = jd->m; - cd = jd->cd; - - /* code for the stub */ - - M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); - M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P); - M_MTCTR(REG_PV); - M_RTS; -} - - -/* codegen_emit_stub_builtin *************************************************** - - Creates a stub routine which calls a builtin function. - -*******************************************************************************/ - -void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte) -{ - codeinfo *code; - codegendata *cd; - methoddesc *md; - int i; - int s1; - int disp; - - /* get required compiler data */ - - code = jd->code; - cd = jd->cd; - - md = bte->md; - - /* calculate stackframe size */ - - cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + - 2 + /* 4 stackframeinfo arguments (darwin)*/ - md->paramcount; - - /* Keep stack 16-byte aligned. */ - - ALIGN_2(cd->stackframesize); - - /* create method header */ - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ - (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ - (void) dseg_add_unique_s4(cd, 0); /* IntSave */ - (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ - - /* generate code */ - - M_MFLR(REG_ZERO); - M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET); - M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8)); - -#if defined(ENABLE_GC_CACAO) - /* Save callee saved integer registers in stackframeinfo (GC may - need to recover them during a collection). */ - - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); - - for (i = 0; i < INT_SAV_CNT; i++) - M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4); -#endif - - /* Save integer and float argument registers. */ - - for (i = 0; i < md->paramcount; i++) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - switch (md->paramtypes[i].type) { - case TYPE_INT: - case TYPE_ADR: - M_IST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - case TYPE_LNG: - M_LST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - } - } - } - - /* create dynamic stack info */ - - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0); - M_MOV(REG_PV, REG_A1); - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2); - M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET); - disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter); - M_ALD(REG_ITMP1, REG_PV, disp); - M_MTCTR(REG_ITMP1); - M_JSR; - - /* Restore integer and float argument registers. */ - - for (i = 0; i < md->paramcount; i++) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - switch (md->paramtypes[i].type) { - case TYPE_INT: - case TYPE_ADR: - M_ILD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - case TYPE_LNG: - M_LLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); - break; - } - } - } - - /* call the builtin function */ - - disp = dseg_add_functionptr(cd, bte->fp); - M_ALD(REG_ITMP3, REG_PV, disp); - M_MTCTR(REG_ITMP3); - M_JSR; - - /* save return value */ - - switch (md->returntype.type) { - case TYPE_INT: - case TYPE_ADR: - M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_LNG: - M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_VOID: - /* XXX This should be done better. */ - if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION) - M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); - break; - } - - /* remove native stackframe info */ - - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0); - disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit); - M_ALD(REG_ITMP1, REG_PV, disp); - M_MTCTR(REG_ITMP1); - M_JSR; - - /* restore return value */ - - switch (md->returntype.type) { - case TYPE_INT: - case TYPE_ADR: - M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_LNG: - M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8); - break; - case TYPE_VOID: - /* XXX This should be done better. */ - if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION) - M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); - break; - } - -#if defined(ENABLE_GC_CACAO) - /* Restore callee saved integer registers from stackframeinfo (GC - might have modified them during a collection). */ - - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); - - for (i = 0; i < INT_SAV_CNT; i++) - M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4); -#endif - - /* remove stackframe */ - - M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET); - M_MTLR(REG_ITMP2_XPC); - M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); - - M_RET; } @@ -3124,19 +2159,22 @@ void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte) *******************************************************************************/ -void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams) { methodinfo *m; codeinfo *code; codegendata *cd; methoddesc *md; - s4 nativeparams; s4 i, j; /* count variables */ s4 t; - s4 s1, s2, disp; - s4 funcdisp; + s4 s1, s2; + int disp; + + /* Sanity check. */ - /* get required compiler data */ + assert(f != NULL); + + /* Get required compiler data. */ m = jd->m; code = jd->code; @@ -3145,14 +2183,13 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* set some variables */ md = m->parseddesc; - nativeparams = (m->flags & ACC_STATIC) ? 2 : 1; /* calculate stackframe size */ cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + + sizeof(stackframeinfo_t) / SIZEOF_VOID_P + sizeof(localref_table) / SIZEOF_VOID_P + - 4 + /* 4 stackframeinfo arguments (darwin)*/ + 4 + /* 4 stackframeinfo arguments (darwin) */ nmd->paramcount + nmd->memuse; @@ -3168,8 +2205,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ (void) dseg_add_unique_s4(cd, 0); /* IntSave */ (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ /* generate code */ @@ -3177,25 +2212,12 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET); M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8)); - /* get function address (this must happen before the stackframeinfo) */ - - funcdisp = dseg_add_functionptr(cd, f); - -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) - patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp); -#endif - - /* emit trace code */ - - emit_verbosecall_enter(jd); - #if defined(ENABLE_GC_CACAO) /* Save callee saved integer registers in stackframeinfo (GC may need to recover them during a collection). */ - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); for (i = 0; i < INT_SAV_CNT; i++) M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4); @@ -3225,15 +2247,18 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* create native stack info */ - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0); + M_MOV(REG_SP, REG_A0); M_MOV(REG_PV, REG_A1); - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2); - M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET); disp = dseg_add_functionptr(cd, codegen_start_native_call); M_ALD(REG_ITMP1, REG_PV, disp); M_MTCTR(REG_ITMP1); M_JSR; + /* remember class argument */ + + if (m->flags & ACC_STATIC) + M_MOV(REG_RESULT, REG_ITMP3); + /* restore integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { @@ -3258,93 +2283,99 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* copy or spill arguments to new locations */ - for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) { + for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) { t = md->paramtypes[i].type; - if (IS_INT_LNG_TYPE(t)) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - s2 = nmd->params[j].regoff; + if (!md->params[i].inmemory) { + s1 = md->params[i].regoff; + s2 = nmd->params[j].regoff; - if (!nmd->params[j].inmemory) { - if (IS_2_WORD_TYPE(t)) - M_LNGMOVE(s1, s2); - else - M_INTMOVE(s1, s2); - } - else { - if (IS_2_WORD_TYPE(t)) - M_LST(s1, REG_SP, s2); - else - M_IST(s1, REG_SP, s2); - } - } - else { - s1 = md->params[i].regoff + cd->stackframesize * 8; - s2 = nmd->params[j].regoff; + switch (t) { + case TYPE_INT: + case TYPE_ADR: + if (!nmd->params[j].inmemory) + M_INTMOVE(s1, s2); + else + M_IST(s1, REG_SP, s2); + break; - M_ILD(REG_ITMP1, REG_SP, s1); - if (IS_2_WORD_TYPE(t)) - M_ILD(REG_ITMP2, REG_SP, s1 + 4); + case TYPE_LNG: + if (!nmd->params[j].inmemory) + M_LNGMOVE(s1, s2); + else + M_LST(s1, REG_SP, s2); + break; - M_IST(REG_ITMP1, REG_SP, s2); - if (IS_2_WORD_TYPE(t)) - M_IST(REG_ITMP2, REG_SP, s2 + 4); + case TYPE_FLT: + case TYPE_DBL: + /* We only copy spilled float arguments, as the float + argument registers keep unchanged. */ + break; } } else { - /* We only copy spilled float arguments, as the float - argument registers keep unchanged. */ + s1 = md->params[i].regoff + cd->stackframesize * 8; + s2 = nmd->params[j].regoff; + + switch (t) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(REG_ITMP1, REG_SP, s1); + M_IST(REG_ITMP1, REG_SP, s2); + break; - if (md->params[i].inmemory) { - s1 = md->params[i].regoff + cd->stackframesize * 8; - s2 = nmd->params[j].regoff; + case TYPE_LNG: + M_LLD(REG_ITMP12_PACKED, REG_SP, s1); + M_LST(REG_ITMP12_PACKED, REG_SP, s2); + break; + case TYPE_FLT: M_DLD(REG_FTMP1, REG_SP, s1); + M_FST(REG_FTMP1, REG_SP, s2); + break; - if (IS_2_WORD_TYPE(t)) - M_DST(REG_FTMP1, REG_SP, s2); - else - M_FST(REG_FTMP1, REG_SP, s2); + case TYPE_DBL: + M_DLD(REG_FTMP1, REG_SP, s1); + M_DST(REG_FTMP1, REG_SP, s2); + break; } } } - /* put class into second argument register */ + /* Handle native Java methods. */ - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, m->class); - M_ALD(REG_A1, REG_PV, disp); - } + if (m->flags & ACC_NATIVE) { + /* put class into second argument register */ - /* put env into first argument register */ + if (m->flags & ACC_STATIC) + M_MOV(REG_ITMP3, REG_A1); - disp = dseg_add_address(cd, _Jv_env); - M_ALD(REG_A0, REG_PV, disp); + /* put env into first argument register */ - /* generate the actual native call */ + disp = dseg_add_address(cd, VM_get_jnienv()); + M_ALD(REG_A0, REG_PV, disp); + } + + /* Call the native function. */ - M_ALD(REG_ITMP3, REG_PV, funcdisp); + disp = dseg_add_functionptr(cd, f); + M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); M_JSR; - /* print call trace */ - - emit_verbosecall_exit(jd); - /* save return value */ switch (md->returntype.type) { case TYPE_INT: case TYPE_ADR: - M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); + M_IST(REG_RESULT, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_LNG: - M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8); + M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_FLT: case TYPE_DBL: - M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8); + M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_VOID: break; @@ -3352,7 +2383,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* remove native stackframe info */ - M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0); + M_MOV(REG_SP, REG_A0); + M_MOV(REG_PV, REG_A1); disp = dseg_add_functionptr(cd, codegen_finish_native_call); M_ALD(REG_ITMP1, REG_PV, disp); M_MTCTR(REG_ITMP1); @@ -3364,14 +2396,14 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) switch (md->returntype.type) { case TYPE_INT: case TYPE_ADR: - M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8); + M_ILD(REG_RESULT, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_LNG: - M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8); + M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_FLT: case TYPE_DBL: - M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8); + M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4); break; case TYPE_VOID: break; @@ -3381,8 +2413,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* Restore callee saved integer registers from stackframeinfo (GC might have modified them during a collection). */ - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); for (i = 0; i < INT_SAV_CNT; i++) M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4); @@ -3407,10 +2439,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); M_RTS; - - /* generate patcher traps */ - - emit_patcher_traps(jd); }