* 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
 
 
 #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 */
 /* 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
 
 /* 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.
    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/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"
 
 #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) */
 
 
        /* 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))
                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);
                        }
                                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 ************************************************/
 
 
                /* 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);
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
@@ -448,30 +260,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* integer operations *************************************************/
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
@@ -1338,15 +1126,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
 
                /* 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);
                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;
 
                        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)                           */
                case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
                                          /* val = value (in current instruction)     */
                                          /* following NOP)                           */
@@ -1975,139 +1664,83 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
 
                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                            */
                        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);
                        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 {
                        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);
                        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 {
                        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);
                        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 {
                        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);
                        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 {
                        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);
                        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 {
                        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);
                        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 {
                        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 ==> ...                         */
                        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_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);
 
                        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_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);
 
                        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;
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -2424,216 +1944,92 @@ nowperformreturn:
                        ALIGNCODENOP;
                        break;
 
                        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;
                        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_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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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;
 
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
@@ -3029,23 +2425,8 @@ gen_method:
                        break;
 
                default:
                        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 */
        } /* 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)
                                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);
                                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 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_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_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_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)
 #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.
 /* 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.
 /* 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 ***********************************************************/
 
 
 /* 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
 /* 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
 
 
 #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 */
 /* 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
 
 /* 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.
    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"
 
 #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);
                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]));
                savedregs_bitmask |= (1<<(rd->savintregs[i]));
+       }
 
 #if !defined(NDEBUG)
        for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; 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
 
        }
 #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) */
 
                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 */
 
 
        /* 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))
                        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
                                        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 */
                                }
                                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)
                                }
                        }
 #if !defined(ENABLE_SOFTFLOAT)
@@ -246,157 +177,94 @@ bool codegen_emit(jitdata *jd)
                        else {
                                if (!(var->flags & INMEMORY)) {
                                        if (IS_2_WORD_TYPE(t))
                        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
                                        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 */
                                }
                                else {
                                        /* Reuse Memory Position on Caller Stack */
-                                       var->vv.regoff = cd->stackframesize + s1;
+                                       var->vv.regoff = cd->stackframesize * 8 + s1;
                                }
                        }
                }
 #endif /* !defined(ENABLE_SOFTFLOAT) */
        }
                                }
                        }
                }
 #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 ************************************************/
 
 
                /* 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);
                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;
 
                        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)
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
 #if defined(ENABLE_SOFTFLOAT)
@@ -448,30 +309,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                   */
                /* integer operations *************************************************/
 
                case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
@@ -681,8 +518,7 @@ bool codegen_emit(jitdata *jd)
                        M_DSEG_BRANCH(disp);
 
                        /* recompute pv */
                        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);
 
                        /* 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 */
                        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);
 
                        /* 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 **************************************************/
 
 
                /* 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);
                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 */
                        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);
 
                        /* check resturn value of builtin */
                        emit_arraystore_check(cd, iptr);
@@ -1385,26 +1210,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
                        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)
                        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;
 
                        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);
                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)       */
 
 
                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);
                        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;
 
                                            /* 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);
                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_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);
                                /*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) */
                        }
                        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);
                                /*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_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);
                                /*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) */
                        }
                        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);
                                /*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_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);
                                /*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) */
                        }
                        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);
                                /*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_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);
                                /*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) */
                        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);
                                /*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_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);
                                /*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_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);
                                /*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;
                        
                        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                     */
 
                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;
 
                        /* 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 */
                        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;
 
                        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
 #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
                                }
                        }
 #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;
 
                        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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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            */
                        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);
 
                                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);
 
                                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 */
 
 
                        /* recompute pv */
 
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
+                       emit_recompute_pv(cd);
 
                        /* check for exception before result assignment */
 
 
                        /* check for exception before result assignment */
 
@@ -2943,29 +2369,9 @@ bool codegen_emit(jitdata *jd)
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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:
                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 */
 
 
        /* recompute pv */
 
