* src/vm/jit/codegen-common.cpp (codegen_emit): New generic version of the
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Mon, 31 Aug 2009 22:59:30 +0000 (00:59 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Mon, 31 Aug 2009 22:59:30 +0000 (00:59 +0200)
code generating loop. This is the main point of this huge commit.

There are some other changes which might be interesting about this commit,
which are described in detail:
* src/vm/jit/code.hpp (codeinfo): Added runtime information to replace most
parts of the method header.
* src/vm/jit/codegen-common.cpp (codegen_finish): Sets runtime information.
(codegen_start_native_call): Use MD function to determine size of stackframe.
(codegen_finish_native_call): Likewise.
* src/vm/jit/codegen-common.hpp: Added prototypes of new MD functions.
* src/vm/jit/emit-common.hpp: Added prototypes of new MD functions.
(emit_xmove): Added generic inline functions for register moves.
* src/vm/jit/optimizing/profile.c: Disabled some broken profiling code.
* src/vm/jit/optimizing/profile.h: Moved definitions CPU cycle counting
macros to where they belong.
* src/vm/jit/replace.cpp: Uses new architecture description macros.
* src/vm/jit/stacktrace.cpp: Use MD function to determine size of stackframe.

The rest of the files were machine dependent adaptions of the different ports
with too many changes to describe here, so I just list the files:
* src/vm/jit/alpha/arch.h
* src/vm/jit/alpha/codegen.c
* src/vm/jit/alpha/codegen.h
* src/vm/jit/alpha/emit.c
* src/vm/jit/alpha/md.h
* src/vm/jit/arm/arch.h
* src/vm/jit/arm/codegen.c
* src/vm/jit/arm/codegen.h
* src/vm/jit/arm/emit.c
* src/vm/jit/arm/md.h
* src/vm/jit/i386/arch.h
* src/vm/jit/i386/codegen.c
* src/vm/jit/i386/codegen.h
* src/vm/jit/i386/emit.c
* src/vm/jit/i386/emit.h
* src/vm/jit/i386/md.h
* src/vm/jit/m68k/arch.h
* src/vm/jit/m68k/codegen.c
* src/vm/jit/m68k/codegen.h
* src/vm/jit/m68k/emit.c
* src/vm/jit/m68k/md.h
* src/vm/jit/mips/arch.h
* src/vm/jit/mips/codegen.c
* src/vm/jit/mips/codegen.h
* src/vm/jit/mips/emit.c
* src/vm/jit/mips/md.h
* src/vm/jit/powerpc/arch.h
* src/vm/jit/powerpc/codegen.c
* src/vm/jit/powerpc/codegen.h
* src/vm/jit/powerpc/emit.c
* src/vm/jit/powerpc/md.h
* src/vm/jit/powerpc64/arch.h
* src/vm/jit/powerpc64/codegen.c
* src/vm/jit/powerpc64/codegen.h
* src/vm/jit/powerpc64/emit.c
* src/vm/jit/powerpc64/md.h
* src/vm/jit/s390/arch.h
* src/vm/jit/s390/codegen.c
* src/vm/jit/s390/codegen.h
* src/vm/jit/s390/emit.c
* src/vm/jit/s390/md.h
* src/vm/jit/sparc64/arch.h
* src/vm/jit/sparc64/codegen.c
* src/vm/jit/sparc64/codegen.h
* src/vm/jit/sparc64/emit.c
* src/vm/jit/sparc64/md.h
* src/vm/jit/x86_64/arch.h
* src/vm/jit/x86_64/codegen.c
* src/vm/jit/x86_64/codegen.h
* src/vm/jit/x86_64/emit.c
* src/vm/jit/x86_64/emit.h
* src/vm/jit/x86_64/md.h

60 files changed:
src/vm/jit/alpha/arch.h
src/vm/jit/alpha/codegen.c
src/vm/jit/alpha/codegen.h
src/vm/jit/alpha/emit.c
src/vm/jit/alpha/md.h
src/vm/jit/arm/arch.h
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/emit.c
src/vm/jit/arm/md.h
src/vm/jit/code.hpp
src/vm/jit/codegen-common.cpp
src/vm/jit/codegen-common.hpp
src/vm/jit/emit-common.hpp
src/vm/jit/i386/arch.h
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/emit.c
src/vm/jit/i386/emit.h
src/vm/jit/i386/md.h
src/vm/jit/m68k/arch.h
src/vm/jit/m68k/codegen.c
src/vm/jit/m68k/codegen.h
src/vm/jit/m68k/emit.c
src/vm/jit/m68k/md.h
src/vm/jit/mips/arch.h
src/vm/jit/mips/codegen.c
src/vm/jit/mips/codegen.h
src/vm/jit/mips/emit.c
src/vm/jit/mips/md.h
src/vm/jit/optimizing/profile.c
src/vm/jit/optimizing/profile.h
src/vm/jit/powerpc/arch.h
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc/codegen.h
src/vm/jit/powerpc/emit.c
src/vm/jit/powerpc/md.h
src/vm/jit/powerpc64/arch.h
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/codegen.h
src/vm/jit/powerpc64/emit.c
src/vm/jit/powerpc64/md.h
src/vm/jit/replace.cpp
src/vm/jit/s390/arch.h
src/vm/jit/s390/codegen.c
src/vm/jit/s390/codegen.h
src/vm/jit/s390/emit.c
src/vm/jit/s390/md.h
src/vm/jit/sparc64/arch.h
src/vm/jit/sparc64/codegen.c
src/vm/jit/sparc64/codegen.h
src/vm/jit/sparc64/emit.c
src/vm/jit/sparc64/md.h
src/vm/jit/stacktrace.cpp
src/vm/jit/x86_64/arch.h
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/jit/x86_64/md.h

index 186f1d1b98948fe7d76b125eda96bf85562cc4bb..e3f96f6a2e7d6a37ea95c087b268c5ebbf24c5ec 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
index 918a94e90efc86e3008b942b66818a4a82b03763..2095481803267eefc9899694c3a09fbe66f4c373 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#elif defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* codegen_emit ****************************************************************
-
-   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;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       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;
-       bte         = NULL;
-       currentline = 0;
-
-       {
-       s4 i, p, t, l;
-       s4 savedregs_num;
-
-       savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the RA */
-
-       /* 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 */
-       if (checksync && code_is_synchronized(code))
-               cd->stackframesize++;
-#endif
-
-       /* create method header */
-
-#if 0
-       cd->stackframesize = (cd->stackframesize + 1) & ~1; /* align stack to 16-bytes */
-#endif
-
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
-
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+       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) */
 
@@ -208,7 +137,7 @@ bool codegen_emit(jitdata *jd)
                else {                                       /* floating args         */
                        if (!md->params[p].inmemory) {           /* register arguments    */
                                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);
                        }
@@ -220,187 +149,70 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-       /* call monitorenter function */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse;
-
-#if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LST(abi_registers_integer_argument[p], REG_SP, p * 8);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
-
-                       s1 += INT_ARG_CNT + FLT_ARG_CNT;
-               }
-#endif /* !defined(NDEBUG) */
-
-               /* decide which monitor enter function to call */
-
-               if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->clazz->object.header);
-                       M_ALD(REG_A0, REG_PV, disp);
-               }
-               else {
-                       M_BNEZ(REG_A0, 1);
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
-               }
-
-               M_AST(REG_A0, REG_SP, s1 * 8);
-               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-               M_ALD(REG_PV, REG_PV, disp);
-               M_JSR(REG_RA, REG_PV);
-               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-               M_LDA(REG_PV, REG_RA, -disp);
 
-#if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8);
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int32_t p;
+       int i;
 
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+       // Get required compiler data.
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
-                       M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
-               }
-#endif /* !defined(NDEBUG) */
-       }                       
-#endif
-
-       /* call trace function */
+       p = cd->stackframesize;
 
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
+       /* restore return address */
 
+       if (!code_is_leafmethod(code)) {
+               p--; M_LLD(REG_RA, 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);
-
-               /* copy interface registers to their destination */
-
-               len = bptr->indepth;
-               MCODECHECK(64+len);
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-               while (len) {
-                       len--;
-                       src = bptr->invars[len];
-                       if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
-                                       /*                              d = reg_of_var(m, src, REG_ITMP1); */
-                                       if (!(src->flags & INMEMORY))
-                                               d = src->vv.regoff;
-                                       else
-                                               d = REG_ITMP1;
-                                       M_INTMOVE(REG_ITMP1, d);
-                                       emit_store(jd, NULL, src, d);
-                               }
-                       }
-               } else {
-#endif
-                       while (len) {
-                               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;
+       /* restore saved registers */
 
-               for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
-                       if (iptr->line != currentline) {
-                               linenumbertable_list_entry_add(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:
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_LLD(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);
+       }
 
-                       REPLACEMENT_POINT_INLINE_START(cd, iptr);
-                       break;
+       /* deallocate stack */
 
-               case ICMD_INLINE_BODY:
+       if (cd->stackframesize)
+               M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
 
-                       REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
+       M_RET(REG_ZERO, REG_RA);
+}
 
-               case ICMD_INLINE_END:
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       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;
 
-               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+       // Get required compiler data.
+       codegendata* cd = jd->cd;
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
-                       break;
+       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_ITMP1);
-                       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);
@@ -448,30 +260,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/move/copy 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                 */
@@ -1338,15 +1126,6 @@ bool codegen_emit(jitdata *jd)
 
                /* 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);
@@ -1712,96 +1491,6 @@ bool codegen_emit(jitdata *jd)
                        M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
                        break;
 
-
-               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
-
-                       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);
-                       }
-                       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->clazz))
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
-                                                                                 0);
-                       }
-
-                       M_ALD(REG_ITMP1, REG_PV, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ILD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_LLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_ADR:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ALD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_FLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:                          
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_DLD(d, REG_ITMP1, 0);
-                               break;
-                       }
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               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);
-                       }
-                       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->clazz))
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
-                                                                                 0);
-                       }
-
-                       M_ALD(REG_ITMP1, REG_PV, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_IST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_LST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_ADR:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_AST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
-                               M_FST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
-                               M_DST(s1, REG_ITMP1, 0);
-                               break;
-                       }
-                       break;
-
                case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
                                          /* val = value (in current instruction)     */
                                          /* following NOP)                           */
@@ -1975,139 +1664,83 @@ 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_JMP(REG_ITMP2_XPC, REG_ITMP2);
                        M_NOP;              /* nop ensures that XPC is less than the end */
                                            /* of basic block                            */
-                       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 ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_beqz(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bltz(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_blez(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bnez(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bgtz(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bgez(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
+                               M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
@@ -2208,7 +1841,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPEQ:    /* op1 = target JavaVM pc                     */
-               case ICMD_IF_ACMPEQ:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -2218,7 +1850,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
-               case ICMD_IF_ACMPNE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -2262,117 +1893,6 @@ bool codegen_emit(jitdata *jd)
                        emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
-
-               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_LRETURN:
-
-                       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_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 */
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_ARETURN:
-                                       M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_ALD(REG_PV, REG_PV, disp);
-                               M_JSR(REG_RA, REG_PV);
-                               disp = -(s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, disp);
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_ARETURN:
-                                       M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore return address                                         */
-
-                       if (!code_is_leafmethod(code)) {
-                               p--; M_LLD(REG_RA, REG_SP, p * 8);
-                       }
-
-                       /* restore saved registers                                        */
-
-                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
-                               p--; M_LLD(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(REG_ZERO, REG_RA);
-                       ALIGNCODENOP;
-                       }
-                       break;
-
-
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -2424,216 +1944,92 @@ nowperformreturn:
                        ALIGNCODENOP;
                        break;
 
+               case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
+                       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);
 
-               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
-                       {
-                       s4 i, val;
-                       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);
+                       M_ALD(REG_PV, REG_PV, disp);  /* Pointer to built-in-function */
 
-                       while (--i >= 0) {
-                               val = lookup->value;
-                               if ((val >= 0) && (val <= 255)) {
-                                       M_CMPEQ_IMM(s1, val, REG_ITMP2);
-                               } else {
-                                       if ((val >= -32768) && (val <= 32767)) {
-                                               M_LDA(REG_ITMP2, REG_ZERO, val);
-                                       } else {
-                                               disp = dseg_add_s4(cd, val);
-                                               M_ILD(REG_ITMP2, REG_PV, disp);
-                                       }
-                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
-                               }
-                               emit_bnez(cd, lookup->target.block, REG_ITMP2);
-                               lookup++;
-                       }
+                       /* generate the actual call */
 
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       ALIGNCODENOP;
+                       M_JSR(REG_RA, REG_PV);
                        break;
-                       }
-
-
-               case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
-
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
 
-                       bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto gen_method;
+               case ICMD_INVOKESPECIAL:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
+                       /* fall-through */
 
                case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               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;
-                               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);         /* method pointer in r27 */
 
-                       MCODECHECK((s3 << 1) + 64);
+                       /* generate the actual call */
 
-                       /* copy arguments to registers or stack location                  */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
-
-                               /* already preallocated (ARGVAR)? */
+                       M_JSR(REG_RA, REG_PV);
+                       break;
 
-                               if (var->flags & PREALLOC)
-                                       continue;
+               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);
 
-                               if (IS_INT_LNG_TYPE(var->type)) {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               M_INTMOVE(s1, d);
-                                       }
-                                       else {
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_LST(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_JSR(REG_RA, REG_PV);
-                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               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);         /* method pointer in r27 */
-
-                               /* generate the actual call */
-
-                               M_JSR(REG_RA, REG_PV);
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -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_JSR(REG_RA, REG_PV);
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               break;
-
-                       case ICMD_INVOKEINTERFACE:
-                               if (lm == NULL) {
-                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_PV, REG_METHODPTR, s1);
 
-                                       s1 = 0;
-                                       s2 = 0;
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->clazz->index;
+                       /* generate the actual call */
 
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
-                                       
-                               /* 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_JSR(REG_RA, REG_PV);
+                       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_JSR(REG_RA, REG_PV);
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -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 the return value */
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
+                       }
+                               
+                       /* 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);
 
-                       d = md->returntype.type;
+                       /* generate the actual call */
 
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-                                       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);
-                       }
+                       M_JSR(REG_RA, REG_PV);
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
@@ -3029,23 +2425,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 */
-
-       /* generate traps */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
@@ -3197,7 +2578,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
                                s2 = nmd->params[j].regoff;
 
                                if (!nmd->params[j].inmemory)
-                                       M_FLTMOVE(s1, s2);
+                                       emit_fmove(cd, s1, s2);
                                else {
                                        if (IS_2_WORD_TYPE(t))
                                                M_DST(s1, REG_SP, s2);
index 17953240b186e95ed0f8fb61e39ec8ae4b3d7ceb..2d4db729eba10d177804522a04b53906dff2b939 100644 (file)
     }
 
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_MOV(a, b); \
-    } while (0)
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_FMOV(a, b); \
-    } while (0)
-
-
 #define ICONST(d,c)        emit_iconst(cd, (d), (c))
 #define LCONST(d,c)        emit_lconst(cd, (d), (c))
 
 
 #define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)                 /* addr load  */
+#define M_ALD_DSEG(a,disp)      M_LLD(a,REG_PV,disp)
 
 #define M_BST(a,b,disp)         M_MEM(0x0e,a,b,disp)            /*  8 store   */
 #define M_SST(a,b,disp)         M_MEM(0x0d,a,b,disp)            /* 16 store   */
 #define M_FCMPLTS(a,b,c)        M_FOP3 (0x16, 0x5a6, a,b,c)     /* c = a<b    */
 
 #define M_FMOV(fa,fb)           M_FOP3 (0x17, 0x020, fa,fa,fb)  /* b = a      */
+#define M_DMOV(fa,fb)           M_FMOV (fa,fb)
 #define M_FMOVN(fa,fb)          M_FOP3 (0x17, 0x021, fa,fa,fb)  /* b = -a     */
 
 #define M_FNOP                  M_FMOV (31,31)
index ac5d0ba12febe305ce5eb2bf8e0327ceb75d67e4..dd5d345c711f3d09d498ff039dd49cec2102416a 100644 (file)
@@ -234,6 +234,28 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
+/**
+ * Emits code comparing one integer register to an immediate value.
+ */
+void emit_icmpeq_imm(codegendata* cd, int reg, int32_t value, int d)
+{
+       int32_t disp;
+
+       if ((value >= 0) && (value <= 255)) {
+               M_CMPEQ_IMM(reg, value, d);
+       } else {
+               assert(reg != REG_ITMP2);
+               if ((value >= -32768) && (value <= 32767)) {
+                       M_LDA(REG_ITMP2, REG_ZERO, value);
+               } else {
+                       disp = dseg_add_s4(cd, value);
+                       M_ILD(REG_ITMP2, REG_PV, disp);
+               }
+               M_CMPEQ(reg, REG_ITMP2, d);
+       }
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -455,6 +477,124 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       M_LDA(REG_PV, REG_RA, -disp);
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
+
+               for (p = 0; p < INT_ARG_CNT; p++)
+                       M_LST(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
+       }
+#endif /* !defined(NDEBUG) */
+
+       /* decide which monitor enter function to call */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, &m->clazz->object.header);
+               M_ALD(REG_A0, REG_PV, disp);
+       }
+       else {
+               M_BNEZ(REG_A0, 1);
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
+       }
+
+       M_AST(REG_A0, REG_SP, syncslot_offset);
+       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+       M_ALD(REG_PV, REG_PV, disp);
+       M_JSR(REG_RA, REG_PV);
+       emit_recompute_pv(cd);
+
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               for (p = 0; p < INT_ARG_CNT; p++)
+                       M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
+       }
+#endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       M_ALD(REG_A0, REG_SP, syncslot_offset);
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_LNG:
+       case TYPE_ADR:
+               M_LST(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset);
+               break;
+       }
+
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_ALD(REG_PV, REG_PV, disp);
+       M_JSR(REG_RA, REG_PV);
+       emit_recompute_pv(cd);
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_LNG:
+       case TYPE_ADR:
+               M_LLD(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset);
+               break;
+       }
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index e939d3803677cc45c07092b70cbb23d87038db05..08d4cca2e92f313e89c9defed73f357e46be2aa2 100644 (file)
@@ -47,6 +47,21 @@ extern bool has_ext_instr_set;
 
 /* inline functions ***********************************************************/
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On Alpha we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 8cd87690336f1d4ddf65add3affb498d81cc1ea6..2d282f9570a5be8bd5c8456c2c7f72253051e2b8 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
index 34bf177cab734d49574c1fc560215af76e45d409..05d3613cf8dcc1599cff51a08c68f98863b20c2c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/arm/codegen.c - machine code generator for Arm
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 
-#if defined(ENABLE_LSRA)
-#include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* codegen_emit ****************************************************************
-
-   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              i, t, len;
-       s4              s1, s2, s3, d;
-       s4              disp;
-       varinfo        *var;
-       basicblock     *bptr;
-       instruction    *iptr;
-
-       s4              spilledregs_num;
-       s4              savedregs_num;
-       u2              savedregs_bitmask;
-       u2              currentline;
-
-       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE* */
-       unresolved_method  *um;
-       builtintable_entry *bte;
-       methoddesc         *md;
-       fieldinfo          *fi;
-       unresolved_field   *uf;
-       int                 fieldtype;
-       int                 varindex;
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* prevent compiler warnings */
-
-       lm  = NULL;
-       um  = NULL;
-       bte = NULL;
-
-       fieldtype = -1;
-       
-       /* space to save used callee saved registers */
-
-       savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the LR */
-
-       savedregs_num += (INT_SAV_CNT - rd->savintreguse);
-       /*savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);*/
-       assert((FLT_SAV_CNT - rd->savfltreguse) == 0);
-
-       spilledregs_num = rd->memuse;
-
-#if defined(ENABLE_THREADS)        /* space to save argument of monitor_enter */
-       if (checksync && code_is_synchronized(code))
-               spilledregs_num++;
-#endif
-
-       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 + 4) & ~4;
-
-       /* SECTION: Method Header */
-       /* create method header */
-
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
-
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
-
-       /* save return address and used callee saved registers */
-
-       savedregs_bitmask = 0;
-
-       if (!code_is_leafmethod(code))
+       varinfo*    var;
+       methoddesc* md;
+       int32_t     s1;
+       int32_t     t, len;
+       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;
+
+       int32_t savedregs_num = 0;
+       uint32_t savedregs_bitmask = 0;
+
+       if (!code_is_leafmethod(code)) {
+               savedregs_num++;
                savedregs_bitmask = (1<<REG_LR);
+       }
 
-       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--)
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               savedregs_num++;
                savedregs_bitmask |= (1<<(rd->savintregs[i]));
+       }
 
 #if !defined(NDEBUG)
        for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
-               log_text("!!! CODEGEN: floating-point callee saved registers are not saved to stack (SEVERE! STACK IS MESSED UP!)");
-               /* TODO: floating-point */
+               vm_abort("codegen_emit_prolog: Floating-point callee saved registers are not saved to stack");
        }
 #endif
 
-       if (savedregs_bitmask)
+       /* save return address and used callee saved registers */
+
+       if (savedregs_bitmask != 0)
                M_STMFD(savedregs_bitmask, REG_SP);
 
        /* create additional stack frame for spilled variables (if necessary) */
 
-       if ((cd->stackframesize / 4 - savedregs_num) > 0)
-               M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
+       int32_t additional_bytes = (cd->stackframesize * 8 - savedregs_num * 4);
+
+       if (additional_bytes > 0)
+               M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, additional_bytes / 4);
 
        /* take arguments out of register or stack frame */
 
@@ -217,13 +148,13 @@ bool codegen_emit(jitdata *jd)
                        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);
+                                               M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
                                        else
-                                               M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
+                                               M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
                                }
                                else {                               /* stack arg -> spilled  */
                                        /* Reuse Memory Position on Caller Stack */
-                                       var->vv.regoff = cd->stackframesize + s1;
+                                       var->vv.regoff = cd->stackframesize * 8 + s1;
                                }
                        }
 #if !defined(ENABLE_SOFTFLOAT)
@@ -246,157 +177,94 @@ bool codegen_emit(jitdata *jd)
                        else {
                                if (!(var->flags & INMEMORY)) {
                                        if (IS_2_WORD_TYPE(t))
-                                               M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
+                                               M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
                                        else
-                                               M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1);
+                                               M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
                                }
                                else {
                                        /* Reuse Memory Position on Caller Stack */
-                                       var->vv.regoff = cd->stackframesize + s1;
+                                       var->vv.regoff = cd->stackframesize * 8 + s1;
                                }
                        }
                }
 #endif /* !defined(ENABLE_SOFTFLOAT) */
        }
+}
 
-#if defined(ENABLE_THREADS)
-       /* call monitorenter function */
-
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse * 8;
-
-# if !defined(NDEBUG)
-               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
-                       M_STMFD(BITMASK_ARGS, REG_SP);
-                       s1 += 4 * 4;
-               }
-# endif
 
-               /* get the correct lock object */
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int i;
 
-               if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->clazz->object.header);
-                       M_DSEG_LOAD(REG_A0, disp);
-               }
-               else {
-                       emit_nullpointer_check_force(cd, iptr, REG_A0);
-               }
+       // Get required compiler data.
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
-               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);
-               M_RECOMPUTE_PV(s1);
+       int32_t savedregs_num = 0;
+       uint32_t savedregs_bitmask = 0;
 
-# if !defined(NDEBUG)
-               if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                       M_LDMFD(BITMASK_ARGS, REG_SP);
-# endif
+       if (!code_is_leafmethod(code)) {
+               savedregs_num++;
+               savedregs_bitmask = (1<<REG_LR);
        }
-#endif
-
-#if !defined(NDEBUG)
-       /* call trace function */
-
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
-
-       /* end of header generation */
 
-       /* create replacement points */
-       REPLACEMENT_POINTS_INIT(cd, jd);
-
-       /* SECTION: ICMD Code Generation */
-       /* for all basic blocks */
-
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-
-               bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
-
-               /* is this basic block reached? */
-
-               if (bptr->flags < BBREACHED)
-                       continue;
-
-               /* branch resolving */
-
-               codegen_resolve_branchrefs(cd, bptr);
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               savedregs_num++;
+               savedregs_bitmask |= (1<<(rd->savintregs[i]));
+       }
 
-               /* handle replacement points */
-               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
+       /* deallocate stackframe for spilled variables */
 
-               /* copy interface registers to their destination */
+       int32_t additional_bytes = (cd->stackframesize * 8 - savedregs_num * 4);
 
-               len = bptr->indepth;
+       if (additional_bytes > 0)
+               M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, additional_bytes / 4);
 
-               MCODECHECK(64+len);
+       /* restore callee saved registers + do return */
 
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-               while (len) {
-                       len--;
-                       var = VAR(bptr->invars[len]);
-                       if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
-                               if (!(var->flags & INMEMORY))
-                                       d= var->vv.regoff;
-                               else
-                                       d=REG_ITMP1;
-                               M_INTMOVE(REG_ITMP1, d);
-                               emit_store(jd, NULL, var, d);   
-                       }
+       if (savedregs_bitmask) {
+               if (!code_is_leafmethod(code)) {
+                       savedregs_bitmask &= ~(1<<REG_LR);
+                       savedregs_bitmask |= (1<<REG_PC);
                }
-               } else {
-#endif
-               while (len) {
-                       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
-
-               /* for all instructions */
-               len = bptr->icount;
-               currentline = 0;
-               for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
+               M_LDMFD(savedregs_bitmask, REG_SP);
+       }
 
-                       /* add line number */
-                       if (iptr->line != currentline) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
+       /* if LR was not on stack, we need to return manually */
 
-                       MCODECHECK(64);   /* an instruction usually needs < 64 words      */
+       if (code_is_leafmethod(code))
+               M_MOV(REG_PC, REG_LR);
+}
 
-               /* the big switch */
-               switch (iptr->opc) {
 
-               case ICMD_NOP:        /* ...  ==> ...                                 */
-               case ICMD_POP:        /* ..., value  ==> ...                          */
-               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
-                       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_ACONST:     /* ... ==> ..., constant                        */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -414,13 +282,6 @@ bool codegen_emit(jitdata *jd)
                        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                       */
 
 #if defined(ENABLE_SOFTFLOAT)
@@ -448,30 +309,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/copy/move operations ************************************/
-
-               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_ALOAD:      /* op1 = local variable                         */
-               case ICMD_FLOAD:
-               case ICMD_LLOAD:
-               case ICMD_DLOAD:
-               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
-               case ICMD_FSTORE:
-               case ICMD_LSTORE:
-               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_INT2BYTE:   /* ..., value  ==> ..., value                   */
@@ -681,8 +518,7 @@ bool codegen_emit(jitdata *jd)
                        M_DSEG_BRANCH(disp);
 
                        /* recompute pv */
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
+                       emit_recompute_pv(cd);
 
                        /* move result into destination register */
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
@@ -710,8 +546,7 @@ bool codegen_emit(jitdata *jd)
                        M_DSEG_BRANCH(disp);
 
                        /* recompute pv */
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
+                       emit_recompute_pv(cd);
 
                        /* move result into destination register */
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
@@ -1150,15 +985,6 @@ bool codegen_emit(jitdata *jd)
 
                /* 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_INTERN(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);
@@ -1370,8 +1196,7 @@ bool codegen_emit(jitdata *jd)
                        M_DSEG_BRANCH(disp);
 
                        /* recompute pv */
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
+                       emit_recompute_pv(cd);
 
                        /* check resturn value of builtin */
                        emit_arraystore_check(cd, iptr);
@@ -1385,26 +1210,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, NULL);
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
-                       }
-                       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->clazz)) {
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                           fi->clazz, 0);
-                               }
-                       }
-
-                       M_DSEG_LOAD(REG_ITMP3, disp);
                        switch (fieldtype) {
                        case TYPE_INT:
 #if defined(ENABLE_SOFTFLOAT)
@@ -1437,58 +1242,6 @@ bool codegen_emit(jitdata *jd)
                        emit_store_dst(jd, iptr, d);
                        break;
 
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, NULL);
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
-                       }
-                       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->clazz)) {
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                           fi->clazz, 0);
-                               }
-                       }
-
-                       M_DSEG_LOAD(REG_ITMP3, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-#if defined(ENABLE_SOFTFLOAT)
-                       case TYPE_FLT:
-#endif
-                       case TYPE_ADR:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                               M_IST_INTERN(s1, REG_ITMP3, 0);
-                               break;
-                       case TYPE_LNG:
-#if defined(ENABLE_SOFTFLOAT)
-                       case TYPE_DBL:
-#endif
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_LST_INTERN(s1, REG_ITMP3, 0);
-                               break;
-#if !defined(ENABLE_SOFTFLOAT)
-                       case TYPE_FLT:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                               M_FST_INTERN(s1, REG_ITMP3, 0);
-                               break;
-                       case TYPE_DBL:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                               M_DST_INTERN(s1, REG_ITMP3, 0);
-                               break;
-#endif
-                       default:
-                               assert(0);
-                       }
-                       break;
-
                case ICMD_GETFIELD:   /* ..., objectref, value  ==> ...               */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP3);
@@ -1636,16 +1389,6 @@ 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_DSEG_LOAD(REG_ITMP3, disp);
                        M_MOV(REG_ITMP2_XPC, REG_PC);
@@ -1654,37 +1397,6 @@ bool codegen_emit(jitdata *jd)
                                            /* of basic block                             */
                        break;
 
-               case ICMD_GOTO:         /* ... ==> ...                                */
-               case ICMD_RET:
-
-                       emit_br(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_JSR:          /* ... ==> ...                                */
-
-                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
-                       break;
-               
-               case ICMD_IFNULL:       /* ..., value ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEQ_IMM(s1, 0);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
-                       break;
-
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-               case ICMD_IFLE:         /* op1 = target JavaVM pc, val.i = constant   */
-               case ICMD_IFGT:
-               case ICMD_IFGE:
-               case ICMD_IFEQ:
-               case ICMD_IFNE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_COMPARE(s1, iptr->sx.val.i);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
-                       break;
-
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -1693,7 +1405,7 @@ bool codegen_emit(jitdata *jd)
                                M_ORR_S(s1, s2, REG_ITMP3);
                        }
                        else {
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
@@ -1713,7 +1425,7 @@ bool codegen_emit(jitdata *jd)
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
@@ -1721,7 +1433,7 @@ bool codegen_emit(jitdata *jd)
                                M_MOVEQ_IMM(1, REG_ITMP1);
 
                                /* low compare: x=x-1(ifLO) */
-                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMP(s2, REG_ITMP3);*/
                                M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
@@ -1747,7 +1459,7 @@ bool codegen_emit(jitdata *jd)
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
@@ -1755,7 +1467,7 @@ bool codegen_emit(jitdata *jd)
                                M_MOVEQ_IMM(1, REG_ITMP1);
 
                                /* low compare: x=x+1(ifHI) */
-                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMP(s2, REG_ITMP3);*/
                                M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
@@ -1777,7 +1489,7 @@ bool codegen_emit(jitdata *jd)
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
@@ -1785,7 +1497,7 @@ bool codegen_emit(jitdata *jd)
                                M_MOVEQ_IMM(1, REG_ITMP1);
 
                                /* low compare: x=x-1(ifLO) */
-                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMP(s2, REG_ITMP3);*/
                                M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
@@ -1817,7 +1529,7 @@ bool codegen_emit(jitdata *jd)
                        else {
 #endif
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
@@ -1825,7 +1537,7 @@ bool codegen_emit(jitdata *jd)
                                M_MOVEQ_IMM(1, REG_ITMP1);
 
                                /* low compare: x=x+1(ifHI) */
-                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMP(s2, REG_ITMP3);*/
                                M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
@@ -1846,7 +1558,7 @@ bool codegen_emit(jitdata *jd)
                                M_ORR_S(s1, s2, REG_ITMP3);
                        }
                        else {
-                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
                                /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s1, REG_ITMP3);*/
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
@@ -1855,28 +1567,6 @@ bool codegen_emit(jitdata *jd)
                        emit_bne(cd, iptr->dst.block);
                        break;
                        
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPNE:
-               case ICMD_IF_ICMPLT:
-               case ICMD_IF_ICMPLE:
-               case ICMD_IF_ICMPGT:
-               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:    /* ..., value, value ==> ...                  */
-               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 ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
@@ -2016,7 +1706,7 @@ bool codegen_emit(jitdata *jd)
 
                        /* range check (index <= high-low) */
                        i = i - l + 1;
-                       M_COMPARE(REG_ITMP1, i-1);
+                       emit_icmp_imm(cd, REG_ITMP1, i-1);
                        emit_bugt(cd, table[0].block);
 
                        /* build jump table top down and use address of lowest entry */
@@ -2035,407 +1725,146 @@ bool codegen_emit(jitdata *jd)
                        M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
                        break;
 
-               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
-                       {
-                       s4 i;
-                       lookup_target_t *lookup;
-
-                       lookup = iptr->dst.lookup;
-
-                       i = iptr->sx.s23.s2.lookupcount;
-                       
-                       /* compare keys */
-                       MCODECHECK((i<<2)+8);
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
-                       while (--i >= 0) {
-                               M_COMPARE(s1, lookup->value);
-                               emit_beq(cd, lookup->target.block);
-                               lookup++;
-                       }
-
-                       /* default branch */
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       }
-                       break;
-
-               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
-
-#if !defined(ENABLE_SOFTFLOAT)
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       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;
-
-               case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
-
-#if !defined(ENABLE_SOFTFLOAT)
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                       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);
-
-#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);
+               case ICMD_BUILTIN:
+                       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);
                        }
-#endif /* ENABLE_VERIFIER */
 
-                       goto ICMD_RETURN_do;
+                       M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
 
-               case ICMD_RETURN:       /* ...  ==> ...                               */
+                       /* generate the actual call */
 
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       ICMD_RETURN_do:
+                       M_MOV(REG_LR, REG_PC);
+                       M_MOV(REG_PC, REG_PV);
 
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
+#if !defined(__SOFTFP__)
+                       /* TODO: this is only a hack, since we use R0/R1 for float
+                          return!  this depends on gcc; it is independent from
+                          our ENABLE_SOFTFLOAT define */
+                       if (d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
+#if 0 && !defined(NDEBUG)
+                               dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
 #endif
-
-#if defined(ENABLE_THREADS)
-                       /* call monitorexit function */
-
-                       if (checksync && code_is_synchronized(code)) {
-                               /* stack offset for monitor argument */
-
-                               s1 = rd->memuse * 8;
-
-                               /* we need to save the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
-                               case ICMD_DRETURN:
-                                       M_STMFD(BITMASK_RESULT, REG_SP);
-                                       s1 += 2 * 4;
-                                       break;
-                               }
-
-                               M_LDR(REG_A0, REG_SP, s1);
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_DSEG_BRANCH(disp);
-
-                               /* we no longer need PV here, no more loading */
-                               /*s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(s1);*/
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
-                               case ICMD_DRETURN:
-                                       M_LDMFD(BITMASK_RESULT, REG_SP);
-                                       break;
+                               /* we cannot use this macro, since it is not defined
+                                  in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
+                                  REG_FRESULT, REG_RESULT_TYPED(d)); */
+                               if (IS_2_WORD_TYPE(d)) {
+                                       DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
+                                       M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
+                               } else {
+                                       DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
+                                       M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
                                }
                        }
 #endif
-
-                       /* deallocate stackframe for spilled variables */
-
-                       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 */
-
-                       if (savedregs_bitmask) {
-                               if (!code_is_leafmethod(code)) {
-                                       savedregs_bitmask &= ~(1<<REG_LR);
-                                       savedregs_bitmask |= (1<<REG_PC);
-                               }
-                               M_LDMFD(savedregs_bitmask, REG_SP);
-                       }
-
-                       /* if LR was not on stack, we need to return manually */
-
-                       if (code_is_leafmethod(code))
-                               M_MOV(REG_PC, REG_LR);
                        break;
 
-               case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
-
-                       bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto ICMD_INVOKE_do;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
-
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+               case ICMD_INVOKESPECIAL:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
+                       /* fall through */
 
+               case ICMD_INVOKESTATIC:
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
-                               md = um->methodref->parseddesc.md;
+                               disp = dseg_add_unique_address(cd, NULL);
+
+                               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);
                        }
 
