* src/vm/jit/arm/codegen.h: Major code cleanup and support VFP instructions.
[cacao.git] / src / vm / jit / arm / codegen.c
index 6ab8eaa8b9faf2c89e61e758e1a756e5a3fa1cd8..cd883d23eb7fdf846b8b66e530d587a12f3d7bda 100644 (file)
@@ -22,8 +22,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7934 2007-05-22 10:07:21Z michi $
-
 */
 
 
@@ -41,6 +39,7 @@
 
 #include "mm/memory.h"
 
+#include "native/localref.h"
 #include "native/native.h"
 
 #include "threads/lock-common.h"
@@ -50,6 +49,7 @@
 #include "vm/global.h"
 #include "vm/vm.h"
 
+#include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
@@ -58,7 +58,7 @@
 #include "vm/jit/md.h"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
+#include "vm/jit/patcher-common.h"
 #include "vm/jit/reg.h"
 
 #if defined(ENABLE_LSRA)
@@ -88,8 +88,6 @@ bool codegen_emit(jitdata *jd)
        basicblock     *bptr;
        instruction    *iptr;
        exception_entry *ex;
-       s4              fieldtype;
-       s4              varindex;
 
        s4              spilledregs_num;
        s4              savedregs_num;
@@ -100,6 +98,10 @@ bool codegen_emit(jitdata *jd)
        unresolved_method  *um;
        builtintable_entry *bte;
        methoddesc         *md;
+       fieldinfo          *fi;
+       unresolved_field   *uf;
+       int                 fieldtype;
+       int                 varindex;
 
        /* get required compiler data */
 
@@ -120,7 +122,8 @@ bool codegen_emit(jitdata *jd)
 
        savedregs_num = (jd->isleafmethod) ? 0 : 1;       /* space to save the LR */
        savedregs_num += (INT_SAV_CNT - rd->savintreguse);
-       savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
+       /*savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);*/
+       assert((FLT_SAV_CNT - rd->savfltreguse) == 0);
 
        spilledregs_num = rd->memuse;
 
@@ -129,19 +132,19 @@ bool codegen_emit(jitdata *jd)
                spilledregs_num++;
 #endif
 
-       cd->stackframesize = spilledregs_num + savedregs_num;
+       cd->stackframesize = spilledregs_num * 8 + savedregs_num * 4;
 
        /* XXX QUICK FIX: We shouldn't align the stack in Java code, but
           only in native stubs. */
        /* align stack to 8-byte */
 
-       cd->stackframesize = (cd->stackframesize + 1) & ~1;
+       cd->stackframesize = (cd->stackframesize + 4) & ~4;
 
        /* SECTION: Method Header */
        /* create method header */
 
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* FrameSize       */
 
 #if defined(ENABLE_THREADS)
        /* IsSync contains the offset relative to the stack pointer for the
@@ -151,7 +154,7 @@ bool codegen_emit(jitdata *jd)
        */
 
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync         */
+               (void) dseg_add_unique_s4(cd, rd->memuse * 8 + 4);/* IsSync         */
        else
 #endif
                (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
@@ -193,8 +196,8 @@ bool codegen_emit(jitdata *jd)
 
        /* create additional stack frame for spilled variables (if necessary) */
 
-       if ((cd->stackframesize - savedregs_num) > 0)
-               M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize - savedregs_num);
+       if ((cd->stackframesize / 4 - savedregs_num) > 0)
+               M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
 
        /* take arguments out of register or stack frame */
 