-       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-       M_RECOMPUTE_PV(s1);
+       emit_recompute_pv(cd);
 
        /* remember class argument */
 
 
        /* 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? */
 
        /* 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! */
 
 #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);
        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);
 
        M_MOV(REG_ITMP1_XPTR, REG_RESULT);
        M_LDMFD(BITMASK_RESULT, REG_SP);
index 0191858b85e41bd36c910966dd224d36d1cc6276..f7fd56ab04b490d4495c40ef69ffd09e60d7ac93 100644 (file)
             codegen_increase(cd); \
     } while (0)
 
             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))
 
 
 /* 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 *************************************************************/
 
 
 /* branch defines *************************************************************/
@@ -1105,66 +1098,6 @@ do { \
 #endif /* !defined(ENABLE_SOFTFLOAT) */
 
 
 #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
 /* 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(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)
 
 
 #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_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)
 #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.
 /* 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.
 /* 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);
        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 */
        M_LONGBRANCH(trace_java_call_enter);
 
        /* restore argument registers */
index 9ce156470118f432c10e3919b93da57270615ef0..9ef90a93e4d418f3da1085a77531827e7852aca3 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
 #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
 /* 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             */
 
        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   */
 
        /* 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;
 
        exceptiontable_t  *exceptiontable;
        LinenumberTable* linenumbertable;
 
@@ -90,9 +97,7 @@ struct codeinfo {
        LockedList*   patchers;
 #endif
 
        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           */
 #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        */
        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
 
        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
 
 /* 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
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
    This file is part of CACAO.
 
 #include "vm/exceptions.hpp"
 #include "vm/method.hpp"
 #include "vm/options.h"
 #include "vm/exceptions.hpp"
 #include "vm/method.hpp"
 #include "vm/options.h"
+#include "vm/statistics.h"
 #include "vm/string.hpp"
 
 #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/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/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"
 #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
 #endif
-#include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trace.hpp"
 
 #if defined(ENABLE_INTRP)
 #include "vm/jit/intrp/intrp.h"
 
 #if defined(ENABLE_INTRP)
 #include "vm/jit/intrp/intrp.h"
 #include <vmlog_cacao.h>
 #endif
 
 #include <vmlog_cacao.h>
 #endif
 
-#include "show.hpp"
-
 
 /* codegen_init ****************************************************************
 
 
 /* codegen_init ****************************************************************
 
@@ -288,7 +291,7 @@ bool codegen_generate(jitdata *jd)
                                return false;
                }
                else {
                                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)
                }
 
 #if !defined(NDEBUG)
@@ -544,21 +547,20 @@ void codegen_set_replacement_point(codegendata *cd)
 
 void codegen_finish(jitdata *jd)
 {
 
 void codegen_finish(jitdata *jd)
 {
-       codeinfo    *code;
-       codegendata *cd;
-       s4           mcodelen;
+       s4       mcodelen;
 #if defined(ENABLE_INTRP)
 #if defined(ENABLE_INTRP)
-       s4           ncodelen;
+       s4       ncodelen;
 #endif
 #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 */
 
 
        /* prevent compiler warning */
 
@@ -641,6 +643,16 @@ void codegen_finish(jitdata *jd)
        }
 #endif
 
        }
 #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);
        /* 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;
 {
        stackframeinfo_t *sfi;
        localref_table   *lrt;
+       codeinfo         *code;
        methodinfo       *m;
        int32_t           framesize;
 
        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++);
 
 
        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);
 
        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__)
        /* 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 */
 #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 */
 #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;
 
        uint8_t  *datasp;
        uint64_t *ret_regs;
 
-       /* get information from method header */
-
+       // Get information from method header.
        code = code_get_codeinfo_for_pv(pv);
        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;
        m = code->m;
-       assert(m);
+       assert(m != NULL);
 
        /* calculate needed values */
 
 
        /* 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
        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 */
 #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.
    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)
 *******************************************************************************/
 
 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.
    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)
 *******************************************************************************/
 
 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.
 /* 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)
 
 #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 **********************************************************/
 
 
 /* branch conditions **********************************************************/
 