-               ICMD_INVOKE_do:
-                       /* copy arguments to registers or stack location */
-
-                       s3 = md->paramcount;
-
-                       MCODECHECK((s3 << 1) + 64);
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
+                       M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
 
-                               if (var->flags & PREALLOC) /* argument was precolored? */
-                                       continue;
+                       /* generate the actual call */
 
-                               /* TODO: document me */
-#if !defined(ENABLE_SOFTFLOAT)
-                               if (IS_INT_LNG_TYPE(var->type)) {
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_LNGMOVE(s1, d);
-                                               else
-                                                       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);
-                                               }
-                                       }
-#if !defined(ENABLE_SOFTFLOAT)
-                               }
-                               else {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               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);
-                                               else
-                                                       M_FST(s1, REG_SP, d);
-                                       }
-                               }
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-                       }
-
-                       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_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
-
-                               /* generate the actual call */
-
-                               M_MOV(REG_LR, REG_PC);
-                               M_MOV(REG_PC, REG_PV);
-                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(s1);
-                               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, NULL);
-
-                                       patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
-                                                                               um, disp);
-                               }
-                               else
-                                       disp = dseg_add_address(cd, lm->stubroutine);
-
-                               M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
-
-                               /* generate the actual call */
-
-                               M_MOV(REG_LR, REG_PC);
-                               M_MOV(REG_PC, REG_PV);
-                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(s1);
-                               break;
-
-                       case ICMD_INVOKEVIRTUAL:
-                               if (lm == NULL) {
-                                       int32_t disp = dseg_add_unique_s4(cd, 0);
-                                       patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
-
-                                       // The following instruction MUST NOT change a0 because of the implicit NPE check.
-                                       M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_MOV(REG_LR, REG_PC);
+                       M_MOV(REG_PC, REG_PV);
+                       break;
 
-                                       // Sanity check.
-                                       assert(REG_ITMP1 != REG_METHODPTR);
-                                       assert(REG_ITMP2 == REG_METHODPTR);
+               case ICMD_INVOKEVIRTUAL:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               int32_t disp = dseg_add_unique_s4(cd, 0);
+                               patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
 
-                                       M_DSEG_LOAD(REG_ITMP1, disp);
-                                       M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
+                               // The following instruction MUST NOT change a0 because of the implicit NPE check.
+                               M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
 
-                                       // This must be a load with displacement,
-                                       // otherwise the JIT method address patching does
-                                       // not work anymore (see md_jit_method_patch_address).
-                                       M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
+                               // Sanity check.
+                               assert(REG_ITMP1 != REG_METHODPTR);
+                               assert(REG_ITMP2 == REG_METHODPTR);
 
-                                       // The following instruction MUST NOT change a0 because of the implicit NPE check.
-                                       M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
-                                       M_LDR(REG_PV, REG_METHODPTR, s1);
-                               }
+                               M_DSEG_LOAD(REG_ITMP1, disp);
+                               M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
 
-                               // Generate the actual call.
-                               M_MOV(REG_LR, REG_PC);
-                               M_MOV(REG_PC, REG_PV);
-                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(s1);
-                               break;
+                               // This must be a load with displacement,
+                               // otherwise the JIT method address patching does
+                               // not work anymore (see md_jit_method_patch_address).
+                               M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
 
-                       case ICMD_INVOKEINTERFACE:
-                               if (lm == NULL) {
-                                       int32_t disp  = dseg_add_unique_s4(cd, 0);
-                                       int32_t disp2 = dseg_add_unique_s4(cd, 0);
+                               // The following instruction MUST NOT change a0 because of the implicit NPE check.
+                               M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                               M_LDR(REG_PV, REG_METHODPTR, s1);
+                       }
 
-                                       // XXX We need two displacements.
-                                       assert(disp2 == disp - 4);
-                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
+                       // Generate the actual call.
+                       M_MOV(REG_LR, REG_PC);
+                       M_MOV(REG_PC, REG_PV);
+                       break;
 
-                                       // The following instruction MUST NOT change a0 because of the implicit NPE check.
-                                       M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+               case ICMD_INVOKEINTERFACE:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               int32_t disp  = dseg_add_unique_s4(cd, 0);
+                               int32_t disp2 = dseg_add_unique_s4(cd, 0);
 
-                                       // Sanity check.
-                                       assert(REG_ITMP1 != REG_METHODPTR);
-                                       assert(REG_ITMP2 == REG_METHODPTR);
-                                       assert(REG_ITMP3 != REG_METHODPTR);
+                               // XXX We need two displacements.
+                               assert(disp2 == disp - 4);
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
 
-                                       M_DSEG_LOAD(REG_ITMP1, disp);
-                                       M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
+                               // The following instruction MUST NOT change a0 because of the implicit NPE check.
+                               M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
 
-                                       M_DSEG_LOAD(REG_ITMP3, disp2);
-                                       M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
+                               // Sanity check.
+                               assert(REG_ITMP1 != REG_METHODPTR);
+                               assert(REG_ITMP2 == REG_METHODPTR);
+                               assert(REG_ITMP3 != REG_METHODPTR);
 
-                                       // This must be a load with displacement,
-                                       // otherwise the JIT method address patching does
-                                       // not work anymore (see md_jit_method_patch_address).
-                                       M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
+                               M_DSEG_LOAD(REG_ITMP1, disp);
+                               M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
 
-                                       // The following instruction MUST NOT change a0 because of the implicit NPE check.
-                                       M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
-                                       M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
-                                       M_LDR(REG_PV, REG_METHODPTR, s2);
-                               }
+                               M_DSEG_LOAD(REG_ITMP3, disp2);
+                               M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
 
-                               // Generate the actual call.
-                               M_MOV(REG_LR, REG_PC);
-                               M_MOV(REG_PC, REG_PV);
-                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(s1);
-                               break;
+                               // This must be a load with displacement,
+                               // otherwise the JIT method address patching does
+                               // not work anymore (see md_jit_method_patch_address).
+                               M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
                        }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
 
-                       /* store size of call code in replacement point */
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-
-                       /* store return value */
-
-                       d = md->returntype.type;
-
-#if !defined(__SOFTFP__)
-                       /* TODO: this is only a hack, since we use R0/R1 for float
-                          return!  this depends on gcc; it is independent from
-                          our ENABLE_SOFTFLOAT define */
-                       if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
-#if 0 && !defined(NDEBUG)
-                               dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
-#endif
-                               /* we cannot use this macro, since it is not defined
-                                  in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
-                                  REG_FRESULT, REG_RESULT_TYPED(d)); */
-                               if (IS_2_WORD_TYPE(d)) {
-                                       DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
-                                       M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
-                               } else {
-                                       DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
-                                       M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
-                               }
+                               // The following instruction MUST NOT change a0 because of the implicit NPE check.
+                               M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                               M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
+                               M_LDR(REG_PV, REG_METHODPTR, s2);
                        }
-#endif
 
-                       if (d != TYPE_VOID) {
-#if !defined(ENABLE_SOFTFLOAT)
-                               if (IS_INT_LNG_TYPE(d)) {
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-                                       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);
-                                       }
-
-#if !defined(ENABLE_SOFTFLOAT)
-                               } else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                                       if (IS_2_WORD_TYPE(d))
-                                               M_CAST_L2D(REG_RESULT_PACKED, s1);
-                                       else
-                                               M_CAST_I2F(REG_RESULT, s1);
-                               }
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-
-                               emit_store_dst(jd, iptr, s1);
-                       }
+                       // Generate the actual call.
+                       M_MOV(REG_LR, REG_PC);
+                       M_MOV(REG_PC, REG_PV);
                        break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
@@ -2648,9 +2077,7 @@ bool codegen_emit(jitdata *jd)
                                disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
                                M_DSEG_BRANCH(disp);
 
-                               /* recompute pv */
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_RECOMPUTE_PV(disp);
+                               emit_recompute_pv(cd);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                                M_TST(REG_RESULT, REG_RESULT);
@@ -2929,8 +2356,7 @@ bool codegen_emit(jitdata *jd)
 
                        /* recompute pv */
 
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
+                       emit_recompute_pv(cd);
 
                        /* check for exception before result assignment */
 
@@ -2943,29 +2369,9 @@ bool codegen_emit(jitdata *jd)
                        emit_store_dst(jd, iptr, d);
                        break;
 
-               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
-                       break;
-
                default:
-                       exceptions_throw_internalerror("Unknown ICMD %d during code generation",
-                                                                                  iptr->opc);
-                       return false;
-               } /* the big switch */
-
-               } /* for all instructions */
-
-       } /* for all basic blocks */
-
-       /* generate traps */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
+                       vm_abort("Unknown ICMD %d during code generation", iptr->opc);
+       } /* the big switch */
 }
 
 
@@ -3052,8 +2458,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
 
        /* recompute pv */
 
-       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-       M_RECOMPUTE_PV(s1);
+       emit_recompute_pv(cd);
 
        /* remember class argument */
 
@@ -3135,8 +2540,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        /* TODO: this is only needed because of the tracer ... do we
           really need it? */
 
-       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-       M_RECOMPUTE_PV(s1);
+       emit_recompute_pv(cd);
 
 #if !defined(__SOFTFP__)
        /* TODO: this is only a hack, since we use R0/R1 for float return! */
@@ -3171,8 +2575,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        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);
-       M_RECOMPUTE_PV(s1);
+       emit_recompute_pv(cd);
 
        M_MOV(REG_ITMP1_XPTR, REG_RESULT);
        M_LDMFD(BITMASK_RESULT, REG_SP);
index 0191858b85e41bd36c910966dd224d36d1cc6276..f7fd56ab04b490d4495c40ef69ffd09e60d7ac93 100644 (file)
             codegen_increase(cd); \
     } while (0)
 
+#define ALIGNCODENOP /* empty */
 
 /* TODO: correct this! */
 #define IS_IMM(val) ( ((val) >= 0) && ((val) <= 255) )
 #define IS_OFFSET(off,max) ((s4)(off) <= (max) && (s4)(off) >= -(max))
 
-#if !defined(NDEBUG)
-# define CHECK_INT_REG(r) if ((r)<0 || (r)>15) printf("CHECK_INT_REG: this is not an integer register: %d\n", r); assert((r)>=0 && (r)<=15)
-# define CHECK_FLT_REG(r) if ((r)<0 || (r)>7) printf("CHECK_FLT_REG: this is not an float register: %d\n", r); assert((r)>=0 && (r)<=7)
-# define CHECK_OFFSET(off,max) \
-       if (!IS_OFFSET(off,max)) printf("CHECK_OFFSET: offset out of range: %x (>%x) SEVERE ERROR!!!\n", ((off)<0)?-(off):off, max); \
-       assert(IS_OFFSET(off,max))
-#else
-# define CHECK_INT_REG(r)
-# define CHECK_FLT_REG(r)
-# define CHECK_OFFSET(off,max)
-#endif
+#define CHECK_INT_REG(r)              assert((r)>=0 && (r)<=15)
+#define CHECK_FLT_REG(r)              assert((r)>=0 && (r)<=7)
+#define CHECK_OFFSET(off,max)         assert(IS_OFFSET(off,max))
 
 
 /* branch defines *************************************************************/
@@ -1105,66 +1098,6 @@ do { \
 #endif /* !defined(ENABLE_SOFTFLOAT) */
 
 
-/* M_RECOMPUTE_PV:
-   used to recompute our PV (we use the IP for this) out of the current PC
-   ATTENTION: if you change this, you have to look at other functions as well!
-   Following things depend on it: md_codegen_get_pv_from_pc();
-*/
-#define M_RECOMPUTE_PV(disp) \
-       disp += 8; /* we use PC relative addr.  */ \
-       assert((disp & 0x03) == 0); \
-       assert(disp >= 0 && disp <= 0x03ffffff); \
-       if (disp > 0x0003ffff) { \
-               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9)); \
-               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); \
-               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
-       } else if (disp > 0x000003ff) { \
-               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5)); \
-               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
-       } else { \
-               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); \
-       }
-
-/* M_INTMOVE:
-   generates an integer-move from register a to b.
-   if a and b are the same int-register, no code will be generated.
-*/
-
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_MOV(b, a); \
-    } while (0)
-
-#define M_LNGMOVE(a,b) \
-    do { \
-        if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \
-            assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-        } else { \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-        } \
-    } while (0)
-
-
-/* M_COMPARE:
-   generates the compare part of an if-sequece
-   uses M_CMP or M_CMP_IMM to do the compare
-   ATTENTION: uses REG_ITMP3 as intermediate register
-*/
-#define M_COMPARE(reg, val) \
-       if (IS_IMM(val)) { \
-               M_CMP_IMM(reg, (val)); \
-       } else if(IS_IMM(-(val))) { \
-               M_CMN_IMM(reg, -(val)); \
-       } else { \
-               assert((reg) != REG_ITMP3); \
-               ICONST(REG_ITMP3, (val)); \
-               M_CMP(reg, REG_ITMP3); \
-       }
-
 /* M_LONGBRANCH:
    performs a long branch to an absolute address with return address in LR
    takes up 3 bytes of code space; address is hard-coded into code
@@ -1203,6 +1136,7 @@ do { \
 
 #define M_ALD(a,b,c)                    M_ILD(a,b,c)
 #define M_ALD_INTERN(a,b,c)             M_ILD_INTERN(a,b,c)
+#define M_ALD_DSEG(a,c)                 M_DSEG_LOAD(a,c)
 
 
 #define M_IST(a,b,c)                    M_STR(a,b,c)
@@ -1215,6 +1149,13 @@ do { \
 #define M_AST_INTERN(a,b,c)             M_IST_INTERN(a,b,c)
 
 
+#define M_ACMP(a,b)                     M_CMP(a,b)
+#define M_ICMP(a,b)                     M_CMP(a,b)
+
+
+#define M_TEST(a)                       M_TEQ_IMM(a, 0);
+
+
 #if !defined(ENABLE_SOFTFLOAT)
 
 #define M_FLD(a,b,c)                    M_LDFS(a,b,c)
index 9f11ca5c2fb32d6d1a09ef15bf08ec505fb3ce3f..6a196037c6807b507f9f5cdb8f2061f80f3f865b 100644 (file)
@@ -383,6 +383,27 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       int32_t disp;
+
+       if (IS_IMM(value)) {
+               M_CMP_IMM(reg, value);
+       } else if (IS_IMM(-value)) {
+               M_CMN_IMM(reg, -value);
+       } else {
+               assert(reg != REG_ITMP3);
+               disp = dseg_add_s4(cd, value);
+               M_DSEG_LOAD(REG_ITMP3, disp);
+               M_CMP(reg, REG_ITMP3);
+       }
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -614,6 +635,126 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       // This is used to recompute our PV (we use the IP for this) out
+       // of the current PC.
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       // We use PC relative addressing.
+       disp += 8;
+
+       // Sanity checks.
+       assert((disp & 0x03) == 0);
+       assert(disp >= 0 && disp <= 0x03ffffff);
+
+       // ATTENTION: If you change this, you have to look at other functions
+       // as well! Following things depend on it: md_codegen_get_pv_from_pc();
+       if (disp > 0x0003ffff) {
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9));
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5));
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1));
+       } else if (disp > 0x000003ff) {
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5));
+               M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1));
+       } else {
+               M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1));
+       }
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               M_STMFD(BITMASK_ARGS, REG_SP);
+               syncslot_offset += 4 * 4;
+       }
+# endif
+
+       /* get the correct lock object */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, &m->clazz->object.header);
+               M_DSEG_LOAD(REG_A0, disp);
+       }
+       else {
+               emit_nullpointer_check_force(cd, NULL, REG_A0);
+       }
+
+       M_STR(REG_A0, REG_SP, syncslot_offset);
+       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+       M_DSEG_BRANCH(disp);
+       emit_recompute_pv(cd);
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               M_LDMFD(BITMASK_ARGS, REG_SP);
+# endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+       case TYPE_LNG:
+       case TYPE_FLT: /* XXX TWISTI: is that correct? */
+       case TYPE_DBL:
+               M_STMFD(BITMASK_RESULT, REG_SP);
+               syncslot_offset += 2 * 4;
+               break;
+       }
+
+       M_LDR(REG_A0, REG_SP, syncslot_offset);
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_DSEG_BRANCH(disp);
+
+       /* we no longer need PV here, no more loading */
+       /*emit_recompute_pv(cd);*/
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+       case TYPE_LNG:
+       case TYPE_FLT: /* XXX TWISTI: is that correct? */
+       case TYPE_DBL:
+               M_LDMFD(BITMASK_RESULT, REG_SP);
+               break;
+       }
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
@@ -688,7 +829,7 @@ void emit_verbosecall_enter(jitdata *jd)
        disp = dseg_add_address(cd, m);
        M_DSEG_LOAD(REG_A0, disp);
        M_MOV(REG_A1, REG_SP);
-       M_ADD_IMM(REG_A2, REG_SP, md->paramcount * 8 + 2 * 4 + cd->stackframesize);
+       M_ADD_IMM(REG_A2, REG_SP, md->paramcount * 8 + 2 * 4 + cd->stackframesize * 8);
        M_LONGBRANCH(trace_java_call_enter);
 
        /* restore argument registers */