@@ -225,17 +228,17 @@ bool codegen_emit(jitdata *jd)
                                }
                                else {
                                        if (IS_2_WORD_TYPE(t))
-                                               M_LST(s1, REG_SP, var->vv.regoff * 4);
+                                               M_LST(s1, REG_SP, var->vv.regoff);
                                        else
-                                               M_IST(s1, REG_SP, var->vv.regoff * 4);
+                                               M_IST(s1, REG_SP, var->vv.regoff);
                                }
                        }
                        else {                                   /* stack arguments       */
                                if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
                                        if (IS_2_WORD_TYPE(t))
-                                               M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+                                               M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
                                        else
-                                               M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+                                               M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
                                }
                                else {                               /* stack arg -> spilled  */
                                        /* Reuse Memory Position on Caller Stack */
@@ -247,21 +250,24 @@ bool codegen_emit(jitdata *jd)
                else {
                        if (!md->params[i].inmemory) {
                                if (!(var->flags & INMEMORY)) {
-                                       M_CAST_INT_TO_FLT_TYPED(t, s1, var->vv.regoff);
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_CAST_L2D(s1, var->vv.regoff);
+                                       else
+                                               M_CAST_I2F(s1, var->vv.regoff);
                                }
                                else {
                                        if (IS_2_WORD_TYPE(t))
-                                               M_LST(s1, REG_SP, var->vv.regoff * 4);
+                                               M_LST(s1, REG_SP, var->vv.regoff);
                                        else
-                                               M_IST(s1, REG_SP, var->vv.regoff * 4);
+                                               M_IST(s1, REG_SP, var->vv.regoff);
                                }
                        }
                        else {
                                if (!(var->flags & INMEMORY)) {
                                        if (IS_2_WORD_TYPE(t))
-                                               M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+                                               M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
                                        else
-                                               M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+                                               M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
                                }
                                else {
                                        /* Reuse Memory Position on Caller Stack */
@@ -278,12 +284,12 @@ bool codegen_emit(jitdata *jd)
        if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
                /* stack offset for monitor argument */
 
-               s1 = rd->memuse;
+               s1 = rd->memuse * 8;
 
 # if !defined(NDEBUG)
                if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
                        M_STMFD(BITMASK_ARGS, REG_SP);
-                       s1 += 4;
+                       s1 += 4 * 4;
                }
 # endif
 
@@ -297,7 +303,7 @@ bool codegen_emit(jitdata *jd)
                        emit_nullpointer_check_force(cd, iptr, REG_A0);
                }
 
-               M_STR(REG_A0, REG_SP, s1 * 4);
+               M_STR(REG_A0, REG_SP, s1);
                disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
                M_DSEG_BRANCH(disp);
                s1 = (s4) (cd->mcodeptr - cd->mcodebase);
@@ -319,6 +325,9 @@ bool codegen_emit(jitdata *jd)
 
        /* end of header generation */
 
+       /* create replacement points */
+       REPLACEMENT_POINTS_INIT(cd, jd);
+
        /* SECTION: ICMD Code Generation */
        /* for all basic blocks */
 
@@ -335,6 +344,9 @@ bool codegen_emit(jitdata *jd)
 
                codegen_resolve_branchrefs(cd, bptr);
 
+               /* handle replacement points */
+               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
+
                /* copy interface registers to their destination */
 
                len = bptr->indepth;
@@ -407,12 +419,8 @@ bool codegen_emit(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                disp = dseg_add_unique_address(cd, NULL);
 
-                               codegen_addpatchref(cd, PATCHER_aconst,
-                                                   iptr->sx.val.c.ref,
-                                                                       disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                               patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
+                                                   iptr->sx.val.c.ref, disp);
 
                                M_DSEG_LOAD(d, disp);
                        }
@@ -914,7 +922,7 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_MNFS(d, s1);
+                       M_FNEG(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -923,7 +931,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_ADFS(d, s1, s2);
+                       M_FADD(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -932,7 +940,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_SUFS(d, s1, s2);
+                       M_FSUB(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -941,7 +949,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_MUFS(d, s1, s2);
+                       M_FMUL(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -949,13 +957,14 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_DVFS(d, s1, s2);
+                       M_FDIV(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                /* ATTENTION: Jave does not want IEEE behaviour in FREM, do
                   not use this */
 
+#if 0
                case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
@@ -964,12 +973,13 @@ bool codegen_emit(jitdata *jd)
                        M_RMFS(d, s1, s2);
                        emit_store_dst(jd, iptr, d);
                        break;
+#endif
 
                case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_MNFD(d, s1);
+                       M_DNEG(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -978,7 +988,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_ADFD(d, s1, s2);
+                       M_DADD(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -987,7 +997,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_SUFD(d, s1, s2);
+                       M_DSUB(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -996,7 +1006,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_MUFD(d, s1, s2);
+                       M_DMUL(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1005,13 +1015,14 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_DVFD(d, s1, s2);
+                       M_DDIV(s1, s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                /* ATTENTION: Jave does not want IEEE behaviour in DREM, do
                   not use this */
 
+#if 0
                case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
@@ -1020,12 +1031,13 @@ bool codegen_emit(jitdata *jd)
                        M_RMFD(d, s1, s2);
                        emit_store_dst(jd, iptr, d);
                        break;
+#endif
 
                case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_FLTS(d, s1);
+                       M_CVTIF(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1033,7 +1045,7 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_FLTD(d, s1);
+                       M_CVTID(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1042,10 +1054,12 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
                        /* this uses round towards zero, as Java likes it */
-                       M_FIX(d, s1);
+                       M_CVTFI(s1, d);
+#if !defined(__VFP_FP__)
                        /* this checks for NaN; to return zero as Java likes it */
-                       M_CMF(s1, 0x8);
+                       M_FCMP(s1, 0x8);
                        M_MOVVS_IMM(0, d);
+#endif
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1054,10 +1068,12 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
                        /* this uses round towards zero, as Java likes it */
-                       M_FIX(d, s1);
+                       M_CVTDI(s1, d);
+#if !defined(__VFP_FP__)
                        /* this checks for NaN; to return zero as Java likes it */
-                       M_CMF(s1, 0x8);
+                       M_DCMP(s1, 0x8);
                        M_MOVVS_IMM(0, d);
+#endif
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1065,7 +1081,7 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       M_MVFS(d,s1);
+                       M_CVTDF(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1073,7 +1089,7 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       M_MVFD(d,s1);
+                       M_CVTFD(s1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1082,8 +1098,11 @@ bool codegen_emit(jitdata *jd)
                        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);
-                       M_CMF(s2, s1);
+                       M_FCMP(s2, s1);
                        M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+                       M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
                        M_SUBGT_IMM(d, d, 1);
                        M_ADDLT_IMM(d, d, 1);
                        emit_store_dst(jd, iptr, d);
@@ -1094,8 +1113,11 @@ bool codegen_emit(jitdata *jd)
                        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);
-                       M_CMF(s2, s1);
+                       M_DCMP(s2, s1);
                        M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+                       M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
                        M_SUBGT_IMM(d, d, 1);
                        M_ADDLT_IMM(d, d, 1);
                        emit_store_dst(jd, iptr, d);
@@ -1106,8 +1128,11 @@ bool codegen_emit(jitdata *jd)
                        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);
-                       M_CMF(s1, s2);
+                       M_FCMP(s1, s2);
                        M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+                       M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
                        M_SUBLT_IMM(d, d, 1);
                        M_ADDGT_IMM(d, d, 1);
                        emit_store_dst(jd, iptr, d);
@@ -1118,8 +1143,11 @@ bool codegen_emit(jitdata *jd)
                        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);
-                       M_CMF(s1, s2);
+                       M_DCMP(s1, s2);
                        M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+                       M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
                        M_SUBLT_IMM(d, d, 1);
                        M_ADDGT_IMM(d, d, 1);
                        emit_store_dst(jd, iptr, d);
@@ -1135,7 +1163,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        /* implicit null-pointer check */
-                       M_ILD_INTERN(d, s1, OFFSET(java_arrayheader, size));
+                       M_ILD_INTERN(d, s1, OFFSET(java_array_t, size));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1147,7 +1175,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
-                       M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1159,7 +1187,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
-                       M_LDRH(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       M_LDRH(d, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1171,7 +1199,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
-                       M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                       M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1183,7 +1211,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1195,7 +1223,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
-                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1208,10 +1236,10 @@ bool codegen_emit(jitdata *jd)
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
 #else
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
 #endif
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1225,10 +1253,10 @@ bool codegen_emit(jitdata *jd)
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
 #else
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
 #endif
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1241,7 +1269,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1253,7 +1281,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
-                       M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
                        break;
 
                case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1264,7 +1292,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
-                       M_STRH(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       M_STRH(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
                        break;
 
                case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1275,7 +1303,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
-                       M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                       M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
                        break;
 
                case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1286,7 +1314,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
                        break;
 
                case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1297,7 +1325,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
                        s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
-                       M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray, data[0]));
+                       M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
                        break;
 
                case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1309,10 +1337,10 @@ bool codegen_emit(jitdata *jd)
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
-                       M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
 #else
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
 #endif
                        break;
 
@@ -1325,10 +1353,10 @@ bool codegen_emit(jitdata *jd)
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
-                       M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
 #else
                        s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
-                       M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
 #endif
                        break;
 
@@ -1346,7 +1374,7 @@ bool codegen_emit(jitdata *jd)
                        M_INTMOVE(s3, REG_A1);
 
                        /* call builtin function */
-                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+                       disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
                        M_DSEG_BRANCH(disp);
 
                        /* recompute pv */
@@ -1354,43 +1382,34 @@ bool codegen_emit(jitdata *jd)
                        M_RECOMPUTE_PV(s1);
 
                        /* check resturn value of builtin */
-                       emit_exception_check(cd, iptr);
+                       emit_arraystore_check(cd, iptr);
 
                        /* finally store address into array */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
                        break;
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = dseg_add_unique_address(cd, NULL);
 
-                               disp = dseg_add_unique_address(cd, NULL);
-
-                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               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)) {
-                                       codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
+                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
+                                                           fi->class, 0);
                                }
-
-                               disp = dseg_add_address(cd, &(fi->value));
                        }
 
                        M_DSEG_LOAD(REG_ITMP3, disp);
@@ -1429,30 +1448,21 @@ bool codegen_emit(jitdata *jd)
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = dseg_add_unique_address(cd, NULL);
 
-                               disp = dseg_add_unique_address(cd, NULL);
-
-                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               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)) {
-                                       codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
+                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
+                                                           fi->class, 0);
                                }
-
-                               disp = dseg_add_address(cd, &(fi->value));
                        }
 
                        M_DSEG_LOAD(REG_ITMP3, disp);
@@ -1494,13 +1504,12 @@ bool codegen_emit(jitdata *jd)
 
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = fi->offset;
                        }
@@ -1512,14 +1521,10 @@ bool codegen_emit(jitdata *jd)
 #endif
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
-                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                               /* XXX REMOVE ME */
+                               uf = iptr->sx.s23.s3.uf;
 
-                               disp = 0;
+                               patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
                        }
 
                        switch (fieldtype) {
@@ -1560,13 +1565,12 @@ bool codegen_emit(jitdata *jd)
                        emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = fi->offset;
                        }
@@ -1602,14 +1606,10 @@ bool codegen_emit(jitdata *jd)
                        }
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
-                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                               /* XXX REMOVE ME */
+                               uf = iptr->sx.s23.s3.uf;
 
-                               disp = 0;
+                               patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
                        }
 
                        switch (fieldtype) {
@@ -1647,11 +1647,8 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_INTMOVE(s1, REG_ITMP1_XPTR);
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               codegen_addpatchref(cd, PATCHER_athrow_areturn,
+                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
                        M_DSEG_LOAD(REG_ITMP3, disp);
@@ -2069,13 +2066,15 @@ bool codegen_emit(jitdata *jd)
                case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
 
 #if !defined(ENABLE_SOFTFLOAT)
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT);
+                       M_CAST_F2I(s1, REG_RESULT);
                        goto ICMD_RETURN_do;
 #endif
 
                case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
 
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
                        s1 = emit_load_s1(jd, iptr, REG_RESULT);
                        M_INTMOVE(s1, REG_RESULT);
                        goto ICMD_RETURN_do;
@@ -2083,31 +2082,33 @@ bool codegen_emit(jitdata *jd)
                case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
 
 #if !defined(ENABLE_SOFTFLOAT)
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT_PACKED);
+                       M_CAST_D2L(s1, REG_RESULT_PACKED);
                        goto ICMD_RETURN_do;
 #endif
 
                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 ICMD_RETURN_do;
 
                case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
 
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
                        s1 = emit_load_s1(jd, iptr, REG_RESULT);
                        M_INTMOVE(s1, REG_RESULT);
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               codegen_addpatchref(cd, PATCHER_athrow_areturn,
+                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
                        goto ICMD_RETURN_do;
 
                case ICMD_RETURN:       /* ...  ==> ...                               */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
                        ICMD_RETURN_do:
 
 #if !defined(NDEBUG)
@@ -2121,7 +2122,7 @@ bool codegen_emit(jitdata *jd)
                        if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
                                /* stack offset for monitor argument */
 
-                               s1 = rd->memuse;
+                               s1 = rd->memuse * 8;
 
                                /* we need to save the proper return value */
 
@@ -2132,11 +2133,11 @@ bool codegen_emit(jitdata *jd)
                                case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
                                case ICMD_DRETURN:
                                        M_STMFD(BITMASK_RESULT, REG_SP);
-                                       s1 += 2;
+                                       s1 += 2 * 4;
                                        break;
                                }
 
-                               M_LDR(REG_A0, REG_SP, s1 * 4);
+                               M_LDR(REG_A0, REG_SP, s1);
                                disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
                                M_DSEG_BRANCH(disp);
 
@@ -2158,8 +2159,8 @@ bool codegen_emit(jitdata *jd)
 
                        /* deallocate stackframe for spilled variables */
 
-                       if ((cd->stackframesize - savedregs_num) > 0)
-                               M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize - savedregs_num);
+                       if ((cd->stackframesize / 4 - savedregs_num) > 0)
+                               M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
 
                        /* restore callee saved registers + do return */
 
@@ -2188,6 +2189,8 @@ bool codegen_emit(jitdata *jd)
                case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
                case ICMD_INVOKEINTERFACE:
 
+                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                lm = NULL;
                                um = iptr->sx.s23.s3.um;
@@ -2228,11 +2231,11 @@ bool codegen_emit(jitdata *jd)
                                        else {
                                                if (IS_2_WORD_TYPE(var->type)) {
                                                        s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                                       M_LST(s1, REG_SP, d * 4);
+                                                       M_LST(s1, REG_SP, d);
                                                }
                                                else {
                                                        s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                                       M_IST(s1, REG_SP, d * 4);
+                                                       M_IST(s1, REG_SP, d);
                                                }
                                        }
 #if !defined(ENABLE_SOFTFLOAT)
@@ -2240,14 +2243,17 @@ bool codegen_emit(jitdata *jd)
                                else {
                                        if (!md->params[s3].inmemory) {
                                                s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_CAST_FLT_TO_INT_TYPED(var->type, s1, d);
+                                               if (IS_2_WORD_TYPE(var->type))
+                                                       M_CAST_D2L(s1, d);
+                                               else
+                                                       M_CAST_F2I(s1, d);
                                        }
                                        else {
                                                s1 = emit_load(jd, iptr, var, REG_FTMP1);
                                                if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(s1, REG_SP, d * 4);
+                                                       M_DST(s1, REG_SP, d);
                                                else
-                                                       M_FST(s1, REG_SP, d * 4);
+                                                       M_FST(s1, REG_SP, d);
                                        }
                                }
 #endif /* !defined(ENABLE_SOFTFLOAT) */
@@ -2255,7 +2261,12 @@ bool codegen_emit(jitdata *jd)
 
                        switch (iptr->opc) {
                        case ICMD_BUILTIN:
-                               disp = dseg_add_functionptr(cd, bte->fp);
+
+                               if (bte->stub == NULL) {
+                                       disp = dseg_add_functionptr(cd, bte->fp);
+                               } else {
+                                       disp = dseg_add_functionptr(cd, bte->stub);
+                               }
 
                                M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
 
@@ -2265,8 +2276,6 @@ bool codegen_emit(jitdata *jd)
                                M_MOV(REG_PC, REG_PV);
                                s1 = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_RECOMPUTE_PV(s1);
-
-                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
@@ -2277,11 +2286,8 @@ bool codegen_emit(jitdata *jd)
                                if (lm == NULL) {
                                        disp = dseg_add_unique_address(cd, NULL);
 
-                                       codegen_addpatchref(cd, PATCHER_invokestatic_special,
+                                       patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
                                                                                um, disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
                                else
                                        disp = dseg_add_address(cd, lm->stubroutine);
@@ -2298,10 +2304,7 @@ bool codegen_emit(jitdata *jd)
 
                        case ICMD_INVOKEVIRTUAL:
                                if (lm == NULL) {
-                                       codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
+                                       patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
 
                                        s1 = 0;
                                }
@@ -2311,7 +2314,7 @@ bool codegen_emit(jitdata *jd)
 
                                /* implicit null-pointer check */
                                M_LDR_INTERN(REG_METHODPTR, REG_A0,
-                                                        OFFSET(java_objectheader, vftbl));
+                                                        OFFSET(java_object_t, vftbl));
                                M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
 
                                /* generate the actual call */
@@ -2324,10 +2327,7 @@ bool codegen_emit(jitdata *jd)
 
                        case ICMD_INVOKEINTERFACE:
                                if (lm == NULL) {
-                                       codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
+                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
                                        s1 = 0;
                                        s2 = 0;
@@ -2340,7 +2340,7 @@ bool codegen_emit(jitdata *jd)
 
                                /* implicit null-pointer check */
                                M_LDR_INTERN(REG_METHODPTR, REG_A0,
-                                                        OFFSET(java_objectheader, vftbl));
+                                                        OFFSET(java_object_t, vftbl));
                                M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
                                M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
 
@@ -2353,6 +2353,9 @@ bool codegen_emit(jitdata *jd)
                                break;
                        }
 
+                       /* store size of call code in replacement point */
+                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+
                        /* store return value */
 
                        d = md->returntype.type;
@@ -2394,7 +2397,10 @@ bool codegen_emit(jitdata *jd)
 #if !defined(ENABLE_SOFTFLOAT)
                                } else {
                                        s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                                       M_CAST_INT_TO_FLT_TYPED(VAROP(iptr->dst)->type, REG_RESULT_TYPED(VAROP(iptr->dst)->type), s1);
+                                       if (IS_2_WORD_TYPE(d))
+                                               M_CAST_L2D(REG_RESULT_PACKED, s1);
+                                       else
+                                               M_CAST_I2F(REG_RESULT, s1);
                                }
 #endif /* !defined(ENABLE_SOFTFLOAT) */
 
@@ -2431,12 +2437,9 @@ bool codegen_emit(jitdata *jd)
                                emit_label_beq(cd, BRANCH_LABEL_1);
 
                                disp = dseg_add_unique_s4(cd, 0); /* super->flags */
-                               codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
+                               patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
                                                    iptr->sx.s23.s3.c.ref, disp);
 
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                                M_DSEG_LOAD(REG_ITMP2, disp);
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_DSEG_LOAD(REG_ITMP3, disp);
@@ -2451,19 +2454,15 @@ bool codegen_emit(jitdata *jd)
                                        disp = dseg_add_unique_s4(cd, superindex);
                                }
                                if (super == NULL) {
-                                       codegen_addpatchref(cd,
-                                                           PATCHER_checkcast_instanceof_interface,
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
                                                            iptr->sx.s23.s3.c.ref, disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
                                else {
                                        M_TST(s1, s1);
                                        emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
-                               M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+                               M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
 
                                /* we put unresolved or non-immediate superindices onto dseg */
@@ -2482,7 +2481,7 @@ bool codegen_emit(jitdata *jd)
                                   things differently here! */
                                if ((super == NULL) || !IS_IMM(superindex)) {
 
-                                       M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_objectheader, vftbl));
+                                       M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
 
                                        /* this assumes something */
                                        assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
@@ -2518,12 +2517,9 @@ bool codegen_emit(jitdata *jd)
 
                                        disp = dseg_add_unique_address(cd, NULL);
 
-                                       codegen_addpatchref(cd, PATCHER_checkcast_instanceof_class,
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
                                                            iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
                                else {
                                        disp = dseg_add_address(cd, super->vftbl);
@@ -2532,7 +2528,7 @@ bool codegen_emit(jitdata *jd)
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+                               M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                M_DSEG_LOAD(REG_ITMP3, disp);
 
                                CODEGEN_CRITICAL_SECTION_START;
@@ -2568,12 +2564,9 @@ bool codegen_emit(jitdata *jd)
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        disp = dseg_add_unique_address(cd, NULL);
 
-                                       codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
                                else
                                        disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
@@ -2632,12 +2625,9 @@ bool codegen_emit(jitdata *jd)
                                emit_label_beq(cd, BRANCH_LABEL_1);
 
                                disp = dseg_add_unique_s4(cd, 0); /* super->flags */
-                               codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
+                               patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
                                                    iptr->sx.s23.s3.c.ref, disp);
 
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                                M_DSEG_LOAD(REG_ITMP2, disp);
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_DSEG_LOAD(REG_ITMP3, disp);
@@ -2657,12 +2647,8 @@ bool codegen_emit(jitdata *jd)
                                        if (d == REG_ITMP2)
                                                M_EOR(d, d, d);
 
-                                       codegen_addpatchref(cd,
-                                                           PATCHER_checkcast_instanceof_interface,
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
                                                            iptr->sx.s23.s3.c.ref, disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
                                else {
                                        M_EOR(d, d, d);
@@ -2670,7 +2656,7 @@ bool codegen_emit(jitdata *jd)
                                        emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
-                               M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_LDR_INTERN(REG_ITMP3,
                                                         REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
 
@@ -2730,12 +2716,8 @@ bool codegen_emit(jitdata *jd)
 
                                        disp = dseg_add_unique_address(cd, NULL);
 
-                                       codegen_addpatchref(cd, PATCHER_checkcast_instanceof_class,
-                                                           iptr->sx.s23.s3.c.ref,
-                                                                               disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
+                                                           iptr->sx.s23.s3.c.ref, disp);
                                }
                                else {
                                        disp = dseg_add_address(cd, super->vftbl);
@@ -2745,7 +2727,7 @@ bool codegen_emit(jitdata *jd)
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_DSEG_LOAD(REG_ITMP2, disp);
 
                                CODEGEN_CRITICAL_SECTION_START;
@@ -2805,11 +2787,8 @@ bool codegen_emit(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                disp = dseg_add_unique_address(cd, NULL);
 
-                               codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
+                               patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
                                                                        iptr->sx.s23.s3.c.ref, disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
                        else
                                disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
@@ -2862,9 +2841,9 @@ bool codegen_emit(jitdata *jd)
        dseg_createlinenumbertable(cd);
 
 
-       /* generate stubs */
+       /* generate traps */
 
-       emit_patcher_stubs(jd);
+       emit_patcher_traps(jd);
 
        /* everything's ok */
 
@@ -2901,12 +2880,11 @@ void codegen_emit_stub_compiler(jitdata *jd)
 
 *******************************************************************************/
 
-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;
-       s4           nativeparams;
        methoddesc  *md;
        s4           i, j;
        s4           t;
@@ -2921,24 +2899,23 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        /* initialize variables */
 
        md = m->parseddesc;
-       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
 
        /* calculate stackframe size */
 
-       cd->stackframesize = 
-               1 +                                                /* return address  */
-               sizeof(stackframeinfo) / SIZEOF_VOID_P +           /* stackframeinfo  */
-               sizeof(localref_table) / SIZEOF_VOID_P +           /* localref_table  */
-               nmd->memuse;                                       /* stack arguments */
+       cd->stackframesize =
+               4 +                                                /* return address  */
+               sizeof(stackframeinfo) +                           /* stackframeinfo  */
+               sizeof(localref_table) +                           /* localref_table  */
+               nmd->memuse * 4;                                   /* stack arguments */
 
        /* align stack to 8-byte */
 
-       cd->stackframesize = (cd->stackframesize + 1) & ~1;
+       cd->stackframesize = (cd->stackframesize + 4) & ~4;
 
        /* create method header */
 
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* 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         */
@@ -2949,7 +2926,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        /* generate stub code */
 
        M_STMFD(1<<REG_LR, REG_SP);
-       M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize - 1);
+       M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
 
 #if !defined(NDEBUG)
        if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
@@ -2960,13 +2937,18 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        funcdisp = dseg_add_functionptr(cd, f);
 
-#if !defined(WITH_STATIC_CLASSPATH)
-       if (f == NULL) {
-               codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
+       if (f == NULL)
+               patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
 
-               if (opt_showdisassemble)
-                       M_NOP;
-       }
+#if defined(ENABLE_GC_CACAO)
+       /* Save callee saved integer registers in stackframeinfo (GC may
+          need to recover them during a collection). */
+
+       disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
+               OFFSET(stackframeinfo, intregs);
+
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
 #endif
 
        /* Save integer and float argument registers (these are 4
@@ -2977,11 +2959,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* create native stackframe info */
 
-       assert(IS_IMM(4*4 + cd->stackframesize * 4));
-       M_ADD_IMM(REG_A0, REG_SP, 4*4 + cd->stackframesize * 4 - SIZEOF_VOID_P);
+       M_ADD_IMM(REG_A0, REG_SP, 4*4);
        M_MOV(REG_A1, REG_PV);
-       M_ADD_IMM(REG_A2, REG_SP, 4*4 + cd->stackframesize * 4);
-       M_LDR_INTERN(REG_A3, REG_SP, 4*4 + cd->stackframesize * 4 - SIZEOF_VOID_P);
        disp = dseg_add_functionptr(cd, codegen_start_native_call);
        M_DSEG_BRANCH(disp);
 
@@ -2990,6 +2969,11 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        s1 = (s4) (cd->mcodeptr - cd->mcodebase);
        M_RECOMPUTE_PV(s1);
 
+       /* remember class argument */
+
+       if (m->flags & ACC_STATIC)
+               M_MOV(REG_ITMP3, REG_RESULT);
+
        /* Restore integer and float argument registers (these are 4
           registers, stack is 8-byte aligned). */
 
@@ -2999,7 +2983,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        /* copy or spill arguments to new locations */
        /* ATTENTION: the ARM has only integer argument registers! */
 
-       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 (!md->params[i].inmemory) {
@@ -3022,9 +3006,9 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
                        }
                        else {
                                if (IS_2_WORD_TYPE(t))
-                                       M_LST(s1, REG_SP, s2 * 4);
+                                       M_LST(s1, REG_SP, s2);
                                else
-                                       M_IST(s1, REG_SP, s2 * 4);
+                                       M_IST(s1, REG_SP, s2);
                        }
                }
                else {
@@ -3032,27 +3016,29 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
                        s2 = nmd->params[j].regoff;
 
                        if (IS_2_WORD_TYPE(t)) {
-                               M_LLD(REG_ITMP12_PACKED, REG_SP, s1 * 4);
-                               M_LST(REG_ITMP12_PACKED, REG_SP, s2 * 4);
+                               M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
+                               M_LST(REG_ITMP12_PACKED, REG_SP, s2);
                        }
                        else {
-                               M_ILD(REG_ITMP1, REG_SP, s1 * 4);
-                               M_IST(REG_ITMP1, REG_SP, s2 * 4);
+                               M_ILD(REG_ITMP1, REG_SP, s1);
+                               M_IST(REG_ITMP1, REG_SP, s2);
                        }
                }
        }
 
-       /* put class into second argument register */
+       /* Handle native Java methods. */
 
-       if (m->flags & ACC_STATIC) {
-               disp = dseg_add_address(cd, m->class);
-               M_DSEG_LOAD(REG_A1, 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_A1, REG_ITMP3);
 
-       disp = dseg_add_address(cd, _Jv_env);
-       M_DSEG_LOAD(REG_A0, disp);
+               /* put env into first argument register */
+
+               disp = dseg_add_address(cd, _Jv_env);
+               M_DSEG_LOAD(REG_A0, disp);
+       }
 
        /* do the native function call */
 
@@ -3094,7 +3080,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        M_STMFD(BITMASK_RESULT, REG_SP);
 
-       M_ADD_IMM(REG_A0, REG_SP, 2*4 + cd->stackframesize * 4 - SIZEOF_VOID_P);
+       M_ADD_IMM(REG_A0, REG_SP, 2*4);
+       M_MOV(REG_A1, REG_PV);
        disp = dseg_add_functionptr(cd, codegen_finish_native_call);
        M_DSEG_BRANCH(disp);
        s1 = (s4) (cd->mcodeptr - cd->mcodebase);
@@ -3103,9 +3090,20 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        M_MOV(REG_ITMP1_XPTR, REG_RESULT);
        M_LDMFD(BITMASK_RESULT, REG_SP);
 
+#if defined(ENABLE_GC_CACAO)
+       /* restore callee saved int registers from stackframeinfo (GC might have  */
+       /* modified them during a collection).                                    */
+
+       disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
+               OFFSET(stackframeinfo, intregs);
+
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
        /* finish stub code, but do not yet return to caller */
 
-       M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize - 1);
+       M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
        M_LDMFD(1<<REG_LR, REG_SP);
 
        /* check for exception */
@@ -3123,7 +3121,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* generate patcher stubs */
 
-       emit_patcher_stubs(jd);
+       emit_patcher_traps(jd);
 }