@@ -211,6 +224,10 @@ void codegen_setup(jitdata *jd);
 bool codegen_generate(jitdata *jd);
 bool codegen_emit(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
 #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
 
 /* 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
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
    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 "config.h"
 #include "vm/types.h"
 
 #include "arch.h"
+#include "codegen.h"
 
 #include "vm/jit/codegen-common.hpp"
 #include "vm/jit/jit.hpp"
 
 #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);
 
 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);
 /* 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_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);
 
 void emit_verbosecall_enter(jitdata *jd);
 void emit_verbosecall_exit(jitdata *jd);
 
@@ -204,7 +232,77 @@ void emit_verbosecall_exit(jitdata *jd);
 }
 #endif
 
 }
 #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
 
 
 #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 */
 /* 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/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"
 
 #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;
 
 
        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);
                M_ASUB_IMM(cd->stackframesize * 8 + 4, REG_SP);
+       }
 
        /* save return address and used callee saved registers */
 
 
        /* save return address and used callee saved registers */
 
@@ -201,9 +108,8 @@ bool codegen_emit(jitdata *jd)
 
        md = m->parseddesc;
 
 
        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)
 
                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 ************************************************/
 
 
                /* 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);
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
@@ -620,29 +398,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* 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;
                        emit_arithmetic_check(cd, iptr, REG_ITMP3);
 
                        bte = iptr->sx.s23.s3.bte;
-                       md = bte->md;
 
                        M_LST(s2, REG_SP, 2 * 4);
 
 
                        M_LST(s2, REG_SP, 2 * 4);
 
@@ -1894,15 +1648,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
 
                /* 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);
                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)       */
 
 
                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);
 
                        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;
 
                        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);
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
@@ -2586,28 +2278,6 @@ bool codegen_emit(jitdata *jd)
                        }
                        break;
 
                        }
                        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);
                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;
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2858,243 +2400,95 @@ nowperformreturn:
                        }
                        break;
 
                        }
                        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
                        }
 #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;
                        }
                        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            */
 
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -3491,59 +2885,9 @@ gen_method:
                        emit_store_dst(jd, iptr, s1);
                        break;
 
                        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:
                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 */
        } /* 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 */
        /* 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         */
        (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)
 
 
     } 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 {                                                             \
     do {                                                             \
-        if ((reg) != (dreg)) {                                       \
-            log_text("M_FLTMOVE");                                   \
-            assert(0);                                               \
-        }                                                            \
+        log_text("M_FMOV");                                          \
+        assert(0);                                                   \
     } while (0)
 
     } while (0)
 