index 9ce156470118f432c10e3919b93da57270615ef0..9ef90a93e4d418f3da1085a77531827e7852aca3 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On ARM we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 9a940457ebe49b1cbf813f73ffda74807c1a0a51..46530ebae7846fb7eec6d686eefcafeb464b7401 100644 (file)
@@ -73,13 +73,20 @@ struct codeinfo {
        u1            optlevel;             /* optimization level of this code    */
        s4            basicblockcount;      /* number of basic blocks             */
 
-       int32_t       synchronizedoffset;   /* stack offset of synchronized obj.  */
-
        /* machine code */
        u1           *mcode;                /* pointer to machine code            */
        u1           *entrypoint;           /* machine code entry point           */
        s4            mcodelength;          /* length of generated machine code   */
 
+       /* runtime information */
+       int32_t       stackframesize;       /* size of the stackframe in slots    */
+       int32_t       synchronizedoffset;   /* stack offset of synchronized obj.  */
+       uint8_t       savedintcount;        /* number of callee saved int regs    */
+       uint8_t       savedfltcount;        /* number of callee saved flt regs    */
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+       uint8_t       savedadrcount;        /* number of callee saved adr regs    */
+# endif
+
        exceptiontable_t  *exceptiontable;
        LinenumberTable* linenumbertable;
 
@@ -90,9 +97,7 @@ struct codeinfo {
        LockedList*   patchers;
 #endif
 
-       /* replacement */                                   
-       s4            stackframesize;       /* size of the stackframe in slots    */
-
+       /* replacement */
 #if defined(ENABLE_REPLACEMENT)
        rplpoint     *rplpoints;            /* replacement points                 */
        rplalloc     *regalloc;             /* register allocation info           */
@@ -100,11 +105,6 @@ struct codeinfo {
        s4            globalcount;          /* number of global allocations       */
        s4            regalloccount;        /* number of total allocations        */
        s4            memuse;               /* number of arg + local slots        */
-       u1            savedintcount;        /* number of callee saved int regs    */
-       u1            savedfltcount;        /* number of callee saved flt regs    */
-# if defined(HAS_ADDRESS_REGISTER_FILE)
-       u1            savedadrcount;        /* number of callee saved adr regs    */
-# endif
        u1           *savedmcode;           /* saved code under patches           */
 #endif
 
index a6f80b60f3213e2653570fbfdae64fefd24965fa..b9dffac2d126f0a114f264966429fe90e3123258 100644 (file)
@@ -1,7 +1,8 @@
 /* src/vm/jit/codegen-common.cpp - architecture independent code generator stuff
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 #include "vm/exceptions.hpp"
 #include "vm/method.hpp"
 #include "vm/options.h"
+#include "vm/statistics.h"
 #include "vm/string.hpp"
 
-# include "vm/statistics.h"
-
-
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/code.hpp"
 #include "vm/jit/methodtree.h"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trace.hpp"
+
+#include "vm/jit/optimizing/profile.h"
+
 #if defined(ENABLE_SSA)
 # include "vm/jit/optimizing/lsra.h"
 # include "vm/jit/optimizing/ssa.h"
+#elif defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
 #endif
-#include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trace.hpp"
 
 #if defined(ENABLE_INTRP)
 #include "vm/jit/intrp/intrp.h"
 #include <vmlog_cacao.h>
 #endif
 
-#include "show.hpp"
-
 
 /* codegen_init ****************************************************************
 
@@ -288,7 +291,7 @@ bool codegen_generate(jitdata *jd)
                                return false;
                }
                else {
-                       vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
+                       os::abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
                }
 
 #if !defined(NDEBUG)
@@ -544,21 +547,20 @@ void codegen_set_replacement_point(codegendata *cd)
 
 void codegen_finish(jitdata *jd)
 {
-       codeinfo    *code;
-       codegendata *cd;
-       s4           mcodelen;
+       s4       mcodelen;
 #if defined(ENABLE_INTRP)
-       s4           ncodelen;
+       s4       ncodelen;
 #endif
-       s4           alignedmcodelen;
-       jumpref     *jr;
-       u1          *epoint;
-       s4           alignedlen;
+       s4       alignedmcodelen;
+       jumpref *jr;
+       u1      *epoint;
+       s4       alignedlen;
 
-       /* get required compiler data */
+       /* Get required compiler data. */
 
-       code = jd->code;
-       cd   = jd->cd;
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
        /* prevent compiler warning */
 
@@ -641,6 +643,16 @@ void codegen_finish(jitdata *jd)
        }
 #endif
 
+       /* Fill runtime information about generated code. */
+
+       code->stackframesize     = cd->stackframesize;
+       code->synchronizedoffset = rd->memuse * 8;
+       code->savedintcount      = INT_SAV_CNT - rd->savintreguse;
+       code->savedfltcount      = FLT_SAV_CNT - rd->savfltreguse;
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       code->savedadrcount      = ADR_SAV_CNT - rd->savadrreguse;
+#endif
+
        /* Create the exception table. */
 
        exceptiontable_create(jd);
@@ -723,6 +735,7 @@ java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
 {
        stackframeinfo_t *sfi;
        localref_table   *lrt;
+       codeinfo         *code;
        methodinfo       *m;
        int32_t           framesize;
 
@@ -733,16 +746,17 @@ java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
 
        STATISTICS(count_calls_java_to_native++);
 
-       /* Get the methodinfo. */
+       // Get information from method header.
+       code = code_get_codeinfo_for_pv(pv);
+       assert(code != NULL);
 
-       m = code_get_methodinfo_for_pv(pv);
+       framesize = md_stacktrace_get_framesize(code);
+       assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
 
+       // Get the methodinfo.
+       m = code_get_methodinfo_for_pv(pv);
        assert(m);
 
-       framesize = *((int32_t *) (pv + FrameSize));
-
-       assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
-
        /* calculate needed values */
 
 #if defined(__ALPHA__) || defined(__ARM__)
@@ -783,7 +797,7 @@ java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
 #else
        /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
        /* XXX maybe we need to pass the RA as argument there */
-       vm_abort("codegen_start_native_call: unsupported architecture");
+       os::abort("codegen_start_native_call: unsupported architecture");
 #endif
 
        /* get data structures from stack */
@@ -850,18 +864,15 @@ java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
        uint8_t  *datasp;
        uint64_t *ret_regs;
 
-       /* get information from method header */
-
+       // Get information from method header.
        code = code_get_codeinfo_for_pv(pv);
+       assert(code != NULL);
 
-       framesize = *((int32_t *) (pv + FrameSize));
-
-       assert(code);
-
-       /* get the methodinfo */
+       framesize = md_stacktrace_get_framesize(code);
 
+       // Get the methodinfo.
        m = code->m;
-       assert(m);
+       assert(m != NULL);
 
        /* calculate needed values */
 
@@ -895,7 +906,7 @@ java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
        datasp   = sp + framesize;
        ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
 #else
-       vm_abort("codegen_finish_native_call: unsupported architecture");
+       os::abort("codegen_finish_native_call: unsupported architecture");
 #endif
 
        /* get data structures from stack */
@@ -950,7 +961,7 @@ java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
    register, this register will be returned.  Otherwise (when v is
    spilled) this function returns tempregnum.  If not already done,
    regoff and flags are set in the stack location.
-       
+
 *******************************************************************************/
 
 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
@@ -970,7 +981,7 @@ s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
    register, this register will be returned.  Otherwise (when it is
    spilled) this function returns tempregnum.  If not already done,
    regoff and flags are set in the stack location.
-       
+
 *******************************************************************************/
 
 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
@@ -979,6 +990,1182 @@ s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
 }
 
 
+/**
+ * Generates machine code.
+ */
+bool codegen_emit(jitdata *jd)
+{
+       varinfo*            var;
+       builtintable_entry* bte;
+       methoddesc*         md;
+       int32_t             s1, s2, /*s3,*/ d;
+       int32_t             fieldtype;
+       int32_t             disp;
+       int                 i;
+
+       // Get required compiler data.
+       //methodinfo*   m    = jd->m;
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
+#if defined(ENABLE_SSA)
+       lsradata*     ls   = jd->ls;
+       bool last_cmd_was_goto = false;
+#endif
+
+       // Space to save used callee saved registers.
+       int32_t savedregs_num = 0;
+       savedregs_num += (INT_SAV_CNT - rd->savintreguse);
+       savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
+#ifdef HAS_ADDRESS_REGISTER_FILE
+       savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
+#endif
+
+       // Calculate size of stackframe.
+       cd->stackframesize = rd->memuse + savedregs_num;
+
+       // Space to save the return address.
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
+       if (!code_is_leafmethod(code))
+# endif
+               cd->stackframesize += 1;
+#endif
+
+       // Space to save argument of monitor_enter.
+#if defined(ENABLE_THREADS)
+       if (checksync && code_is_synchronized(code))
+# if STACKFRAME_SYNC_NEEDS_TWO_SLOTS
+               /* On some architectures the stack position for the argument can
+                  not be shared with place to save the return register values to
+                  survive monitor_exit since both values reside in the same register. */
+               cd->stackframesize += 2;
+# else
+               cd->stackframesize += 1;
+# endif
+#endif
+
+       // Keep stack of non-leaf functions 16-byte aligned for calls into
+       // native code.
+       if (!code_is_leafmethod(code) || JITDATA_HAS_FLAG_VERBOSECALL(jd))
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+               ALIGN_ODD(cd->stackframesize);
+#else
+               ALIGN_EVEN(cd->stackframesize);
+#endif
+
+#if defined(SPECIALMEMUSE)
+       // On architectures having a linkage area, we can get rid of the whole
+       // stackframe in leaf functions without saved registers.
+       if (code_is_leafmethod(code) && (cd->stackframesize == LA_SIZE_IN_POINTERS))
+               cd->stackframesize = 0;
+#endif
+
+       /*
+        * SECTION 1: Method header generation.
+        */
+
+       // The method header was reduced to the bare minimum of one pointer
+       // to the codeinfo structure, which in turn contains all runtime
+       // information. However this section together with the methodheader.h
+       // file will be kept alive for historical reasons. It might come in
+       // handy at some point.
+
+       (void) dseg_add_unique_address(cd, code);   ///< CodeinfoPointer
+
+       // XXX, REMOVEME: We still need it for exception handling in assembler.
+       // XXX ARM, M68K: (void) dseg_add_unique_s4(cd, cd->stackframesize);
+#if defined(__I386__)
+       int align_off = (cd->stackframesize != 0) ? 4 : 0;
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8 + align_off); /* FrameSize       */
+#else
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
+#endif
+       // XXX M68K: We use the IntSave as a split field for the adr now
+       //           (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
+       (void) dseg_add_unique_s4(cd, code_is_leafmethod(code) ? 1 : 0);
+       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+
+       /*
+        * SECTION 2: Method prolog generation.
+        */
+
+#if defined(ENABLE_PROFILING)
+       // Generate method profiling code.
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+
+               // Count method frequency.
+               emit_profile_method(cd, code);
+
+# if defined(__X86_64__)
+               // Start CPU cycle counting.
+               emit_profile_cycle_start();
+# endif
+       }
+#endif
+
+       // Emit code for the method prolog.
+       codegen_emit_prolog(jd);
+
+#if defined(ENABLE_THREADS)
+       // Emit code to call monitorenter function.
+       if (checksync && code_is_synchronized(code))
+               emit_monitor_enter(jd, rd->memuse * 8);
+#endif
+
+#if !defined(NDEBUG)
+       // Call trace function.
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               emit_verbosecall_enter(jd);
+#endif
+
+#if defined(ENABLE_SSA)
+       // With SSA the header is basicblock 0, insert phi moves if necessary.
+       if (ls != NULL)
+               codegen_emit_phi_moves(jd, ls->basicblocks[0]);
+#endif
+
+       // Create replacement points.
+       REPLACEMENT_POINTS_INIT(cd, jd);
+
+       /*
+        * SECTION 3: ICMD code generation.
+        */
+
+       // Walk through all basic blocks.
+       for (basicblock* bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+
+               bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
+
+               // Is this basic block reached?
+               if (bptr->flags < BBREACHED)
+                       continue;
+
+               // Branch resolving.
+               codegen_resolve_branchrefs(cd, bptr);
+
+               // Handle replacement points.
+               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
+
+#if defined(ENABLE_REPLACEMENT) && defined(__I386__)
+               // Generate countdown trap code.
+               methodinfo* m = jd->m;
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+                       if (cd->replacementpoint[-1].flags & RPLPOINT_FLAG_COUNTDOWN) {
+                               MCODECHECK(32);
+                               emit_trap_countdown(cd, &(m->hitcountdown));
+                       }
+               }
+#endif
+
+#if defined(ENABLE_PROFILING)
+               // Generate basicblock profiling code.
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+
+                       // Count basicblock frequency.
+                       emit_profile_basicblock(cd, code, bptr);
+
+# if defined(__X86_64__)
+                       // If this is an exception handler, start profiling again.
+                       if (bptr->type == BBTYPE_EXH)
+                               emit_profile_cycle_start();
+# endif
+               }
+#endif
+
+               // Copy interface registers to their destination.
+               int32_t indepth = bptr->indepth;
+               // XXX Check if this is true for all archs.
+               MCODECHECK(64+indepth);   // All
+               MCODECHECK(128+indepth);  // PPC64
+               MCODECHECK(512);          // I386, X86_64, S390
+#if defined(ENABLE_SSA)
+               // XXX Check if this is correct and add a propper comment!
+               if (ls != NULL) {
+                       last_cmd_was_goto = false;
+               } else {
+#elif defined(ENABLE_LSRA)
+               if (opt_lsra) {
+                       while (indepth > 0) {
+                               indepth--;
+                               var = VAR(bptr->invars[indepth]);
+                               if ((indepth == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
+                                       if (!IS_INMEMORY(src->flags))
+                                               d = var->vv.regoff;
+                                       else
+                                               d = REG_ITMP1_XPTR;
+                                       // XXX M68K: Actually this is M_ADRMOVE(REG_ATMP1_XPTR, d);
+                                       // XXX Sparc64: Here we use REG_ITMP2_XPTR, fix this!
+                                       // XXX S390: Here we use REG_ITMP3_XPTR, fix this!
+                                       emit_imove(cd, REG_ITMP1_XPTR, d);
+                                       emit_store(jd, NULL, var, d);
+                               }
+                       }
+               } else {
+#endif
+                       while (indepth > 0) {
+                               indepth--;
+                               var = VAR(bptr->invars[indepth]);
+                               if ((indepth == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
+                                       d = codegen_reg_of_var(0, var, REG_ITMP1_XPTR);
+                                       // XXX M68K: Actually this is M_ADRMOVE(REG_ATMP1_XPTR, d);
+                                       // XXX Sparc64: Here we use REG_ITMP2_XPTR, fix this!
+                                       // XXX S390: Here we use REG_ITMP3_XPTR, fix this!
+                                       emit_imove(cd, REG_ITMP1_XPTR, d);
+                                       emit_store(jd, NULL, var, d);
+                               }
+                               else {
+                                       assert((var->flags & INOUT));
+                               }
+                       }
+#if defined(ENABLE_SSA) || defined(ENABLE_LSRA)
+               }
+#endif
+
+               // Walk through all instructions.
+               int32_t len = bptr->icount;
+               uint16_t currentline = 0;
+               for (instruction* iptr = bptr->iinstr; len > 0; len--, iptr++) {
+
+                       // Add line number.
+                       if (iptr->line != currentline) {
+                               linenumbertable_list_entry_add(cd, iptr->line);
+                               currentline = iptr->line;
+                       }
+
+                       // An instruction usually needs < 64 words.
+                       // XXX Check if this is true for all archs.
+                       MCODECHECK(64);    // All
+                       MCODECHECK(128);   // PPC64
+                       MCODECHECK(1024);  // I386, X86_64, M68K, S390      /* 1kB should be enough */
+
+                       // The big switch.
+                       switch (iptr->opc) {
+
+                       case ICMD_NOP:        /* ...  ==> ...                             */
+                       case ICMD_POP:        /* ..., value  ==> ...                      */
+                       case ICMD_POP2:       /* ..., value, value  ==> ...               */
+                               break;
+
+                       case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref       */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               emit_nullpointer_check(cd, iptr, s1);
+                               break;
+
+#if defined(ENABLE_SSA)
+                       case ICMD_GETEXCEPTION:
+
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               emit_imove(cd, REG_ITMP1, d);
+                               emit_store_dst(jd, iptr, d);
+                               break;
+#endif
+
+                       /* inline operations **********************************************/
+
+                       case ICMD_INLINE_START:
+
+                               REPLACEMENT_POINT_INLINE_START(cd, iptr);
+                               break;
+
+                       case ICMD_INLINE_BODY:
+
+                               REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
+                               linenumbertable_list_entry_add_inline_start(cd, iptr);
+                               linenumbertable_list_entry_add(cd, iptr->line);
+                               break;
+
+                       case ICMD_INLINE_END:
+
+                               linenumbertable_list_entry_add_inline_end(cd, iptr);
+                               linenumbertable_list_entry_add(cd, iptr->line);
+                               break;
+
+
+                       /* constant operations ********************************************/
+
+                       case ICMD_ICONST:     /* ...  ==> ..., constant                   */
+
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               ICONST(d, iptr->sx.val.i);
+                               emit_store_dst(jd, iptr, d);
+                               break;
+
+                       case ICMD_LCONST:     /* ...  ==> ..., constant                   */
+
+                               d = codegen_reg_of_dst(jd, iptr, REG_LTMP12);
+                               LCONST(d, iptr->sx.val.l);
+                               emit_store_dst(jd, iptr, d);
+                               break;
+
+
+                       /* load/store/copy/move operations ********************************/
+
+                       case ICMD_COPY:
+                       case ICMD_MOVE:
+                       case ICMD_ILOAD:      /* ...  ==> ..., content of local variable  */
+                       case ICMD_LLOAD:      /* s1 = local variable                      */
+                       case ICMD_FLOAD:
+                       case ICMD_DLOAD:
+                       case ICMD_ALOAD:
+                       case ICMD_ISTORE:     /* ..., value  ==> ...                      */
+                       case ICMD_LSTORE:
+                       case ICMD_FSTORE:
+                       case ICMD_DSTORE:
+
+                               emit_copy(jd, iptr);
+                               break;
+
+                       case ICMD_ASTORE:
+
+                               if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+                                       emit_copy(jd, iptr);
+                               break;
+
+
+                       /* integer operations *********************************************/
+
+                       case ICMD_FCONST:     /* ...  ==> ..., constant                   */
+                       case ICMD_DCONST:     /* ...  ==> ..., constant                   */
+                       case ICMD_ACONST:     /* ...  ==> ..., constant                   */
+                       case ICMD_INEG:       /* ..., value  ==> ..., - value             */
+                       case ICMD_LNEG:       /* ..., value  ==> ..., - value             */
+                       case ICMD_I2L:        /* ..., value  ==> ..., value               */
+                       case ICMD_L2I:        /* ..., value  ==> ..., value               */
+                       case ICMD_INT2BYTE:   /* ..., value  ==> ..., value               */
+                       case ICMD_INT2CHAR:   /* ..., value  ==> ..., value               */
+                       case ICMD_INT2SHORT:  /* ..., value  ==> ..., value               */
+                       case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2    */
+                       case ICMD_IINC:
+                       case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2    */
+                       case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2    */
+                       case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2    */
+                       case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2    */
+                       case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2    */
+                       case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2    */
+                       case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2    */
+                       case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2    */
+                       case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2    */
+                       case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value >> constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2   */
+                       case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2   */
+                       case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2  */
+                       case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant  */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2   */
+                       case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2   */
+                       case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant   */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2  */
+                       case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant  */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2    */
+                       case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2    */
+                       case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2    */
+                       case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2    */
+                       case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant    */
+                                             /* sx.val.l = constant                      */
+                       case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2    */
+                       case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant    */
+                                             /* sx.val.i = constant                      */
+                       case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2    */
+                       case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant    */
+                                             /* sx.val.l = constant                      */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+
+                       /* floating operations ********************************************/
+
+#if !defined(ENABLE_SOFTFLOAT)
+                       case ICMD_FNEG:       /* ..., value  ==> ..., - value             */
+                       case ICMD_DNEG:
+                       case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2    */
+                       case ICMD_DADD:
+                       case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2    */
+                       case ICMD_DSUB:
+                       case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2    */
+                       case ICMD_DMUL:
+                       case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2    */
+                       case ICMD_DDIV:
+                       case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+                       case ICMD_DREM:
+                       case ICMD_I2F:        /* ..., value  ==> ..., (float) value       */
+                       case ICMD_I2D:        /* ..., value  ==> ..., (double) value      */
+                       case ICMD_L2F:        /* ..., value  ==> ..., (float) value       */
+                       case ICMD_L2D:        /* ..., value  ==> ..., (double) value      */
+                       case ICMD_F2I:        /* ..., value  ==> ..., (int) value         */
+                       case ICMD_D2I:
+                       case ICMD_F2L:        /* ..., value  ==> ..., (long) value        */
+                       case ICMD_D2L:
+                       case ICMD_F2D:        /* ..., value  ==> ..., (double) value      */
+                       case ICMD_D2F:        /* ..., value  ==> ..., (float) value       */
+                       case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2 */
+                       case ICMD_DCMPL:      /* == => 0, < => 1, > => -1                 */
+                       case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2 */
+                       case ICMD_DCMPG:      /* == => 0, < => 1, > => -1                 */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+#endif /* !defined(ENABLE_SOFTFLOAT) */
+
+
+                       /* 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 */
+                               // XXX PPC64: Here we had an explicit null-pointer check
+                               //     which I think was obsolete, please confirm. Otherwise:
+                               // emit_nullpointer_check(cd, iptr, s1);
+                               M_ILD(d, s1, OFFSET(java_array_t, size));
+                               emit_store_dst(jd, iptr, d);
+                               break;
+
+                       case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value     */
+                       case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...     */
+                       case ICMD_BASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_IASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_LASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_FASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_DASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_AASTORECONST:   /* ..., arrayref, index  ==> ...        */
+                       case ICMD_GETFIELD:   /* ...  ==> ..., value                      */
+                       case ICMD_PUTFIELD:   /* ..., value  ==> ...                      */
+                       case ICMD_PUTFIELDCONST:  /* ..., objectref  ==> ...              */
+                                                 /* val = value (in current instruction) */
+                       case ICMD_PUTSTATICCONST: /* ...  ==> ...                         */
+                                                 /* val = value (in current instruction) */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+                       case ICMD_GETSTATIC:  /* ...  ==> ..., value                      */
+
+#if defined(__I386__)
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+#else
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       unresolved_field* uf = iptr->sx.s23.s3.uf;
+                                       fieldtype = uf->fieldref->parseddesc.fd->type;
+                                       disp      = dseg_add_unique_address(cd, 0);
+
+                                       patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+                               }
+                               else {
+                                       fieldinfo* 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->clazz)) {
+                                               PROFILE_CYCLE_STOP;
+                                               patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
+                                               PROFILE_CYCLE_START;
+                                       }
+                               }
+
+                               // XXX X86_64: Here We had this:
+                               /* This approach is much faster than moving the field
+                                  address inline into a register. */
+
+                               // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
+                               M_ALD_DSEG(REG_ITMP1, disp);
+
+                               switch (fieldtype) {
+                               case TYPE_ADR:
+                                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                                       M_ALD(d, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_INT:
+                                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                                       M_ILD(d, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_LNG:
+                                       d = codegen_reg_of_dst(jd, iptr, REG_LTMP23);
+                                       M_LLD(d, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_FLT:
+                                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                                       M_FLD(d, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_DBL:
+                                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                                       M_DLD(d, REG_ITMP1, 0);
+                                       break;
+                               }
+                               emit_store_dst(jd, iptr, d);
+#endif
+                               break;
+
+                       case ICMD_PUTSTATIC:  /* ..., value  ==> ...                      */
+
+#if defined(__I386__)
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+#else
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       unresolved_field* uf = iptr->sx.s23.s3.uf;
+                                       fieldtype = uf->fieldref->parseddesc.fd->type;
+                                       disp      = dseg_add_unique_address(cd, 0);
+
+                                       patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+                               }
+                               else {
+                                       fieldinfo* 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->clazz)) {
+                                               PROFILE_CYCLE_STOP;
+                                               patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
+                                               PROFILE_CYCLE_START;
+                                       }
+                               }
+
+                               // XXX X86_64: Here We had this:
+                               /* This approach is much faster than moving the field
+                                  address inline into a register. */
+
+                               // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
+                               M_ALD_DSEG(REG_ITMP1, disp);
+
+                               switch (fieldtype) {
+                               case TYPE_ADR:
+                                       s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                                       M_AST(s1, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_INT:
+                                       s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                                       M_IST(s1, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_LNG:
+                                       s1 = emit_load_s1(jd, iptr, REG_LTMP23);
+                                       M_LST(s1, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_FLT:
+                                       s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                                       M_FST(s1, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_DBL:
+                                       s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                                       M_DST(s1, REG_ITMP1, 0);
+                                       break;
+                               }
+#endif
+                               break;
+
+                       /* branch operations **********************************************/
+
+                       case ICMD_ATHROW:     /* ..., objectref ==> ... (, objectref)     */
+
+                               // We might leave this method, stop profiling.
+                               PROFILE_CYCLE_STOP;
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               // XXX M68K: Actually this is M_ADRMOVE(s1, REG_ATMP1_XPTR);
+                               // XXX Sparc64: We use REG_ITMP2_XPTR here, fix me!
+                               emit_imove(cd, 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 */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               ALIGNCODENOP;
+                               break;
+
+                       case ICMD_GOTO:       /* ... ==> ...                              */
+                       case ICMD_RET:        /* ... ==> ...                              */
+
+#if defined(ENABLE_SSA)
+                               // In case of a goto, phimoves have to be inserted
+                               // before the jump.
+                               if (ls != NULL) {
+                                       last_cmd_was_goto = true;
+                                       codegen_emit_phi_moves(jd, bptr);
+                               }
+#endif
+                               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 ==> ...                       */
+                       case ICMD_IFNONNULL:
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+                               emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
+#elif SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+                               M_TEST(s1);
+                               emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
+#else
+# error Unable to generate code for this configuration!
+#endif
+                               break;
+
+                       case ICMD_IFEQ:       /* ..., value ==> ...                       */
+                       case ICMD_IFNE:
+                       case ICMD_IFLT:
+                       case ICMD_IFLE:
+                       case ICMD_IFGT:
+                       case ICMD_IFGE:
+
+                               // XXX Sparc64: int compares must not branch on the
+                               // register directly. Reason is, that register content is
+                               // not 32-bit clean. Fix this!
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+                               if (iptr->sx.val.i == 0) {
+                                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, s1, BRANCH_OPT_NONE);
+                               } else {
+                                       // Generate architecture specific instructions.
+                                       codegen_emit_instruction(jd, iptr);
+                               }
+#elif SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               emit_icmp_imm(cd, s1, iptr->sx.val.i);
+                               emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
+#else
+# error Unable to generate code for this configuration!
+#endif
+                               break;
+
+                       case ICMD_IF_LEQ:     /* ..., value ==> ...                       */
+                       case ICMD_IF_LNE:
+                       case ICMD_IF_LLT:
+                       case ICMD_IF_LGE:
+                       case ICMD_IF_LGT:
+                       case ICMD_IF_LLE:
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+                       case ICMD_IF_ACMPEQ:  /* ..., value, value ==> ...                */
+                       case ICMD_IF_ACMPNE:  /* op1 = target JavaVM pc                   */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+                               switch (iptr->opc) {
+                                       case ICMD_IF_ACMPEQ:
+                                               emit_beq(cd, iptr->dst.block, s1, s2);
+                                               break;
+                                       case ICMD_IF_ACMPNE:
+                                               emit_bne(cd, iptr->dst.block, s1, s2);
+                                               break;
+                               }
+#elif SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+                               M_ACMP(s1, s2);
+                               emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
+#elif SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+                               M_CMPEQ(s1, s2, REG_ITMP1);
+                               switch (iptr->opc) {
+                                       case ICMD_IF_ACMPEQ:
+                                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                                               break;
+                                       case ICMD_IF_ACMPNE:
+                                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                                               break;
+                               }
+#else
+# error Unable to generate code for this configuration!
+#endif
+                               break;
+
+                       case ICMD_IF_ICMPEQ:  /* ..., value, value ==> ...                */
+                       case ICMD_IF_ICMPNE:  /* op1 = target JavaVM pc                   */
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                               switch (iptr->opc) {
+                                       case ICMD_IF_ICMPEQ:
+                                               emit_beq(cd, iptr->dst.block, s1, s2);
+                                               break;
+                                       case ICMD_IF_ICMPNE:
+                                               emit_bne(cd, iptr->dst.block, s1, s2);
+                                               break;
+                               }
+                               break;
+#else
+                               /* fall-through */
+#endif
+
+                       case ICMD_IF_ICMPLT:  /* ..., value, value ==> ...                */
+                       case ICMD_IF_ICMPGT:  /* op1 = target JavaVM pc                   */
+                       case ICMD_IF_ICMPLE:
+                       case ICMD_IF_ICMPGE:
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+# if defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
+                               // XXX Fix this soon!!!
+                               M_ICMP(s2, s1);
+# else
+                               M_ICMP(s1, s2);
+# endif
+                               emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+#elif SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+#else
+# error Unable to generate code for this configuration!
+#endif
+                               break;
+
+                       case ICMD_IF_LCMPEQ:  /* ..., value, value ==> ...                */
+                       case ICMD_IF_LCMPNE:  /* op1 = target JavaVM pc                   */
+                       case ICMD_IF_LCMPLT:
+                       case ICMD_IF_LCMPGT:
+                       case ICMD_IF_LCMPLE:
+                       case ICMD_IF_LCMPGE:
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+                       case ICMD_RETURN:     /* ...  ==> ...                             */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               goto nowperformreturn;
+
+                       case ICMD_ARETURN:    /* ..., retvalue ==> ...                    */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                               // XXX M68K: This should actually be M_ADR2INTMOVE(s1, REG_RESULT);
+                               // XXX Sparc64: Here this should be REG_RESULT_CALLEE!
+                               emit_imove(cd, s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       PROFILE_CYCLE_STOP;
+                                       unresolved_class *uc = iptr->sx.s23.s2.uc;
+                                       patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
+                                       PROFILE_CYCLE_START;
+                               }
+#endif /* ENABLE_VERIFIER */
+                               goto nowperformreturn;
+
+                       case ICMD_IRETURN:    /* ..., retvalue ==> ...                    */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                               // XXX Sparc64: Here this should be REG_RESULT_CALLEE!
+                               emit_imove(cd, s1, REG_RESULT);
+                               goto nowperformreturn;
+
+                       case ICMD_LRETURN:    /* ..., retvalue ==> ...                    */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               s1 = emit_load_s1(jd, iptr, REG_LRESULT);
+                               // XXX Sparc64: Here this should be REG_RESULT_CALLEE!
+                               emit_lmove(cd, s1, REG_LRESULT);
+                               goto nowperformreturn;
+
+                       case ICMD_FRETURN:    /* ..., retvalue ==> ...                    */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               s1 = emit_load_s1(jd, iptr, REG_FRESULT);
+                               // XXX ARM: Here this was M_CAST_F2I(s1, REG_RESULT);
+                               emit_fmove(cd, s1, REG_FRESULT);
+                               goto nowperformreturn;
+
+                       case ICMD_DRETURN:    /* ..., retvalue ==> ...                    */
+
+                               REPLACEMENT_POINT_RETURN(cd, iptr);
+                               s1 = emit_load_s1(jd, iptr, REG_FRESULT);
+                               // XXX ARM: Here this was M_CAST_D2L(s1, REG_RESULT_PACKED);
+                               emit_dmove(cd, s1, REG_FRESULT);
+                               goto nowperformreturn;
+
+nowperformreturn:
+#if !defined(NDEBUG)
+                               // Call trace function.
+                               if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+                                       emit_verbosecall_exit(jd);
+#endif
+
+#if defined(ENABLE_THREADS)
+                               // Emit code to call monitorexit function.
+                               if (checksync && code_is_synchronized(code)) {
+                                       emit_monitor_exit(jd, rd->memuse * 8);
+                               }
+#endif
+
+                               // Generate method profiling code.
+                               PROFILE_CYCLE_STOP;
+
+                               // Emit code for the method epilog.
+                               codegen_emit_epilog(jd);
+                               ALIGNCODENOP;
+                               break;
+
+                       case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...        */
+
+                               REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
+
+                               bte = iptr->sx.s23.s3.bte;
+                               md  = bte->md;
+
+#if defined(ENABLE_ESCAPE_REASON) && defined(__I386__)
+                               if (bte->fp == BUILTIN_escape_reason_new) {
+                                       void set_escape_reasons(void *);
+                                       M_ASUB_IMM(8, REG_SP);
+                                       M_MOV_IMM(iptr->escape_reasons, REG_ITMP1);
+                                       M_AST(EDX, REG_SP, 4);
+                                       M_AST(REG_ITMP1, REG_SP, 0);
+                                       M_MOV_IMM(set_escape_reasons, REG_ITMP1);
+                                       M_CALL(REG_ITMP1);
+                                       M_ALD(EDX, REG_SP, 4);
+                                       M_AADD_IMM(8, REG_SP);
+                               }
+#endif
+
+                               goto gen_method;
+
+                       case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...        */
+                       case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
+                       case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+                       case ICMD_INVOKEINTERFACE:
+
+                               REPLACEMENT_POINT_INVOKE(cd, iptr);
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       unresolved_method* um = iptr->sx.s23.s3.um;
+                                       md = um->methodref->parseddesc.md;
+                               }
+                               else {
+                                       methodinfo* lm = iptr->sx.s23.s3.fmiref->p.method;
+                                       md = lm->parseddesc;
+                               }
+
+gen_method:
+                               i = md->paramcount;
+
+                               // XXX Check this again!
+                               MCODECHECK((i << 1) + 64);   // PPC
+
+                               // Copy arguments to registers or stack location.
+                               for (i = i - 1; i >= 0; i--) {
+                                       var = VAR(iptr->sx.s23.s2.args[i]);
+                                       d   = md->params[i].regoff;
+
+                                       // Already pre-allocated?
+                                       if (var->flags & PREALLOC)
+                                               continue;
+
+                                       if (!md->params[i].inmemory) {
+                                               assert(ARG_CNT > 0);
+                                               s1 = emit_load(jd, iptr, var, d);
+
+                                               switch (var->type) {
+                                               case TYPE_ADR:
+                                               case TYPE_INT:
+                                                       assert(INT_ARG_CNT > 0);
+                                                       emit_imove(cd, s1, d);
+                                                       break;
+
+#if 0 //XXX For ARM:
+if (!md->params[s3].inmemory) {
+       s1 = emit_load(jd, iptr, var, REG_FTMP1);
+       if (IS_2_WORD_TYPE(var->type))
+               M_CAST_D2L(s1, d);
+       else
+               M_CAST_F2I(s1, d);
+}
+#endif //XXX End of ARM!
+
+                                               case TYPE_LNG:
+                                                       emit_lmove(cd, s1, d);
+                                                       break;
+
+                                               case TYPE_FLT:
+                                                       emit_fmove(cd, s1, d);
+                                                       break;
+
+                                               case TYPE_DBL:
+                                                       emit_dmove(cd, s1, d);
+                                                       break;
+                                               }
+                                       }
+                                       else {
+                                               switch (var->type) {
+                                               case TYPE_ADR:
+                                                       s1 = emit_load(jd, iptr, var, REG_ITMP1);
+                                                       // XXX M68K: This should actually be like this:
+                                                       //     s1 = emit_load(jd, iptr, var, REG_ATMP1);
+                                                       // XXX Sparc64: Here this actually was:
+                                                       //     M_STX(s1, REG_SP, JITSTACK + d);
+                                                       M_AST(s1, REG_SP, d);
+                                                       break;
+
+                                               case TYPE_INT:
+#if SIZEOF_VOID_P == 4
+                                                       s1 = emit_load(jd, iptr, var, REG_ITMP1);
+                                                       M_IST(s1, REG_SP, d);
+                                                       break;
+#else
+                                                       /* fall-through */
+#endif
+
+                                               case TYPE_LNG:
+                                                       s1 = emit_load(jd, iptr, var, REG_LTMP12);
+                                                       // XXX Sparc64: Here this actually was:
+                                                       //     M_STX(s1, REG_SP, JITSTACK + d);
+                                                       M_LST(s1, REG_SP, d);
+                                                       break;
+
+                                               case TYPE_FLT:
+#if SIZEOF_VOID_P == 4
+                                                       s1 = emit_load(jd, iptr, var, REG_FTMP1);
+                                                       M_FST(s1, REG_SP, d);
+                                                       break;
+#else
+                                                       /* fall-through */
+#endif
+
+                                               case TYPE_DBL:
+                                                       s1 = emit_load(jd, iptr, var, REG_FTMP1);
+                                                       // XXX Sparc64: Here this actually was:
+                                                       //     M_DST(s1, REG_SP, JITSTACK + d);
+                                                       M_DST(s1, REG_SP, d);
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               // Generate method profiling code.
+                               PROFILE_CYCLE_STOP;
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+
+                               // Generate method profiling code.
+                               PROFILE_CYCLE_START;
+
+                               // Store size of call code in replacement point.
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
+
+                               // Recompute the procedure vector (PV).
+                               emit_recompute_pv(cd);
+
+                               // Store return value.
+#if defined(ENABLE_SSA)
+                               if ((ls == NULL) /* || (!IS_TEMPVAR_INDEX(iptr->dst.varindex)) */ ||
+                                       (ls->lifetime[iptr->dst.varindex].type != UNUSED))
+                                       /* a "living" stackslot */
+#endif
+                               switch (md->returntype.type) {
+                               case TYPE_INT:
+                               case TYPE_ADR:
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                                       // XXX Sparc64: This should actually be REG_RESULT_CALLER, fix this!
+                                       emit_imove(cd, REG_RESULT, s1);
+                                       emit_store_dst(jd, iptr, s1);
+                                       break;
+
+                               case TYPE_LNG:
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_LRESULT);
+                                       // XXX Sparc64: This should actually be REG_RESULT_CALLER, fix this!
+                                       emit_lmove(cd, REG_LRESULT, s1);
+                                       emit_store_dst(jd, iptr, s1);
+                                       break;
+
+#if 0 //XXX For ARM!!!
+#if !defined(ENABLE_SOFTFLOAT)
+                               } else {
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                                       if (IS_2_WORD_TYPE(d))
+                                               M_CAST_L2D(REG_RESULT_PACKED, s1);
+                                       else
+                                               M_CAST_I2F(REG_RESULT, s1);
+                               }
+#endif /* !defined(ENABLE_SOFTFLOAT) */
+#endif //XXX End of ARM
+
+                               case TYPE_FLT:
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                                       emit_fmove(cd, REG_FRESULT, s1);
+                                       emit_store_dst(jd, iptr, s1);
+                                       break;
+
+                               case TYPE_DBL:
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                                       emit_dmove(cd, REG_FRESULT, s1);
+                                       emit_store_dst(jd, iptr, s1);
+                                       break;
+
+                               case TYPE_VOID:
+                                       break;
+                               }
+
+                               break;
+
+                       case ICMD_TABLESWITCH:  /* ..., index ==> ...                     */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+                       case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                       */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               i = iptr->sx.s23.s2.lookupcount;
+
+                               // XXX Again we need to check this
+                               MCODECHECK((i<<2)+8);   // Alpha, ARM, i386, MIPS, M68K, Sparc64
+                               MCODECHECK((i<<3)+8);   // PPC64
+                               MCODECHECK(8 + ((7 + 6) * i) + 5);   // X86_64, S390
+
+                               // Compare keys.
+                               for (lookup_target_t* lookup = iptr->dst.lookup; i > 0; ++lookup, --i) {
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+                                       emit_icmp_imm(cd, s1, lookup->value);
+                                       emit_beq(cd, lookup->target.block);
+#elif SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+                                       ICONST(REG_ITMP2, lookup->value);
+                                       emit_beq(cd, lookup->target.block, s1, REG_ITMP2);
+#elif SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+                                       emit_icmpeq_imm(cd, s1, lookup->value, REG_ITMP2);
+                                       emit_bnez(cd, lookup->target.block, REG_ITMP2);
+#else
+# error Unable to generate code for this configuration!
+#endif
+                               }
+
+                               // Default branch.
+                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               ALIGNCODENOP;
+                               break;
+
+                       case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref        */
+                       case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult        */
+                       case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
+
+                               // Generate architecture specific instructions.
+                               codegen_emit_instruction(jd, iptr);
+                               break;
+
+                       default:
+                               exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+                                                                                          iptr->opc);
+                               return false;
+
+                       } // the big switch
+
+               } // for all instructions
+
+#if defined(ENABLE_SSA)
+               // By edge splitting, in blocks with phi moves there can only
+               // be a goto as last command, no other jump/branch command.
+               if (ls != NULL) {
+                       if (!last_cmd_was_goto)
+                               codegen_emit_phi_moves(jd, bptr);
+               }
+#endif
+
+#if defined(__I386__) || defined(__M68K__) || defined(__MIPS__) || defined(__S390__) || defined(__SPARC_64__) || defined(__X86_64__)
+               // XXX Again!!!
+               /* XXX require a lower number? */
+               MCODECHECK(64);  // I386, MIPS, Sparc64
+               MCODECHECK(512); // S390, X86_64
+
+               /* XXX We can remove that when we don't use UD2 anymore on i386
+                  and x86_64. */
+
+               /* At the end of a basic block we may have to append some nops,
+                  because the patcher stub calling code might be longer than the
+                  actual instruction. So codepatching does not change the
+                  following block unintentionally. */
+
+               if (cd->mcodeptr < cd->lastmcodeptr) {
+                       while (cd->mcodeptr < cd->lastmcodeptr) {
+                               M_NOP;
+                       }
+               }
+#endif
+
+       } // for all basic blocks
+
+       // Generate traps.
+       emit_patcher_traps(jd);
+
+       // Everything's ok.
+       return true;
+}
+
+
 /* codegen_emit_phi_moves ****************************************************
 
    Emits phi moves at the end of the basicblock.
index b988853b39629bf11a957320305f2b67b14ffc86..68fc49bdff27c263109524fe155e1f75d8680ccb 100644 (file)
@@ -71,6 +71,19 @@ typedef struct dataref                dataref;
 #define GET_LOW_REG(a)      ((a) & 0x0000ffff)
 #define GET_HIGH_REG(a)    (((a) & 0xffff0000) >> 16)
 
+/* All 32-bit machines we support use packed registers to store
+   return values and temporary values. */
+
+#if SIZEOF_VOID_P == 8
+# define REG_LRESULT         REG_RESULT
+# define REG_LTMP12          REG_ITMP1
+# define REG_LTMP23          REG_ITMP2
+#else
+# define REG_LRESULT         REG_RESULT_PACKED
+# define REG_LTMP12          REG_ITMP12_PACKED
+# define REG_LTMP23          REG_ITMP23_PACKED
+#endif
+
 
 /* branch conditions **********************************************************/
 
@@ -211,6 +224,10 @@ void codegen_setup(jitdata *jd);
 bool codegen_generate(jitdata *jd);
 bool codegen_emit(jitdata *jd);
 
+void codegen_emit_prolog(jitdata* jd);
+void codegen_emit_epilog(jitdata* jd);
+void codegen_emit_instruction(jitdata* jd, instruction* iptr);
+
 #if defined(ENABLE_INTRP)
 bool intrp_codegen(jitdata *jd);
 #endif
index c3c3af73db15566eef07ba2290ce158d883859e8..24f6b15109fcdb3bd09ea842c0b01662a64789c7 100644 (file)
@@ -1,7 +1,8 @@
 /* src/vm/jit/emit-common.hpp - common code emitter functions
 
-   Copyright (C) 2006, 2007, 2008
+   Copyright (C) 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 */
 
 
-#ifndef _EMIT_COMMON_H
-#define _EMIT_COMMON_H
+#ifndef _EMIT_COMMON_HPP
+#define _EMIT_COMMON_HPP
 
 #include "config.h"
 #include "vm/types.h"
 
 #include "arch.h"
+#include "codegen.h"
 
 #include "vm/jit/codegen-common.hpp"
 #include "vm/jit/jit.hpp"
@@ -106,6 +108,18 @@ void emit_copy(jitdata *jd, instruction *iptr);
 void emit_iconst(codegendata *cd, s4 d, s4 value);
 void emit_lconst(codegendata *cd, s4 d, s8 value);
 
+/* compare-emitting functions targeting an integer register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_icmpeq_imm(codegendata* cd, int reg, int32_t value, int d);
+#endif
+
+/* compare-emitting functions targeting the condition register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value);
+#endif
+
 /* branch-emitting functions */
 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
@@ -197,6 +211,20 @@ uint32_t emit_trap(codegendata *cd);
 
 void emit_patcher_traps(jitdata *jd);
 
+void emit_recompute_pv(codegendata* cd);
+
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset);
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset);
+#endif
+
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code);
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr);
+void emit_profile_cycle_start();
+void emit_profile_cycle_stop();
+#endif
+
 void emit_verbosecall_enter(jitdata *jd);
 void emit_verbosecall_exit(jitdata *jd);
 
@@ -204,7 +232,77 @@ void emit_verbosecall_exit(jitdata *jd);
 }
 #endif
 
-#endif /* _EMIT_COMMON_H */
+
+/* inline code generation functions *******************************************/
+
+/**
+ * Generates an integer-move from register s to d. If s and d are
+ * the same registers, no code will be generated.
+ */
+static inline void emit_imove(codegendata* cd, int s, int d)
+{
+       if (s != d)
+#if defined(__ARM__)
+               // XXX Fix this!!!
+               M_MOV(d, s);
+#else
+               M_MOV(s, d);
+#endif
+}
+
+
+/**
+ * Generates a long-move from register s to d. If s and d are
+ * the same registers, no code will be generated.
+ */
+static inline void emit_lmove(codegendata* cd, int s, int d)
+{
+#if SIZEOF_VOID_P == 8
+       emit_imove(cd, s, d);
+#else
+       if (GET_HIGH_REG(s) == GET_LOW_REG(d)) {
+               assert((GET_LOW_REG(s) != GET_HIGH_REG(d)));
+               emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d));
+               emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d));
+       } else {
+               emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d));
+               emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d));
+       }
+#endif
+}
+
+
+/**
+ * Generates a float-move from register s to d. If s and d are
+ * the same registers, no code will be generated.
+ */
+static inline void emit_fmove(codegendata* cd, int s, int d)
+{
+       if (s != d)
+               M_FMOV(s, d);
+}
+
+
+/**
+ * Generates an double-move from register s to d. If s and d are
+ * the same registers, no code will be generated.
+ */
+static inline void emit_dmove(codegendata* cd, int s, int d)
+{
+       if (s != d)
+               M_DMOV(s, d);
+}
+
+
+/* preserve compatibility with legacy code ************************************/
+
+#define M_INTMOVE(a, b)      emit_imove(cd, a, b)
+#define M_LNGMOVE(a, b)      emit_lmove(cd, a, b)
+#define M_FLTMOVE(a, b)      emit_fmove(cd, a, b)
+#define M_DBLMOVE(a, b)      emit_dmove(cd, a, b)
+
+
+#endif /* _EMIT_COMMON_HPP */
 
 
 /*
index f0bcdfc9970f446bca1efc6132f5dcfd10d73ca6..a3a91be153706d0abfdc8589163cdc47c6fecefd 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              1
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           2       /* bytes */
index 14340d7a4050151e87ba894f69327ed40f4934f8..2eb99c0d4f7d2198239f5f0ab5f24ad128cda14b 100644 (file)
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#elif defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* codegen_emit ****************************************************************
-
-   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;
-       int                 align_off;      /* offset for alignment compensation  */
-       varinfo            *var, *var1;
-       basicblock         *bptr;
-       instruction        *iptr;
-       u2                  currentline;
-       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
-       builtintable_entry *bte;
-       methoddesc         *md;
-       fieldinfo          *fi;
-       unresolved_field   *uf;
-       s4                  fieldtype;
-       s4                  varindex;
-#if defined(ENABLE_SSA)
-       lsradata *ls;
-       bool last_cmd_was_goto;
-
-       last_cmd_was_goto = false;
-       ls = jd->ls;
-#endif
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* prevent compiler warnings */
-
-       s1          = 0;
-       s2          = 0;
-       d           = 0;
-       currentline = 0;
-       lm          = NULL;
-       bte         = NULL;
-
-       {
-       s4 i, p, t, l;
-       s4 savedregs_num = 0;
-       s4 stack_off = 0;
-
-       /* space to save used callee saved registers */
-
-       savedregs_num += (INT_SAV_CNT - rd->savintreguse);
-       savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
-
-       cd->stackframesize = rd->memuse + savedregs_num;
+       varinfo*    var;
+       methoddesc* md;
+       int32_t     s1, d;
+       int32_t     p, t, l;
+       int32_t     varindex;
+       int         i;
+       int         align_off;
+
+       // Get required compiler data.
+       methodinfo*   m  = jd->m;
+       codegendata*  cd = jd->cd;
+       registerdata* rd = jd->rd;
 
-          
-#if defined(ENABLE_THREADS)
-       /* space to save argument of monitor_enter */
-
-       if (checksync && code_is_synchronized(code))
-               cd->stackframesize++;
-#endif
-
-       /* create method header */
-
-    /* Keep stack of non-leaf functions 16-byte aligned. */
-
-       if (!code_is_leafmethod(code)) {
-               ALIGN_ODD(cd->stackframesize);
-       }
+       /* create stack frame (if necessary) */
 
        align_off = cd->stackframesize ? 4 : 0;
 
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(
-               cd, cd->stackframesize * 8 + align_off);           /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);                  /* IsLeaf          */
-       else
-               (void) dseg_add_unique_s4(cd, 0);                  /* 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 */
-
-#if defined(ENABLE_PROFILING)
-       /* generate method profiling code */
-
-       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-               /* count frequency */
-
-               M_MOV_IMM(code, REG_ITMP3);
-               M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
-       }
-#endif
-
-       /* create stack frame (if necessary) */
-
-       if (cd->stackframesize)
-               /* align_off == 4 */
+       if (cd->stackframesize) {
+               assert(align_off == 4);
                M_ASUB_IMM(cd->stackframesize * 8 + 4, REG_SP);
+       }
 
        /* save return address and used callee saved registers */
 
@@ -201,9 +108,8 @@ bool codegen_emit(jitdata *jd)
 
        md = m->parseddesc;
 
-       stack_off = 0;
-       for (p = 0, l = 0; p < md->paramcount; p++) {
-               t = md->paramtypes[p].type;
+       for (p = 0, l = 0; p < md->paramcount; p++) {
+               t = md->paramtypes[p].type;
 
                varindex = jd->local_map[l * 5 + t];
 #if defined(ENABLE_SSA)
@@ -346,204 +252,76 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-       /* call monitorenter function */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               s1 = rd->memuse;
-
-               if (m->flags & ACC_STATIC) {
-                       M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
-               }
-               else {
-                       M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
-                       M_TEST(REG_ITMP1);
-                       M_BNE(6);
-                       M_ALD_MEM(REG_ITMP1, TRAP_NullPointerException);
-               }
-
-               M_AST(REG_ITMP1, REG_SP, s1 * 8);
-               M_AST(REG_ITMP1, REG_SP, 0 * 4);
-               M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
-               M_CALL(REG_ITMP3);
-       }                       
-#endif
-
-#if !defined(NDEBUG)
-       emit_verbosecall_enter(jd);
-#endif
-
-       } 
-
-#if defined(ENABLE_SSA)
-       /* with SSA the Header is Basic Block 0 - insert phi Moves if necessary */
-       if ( ls != NULL)
-               codegen_emit_phi_moves(jd, ls->basicblocks[0]);
-#endif
-
-       /* 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_REPLACEMENT)
-               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
-                       if (cd->replacementpoint[-1].flags & RPLPOINT_FLAG_COUNTDOWN) {
-                               MCODECHECK(32);
-                               emit_trap_countdown(cd, &(m->hitcountdown));
-                       }
-               }
-#endif
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       methoddesc* md;
+       int32_t p;
+       int i;
 
-               /* copy interface registers to their destination */
+       // Get required compiler data.
+       methodinfo*   m  = jd->m;
+       codegendata*  cd = jd->cd;
+       registerdata* rd = jd->rd;
 
-               len = bptr->indepth;
-               MCODECHECK(512);
+       p = cd->stackframesize;
+       md = m->parseddesc;
 
-#if defined(ENABLE_PROFILING)
-               /* generate basic block profiling code */
+       /* restore saved registers */
 
-               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-                       /* count frequency */
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_ALD(rd->savintregs[i], REG_SP, p * 8);
+       }
 
-                       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
-                       M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->nr * 4);
+       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+               p--;
+               emit_fldl_membase(cd, REG_SP, p * 8);
+               if (md->returntype.type == TYPE_FLT || md->returntype.type == TYPE_DBL) {
+                       assert(0);
+/*                     emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
+               } else {
+                       assert(0);
+/*                     emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
                }
-#endif
-
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
-# if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
-               if (opt_lsra) {
-# endif
-# if defined(ENABLE_SSA)
-               if (ls != NULL) {
-                       last_cmd_was_goto = false;
-# endif
-                       if (len > 0) {
-                               len--;
-                               var = VAR(bptr->invars[len]);
-                               if (bptr->type != BBTYPE_STD) {
-                                       if (!IS_2_WORD_TYPE(var->type)) {
-#if !defined(ENABLE_SSA)
-                                               if (bptr->type == BBTYPE_EXH) {
-                                                       d = codegen_reg_of_var(0, var, REG_ITMP1);
-                                                       M_INTMOVE(REG_ITMP1, d);
-                                                       emit_store(jd, NULL, var, d);
-                                               }
-#endif
-                                       } 
-                                       else {
-                                               log_text("copy interface registers(EXH, SBR): longs \
-                                  have to be in memory (begin 1)");
-                                               assert(0);
-                                       }
-                               }
-                       }
-
-               } 
-               else
-#endif /* defined(ENABLE_LSRA) || defined(ENABLE_SSA) */
-               {
-               while (len) {
-                       len--;
-                       var = VAR(bptr->invars[len]);
-                       if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
-                               if (!IS_2_WORD_TYPE(var->type)) {
-                                       if (bptr->type == BBTYPE_EXH) {
-                                               d = codegen_reg_of_var(0, var, REG_ITMP1);
-                                               M_INTMOVE(REG_ITMP1, d);
-                                               emit_store(jd, NULL, var, d);
-                                       }
-                               } 
-                               else {
-                                       log_text("copy interface registers: longs have to be in \
-                               memory (begin 1)");
-                                       assert(0);
-                               }
-
-                       } 
-                       else {
-                               assert((var->flags & INOUT));
-                       }
-               } /* while (len) */
-               } /* */
-
-               /* walk through all instructions */
-               
-               len = bptr->icount;
-               currentline = 0;
-
-               for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
-                       if (iptr->line != currentline) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
-
-                       MCODECHECK(1024);                         /* 1kB should be enough */
-
-               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);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
+       /* deallocate stack */
 
-               case ICMD_INLINE_END:
+       if (cd->stackframesize)
+               M_AADD_IMM(cd->stackframesize * 8 + 4, REG_SP);
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(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;
+       varinfo*            var1;
+       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.
+       codegendata* cd = jd->cd;
+
+       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);
@@ -620,29 +398,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/copy/move operations ************************************/
-
-               case ICMD_ILOAD:
-               case ICMD_ALOAD:
-               case ICMD_LLOAD:
-               case ICMD_FLOAD:
-               case ICMD_DLOAD:
-               case ICMD_ISTORE:
-               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                 */
@@ -988,7 +743,6 @@ bool codegen_emit(jitdata *jd)
                        emit_arithmetic_check(cd, iptr, REG_ITMP3);
 
                        bte = iptr->sx.s23.s3.bte;
-                       md = bte->md;
 
                        M_LST(s2, REG_SP, 2 * 4);
 
@@ -1894,15 +1648,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
-               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       /* 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);
@@ -2436,16 +2181,6 @@ 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)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
                        M_CALL_IMM(0);                            /* passing exception pc */
                        M_POP(REG_ITMP2_XPC);
 
@@ -2453,49 +2188,6 @@ bool codegen_emit(jitdata *jd)
                        M_JMP(REG_ITMP3);
                        break;
 
-               case ICMD_GOTO:         /* ... ==> ...                                */
-               case ICMD_RET:          /* ... ==> ...                                */
-
-#if defined(ENABLE_SSA)
-                       if ( ls != NULL ) {
-                               last_cmd_was_goto = true;
-
-                               /* In case of a Goto phimoves have to be inserted before the */
-                               /* jump */
-
-                               codegen_emit_phi_moves(jd, bptr);
-                       }
-#endif
-                       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 ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
-                       break;
-
-               case ICMD_IFEQ:         /* ..., value ==> ...                         */
-               case ICMD_IFLT:
-               case ICMD_IFLE:
-               case ICMD_IFNE:
-               case ICMD_IFGT:
-               case ICMD_IFGE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
-                       break;
-
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
@@ -2586,28 +2278,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_ICMPGE:
-               case ICMD_IF_ICMPLE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
-                       break;
-
-               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       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_low(jd, iptr, REG_ITMP1);
@@ -2688,134 +2358,6 @@ bool codegen_emit(jitdata *jd)
                        emit_buge(cd, iptr->dst.block);
                        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_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_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)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-                       goto nowperformreturn;
-
-               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_DRETURN:
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       goto nowperformreturn;
-
-               case ICMD_RETURN:      /* ...  ==> ...                                */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-nowperformreturn:
-                       {
-                       s4 i, p;
-                       
-                       p = cd->stackframesize;
-                       
-#if !defined(NDEBUG)
-                       emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               M_ALD(REG_ITMP2, REG_SP, rd->memuse * 8);
-
-                               /* we need to save the proper return value */
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_IST(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_LRETURN:
-                                       M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_FRETURN:
-                                       emit_fstps_membase(cd, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_DRETURN:
-                                       emit_fstpl_membase(cd, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-
-                               M_AST(REG_ITMP2, REG_SP, 0);
-                               M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
-                               M_CALL(REG_ITMP3);
-
-                               /* and now restore the proper return value */
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_ILD(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_LRETURN:
-                                       M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_FRETURN:
-                                       emit_flds_membase(cd, REG_SP, rd->memuse * 8);
-                                       break;
-
-                               case ICMD_DRETURN:
-                                       emit_fldl_membase(cd, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore saved registers */
-
-                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
-                               p--; M_ALD(rd->savintregs[i], REG_SP, p * 8);
-                       }
-
-                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
-                               p--;
-                               emit_fldl_membase(cd, REG_SP, p * 8);
-                               if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
-                                       assert(0);
-/*                                     emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1); */
-                               } else {
-                                       assert(0);
-/*                                     emit_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset); */
-                               }
-                       }
-
-                       /* deallocate stack */
-
-                       if (cd->stackframesize)
-                               M_AADD_IMM(cd->stackframesize * 8 + 4, REG_SP);
-
-                       M_RET;
-                       }
-                       break;
-
-
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2858,243 +2400,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) {
-                                       M_CMP_IMM(lookup->value, s1);
-                                       emit_beq(cd, lookup->target.block);
-                                       lookup++;
-                               }
-
-                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                               ALIGNCODENOP;
+               case ICMD_BUILTIN:
+                       bte = iptr->sx.s23.s3.bte;
+                       if (bte->stub == NULL) {
+                               M_MOV_IMM(bte->fp, REG_ITMP1);
                        }
-                       break;
-
-               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
+                       else {
+                               M_MOV_IMM(bte->stub, REG_ITMP1);
+                       }
+                       M_CALL(REG_ITMP1);
 
-                       bte = iptr->sx.s23.s3.bte;
-                       md = bte->md;
-
-#if defined(ENABLE_ESCAPE_REASON)
-                       if (bte->fp == BUILTIN_escape_reason_new) {
-                               void set_escape_reasons(void *);
-                               M_ASUB_IMM(8, REG_SP);
-                               M_MOV_IMM(iptr->escape_reasons, REG_ITMP1);
-                               M_AST(EDX, REG_SP, 4);
-                               M_AST(REG_ITMP1, REG_SP, 0);
-                               M_MOV_IMM(set_escape_reasons, REG_ITMP1);
-                               M_CALL(REG_ITMP1);
-                               M_ALD(EDX, REG_SP, 4);
-                               M_AADD_IMM(8, REG_SP);
+#if defined(ENABLE_ESCAPE_CHECK)
+                       if (bte->opcode == ICMD_NEW || bte->opcode == ICMD_NEWARRAY) {
+                               /*emit_escape_annotate_object(cd, m);*/
                        }
 #endif
+                       break;
 
-                       goto gen_method;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
+               case ICMD_INVOKESPECIAL:
+                       M_ALD(REG_ITMP1, REG_SP, 0 * 8);
+                       emit_nullpointer_check(cd, iptr, REG_ITMP1);
+                       /* fall through */
 
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
+               case ICMD_INVOKESTATIC:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
 
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+                               patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
+                                                                       um, 0);
 
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
-                               lm = NULL;
+                               disp = 0;
                        }
                        else {
                                lm = iptr->sx.s23.s3.fmiref->p.method;
-                               md = lm->parseddesc;
+                               disp = (ptrint) lm->stubroutine;
                        }
 
-gen_method:
-                       s3 = md->paramcount;
-
-                       MCODECHECK((s3 << 1) + 64);
-
-                       /* copy arguments to registers or stack location                  */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-         
-                               /* Already Preallocated (ARGVAR) ? */
-                               if (var->flags & PREALLOC)
-                                       continue;
-                               if (IS_INT_LNG_TYPE(var->type)) {
-                                       if (!md->params[s3].inmemory) {
-                                               log_text("No integer argument registers available!");
-                                               assert(0);
-
-                                       } else {
-                                               if (IS_2_WORD_TYPE(var->type)) {
-                                                       d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                                       M_LST(d, REG_SP, md->params[s3].regoff);
-                                               } else {
-                                                       d = emit_load(jd, iptr, var, REG_ITMP1);
-                                                       M_IST(d, REG_SP, md->params[s3].regoff);
-                                               }
-                                       }
-
-                               } else {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = md->params[s3].regoff;
-                                               d = emit_load(jd, iptr, var, s1);
-                                               M_FLTMOVE(d, s1);
-
-                                       } else {
-                                               d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(d, REG_SP, md->params[s3].regoff);
-                                               else
-                                                       M_FST(d, REG_SP, md->params[s3].regoff);
-                                       }
-                               }
-                       } /* end of for */
-
-                       switch (iptr->opc) {
-                       case ICMD_BUILTIN:
-                               d = md->returntype.type;
-
-                               if (bte->stub == NULL) {
-                                       M_MOV_IMM(bte->fp, REG_ITMP1);
-                               }
-                               else {
-                                       M_MOV_IMM(bte->stub, REG_ITMP1);
-                               }
-                               M_CALL(REG_ITMP1);
-
-#if defined(ENABLE_ESCAPE_CHECK)
-                               if (bte->opcode == ICMD_NEW || bte->opcode == ICMD_NEWARRAY) {
-                                       /*emit_escape_annotate_object(cd, m);*/
-                               }
-#endif
-                               break;
-
-                       case ICMD_INVOKESPECIAL:
-                               M_ALD(REG_ITMP1, REG_SP, 0 * 8);
-                               emit_nullpointer_check(cd, iptr, REG_ITMP1);
-                               /* fall through */
-
-                       case ICMD_INVOKESTATIC:
-                               if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
-                                       patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
-                                                                               um, 0);
-
-                                       disp = 0;
-                                       d = md->returntype.type;
-                               }
-                               else {
-                                       disp = (ptrint) lm->stubroutine;
-                                       d = lm->parseddesc->returntype.type;
-                               }
-
-                               M_MOV_IMM2(disp, REG_ITMP2);
-                               M_CALL(REG_ITMP2);
-                               break;
-
-                       case ICMD_INVOKEVIRTUAL:
-                               M_ALD(REG_ITMP1, REG_SP, 0 * 8);
-                               emit_nullpointer_check(cd, iptr, s1);
-
-                               if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
-                                       patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
+                       M_MOV_IMM2(disp, REG_ITMP2);
+                       M_CALL(REG_ITMP2);
+                       break;
 
-                                       s1 = 0;
-                                       d = md->returntype.type;
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, table[0]) +
-                                               sizeof(methodptr) * lm->vftblindex;
-                                       d = md->returntype.type;
-                               }
+               case ICMD_INVOKEVIRTUAL:
+                       M_ALD(REG_ITMP1, REG_SP, 0 * 8);
+                       emit_nullpointer_check(cd, iptr, s1);
 
-                               M_ALD(REG_METHODPTR, REG_ITMP1,
-                                         OFFSET(java_object_t, vftbl));
-                               M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
-                               M_CALL(REG_ITMP3);
-                               break;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
 
-                       case ICMD_INVOKEINTERFACE:
-                               M_ALD(REG_ITMP1, REG_SP, 0 * 8);
-                               emit_nullpointer_check(cd, iptr, s1);
+                               patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
 
-                               if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
+                               s1 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) +
+                                       sizeof(methodptr) * lm->vftblindex;
+                       }
 
-                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
+                       M_ALD(REG_METHODPTR, REG_ITMP1,
+                                 OFFSET(java_object_t, vftbl));
+                       M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
+                       M_CALL(REG_ITMP3);
+                       break;
 
-                                       s1 = 0;
-                                       s2 = 0;
-                                       d = md->returntype.type;
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr) * lm->clazz->index;
+               case ICMD_INVOKEINTERFACE:
+                       M_ALD(REG_ITMP1, REG_SP, 0 * 8);
+                       emit_nullpointer_check(cd, iptr, s1);
 
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
 
-                                       d = md->returntype.type;
-                               }
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                               M_ALD(REG_METHODPTR, REG_ITMP1,
-                                         OFFSET(java_object_t, vftbl));
-                               M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
-                               M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
-                               M_CALL(REG_ITMP3);
-                               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 size of call code in replacement point */
-
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
-
-                       /* d contains return type */
-
-                       if (d != TYPE_VOID) {
-#if defined(ENABLE_SSA)
-                               if ((ls == NULL) /* || (!IS_TEMPVAR_INDEX(iptr->dst.varindex)) */ ||
-                                       (ls->lifetime[iptr->dst.varindex].type != UNUSED)) 
-                                       /* a "living" stackslot */
-#endif
-                               {
-                                       if (IS_INT_LNG_TYPE(d)) {
-                                               if (IS_2_WORD_TYPE(d)) {
-                                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
-                                                       M_LNGMOVE(REG_RESULT_PACKED, s1);
-                                               }
-                                               else {
-                                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                                       M_INTMOVE(REG_RESULT, s1);
-                                               }
-                                       }
-                                       else {
-                                               s1 = codegen_reg_of_dst(jd, iptr, REG_NULL);
-                                       }
-                                       emit_store_dst(jd, iptr, s1);
-                               }
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                        }
-                       break;
 
+                       M_ALD(REG_METHODPTR, REG_ITMP1,
+                                 OFFSET(java_object_t, vftbl));
+                       M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
+                       M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
+                       M_CALL(REG_ITMP3);
+                       break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -3491,59 +2885,9 @@ gen_method:
                        emit_store_dst(jd, iptr, s1);
                        break;
 
-#if defined(ENABLE_SSA)
-               case ICMD_GETEXCEPTION:
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       M_INTMOVE(REG_ITMP1, d);
-                       emit_store_dst(jd, iptr, d);
-                       break;
-#endif
                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 */
-               
-       MCODECHECK(64);
-
-#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
-       if (!opt_lsra)
-#endif
-#if defined(ENABLE_SSA)
-       if ( ls != NULL ) {
-
-               /* by edge splitting, in Blocks with phi moves there can only */
-               /* be a goto as last command, no other Jump/Branch Command    */
-
-               if (!last_cmd_was_goto)
-                       codegen_emit_phi_moves(jd, bptr);
-       }
-
-#endif
-
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr) {
-                       M_NOP;
-               }
-       }
-
-       } /* if (bptr -> flags >= BBREACHED) */
-       } /* for basic block */
-
-       /* generate stubs */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
@@ -3588,7 +2932,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        /* create method header */
 
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8 + 4); /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
        (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
        (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
        (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
index 3f61d96a88833bc9b9ff8eedc1f1a7aa5595d3db..375154c059cd69940cf299ad122852a867126257 100644 (file)
     } while (0)
 
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_MOV(a, b); \
-    } while (0)
-
-#define M_LNGMOVE(a,b) \
-    do { \
-        if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \
-            assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-        } else { \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-        } \
-    } while (0)
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/
-
-#define M_FLTMOVE(reg,dreg)                                          \
+#define M_FMOV(reg,dreg)                                             \
     do {                                                             \
-        if ((reg) != (dreg)) {                                       \
-            log_text("M_FLTMOVE");                                   \
-            assert(0);                                               \
-        }                                                            \
+        log_text("M_FMOV");                                          \
+        assert(0);                                                   \
     } while (0)
 
+#define M_DMOV(a,b) M_FMOV(a,b)
 
 #define ICONST(d,c) \
     do { \
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
 #define M_RET                   M_BYTE1(0xc3)
 
+#define M_ACMP(a,b)             M_CMP(a,b)
+
+#define M_ICMP(a,b)             M_CMP(a,b)
 #define M_ICMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
 
 #define M_BEQ(a)                emit_jcc(cd, CC_E, (a))
index cfddc22a70f64aeb6934e5de08a063ac1d4f5ba6..d69217920db6745eda2d90baddd3ba1fbe284846 100644 (file)
@@ -332,6 +332,16 @@ void emit_copy(jitdata *jd, instruction *iptr)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       M_CMP_IMM(value, reg);
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -577,6 +587,125 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int align_off;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       align_off = cd->stackframesize ? 4 : 0;
+
+       if (m->flags & ACC_STATIC) {
+               M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
+       }
+       else {
+               M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
+               M_TEST(REG_ITMP1);
+               M_BNE(6);
+               M_ALD_MEM(REG_ITMP1, TRAP_NullPointerException);
+       }
+
+       M_AST(REG_ITMP1, REG_SP, syncslot_offset);
+       M_AST(REG_ITMP1, REG_SP, 0 * 4);
+       M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
+       M_CALL(REG_ITMP3);
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       M_ALD(REG_ITMP2, REG_SP, syncslot_offset);
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_LNG:
+               M_LST(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_FLT:
+               emit_fstps_membase(cd, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_DBL:
+               emit_fstpl_membase(cd, REG_SP, syncslot_offset);
+               break;
+       }
+
+       M_AST(REG_ITMP2, REG_SP, 0);
+       M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
+       M_CALL(REG_ITMP3);
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_LNG:
+               M_LLD(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_FLT:
+               emit_flds_membase(cd, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_DBL:
+               emit_fldl_membase(cd, REG_SP, syncslot_offset);
+               break;
+       }
+}
+#endif
+
+
+/**
+ * Emit profiling code for method frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code)
+{
+       M_MOV_IMM(code, REG_ITMP3);
+       M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
+}
+#endif
+
+
+/**
+ * Emit profiling code for basicblock frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
+{
+       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
+       M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->nr * 4);
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index c17c0229f15e1ba1cd72f9bda33b0c94013e5e69..8438d0dd1e600b637b2cd1306785382384629e4f 100644 (file)
@@ -1,9 +1,7 @@
-/* src/vm/jit/i386/emitfuncs.h - emit function prototypes
+/* src/vm/jit/i386/emit.h - machine dependent emit function prototypes
 
-   Copyright (C) 1996-2005, 2006 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
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
 */
 
 
-#ifndef _EMITFUNCS_H
-#define _EMITFUNCS_H
+#ifndef _MD_EMIT_H
+#define _MD_EMIT_H
 
+#include "config.h"
 #include "vm/types.h"
 
 #include "vm/jit/codegen-common.hpp"
 
 #define emit_reg(reg,rm)                emit_address_byte(3,(reg),(rm))
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* integer instructions */
 
@@ -304,7 +300,19 @@ void emit_escape_check(codegendata *cd, s4 reg);
 void emit_escape_annotate_object(codegendata *cd, methodinfo *m);
 #endif
 
-#endif /* _EMITFUNCS_H */
+
+/**
+ * Emit code to recompute the procedure vector. This is a nop,
+ * because we do not use a procedure vector.
+ */
+static inline void emit_recompute_pv(codegendata* cd) {}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MD_EMIT_H */
 
 
 /*
index 562736be4f66d47c4fb2fd343d16a7d75a525a48..9bfa133732d07630da8dfad573d31a59e366fbeb 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/md.h - machine dependent i386 functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 /* inline functions ***********************************************************/
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       int32_t stackframesize;
+
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On i386 we use 8-byte stackslots.
+       stackframesize = code->stackframesize * 8;
+
+       // If there is a stackframe present, we need to take the alignment
+       // compensation for the stored return address into account.
+       if (stackframesize != 0)
+               stackframesize += 4;
+
+       return stackframesize;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 5498aabeebe0dceaa445a0469e51e0491ac73140..77a189f2551d7dfc08f7eeceae95c202f23d91c0 100644 (file)
 #define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
 #define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
 
+
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              1
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
+
+
 #define TRACE_ARGS_NUM                 8
 
 #define REG_ZERO -1
index 12fd5184044329237c4489565e135ee28fdd25bc..0633aefc43790eefd527cff289dc72a27fa0e887 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/m68k/codegen.c
+/* src/vm/jit/m68k/codegen.c - machine code generator for m68k
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/jit/abi.h"
 #include "vm/jit/parse.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
 
-bool codegen_emit(jitdata *jd) 
-{      
-       methodinfo         *m;
-       codeinfo           *code;
-       codegendata        *cd;
-       registerdata       *rd;
-       s4                  len, s1, s2, s3, d, disp;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       u2                  currentline;
-       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
-       unresolved_method  *um;
-       builtintable_entry *bte;
-       methoddesc         *md;
-       s4                  fieldtype;
-       s4                  varindex;
-       unresolved_field   *uf;
-       fieldinfo          *fi;
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* prevent compiler warnings */
-
-       d = 0;
-       lm = NULL;
-       bte = NULL;
-
-       {
-               s4 i, p, t, l;
-               /* save calle saved registers */
-               s4 savedregs_num = 0;
-
-               savedregs_num += (INT_SAV_CNT - rd->savintreguse);
-               savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
-               savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
-
-               cd->stackframesize = rd->memuse + savedregs_num;
-       
-               /* we always add 2 stack slots.
-                * 1 word the lock word, which may be unused and resides @ rd->memuse * 8
-                * + 2 words to either save the return value for LOCK_monitor_exit @ rd->memuse * 8 + 8
-                * on the other hand we could use 2 words when a builtin returns a doulbe which are
-                * returned in %d0, %d1 and need to be stored onto the stack and read in used a fmovemd
-                * so we always _need_ at least 2 slots, and this keeps the code simple */
-               cd->stackframesize += 2;        
-
-               cd->stackframesize *= 8;        /* we use 8 byte stack slots */
-
-#if 0
-#if defined(ENABLE_THREADS)
-               /* we need additional space to save argument of monitor_enter */
-               if (checksync && code_is_synchronized(code))    {
-                       if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))     {
-                               cd->stackframesize += 2;
-                       } else  {
-                               cd->stackframesize += 1;
-                       }
-               }
-#endif
-#endif 
-       
-               /* create method header */
-               (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-               (void) dseg_add_unique_s4(cd, cd->stackframesize);         /* FrameSize       */
-
-               code->synchronizedoffset = rd->memuse * 8;
-
-               /* REMOVEME: We still need it for exception handling in assembler. */
-
-               if (code_is_leafmethod(code))
-                       (void) dseg_add_unique_s4(cd, 1);
-               else
-                       (void) dseg_add_unique_s4(cd, 0);
-
-               /* XXX we use the IntSave a split field for the adr now */
-               (void) dseg_add_unique_s4(cd, (ADR_SAV_CNT - rd->savadrreguse) << 16 | (INT_SAV_CNT - rd->savintreguse)); /* IntSave */
-               (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
-
-#if defined(ENABLE_PROFILING)
-               assert(0);
-#endif
-
-#if !defined(NDEBUG)
-               emit_verbosecall_enter(jd);
-#endif
-               /* create stack frame */
-               M_AADD_IMM(-(cd->stackframesize), REG_SP);
-
-               /* save used callee saved registers */
-               p = cd->stackframesize;
-               for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
-                       p-=8; M_IST(rd->savintregs[i], REG_SP, p);
-               }
-               for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
-                       p-=8; M_AST(rd->savadrregs[i], REG_SP, p);
-               }
+/**
+ * Generates machine code for the method prolog.
+ */
+void codegen_emit_prolog(jitdata* jd)
+{
+       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;
+
+       // XXX XXX
+       // XXX Fix the below stuff, cd->stackframesize is a slot counter
+       //     and not a byte counter!!!
+       // XXX XXX
+
+       /* create stack frame */
+       M_AADD_IMM(-(cd->stackframesize), REG_SP);
+
+       /* save used callee saved registers */
+       p = cd->stackframesize;
+       for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
+               p-=8; M_IST(rd->savintregs[i], REG_SP, p);
+       }
+       for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
+               p-=8; M_AST(rd->savadrregs[i], REG_SP, p);
+       }
 #if !defined(ENABLE_SOFTFLOAT)
-               for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
-                       p-=8; M_FSTORE(rd->savfltregs[i], REG_SP, p);
-               }       
+       for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
+               p-=8; M_FSTORE(rd->savfltregs[i], REG_SP, p);
+       }       
 #else
-               assert(FLT_SAV_CNT == 0);
-               assert(rd->savfltreguse == 0);
+       assert(FLT_SAV_CNT == 0);
+       assert(rd->savfltreguse == 0);
 #endif
-               /* take arguments out of stack frame */
-               md = m->parseddesc;
-               for (p = 0, l = 0; p < md->paramcount; p++) {
-                       t = md->paramtypes[p].type;
-                       varindex = jd->local_map[l * 5 + t];
-       
-                       l++;
-                       if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
-                               l++;
+       /* take arguments out of stack frame */
+       md = m->parseddesc;
+       for (p = 0, l = 0; p < md->paramcount; p++) {
+               t = md->paramtypes[p].type;
+               varindex = jd->local_map[l * 5 + t];
 
-                       if (varindex == UNUSED)
-                               continue;
+                       l++;
+                       if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
+                               l++;
 
-                       var = VAR(varindex);
-       
-                       s1 = md->params[p].regoff;
-                       assert(md->params[p].inmemory);                 /* all args are on stack */
+               if (varindex == UNUSED)
+                       continue;
+
+               var = VAR(varindex);
 
-                       switch (t)      {
+               s1 = md->params[p].regoff;
+               assert(md->params[p].inmemory);                 /* all args are on stack */
+
+               switch (t)      {
 #if defined(ENABLE_SOFTFLOAT)
-                       case TYPE_FLT:
-                       case TYPE_DBL:
+               case TYPE_FLT:
+               case TYPE_DBL:
 #endif
-                       case TYPE_LNG:
-                       case TYPE_INT:
-                               if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
-                                       if (IS_2_WORD_TYPE(t))  {
-                                               M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
-                                       } else {
-                                               M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
-                                       }
-                               } else {                             /* stack arg -> spilled  */
-                                       M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4);
-                                       M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
-                                       if (IS_2_WORD_TYPE(t)) {
-                                               M_ILD(REG_ITMP1, REG_SP, cd->stackframesize  + s1 + 4 + 4);
-                                               M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
-                                       }
-                               
-                               break;
+               case TYPE_LNG:
+               case TYPE_INT:
+                       if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
+                               if (IS_2_WORD_TYPE(t))  {
+                                       M_LLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
+                               } else {
+                                       M_ILD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
+                               }
+                       } else {                             /* stack arg -> spilled  */
+                                       M_ILD(REG_ITMP1, REG_SP, cd->stackframesize + s1 + 4);
+                                       M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_ILD(REG_ITMP1, REG_SP, cd->stackframesize  + s1 + 4 + 4);
+                                       M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
+                               }
+                       } 
+                       break;
 #if !defined(ENABLE_SOFTFLOAT)
-                       case TYPE_FLT:
-                       case TYPE_DBL:
-                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
-                                       if (IS_2_WORD_TYPE(t))  {
-                                               M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
-                                       } else {
-                                               M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
-                                       }
-                               } else {                             /* stack-arg -> spilled  */
-                                       if (IS_2_WORD_TYPE(t)) {
-                                               M_DLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
-                                               M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
-                                       } else {
-                                               M_FLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
-                                               M_FST(REG_FTMP1, REG_SP, var->vv.regoff);
-                                       }
+               case TYPE_FLT:
+               case TYPE_DBL:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                               if (IS_2_WORD_TYPE(t))  {
+                                       M_DLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
+                               } else {
+                                       M_FLD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
                                }
-                               break;
-#endif /* SOFTFLOAT */
-                       case TYPE_ADR:
-                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
-                                       M_ALD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
-                               } else {                             /* stack-arg -> spilled  */
-                                       M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + s1 + 4);
-                                       M_AST(REG_ATMP1, REG_SP, var->vv.regoff);
+                               } else {                             /* stack-arg -> spilled  */
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_DLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
+                                       M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
+                               } else {
+                                       M_FLD(REG_FTMP1, REG_SP, cd->stackframesize + s1 + 4);
+                                       M_FST(REG_FTMP1, REG_SP, var->vv.regoff);
                                }
-                               break;
-                       default: assert(0);
                        }
-               } /* end for argument out of stack*/
-
-#if defined(ENABLE_THREADS)
-       /* call lock_monitor_enter function */
-       if (checksync && code_is_synchronized(code))    {
-               if (m->flags & ACC_STATIC)      {
-                       M_AMOV_IMM((&m->clazz->object.header), REG_ATMP1);
-               } else  {
-                       /* for non-static case the first arg is the object */
-                       M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
-                       M_ATST(REG_ATMP1);
-                       M_BNE(2);
-                       M_TRAP(TRAP_NullPointerException);
+                       break;
+#endif /* SOFTFLOAT */
+               case TYPE_ADR:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                               M_ALD(var->vv.regoff, REG_SP, cd->stackframesize + s1 + 4);
+                               } else {                             /* stack-arg -> spilled  */
+                               M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + s1 + 4);
+                               M_AST(REG_ATMP1, REG_SP, var->vv.regoff);
+                       }
+                       break;
+               default: assert(0);
                }
+       } /* end for argument out of stack*/
+}
 
-               M_AST(REG_ATMP1, REG_SP, rd->memuse * 8);
-               M_AST(REG_ATMP1, REG_SP, 0 * 4);
-               M_JSR_IMM(LOCK_monitor_enter);
-       }
-#endif
 
-       }
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int32_t p;
+       int i;
 
-       /* create replacement points */
-       REPLACEMENT_POINTS_INIT(cd, jd);
+       // Get required compiler data.
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
-       /* foreach basic block */
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-       
-       bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
+       p = cd->stackframesize;
 
-       if (bptr->flags >= BBREACHED)   {
-       
-       /* branch resolving */
-       codegen_resolve_branchrefs(cd, bptr);
+       /* restore return address */
 
-       /* handle replacement points */
-       REPLACEMENT_POINT_BLOCK_START(cd, bptr);
+#if 0
+       if (!code_is_leafmethod(code)) {
+               /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
+                  may have a displacement overflow. */
 
-#if defined(ENABLE_PROFILING)
-       assert(0);
+               M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
+               M_MTLR(REG_ITMP1);
+       }
 #endif
-       /* FIXME there are still some constrcuts to copy in here */
 
-#if defined(ENABLE_LSRA)
-       assert(0);
-#endif
+       /* restore saved registers */
 
-       /* copy interface registers to their destination */
-       len = bptr->indepth;
-       MCODECHECK(64+len);
-
-       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_ATMP1_XPTR);
-                       M_ADRMOVE(REG_ATMP1_XPTR, d);
-                       emit_store(jd, NULL, var, d);
-               }
-               else {
-                       assert((var->flags & INOUT));
-               }
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p-=8; M_ILD(rd->savintregs[i], REG_SP, p);
        }
+       for (i = ADR_SAV_CNT - 1; i >= rd->savadrreguse; --i) {
+               p-=8; M_ALD(rd->savadrregs[i], REG_SP, p);
+       }
+#if !defined(ENABLE_SOFTFLOAT)
+       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+               p-=8; M_FLOAD(rd->savfltregs[i], REG_SP, p);
+       }
+#endif
 
-       /* walk through all instructions */
-       len = bptr->icount;
-       currentline = 0;
-
-       for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
-               if (iptr->line != currentline) {
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       currentline = iptr->line;
-               }
-
-               MCODECHECK(1024);                         /* 1kB should be enough */
-
-               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);
-                       linenumbertable_list_entry_add_intern(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_INLINE_END:
-
-                       linenumbertable_list_entry_add_inline(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+       /* deallocate stack */
+       M_AADD_IMM(cd->stackframesize, REG_SP);
+       M_RET;
+}
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
-                       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;
+
+       switch (iptr->opc) {
 
                /* CONST **************************************************************/
-               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       M_IMOV_IMM(iptr->sx.val.i, d);
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
-               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
-
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       LCONST(iptr->sx.val.l, d);
-                       emit_store_dst(jd, iptr, d);
-                       break;
 
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
@@ -876,9 +758,9 @@ 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_FTMP2);
-                       M_FLTMOVE(s2, REG_FTMP2);
+                       emit_fmove(cd, s2, REG_FTMP2);
                        M_FMUL(s1, REG_FTMP2);
-                       M_FLTMOVE(REG_FTMP2, d);
+                       emit_fmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -886,9 +768,9 @@ 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_FTMP2);
-                       M_DBLMOVE(s2, REG_FTMP2);
+                       emit_dmove(cd, s2, REG_FTMP2);
                        M_DMUL(s1, REG_FTMP2);
-                       M_DBLMOVE(REG_FTMP2, d);
+                       emit_dmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -896,9 +778,9 @@ 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_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_FDIV(s2, REG_FTMP1);
-                       M_FLTMOVE(REG_FTMP1, d);
+                       emit_fmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -906,9 +788,9 @@ 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_DBLMOVE(s1, REG_FTMP1);
+                       emit_dmove(cd, s1, REG_FTMP1);
                        M_DDIV(s2, REG_FTMP1);
-                       M_DBLMOVE(REG_FTMP1, d);
+                       emit_dmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -916,9 +798,9 @@ 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_FTMP2);
-                       M_FLTMOVE(s2, REG_FTMP2);
+                       emit_fmove(cd, s2, REG_FTMP2);
                        M_FADD(s1, REG_FTMP2);
-                       M_FLTMOVE(REG_FTMP2, d);
+                       emit_fmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -926,9 +808,9 @@ 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_FTMP2);
-                       M_DBLMOVE(s2, REG_FTMP2);
+                       emit_dmove(cd, s2, REG_FTMP2);
                        M_DADD(s1, REG_FTMP2);
-                       M_DBLMOVE(REG_FTMP2, d);
+                       emit_dmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -936,9 +818,9 @@ 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_FTMP2);
-                       M_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_FSUB(s2, REG_FTMP1);
-                       M_FLTMOVE(REG_FTMP1, d);
+                       emit_fmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -946,9 +828,9 @@ 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_FTMP2);
-                       M_DBLMOVE(s1, REG_FTMP1);
+                       emit_dmove(cd, s1, REG_FTMP1);
                        M_DSUB(s2, REG_FTMP1);
-                       M_DBLMOVE(REG_FTMP1, d);
+                       emit_dmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -982,29 +864,6 @@ bool codegen_emit(jitdata *jd)
 
                #endif
 
-               /* 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;
-
 
                case ICMD_ACONST:     /* ...  ==> ..., constant                       */
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -1022,83 +881,13 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
-                       M_ADRMOVE(s1, REG_ATMP1_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 */
                        M_JSR_PCREL(2);                         /* get current PC */
                        M_APOP(REG_ATMP2);              
 
                        M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
                        M_JMP(REG_ATMP3);
-                       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 ==> ...                         */
-               case ICMD_IFNONNULL:
-                       assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
-                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
-                       M_ATST(s1);
-                       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);
-                       assert (VAROP(iptr->s1)->type == TYPE_INT);
-                       M_ICMP_IMM(iptr->sx.val.i, s1); 
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
-                       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_ICMP(s2, s1);
-                       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_ATMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ATMP2);
-                       M_ACMP(s1, s2);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
-                       break;
-
-
                /* MEMORY *************************************************************/
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
@@ -1316,15 +1105,6 @@ bool codegen_emit(jitdata *jd)
                        }
                        break;
 
-               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
-                       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_ATMP1);
@@ -1605,172 +1385,81 @@ bool codegen_emit(jitdata *jd)
 
                /* METHOD INVOCATION *********************************************************/
                case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