+#define M_DMOV(a,b) M_FMOV(a,b)
 
 #define ICONST(d,c) \
     do { \
 
 #define ICONST(d,c) \
     do { \
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
 #define M_RET                   M_BYTE1(0xc3)
 
 #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))
 #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.
 /* 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.
 /* 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.
 
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
    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"
 #include "vm/types.h"
 
 #include "vm/jit/codegen-common.hpp"
 
 #define emit_reg(reg,rm)                emit_address_byte(3,(reg),(rm))
 
 
 #define emit_reg(reg,rm)                emit_address_byte(3,(reg),(rm))
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* integer instructions */
 
 
 /* integer instructions */
 
@@ -304,7 +300,19 @@ void emit_escape_check(codegendata *cd, s4 reg);
 void emit_escape_annotate_object(codegendata *cd, methodinfo *m);
 #endif
 
 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
 
 /* 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.
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 /* inline functions ***********************************************************/
 
 
 /* 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
 /* 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
 
 #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
 #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.
    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/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"
 
 
 #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)
 #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
 #else
-               assert(FLT_SAV_CNT == 0);
-               assert(rd->savfltreguse == 0);
+       assert(FLT_SAV_CNT == 0);
+       assert(rd->savfltreguse == 0);
 #endif
 #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)
 #if defined(ENABLE_SOFTFLOAT)
-                       case TYPE_FLT:
-                       case TYPE_DBL:
+               case TYPE_FLT:
+               case TYPE_DBL:
 #endif
 #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)
 #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
 #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 **************************************************************/
 
                /* 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                       */
 
 
                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);
                        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_FMUL(s1, REG_FTMP2);
-                       M_FLTMOVE(REG_FTMP2, d);
+                       emit_fmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_DMUL(s1, REG_FTMP2);
-                       M_DBLMOVE(REG_FTMP2, d);
+                       emit_dmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_FDIV(s2, REG_FTMP1);
-                       M_FLTMOVE(REG_FTMP1, d);
+                       emit_fmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_DDIV(s2, REG_FTMP1);
-                       M_DBLMOVE(REG_FTMP1, d);
+                       emit_dmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_FADD(s1, REG_FTMP2);
-                       M_FLTMOVE(REG_FTMP2, d);
+                       emit_fmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_DADD(s1, REG_FTMP2);
-                       M_DBLMOVE(REG_FTMP2, d);
+                       emit_dmove(cd, REG_FTMP2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_FSUB(s2, REG_FTMP1);
-                       M_FLTMOVE(REG_FTMP1, d);
+                       emit_fmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        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);
                        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_DSUB(s2, REG_FTMP1);
-                       M_DBLMOVE(REG_FTMP1, d);
+                       emit_dmove(cd, REG_FTMP1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -982,29 +864,6 @@ bool codegen_emit(jitdata *jd)
 
                #endif
 
 
                #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);
 
                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)       */
 
 
                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);
                        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;
 
                        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                          */
                /* MEMORY *************************************************************/
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
@@ -1316,15 +1105,6 @@ bool codegen_emit(jitdata *jd)
                        }
                        break;
 
                        }
                        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);
                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 ...]] ==> ...            */
 
                /* METHOD INVOCATION *********************************************************/
                case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
-
                        bte = iptr->sx.s23.s3.bte;
                        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_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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                                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)      {
 
                                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 */
                                        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  {
                                                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:
                                                }
                                                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_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
                                                }
                                                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            */
 
                /* the evil ones */
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
@@ -2257,29 +1787,6 @@ nowperformreturn:
                        }
                        break;
 
                        }
                        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  */
                case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
 
                        /* check for negative sizes and copy sizes to stack if necessary  */
@@ -2327,34 +1834,11 @@ nowperformreturn:
 
 
                default:
 
 
                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 */
        } /* 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.
 /* 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 */
 
 #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 { \
 /* assert on the opcode */
 #define OPWORD_ASSERT(a, u,v,w)        \
        do { \
        } while(0);
 
 /* M_XMOVE....M_XMOVE(sourcereg, destreg) */
        } 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_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)
 
 #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_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 */
 #endif
 /* M_XTST....M_XTST(register) */
 #define M_ITST(a)              OPWORD(0x12a, 0, (a))                   /* tst.l */
                cd->mcodeptr += 2; \
        } while(0);
 
                cd->mcodeptr += 2; \
        } while(0);
 