-
                        bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto gen_method;
+                       if (bte->stub == NULL)
+                               disp = (ptrint) bte->fp;
+                       else
+                               disp = (ptrint) bte->stub;
+                       M_JSR_IMM(disp);
+                       break;
 
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
                case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+                       /* adress register for sure */
+                       M_ALD(REG_ATMP1, REG_SP, 0);
+                       emit_nullpointer_check(cd, iptr, REG_ATMP1);
+                       /* 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;
-                       }
-                       else {
+                               patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, 0);
+                               disp = 0;
+                               M_AMOV_IMM(disp, REG_ATMP1);
+                       } else  {
                                lm = iptr->sx.s23.s3.fmiref->p.method;
-                               um = NULL;
-                               md = lm->parseddesc;
+                               disp = lm->stubroutine;
+                               M_AMOV_IMM(disp, REG_ATMP1);
                        }
-       gen_method:
-                       s3 = md->paramcount;
-       
-                       MCODECHECK((s3 << 1) + 64);
 
-                       /* copy arguments to stack */
-                       for (s3 = s3 - 1; s3 >= 0; s3--)        {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               /* already preallocated */
-                               if (var->flags & PREALLOC) continue;
-               
-                               if (!md->params[s3].inmemory) assert(0);
+                       /* generate the actual call */
+                       M_JSR(REG_ATMP1);
+                       break;
 
-                               switch (var->type)      {
-#if defined(ENABLE_SOFTFLOAT)
-                                       case TYPE_DBL:
-#endif
-                                       case TYPE_LNG:
-                                               d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                               M_LST(d, REG_SP, md->params[s3].regoff);
-                                               break;
-#if defined(ENABLE_SOFTFLOAT)
-                                       case TYPE_FLT:
-#endif
-                                       case TYPE_INT:
-                                               d = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_IST(d, REG_SP, md->params[s3].regoff);
-                                               break;
-                                       case TYPE_ADR:
-                                               d = emit_load(jd, iptr, var, REG_ATMP1);
-                                               M_AST(d, REG_SP, md->params[s3].regoff);
-                                               break;
-#if !defined(ENABLE_SOFTFLOAT)
-                                       case TYPE_FLT:
-                                               d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_FST(d, REG_SP, md->params[s3].regoff);
-                                               break;
-                                       case TYPE_DBL:
-                                               d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_DST(d, REG_SP, md->params[s3].regoff);
-                                               break;
-#endif
-                                       default:
-                                               assert(0);
-                               }
+               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);
+                               s1 = 0;
+                       } else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
                        }
+                       /* load object pointer (==argument 0) */
+                       M_ALD(REG_ATMP1, REG_SP, 0);
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_ATMP3, REG_METHODPTR, s1);
+                       /* generate the actual call */
+                       M_JSR(REG_ATMP3);
+                       break;
 
-                       /* arguments in place now */
-                       switch(iptr->opc)       {
-                               case ICMD_BUILTIN:
-                                       if (bte->stub == NULL)
-                                               disp = (ptrint) bte->fp;
-                                       else
-                                               disp = (ptrint) bte->stub;
-                                       d = md->returntype.type;
-                                       M_JSR_IMM(disp);
-
-                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                                       break;
-
-                               case ICMD_INVOKESPECIAL: 
-                                       /* adress register for sure */
-                                       M_ALD(REG_ATMP1, REG_SP, 0);
-                                       emit_nullpointer_check(cd, iptr, REG_ATMP1);
-                                       /* fall through */
-                               case ICMD_INVOKESTATIC: 
-                                       if (lm == NULL) {
-                                               patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, 0);
-                                               disp = 0;
-                                               M_AMOV_IMM(disp, REG_ATMP1);
-                                       } else  {
-                                               disp = lm->stubroutine;
-                                               M_AMOV_IMM(disp, REG_ATMP1);
-                                       }
-
-                                       /* generate the actual call */
-                                       M_JSR(REG_ATMP1);
-                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                                       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;
-                                       }
-                                       /* load object pointer (==argument 0) */
-                                       M_ALD(REG_ATMP1, REG_SP, 0);
-                                       /* implicit null-pointer check */
-                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
-                                       M_ALD(REG_ATMP3, REG_METHODPTR, s1);
-                                       /* generate the actual call */
-                                       M_JSR(REG_ATMP3);
-                                       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->clazz->index;
-                                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                                       }
-                                       /* load object pointer (==argument 0) */
-                                       M_ALD(REG_ATMP1, REG_SP, 0);
+               case ICMD_INVOKEINTERFACE:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                                       /* implicit null-pointer check */
-                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
-                                       M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
-                                       M_ALD(REG_ATMP3, REG_METHODPTR, s2);
+                               s1 = 0;
+                               s2 = 0;
+                       } else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
+                       }
+                       /* load object pointer (==argument 0) */
+                       M_ALD(REG_ATMP1, REG_SP, 0);
 
-                                       /* generate the actual call */
-                                       M_JSR(REG_ATMP3);
-                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                                       break;
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+                       M_ALD(REG_ATMP3, REG_METHODPTR, s2);
 
-                               default: assert(0);
-                               }       /* switch (iptr->opc) */
+                       /* generate the actual call */
+                       M_JSR(REG_ATMP3);
+                       break;
 
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
-                               
-                               /* store return value */
-                               d = md->returntype.type;
+XXXXXX
 
                                switch (d)      {
-                                       case TYPE_VOID: break;
-#if defined(ENABLE_SOFTFLOAT)
-                                       case TYPE_FLT:
-#endif
-                                       case TYPE_INT:
-                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                               M_INTMOVE(REG_RESULT, s1);
-                                               break;
-#if defined(ENABLE_SOFTFLOAT)
-                                       case TYPE_DBL:
-#endif
-                                       case TYPE_LNG:
-                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
-                                               M_LNGMOVE(REG_RESULT_PACKED, s1);
-                                               break;
                                        case TYPE_ADR:
                                                s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
                                                /* all stuff is returned in %d0 */
@@ -1786,7 +1475,7 @@ bool codegen_emit(jitdata *jd)
                                                if (iptr->opc == ICMD_BUILTIN)  {
                                                        M_INT2FLTMOVE(REG_FRESULT, s1);
                                                } else  {
-                                                       M_FLTMOVE(REG_FRESULT, s1);
+                                                       emit_fmove(cd, REG_FRESULT, s1);
                                                }
                                                break;
                                        case TYPE_DBL:
@@ -1795,172 +1484,13 @@ bool codegen_emit(jitdata *jd)
                                                        M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 4 + 4);
                                                        M_DLD(s1, REG_SP, rd->memuse * 4 + 4);
                                                } else  {
-                                                       M_DBLMOVE(REG_FRESULT, s1);
+                                                       emit_dmove(cd, REG_FRESULT, s1);
                                                }
                                                break;
 #endif
-                                       default:
-                                               assert(0);
                                }
-                               if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
-                       break; /* ICMD_INVOKE* */
 
-#if defined(ENABLE_SOFTFLOAT)
-               case ICMD_FRETURN:
-#endif
-               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);
-                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
-                       M_ADR2INTMOVE(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;
-
-#if defined(ENABLE_SOFTFLOAT)
-               case ICMD_DRETURN:
-#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 nowperformreturn;
-
-#if !defined(ENABLE_SOFTFLOAT)
-               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       M_FLTMOVE(s1, REG_FRESULT);
-                       goto nowperformreturn;
-
-               case ICMD_DRETURN:
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       M_DBLMOVE(s1, REG_FRESULT);
-                       goto nowperformreturn;
-
-#endif
-
-               case ICMD_RETURN:      /* ...  ==> ...                                */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-nowperformreturn:
-                       {
-                       s4 i, p;
-                       
-                       p = cd->stackframesize;
-
-                       /* call trace function */
-#if !defined(NDEBUG)
-                       emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
-                       /* call lock_monitor_exit */
-                       if (checksync && code_is_synchronized(code)) {
-                               M_ILD(REG_ITMP3, REG_SP, rd->memuse * 8);
-
-                               /* we need to save the proper return value */
-                               /* we do not care for the long -> doubel convert space here */
-                               switch (iptr->opc) {
-#if defined(ENABLE_SOFTFLOAT)
-                               case ICMD_DRETURN:
-#endif
-                               case ICMD_LRETURN:
-                                       M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#if defined(ENABLE_SOFTFLOAT)
-                               case ICMD_FRETURN:
-#endif
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#if !defined(ENABLE_SOFTFLOAT)
-                               case ICMD_FRETURN:
-                                       M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#endif
-                               }
-
-                               M_IST(REG_ITMP3, REG_SP, 0 * 4);
-                               M_JSR_IMM(LOCK_monitor_exit);
-
-                               /* and now restore the proper return value */
-                               switch (iptr->opc) {
-
-#if defined(ENABLE_SOFTFLOAT)
-                               case ICMD_DRETURN:
-#endif
-                               case ICMD_LRETURN:
-                                       M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#if defined(ENABLE_SOFTFLOAT)
-                               case ICMD_FRETURN:
-#endif
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#if !defined(ENABLE_SOFTFLOAT)
-                               case ICMD_FRETURN:
-                                       M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-#endif
-                               }
-                       }
-#endif
-
-
-                       /* restore return address                                         */
-#if 0
-                       if (!code_is_leafmethod(code)) {
-                               /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
-                                  may have a displacement overflow. */
-
-                               M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
-                               M_MTLR(REG_ITMP1);
-                       }
-#endif
-                       /* restore saved registers                                        */
-
-                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
-                               p-=8; M_ILD(rd->savintregs[i], REG_SP, p);
-                       }
-                       for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
-                               p-=8; M_ALD(rd->savadrregs[i], REG_SP, p);
-                       }
-#if !defined(ENABLE_SOFTFLOAT)
-                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
-                               p-=8; M_FLOAD(rd->savfltregs[i], REG_SP, p);
-                       }
-#endif
-                       /* deallocate stack                                               */
-                       M_AADD_IMM(cd->stackframesize, REG_SP);
-                       M_RET;
-                       }
-                       break;
+XXXXXXX
 
                /* the evil ones */
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
@@ -2257,29 +1787,6 @@ 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) {
-                               M_ICMP_IMM(lookup->value, s1);
-                               emit_beq(cd, lookup->target.block);
-                               lookup++;
-                       }
-
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       ALIGNCODENOP;
-                       break;
-                       }
-
                case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
 
                        /* check for negative sizes and copy sizes to stack if necessary  */
@@ -2327,34 +1834,11 @@ nowperformreturn:
 
 
                default:
-                       printf("UNKNOWN OPCODE %d\n", iptr->opc);
-                       exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
-                       return false;
+                       vm_abort("Unknown ICMD %d during code generation", iptr->opc);
        } /* switch */
-       /* M_TPF; */ /* nop after each ICMD */
-       } /* for each instruction */
-
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr) {
-                       M_NOP;
-               }
-       }
-
-
-       } /* if (btpre->flags >= BBREACHED) */
-       } /* for each basic block */
-
-       /* generate stubs */
-       emit_patcher_traps(jd);
-
-       return true;
 }
 
+
 /* codegen_emit_stub_native ****************************************************
 
    Emits a stub routine which calls a native method.
index 0cb13d0fa215b61b8bb80eb7088e1586b4c96466..b9cdc12c2ef364200677807b78827164f3598f27 100644 (file)
 #define M_INEG(a)              OPWORD(0x112, 0, (a))                                           /* neg.l */
 #define M_INEGX(a)             OPWORD(0x102, 0, (a))                                           /* neg.l */
 
-/* only generate opcode when condition true */
-#define OPWORD_COND(c, u,v,w)  \
-       do { \
-               if ( (c) ) { OPWORD( (u),(v),(w) ) }  \
-       } while(0);
-#define OPWORD_IMM16_COND(c, u,v,w,x)  \
-       do { \
-               if ( (c) ) { OPWORD_IMM16( (u),(v),(w),(x) ) }  \
-       } while(0);
 /* assert on the opcode */
 #define OPWORD_ASSERT(a, u,v,w)        \
        do { \
        } while(0);
 
 /* M_XMOVE....M_XMOVE(sourcereg, destreg) */
-#define M_INTMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 0), 0, (a));
-#define M_ADRMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 1), 1, (a));
+#define M_MOV(a,b)                     OPWORD( ( ( 2<<6) | ((b) << 3) | 0), 0, (a));
+#define M_AMOV(a,b)                    OPWORD( ( ( 2<<6) | ((b) << 3) | 1), 1, (a));
 #define M_INT2ADRMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 1), 0, (a));
 #define M_ADR2INTMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 0), 1, (a));
-#define M_LNGMOVE(a,b)         do      {\
-                                       M_INTMOVE(GET_LOW_REG (a), GET_LOW_REG (b));\
-                                       M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b));\
-                               } while(0);
 
 #if !defined(ENABLE_SOFTLFOAT)
-       #define M_FLTMOVE(a,b)          OPWORD_IMM16_COND( ((a)!=(b)), 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x40)
+       #define M_FMOV(a,b)                     OPWORD_IMM16( 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x40)
        #define M_INT2FLTMOVE(a,b)      OPWORD_IMM16( 0x3c8, 0, (a), ((0x11 << 10) | ((b) << 7) | 0x40 )) 
-       #define M_DBLMOVE(a,b)          OPWORD_IMM16_COND( ((a)!=(b)), 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x44)
+       #define M_DMOV(a,b)                     OPWORD_IMM16( 0x3c8, 0, 0, ((a)<<10) | ((b)<<7) | 0x44)
 #endif
 /* M_XTST....M_XTST(register) */
 #define M_ITST(a)              OPWORD(0x12a, 0, (a))                   /* tst.l */
                cd->mcodeptr += 2; \
        } while(0);
 
+#define M_TEST(a)                      M_ATST(a)
+
 
 #if !defined(ENABLE_SOFTFLOAT)
        
index f0e3e5fbe7537981ad48419175ff565d6e923e6c..00b0d5afe87479d126d9f92e832ab86567b1ce53 100644 (file)
@@ -310,6 +310,18 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
        }
        return reg;
 }
+
+
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       M_ICMP_IMM(value, reg);
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -701,6 +713,115 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       // This is a nop, because we do not use a procedure vector.
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       if (m->flags & ACC_STATIC) {
+               M_AMOV_IMM((&m->clazz->object.header), REG_ATMP1);
+       } else  {
+               /* for non-static case the first arg is the object */
+               M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
+               M_ATST(REG_ATMP1);
+               M_BNE(2);
+               M_TRAP(TRAP_NullPointerException);
+       }
+
+       M_AST(REG_ATMP1, REG_SP, syncslot_offset);
+       M_AST(REG_ATMP1, REG_SP, 0 * 4);
+       M_JSR_IMM(LOCK_monitor_enter);
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       M_ILD(REG_ITMP3, REG_SP, syncslot_offset);
+
+       /* we need to save the proper return value */
+       /* we do not care for the long -> doubel convert space here */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+#if defined(ENABLE_SOFTFLOAT)
+       case TYPE_DBL:
+#endif
+       case TYPE_LNG:
+               M_LST(REG_RESULT_PACKED, REG_SP, syncslot_offset + 8);
+               break;
+#if defined(ENABLE_SOFTFLOAT)
+       case TYPE_FLT:
+#endif
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+#if !defined(ENABLE_SOFTFLOAT)
+       case TYPE_FLT:
+               M_FST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+#endif
+       }
+
+       M_IST(REG_ITMP3, REG_SP, 0 * 4);
+       M_JSR_IMM(LOCK_monitor_exit);
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+
+#if defined(ENABLE_SOFTFLOAT)
+       case TYPE_DBL:
+#endif
+       case TYPE_LNG:
+               M_LLD(REG_RESULT_PACKED, REG_SP, syncslot_offset + 8);
+               break;
+#if defined(ENABLE_SOFTFLOAT)
+       case TYPE_FLT:
+#endif
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+#if !defined(ENABLE_SOFTFLOAT)
+       case TYPE_FLT:
+               M_FLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+#endif
+       }
+}
+#endif
+
 
 /*
  * These are local overrides for various environment variables in Emacs.
index 5514cc4b885b87ba0c3d5111058a262d8010f7d7..63c9eb626c18b4d534a07e7196dd61adfb3dfbe5 100644 (file)
 #include "vm/jit/methodtree.h"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On M68K we use 8-byte stackslots.
+#error Verify the below line, then remove this error!
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 37b90494bebef6b0e88e36f2699750bb54179f43..6f6cad855e203a893438580ce2f7ce998fb44ed9 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           (2*4) /* bytes */
index 29e3a4137b9b2540c30d322f225fffcd8a8ca69e..cf207a347b1c06c9ed197af441edacd916ae05fb 100644 (file)
@@ -57,7 +57,6 @@
 #include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 
 bool codegen_emit(jitdata *jd)
 {
-       methodinfo         *m;
-       codeinfo           *code;
-       codegendata        *cd;
-       registerdata       *rd;
-       s4                  len, s1, s2, s3, d, disp;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       u2                  currentline;
-       constant_classref  *cr;
-       unresolved_class   *uc;
-       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 */
-
-       s1          = 0;
-       d           = 0;
-       fieldtype   = 0;
-       lm          = NULL;
-       um          = NULL;
-       bte         = NULL;
-       currentline = 0;
-       uf          = NULL;
-
-       {
-       s4 i, p, t, l;
-       s4 savedregs_num;
 
        savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the RA */
 
-       /* 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 */
@@ -142,22 +95,39 @@ bool codegen_emit(jitdata *jd)
        if (cd->stackframesize & 1)
                cd->stackframesize++;
 
-       /* create method header */
 
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
 
-       code->synchronizedoffset = rd->memuse * 8;
 
-       /* REMOVEME: We still need it for exception handling in assembler. */
 
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
 
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Generates machine code for the method prolog.
+ */
+void codegen_emit_prolog(jitdata* jd)
+{
+       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) */
 
@@ -237,9 +207,9 @@ bool codegen_emit(jitdata *jd)
                        if (!md->params[p].inmemory) {
                                if (!(var->flags & INMEMORY)) {
                                        if (IS_2_WORD_TYPE(t))
-                                               M_DBLMOVE(s1, var->vv.regoff);
+                                               emit_dmove(cd, s1, var->vv.regoff);
                                        else
-                                               M_FLTMOVE(s1, var->vv.regoff);
+                                               emit_fmove(cd, s1, var->vv.regoff);
                                }
                                else {
                                        if (IS_2_WORD_TYPE(t))
@@ -260,181 +230,88 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-       /* call monitorenter function */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse;
-
-# if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_AST(abi_registers_integer_argument[p], REG_SP, p * 8);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
 
-                       s1 += INT_ARG_CNT + FLT_ARG_CNT;
-               }
-# endif
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int32_t p;
+       int i;
 
-               /* get correct lock object */
+       // Get required compiler data.
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
-               if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->clazz->object.header);
-                       M_ALD(REG_A0, REG_PV, disp);
-                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-               }
-               else {
-/*                     emit_nullpointer_check(cd, iptr, REG_A0); */
-                       M_BNEZ(REG_A0, 2);
-                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-                       M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
-               }
-
-               M_JSR(REG_RA, REG_ITMP3);
-               M_AST(REG_A0, REG_SP, s1 * 8);                        /* branch delay */
+       p = cd->stackframesize;
 
-# if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_ALD(abi_registers_integer_argument[p], REG_SP, p * 8);
+       /* restore return address */
 
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+       if (!code_is_leafmethod(code)) {
+               p--; M_ALD(REG_RA, REG_SP, p * 8);
+       }
 
+       /* restore saved registers */
 
-                       M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
-               }
-# endif
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_ALD(rd->savintregs[i], REG_SP, p * 8);
        }
-#endif
+       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+               p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
        }
 
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
-
-       /* end of header generation */
-
-       /* create replacement points */
-
-       REPLACEMENT_POINTS_INIT(cd, jd);
+       /* deallocate stack and return */
 
-       /* walk through all basic blocks */
+       if (cd->stackframesize) {
+               int32_t lo, hi;
 
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               disp = cd->stackframesize * 8;
+               lo = (short) (disp);
+               hi = (short) (((disp) - lo) >> 16);
 
-               /* handle replacement points */
-
-               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
-
-               /* store relative start of block */
-
-               bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
-
-               if (bptr->flags >= BBREACHED) {
-                       /* branch resolving */
-
-                       codegen_resolve_branchrefs(cd, bptr);
-
-               /* copy interface registers to their destination */
-
-               len = bptr->indepth;
-               MCODECHECK(64+len);
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-               while (len) {
-                       len--;
-                       src = bptr->invars[len];
-                       if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
-                                       /*                              d = reg_of_var(m, src, REG_ITMP1); */
-                                       if (!(src->flags & INMEMORY))
-                                               d = src->vv.regoff;
-                                       else
-                                               d = REG_ITMP1;
-                                       M_INTMOVE(REG_ITMP1, d);
-                                       emit_store(jd, NULL, src, d);
-                               }
-                       }
+               if (hi == 0) {
+                       M_RET(REG_RA);
+                       M_AADD_IMM(REG_SP, lo, REG_SP);             /* delay slot */
                } else {
-#endif
-               while (len) {
-                       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));
-                       }
+                       M_LUI(REG_ITMP3,hi);
+                       M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3);
+                       M_RET(REG_RA);
+                       M_AADD(REG_ITMP3,REG_SP,REG_SP);            /* delay slot */
                }
-#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) {
-                               linenumbertable_list_entry_add(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);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_INLINE_END:
-
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
+       } else {
+               M_RET(REG_RA);
+               M_NOP;
+       }
+}
 
-               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;
+
+       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                       */
 
 #if SIZEOF_VOID_P == 8
@@ -467,7 +344,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr   = iptr->sx.val.c.ref;
+                               constant_classref *cr = iptr->sx.val.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
                                patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
@@ -487,29 +364,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/copy/move operations ************************************/
-
-               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_LLOAD:
-               case ICMD_ALOAD:
-               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                 */
@@ -2245,17 +2099,6 @@ 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)) {
-                               uc = iptr->sx.s23.s2.uc;
-
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
                        // Some processor implementations seem to have a problem when using
                        // the JALR instruction with (reg_dest == reg_src), so avoid that.
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
@@ -2264,117 +2107,72 @@ bool codegen_emit(jitdata *jd)
                        M_NOP;
                        M_NOP;              /* nop ensures that XPC is less than the end */
                                            /* of basic block                            */
-                       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 ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_beqz(cd, iptr->dst.block, s1);
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               emit_beq(cd, iptr->dst.block, s1, REG_ITMP2);
-                       }
+                       ICONST(REG_ITMP2, iptr->sx.val.i);
+                       emit_beq(cd, iptr->dst.block, s1, REG_ITMP2);
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bltz(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
+                               M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_blez(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
+                               M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
-                               }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
-                               }
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        }
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bnez(cd, iptr->dst.block, s1);
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               emit_bne(cd, iptr->dst.block, s1, REG_ITMP2);
-                       }
+                       ICONST(REG_ITMP2, iptr->sx.val.i);
+                       emit_bne(cd, iptr->dst.block, s1, REG_ITMP2);
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bgtz(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
+                               M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
-                               }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
-                               }
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        }
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0)
-                               emit_bgez(cd, iptr->dst.block, s1);
+                       if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
+                               M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
                        else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
-                                       M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                               }
-                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                        }
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
@@ -2588,8 +2386,6 @@ bool codegen_emit(jitdata *jd)
 #endif
                        break;
 
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
 #if SIZEOF_VOID_P == 8
                case ICMD_IF_LCMPEQ:
 #endif
@@ -2613,8 +2409,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 #endif
 
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
 #if SIZEOF_VOID_P == 8
                case ICMD_IF_LCMPNE:
 #endif
@@ -2749,171 +2543,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 #endif
 
-               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
-#if SIZEOF_VOID_P == 8
-               case ICMD_LRETURN:
-#endif
-
-                       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)) {
-                               uc = iptr->sx.s23.s2.uc;
-
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-                       goto nowperformreturn;
-
-#if SIZEOF_VOID_P == 4
-               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
-
-                       s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
-                       M_LNGMOVE(s1, REG_RESULT_PACKED);
-                       goto nowperformreturn;
-#endif
-
-           case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       M_FLTMOVE(s1, REG_FRESULT);
-                       goto nowperformreturn;
-
-           case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       M_DBLMOVE(s1, REG_FRESULT);
-                       goto nowperformreturn;
-
-               case ICMD_RETURN:      /* ...  ==> ...                                */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-nowperformreturn:
-                       {
-                       s4 i, p;
-                       
-                       p = cd->stackframesize;
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-
-                               /* we need to save the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-#if SIZEOF_VOID_P == 8
-                               case ICMD_LRETURN:
-#endif
-                                       M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-                                       M_JSR(REG_RA, REG_ITMP3);
-                                       M_AST(REG_RESULT, REG_SP, rd->memuse * 8);  /* delay slot */
-                                       break;
-#if SIZEOF_VOID_P == 4
-                               case ICMD_LRETURN:
-                                       M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-                                       M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8);
-                                       M_JSR(REG_RA, REG_ITMP3);
-                                       M_NOP;
-                                       break;
-#endif
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-                                       M_JSR(REG_RA, REG_ITMP3);
-                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
-                                       break;
-                               case ICMD_RETURN:
-                                       M_JSR(REG_RA, REG_ITMP3);
-                                       M_ALD(REG_A0, REG_SP, rd->memuse * 8); /* delay*/
-                                       break;
-                               }
-
-                               /* and now restore the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-#if SIZEOF_VOID_P == 8
-                               case ICMD_LRETURN:
-#endif
-                                       M_ALD(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-#if SIZEOF_VOID_P == 4
-                               case ICMD_LRETURN:
-                                       M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8);
-                                       break;
-#endif
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore return address                                         */
-
-                       if (!code_is_leafmethod(code)) {
-                               p--; M_ALD(REG_RA, REG_SP, p * 8);
-                       }
-
-                       /* restore saved registers                                        */
-
-                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
-                               p--; M_ALD(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 and return                                    */
-
-                       if (cd->stackframesize) {
-                               s4 lo, hi;
-
-                               disp = cd->stackframesize * 8;
-                               lo = (short) (disp);
-                               hi = (short) (((disp) - lo) >> 16);
-
-                               if (hi == 0) {
-                                       M_RET(REG_RA);
-                                       M_AADD_IMM(REG_SP, lo, REG_SP);             /* delay slot */
-                               } else {
-                                       M_LUI(REG_ITMP3,hi);
-                                       M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3);
-                                       M_RET(REG_RA);
-                                       M_AADD(REG_ITMP3,REG_SP,REG_SP);            /* delay slot */
-                               }
-
-                       } else {
-                               M_RET(REG_RA);
-                               M_NOP;
-                       }
-
-                       ALIGNCODENOP;
-                       }
-                       break;
-
-
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -2963,249 +2592,113 @@ nowperformreturn:
                        ALIGNCODENOP;
                        break;
 
+               case ICMD_BUILTIN:
+                       bte = iptr->sx.s23.s3.bte;
+                       if (bte->stub == NULL) {
+                               disp = dseg_add_functionptr(cd, bte->fp);
+                               M_ALD(REG_ITMP3, REG_PV, disp);  /* built-in-function pointer */
 
-               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);
+                               /* generate the actual call */
 
-                       while (--i >= 0) {
-                               ICONST(REG_ITMP2, lookup->value);
-                               emit_beq(cd, lookup->target.block, s1, REG_ITMP2);
-                               ++lookup;
-                       }
+                               /* TWISTI: i actually don't know the reason for using
+                                  REG_ITMP3 here instead of REG_PV. */
 
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       ALIGNCODENOP;
-                       break;
+                               M_JSR(REG_RA, REG_ITMP3);
+                               M_NOP;
                        }
+                       else {
+                               disp = dseg_add_functionptr(cd, bte->stub);
+                               M_ALD(REG_PV, REG_PV, disp);          /* method pointer in pv */
 
+                               /* generate the actual call */
 
-               case ICMD_BUILTIN:      /* ..., arg1 ==> ...                          */
-
-                       bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto gen_method;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                       }
+                       break;
 
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+               case ICMD_INVOKESPECIAL:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
+                       /* fall through */
 
+               case ICMD_INVOKESTATIC:
                        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);          /* method pointer in pv */
 
-                       MCODECHECK((s3 << 1) + 64);
+                       /* generate the actual call */
 
-                       /* copy arguments to registers or stack location                  */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
+                       M_JSR(REG_RA, REG_PV);
+                       M_NOP;
+                       break;
 
-                               if (var->flags & PREALLOC)
-                                       continue;
+               case ICMD_INVOKEVIRTUAL:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
 
-                               if (IS_INT_LNG_TYPE(var->type)) {
-#if SIZEOF_VOID_P == 8
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               M_INTMOVE(s1, d);
-                                       }
-                                       else  {
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_LST(s1, REG_SP, d);
-                                       }
-#else
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
 
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_LNGMOVE(s1, d);
-                                               else
-                                                       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);
-                                               }
-                                       }
-#endif
-                               }
-                               else {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DBLMOVE(s1, d);
-                                               else
-                                                       M_FLTMOVE(s1, d);
-                                       }
-                                       else {
-                                               s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(s1, REG_SP, d);
-                                               else
-                                                       M_FST(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);
-                                       M_ALD(REG_ITMP3, REG_PV, disp);  /* built-in-function pointer */
-
-                                       /* generate the actual call */
-
-                                       /* TWISTI: i actually don't know the reason for using
-                                          REG_ITMP3 here instead of REG_PV. */
-
-                                       M_JSR(REG_RA, REG_ITMP3);
-                                       M_NOP;
-                               }
-                               else {
-                                       disp = dseg_add_functionptr(cd, bte->stub);
-                                       M_ALD(REG_PV, REG_PV, disp);          /* method pointer in pv */
-
-                                       /* generate the actual call */
-
-                                       M_JSR(REG_RA, REG_PV);
-                                       M_NOP;
-                               }
-
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               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);          /* method pointer in pv */
-
-                               /* generate the actual call */
-
-                               M_JSR(REG_RA, REG_PV);
-                               M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               break;
-
-                       case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
-                               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);
 
-                               /* 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 */
 
-                               /* generate the actual call */
-
-                               M_JSR(REG_RA, REG_PV);
-                               M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               break;
+                       M_JSR(REG_RA, REG_PV);
+                       M_NOP;
+                       break;
 
-                       case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
+               case ICMD_INVOKEINTERFACE:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
 
-                               if (lm == NULL) {
-                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                                       s1 = 0;
-                                       s2 = 0;
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->clazz->index;
+                               s1 = 0;
+                               s2 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr*) * lm->clazz->index;
 
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
+                       }
 
-                               /* 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);
+                       /* 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);
 
-                               /* generate the actual call */
+                       /* generate the actual call */
 
-                               M_JSR(REG_RA, REG_PV);
-                               M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                               M_LDA(REG_PV, REG_RA, -disp);
-                               break;
-                       }
+                       M_JSR(REG_RA, REG_PV);
+                       M_NOP;
+                       break;
 
-                       /* store return value */
 
-                       d = md->returntype.type;
 
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-#if SIZEOF_VOID_P == 8
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                       M_INTMOVE(REG_RESULT, s1);
-#else
-                                       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);
-                                       }
-#endif
-                               }
+XXX
                                else {
                                        s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
                                        if (IS_2_WORD_TYPE(d))
@@ -3240,7 +2733,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
 
                                        patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
@@ -3255,7 +2748,7 @@ gen_method:
 
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
-                                               cr = iptr->sx.s23.s3.c.ref;
+                                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
 
                                                patcher_add_patch_ref(jd, PATCHER_checkcast_interface,
                                                                                          cr, 0);
@@ -3287,7 +2780,7 @@ gen_method:
                                        if (super == NULL) {
                                                emit_label(cd, BRANCH_LABEL_2);
 
-                                               cr   = iptr->sx.s23.s3.c.ref;
+                                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
                                                patcher_add_patch_ref(jd,
@@ -3386,7 +2879,7 @@ gen_method:
                                M_INTMOVE(s1, REG_A0);
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        patcher_add_patch_ref(jd,
@@ -3445,7 +2938,7 @@ gen_method:
                        if (super == NULL) {
                                emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
-                               cr   = iptr->sx.s23.s3.c.ref;
+                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
 
                                patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
@@ -3460,7 +2953,7 @@ gen_method:
 
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
-                                       cr = iptr->sx.s23.s3.c.ref;
+                                       constant_classref * iptr->sx.s23.s3.c.ref;
 
                                        patcher_add_patch_ref(jd, PATCHER_instanceof_interface,
                                                                                  cr, 0);
@@ -3492,7 +2985,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label(cd, BRANCH_LABEL_2);
 
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
@@ -3619,7 +3112,7 @@ gen_method:
                        /* is patcher function set? */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr   = iptr->sx.s23.s3.c.ref;
+                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_address(cd, NULL);
 
                                patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
@@ -3656,35 +3149,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 */
-               
-       MCODECHECK(64); /* XXX require smaller number? */
-
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr)
-                       M_NOP;
-       }
-
-       } /* if (bptr -> flags >= BBREACHED) */
-       } /* for basic block */
-
-       /* generate traps */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
index f1819f84887019bfde43a03560182b44a9a74603..8c215be81ac7c56419eedc46eb3c4b6fc7d89cea 100644 (file)
         M_NOP; \
     }
 
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_MOV(a, b); \
-    } while (0)
-
-#if SIZEOF_VOID_P == 8
-
-#define M_LNGMOVE(a,b)    M_INTMOVE(a,b)
-
-#else /* SIZEOF_VOID_P == 8 */
-
-#define M_LNGMOVE(a,b) \
-    do { \
-        if (GET_LOW_REG(b) == GET_HIGH_REG(a)) { \
-            assert(GET_HIGH_REG(b) == GET_LOW_REG(a)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-        } else { \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-        } \
-    } while (0)
-
-#endif /* SIZEOF_VOID_P == 8 */
-
-#define M_FLTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_FMOV(a, b); \
-    } while (0)
-
-#define M_DBLMOVE(a,b) \
-    do { \
-        if ((a) != (b)) \
-            M_DMOV(a, b); \
-    } while (0)
-
 #define ICONST(r,c)                     emit_iconst(cd, (r), (c))
 #define LCONST(r,c)                     emit_lconst(cd, (r), (c))
 
index d2edc03ee94e175423b2c73f808c20a7084e25c1..9798b22226a16f80bd23affb1cbac367af2841c2 100644 (file)
@@ -642,6 +642,152 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       M_LDA(REG_PV, REG_RA, -disp);
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+# if !defined(NDEBUG)
+               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                       M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
+
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_AST(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+                       syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
+               }
+# endif
+
+               /* get correct lock object */
+
+               if (m->flags & ACC_STATIC) {
+                       disp = dseg_add_address(cd, &m->clazz->object.header);
+                       M_ALD(REG_A0, REG_PV, disp);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+               }
+               else {
+/*                     emit_nullpointer_check(cd, iptr, REG_A0); */
+                       M_BNEZ(REG_A0, 2);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
+               }
+
+               M_JSR(REG_RA, REG_ITMP3);
+               M_AST(REG_A0, REG_SP, syncslot_offset);               /* branch delay */
+
+# if !defined(NDEBUG)
+               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_ALD(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+
+                       M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
+               }
+# endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_ALD(REG_ITMP3, REG_PV, disp);
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+#if SIZEOF_VOID_P == 8
+       case TYPE_LNG:
+#endif
+               M_ALD(REG_A0, REG_SP, syncslot_offset);
+               M_JSR(REG_RA, REG_ITMP3);
+               M_AST(REG_RESULT, REG_SP, syncslot_offset);  /* delay slot */
+               break;
+#if SIZEOF_VOID_P == 4
+       case TYPE_LNG:
+               M_ALD(REG_A0, REG_SP, syncslot_offset);
+               M_LST(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               M_JSR(REG_RA, REG_ITMP3);
+               M_NOP;
+               break;
+#endif
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_ALD(REG_A0, REG_SP, syncslot_offset);
+               M_JSR(REG_RA, REG_ITMP3);
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset); /* delay slot */
+               break;
+       default:
+               M_JSR(REG_RA, REG_ITMP3);
+               M_ALD(REG_A0, REG_SP, syncslot_offset); /* delay*/
+               break;
+       }
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+#if SIZEOF_VOID_P == 8
+       case TYPE_LNG:
+#endif
+               M_ALD(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+#if SIZEOF_VOID_P == 4
+       case TYPE_LNG:
+               M_LLD(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               break;
+#endif
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset);
+               break;
+       }
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 100be5e306f3b2fa006624ca76270654f7d09028..67bb24cdc8100045f0c891c2028abf2dc3ddacd5 100644 (file)
 #include "vm/vm.hpp"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On MIPS we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index ea81010678fd9687b4a2c9eedd0dd736e67fdef3..5268c8d75db6ab52a9f728ddef26b8b0e79c0672 100644 (file)
@@ -95,6 +95,7 @@ static void profile_thread(void)
                // Lock the thread lists.
                ThreadList_lock();
 
+#if 0
                /* iterate over all started threads */
 
                for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
@@ -153,6 +154,7 @@ static void profile_thread(void)
                                }
                        }
                }
+#endif
 
                // Unlock the thread lists.
                ThreadList_unlock();
@@ -207,6 +209,7 @@ void profile_printstats(void)
        frequency = 0;
        cycles    = 0;
 
+#if 0
        /* create new method list */
        // TODO Use a sorted container.
        List* l = List_new();
@@ -297,6 +300,7 @@ void profile_printstats(void)
                                           j, code->bbfrequency[j]);
                }
        }
+#endif
 
        printf("-----------           -------------- \n");
        printf("%10d             %12ld\n", frequency, (long) cycles);
index a235afacd4cab06e0c2df9114bb93255b3575fc5..06a672a8049fab6265cd4dc06d92b2b21d871082 100644 (file)
@@ -37,6 +37,50 @@ extern "C" {
 #include "vm/global.h"
 
 
+/* CPU cycle counting macros **************************************************/
+
+#if defined(ENABLE_PROFILING) && defined(__X86_64__)
+
+#define PROFILE_CYCLE_START \
+    do { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+            M_PUSH(RAX); \
+            M_PUSH(RDX); \
+            \
+            M_MOV_IMM(code, REG_ITMP3); \
+            M_RDTSC; \
+            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
+            \
+            M_POP(RDX); \
+            M_POP(RAX); \
+        } \
+    } while (0)
+
+#define PROFILE_CYCLE_STOP \
+    do { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+            M_PUSH(RAX); \
+            M_PUSH(RDX); \
+            \
+            M_MOV_IMM(code, REG_ITMP3); \
+            M_RDTSC; \
+            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
+            \
+            M_POP(RDX); \
+            M_POP(RAX); \
+        } \
+    } while (0)
+
+#else
+
+#define PROFILE_CYCLE_START
+#define PROFILE_CYCLE_STOP
+
+#endif
+
+
 /* function prototypes ********************************************************/
 
 bool profile_init(void);
index e9259c4afe7c44985e96af7cc091e73d4d1cac39..6e0f1fce58f313191cdd64be9082dffd0f1a375c 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
index 53d4a37d852fb23465391fbded2fc451aa089f98..48a1ff2a46a129972b2d1c57ea3a17950654a88a 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* 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;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       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;
-       int                 i;
-
-       /* 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 && code_is_synchronized(code))
-               cd->stackframesize += 2;
-#endif
-
-       /* create method header */
-
-       /* align stack to 16-bytes */
-
-       if (!code_is_leafmethod(code) || JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               ALIGN_2(cd->stackframesize);
-
-       else if (code_is_leafmethod(code) && (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       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
-
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
-
-#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) */
 
@@ -255,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);
                        }
@@ -274,204 +181,76 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-#if defined(ENABLE_THREADS)
-       /* call monitorenter function */
-
-       if (checksync && code_is_synchronized(code)) {
-               /* 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->clazz->object.header);
-                       M_ALD(REG_A0, REG_PV, disp);
-               }
-               else {
-                       M_TST(REG_A0);
-                       M_BNE(1);
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
-               }
+       // 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) {
-                               linenumbertable_list_entry_add(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);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
+       /* deallocate stack */
 
-               case ICMD_INLINE_END:
+       if (cd->stackframesize)
+               M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(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);
@@ -508,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                 */
@@ -1208,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;
                                        
@@ -1255,15 +1010,6 @@ bool codegen_emit(jitdata *jd)
 
                /* 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);
@@ -1482,97 +1228,16 @@ bool codegen_emit(jitdata *jd)
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
-
+#if 0
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
-                       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);
-                       }
-                       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->clazz))
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                               fi->clazz, disp);
-                       }
-
-                       M_ALD(REG_ITMP1, REG_PV, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ILD_INTERN(d, REG_ITMP1, 0);
-                               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 */
                                break;
-                       case TYPE_ADR:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ALD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_FLD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:                          
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_DLD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       }
-                       emit_store_dst(jd, iptr, d);
                        break;
-
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-                       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);
-                       }
-                       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->clazz))
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                               fi->clazz, 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;
-
+#endif
 
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
@@ -1677,17 +1342,6 @@ 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);
@@ -1702,20 +1356,6 @@ bool codegen_emit(jitdata *jd)
                                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 ==> ...                         */
@@ -1726,24 +1366,6 @@ 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);
@@ -1900,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);
@@ -2003,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 && code_is_synchronized(code)) {
-                               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 (!code_is_leafmethod(code)) {
-                               /* 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;
@@ -2175,251 +1651,96 @@ 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:
-                       i = md->paramcount;
-
-                       MCODECHECK((i << 1) + 64);
-
-                       /* Copy arguments to registers or stack location. */
-
-                       for (i = i - 1; i >= 0; i--) {
-                               var = VAR(iptr->sx.s23.s2.args[i]);
-                               d   = md->params[i].regoff;
-
-                               /* Already pre-allocated? */
+                       M_ALD(REG_PV, REG_PV, disp);
 
-                               if (var->flags & PREALLOC)
-                                       continue;
+                       /* generate the actual call */
 
-                               if (!md->params[i].inmemory) {
-                                       s1 = emit_load(jd, iptr, var, d);
-
-                                       switch (var->type) {
-                                       case TYPE_INT:
-                                       case TYPE_ADR:
-                                               M_INTMOVE(s1, d);
-                                               break;
+                       M_MTCTR(REG_PV);
+                       M_JSR;
+                       break;
 
-                                       case TYPE_LNG:
-                                               M_LNGMOVE(s1, d);
-                                               break;
+               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);
 
-                                       case TYPE_FLT:
-                                       case TYPE_DBL:
-                                               M_FLTMOVE(s1, d);
-                                               break;
-                                       }
-                               }
-                               else {
-                                       switch (var->type) {
-                                       case TYPE_INT:
-                                       case TYPE_ADR:
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_IST(s1, REG_SP, d);
-                                               break;
-
-                                       case TYPE_LNG:
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                               M_LST(s1, REG_SP, d);
-                                               break;
-
-                                       case TYPE_FLT:
-                                       case TYPE_DBL:
-                                               s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_DST(s1, REG_SP, d);
-                                               break;
-                                       }
-                               }
+                               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);
-                               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->clazz->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->clazz->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);
+                       }
 
-                       switch (md->returntype.type) {
-                       case TYPE_INT:
-                       case TYPE_ADR:
-                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                               M_INTMOVE(REG_RESULT, s1);
-                               emit_store_dst(jd, iptr, s1);
-                               break;
+                       /* 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);
 
-                       case TYPE_LNG:
-                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
-                               M_LNGMOVE(REG_RESULT_PACKED, s1);
-                               emit_store_dst(jd, iptr, s1);
-                               break;
+                       /* generate the actual call */
 
-                       case TYPE_FLT:
-                       case TYPE_DBL:
-                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                               M_FLTMOVE(REG_FRESULT, s1);
-                               emit_store_dst(jd, iptr, s1);
-                               break;
-
-                       case TYPE_VOID:
-                               break;
-                       }
+                       M_MTCTR(REG_PV);
+                       M_JSR;
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
@@ -2827,23 +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 */
-
-       /* generate traps */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
index 6081382ea554d3723318b6912fa339e8a041c552..d8326aa4db4f6ad2164f69f0ec76ba6e600c18c7 100644 (file)
     } while (0)
 
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) { \
-            M_MOV(a, b); \
-        } \
-    } while (0)
-
-#define M_LNGMOVE(a,b) \
-    do { \
-        if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \
-            assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-        } else { \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-        } \
-    } while (0)
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) { \
-            M_FMOV(a, b); \
-        } \
-    } while (0)
-
-
 #define ICONST(d,c)                     emit_iconst(cd, (d), (c))
 
 #define LCONST(reg,c) \
     ICONST(GET_HIGH_REG((reg)), (s4) ((s8) (c) >> 32));        \
     ICONST(GET_LOW_REG((reg)), (s4) ((s8) (c)));
 
+#define M_DMOV(a,b) M_FMOV(a,b)
 
 #define ALIGNCODENOP \
     if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
 #define M_AST_INTERN(a,b,disp)          M_IST_INTERN(a,b,disp)
 #define M_AST(a,b,disp)                 M_IST(a,b,disp)
 
+#define M_ACMP(a,b)                     M_CMP(a,b)
+#define M_ICMP(a,b)                     M_CMP(a,b)
+
+#define M_TEST(a)                       M_TST(a)
+#define M_ALD_DSEG(a,disp)              M_ALD(a,REG_PV,disp);
+
 
 /* floating point instructions ************************************************/
 
index 74adff082fc03ab3c668b84d410b659823448cf4..1e35669c81c4892d9cf0173149dc63ba61887b75 100644 (file)
@@ -298,6 +298,26 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       int32_t disp;
+
+       if ((value >= -32768) && (value <= 32767)) {
+               M_CMPI(reg, value);
+       }
+       else {
+               assert(reg != REG_ITMP2);
+               disp = dseg_add_s4(cd, value);
+               M_ILD(REG_ITMP2, REG_PV, disp);
+               M_CMP(reg, REG_ITMP2);
+       }
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -556,6 +576,165 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       M_MFLR(REG_ITMP1);
+       M_LDA(REG_PV, REG_ITMP1, -disp);
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+# 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);
+
+               syncslot_offset += (LA_SIZE_IN_POINTERS + ARG_CNT) * 8;
+       }
+# 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 */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, &m->clazz->object.header);
+               M_ALD(REG_A0, REG_PV, disp);
+       }
+       else {
+               M_TST(REG_A0);
+               M_BNE(1);
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
+       }
+
+       M_AST(REG_A0, REG_SP, syncslot_offset);
+       M_JSR;
+
+# 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);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
+
+               M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
+       }
+# endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       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 */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+               M_IST(REG_RESULT2, REG_SP, syncslot_offset + 8);
+               /* fall through */
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT , REG_SP, syncslot_offset + 4);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset + 4);
+               break;
+       }
+
+       M_ALD(REG_A0, REG_SP, syncslot_offset);
+       M_JSR;
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+               M_ILD(REG_RESULT2, REG_SP, syncslot_offset + 8);
+               /* fall through */
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT , REG_SP, syncslot_offset + 4);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 4);
+               break;
+       }
+}
+#endif
+
+
+/**
+ * Emit profiling code for method frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code)
+{
+       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));
+}
+#endif
+
+
+/**
+ * Emit profiling code for basicblock frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
+{
+       int32_t 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);
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 33724ab14ae24b774b90f4536e4fcb9448d95a1e..e4f8052814af004e502daa5acebf984687d78cee 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On PowerPC we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index b10b650f98b727148204850c91fa05f9f586cb6e..0488a1d7c6eee658318700def09b58c1c8199aec 100644 (file)
 #define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 1c7831631f76964fadf62b883ef9a173d5100beb..3873d3f172fe4b2cfccb975e2f1c999b3640928a 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc64/codegen.c - machine code generator for 64-bit PowerPC
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* codegen_emit ****************************************************************
-
-   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;
-       u2                  currentline;
-       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
-       unresolved_method  *um;
-       builtintable_entry *bte;
-       methoddesc         *md;
-       s4                  fieldtype;
-       s4                  varindex;
-       unresolved_field   *uf;
-       fieldinfo          *fi;
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* prevent compiler warnings */
-
-       d   = 0;
-       lm  = NULL;
-       um  = NULL;
-       bte = NULL;
-       uf  = 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 PPC64, since both values     */
-       /* reside in R3 */
-       if (checksync && code_is_synchronized(code)) {
-               /* reserve 2 slots for long/double return values for monitorexit */
-               cd->stackframesize += 2;
-       }
-
-#endif
-
-       /* create method header */
-
-       /* align stack to 16-bytes */
-
-/* FIXME */
-/*     if (!m->isleafmethod || opt_verbosecall) */
-/*             stackframesize = (stackframesize + 3) & ~3;
-*/
-/*     else if (m->isleafmethod && (stackframesize == LA_WORD_SIZE)) */
-/*             stackframesize = 0; */
-
-       (void) dseg_add_unique_address(cd, code);                      /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8);             /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
-
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave         */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave         */
-
-       /* create stack frame (if necessary) */
+       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;
 
        if (!code_is_leafmethod(code)) {
                M_MFLR(REG_ZERO);
@@ -217,7 +135,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);
                        }
@@ -233,206 +151,88 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-       /* save monitorenter argument */
-
-#if defined(ENABLE_THREADS)
-
-       if (checksync && code_is_synchronized(code)) {
-
-               /* stackoffset for argument used for LOCK_monitor_exit */
-               s1 = rd->memuse;
-
-#if !defined (NDEBUG)
-               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
-                       M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
-
-                       /* used for LOCK_monitor_exit, adopt size because we created another stackframe */
-                       s1 += (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT);
-               }
-#endif
-
-               p = dseg_add_functionptr(cd, LOCK_monitor_enter);
-               M_ALD(REG_ITMP3, REG_PV, p);
-               M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
-               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) {
-                       p = dseg_add_address(cd, &m->clazz->object.header);
-                       M_ALD(REG_A0, REG_PV, p);
-               }
-               else {
-                       M_TST(REG_A0);
-                       M_BNE(1);
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
-               }
+       // Get required compiler data.
+       codeinfo*     code = jd->code;
+       codegendata*  cd   = jd->cd;
+       registerdata* rd   = jd->rd;
 
-               M_AST(REG_A0, REG_SP, s1 * 8);                      /* rd->memuse * 8 */
-               M_JSR;
+       p = cd->stackframesize;
 
-#if !defined(NDEBUG)
-               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LLD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_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 + PA_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 + PA_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
 
-       /* call trace function */
-#if !defined (NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
+       /* restore saved registers */
 
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_LLD(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);
-
-               /* copy interface registers to their destination */
-
-               len = bptr->indepth;
-               MCODECHECK(128+len);
-
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-                       while (len) {
-                               len--;
-                               var = VAR(bptr->invars[len]);
-                               if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
-                                       /* d = reg_of_var(m, var, REG_ITMP1); */
-                                       if (!(var->flags & INMEMORY))
-                                               d = var->vv.regoff;
-                                       else
-                                               d = REG_ITMP1;
-                                       M_INTMOVE(REG_ITMP1, d);
-                                       emit_store(jd, NULL, var, d);
-                               }
-                       }
-               } else {
-#endif
-               while (len) {
-                       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) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
-
-                       MCODECHECK(128);   /* 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:
+       /* deallocate stack */
 
-                       REPLACEMENT_POINT_INLINE_START(cd, iptr);
-                       break;
-
-               case ICMD_INLINE_BODY:
-        
-                       REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_INLINE_END:
+       if (cd->stackframesize)
+               M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
+       M_RET;
+}
 
-               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TST(s1);
-                       M_BEQ(0);
-                       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;
+
+       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_ITMP1);
-                       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;
 
@@ -453,29 +253,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/copy/move operations ************************************/
-
-               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_ALOAD:      /* s1.localindex = 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                 */
@@ -1167,7 +944,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;
                                        
@@ -1214,15 +991,6 @@ bool codegen_emit(jitdata *jd)
                        
                /* memory operations **************************************************/
 
-               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
-                       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);
@@ -1437,101 +1205,6 @@ bool codegen_emit(jitdata *jd)
                        M_ASTX(s3, s1, REG_ITMP2);
                        break;
 
-
-               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, NULL);
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic,
-                                                                       iptr->sx.s23.s3.uf, disp);
-
-                       }
-                       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->clazz)) {
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
-                               }
-                       }
-
-                       M_ALD(REG_ITMP1, REG_PV, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ILD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_LLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_ADR:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ALD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_FLD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:                          
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_DLD_INTERN(d, REG_ITMP1, 0);
-                               break;
-                       }
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, NULL);
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic,
-                                                                       iptr->sx.s23.s3.uf, disp);
-                       }
-                       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->clazz)) {
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 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_ITMP2);
-                               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);
@@ -1626,16 +1299,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_LNGMOVE(s1, REG_ITMP1_XPTR);
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
                        M_ALD(REG_ITMP2, REG_PV, disp);
                        M_MTCTR(REG_ITMP2);
@@ -1650,53 +1313,8 @@ bool codegen_emit(jitdata *jd)
                                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 ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TST(s1);
-                       emit_beq(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TST(s1);
-                       emit_bne(cd, iptr->dst.block);
-                       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(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
@@ -1734,9 +1352,7 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, REG_ITMP2);
                        emit_bgt(cd, iptr->dst.block);
                        break;
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
-               case ICMD_IF_LCMPEQ: 
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1744,9 +1360,7 @@ bool codegen_emit(jitdata *jd)
                        emit_beq(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
-               case ICMD_IF_LCMPNE:  
+               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1755,8 +1369,7 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_LCMPLT:
+               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1764,8 +1377,7 @@ bool codegen_emit(jitdata *jd)
                        emit_blt(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_LCMPGT:
+               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1773,8 +1385,7 @@ bool codegen_emit(jitdata *jd)
                        emit_bgt(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_LCMPLE:
+               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1782,8 +1393,7 @@ bool codegen_emit(jitdata *jd)
                        emit_ble(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_LCMPGE:
+               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1791,131 +1401,6 @@ bool codegen_emit(jitdata *jd)
                        emit_bge(cd, iptr->dst.block);
                        break;
 
-
-               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
-                       M_LNGMOVE(s1, REG_RESULT);
-                       goto nowperformreturn;
-
-               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
-                       M_LNGMOVE(s1, REG_RESULT);
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
-                       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 */
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif         
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
-                               M_MTCTR(REG_ITMP3);
-
-                               /* we need to save the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_LRETURN:
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       /* fall through */
-                                       M_LST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_FRETURN:
-                                       M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       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:
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       /* fall through */
-                                       M_LLD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_FRETURN:
-                                       M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore return address                                         */
-
-                       if (!code_is_leafmethod(code)) {
-                               /* 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_LLD(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;
@@ -1965,212 +1450,92 @@ nowperformreturn:
                        break;
 
 
-               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
-                       {
-                       s4 i, val;
-                       lookup_target_t *lookup;
-
-                       lookup = iptr->dst.lookup;
-
-                       i = iptr->sx.s23.s2.lookupcount;
-                       
-                       MCODECHECK((i<<3)+8);
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       while (--i >= 0) {
-                               val = lookup->value;
-                               if ((val >= -32768) && (val <= 32767)) {
-                                       M_CMPI(s1, val);
-                       
-                               } else {
-                                       a = dseg_add_s4(cd, val);
-                                       M_ILD(REG_ITMP2, REG_PV, a);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               emit_beq(cd, lookup->target.block);
-                               ++lookup;
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                       bte = iptr->sx.s23.s3.bte;
+                       if (bte->stub == NULL) {
+                               disp = dseg_add_functionptr(cd, bte->fp);
+                               M_ALD(REG_PV, REG_PV, disp);
+                               M_ALD(REG_PV, REG_PV, 0);       /* TOC */
                        }
-
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-
-                       ALIGNCODENOP;
-                       break;
+                       else {
+                               disp = dseg_add_functionptr(cd, bte->stub);
+                               M_ALD(REG_PV, REG_PV, disp);
                        }
 
+                       /* generate the actual call */
+                       M_MTCTR(REG_PV);
+                       M_JSR;
+                       break;
 
-               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-                       bte = iptr->sx.s23.s3.bte;
-                       md = bte->md;
-                       goto gen_method;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
                case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
-
-                       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;
-                       }
-                       else {
+                               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);
                        }
+                       M_ALD(REG_PV, REG_PV, disp);
 
-gen_method:
-                       s3 = md->paramcount;
-
-                       MCODECHECK((s3 << 2) + 128);
-
-                       /* copy arguments to registers or stack location */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
+                       /* generate the actual call */
 
-                               if (var->flags & PREALLOC)
-                                       continue;
+                       M_MTCTR(REG_PV);
+                       M_JSR;
+                       break;
 
-                               if (IS_INT_LNG_TYPE(var->type)) {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               M_LNGMOVE(s1, d);
-                                       }
-                                       else {
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_LST(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);
-                                       }
-                               }
+               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);
+                               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);
-                                       M_ALD(REG_PV, REG_PV, disp);
-                                       M_ALD(REG_PV, REG_PV, 0);       /* TOC */
-                               }
-                               else {
-                                       disp = dseg_add_functionptr(cd, bte->stub);
-                                       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_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);
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_PV, REG_METHODPTR, s1);
 
-                                       s1 = 0;
-                                       s2 = 0;
+                       /* generate the actual call */
 
-                               } else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->clazz->index;
-
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
+                       M_MTCTR(REG_PV);
+                       M_JSR;
+                       break;
 
-                               /* 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);
+               case ICMD_INVOKEINTERFACE:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                               /* generate the actual call */
+                               s1 = 0;
+                               s2 = 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);
+                       } else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr*) * lm->clazz->index;
 
-                               break;
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                        }
-                       /* store return value */
 
-                       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)) {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                       M_MOV(REG_RESULT, s1);
-                               }
-                               else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                                       M_FLTMOVE(REG_FRESULT, s1);
-                               }
-                               emit_store_dst(jd, iptr, s1);
-                       }
+                       /* generate the actual call */
+
+                       M_MTCTR(REG_PV);
+                       M_JSR;
                        break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
@@ -2605,23 +1970,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 */
-
-       /* generate traps */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
index ca1a20a0d0d1822c4833818a702c39bc1bf1d83c..f8f47e9d35cb295ef5a5ebfdf5495aa8ebfe7637 100644 (file)
     } while (0)
 
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) { \
-            M_MOV(a, b); \
-        } \
-    } while (0)
-
-#define M_LNGMOVE(a,b) M_INTMOVE(a,b)
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(a,b) \
-    do { \
-        if ((a) != (b)) { \
-            M_FMOV(a, b); \
-        } \
-    } while (0)
-
-
 #define ICONST(d,c)                     emit_iconst(cd, (d), (c))
 #define LCONST(reg,c)                  emit_lconst(cd, (reg), (c))
 
 
 #define M_ALD_INTERN(a,b,disp)          M_LLD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)                 M_LLD(a,b,disp)
+#define M_ALD_DSEG(a,disp)              M_LLD(a,REG_PV,disp)
 #define M_ALDX(a,b,c)                  M_OP3(31, 21, 0, 0, a, b, c)    /* LDX */
 
 #define M_BST(a,b,c)                    M_OP2_IMM(38, a, b, c) /* STB */
 #define M_CLR_HIGH(a)                  M_OP3(30, 0, 0, 0x20, (a), (a), 0);
 #define M_AADD_IMM(a,b,c)               M_LADD_IMM(a, b, c)
 
+#define M_DMOV(a,b)                     M_FMOV(a,b)
+
+#define M_ACMP(a,b)                     M_CMP(a,b)
+#define M_ICMP(a,b)                     M_CMP(a,b)
+
+#define M_TEST(a)                       M_TST(a)
+
 #endif /* _CODEGEN_H */
 
 
index a969a3bc5688f0814e54ba698d278fba64cfbba7..62e2616a1e29a57d8dc5824ee75235484bc52f3e 100644 (file)
@@ -196,6 +196,146 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       int32_t disp;
+
+       if ((value >= -32768) && (value <= 32767)) {
+               M_CMPI(reg, value);
+       } else {
+               assert(reg != REG_ITMP2);
+               disp = dseg_add_s4(cd, value);
+               M_ILD(REG_ITMP2, REG_PV, disp);
+               M_CMP(reg, REG_ITMP2);
+       }
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+#if !defined (NDEBUG)
+               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                       M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
+
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_LST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
+
+                       /* used for LOCK_monitor_exit, adopt size because we created another stackframe */
+                       syncslot_offset += (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8;
+               }
+#endif
+
+               p = dseg_add_functionptr(cd, LOCK_monitor_enter);
+               M_ALD(REG_ITMP3, REG_PV, p);
+               M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
+               M_MTCTR(REG_ITMP3);
+
+               /* get or test the lock object */
+
+               if (m->flags & ACC_STATIC) {
+                       p = dseg_add_address(cd, &m->clazz->object.header);
+                       M_ALD(REG_A0, REG_PV, p);
+               }
+               else {
+                       M_TST(REG_A0);
+                       M_BNE(1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
+               }
+
+               M_AST(REG_A0, REG_SP, syncslot_offset);
+               M_JSR;
+
+#if !defined(NDEBUG)
+               if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_LLD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
+
+                       M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
+               }
+#endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_ALD(REG_ITMP3, REG_PV, disp);
+       M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
+       M_MTCTR(REG_ITMP3);
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+       case TYPE_INT:
+       case TYPE_ADR:
+               /* fall through */
+               M_LST(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_FLT:
+               M_FST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       }
+
+       M_ALD(REG_A0, REG_SP, syncslot_offset);
+       M_JSR;
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+       case TYPE_INT:
+       case TYPE_ADR:
+               /* fall through */
+               M_LLD(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_FLT:
+               M_FLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       }
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
@@ -648,6 +788,18 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       M_MFLR(REG_ITMP1);
+       M_LDA(REG_PV, REG_ITMP1, -disp);
+}
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index b70509f86130e849b1ef14677104dc89303e045c..85c46b109598fa1b569f34fe01644c713c2bc8bb 100644 (file)
 #include "vm/jit/jit.hpp"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On PowerPC64 we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 94b0b1edb06932ddf640baee19d618a033c03082..1e6650f2048eb196a7210ee6cf4b4a6261aaaff0 100644 (file)
 /*** architecture-dependent configuration *************************************/
 
 /* first unset the macros (default) */
-#undef REPLACE_RA_BETWEEN_FRAMES
-#undef REPLACE_RA_TOP_OF_FRAME
 #undef REPLACE_RA_LINKAGE_AREA
-#undef REPLACE_LEAFMETHODS_RA_REGISTER
-
-/* i386, x86_64 and m68k */
-#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
-#define REPLACE_RA_BETWEEN_FRAMES
-/* alpha */
-#elif defined(__ALPHA__)
-#define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_LEAFMETHODS_RA_REGISTER
+
 /* powerpc */
-#elif defined(__POWERPC__)
-#define REPLACE_RA_LINKAGE_AREA
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* s390 */
-#elif defined(__S390__)
-#define REPLACE_RA_TOP_OF_FRAME
+#if defined(__POWERPC__)
+# define REPLACE_RA_LINKAGE_AREA
 #endif
 
 
@@ -728,13 +714,7 @@ bool replace_create_replacement_points(jitdata *jd)
        code->regalloc      = regalloc;
        code->regalloccount = alloccount;
        code->globalcount   = 0;
-       code->savedintcount = INT_SAV_CNT - rd->savintreguse;
-       code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
-#endif
        code->memuse        = rd->memuse;
-       code->stackframesize = jd->cd->stackframesize;
 
        REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
        REPLACE_COUNT_INC(stat_regallocs, alloccount);
@@ -1512,7 +1492,7 @@ static void replace_write_executionstate(rplpoint *rp,
 void md_pop_stackframe(executionstate_t *es)
 {
        u1 *ra;
-       s4 ra_align_off;
+       s4 framesize;
        s4 reg;
        s4 i;
        stackslot_t *basesp;
@@ -1520,23 +1500,18 @@ void md_pop_stackframe(executionstate_t *es)
 
        assert(es->code);
 
-       /* alignment offset of RA */
+       /* calculate the size of the stackframe */
 
-       ra_align_off = 0;
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-    if (es->code->stackframesize)
-               ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
-#endif
+       framesize = md_stacktrace_get_framesize(es->code);
 
        /* read the return address */
 
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (code_is_leafmethod(es->code))
                ra = es->ra;
        else
 #endif
-               ra = (u1*) md_stacktrace_get_returnaddress(es->sp,
-                          SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
+               ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
 
        /* calculate the base of the stack frame */
 
@@ -1545,17 +1520,17 @@ void md_pop_stackframe(executionstate_t *es)
 
        /* restore return address, if part of frame */
 
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(es->code))
-#endif
+# endif
                es->ra = (u1*) (ptrint) *--basesp;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
 
 #if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(es->code))
-#endif
+# endif
                es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
 #endif /* REPLACE_RA_LINKAGE_AREA */
 
@@ -1592,10 +1567,9 @@ void md_pop_stackframe(executionstate_t *es)
 
        /* adjust the stackpointer */
 
-       es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
+       es->sp += framesize;
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+       es->sp += SIZEOF_VOID_P; /* skip return address */
 #endif
 
        /* set the program counter to the return address */
@@ -1652,12 +1626,12 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
 
        /* write the return address */
 
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
+#if STACKFRMAE_RA_BETWEEN_FRAMES
        es->sp -= SIZEOF_VOID_P;
        *((void **)es->sp) = (void *) ra;
        if (calleecode->stackframesize)
                es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
-#endif /* REPLACE_RA_BETWEEN_FRAMES */
+#endif /* STACKFRAME_RA_BETWEEN_FRAMES */
 
        es->ra = (u1*) (ptrint) ra;
 
@@ -1692,17 +1666,17 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
 
        /* save the return address register */
 
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(calleecode))
-#endif
+# endif
                *--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
 
 #if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(calleecode))
-#endif
+# endif
                basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
 #endif /* REPLACE_RA_LINKAGE_AREA */
 
@@ -2371,11 +2345,9 @@ static void replace_pop_native_frame(executionstate_t *es,
 
        /* restore sp, pv, pc and codeinfo of the parent method */
 
-       /* XXX michi: use this instead:
-       es->sp = sfi->sp + code->stackframesize; */
-       es->sp   = (uint8_t*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp  += SIZE_OF_STACKSLOT; /* skip return address */
+       es->sp   = (uint8_t*) (((uintptr_t) sfi->sp) + md_stacktrace_get_framesize(code));
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+       es->sp  += SIZEOF_VOID_P; /* skip return address */
 #endif
        es->pv   = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
        es->pc   = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
@@ -2422,9 +2394,9 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
 
        /* skip sp for the native stub */
 
-       es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+       es->sp -= md_stacktrace_get_framesize(frame->sfi->code);
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+       es->sp -= SIZEOF_VOID_P; /* skip return address */
 #endif
 
        /* assert that the native frame has not moved */
index 002ba7f956db07116bfbffcb4dcdf4a397bb72fa..e5c26995547822fa8999df4bd5fe16537636fcbe 100644 (file)
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           5             /* bytes */
index 05055ba81b55bf7bf8f0de37697cf6d6f9659e09..77c685e7723ea6f31dde93e2aee80fb24939e100 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/s390/codegen.c - machine code generator for s390
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -51,9 +51,6 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
@@ -64,7 +61,6 @@
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
@@ -94,12 +90,6 @@ static void do__log(u4 *regs) {
 
 /* #define SUPPORT_HERCULES 1 */
 
-/* codegen *********************************************************************
-
-   Generates machine code.
-
-*******************************************************************************/
-
 /*
 
 Layout of stackframe:
@@ -125,100 +115,29 @@ local[0]                               0 * 8
 
 */
 
-bool codegen_emit(jitdata *jd)
-{
-       methodinfo         *m;
-       codeinfo           *code;
-       codegendata        *cd;
-       registerdata       *rd;
-       s4                  len, s1, s2, s3, d, dd, disp;
-       u2                  currentline;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       constant_classref  *cr;
-       unresolved_class   *uc;
-       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
-       unresolved_method  *um;
-       builtintable_entry *bte;
-       methoddesc         *md;
-       fieldinfo          *fi;
-       unresolved_field   *uf;
-       s4                  fieldtype;
-#if 0
-       rplpoint           *replacementpoint;
-#endif
-       s4                 varindex;
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
-       rd   = jd->rd;
-
-       /* prevent compiler warnings */
-
-       d   = 0;
-       lm  = NULL;
-       um  = 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 + 1  /* space to save RA */;
+/**
+ * Generates machine code for the method prolog.
+ */
+void codegen_emit_prolog(jitdata* jd)
+{
+       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;
 
        /* CAUTION:
         * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
         */
 
-#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
-          since both values reside in R2. */
-
-       if (checksync && code_is_synchronized(code)) {
-               /* 1 slot space to save argument of monitor_enter */
-               /* 1 slot to temporary store return value before monitor_exit */
-               cd->stackframesize += 2;
-       }
-#endif
-
-       /* Keep stack of non-leaf functions 16-byte aligned for calls into
-          native code e.g. libc or jni (alignment problems with
-          movaps). */
-
-       if (!code_is_leafmethod(code) || opt_verbosecall )
-               /* TODO really 16 bytes ? */
-               cd->stackframesize = (cd->stackframesize + 2) & ~2;
-
-       /* create method header */
-
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       /* REMOVEME: We still need it for exception handling in assembler. */
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
-
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
-
        /* Offset PV */
 
        M_AADD_IMM(N_PV_OFFSET, REG_PV);
@@ -233,20 +152,6 @@ bool codegen_emit(jitdata *jd)
 
        M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
 
-       /* generate method profiling code */
-
-#if defined(ENABLE_PROFILING)
-       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-               /* count frequency */
-               M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
-               ICONST(REG_ITMP2, 1);
-               N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
-               M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
-
-               PROFILE_CYCLE_START;
-       }
-#endif
-
        /* save used callee saved registers and return address */
 
        p = cd->stackframesize - 1;
@@ -318,7 +223,7 @@ bool codegen_emit(jitdata *jd)
                        if (!md->params[p].inmemory) {           /* register arguments    */
                                s2 = s1;
                                if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
-                                       M_FLTMOVE(s2, var->vv.regoff);
+                                       emit_fmove(cd, s2, var->vv.regoff);
 
                                } else {                                         /* reg arg -> spilled    */
                                        if (IS_2_WORD_TYPE(t))
@@ -342,212 +247,68 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        } /* end for */
+}
 
-       /* save monitorenter argument */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse;
-
-#if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
-
-                       s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
-               }
-#endif
-
-               /* decide which monitor enter function to call */
 
-               if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->clazz->object.header);
-                       M_ALD_DSEG(REG_A0, disp);
-               }
-               else {
-                       M_TEST(REG_A0);
-                       M_BNE(SZ_BRC + SZ_ILL);
-                       M_ILL(TRAP_NullPointerException);
-               }
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int32_t p;
+       int i;
 
-               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-               M_ALD_DSEG(REG_ITMP2, disp);
+       // Get required compiler data.
+       codegendata*  cd = jd->cd;
+       registerdata* rd = jd->rd;
 
-               M_AST(REG_A0, REG_SP, s1 * 8);
+       p = cd->stackframesize;
 
-               M_ASUB_IMM(96, REG_SP); 
-               M_CALL(REG_ITMP2);
-               M_AADD_IMM(96, REG_SP); 
+       /* restore return address */
 
-#if !defined(NDEBUG)
-               if (opt_verbosecall) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
+       p--; M_ALD(REG_RA, REG_SP, p * 8);
 
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+       /* restore saved registers */
 
-                       M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
-               }
-#endif
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
        }