+#define M_TEST(a)                      M_ATST(a)
+
 
 #if !defined(ENABLE_SOFTFLOAT)
        
 
 #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;
 }
        }
        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.
 /* 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.
 
 /*
  * These are local overrides for various environment variables in Emacs.
index 5514cc4b885b87ba0c3d5111058a262d8010f7d7..63c9eb626c18b4d534a07e7196dd61adfb3dfbe5 100644 (file)
 #include "vm/jit/methodtree.h"
 
 
 #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
 /* 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
 
 
 #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 */
 /* 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/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)
 #include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 
 bool codegen_emit(jitdata *jd)
 {
 
 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 */
 
 
        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 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++;
 
        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) */
 
 
        /* 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))
                        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
                                        else
-                                               M_FLTMOVE(s1, var->vv.regoff);
+                                               emit_fmove(cd, s1, var->vv.regoff);
                                }
                                else {
                                        if (IS_2_WORD_TYPE(t))
                                }
                                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 {
                } 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 ************************************************/
 
 
                /* 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
                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)) {
                        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,
                                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;
 
 
                        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                 */
                /* integer operations *************************************************/
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
@@ -2245,17 +2099,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
 
                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);
                        // 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                            */
                        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);
                        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);
                        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 {
                        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);
                        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 {
                        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);
                        }
                        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);
                        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 {
                        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);
                        }
                        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 {
                        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 ==> ...                         */
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
@@ -2588,8 +2386,6 @@ bool codegen_emit(jitdata *jd)
 #endif
                        break;
 
 #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
 #if SIZEOF_VOID_P == 8
                case ICMD_IF_LCMPEQ:
 #endif
@@ -2613,8 +2409,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 #endif
 
                        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
 #if SIZEOF_VOID_P == 8
                case ICMD_IF_LCMPNE:
 #endif
@@ -2749,171 +2543,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 #endif
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -2963,249 +2592,113 @@ nowperformreturn:
                        ALIGNCODENOP;
                        break;
 
                        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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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))
                                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);
 
                                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,
                                        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) {
 
                                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);
 
                                                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);
 
                                        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,
                                                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)) {
                                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,
                                        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);
 
                        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,
                                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) {
 
                        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);
 
                                        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);
 
                                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,
                                        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)) {
                        /* 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,
                                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:
                        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 */
        } /* 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; \
     }
 
         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))
 
 #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.
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 100be5e306f3b2fa006624ca76270654f7d09028..67bb24cdc8100045f0c891c2028abf2dc3ddacd5 100644 (file)
 #include "vm/vm.hpp"
 
 
 #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
 /* 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();
 
                // Lock the thread lists.
                ThreadList_lock();
 
+#if 0
                /* iterate over all started threads */
 
                for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
                /* 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();
 
                // Unlock the thread lists.
                ThreadList_unlock();
@@ -207,6 +209,7 @@ void profile_printstats(void)
        frequency = 0;
        cycles    = 0;
 
        frequency = 0;
        cycles    = 0;
 
+#if 0
        /* create new method list */
        // TODO Use a sorted container.
        List* l = List_new();
        /* 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]);
                }
        }
                                           j, code->bbfrequency[j]);
                }
        }
+#endif
 
        printf("-----------           -------------- \n");
        printf("%10d             %12ld\n", frequency, (long) cycles);
 
        printf("-----------           -------------- \n");
        printf("%10d             %12ld\n", frequency, (long) cycles);
index a235afacd4cab06e0c2df9114bb93255b3575fc5..06a672a8049fab6265cd4dc06d92b2b21d871082 100644 (file)
@@ -37,6 +37,50 @@ extern "C" {
 #include "vm/global.h"
 
 
 #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);
 /* function prototypes ********************************************************/
 
 bool profile_init(void);