-#endif
-
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif /* !defined(NDEBUG) */
-
+       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 = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
-
-               if (bptr->flags >= BBREACHED) {
-
-               /* branch resolving */
-
-               codegen_resolve_branchrefs(cd, bptr);
-
-               /* handle replacement points */
-
-               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
-
-               /* copy interface registers to their destination */
+       /* deallocate stack */
 
-               len = bptr->indepth;
-               MCODECHECK(512);
+       if (cd->stackframesize)
+               M_AADD_IMM(cd->stackframesize * 8, REG_SP);
 
-#if defined(ENABLE_PROFILING)
-               /* generate basicblock profiling code */
-
-               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-                       /* count frequency */
-
-                       M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
-                       M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
-                       ICONST(REG_ITMP2, 1);
-                       N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
-                       M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
-
-                       /* if this is an exception handler, start profiling again */
-
-                       if (bptr->type == BBTYPE_EXH)
-                               PROFILE_CYCLE_START;
-               }
-#endif
-
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-                       while (len) {
-                               len--;
-                               src = bptr->invars[len];
-                               if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
-                                       if (bptr->type == BBTYPE_EXH) {
-/*                                     d = reg_of_var(rd, src, REG_ITMP1); */
-                                               if (!IS_INMEMORY(src->flags))
-                                                       d = src->vv.regoff;
-                                               else
-                                                       d = REG_ITMP3_XPTR;
-                                               M_INTMOVE(REG_ITMP3_XPTR, d);
-                                               emit_store(jd, NULL, src, d);
-                                       }
-                               }
-                       }
-                       
-               } else {
-#endif
-
-               while (len) {
-                       len--;
-                       var = VAR(bptr->invars[len]);
-                       if ((len ==  bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
-                               if (bptr->type == BBTYPE_EXH) {
-                                       d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
-                                       M_INTMOVE(REG_ITMP3_XPTR, 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) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
-
-                       MCODECHECK(1024);                         /* 1KB should be enough */
-
-               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);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_INLINE_END:
+       M_RET;
+}
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
 
-               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;
+
+       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);
                        disp = dseg_add_float(cd, iptr->sx.val.f);
@@ -566,7 +327,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr = iptr->sx.val.c.ref;
+                               constant_classref *cr = iptr->sx.val.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
 /*                             PROFILE_CYCLE_STOP; */
@@ -599,28 +360,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                 */
@@ -1444,7 +1183,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_FADD(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_FADD(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1457,7 +1196,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_DADD(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_DADD(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1468,7 +1207,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
 
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1478,7 +1217,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
 
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1490,7 +1229,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_FMUL(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_FMUL(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1503,7 +1242,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_DMUL(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_DMUL(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1514,7 +1253,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
 
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1524,7 +1263,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
 
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1700,17 +1439,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
-               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       /* TODO softnull */
-                       /* 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);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1982,109 +1710,6 @@ bool codegen_emit(jitdata *jd)
                        */
                        break;
 
-
-               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, NULL);
-
-/*                             PROFILE_CYCLE_STOP; */
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
-
-/*                             PROFILE_CYCLE_START; */
-                       }
-                       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->clazz)) {
-                                       PROFILE_CYCLE_STOP;
-
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
-
-                                       PROFILE_CYCLE_START;
-                               }
-                       }
-
-                       M_ALD_DSEG(REG_ITMP1, disp);
-
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ILD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
-                               M_LLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_ADR:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ALD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_FLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:                          
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_DLD(d, REG_ITMP1, 0);
-                               break;
-                       }
-
-                       emit_store_dst(jd, iptr, d);
-
-                       break;
-
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               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);
-                       }
-                       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->clazz)) {
-                                       PROFILE_CYCLE_STOP;
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
-                                       PROFILE_CYCLE_START;
-                               }
-                       }
-
-                       M_ALD_DSEG(REG_ITMP1, disp);
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_IST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
-                               M_LST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_ADR:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_AST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
-                               M_FST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
-                               M_DST(s1, REG_ITMP1, 0);
-                               break;
-                       }
-                       break;
-
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
@@ -2207,19 +1832,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       /* PROFILE_CYCLE_STOP; */
-               
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP3);
-                       M_INTMOVE(s1, REG_ITMP3_XPTR);
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               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_DSEG(REG_ITMP1, disp);
                        M_JMP(REG_ITMP1_XPC, REG_ITMP1);
@@ -2227,77 +1839,6 @@ bool codegen_emit(jitdata *jd)
 
                        break;
 
-               case ICMD_GOTO:         /* ... ==> ...                                */
-               case ICMD_RET:          /* ... ==> ...                                */
-
-                       emit_br(cd, iptr->dst.block);
-
-                       break;
-
-               case ICMD_JSR:          /* ... ==> ...                                */
-
-                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
-
-                       break;
-                       
-               case ICMD_IFNULL:       /* ..., value ==> ...                         */
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       switch (iptr->opc) {    
-                               case ICMD_IFNULL:
-                                       emit_beq(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IFNONNULL:
-                                       emit_bne(cd, iptr->dst.block);
-                                       break;
-                       }
-                       break;
-
-               case ICMD_IFEQ:         /* ..., value ==> ...                         */
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-               case ICMD_IFLE:         /* ..., value ==> ...                         */
-               case ICMD_IFNE:         /* ..., value ==> ...                         */
-               case ICMD_IFGT:         /* ..., value ==> ...                         */
-               case ICMD_IFGE:         /* ..., value ==> ...                         */
-                       
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
-                       if (N_VALID_IMM(iptr->sx.val.i))
-                               M_ICMP_IMM(s1, iptr->sx.val.i);
-                       else {
-                               disp = dseg_add_s4(cd, iptr->sx.val.i);
-                               if (N_VALID_DSEG_DISP(disp)) {
-                                       N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
-                               } else {
-                                       ICONST(REG_ITMP2, disp);
-                                       N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
-                               }
-                       }
-
-                       switch (iptr->opc) {
-                       case ICMD_IFLT:
-                               emit_blt(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IFLE:
-                               emit_ble(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IFNE:
-                               emit_bne(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IFGT:
-                               emit_bgt(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IFGE:
-                               emit_bge(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IFEQ:
-                               emit_beq(cd, iptr->dst.block);
-                               break;
-                       }
-
-                       break;
-
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
                case ICMD_IF_LLE:       /* op1 = target JavaVM pc, val.l = constant   */
                case ICMD_IF_LGT:
@@ -2413,39 +1954,6 @@ bool codegen_emit(jitdata *jd)
 
                        break;
 
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       switch (iptr->opc) {
-                               case ICMD_IF_ICMPEQ:
-                                       emit_beq(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IF_ICMPNE:
-                                       emit_bne(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IF_ICMPLT:
-                                       emit_blt(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IF_ICMPGT:
-                                       emit_bgt(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IF_ICMPLE:
-                                       emit_ble(cd, iptr->dst.block);
-                                       break;
-                               case ICMD_IF_ICMPGE:
-                                       emit_bge(cd, iptr->dst.block);
-                                       break;
-                       }
-
-                       break;
-
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2526,137 +2034,6 @@ bool codegen_emit(jitdata *jd)
                        }
                        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;
-
-                               PROFILE_CYCLE_STOP;
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
-                               PROFILE_CYCLE_START;
-                       }
-#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 */
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif /* !defined(NDEBUG) */
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               /* we need to save the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_LRETURN:
-                                       M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
-                                       /* fall through */
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                                       M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               }
-
-                               M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_ALD_DSEG(REG_ITMP2, disp);
-
-                               M_ASUB_IMM(96, REG_SP);
-                               M_CALL(REG_ITMP2);
-                               M_AADD_IMM(96, REG_SP);
-
-                               /* and now restore the proper return value */
-
-                               switch (iptr->opc) {
-                               case ICMD_LRETURN:
-                                       M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
-                                       /* fall through */
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                                       M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                                       M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore return address                                         */
-
-                       p--; M_ALD(REG_RA, REG_SP, p * 8);
-
-                       /* 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_AADD_IMM(cd->stackframesize * 8, REG_SP);
-
-                       /* generate method profiling code */
-
-                       PROFILE_CYCLE_STOP;
-
-                       M_RET;
-                       }
-                       break;
-
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2709,255 +2086,116 @@ nowperformreturn:
                        break;
 
 
-               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
-                       {
-                               s4 i;
-                               lookup_target_t *lookup;
-
-                               lookup = iptr->dst.lookup;
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                       bte = iptr->sx.s23.s3.bte;
+                       if (bte->stub == NULL) {
+                               disp = dseg_add_functionptr(cd, bte->fp);
+                               M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */   
+                       } else {
+                               disp = dseg_add_functionptr(cd, bte->stub);
+                       }
 
-                               i = iptr->sx.s23.s2.lookupcount;
-                       
-                               MCODECHECK(8 + ((7 + 6) * i) + 5);
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       if (N_VALID_DSEG_DISP(disp)) {
+                               N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
+                       } else {
+                               N_LHI(REG_ITMP1, disp);
+                               N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
+                       }
 
-                               while (--i >= 0) {
-                                       if (N_VALID_IMM(lookup->value)) {
-                                               M_ICMP_IMM(s1, lookup->value);
-                                       } else {
-                                               ICONST(REG_ITMP2, lookup->value);
-                                               M_ICMP(REG_ITMP2, s1);
-                                       }
-                                       emit_beq(cd, lookup->target.block);
-                                       lookup++;
-                               }
+                       /* generate the actual call */
+                       M_CALL(REG_PV);
 
-                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       /* post call finalization */
+                       if (bte->stub == NULL) {
+                               M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
                        }
                        break;
 
-
-               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-                       bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto gen_method;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
                case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
-
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+                               /* TODO softnull */
+                               /* Implicit NULL pointer check */
+                               M_ILD(REG_ITMP1, REG_A0, 0);
+                               /* 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;
-
-                       MCODECHECK((s3 << 1) + 64);
-
-                       /* copy arguments to registers or stack location */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-
-                               /* 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 = PACK_REGS(
-                                                               GET_LOW_REG(md->params[s3].regoff),
-                                                               GET_HIGH_REG(md->params[s3].regoff)
-                                                       );
-                                                       d = emit_load(jd, iptr, var, s1);
-                                                       M_LNGMOVE(d, s1);
-                                               }
-                                               else {
-                                                       s1 = md->params[s3].regoff;
-                                                       d = emit_load(jd, iptr, var, s1);
-                                                       M_INTMOVE(d, s1);
-                                               }
-                                       }
-                                       else {
-                                               if (IS_2_WORD_TYPE(var->type)) {
-                                                       d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
-                                                       M_LST(d, REG_SP, md->params[s3].regoff);
-                                               }
-                                               else {
-                                                       d = emit_load(jd, iptr, var, REG_ITMP1);
-                                                       M_IST(d, REG_SP, md->params[s3].regoff);
-                                               }
-                                       }
-                               }
-                               else {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = md->params[s3].regoff;
-                                               d = emit_load(jd, iptr, var, s1);
-                                               M_FLTMOVE(d, s1);
-                                       }
-                                       else {
-                                               d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(d, REG_SP, md->params[s3].regoff);
-                                               else
-                                                       M_FST(d, REG_SP, md->params[s3].regoff);
-                                       }
-                               }
+                       if (N_VALID_DSEG_DISP(disp)) {
+                               N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
+                       } else {
+                               N_LHI(REG_ITMP1, disp);
+                               N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
                        }
 
-                       /* generate method profiling code */
-
-                       PROFILE_CYCLE_STOP;
-
-                       switch (iptr->opc) {
-                       case ICMD_BUILTIN:
-                               if (bte->stub == NULL) {
-                                       disp = dseg_add_functionptr(cd, bte->fp);
-                                       M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */   
-                               } else {
-                                       disp = dseg_add_functionptr(cd, bte->stub);
-                               }
-
-                               if (N_VALID_DSEG_DISP(disp)) {
-                                       N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
-                               } else {
-                                       N_LHI(REG_ITMP1, disp);
-                                       N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
-                               }
-                               break;
-
-                       case ICMD_INVOKESPECIAL:
-                               /* TODO softnull */
-                               /* Implicit NULL pointer check */
-                               M_ILD(REG_ITMP1, REG_A0, 0);
-
-                               /* 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);
-
-                               if (N_VALID_DSEG_DISP(disp)) {
-                                       N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
-                               } else {
-                                       N_LHI(REG_ITMP1, disp);
-                                       N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
-                               }
-                               break;
-
-                       case ICMD_INVOKEVIRTUAL:
-                               /* TODO softnull REG_A0 */
-
-                               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);
-                               break;
-
-                       case ICMD_INVOKEINTERFACE:
-                               /* TODO softnull REG_A0 */
+                       /* generate the actual call */
+                       M_CALL(REG_PV);
+                       break;
 
-                               /* s1 will be negative here, so use (0xFFF + s1) as displacement
-                                * and -0xFFF in index register (itmp1)
-                                */
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+                       /* TODO softnull REG_A0 */
 
-                               if (lm == NULL) {
-                                       patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
 
-                                       s1 = 0;
-                                       s2 = 0;
-                               }
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->clazz->index;
+                               s1 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) +
+                                       sizeof(methodptr) * lm->vftblindex;
+                       }
 
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
+                       /* implicit null-pointer check */
 
-                               /* Implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
-                               N_LHI(REG_ITMP2, s1);
-                               N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
-                               M_ALD(REG_PV, REG_METHODPTR, s2);
-                               break;
-                       }
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_PV, REG_METHODPTR, s1);
 
                        /* generate the actual call */
-
                        M_CALL(REG_PV);
-                       emit_restore_pv(cd);
-
-                       /* post call finalization */
-
-                       switch (iptr->opc) {
-                               case ICMD_BUILTIN:
-                                       if (bte->stub == NULL) {
-                                               M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
-                                       }
-                                       break;
-                       }
-
-                       /* generate method profiling code */
+                       break;
 
-                       PROFILE_CYCLE_START;
+               case ICMD_INVOKEINTERFACE:
+                       /* TODO softnull REG_A0 */
 
-                       /* store size of call code in replacement point */
+                       /* s1 will be negative here, so use (0xFFF + s1) as displacement
+                        * and -0xFFF in index register (itmp1)
+                        */
 
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-       
-                       /* store return value */
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                       d = md->returntype.type;
+                               s1 = 0;
+                               s2 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr*) * lm->clazz->index;
 
-                       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);
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                        }
 
-                       break;
+                       /* Implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       N_LHI(REG_ITMP2, s1);
+                       N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
+                       M_ALD(REG_PV, REG_METHODPTR, s2);
 
+                       /* generate the actual call */
+                       M_CALL(REG_PV);
+                       break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -3406,37 +2644,11 @@ gen_method:
                        break;
 
                default:
-                       exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
-                       return false;
+                       vm_abort("Unknown ICMD %d during code generation", iptr->opc);
        } /* switch */
-
-       } /* for instruction */
-               
-       MCODECHECK(512); /* XXX require a lower number? */
-
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr) {
-                       M_NOP;
-               }
-       }
-
-       } /* if (bptr -> flags >= BBREACHED) */
-       } /* for basic block */
-
-       /* generate stubs */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
+
 /* codegen_emit_stub_native ****************************************************
 
    Emits a stub routine which calls a native method.
index 3e5262d459631f77cad2ac7bf499570b7a9d1f61..fcaeba52793f822dc6d8e6617e0662afaad0d724 100644 (file)
@@ -730,6 +730,7 @@ static inline uint8_t N_ILL_GET_TYPE(uint8_t *instrp) {
 #define M_ICMP(a, b) N_CR(a, b)
 #define M_ICMPU(a, b) N_CLR(a, b)
 #define M_ICMP_IMM(a, b) N_CHI(a, b)
+#define M_ACMP(a, b) N_CR(a, b)
 #define M_CVTIF(src, dst) N_CEFBR(dst, src)
 #define M_CVTID(src, dst) N_CDFBR(dst, src)
 #define M_FMUL(a, dest) N_MEEBR(dest, a)
@@ -803,42 +804,6 @@ static inline uint8_t N_ILL_GET_TYPE(uint8_t *instrp) {
            ICONST(GET_LOW_REG((reg)), (s4) ((s8) (c))); \
        } while (0)
 
-/* M_INTMOVE:
-    generates an integer-move from register a to b.
-    if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(reg,dreg) \
-    do { \
-        if ((reg) != (dreg)) { \
-            M_MOV(reg, dreg); \
-        } \
-    } while (0)
-
-#define M_LNGMOVE(a, b) \
-    do { \
-        if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \
-            assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-        } else { \
-            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
-            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
-        } \
-    } while (0)
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(reg,dreg) \
-    do { \
-        if ((reg) != (dreg)) { \
-            M_FMOV(reg, dreg); \
-        } \
-    } while (0)
-
 #define M_ISUB_IMM32(imm, tmpreg, reg) \
        do { \
                if (N_VALID_IMM(imm)) { \
index 0720e1387008dc512f22cb2aa7746bfb5adc7d79..358d154e627ec95008fa9a86b83b26ef90e612b9 100644 (file)
@@ -215,6 +215,30 @@ void emit_copy(jitdata *jd, instruction *iptr)
        }
 }
 
+
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       int32_t disp;
+
+       if (N_VALID_IMM(value)) {
+               M_ICMP_IMM(reg, value);
+       } else {
+               disp = dseg_add_s4(cd, iptr->sx.val.i);
+               if (N_VALID_DSEG_DISP(disp)) {
+                       N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
+               } else {
+                       assert(reg != REG_ITMP2);
+                       ICONST(REG_ITMP2, disp);
+                       N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
+               }
+       }
+}
+
+
 /* emit_trap *******************************************************************
 
    Emit a trap instruction and return the original machine code.
@@ -236,6 +260,160 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+
+               for (p = 0; p < INT_ARG_CNT; p++)
+                       M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
+       }
+#endif
+
+       /* decide which monitor enter function to call */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, &m->clazz->object.header);
+               M_ALD_DSEG(REG_A0, disp);
+       }
+       else {
+               M_TEST(REG_A0);
+               M_BNE(SZ_BRC + SZ_ILL);
+               M_ILL(TRAP_NullPointerException);
+       }
+
+       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+       M_ALD_DSEG(REG_ITMP2, disp);
+
+       M_AST(REG_A0, REG_SP, syncslot_offset);
+
+       M_ASUB_IMM(96, REG_SP); 
+       M_CALL(REG_ITMP2);
+       M_AADD_IMM(96, REG_SP); 
+
+#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, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+       }
+#endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+               M_IST(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
+               /* fall through */
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_FLT:
+               M_FST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       }
+
+       M_ALD(REG_A0, REG_SP, syncslot_offset);
+
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_ALD_DSEG(REG_ITMP2, disp);
+
+       M_ASUB_IMM(96, REG_SP);
+       M_CALL(REG_ITMP2);
+       M_AADD_IMM(96, REG_SP);
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+               M_ILD(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
+               /* fall through */
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT , REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_FLT:
+               M_FLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
+               break;
+       }
+}
+#endif
+
+
+/**
+ * Emit profiling code for method frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code)
+{
+       M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
+       ICONST(REG_ITMP2, 1);
+       N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
+       M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
+}
+#endif
+
+
+/**
+ * Emit profiling code for basicblock frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
+{
+       M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
+       M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
+       ICONST(REG_ITMP2, 1);
+       N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
+       M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
@@ -770,7 +948,7 @@ void emit_exception_check(codegendata *cd, instruction *iptr)
        }
 }
 
-void emit_restore_pv(codegendata *cd) {
+void emit_recompute_pv(codegendata *cd) {
        s4 offset, offset_imm;
 
        /*
index cbb7f9b6df26dd1609b9144d02f7a4548aa306be..7f6c131d78771993c9586883c97bb0b8265839c4 100644 (file)
 #include "vm/jit/methodtree.h"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On S390 we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 5897ad13ae47b817ad38c5810f821b4902c7d376..48c674101ca8bf66fb34b78b1546a231026c73ae 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
+/* stackframe *****************************************************************/
+
+#error Set the values below correctly!!!
+#define STACKFRMAE_RA_BETWEEN_FRAMES              0
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
index 1de656e749b74e8aefc6ce82f545b00b1dfbc682..5ca25f250608960884e794fb92ff6574a9354c33 100644 (file)
@@ -58,7 +58,6 @@
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 #include "vm/jit/sparc64/solaris/macro_rename.h"
@@ -121,41 +120,7 @@ bool check_13bit_imm(s8 imm)
 
 bool codegen_emit(jitdata *jd)
 {
-       methodinfo         *m;
-       codeinfo           *code;
-       codegendata        *cd;
-       registerdata       *rd;
-       s4                  len, s1, s2, s3, d, disp, slots;
-       varinfo            *var;
-       basicblock         *bptr;
-       instruction        *iptr;
-       u2                  currentline;
-       constant_classref  *cr;
-       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;
-       currentline = 0;
-       lm = NULL;
-       bte = NULL;
-
-       {
-       s4 i, p, t, l;
        s4 savedregs_num;
        s4 framesize_disp;
 
@@ -165,13 +130,6 @@ bool codegen_emit(jitdata *jd)
        savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */ 
 
 
-       /* 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 */
        if (checksync && code_is_synchronized(code))
                cd->stackframesize++;
@@ -182,22 +140,33 @@ bool codegen_emit(jitdata *jd)
        if (cd->stackframesize & 1)
                cd->stackframesize++;
 
-       /* create method header */
 
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
 
-       code->synchronizedoffset = JITSTACK + rd->memuse * 8;
 
-       /* REMOVEME: We still need it for exception handling in assembler. */
 
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);
-       else
-               (void) dseg_add_unique_s4(cd, 0);
 
-       (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
-       (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+
+
+
+
+
+/**
+ * Generates machine code for the method prolog.
+ */
+void codegen_emit_prolog(jitdata* jd)
+{
+       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;
 
        /* save register window and create stack frame (if necessary) */
 
@@ -219,61 +188,6 @@ bool codegen_emit(jitdata *jd)
        }
 #endif
 
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
-       
-       
-               /* call monitorenter function */
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse;
-
-               /* save float argument registers */
-
-               /* XXX jit-c-call */
-               slots = FLT_ARG_CNT;
-               ALIGN_STACK_SLOTS(slots);
-
-               M_LDA(REG_SP, REG_SP, -(slots * 8));
-               for (i = 0; i < FLT_ARG_CNT; i++)
-                       M_DST(abi_registers_float_argument[i], REG_SP, CSTACK +  i * 8);
-
-               s1 += slots;
-
-               /* get correct lock object */
-
-               if (m->flags & ACC_STATIC) {
-                       disp = dseg_add_address(cd, &m->clazz->object.header);
-                       M_ALD(REG_OUT0, REG_PV, disp);
-                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-               }
-               else {
-                       /* copy class pointer: $i0 -> $o0 */
-                       M_MOV(REG_RESULT_CALLEE, REG_OUT0);
-                       M_BNEZ(REG_OUT0, 3);
-                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-                       M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
-                       M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
-               }
-
-               M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
-               M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8);             /* branch delay */
-
-               /* restore float argument registers */
-
-               for (i = 0; i < FLT_ARG_CNT; i++)
-                       M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
-
-               M_LDA(REG_SP, REG_SP, slots * 8);
-       }
-#endif
-
-
        /* take arguments out of register or stack frame */
        
        md = m->parseddesc;
@@ -356,7 +270,7 @@ bool codegen_emit(jitdata *jd)
                } else {                                     /* floating args         */
                        if (!md->params[p].inmemory) {           /* register arguments    */
                                if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
-                                       M_FLTMOVE(s1, var->vv.regoff);
+                                       emit_fmove(cd, s1, var->vv.regoff);
 
                                } else {                                         /* reg arg -> spilled    */
                                        M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
@@ -372,107 +286,42 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        } /* end for */
-       
-       
-       }
-       
-       /* 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);
-
-
-               /* copy interface registers to their destination */
-
-               len = bptr->indepth;
-               MCODECHECK(64+len);
-               
-#if defined(ENABLE_LSRA)
-#error XXX LSRA not tested yet
-               if (opt_lsra) {
-               while (len) {
-                       len--;
-                       src = bptr->invars[len];
-                       if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
-                                       /*                              d = reg_of_var(m, src, REG_ITMP1); */
-                                       if (!(src->flags & INMEMORY))
-                                               d = src->vv.regoff;
-                                       else
-                                               d = REG_ITMP1;
-                                       M_INTMOVE(REG_ITMP1, d);
-                                       emit_store(jd, NULL, src, d);
-                               }
-                       }
-               } else {
-#endif
-               while (len) {
-                       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_ITMP2_XPTR, d);
-                               emit_store(jd, NULL, var, d);
-                       }
-                       else {
-                               assert((var->flags & INOUT));
-                       }
-               }
-#if defined(ENABLE_LSRA)
-               }
-#endif
-               /* walk through all instructions */
-               
-               len = bptr->icount;
-
-               for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
-                       if (iptr->line != currentline) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
-
-               MCODECHECK(64);       /* an instruction usually needs < 64 words      */
+}
 
-               switch (iptr->opc) {
 
-               case ICMD_INLINE_START:
-               case ICMD_INLINE_END:
-                       break;
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
+       M_NOP;
+}
 
-               case ICMD_NOP:        /* ...  ==> ...                                 */
-                       break;
 
-               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+/**
+ * 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;
+
+       switch (iptr->opc) {
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
-                       break;
-       
                /* constant operations ************************************************/
 
-               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
-
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       ICONST(d, iptr->sx.val.i);
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
                case ICMD_LCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -501,7 +350,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr   = iptr->sx.val.c.ref;
+                               constant_classref *cr = iptr->sx.val.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
                                codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
@@ -522,38 +371,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
-               /* load/store/copy/move operations ************************************/
-
-               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_LLOAD:
-               case ICMD_ALOAD:
-               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;
-
-
-               /* pop/dup/swap operations ********************************************/
-
-               /* attention: double and longs are only one entry in CACAO ICMDs      */
-
-               case ICMD_POP:        /* ..., value  ==> ...                          */
-               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
-                       break;
-
-
                /* integer operations *************************************************/
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
@@ -1886,133 +1703,14 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_INTMOVE(s1, REG_ITMP2_XPTR);
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_class *uc = iptr->sx.s23.s2.uc;
-
-                               codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
                        M_ALD(REG_ITMP1, REG_PV, disp);
                        M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
                        M_NOP;
                        M_NOP;              /* nop ensures that XPC is less than the end */
                                            /* of basic block                            */
-                       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 ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
-                       break;
-                       
-               /* Note: int compares must not branch on the register directly.       */
-               /* Reason is, that register content is not 32-bit clean.              */
-
-               case ICMD_IFEQ:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       }
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_beq(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       } 
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_blt(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       }
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_ble(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-               
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       }
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_bne(cd, iptr->dst.block);
-                       break;
-                                               
-               case ICMD_IFGT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-               
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       } 
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_bgt(cd, iptr->dst.block);          
-                       break;
-
-               case ICMD_IFGE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
-                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                               M_CMP_IMM(s1, iptr->sx.val.i);
-                       }
-                       else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_CMP(s1, REG_ITMP2);
-                       }
-                       emit_bge(cd, iptr->dst.block);
-                       break;
-                       
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
@@ -2125,14 +1823,6 @@ bool codegen_emit(jitdata *jd)
                        emit_beq_xcc(cd, iptr->dst.block);
                        break;
 
-               case ICMD_IF_ICMPEQ:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_beq(cd, iptr->dst.block);
-                       break;
-
                case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
 
@@ -2141,14 +1831,6 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, s2);
                        emit_bne_xcc(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_ICMPNE:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_bne(cd, iptr->dst.block);
-                       break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
 
@@ -2157,14 +1839,6 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, s2);
                        emit_blt_xcc(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_ICMPLT:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_blt(cd, iptr->dst.block);
-                       break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
 
@@ -2173,14 +1847,6 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, s2);
                        emit_bgt_xcc(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_ICMPGT:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_bgt(cd, iptr->dst.block);
-                       break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
 
@@ -2189,15 +1855,6 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, s2);
                        emit_ble_xcc(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_ICMPLE:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_ble(cd, iptr->dst.block);
-                       break;                  
-       
 
                case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
 
@@ -2206,105 +1863,6 @@ bool codegen_emit(jitdata *jd)
                        M_CMP(s1, s2);
                        emit_bge_xcc(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_ICMPGE:    /* 32-bit compare                             */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       emit_bge(cd, iptr->dst.block);
-                       break;
-
-
-               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_LRETURN:
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-                       s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
-                       M_INTMOVE(s1, REG_RESULT_CALLEE);
-                       goto nowperformreturn;
-
-               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-                       s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
-                       M_INTMOVE(s1, REG_RESULT_CALLEE);
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_class *uc = iptr->sx.s23.s2.uc;
-
-                               codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-                       goto nowperformreturn;
-
-               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_DRETURN:
-
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                       M_DBLMOVE(s1, REG_FRESULT);
-                       goto nowperformreturn;
-
-               case ICMD_RETURN:       /* ...  ==> ...                               */
-                       
-                       REPLACEMENT_POINT_RETURN(cd, iptr);
-
-nowperformreturn:
-                       {
-                       s4 i, p;
-                       
-                       p = cd->stackframesize;
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               /* XXX jit-c-call */
-                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-
-                               /* we need to save fp return value (int saved by window) */
-
-                               switch (iptr->opc) {
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
-                                       M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
-                                       M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
-
-                                       /* restore the fp return value */
-
-                                       M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
-                                       break;
-                               case ICMD_IRETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_RETURN:
-                                       M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
-                                       M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
-                                       break;
-                               default:
-                                       assert(false);
-                                       break;
-                               }
-                       }
-#endif
-
-
-
-                       M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
-                       M_NOP;
-                       ALIGNCODENOP;
-                       }
-                       break;
 
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
@@ -2361,40 +1919,11 @@ nowperformreturn:
                        M_NOP;
                        ALIGNCODENOP;
                        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 >= -4096) && (lookup->value <= 4095)) {
-                                       M_CMP_IMM(s1, lookup->value);
-                               } else {                                        
-                                       ICONST(REG_ITMP2, lookup->value);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               emit_beq(cd, lookup->target.block);
-                               ++lookup;
-                       }
-
-                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       ALIGNCODENOP;
-                       break;
-                       }
-
 
+               // XXX This is the old builtin invocation containing some
+               // special argument handling code, port me!
                case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
 
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
-
                        bte = iptr->sx.s23.s3.bte;
                        md = bte->md;
                        
@@ -2442,41 +1971,11 @@ nowperformreturn:
 #else
                        assert(md->argfltreguse == 0);
 #endif
-                       
-                       goto gen_method;
 
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
 
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
 
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
-                               um = iptr->sx.s23.s3.um;
-                               md = um->methodref->parseddesc.md;
-                       }
-                       else {
-                               lm = iptr->sx.s23.s3.fmiref->p.method;
-                               um = NULL;
-                               md = lm->parseddesc;
-                       }
-
-gen_method:
-                       s3 = md->paramcount;
-
-                       MCODECHECK((s3 << 1) + 64);
-
-                       /* copy arguments to registers or stack location                  */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d  = md->params[s3].regoff;
-
-                               if (var->flags & PREALLOC)
-                                       continue;
 
+XXXXXX
                                if (IS_INT_LNG_TYPE(var->type)) {
                                        if (!md->params[s3].inmemory) {
                                                s1 = emit_load(jd, iptr, var, d);
@@ -2487,159 +1986,122 @@ gen_method:
                                                M_STX(s1, REG_SP, JITSTACK + d);
                                        }
                                }
-                               else {
-#ifdef BUILTIN_FLOAT_ARGS
-                                       if (iptr->opc == ICMD_BUILTIN)
-                                               continue;
-#endif
-                                               
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DMOV(s1, d);
-                                               else
-                                                       M_FMOV(s1, d);
-                                       }
-                                       else {
-                                               s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_DST(s1, REG_SP, JITSTACK + d);
-                                       }
-                               }
                        }
+XXXXXX
 
-                       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);
-                               }
+               case ICMD_BUILTIN:
+                       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);
+                       }
 
-                               M_ALD(REG_PV_CALLER, REG_PV, disp);  /* built-in-function pointer */
+                       M_ALD(REG_PV_CALLER, REG_PV, disp);  /* built-in-function pointer */
 
-                               /* XXX jit-c-call */
-                               /* generate the actual call */
-    
-                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
-                           M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
-                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
-
-                               if (md->returntype.type == TYPE_FLT) {
-                                       /* special handling for float return value in %f0 */
-                                       M_FMOV_INTERN(0,1);
-                               }
-                               break;
+                       /* XXX jit-c-call */
+                       /* generate the actual call */
+   
+                   M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                   M_NOP;
 
-                       case ICMD_INVOKESPECIAL:
-                               emit_nullpointer_check(cd, iptr, REG_OUT0);
-                               /* fall-through */
+                       if (md->returntype.type == TYPE_FLT) {
+                               /* special handling for float return value in %f0 */
+                               M_FMOV_INTERN(0,1);
+                       }
+                       break;
 
-                       case ICMD_INVOKESTATIC:
-                               if (lm == NULL) {
-                                       disp = dseg_add_unique_address(cd, NULL);
+               case ICMD_INVOKESPECIAL:
+                       emit_nullpointer_check(cd, iptr, REG_OUT0);
+                       /* fall-through */
 
-                                       codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
-                                                                               um, disp);
-                               }
-                               else
-                                       disp = dseg_add_address(cd, lm->stubroutine);
+               case ICMD_INVOKESTATIC:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               disp = dseg_add_unique_address(cd, NULL);
 
-                               M_ALD(REG_PV_CALLER, REG_PV, disp);          /* method pointer in pv */
-                               
-                               /* generate the actual call */
-    
-                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
-                           M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
-                               break;
+                               codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
+                                                                       um, disp);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               disp = dseg_add_address(cd, lm->stubroutine);
+                       }
 
-                       case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_OUT0);
+                       M_ALD(REG_PV_CALLER, REG_PV, disp);          /* method pointer in pv */
+                       
+                       /* generate the actual call */
+   
+                   M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                   M_NOP;
+                       break;
 
-                               if (lm == NULL) {
-                                       codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
+               case ICMD_INVOKEVIRTUAL:
+                       emit_nullpointer_check(cd, iptr, REG_OUT0);
 
-                                       s1 = 0;
-                               }
-                               else
-                                       s1 = OFFSET(vftbl_t, table[0]) +
-                                               sizeof(methodptr) * lm->vftblindex;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
 
-                               /* implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
-                               
-                               /* generate the actual call */
-    
-                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
-                           M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
-                               break;
+                               s1 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) +
+                                       sizeof(methodptr) * lm->vftblindex;
+                       }
 
-                       case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_OUT0);
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
+                       
+                       /* generate the actual call */
+   
+                   M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                   M_NOP;
+                       break;
 