index e9259c4afe7c44985e96af7cc091e73d4d1cac39..6e0f1fce58f313191cdd64be9082dffd0f1a375c 100644 (file)
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
 
 
 #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 */
 /* 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
 
 /* 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.
    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/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"
 
 #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) */
 
 
        /* 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))
                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);
                        }
                                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 ************************************************/
 
 
                /* 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);
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
@@ -508,30 +287,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* 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);
 
                        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;
                                        
                        emit_store_dst(jd, iptr, d);
                        break;
                                        
@@ -1255,15 +1010,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
 
                /* 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);
                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;
 
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
-
+#if 0
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
                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_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;
                        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                          */
 
 
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
@@ -1677,17 +1342,6 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
 
                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);
                        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    */
                                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 ==> ...                         */
                        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;
 
                        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);
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
@@ -1900,28 +1522,6 @@ bool codegen_emit(jitdata *jd)
                        }
                        break;
 
                        }
                        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);
                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;
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -2175,251 +1651,96 @@ nowperformreturn:
                        break;
 
 
                        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 ...]] ==> ...            */
                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_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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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;
 
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
@@ -2827,23 +2148,8 @@ gen_method:
                        break;
 
                default:
                        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 */
        } /* 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)
 
 
     } 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 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 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_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 ************************************************/
 
 
 /* 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.
 /* 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.
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 33724ab14ae24b774b90f4536e4fcb9448d95a1e..e4f8052814af004e502daa5acebf984687d78cee 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
 #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
 /* 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
 
 
 #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
 /* 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
 
 /* 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.
    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/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"
 
 #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);
 
        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))
                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);
                        }
                                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 ************************************************/
 
 
                /* 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);
                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);
                        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;
 
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -453,29 +253,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* 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);
 
                        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;
                                        
                        emit_store_dst(jd, iptr, d);
                        break;
                                        
@@ -1214,15 +991,6 @@ bool codegen_emit(jitdata *jd)
                        
                /* memory operations **************************************************/
 
                        
                /* 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);
                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;
 
                        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);
                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)       */
 
 
                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);
                        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    */
                                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;
 
                        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);
                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;
                        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);
 
                        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;
 
                        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);
 
                        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;
 
 
                        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);
 
                        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;
 
                        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);
 
                        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;
 
                        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);
 
                        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;
 
                        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);
 
                        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;
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                        s4 i, l;
@@ -1965,212 +1450,92 @@ nowperformreturn:
                        break;
 
 
                        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_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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                                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            */
                        break;
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
@@ -2605,23 +1970,8 @@ gen_method:
                        break;
 
                default:
                        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 */
        } /* 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)
 
 
     } 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 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_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_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_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 */
 
 
 #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.
 /* 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
 /*
  * 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"
 
 
 #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
 /* 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) */
 /*** 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_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 */
 /* 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
 
 
 #endif
 
 
@@ -728,13 +714,7 @@ bool replace_create_replacement_points(jitdata *jd)
        code->regalloc      = regalloc;
        code->regalloccount = alloccount;
        code->globalcount   = 0;
        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->memuse        = rd->memuse;
-       code->stackframesize = jd->cd->stackframesize;
 
        REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
        REPLACE_COUNT_INC(stat_regallocs, alloccount);
 
        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;
 void md_pop_stackframe(executionstate_t *es)
 {
        u1 *ra;
-       s4 ra_align_off;
+       s4 framesize;
        s4 reg;
        s4 i;
        stackslot_t *basesp;
        s4 reg;
        s4 i;
        stackslot_t *basesp;
@@ -1520,23 +1500,18 @@ void md_pop_stackframe(executionstate_t *es)
 
        assert(es->code);
 
 
        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 */
 
 
        /* 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
        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 */
 
 
        /* 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 */
 
 
        /* 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))
        if (!code_is_leafmethod(es->code))
-#endif
+# endif
                es->ra = (u1*) (ptrint) *--basesp;
                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_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(es->code))
        if (!code_is_leafmethod(es->code))
-#endif
+# endif
                es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
 #endif /* REPLACE_RA_LINKAGE_AREA */
 
                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 */
 
 
        /* 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 */
 #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 */
 
 
        /* 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);
        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;
 
 
        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 */
 
 
        /* 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))
        if (!code_is_leafmethod(calleecode))
-#endif
+# endif
                *--basesp = (ptrint) ra;
                *--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
 
 #if defined(REPLACE_RA_LINKAGE_AREA)
 
 #if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(calleecode))
        if (!code_is_leafmethod(calleecode))
-#endif
+# endif
                basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
 #endif /* REPLACE_RA_LINKAGE_AREA */
 
                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 */
 
 
        /* 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);
 #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 */
 
 
        /* 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 */
 #endif
 
        /* assert that the native frame has not moved */
index 002ba7f956db07116bfbffcb4dcdf4a397bb72fa..e5c26995547822fa8999df4bd5fe16537636fcbe 100644 (file)
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
 
 
 #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 */
 /* 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
 
 /* 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.
    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"
 #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"
 #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/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"
 
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
@@ -94,12 +90,6 @@ static void do__log(u4 *regs) {
 
 /* #define SUPPORT_HERCULES 1 */
 
 
 /* #define SUPPORT_HERCULES 1 */
 
-/* codegen *********************************************************************
-
-   Generates machine code.
-
-*******************************************************************************/
-
 /*
 
 Layout of stackframe:
 /*
 
 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.
         */
 
 
        /* 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);
        /* 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);
 
 
        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;
        /* 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   */
                        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))
 
                                } else {                                         /* reg arg -> spilled    */
                                        if (IS_2_WORD_TYPE(t))
@@ -342,212 +247,68 @@ bool codegen_emit(jitdata *jd)
                        }
                }
        } /* end for */
                        }
                }
        } /* 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 ************************************************/
 
 
                /* 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);
                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)) {
                        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; */
                                disp = dseg_add_unique_address(cd, cr);
 
 /*                             PROFILE_CYCLE_STOP; */
@@ -599,28 +360,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* integer operations *************************************************/
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
@@ -1444,7 +1183,7 @@ bool codegen_emit(jitdata *jd)
                        if (s2 == d)
                                M_FADD(s1, d);
                        else {
                        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);
                                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 {
                        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);
                                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);
 
                        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;
                        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);
 
                        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;
                        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 {
                        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);
                                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 {
                        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);
                                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);
 
                        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;
                        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);
 
                        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;
                        M_DDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1700,17 +1439,6 @@ bool codegen_emit(jitdata *jd)
 
                /* memory operations **************************************************/
 
 
                /* 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);
                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;
 
                        */
                        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);
                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)       */
 
 
                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);
                        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;
 
 
                        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:
                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;
 
 
                        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 ==> ...                  */
                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;
 
                        }
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2709,255 +2086,116 @@ nowperformreturn:
                        break;
 
 
                        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;
 
                        }
                        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_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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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 */
 
                        /* generate the actual call */
-
                        M_CALL(REG_PV);
                        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            */
 
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -3406,37 +2644,11 @@ gen_method:
                        break;
 
                default:
                        break;
 
                default:
-                       exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
-                       return false;
+                       vm_abort("Unknown ICMD %d during code generation", iptr->opc);
        } /* switch */
        } /* 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.
 /* 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_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)
 #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)
 
            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)) { \
 #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.
 /* 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.
 /* 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;
 
        /*
        s4 offset, offset_imm;
 
        /*
index cbb7f9b6df26dd1609b9144d02f7a4548aa306be..7f6c131d78771993c9586883c97bb0b8265839c4 100644 (file)
 #include "vm/jit/methodtree.h"
 
 
 #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
 /* 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
 
 
 #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 */
 /* 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/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"
 #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)
 {
 
 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;
 
        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 */ 
 
 
        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++;
 #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++;
 
        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) */
 
 
        /* save register window and create stack frame (if necessary) */
 
@@ -219,61 +188,6 @@ bool codegen_emit(jitdata *jd)
        }
 #endif
 
        }
 #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;
        /* 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   */
                } 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);
 
                                } 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 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 ************************************************/
 
                /* 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);
                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)) {
                        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);
                                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;
 
 
                        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                 */
                /* integer operations *************************************************/
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
@@ -1886,133 +1703,14 @@ bool codegen_emit(jitdata *jd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
 
                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                            */
                        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;
 
                        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);
                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;
 
                        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                     */
 
                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;
                        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 ==> ...                  */
 
 
                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;
                        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 ==> ...                  */
 
 
                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;
                        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 ==> ...                  */
 
 
                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;
                        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 ==> ...                  */
 
 
                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;
                        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 ==> ...                         */
                        {
 
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
@@ -2361,40 +1919,11 @@ nowperformreturn:
                        M_NOP;
                        ALIGNCODENOP;
                        break;
                        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 ==> ...              */
 
                case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
 
-                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
-
                        bte = iptr->sx.s23.s3.bte;
                        md = bte->md;
                        
                        bte = iptr->sx.s23.s3.bte;
                        md = bte->md;
                        
@@ -2442,41 +1971,11 @@ nowperformreturn:
 #else
                        assert(md->argfltreguse == 0);
 #endif
 #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);
                                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);
                                        }
                                }
                                                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               */
 
                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);
 
                                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,
                                        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) {
 
                                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);
 
                                                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);
 
                                        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,
                                                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)) {
                                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,
                                        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);
 
                        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,
                                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) {
 
                        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);
 
                                        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);
 
                                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,
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
@@ -2984,37 +2446,8 @@ gen_method:
                        break;
 
                default:
                        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 */
        } /* 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++;
 
 
                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))
 #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_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 */
 
 #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.
 /* 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.
 /* emit_patcher_stubs **********************************************************
 
    Generates the code for the patcher stubs.
index f47f7750d88747e331d0b228e4231be8ffb36ace..8f71e2fae9cba28060a174dbc609765beba246d3 100644 (file)
 #include "vm/jit/codegen-common.hpp"
 
 
 #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
 /* 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 "vm/types.h"
 
+#include "arch.h"
 #include "md.h"
 
 #include "mm/gc.hpp"
 #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. */
 
                /* 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
 
                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)) {
                   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);
                }
 
                        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. */
 
  
        /* 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
 
        /* 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
                {
        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 */
                        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
 
 
 #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 */
 /* 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/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"
 
 #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) */
 
 
        /* 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))
                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);
                        }
                                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 ************************************************/
 
 
                /* 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);
                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)) {
                        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; */
                                disp = dseg_add_unique_address(cd, cr);
 
 /*                             PROFILE_CYCLE_STOP; */