-                               if (lm == NULL) {
-                                       codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
+               case ICMD_INVOKEINTERFACE:
+                       emit_nullpointer_check(cd, iptr, REG_OUT0);
 
-                                       s1 = 0;
-                                       s2 = 0;
-                               } 
-                               else {
-                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                               sizeof(methodptr*) * lm->clazz->index;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
 
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
+                               s1 = 0;
+                               s2 = 0;
+                       } 
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr*) * lm->clazz->index;
 
-                               /* implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
-                               M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
-
-                           /* generate the actual call */
-    
-                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
-                           M_NOP;
-                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
-                               break;
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                        }
 
-                       /* store return value */
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
+                       M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+                       M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
 
-                       d = md->returntype.type;
+                   /* generate the actual call */
+   
+                   M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                   M_NOP;
+                       break;
 
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
-                                       M_INTMOVE(REG_RESULT_CALLER, s1);
-                               } 
-                               else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                                       if (IS_2_WORD_TYPE(d)) {
-                                               M_DBLMOVE(REG_FRESULT, s1);
-                                       } else {
-                                               M_FLTMOVE(REG_FRESULT, s1);
-                                       }
+XXXXXX
+                       /* store return value */
+                       else {
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                               if (IS_2_WORD_TYPE(d)) {
+                                       emit_dmove(cd, REG_FRESULT, s1);
+                               } else {
+                                       emit_fmove(cd, REG_FRESULT, s1);
                                }
-                               emit_store_dst(jd, iptr, s1);
                        }
-                       break;
-
+XXXXX
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
                                      /* val.a: (classinfo*) superclass               */
@@ -2677,7 +2139,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
 
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
@@ -2692,7 +2154,7 @@ gen_method:
 
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
-                                               cr = iptr->sx.s23.s3.c.ref;
+                                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
 
                                                codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
                                                                                          cr, 0);
@@ -2724,7 +2186,7 @@ gen_method:
                                        if (super == NULL) {
                                                emit_label(cd, BRANCH_LABEL_2);
 
-                                               cr   = iptr->sx.s23.s3.c.ref;
+                                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
                                                codegen_add_patch_ref(cd,
@@ -2770,7 +2232,7 @@ gen_method:
                                disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
@@ -2842,7 +2304,7 @@ gen_method:
                        if (super == NULL) {
                                emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
-                               cr   = iptr->sx.s23.s3.c.ref;
+                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
 
                                codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
@@ -2857,7 +2319,7 @@ gen_method:
 
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
-                                       cr = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
 
                                        codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
                                                                                  cr, 0);
@@ -2888,7 +2350,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label(cd, BRANCH_LABEL_2);
 
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
@@ -2984,37 +2446,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 */
-
-       MCODECHECK(64);
-       
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr) {
-                       M_NOP;
-               }
-       }
-               
-       } /* if (bptr -> flags >= BBREACHED) */
-       } /* for basic block */
-       
-       /* generate stubs */
-
-       emit_patcher_stubs(jd);
-       
-       /* everything's ok */
-
-       return true;    
 }
 
 
index b64cf4fc656ed4f6bf991b7ae42fee51ee512caf..35759493a501e76b46983d9d473a06609b4310a3 100644 (file)
@@ -92,31 +92,6 @@ s4 nat_argintregs[INT_NATARG_CNT];
                slots++;
 
 
-/* M_INTMOVE:
-     generates an integer-move from register rs to rd.
-     if rs and rd are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(rs,rd) if (rs != rd) { M_MOV(rs, rd); }
-
-
-/* M_DBLMOVE:
-    generates a double floating-point-move from register (pair) rs to rd.
-    if rs and rd are the same double-register, no code will be generated
-*/ 
-
-#define M_DBLMOVE(rs, rd) if (rs != rd) { M_DMOV (rs, rd); }
-
-
-/* M_FLTMOVE:
-    generates a double floating-point-move from pseudo register rs to rd.
-       (ie. lower register of double rs pair to lower register of double rd pair)
-    if rs and rd are the same double-register, no code will be generated
-*/ 
-#define M_FLTMOVE(rs, rd) if (rs != rd) { M_FMOV (rs, rd); }
-
-
-
 #define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
 #define ICONST(d,c)                     emit_iconst(cd, (d), (c))
 #define LCONST(d,c)                     emit_lconst(cd, (d), (c))
@@ -692,6 +667,8 @@ s4   get_lopart_disp(s4 disp);
 #define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
 #define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
 #define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
-       
+
+#define M_ACMP(a,b)             M_CMP(a,b)
+#define M_ICMP(a,b)             M_CMP(a,b)
 
 #endif /* _CODEGEN_H */
index 0c71d11a786dad601fb80cc9fea719a3fc1f54f4..e4d9a3fa6ae668fd952b88eebb67935b860cd646 100644 (file)
@@ -239,6 +239,23 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
        }
 }
 
+
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       if ((value >= -4096) && (value <= 4095)) {
+               M_CMP_IMM(reg, value);
+       } else {
+               assert(reg != REG_ITMP2);
+               ICONST(REG_ITMP2, value);
+               M_CMP(reg, REG_ITMP2);
+       }
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -583,6 +600,124 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Emit code to recompute the procedure vector.
+ */
+void emit_recompute_pv(codegendata *cd)
+{
+       int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
+
+       /* REG_RA holds the value of the jmp instruction, therefore +8 */
+       M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
+}
+
+
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t i, slots;
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               /* save float argument registers */
+
+               /* XXX jit-c-call */
+               slots = FLT_ARG_CNT;
+               ALIGN_STACK_SLOTS(slots);
+
+               M_LDA(REG_SP, REG_SP, -(slots * 8));
+               for (i = 0; i < FLT_ARG_CNT; i++)
+                       M_DST(abi_registers_float_argument[i], REG_SP, CSTACK +  i * 8);
+
+               syncslot_offset += slots * 8;
+       }
+# endif
+
+       /* get correct lock object */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, &m->clazz->object.header);
+               M_ALD(REG_OUT0, REG_PV, disp);
+               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+       }
+       else {
+               /* copy class pointer: $i0 -> $o0 */
+               M_MOV(REG_RESULT_CALLEE, REG_OUT0);
+               M_BNEZ(REG_OUT0, 3);
+               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+               M_ALD(REG_ITMP3, REG_PV, disp);                       /* branch delay */
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
+       }
+
+       M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+       M_AST(REG_OUT0, REG_SP, CSTACK + syncslot_offset);        /* branch delay */
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               /* restore float argument registers */
+
+               for (i = 0; i < FLT_ARG_CNT; i++)
+                       M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
+
+               M_LDA(REG_SP, REG_SP, slots * 8);
+       }
+# endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t disp;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       /* XXX jit-c-call */
+       disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+       M_ALD(REG_ITMP3, REG_PV, disp);
+
+       /* we need to save fp return value (int saved by window) */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_ALD(REG_OUT0, REG_SP, CSTACK + syncslot_offset);
+               M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+               M_DST(REG_FRESULT, REG_SP, CSTACK + syncslot_offset); /* delay */
+
+               /* restore the fp return value */
+
+               M_DLD(REG_FRESULT, REG_SP, CSTACK + syncslot_offset);
+               break;
+       case TYPE_INT:
+       case TYPE_LNG:
+       case TYPE_DBL:
+       default:
+               M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+               M_ALD(REG_OUT0, REG_SP, CSTACK + syncslot_offset); /* delay */
+               break;
+       }
+}
+#endif
+
+
 /* emit_patcher_stubs **********************************************************
 
    Generates the code for the patcher stubs.
index f47f7750d88747e331d0b228e4231be8ffb36ace..8f71e2fae9cba28060a174dbc609765beba246d3 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On SPARC we use 8-byte stackslots.
+#error Verify the below line, then remove this error!
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index b51154ed2578fdb94b3068f88660ece7eb2bffa1..ad3b438255da749d1107fa5f5e974d6e5e9e59dd 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "vm/types.h"
 
+#include "arch.h"
 #include "md.h"
 
 #include "mm/gc.hpp"
@@ -138,7 +139,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, vo
                /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
                   the RA from stack. */
 
-               framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+               framesize = md_stacktrace_get_framesize(code);
 
                ra = md_stacktrace_get_returnaddress(sp, framesize);
 # else
@@ -149,7 +150,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, vo
                   the asm_vm_call_method special case. */
 
                if ((code == NULL) || !code_is_leafmethod(code)) {
-                       framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+                       framesize = md_stacktrace_get_framesize(code);
 
                        ra = md_stacktrace_get_returnaddress(sp, framesize);
                }
@@ -306,7 +307,7 @@ static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
  
        /* Get the current stack frame size. */
 
-       framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
+       framesize = md_stacktrace_get_framesize(code);
 
        /* Get the RA of the current stack frame (RA to the parent Java
           method) if the current method is a non-leaf method.  Otherwise
@@ -357,7 +358,7 @@ static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
        else
 #endif
                {
-#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
+#if STACKFRMAE_RA_BETWEEN_FRAMES
                        sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
 #elif defined(__SPARC_64__)
                        /* already has the new sp */
index 7bd7d809de65cc93262764c3d4cd06506cf60d7e..787eba2d30dc97d9f87c0a5180ddabf922047c4c 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
 
 
+/* stackframe *****************************************************************/
+
+#define STACKFRMAE_RA_BETWEEN_FRAMES              1
+#define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
+
+
 /* replacement ****************************************************************/
 
 #define REPLACEMENT_PATCH_SIZE           2             /* bytes */
index 008172b196548bf2828d28fbc097875d8cee57ea..61c86520adac4c06c365ecc0f722c52b250af9f2 100644 (file)
 #include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-
-/* codegen_emit ****************************************************************
-
-   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;
-       u2                  currentline;
-       ptrint              a;
-       varinfo            *var, *dst;
-       basicblock         *bptr;
-       instruction        *iptr;
-       constant_classref  *cr;
-       unresolved_class   *uc;
-       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;
-       lm  = NULL;
-       um  = 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 */
-
-       if (checksync && code_is_synchronized(code))
-               cd->stackframesize++;
-#endif
-
-       /* Keep stack of non-leaf functions 16-byte aligned for calls into
-          native code e.g. libc or jni (alignment problems with
-          movaps). */
-
-       if (!code_is_leafmethod(code) || opt_verbosecall)
-               cd->stackframesize |= 0x1;
-
-       /* create method header */
-
-       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
-
-       code->synchronizedoffset = rd->memuse * 8;
-
-       if (code_is_leafmethod(code))
-               (void) dseg_add_unique_s4(cd, 1);                  /* IsLeaf          */
-       else
-               (void) dseg_add_unique_s4(cd, 0);                  /* 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 */
-
-#if defined(ENABLE_PROFILING)
-       /* generate method profiling code */
-
-       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-               /* count frequency */
-
-               M_MOV_IMM(code, REG_ITMP3);
-               M_IINC_MEMBASE(REG_ITMP3, 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;
+       codegendata*  cd = jd->cd;
+       registerdata* rd = jd->rd;
 
        /* create stack frame (if necessary) */
 
@@ -227,7 +141,7 @@ bool codegen_emit(jitdata *jd)
                else {                                     /* floating args         */
                        if (!md->params[p].inmemory) {           /* register arguments    */
                                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);
                        }
@@ -239,201 +153,64 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        }
+}
 
-       /* save monitorenter argument */
-
-#if defined(ENABLE_THREADS)
-       if (checksync && code_is_synchronized(code)) {
-               /* stack offset for monitor argument */
-
-               s1 = rd->memuse;
-
-               if (opt_verbosecall) {
-                       M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LST(abi_registers_integer_argument[p], REG_SP, p * 8);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
-
-                       s1 += INT_ARG_CNT + FLT_ARG_CNT;
-               }
-
-               /* decide which monitor enter function to call */
 
-               if (m->flags & ACC_STATIC) {
-                       M_MOV_IMM(&m->clazz->object.header, REG_A0);
-               }
-               else {
-                       M_TEST(REG_A0);
-                       M_BNE(8);
-                       M_ALD_MEM(REG_A0, TRAP_NullPointerException);
-               }
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+       int32_t p;
+       int i;
 
-               M_AST(REG_A0, REG_SP, s1 * 8);
-               M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
-               M_CALL(REG_ITMP1);
+       // Get required compiler data.
+       codegendata*  cd = jd->cd;
+       registerdata* rd = jd->rd;
 
-               if (opt_verbosecall) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8);
+       p = cd->stackframesize;
 
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+       /* restore saved registers */
 
-                       M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
-               }
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
        }
-#endif
-
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif /* !defined(NDEBUG) */
-
+       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 = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
-
-               if (bptr->flags >= BBREACHED) {
-
-               /* branch resolving */
-
-               codegen_resolve_branchrefs(cd, bptr);
-
-               /* handle replacement points */
-
-               REPLACEMENT_POINT_BLOCK_START(cd, bptr);
-
-               /* copy interface registers to their destination */
-
-               len = bptr->indepth;
-               MCODECHECK(512);
-
-#if defined(ENABLE_PROFILING)
-               /* generate basicblock profiling code */
-
-               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
-                       /* count frequency */
-
-                       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
-                       M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
-
-                       /* if this is an exception handler, start profiling again */
-
-                       if (bptr->type == BBTYPE_EXH)
-                               PROFILE_CYCLE_START;
-               }
-#endif
-
-#if defined(ENABLE_LSRA)
-               if (opt_lsra) {
-                       while (len) {
-                               len--;
-                               src = bptr->invars[len];
-                               if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
-                                       if (bptr->type == BBTYPE_EXH) {
-/*                                     d = reg_of_var(rd, 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);
-                                       }
-                               }
-                       }
-                       
-               } else {
-#endif
-
-               while (len) {
-                       len--;
-                       var = VAR(bptr->invars[len]);
-                       if ((len ==  bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
-                               if (bptr->type == BBTYPE_EXH) {
-                                       d = codegen_reg_of_var(0, var, REG_ITMP1);
-                                       M_INTMOVE(REG_ITMP1, d);
-                                       emit_store(jd, NULL, var, d);
-                               }
-                       } 
-                       else {
-                               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) {
-                               linenumbertable_list_entry_add(cd, iptr->line);
-                               currentline = iptr->line;
-                       }
-
-                       MCODECHECK(1024);                         /* 1KB should be enough */
-
-               switch (iptr->opc) {
-               case ICMD_NOP:        /* ...  ==> ...                                 */
-               case ICMD_POP:        /* ..., value  ==> ...                          */
-               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
-                       break;
-
-               case ICMD_INLINE_START:
+       /* deallocate stack */
 
-                       REPLACEMENT_POINT_INLINE_START(cd, iptr);
-                       break;
-
-               case ICMD_INLINE_BODY:
-
-                       REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
-                       linenumbertable_list_entry_add_inline_start(cd, iptr);
-                       linenumbertable_list_entry_add(cd, iptr->line);
-                       break;
-
-               case ICMD_INLINE_END:
+       if (cd->stackframesize)
+               M_AADD_IMM(cd->stackframesize * 8, REG_SP);
 
-                       linenumbertable_list_entry_add_inline_end(cd, iptr);
-                       linenumbertable_list_entry_add(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;
+       varinfo*            dst;
+       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.
+       codegendata*  cd = jd->cd;
+
+       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_ITMP1);
-                       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);
@@ -455,7 +232,7 @@ bool codegen_emit(jitdata *jd)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr   = iptr->sx.val.c.ref;
+                               constant_classref *cr = iptr->sx.val.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
 /*                             PROFILE_CYCLE_STOP; */
@@ -480,28 +257,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                 */
@@ -1170,7 +925,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        disp = dseg_add_s4(cd, 0x80000000);
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
                        emit_xorps_reg_reg(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
@@ -1181,7 +936,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        disp = dseg_add_s8(cd, 0x8000000000000000);
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
                        emit_xorpd_reg_reg(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
@@ -1195,7 +950,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_FADD(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_FADD(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1209,7 +964,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_DADD(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_DADD(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1221,10 +976,10 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        if (s2 == d) {
-                               M_FLTMOVE(s2, REG_FTMP2);
+                               emit_fmove(cd, s2, REG_FTMP2);
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1235,10 +990,10 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        if (s2 == d) {
-                               M_FLTMOVE(s2, REG_FTMP2);
+                               emit_fmove(cd, s2, REG_FTMP2);
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1251,7 +1006,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_FMUL(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_FMUL(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1265,7 +1020,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_DMUL(s1, d);
                        else {
-                               M_FLTMOVE(s1, d);
+                               emit_fmove(cd, s1, d);
                                M_DMUL(s2, d);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -1277,10 +1032,10 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        if (s2 == d) {
-                               M_FLTMOVE(s2, REG_FTMP2);
+                               emit_fmove(cd, s2, REG_FTMP2);
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1291,10 +1046,10 @@ bool codegen_emit(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
                        if (s2 == d) {
-                               M_FLTMOVE(s2, REG_FTMP2);
+                               emit_fmove(cd, s2, REG_FTMP2);
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1340,7 +1095,7 @@ bool codegen_emit(jitdata *jd)
                        disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
                                ((REG_RESULT == d) ? 0 : 3);
                        M_BNE(disp);
-                       M_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
                        M_CALL(REG_ITMP2);
                        M_INTMOVE(REG_RESULT, d);
@@ -1356,7 +1111,7 @@ bool codegen_emit(jitdata *jd)
                        disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
                                ((REG_RESULT == d) ? 0 : 3);
                        M_BNE(disp);
-                       M_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
                        M_CALL(REG_ITMP2);
                        M_INTMOVE(REG_RESULT, d);
@@ -1373,7 +1128,7 @@ bool codegen_emit(jitdata *jd)
                        disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
                                ((REG_RESULT == d) ? 0 : 3);
                        M_BNE(disp);
-                       M_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
                        M_CALL(REG_ITMP2);
                        M_INTMOVE(REG_RESULT, d);
@@ -1390,7 +1145,7 @@ bool codegen_emit(jitdata *jd)
                        disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
                                ((REG_RESULT == d) ? 0 : 3);
                        M_BNE(disp);
-                       M_FLTMOVE(s1, REG_FTMP1);
+                       emit_fmove(cd, s1, REG_FTMP1);
                        M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
                        M_CALL(REG_ITMP2);
                        M_INTMOVE(REG_RESULT, d);
@@ -1480,15 +1235,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
-               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       /* 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);
@@ -1730,116 +1476,6 @@ bool codegen_emit(jitdata *jd)
                        emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray_t, data[0]), s1, s2, 3);
                        break;
 
-
-               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, uf);
-
-/*                             PROFILE_CYCLE_STOP; */
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
-
-/*                             PROFILE_CYCLE_START; */
-                       }
-                       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->clazz)) {
-                                       PROFILE_CYCLE_STOP;
-
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                                 fi->clazz, 0);
-
-                                       PROFILE_CYCLE_START;
-                               }
-                       }
-
-                       /* This approach is much faster than moving the field
-                          address inline into a register. */
-
-                       M_ALD(REG_ITMP1, RIP, disp);
-
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_ILD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                       case TYPE_ADR:
-                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                               M_LLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_FLD(d, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:                          
-                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                               M_DLD(d, REG_ITMP1, 0);
-                               break;
-                       }
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
-               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf        = iptr->sx.s23.s3.uf;
-                               fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp      = dseg_add_unique_address(cd, uf);
-
-/*                             PROFILE_CYCLE_STOP; */
-
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
-
-/*                             PROFILE_CYCLE_START; */
-                       }
-                       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->clazz)) {
-                                       PROFILE_CYCLE_STOP;
-
-                                       patcher_add_patch_ref(jd, PATCHER_initialize_class,
-                                                                                 fi->clazz, 0);
-
-                                       PROFILE_CYCLE_START;
-                               }
-                       }
-
-                       /* This approach is much faster than moving the field
-                          address inline into a register. */
-
-                       M_ALD(REG_ITMP1, RIP, disp);
-
-                       switch (fieldtype) {
-                       case TYPE_INT:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_IST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_LNG:
-                       case TYPE_ADR:
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
-                               M_LST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_FLT:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                               M_FST(s1, REG_ITMP1, 0);
-                               break;
-                       case TYPE_DBL:
-                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
-                               M_DST(s1, REG_ITMP1, 0);
-                               break;
-                       }
-                       break;
-
                case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
                                          /* val = value (in current instruction)     */
                                          /* following NOP)                           */
@@ -1861,12 +1497,12 @@ bool codegen_emit(jitdata *jd)
                                disp      = dseg_add_address(cd, fi->value);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
-                                       PROFILE_CYCLE_STOP;
+                                       //PROFILE_CYCLE_STOP;
 
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class,
                                                                                  fi->clazz, 0);
 
-                                       PROFILE_CYCLE_START;
+                                       //PROFILE_CYCLE_START;
                                }
                        }
 
@@ -2024,19 +1660,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_INTMOVE(s1, REG_ITMP1_XPTR);
-
-                       PROFILE_CYCLE_STOP;
-
-#ifdef ENABLE_VERIFIER
-                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uc = iptr->sx.s23.s2.uc;
-
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
-                       }
-#endif /* ENABLE_VERIFIER */
-
                        M_CALL_IMM(0);                            /* passing exception pc */
                        M_POP(REG_ITMP2_XPC);
 
@@ -2044,39 +1667,6 @@ bool codegen_emit(jitdata *jd)
                        M_JMP(REG_ITMP3);
                        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 ==> ...                         */
-               case ICMD_IFNONNULL:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
-                       break;
-
-               case ICMD_IFEQ:         /* ..., value ==> ...                         */
-               case ICMD_IFLT:
-               case ICMD_IFLE:
-               case ICMD_IFNE:
-               case ICMD_IFGT:
-               case ICMD_IFGE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
-                       break;
-
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
                case ICMD_IF_LNE:
                case ICMD_IF_LLT:
@@ -2094,28 +1684,6 @@ bool codegen_emit(jitdata *jd)
                        emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ICMPNE:
-               case ICMD_IF_ICMPLT:
-               case ICMD_IF_ICMPGE:
-               case ICMD_IF_ICMPGT:
-               case ICMD_IF_ICMPLE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
-                       break;
-
-               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
-                       break;
-
                case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
                case ICMD_IF_LCMPNE:
                case ICMD_IF_LCMPLT:
@@ -2129,114 +1697,6 @@ bool codegen_emit(jitdata *jd)
                        emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
-               case ICMD_LRETURN:
-
-                       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)) {
-                               uc = iptr->sx.s23.s2.uc;
-
-                               PROFILE_CYCLE_STOP;
-
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
-
-                               PROFILE_CYCLE_START;
-                       }
-#endif /* ENABLE_VERIFIER */
-                       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;
-
-#if !defined(NDEBUG)
-                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-                               emit_verbosecall_exit(jd);
-#endif /* !defined(NDEBUG) */
-
-#if defined(ENABLE_THREADS)
-                       if (checksync && code_is_synchronized(code)) {
-                               M_ALD(REG_A0, REG_SP, rd->memuse * 8);
-       
-                               /* we need to save the proper return value */
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_LRETURN:
-                                       M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-
-                               M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
-                               M_CALL(REG_ITMP1);
-
-                               /* and now restore the proper return value */
-                               switch (iptr->opc) {
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_LRETURN:
-                                       M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
-                                       break;
-                               }
-                       }
-#endif
-
-                       /* restore saved registers */
-
-                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
-                               p--; M_LLD(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_AADD_IMM(cd->stackframesize * 8, REG_SP);
-
-                       /* generate method profiling code */
-
-                       PROFILE_CYCLE_STOP;
-
-                       M_RET;
-                       }
-                       break;
-
-
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2280,204 +1740,79 @@ nowperformreturn:
                        }
                        break;
 
-
-               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
-                       {
-                               s4 i;
-                               lookup_target_t *lookup;
-
-                               lookup = iptr->dst.lookup;
-
-                               i = iptr->sx.s23.s2.lookupcount;
-                       
-                               MCODECHECK(8 + ((7 + 6) * i) + 5);
-                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
-                               while (--i >= 0) {
-                                       M_ICMP_IMM(lookup->value, s1);
-                                       emit_beq(cd, lookup->target.block);
-                                       lookup++;
-                               }
-
-                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
-                               ALIGNCODENOP;
+               case ICMD_BUILTIN:
+                       bte = iptr->sx.s23.s3.bte;
+                       if (bte->stub == NULL) {
+                               M_MOV_IMM(bte->fp, REG_ITMP1);
                        }
+                       else {
+                               M_MOV_IMM(bte->stub, REG_ITMP1);
+                       }
+                       M_CALL(REG_ITMP1);
                        break;
 
+               case ICMD_INVOKESPECIAL:
+                       emit_nullpointer_check(cd, iptr, REG_A0);
+                       /* fall through */
 
-               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
-
-                       bte = iptr->sx.s23.s3.bte;
-                       md  = bte->md;
-                       goto gen_method;
-
-               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
-
-               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
-               case ICMD_INVOKEINTERFACE:
-
-                       REPLACEMENT_POINT_INVOKE(cd, iptr);
-
+               case ICMD_INVOKESTATIC:
                        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_functionptr(cd, lm->stubroutine);
                        }
 
-gen_method:
-                       s3 = md->paramcount;
-
-                       MCODECHECK((20 * s3) + 128);
-
-                       /* copy arguments to registers or stack location */
-
-                       for (s3 = s3 - 1; s3 >= 0; s3--) {
-                               var = VAR(iptr->sx.s23.s2.args[s3]);
-                               d   = md->params[s3].regoff;
-
-                               /* already preallocated (ARGVAR)? */
-
-                               if (var->flags & PREALLOC)
-                                       continue;
+                       M_ALD(REG_ITMP2, RIP, disp);
+                       M_CALL(REG_ITMP2);
+                       break;
 
-                               if (IS_INT_LNG_TYPE(var->type)) {
-                                       if (!md->params[s3].inmemory) {
-                                               s1 = emit_load(jd, iptr, var, d);
-                                               M_INTMOVE(s1, d);
-                                       }
-                                       else {
-                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_LST(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);
+               case ICMD_INVOKEVIRTUAL:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
 
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(s1, REG_SP, d);
-                                               else
-                                                       M_FST(s1, REG_SP, d);
-                                       }
-                               }
+                               s1 = 0;
                        }
-
-                       /* generate method profiling code */
-
-                       PROFILE_CYCLE_STOP;
-
-                       switch (iptr->opc) {
-                       case ICMD_BUILTIN:
-                               if (bte->stub == NULL) {
-                                       M_MOV_IMM(bte->fp, REG_ITMP1);
-                               }
-                               else {
-                                       M_MOV_IMM(bte->stub, REG_ITMP1);
-                               }
-                               M_CALL(REG_ITMP1);
-                               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_functionptr(cd, lm->stubroutine);
-                               }
-
-                               M_ALD(REG_ITMP2, RIP, disp);
-                               M_CALL(REG_ITMP2);
-                               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_ALD32(REG_ITMP3, REG_METHODPTR, s1);
-                               M_CALL(REG_ITMP3);
-                               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->clazz->index;
-
-                                       s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
-                               }
-
-                               /* implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
-                               M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
-                               M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
-                               M_CALL(REG_ITMP3);
-                               break;
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, table[0]) +
+                                       sizeof(methodptr) * lm->vftblindex;
                        }
 
-                       /* generate method profiling code */
-
-                       PROFILE_CYCLE_START;
-
-                       /* store size of call code in replacement point */
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
+                       M_CALL(REG_ITMP3);
+                       break;
 
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
+               case ICMD_INVOKEINTERFACE:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
+                               patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
 
-                       /* store return value */
+                               s1 = 0;
+                               s2 = 0;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr) * lm->clazz->index;
 
-                       switch (md->returntype.type) {
-                       case TYPE_INT:
-                       case TYPE_LNG:
-                       case TYPE_ADR:
-                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                               M_INTMOVE(REG_RESULT, s1);
-                               emit_store_dst(jd, iptr, s1);
-                               break;
-                       case TYPE_FLT:
-                       case TYPE_DBL:
-                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                               M_FLTMOVE(REG_FRESULT, s1);
-                               emit_store_dst(jd, iptr, s1);
-                               break;
-                       default:
-                               /* TYPE_VOID */
-                               break;
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
                        }
-                       break;
 
+                       /* implicit null-pointer check */
+                       M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+                       M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
+                       M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
+                       M_CALL(REG_ITMP3);
+                       break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -2551,7 +1886,7 @@ gen_method:
                                        if (super == NULL) {
                                                emit_label(cd, BRANCH_LABEL_2);
 
-                                               cr   = iptr->sx.s23.s3.c.ref;
+                                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, cr);
 
                                                patcher_add_patch_ref(jd,
@@ -2622,7 +1957,7 @@ gen_method:
                                M_INTMOVE(s1, REG_A0);
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, cr);
 
                                        patcher_add_patch_ref(jd,
@@ -2707,7 +2042,7 @@ gen_method:
                                                REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
                                M_ICMP_IMM32(superindex, REG_ITMP3);
 
-                               a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
+                               int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
 
                                M_BLE(a);
                                M_ALD32(REG_ITMP1, REG_ITMP1,
@@ -2728,7 +2063,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label(cd, BRANCH_LABEL_2);
 
-                                       cr   = iptr->sx.s23.s3.c.ref;
+                                       constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, cr);
 
                                        patcher_add_patch_ref(jd,
@@ -2830,7 +2165,7 @@ gen_method:
                        /* is a patcher function set? */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               cr   = iptr->sx.s23.s3.c.ref;
+                               constant_classref *cr = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
                                patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
@@ -2861,36 +2196,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 */
-               
-       MCODECHECK(512); /* XXX require a lower number? */
-
-       /* At the end of a basic block we may have to append some nops,
-          because the patcher stub calling code might be longer than the
-          actual instruction. So codepatching does not change the
-          following block unintentionally. */
-
-       if (cd->mcodeptr < cd->lastmcodeptr) {
-               while (cd->mcodeptr < cd->lastmcodeptr) {
-                       M_NOP;
-               }
-       }
-
-       } /* if (bptr -> flags >= BBREACHED) */
-       } /* for basic block */
-
-       /* Generate patcher traps. */
-
-       emit_patcher_traps(jd);
-
-       /* everything's ok */
-
-       return true;
 }
 
 
index cb073729dd0d69d438a67e1263d05e340a0d4f3a..ce8576e3d9bb421ef6e4e3ca246d2bad44bff592 100644 (file)
     } while (0)
 
 
-/* M_INTMOVE:
-    generates an integer-move from register a to b.
-    if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(reg,dreg) \
-    do { \
-        if ((reg) != (dreg)) { \
-            M_MOV(reg, dreg); \
-        } \
-    } while (0)
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(reg,dreg) \
-    do { \
-        if ((reg) != (dreg)) { \
-            M_FMOV(reg, dreg); \
-        } \
-    } while (0)
-
-
 #define ICONST(r,c) \
     do { \
         if ((c) == 0) \
 #define M_IMOV_IMM(a,b)         emit_movl_imm_reg(cd, (u4) (a), (b))
 
 #define M_FMOV(a,b)             emit_movq_reg_reg(cd, (a), (b))
+#define M_DMOV(a,b)             M_FMOV(a,b)
 
 #define M_ILD(a,b,disp)         emit_movl_membase_reg(cd, (b), (disp), (a))
 #define M_LLD(a,b,disp)         emit_mov_membase_reg(cd, (b), (disp), (a))
     } while (0)
 
 #define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
+#define M_ALD_DSEG(a,disp)      M_ALD(a,RIP,disp)
 
 #define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
 
 #define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
 #define M_ICMP_MEMINDEX(a,b,c,d,e) emit_alu_memindex_reg(cd, ALU_CMP, (b), (a), (c), (d), (e))
 
+#define M_ACMP(a,b)             M_LCMP(a,b)
+
 #define M_BEQ(disp)             emit_jcc(cd, CC_E, (disp))
 #define M_BNE(disp)             emit_jcc(cd, CC_NE, (disp))
 #define M_BLT(disp)             emit_jcc(cd, CC_L, (disp))
 #define M_ISBB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SBB, (a), (b), (c))
 
 
-#if defined(ENABLE_PROFILING)
-
-#define PROFILE_CYCLE_START \
-    do { \
-        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
-            M_PUSH(RAX); \
-            M_PUSH(RDX); \
-            \
-            M_MOV_IMM(code, REG_ITMP3); \
-            M_RDTSC; \
-            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
-            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
-            \
-            M_POP(RDX); \
-            M_POP(RAX); \
-        } \
-    } while (0)
-
-#define PROFILE_CYCLE_STOP \
-    do { \
-        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
-            M_PUSH(RAX); \
-            M_PUSH(RDX); \
-            \
-            M_MOV_IMM(code, REG_ITMP3); \
-            M_RDTSC; \
-            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
-            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
-            \
-            M_POP(RDX); \
-            M_POP(RAX); \
-        } \
-    } while (0)
-
-#else
-
-#define PROFILE_CYCLE_START
-#define PROFILE_CYCLE_STOP
-
-#endif
-
 #endif /* _CODEGEN_H */
 
 
index 398d7d05843a96d1fbff1a8a50c7581b302c266d..649270abe8f7080f871777905a13ff79aebf8e29 100644 (file)
@@ -233,6 +233,16 @@ void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       M_ICMP_IMM(value, reg);
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -461,6 +471,135 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int32_t p;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+
+               for (p = 0; p < INT_ARG_CNT; p++)
+                       M_LST(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
+       }
+# endif
+
+       /* decide which monitor enter function to call */
+
+       if (m->flags & ACC_STATIC) {
+               M_MOV_IMM(&m->clazz->object.header, REG_A0);
+       }
+       else {
+               M_TEST(REG_A0);
+               M_BNE(8);
+               M_ALD_MEM(REG_A0, TRAP_NullPointerException);
+       }
+
+       M_AST(REG_A0, REG_SP, syncslot_offset);
+       M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
+       M_CALL(REG_ITMP1);
+
+# if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+
+               for (p = 0; p < INT_ARG_CNT; p++)
+                       M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8);
+
+               for (p = 0; p < FLT_ARG_CNT; p++)
+                       M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+               M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+       }
+# endif
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       M_ALD(REG_A0, REG_SP, syncslot_offset);
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+       case TYPE_LNG:
+               M_LST(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, syncslot_offset);
+               break;
+       }
+
+       M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
+       M_CALL(REG_ITMP1);
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+       case TYPE_LNG:
+               M_LLD(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, syncslot_offset);
+               break;
+       }
+}
+#endif
+
+
+/**
+ * Emit profiling code for method frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code)
+{
+       M_MOV_IMM(code, REG_ITMP3);
+       M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
+}
+#endif
+
+
+/**
+ * Emit profiling code for basicblock frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
+{
+       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
+       M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 4a1cb4c9884a8998b53b94a92ec8c6321a13abee..790f659a9aa1b6e8889519066c64f63e1470a208 100644 (file)
@@ -180,6 +180,10 @@ typedef union {
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d);
 
 
@@ -363,6 +367,18 @@ void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
 
 void emit_rdtsc(codegendata *cd);
 
+
+/**
+ * Emit code to recompute the procedure vector. This is a nop,
+ * because we do not use a procedure vector.
+ */
+static inline void emit_recompute_pv(codegendata* cd) {}
+
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _MD_EMIT_H */
 
 
index 6495479a83f794fcdccf442809275630f85cf087..9a65d6b6597df307116132f144011ea18d49bd45 100644 (file)
 
 /* inline functions ***********************************************************/
 
+/**
+ * Returns the size (in bytes) of the current stackframe, specified by
+ * the passed codeinfo structure.
+ */
+inline static int32_t md_stacktrace_get_framesize(codeinfo* code)
+{
+       // Check for the asm_vm_call_method special case.
+       if (code == NULL)
+               return 0;
+
+       // On x86_64 we use 8-byte stackslots.
+       return code->stackframesize * 8;
+}
+
+
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by