@@ -480,28 +257,6 @@ bool codegen_emit(jitdata *jd)
                        break;
 
 
                        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                 */
                /* 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);
                        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);
                        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);
                        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);
                        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 {
                        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);
                                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 {
                        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);
                                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) {
                        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;
                        }
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        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) {
                        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;
                        }
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DSUB(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        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 {
                        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);
                                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 {
                        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);
                                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) {
                        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;
                        }
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_FDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        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) {
                        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;
                        }
                                s2 = REG_FTMP2;
                        }
-                       M_FLTMOVE(s1, d);
+                       emit_fmove(cd, s1, d);
                        M_DDIV(s2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
                        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);
                        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);
                        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);
                        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);
                        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);
                        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);
                        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);
                        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);
                        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 **************************************************/
 
 
                /* 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);
                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;
 
                        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)                           */
                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)) {
                                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);
 
 
                                        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)       */
 
 
                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);
 
                        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;
 
                        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:
                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;
 
                        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:
                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;
 
                        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;
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
                                s4 i, l;
@@ -2280,204 +1740,79 @@ nowperformreturn:
                        }
                        break;
 
                        }
                        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;
 
                        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)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               lm = NULL;
                                um = iptr->sx.s23.s3.um;
                                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;
                        }
                        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            */
 
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
@@ -2551,7 +1886,7 @@ gen_method:
                                        if (super == NULL) {
                                                emit_label(cd, BRANCH_LABEL_2);
 
                                        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,
                                                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)) {
                                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,
                                        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);
 
                                                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,
 
                                M_BLE(a);
                                M_ALD32(REG_ITMP1, REG_ITMP1,
@@ -2728,7 +2063,7 @@ gen_method:
                                if (super == NULL) {
                                        emit_label(cd, BRANCH_LABEL_2);
 
                                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,
                                        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)) {
                        /* 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,
                                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:
                        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 */
        } /* 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)
 
 
     } 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 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_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))
 
 #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)
     } 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_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_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_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))
 
 
 #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 */
 
 
 #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.
 /* 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.
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 4a1cb4c9884a8998b53b94a92ec8c6321a13abee..790f659a9aa1b6e8889519066c64f63e1470a208 100644 (file)
@@ -180,6 +180,10 @@ typedef union {
 
 /* function prototypes ********************************************************/
 
 
 /* function prototypes ********************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d);
 
 
 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);
 
 
 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 */
 
 
 #endif /* _MD_EMIT_H */
 
 
index 6495479a83f794fcdccf442809275630f85cf087..9a65d6b6597df307116132f144011ea18d49bd45 100644 (file)
 
 /* inline functions ***********************************************************/
 
 
 /* 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
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by