* src/vm/jit/parse.cpp,
[cacao.git] / src / vm / jit / intrp / codegen.c
index 2b811939878776504bad2e770324dec6544694a4..4fbca4a70d15856dfe575b7af0675374fcef8cea 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Andreas Krall
-            Reinhard Grafl
-
-   Changes: Christian Thalinger
-            Anton Ertl
-
-   $Id: codegen.c 3247 2005-09-21 14:59:57Z twisti $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 
-#define __INTRP__
+#include "config.h"
 
+#include <assert.h>
 #include <stdio.h>
 
-#include "config.h"
+#if defined(WITH_FFI)
+# include <ffi.h>
+#elif defined(WITH_FFCALL)
+# include <avcall.h>
+#else
+# error neither WITH_FFI nor WITH_FFCALL defined
+#endif
+
 #include "vm/types.h"
 
 #include "arch.h"
 
 #include "vm/jit/intrp/codegen.h"
+#include "vm/jit/intrp/intrp.h"
 
-#include "cacao/cacao.h"
-#include "native/native.h"
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/stringlocal.h"
-#include "vm/tables.h"
-#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc"
-#include "vm/jit/jit.h"
+#include "mm/memory.h"
 
-#include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
+#include "native/native.hpp"
 
-#include "vm/jit/intrp/intrp.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
 
-#include "libffi/include/ffi.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/dseg.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/patcher.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.hpp"
 
 
 #define gen_branch(_inst) { \
-  gen_##_inst(((Inst **)cd), 0); \
-  codegen_addreference(cd, (basicblock *) (iptr->target), cd->mcodeptr); \
+  gen_##_inst(cd, 0); \
+  codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
 }
 
 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
 
 /* functions used by cacao-gen.i */
 
-/* vmgen-0.6.2 generates gen_... calls with Inst ** as first
-   parameter, but we need to pass in cd to make last_compiled
-   thread-safe */
-
-void genarg_v(Inst **cd1, Cell v)
+void genarg_v(codegendata *cd1, Cell v)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *) cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((Cell *) *mcodepp) = v;
        (*mcodepp)++;
 }
 
-void genarg_i(Inst **cd1, s4 i)
+void genarg_i(codegendata *cd1, s4 i)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *) cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((Cell *) *mcodepp) = i;
        (*mcodepp)++;
 }
 
-void genarg_b(Inst ** cd1, s4 i)
+void genarg_b(codegendata *cd1, s4 i)
 {
   genarg_i(cd1, i);
 }
 
-void genarg_f(Inst ** cd1, float f)
+void genarg_f(codegendata *cd1, float f)
 {
        s4 fi;
 
@@ -105,100 +100,107 @@ void genarg_f(Inst ** cd1, float f)
        genarg_i(cd1, fi);
 }
 
-void genarg_l(Inst ** cd1, s8 l)
+void genarg_l(codegendata *cd1, s8 l)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *) cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
        (*mcodepp) +=2;
 }
 
-void genarg_aRef(Inst ** cd1, java_objectheader *a)
+void genarg_aRef(codegendata *cd1, java_objectheader *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *) cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((java_objectheader **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_aArray(Inst ** cd1, java_arrayheader *a)
+void genarg_aArray(codegendata *cd1, java_arrayheader *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *) cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((java_arrayheader **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_aaTarget(Inst ** cd1, Inst **a)
+void genarg_aaTarget(codegendata *cd1, Inst **a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((Inst ***) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_aClass(Inst ** cd1, classinfo *a)
+void genarg_aClass(codegendata *cd1, classinfo *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((classinfo **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_acr(Inst ** cd1, constant_classref *a)
+void genarg_acr(codegendata *cd1, constant_classref *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((constant_classref **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_addr(Inst ** cd1, u1 *a)
+void genarg_addr(codegendata *cd1, u1 *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((u1 **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_af(Inst ** cd1, functionptr a)
+void genarg_af(codegendata *cd1, functionptr a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((functionptr *) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_am(Inst ** cd1, methodinfo *a)
+void genarg_afi(codegendata *cd1, fieldinfo *a)
+{
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+       *((fieldinfo **) *mcodepp) = a;
+       (*mcodepp)++;
+}
+
+void genarg_am(codegendata *cd1, methodinfo *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((methodinfo **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_acell(Inst ** cd1, Cell *a)
+void genarg_acell(codegendata *cd1, Cell *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((Cell **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_ainst(Inst ** cd1, Inst *a)
+void genarg_ainst(codegendata *cd1, Inst *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((Inst **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_auf(Inst ** cd1, unresolved_field *a)
+void genarg_auf(codegendata *cd1, unresolved_field *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((unresolved_field **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_aum(Inst ** cd1, unresolved_method *a)
+void genarg_aum(codegendata *cd1, unresolved_method *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((unresolved_method **) *mcodepp) = a;
        (*mcodepp)++;
 }
 
-void genarg_avftbl(Inst ** cd1, vftbl_t *a)
+void genarg_avftbl(codegendata *cd1, vftbl_t *a)
 {
-       Inst **mcodepp = (Inst **) &(((codegendata *)cd1)->mcodeptr);
+       Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
        *((vftbl_t **) *mcodepp) = a;
        (*mcodepp)++;
 }
@@ -206,10 +208,11 @@ void genarg_avftbl(Inst ** cd1, vftbl_t *a)
 
 /* include the interpreter generation functions *******************************/
 
-#include "vm/jit/intrp/java-gen.i"
+/* Do not use "java-gen.i", it does not work with builddir. */
+#include <java-gen.i>
 
 
-typedef void (*genfunctionptr) (Inst **);
+typedef void (*genfunctionptr) (codegendata *);
 
 typedef struct builtin_gen builtin_gen;
 
@@ -230,33 +233,42 @@ struct builtin_gen builtin_gen_table[] = {
     {BUILTIN_newarray_float,          gen_NEWARRAY_FLOAT,  },    
     {BUILTIN_newarray_double,         gen_NEWARRAY_DOUBLE, },
     {BUILTIN_arrayinstanceof,         gen_ARRAYINSTANCEOF, },
-#if defined(USE_THREADS)
-    {BUILTIN_monitorenter,            gen_MONITORENTER,    },
-    {BUILTIN_monitorexit,             gen_MONITOREXIT,     },
+
+#if defined(ENABLE_THREADS)
+    {LOCK_monitor_enter,              gen_MONITORENTER,    },
+    {LOCK_monitor_exit,               gen_MONITOREXIT,     },
 #endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
     {BUILTIN_f2l,                     gen_F2L,             },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
     {BUILTIN_d2l,                                        gen_D2L,                         },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I)
     {BUILTIN_f2i,                                        gen_F2I,                         },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
     {BUILTIN_d2i,                                        gen_D2I,                         },
+#endif
+
+#if !SUPPORT_DIVISION
     {BUILTIN_idiv,                                       gen_IDIV,                        },
     {BUILTIN_irem,                                       gen_IREM,                        },
+#endif
+
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
     {BUILTIN_ldiv,                                       gen_LDIV,                        },
     {BUILTIN_lrem,                                       gen_LREM,                        },
+#endif
+
     {BUILTIN_frem,                                       gen_FREM,                        },
     {BUILTIN_drem,                                       gen_DREM,            },
 };
 
-/*
-  The following ones cannot use the BUILTIN mechanism, because they
-  need the class as immediate arguments of the patcher
-
-       PATCHER_builtin_new,                 gen_PATCHER_NEW,    
-       PATCHER_builtin_newarray,            gen_PATCHER_NEWARRAY,       
-       PATCHER_builtin_arrayinstanceof, gen_PATCHER_ARRAYINSTANCEOF,
-*/
-
-
-
 
 /* codegen *********************************************************************
 
@@ -264,18 +276,30 @@ struct builtin_gen builtin_gen_table[] = {
 
 *******************************************************************************/
 
-void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
+#define I(value)   iptr[0].sx.val.i = (value); break;
+
+bool intrp_codegen(jitdata *jd)
 {
+       methodinfo         *m;
+       codegendata        *cd;
+       registerdata       *rd;
        s4                  i, len, s1, s2, d;
-       stackptr            src;
        basicblock         *bptr;
        instruction        *iptr;
-       exceptiontable     *ex;
        u2                  currentline;
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
        unresolved_method  *um;
        builtintable_entry *bte;
        methoddesc         *md;
+       fieldinfo          *fi;
+       unresolved_field   *uf;
+       s4                  fieldtype;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
 
        /* prevent compiler warnings */
 
@@ -284,78 +308,86 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
        lm = NULL;
        bte = NULL;
 
-       /* create method header */
+       /* determine stackframe size (in units of ptrint slots) */
 
-       (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
-       (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P);    /* FrameSize      */
+       cd->stackframesize = m->maxlocals;
 
-#if defined(USE_THREADS)
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_adds4(cd, 1);                           /* IsSync         */
-       else
+#if defined(ENABLE_THREADS)
+       if (checksync && code_is_synchronized(code))
+               cd->stackframesize += 1;
 #endif
-               (void) dseg_adds4(cd, 0);                           /* IsSync         */
-                                              
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
 
-       dseg_addlinenumbertablesize(cd);
+       /* create method header */
 
-       (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
+       (void) dseg_add_unique_address(cd, jd->code);
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
 
-       /* create exception table */
+       code->synchronizedoffset = rd->memuse * 8;
 
-       for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
-               dseg_addtarget(cd, ex->start);
-               dseg_addtarget(cd, ex->end);
-               dseg_addtarget(cd, ex->handler);
-               (void) dseg_addaddress(cd, ex->catchtype.cls);
-       }
-       
+       /* 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, 0);
+       (void) dseg_add_unique_s4(cd, 0);
+
+       dseg_addlinenumbertablesize(cd);
+
+#if 0  
        /* initialize mcode variables */
        
        cd->mcodeptr = cd->mcodebase;
        cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+#endif
 
        gen_BBSTART;
 
-#if defined(USE_THREADS)
-       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
-               if (m->flags & ACC_STATIC)
-                       gen_ACONST(((Inst **)cd), (java_objectheader *) m->class);
-               else
-                       gen_ALOAD(((Inst **)cd), 0);
+#if defined(ENABLE_THREADS)
+       if (checksync && code_is_synchronized(code)) {
+               if (m->flags & ACC_STATIC) {
+                       gen_ACONST(cd, (java_objectheader *) m->clazz);
+               }
+               else {
+                       gen_ALOAD(cd, 0);
+                       gen_DUP(cd);
+                       gen_ASTORE(cd, index2offset(m->maxlocals));
+               }
                
-               gen_MONITORENTER(((Inst **)cd));
+               gen_MONITORENTER(cd);
        }                       
 #endif
 
-       if (runverbose)
-               gen_TRACECALL(((Inst **)cd));
+       if (opt_verbosecall)
+               gen_TRACECALL(cd, m);
+
+       gen_BBEND;
 
        /* walk through all basic blocks */
 
-       for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
 
                bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
 
-               if (bptr->flags >= BBREACHED) {
+               if (bptr->flags != BBDELETED) {
 
                /* walk through all instructions */
                
-               src = bptr->instack;
                len = bptr->icount;
 
                gen_BBSTART;
 
-               for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
+               for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
                        if (iptr->line != currentline) {
-                               dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
+                               dseg_addlinenumber(cd, iptr->line);
                                currentline = iptr->line;
                        }
 
                MCODECHECK(64);       /* an instruction usually needs < 64 words      */
+
+switch_again:
                switch (iptr->opc) {
 
                case ICMD_INLINE_START:
@@ -367,7 +399,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
 
-                       gen_CHECKNULL(((Inst **)cd));
+                       gen_CHECKNULL(cd);
                        break;
 
                /* constant operations ************************************************/
@@ -375,35 +407,153 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_ICONST:     /* ...  ==> ..., constant                       */
                                      /* op1 = 0, val.i = constant                    */
 
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
+                       /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
+
+                       if (len >= 2 && iptr[1].opc == ICMD_IREM) {
+                               switch (iptr[0].sx.val.i) {
+       case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
+       case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
+       case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
+       case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
+       case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
+       case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
+       case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
+       case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
+                                       iptr[0].opc = ICMD_IREMPOW2;
+                                       iptr[0].sx.val.i--;
+                                       iptr[1].opc = ICMD_NOP;
+                                       goto switch_again;
+                               }
+                       }
+
+                       /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
+
+                       if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
+                               switch (iptr[0].sx.val.i) {
+                              case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
+       case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
+       case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+       case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+       case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+       case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+       case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+       case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+       default: goto dont_opt_IDIVPOW2;
+                               }
+                               iptr[0].opc = ICMD_IDIVPOW2;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+dont_opt_IDIVPOW2:
+
+                       /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
+
+                       if (len >= 2) {
+                               switch (iptr[1].opc) {
+                                       case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
+                                       case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
+                                       case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
+                                       case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
+                                       case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
+                                       case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
+                                       default:        goto dont_opt_IFxx;
+                               }
+                               iptr[0].dst.insindex = iptr[1].dst.insindex;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+dont_opt_IFxx:
+
+                       gen_ICONST(cd, iptr->sx.val.i);
                        break;
 
                case ICMD_LCONST:     /* ...  ==> ..., constant                       */
                                      /* op1 = 0, val.l = constant                    */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
+
+                       if (len >= 2 && iptr[1].opc == ICMD_LREM) {
+                               switch (iptr[0].sx.val.l) {
+       case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
+       case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
+       case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
+       case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
+       case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
+       case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
+       case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
+       case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
+                                       iptr[0].opc = ICMD_LREMPOW2;
+                                       iptr[0].sx.val.l--;
+                                       iptr[1].opc = ICMD_NOP;
+                                       goto switch_again;
+                               }
+                       }
+
+                       /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
+
+                       if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
+                               switch (iptr[0].sx.val.l) {
+                              case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
+       case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
+       case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+       case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+       case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+       case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+       case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+       case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+       default: goto dont_opt_LDIVPOW2;
+                               }
+                               iptr[0].opc = ICMD_LDIVPOW2;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+dont_opt_LDIVPOW2:
+
+                       /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
+
+                       if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
+                               switch (iptr[2].opc) {
+                                       case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
+                                       case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
+                                       case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
+                                       case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
+                                       case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
+                                       case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
+                                       default:        goto dont_opt_IF_Lxx;
+                               }
+                               iptr[0].dst.insindex = iptr[2].dst.insindex;
+                               iptr[1].opc = ICMD_NOP;
+                               iptr[2].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+dont_opt_IF_Lxx:
+
+                       gen_LCONST(cd, iptr->sx.val.l);
                        break;
 
                case ICMD_FCONST:     /* ...  ==> ..., constant                       */
                                      /* op1 = 0, val.f = constant                    */
                        {
-                               s4 fi;
+                               ptrint fi;
 
-                               vm_f2Cell(iptr->val.f, fi);
-                               gen_ICONST(((Inst **)cd), fi);
+                               vm_f2Cell(iptr->sx.val.f, fi);
+                               gen_ICONST(cd, fi);
                        }
                        break;
                        
                case ICMD_DCONST:     /* ...  ==> ..., constant                       */
                                      /* op1 = 0, val.d = constant                    */
 
-                       gen_LCONST(((Inst **)cd), *(s8 *)&(iptr->val.d));
+                       gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
                        break;
 
                case ICMD_ACONST:     /* ...  ==> ..., constant                       */
                                      /* op1 = 0, val.a = constant                    */
 
-                       gen_ACONST(((Inst **)cd), iptr->val.a);
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                               gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
+                       else
+                               gen_ACONST(cd, iptr->sx.val.anyptr);
                        break;
 
 
@@ -412,141 +562,111 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
                                      /* op1 = local variable                         */
 
-                       gen_ILOAD(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ILOAD(cd, index2offset(iptr->s1.varindex));
                        break;
 
                case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
                                      /* op1 = local variable                         */
 
-                       gen_LLOAD(((Inst **)cd), index2offset(iptr->op1));
+                       gen_LLOAD(cd, index2offset(iptr->s1.varindex));
                        break;
 
                case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
                                      /* op1 = local variable                         */
 
-                       gen_ALOAD(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ALOAD(cd, index2offset(iptr->s1.varindex));
                        break;
 
                case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
                                      /* op1 = local variable                         */
 
-                       gen_ILOAD(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ILOAD(cd, index2offset(iptr->s1.varindex));
                        break;
 
                case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
                                      /* op1 = local variable                         */
 
-                       gen_LLOAD(((Inst **)cd), index2offset(iptr->op1));
+                       gen_LLOAD(cd, index2offset(iptr->s1.varindex));
                        break;
 
 
                case ICMD_ISTORE:     /* ..., value  ==> ...                          */
                                      /* op1 = local variable                         */
 
-                       gen_ISTORE(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ISTORE(cd, index2offset(iptr->dst.varindex));
                        break;
 
                case ICMD_LSTORE:     /* ..., value  ==> ...                          */
                                      /* op1 = local variable                         */
 
-                       gen_LSTORE(((Inst **)cd), index2offset(iptr->op1));
+                       gen_LSTORE(cd, index2offset(iptr->dst.varindex));
                        break;
 
                case ICMD_ASTORE:     /* ..., value  ==> ...                          */
                                      /* op1 = local variable                         */
 
-                       gen_ASTORE(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ASTORE(cd, index2offset(iptr->dst.varindex));
                        break;
 
 
                case ICMD_FSTORE:     /* ..., value  ==> ...                          */
                                      /* op1 = local variable                         */
 
-                       gen_ISTORE(((Inst **)cd), index2offset(iptr->op1));
+                       gen_ISTORE(cd, index2offset(iptr->dst.varindex));
                        break;
 
                case ICMD_DSTORE:     /* ..., value  ==> ...                          */
                                      /* op1 = local variable                         */
 
-                       gen_LSTORE(((Inst **)cd), index2offset(iptr->op1));
+                       gen_LSTORE(cd, index2offset(iptr->dst.varindex));
                        break;
 
 
                /* pop/dup/swap operations ********************************************/
 
-               /* attention: double and longs are only one entry in CACAO ICMDs      */
-
-               /* stack.c changes stack manipulation operations to treat
-                  longs/doubles as occupying a single slot.  Here we are
-                  undoing that (and only those things that stack.c did). */
-
                case ICMD_POP:        /* ..., value  ==> ...                          */
 
-                       if (IS_2_WORD_TYPE(src->type))
-                               gen_POP2(((Inst **)cd));
-                       else
-                               gen_POP(((Inst **)cd));
+                       gen_POP(cd);
                        break;
 
                case ICMD_POP2:       /* ..., value, value  ==> ...                   */
 
-                       gen_POP2(((Inst **)cd));
+                       gen_POP2(cd);
                        break;
 
                case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
 
-                       if (IS_2_WORD_TYPE(src->type))
-                               gen_DUP2(((Inst **)cd));
-                       else
-                               gen_DUP(((Inst **)cd));
+                       gen_DUP(cd);
                        break;
 
                case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
 
-                       if (IS_2_WORD_TYPE(src->type)) {
-                               if (IS_2_WORD_TYPE(src->prev->type)) {
-                                       gen_DUP2_X2(((Inst **)cd));
-                               } else {
-                                       gen_DUP2_X1(((Inst **)cd));
-                               }
-                       } else {
-                               if (IS_2_WORD_TYPE(src->prev->type)) {
-                                       gen_DUP_X2(((Inst **)cd));
-                               } else {
-                                       gen_DUP_X1(((Inst **)cd));
-                               }
-                       }
+                       gen_DUP_X1(cd);
                        break;
 
                case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
 
-                       if (IS_2_WORD_TYPE(src->type)) {
-                               gen_DUP2_X2(((Inst **)cd));
-                       } else
-                               gen_DUP_X2(((Inst **)cd));
+                       gen_DUP_X2(cd);
                        break;
 
                case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
 
-                       gen_DUP2(((Inst **)cd));
+                       gen_DUP2(cd);
                        break;
 
                case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
 
-                       if (IS_2_WORD_TYPE(src->prev->prev->type))
-                               gen_DUP2_X2(((Inst **)cd));
-                       else
-                               gen_DUP2_X1(((Inst **)cd));
+                       gen_DUP2_X1(cd);
                        break;
 
                case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
 
-                       gen_DUP2_X2(((Inst **)cd));
+                       gen_DUP2_X2(cd);
                        break;
 
                case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
 
-                       gen_SWAP(((Inst **)cd));
+                       gen_SWAP(cd);
                        break;
 
 
@@ -554,309 +674,203 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
 
-                       gen_INEG(((Inst **)cd));
+                       gen_INEG(cd);
                        break;
 
                case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
 
-                       gen_LNEG(((Inst **)cd));
+                       gen_LNEG(cd);
                        break;
 
                case ICMD_I2L:        /* ..., value  ==> ..., value                   */
 
-                       gen_I2L(((Inst **)cd));
+                       gen_I2L(cd);
                        break;
 
                case ICMD_L2I:        /* ..., value  ==> ..., value                   */
 
-                       gen_L2I(((Inst **)cd));
+                       gen_L2I(cd);
                        break;
 
                case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
 
-                       gen_INT2BYTE(((Inst **)cd));
+                       gen_INT2BYTE(cd);
                        break;
 
                case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
 
-                       gen_INT2CHAR(((Inst **)cd));
+                       gen_INT2CHAR(cd);
                        break;
 
                case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
 
-                       gen_INT2SHORT(((Inst **)cd));
+                       gen_INT2SHORT(cd);
                        break;
 
 
                case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
 
-                       gen_IADD(((Inst **)cd));
-                       break;
-
-               case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IADD(((Inst **)cd));
+                       gen_IADD(cd);
                        break;
 
                case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
 
-                       gen_LADD(((Inst **)cd));
-                       break;
-
-               case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
-                                     /* val.l = constant                             */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LADD(((Inst **)cd));
+                       gen_LADD(cd);
                        break;
 
                case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
 
-                       gen_ISUB(((Inst **)cd));
-                       break;
-
-               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_ISUB(((Inst **)cd));
+                       gen_ISUB(cd);
                        break;
 
                case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
 
-                       gen_LSUB(((Inst **)cd));
-                       break;
-
-               case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
-                                     /* val.l = constant                             */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LSUB(((Inst **)cd));
+                       gen_LSUB(cd);
                        break;
 
                case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
 
-                       gen_IMUL(((Inst **)cd));
-                       break;
-
-               case ICMD_IMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IMUL(((Inst **)cd));
+                       gen_IMUL(cd);
                        break;
 
                case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
 
-                       gen_LMUL(((Inst **)cd));
-                       break;
-
-               case ICMD_LMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LMUL(((Inst **)cd));
+                       gen_LMUL(cd);
                        break;
 
                case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
 
-                       gen_IDIV(((Inst **)cd));
+                       gen_IDIV(cd);
                        break;
 
                case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       gen_IREM(((Inst **)cd));
+                       gen_IREM(cd);
                        break;
 
                case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
 
-                       gen_LDIV(((Inst **)cd));
+                       gen_LDIV(cd);
                        break;
 
                case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       gen_LREM(((Inst **)cd));
+                       gen_LREM(cd);
                        break;
 
                case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                      /* val.i = constant                             */
                                      
-                       gen_IDIVPOW2(((Inst **)cd), iptr->val.i);
+                       gen_IDIVPOW2(cd, iptr->sx.val.i);
                        break;
 
                case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                      /* val.i = constant                             */
 
-                       gen_IREMPOW2(((Inst **)cd), iptr->val.i);
+                       gen_IREMPOW2(cd, iptr->sx.val.i);
                        break;
 
                case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                      /* val.i = constant                             */
                                      
-                       gen_LDIVPOW2(((Inst **)cd), iptr->val.i);
+                       gen_LDIVPOW2(cd, iptr->sx.val.i);
                        break;
 
                case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                      /* val.l = constant                             */
 
-                       gen_LREMPOW2(((Inst **)cd), iptr->val.i);
+                       gen_LREMPOW2(cd, iptr->sx.val.i);
                        break;
 
                case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
 
-                       gen_ISHL(((Inst **)cd));
-                       break;
-
-               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_ISHL(((Inst **)cd));
+                       gen_ISHL(cd);
                        break;
 
                case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
 
-                       gen_ISHR(((Inst **)cd));
-                       break;
-
-               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_ISHR(((Inst **)cd));
+                       gen_ISHR(cd);
                        break;
 
                case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
 
-                       gen_IUSHR(((Inst **)cd));
-                       break;
-
-               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IUSHR(((Inst **)cd));
+                       gen_IUSHR(cd);
                        break;
 
                case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
 
-                       gen_LSHL(((Inst **)cd));
-                       break;
-
-               case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_LSHL(((Inst **)cd));
+                       gen_LSHL(cd);
                        break;
 
                case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
 
-                       gen_LSHR(((Inst **)cd));
-                       break;
-
-               case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_LSHR(((Inst **)cd));
+                       gen_LSHR(cd);
                        break;
 
                case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
 
-                       gen_LUSHR(((Inst **)cd));
-                       break;
-
-               case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_LUSHR(((Inst **)cd));
+                       gen_LUSHR(cd);
                        break;
 
                case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
 
-                       gen_IAND(((Inst **)cd));
-                       break;
-
-               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IAND(((Inst **)cd));
+                       gen_IAND(cd);
                        break;
 
                case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
 
-                       gen_LAND(((Inst **)cd));
-                       break;
-
-               case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
-                                     /* val.l = constant                             */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LAND(((Inst **)cd));
+                       gen_LAND(cd);
                        break;
 
                case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
 
-                       gen_IOR(((Inst **)cd));
-                       break;
-
-               case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IOR(((Inst **)cd));
+                       gen_IOR(cd);
                        break;
 
                case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
 
-                       gen_LOR(((Inst **)cd));
-                       break;
-
-               case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
-                                     /* val.l = constant                             */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LOR(((Inst **)cd));
+                       gen_LOR(cd);
                        break;
 
                case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
 
-                       gen_IXOR(((Inst **)cd));
-                       break;
-
-               case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
-                                     /* val.i = constant                             */
-
-                       gen_ICONST(((Inst **)cd), iptr->val.i);
-                       gen_IXOR(((Inst **)cd));
+                       gen_IXOR(cd);
                        break;
 
                case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
 
-                       gen_LXOR(((Inst **)cd));
-                       break;
-
-               case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
-                                     /* val.l = constant                             */
-
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
-                       gen_LXOR(((Inst **)cd));
+                       gen_LXOR(cd);
                        break;
 
 
                case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
 
-                       gen_LCMP(((Inst **)cd));
+                       /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
+
+                       if (len >= 2 && iptr[1].sx.val.i == 0) {
+                               switch (iptr[1].opc) {
+                                       case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
+                                       case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
+                                       case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
+                                       case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
+                                       case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
+                                       case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
+                                       default:        goto dont_opt_IF_LCMPxx;
+                               }
+                               iptr[0].dst.insindex = iptr[1].dst.insindex;
+                               iptr[1].opc = ICMD_NOP;
+                               goto switch_again;
+                       }
+dont_opt_IF_LCMPxx:
+
+                       gen_LCMP(cd);
                        break;
 
 
                case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
                                      /* op1 = variable, val.i = constant             */
 
-                       gen_IINC(((Inst **)cd), index2offset(iptr->op1), iptr->val.i);
+                       gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
                        break;
 
 
@@ -864,132 +878,132 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
 
-                       gen_FNEG(((Inst **)cd));
+                       gen_FNEG(cd);
                        break;
 
                case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
 
-                       gen_DNEG(((Inst **)cd));
+                       gen_DNEG(cd);
                        break;
 
                case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
 
-                       gen_FADD(((Inst **)cd));
+                       gen_FADD(cd);
                        break;
 
                case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
 
-                       gen_DADD(((Inst **)cd));
+                       gen_DADD(cd);
                        break;
 
                case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
 
-                       gen_FSUB(((Inst **)cd));
+                       gen_FSUB(cd);
                        break;
 
                case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
 
-                       gen_DSUB(((Inst **)cd));
+                       gen_DSUB(cd);
                        break;
 
                case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
 
-                       gen_FMUL(((Inst **)cd));
+                       gen_FMUL(cd);
                        break;
 
                case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */
 
-                       gen_DMUL(((Inst **)cd));
+                       gen_DMUL(cd);
                        break;
 
                case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
 
-                       gen_FDIV(((Inst **)cd));
+                       gen_FDIV(cd);
                        break;
 
                case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
 
-                       gen_DDIV(((Inst **)cd));
+                       gen_DDIV(cd);
                        break;
                
                case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       gen_FREM(((Inst **)cd));
+                       gen_FREM(cd);
                        break;
 
                case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       gen_DREM(((Inst **)cd));
+                       gen_DREM(cd);
                        break;
                
                case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
 
-                       gen_I2F(((Inst **)cd));
+                       gen_I2F(cd);
                        break;
 
                case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
 
-                       gen_L2F(((Inst **)cd));
+                       gen_L2F(cd);
                        break;
 
                case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
 
-                       gen_I2D(((Inst **)cd));
+                       gen_I2D(cd);
                        break;
                        
                case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
 
-                       gen_L2D(((Inst **)cd));
+                       gen_L2D(cd);
                        break;
                        
                case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
 
-                       gen_F2I(((Inst **)cd));
+                       gen_F2I(cd);
                        break;
                
                case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
 
-                       gen_D2I(((Inst **)cd));
+                       gen_D2I(cd);
                        break;
                
                case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
 
-                       gen_F2L(((Inst **)cd));
+                       gen_F2L(cd);
                        break;
 
                case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
 
-                       gen_D2L(((Inst **)cd));
+                       gen_D2L(cd);
                        break;
 
                case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
 
-                       gen_F2D(((Inst **)cd));
+                       gen_F2D(cd);
                        break;
                                        
                case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
 
-                       gen_D2F(((Inst **)cd));
+                       gen_D2F(cd);
                        break;
                
                case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
 
-                       gen_FCMPL(((Inst **)cd));
+                       gen_FCMPL(cd);
                        break;
                        
                case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
 
-                       gen_DCMPL(((Inst **)cd));
+                       gen_DCMPL(cd);
                        break;
                        
                case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
 
-                       gen_FCMPG(((Inst **)cd));
+                       gen_FCMPG(cd);
                        break;
 
                case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
 
-                       gen_DCMPG(((Inst **)cd));
+                       gen_DCMPG(cd);
                        break;
 
 
@@ -997,290 +1011,266 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
 
-                       gen_ARRAYLENGTH(((Inst **)cd));
+                       gen_ARRAYLENGTH(cd);
                        break;
 
                case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_BALOAD(((Inst **)cd));
+                       gen_BALOAD(cd);
                        break;
 
                case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_CALOAD(((Inst **)cd));
+                       gen_CALOAD(cd);
                        break;                  
 
                case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_SALOAD(((Inst **)cd));
+                       gen_SALOAD(cd);
                        break;
 
                case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_IALOAD(cd);
+                       break;
+
                case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_IALOAD(((Inst **)cd));
+                       gen_FALOAD(cd);
                        break;
 
                case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
                case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_LALOAD(((Inst **)cd));
+                       gen_LALOAD(cd);
                        break;
 
                case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
-                       gen_AALOAD(((Inst **)cd));
+                       gen_AALOAD(cd);
                        break;
 
 
                case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       gen_BASTORE(((Inst **)cd));
+                       gen_BASTORE(cd);
                        break;
 
                case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
                case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       gen_CASTORE(((Inst **)cd));
+                       gen_CASTORE(cd);
                        break;
 
                case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_IASTORE(cd);
+                       break;
+
                case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       gen_IASTORE(((Inst **)cd));
+                       gen_FASTORE(cd);
                        break;
 
                case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
                case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       gen_LASTORE(((Inst **)cd));
+                       gen_LASTORE(cd);
                        break;
 
                case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       gen_AASTORE(((Inst **)cd));
+                       gen_AASTORE(cd);
                        break;
 
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
                                      /* op1 = type, val.a = field address            */
 
-                       {
-                       fieldinfo *fi = iptr->val.a;
-                       unresolved_field *uf = iptr->target;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               fi        = NULL;
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
+                               fieldtype = fi->type;
+                       }
 
-                       switch (iptr->op1) {
+                       switch (fieldtype) {
                        case TYPE_INT:
+                               if (fi == NULL)
+                                       gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
+                               else
+                                       gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
+                               break;
                        case TYPE_FLT:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_GETSTATIC_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETSTATIC_INT(((Inst **)cd), (u1 *)&(fi->value.i), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
+                               else
+                                       gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
                                break;
                        case TYPE_LNG:
                        case TYPE_DBL:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_GETSTATIC_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETSTATIC_LONG(((Inst **)cd), (u1 *)&(fi->value.l), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
+                               else
+                                       gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
                                break;
                        case TYPE_ADR:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_GETSTATIC_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETSTATIC_CELL(((Inst **)cd), (u1 *)&(fi->value.a), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
+                               else
+                                       gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
                                break;
                        }
-                       }
                        break;
 
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
                                      /* op1 = type, val.a = field address            */
 
-                       {
-                       fieldinfo *fi = iptr->val.a;
-                       unresolved_field *uf = iptr->target;
-
-                       switch (iptr->op1) {
-                       case TYPE_INT:
-                       case TYPE_FLT:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_INT(((Inst **)cd), (u1 *)&(fi->value.i), uf);
-                               }
-                               break;
-                       case TYPE_LNG:
-                       case TYPE_DBL:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_LONG(((Inst **)cd), (u1 *)&(fi->value.l), uf);
-                               }
-                               break;
-                       case TYPE_ADR:
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_CELL(((Inst **)cd), (u1 *)&(fi->value.a), uf);
-                               }
-                               break;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               fi        = NULL;
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
                        }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
+                               fieldtype = fi->type;
                        }
-                       break;
-
-               case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
-                                         /* val = value (in current instruction)     */
-                                         /* op1 = type, val.a = field address (in    */
-                                         /* following NOP)                           */
-
-                       {
-                       fieldinfo *fi = iptr[1].val.a;
-                       unresolved_field *uf = iptr[1].target;
 
-                       switch (iptr->op1) {
+                       switch (fieldtype) {
                        case TYPE_INT:
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
+                               else
+                                       gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
+                               break;
                        case TYPE_FLT:
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_INT(((Inst **)cd), (u1 *)&(fi->value.i), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
+                               else
+                                       gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
                                break;
                        case TYPE_LNG:
                        case TYPE_DBL:
-                               gen_LCONST(((Inst **)cd), iptr->val.l);
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_LONG(((Inst **)cd), (u1 *)&(fi->value.l), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
+                               else
+                                       gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
                                break;
                        case TYPE_ADR:
-                               gen_ACONST(((Inst **)cd), iptr->val.a);
-                               if (fi == NULL || !fi->class->initialized) {
-                                       gen_PATCHER_PUTSTATIC_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTSTATIC_CELL(((Inst **)cd), (u1 *)&(fi->value.a), uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
+                               else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+                                       gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
+                               else
+                                       gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
                                break;
                        }
-                       }
                        break;
 
 
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
                                      /* op1 = type, val.a = field address            */
 
-                       {
-                       fieldinfo *fi = iptr->val.a;
-                       unresolved_field *uf = iptr->target;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               fi        = NULL;
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
+                               fieldtype = fi->type;
+                       }
 
-                       switch (iptr->op1) {
+                       switch (fieldtype) {
                        case TYPE_INT:
+                               if (fi == NULL)
+                                       gen_PATCHER_GETFIELD_INT(cd, 0, uf);
+                               else
+                                       gen_GETFIELD_INT(cd, fi->offset, fi);
+                               break;
                        case TYPE_FLT:
-                               if (fi == NULL) {
-                                       gen_PATCHER_GETFIELD_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETFIELD_INT(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
+                               else
+                                       gen_GETFIELD_FLOAT(cd, fi->offset, fi);
                                break;
                        case TYPE_LNG:
                        case TYPE_DBL:
-                               if (fi == NULL) {
-                                       gen_PATCHER_GETFIELD_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETFIELD_LONG(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
+                               else
+                                       gen_GETFIELD_LONG(cd, fi->offset, fi);
                                break;
                        case TYPE_ADR:
-                               if (fi == NULL) {
-                                       gen_PATCHER_GETFIELD_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_GETFIELD_CELL(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
+                               else
+                                       gen_GETFIELD_CELL(cd, fi->offset, fi);
                                break;
                        }
-                       }
                        break;
 
                case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
                                      /* op1 = type, val.a = field address            */
 
-                       {
-                       fieldinfo *fi = iptr->val.a;
-                       unresolved_field *uf = iptr->target;
-
-                       switch (iptr->op1) {
-                       case TYPE_INT:
-                       case TYPE_FLT:
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_INT(((Inst **)cd), fi->offset, uf);
-                               }
-                               break;
-                       case TYPE_LNG:
-                       case TYPE_DBL:
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_LONG(((Inst **)cd), fi->offset, uf);
-                               }
-                               break;
-                       case TYPE_ADR:
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_CELL(((Inst **)cd), fi->offset, uf);
-                               }
-                               break;
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               fi        = NULL;
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
                        }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               uf        = NULL;
+                               fieldtype = fi->type;
                        }
-                       break;
 
-               case ICMD_PUTFIELDCONST:  /* ..., objectref  ==> ...                  */
-                                         /* val = value (in current instruction)     */
-                                         /* op1 = type, val.a = field address (in    */
-                                         /* following NOP)                           */
-
-                       {
-                       fieldinfo *fi = iptr[1].val.a;
-                       unresolved_field *uf = iptr[1].target;
-
-                       switch (iptr[1].op1) {
+                       switch (fieldtype) {
                        case TYPE_INT:
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
+                               else
+                                       gen_PUTFIELD_INT(cd, fi->offset, fi);
+                               break;
                        case TYPE_FLT:
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_INT(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_INT(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
+                               else
+                                       gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
                                break;
                        case TYPE_LNG:
                        case TYPE_DBL:
-                               gen_LCONST(((Inst **)cd), iptr->val.l);
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_LONG(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_LONG(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
+                               else
+                                       gen_PUTFIELD_LONG(cd, fi->offset, fi);
                                break;
                        case TYPE_ADR:
-                               gen_ACONST(((Inst **)cd), iptr->val.a);
-                               if (fi == NULL) {
-                                       gen_PATCHER_PUTFIELD_CELL(((Inst **)cd), 0, uf);
-                               } else {
-                                       gen_PUTFIELD_CELL(((Inst **)cd), fi->offset, uf);
-                               }
+                               if (fi == NULL)
+                                       gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
+                               else
+                                       gen_PUTFIELD_CELL(cd, fi->offset, fi);
                                break;
                        }
-                       }
                        break;
 
 
@@ -1288,7 +1278,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
 
-                       gen_ATHROW(((Inst **)cd));
+                       gen_ATHROW(cd);
                        break;
 
                case ICMD_GOTO:         /* ... ==> ...                                */
@@ -1298,13 +1288,15 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                case ICMD_JSR:          /* ... ==> ...                                */
                                        /* op1 = target JavaVM pc                     */
-                       gen_branch(JSR);
+
+                       gen_JSR(cd, NULL);
+                       codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
                        break;
-                       
+
                case ICMD_RET:          /* ... ==> ...                                */
                                        /* op1 = local variable                       */
 
-                       gen_RET(((Inst **)cd), index2offset(iptr->op1));
+                       gen_RET(cd, index2offset(iptr->s1.varindex));
                        break;
 
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
@@ -1322,10 +1314,10 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFEQ);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPEQ);
                        }
                        break;
@@ -1333,10 +1325,10 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFLT:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFLT);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPLT);
                        }
                        break;
@@ -1344,10 +1336,10 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFLE:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFLE);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPLE);
                        }
                        break;
@@ -1355,10 +1347,10 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFNE:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFNE);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPNE);
                        }
                        break;
@@ -1366,10 +1358,10 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFGT:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFGT);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPGT);
                        }
                        break;
@@ -1377,138 +1369,140 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IFGE:         /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.i = constant   */
 
-                       if (iptr->val.i == 0) {
+                       if (iptr->sx.val.i == 0) {
                                gen_branch(IFGE);
                        } else {
-                               gen_ICONST(((Inst **)cd), iptr->val.i);
+                               gen_ICONST(cd, iptr->sx.val.i);
                                gen_branch(IF_ICMPGE);
                        }
                        break;
 
+
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPEQ);
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPLT);
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPLE);
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPNE);
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPGT);
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
                                        /* op1 = target JavaVM pc, val.l = constant   */
 
-                       gen_LCONST(((Inst **)cd), iptr->val.l);
+                       gen_LCONST(cd, iptr->sx.val.l);
                        gen_branch(IF_LCMPGE);
                        break;
 
-               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPEQ);
+                       gen_branch(IF_LCMPEQ);
                        break;
 
-               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPEQ);
+                       gen_branch(IF_LCMPNE);
                        break;
 
-               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ACMPEQ);
+                       gen_branch(IF_LCMPLT);
                        break;
 
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPNE);
+                       gen_branch(IF_LCMPGT);
                        break;
 
-               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPNE);
+                       gen_branch(IF_LCMPLE);
                        break;
 
-               case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ACMPNE);
+                       gen_branch(IF_LCMPGE);
                        break;
 
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPLT);
+                       gen_branch(IF_ICMPEQ);
                        break;
 
-               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPLT);
+                       gen_branch(IF_ACMPEQ);
                        break;
 
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPGT);
+                       gen_branch(IF_ICMPNE);
                        break;
 
-               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPGT);
+                       gen_branch(IF_ACMPNE);
                        break;
 
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPLE);
+                       gen_branch(IF_ICMPLT);
                        break;
 
-               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPLE);
+                       gen_branch(IF_ICMPGT);
                        break;
 
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_ICMPGE);
+                       gen_branch(IF_ICMPLE);
                        break;
 
-               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
                                        /* op1 = target JavaVM pc                     */
 
-                       gen_branch(IF_LCMPGE);
+                       gen_branch(IF_ICMPGE);
                        break;
 
 
@@ -1516,220 +1510,216 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
                case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
 
-#if defined(USE_THREADS)
-                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+#if defined(ENABLE_THREADS)
+                       if (checksync && code_is_synchronized(code)) {
                                if (m->flags & ACC_STATIC) {
-                                       gen_ACONST(((Inst **)cd), (java_objectheader *) m->class);
+                                       gen_ACONST(cd, (java_objectheader *) m->clazz);
                                } else {
-                                       gen_ALOAD(((Inst **)cd), 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
-                               gen_MONITOREXIT(((Inst **)cd));
+                               gen_MONITOREXIT(cd);
                        }
 #endif
-                       if (runverbose)
-                               gen_TRACERETURN(((Inst **)cd));
+                       if (opt_verbosecall)
+                               gen_TRACERETURN(cd, m);
 
-                       gen_IRETURN(((Inst **)cd), index2offset(cd->maxlocals));
+                       gen_IRETURN(cd, index2offset(cd->stackframesize));
                        break;
 
                case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
                case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
 
-#if defined(USE_THREADS)
-                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+#if defined(ENABLE_THREADS)
+                       if (checksync && code_is_synchronized(code)) {
                                if (m->flags & ACC_STATIC) {
-                                       gen_ACONST(((Inst **)cd), (java_objectheader *) m->class);
+                                       gen_ACONST(cd, (java_objectheader *) m->clazz);
                                } else {
-                                       gen_ALOAD(((Inst **)cd), 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
-                               gen_MONITOREXIT(((Inst **)cd));
+                               gen_MONITOREXIT(cd);
                        }
 #endif
-                       if (runverbose)
-                               gen_TRACELRETURN(((Inst **)cd));
+                       if (opt_verbosecall)
+                               gen_TRACELRETURN(cd, m);
 
-                       gen_LRETURN(((Inst **)cd), index2offset(cd->maxlocals));
+                       gen_LRETURN(cd, index2offset(cd->stackframesize));
                        break;
 
                case ICMD_RETURN:       /* ...  ==> ...                               */
 
-#if defined(USE_THREADS)
-                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+#if defined(ENABLE_THREADS)
+                       if (checksync && code_is_synchronized(code)) {
                                if (m->flags & ACC_STATIC) {
-                                       gen_ACONST(((Inst **)cd), (java_objectheader *) m->class);
+                                       gen_ACONST(cd, (java_objectheader *) m->clazz);
                                } else {
-                                       gen_ALOAD(((Inst **)cd), 0);
+                                       gen_ALOAD(cd, index2offset(m->maxlocals));
                                }
-                               gen_MONITOREXIT(((Inst **)cd));
+                               gen_MONITOREXIT(cd);
                        }
 #endif
-                       if (runverbose)
-                               gen_TRACERETURN(((Inst **)cd));
+                       if (opt_verbosecall)
+                               gen_TRACERETURN(cd, m);
 
-                       gen_RETURN(((Inst **)cd), index2offset(cd->maxlocals));
+                       gen_RETURN(cd, index2offset(cd->stackframesize));
                        break;
 
 
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                        {
-                       s4 i, l, *s4ptr;
-                       void **tptr;
+                       s4 i, l;
+                       branch_target_t *table;
 
-                       tptr = (void **) iptr->target;
+                       table = iptr->dst.table;
 
-                       s4ptr = iptr->val.a;
-                       l = s4ptr[1];                          /* low     */
-                       i = s4ptr[2];                          /* high    */
+                       l = iptr->sx.s23.s2.tablelow;
+                       i = iptr->sx.s23.s3.tablehigh;
                        
                        i = i - l + 1;
 
-                       /* arguments: low, range, datasegment address, table offset in     */
-                       /* datasegment, default target                                    */
-                       gen_TABLESWITCH(((Inst **)cd), l, i, NULL, 0, NULL);
-                       dseg_adddata(cd, (cd->mcodeptr - 2*sizeof(Inst))); /* actually -3 cells offset*/
-                       codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
+                       /* arguments: low, range, datasegment address, table
+                      offset in datasegment, default target */
+
+                       gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
+
+                       /* actually -3 cells offset */
+
+                       cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
+                       dseg_adddata(cd);
+                       cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
+
+                       codegen_addreference(cd, BLOCK_OF(table[0].insindex));
 
                        /* build jump table top down and use address of lowest entry */
 
-                       tptr += i;
+                       table += i;
 
                        while (--i >= 0) {
-                               dseg_addtarget(cd, (basicblock *) tptr[0]); 
-                               --tptr;
+                               dseg_add_target(cd, BLOCK_OF(table->insindex)); 
+                               --table;
                        }
                        }
 
-                       /* length of dataseg after last dseg_addtarget is used by load */
+                       /* length of dataseg after last dseg_add_target is used by load */
                        ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                        break;
 
 
                case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
                        {
-                       s4 i, *s4ptr;
-                       void **tptr;
+                       s4 i;
+                       lookup_target_t *lookup;
 
-                       tptr = (void **) iptr->target;
+                       lookup = iptr->dst.lookup;
 
-                       s4ptr = iptr->val.a;
-
-                       /* s4ptr[0] is equal to tptr[0] */
-                       i = s4ptr[1];                          /* count    */
+                       i = iptr->sx.s23.s2.lookupcount;
                        
                        /* arguments: count, datasegment address, table offset in         */
                        /* datasegment, default target                                    */
-                       gen_LOOKUPSWITCH(((Inst **)cd), i, NULL, 0, NULL);
-                       dseg_adddata(cd, (cd->mcodeptr - 2*sizeof(Inst))); /* actually -3 cells offset*/
-                       codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
+                       gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
 
-                       /* build jump table top down and use address of lowest entry */
+                       /* actually -3 cells offset */
 
-                       tptr += i;
-                       s4ptr += i * 2;
+                       cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
+                       dseg_adddata(cd);
+                       cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
+
+                       /* build jump table top down and use address of lowest entry */
 
                        while (--i >= 0) {
-                               dseg_addtarget(cd, (basicblock *) tptr[0]); 
-                               dseg_addaddress(cd, s4ptr[0]);
-                               --tptr;
-                               s4ptr -= 2;
+                               dseg_add_target(cd, BLOCK_OF(lookup->target.insindex)); 
+                               dseg_add_unique_address(cd, lookup->value);
+                               lookup++;
                        }
+
+                       codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
                        }
 
-                       /* length of dataseg after last dseg_addtarget is used by load */
+                       /* length of dataseg after last dseg_add_target is used by load */
                        ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                        break;
 
 
                case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
                                        /* op1 = arg count val.a = builtintable entry */
-                       bte = iptr->val.a;
-                       if (bte->fp == PATCHER_builtin_new) {
-                               gen_PATCHER_NEW(((Inst **)cd), 0);
-                       } else if (bte->fp == PATCHER_builtin_newarray) {
-                               gen_PATCHER_NEWARRAY(((Inst **)cd), 0);
-                       } else if (bte->fp == PATCHER_builtin_arrayinstanceof) {
-                               gen_PATCHER_ARRAYINSTANCEOF(((Inst **)cd), 0);
-                       } else {
-                               for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
-                                       builtin_gen *bg = &builtin_gen_table[i];
-                                       if (bg->builtin == bte->fp) {
-                                               (bg->gen)(((Inst **)cd));
-                                               goto gen_builtin_end;
-                                       }
+                       bte = iptr->sx.s23.s3.bte;
+
+                       for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
+                               builtin_gen *bg = &builtin_gen_table[i];
+                               if (bg->builtin == bte->fp) {
+                                       (bg->gen)(cd);
+                                       goto gen_builtin_end;
                                }
-                               assert(0);
                        }
+
+                       vm_abort(0);
+
                gen_builtin_end:
                        break;
 
                case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
                                        /* op1 = arg count, val.a = method pointer    */
 
-                       lm = iptr->val.a;
-                       um = iptr->target;
-
-                       if (lm == NULL) {
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
                                md = um->methodref->parseddesc.md;
-                               gen_PATCHER_INVOKESTATIC(((Inst **)cd), 0, md->paramslots, um);
-
-                       } else {
+                               gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
                                md = lm->parseddesc;
-                               gen_INVOKESTATIC(((Inst **)cd), (Inst **)lm->stubroutine, md->paramslots, um);
+                               gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
                        }
                        break;
 
                case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
 
-                       lm = iptr->val.a;
-                       um = iptr->target;
-
-                       if (lm == NULL) {
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
                                md = um->methodref->parseddesc.md;
-                               gen_PATCHER_INVOKESPECIAL(((Inst **)cd), 0, md->paramslots, um);
-
-                       } else {
+                               gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
                                md = lm->parseddesc;
-                               gen_INVOKESPECIAL(((Inst **)cd), (Inst **)lm->stubroutine, md->paramslots, um);
+                               gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
                        }
                        break;
 
                case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
 
-                       lm = iptr->val.a;
-                       um = iptr->target;
-
-                       if (lm == NULL) {
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
                                md = um->methodref->parseddesc.md;
-                               gen_PATCHER_INVOKEVIRTUAL(((Inst **)cd), 0, md->paramslots, um);
-
-                       } else {
+                               gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
                                md = lm->parseddesc;
 
                                s1 = OFFSET(vftbl_t, table[0]) +
                                        sizeof(methodptr) * lm->vftblindex;
 
-                               gen_INVOKEVIRTUAL(((Inst **)cd), s1, md->paramslots, um);
+                               gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
                        }
                        break;
 
                case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */
 
-                       lm = iptr->val.a;
-                       um = iptr->target;
-
-                       if (lm == NULL) {
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               um = iptr->sx.s23.s3.um;
                                md = um->methodref->parseddesc.md;
-                               gen_PATCHER_INVOKEINTERFACE(((Inst **)cd), 0, 0, md->paramslots, um);
-
-                       } else {
+                               gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
                                md = lm->parseddesc;
 
                                s1 = OFFSET(vftbl_t, interfacetable[0]) -
-                                       sizeof(methodptr*) * lm->class->index;
+                                       sizeof(methodptr*) * lm->clazz->index;
 
-                               s2 = sizeof(methodptr) * (lm - lm->class->methods);
+                               s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
 
-                               gen_INVOKEINTERFACE(((Inst **)cd), s1, s2, md->paramslots, um);
+                               gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
                        }
                        break;
 
@@ -1738,22 +1728,17 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                      /* op1:   0 == array, 1 == class                */
                                      /* val.a: (classinfo *) superclass              */
 
-                       if (iptr->val.a == NULL) {
-                               gen_PATCHER_CHECKCAST(((Inst **)cd), 0, iptr->target);
-
-                       } else {
-                               gen_CHECKCAST(((Inst **)cd), iptr->val.a, iptr->target);
+                       if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                                       gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
+                               else
+                                       gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
                        }
-                       
-                       break;
-
-               case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref        */
-                                         /* op1: 1... resolved, 0... not resolved    */
-
-                       if (iptr->op1 == 0) {
-                               gen_PATCHER_ARRAYCHECKCAST(((Inst **)cd), 0, iptr->target);
-                       } else {
-                               gen_ARRAYCHECKCAST(((Inst **)cd), iptr->target, 0);
+                       else {
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                                       gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
+                               else
+                                       gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
                        }
                        break;
 
@@ -1761,128 +1746,183 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                      /* op1:   0 == array, 1 == class                */
                                      /* val.a: (classinfo *) superclass              */
 
-                       if (iptr->val.a == NULL) {
-                               gen_PATCHER_INSTANCEOF(((Inst **)cd), 0, iptr->target);
-                       } else {
-                               gen_INSTANCEOF(((Inst **)cd), iptr->val.a, iptr->target);
-                       }
-                       
-                       break;
-
-
-               case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
-
-                       /* XXX remove me! */
-                       break;
-
-               case ICMD_CHECKEXCEPTION:    /* ..., objectref ==> ..., objectref     */
-
-                       gen_CHECKEXCEPTION(((Inst **)cd));
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                               gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
+                       else
+                               gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
                        break;
 
                case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
-                                     /* op1 = dimension, val.a = array descriptor    */
+                                     /* op1 = dimension, val.a = class               */
 
-                       if (iptr->target) {
-                               gen_PATCHER_MULTIANEWARRAY(((Inst **)cd), 0, iptr->op1, iptr->val.a);
-                       } else {
-                               gen_MULTIANEWARRAY(((Inst **)cd), iptr->val.a, iptr->op1, 0);
-                       }
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                               gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
+                       else
+                               gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
                        break;
 
                default:
-                       throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                          "Unknown ICMD %d", iptr->opc);
+                       exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+                                                                                  iptr->opc);
+                       return false;
        } /* switch */
                
        } /* for instruction */
-               
-       } /* if (bptr -> flags >= BBREACHED) */
+
+       gen_BBEND;
+
+       } /* if (bptr->flags != BBDELETED) */
        } /* for basic block */
 
-       codegen_createlinenumbertable(cd);
+       dseg_createlinenumbertable(cd);
 
-       codegen_finish(m, cd, (s4) (cd->mcodeptr - cd->mcodebase));
+       codegen_finish(jd);
 
 #ifdef VM_PROFILING
-       vm_block_insert(m->mcode + m->mcodelength);
+       vm_block_insert(jd->code->mcode + jd->code->mcodelength);
 #endif
 
        /* branch resolving (walk through all basic blocks) */
 
-       for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
                branchref *brefs;
 
                for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
-                       gen_resolveanybranch(((u1*) m->entrypoint) + brefs->branchpos,
-                                            ((u1 *)m->entrypoint) + bptr->mpc);
+                       gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
+                                            ((u1 *)jd->code->entrypoint) + bptr->mpc);
                }
        }
+
+       /* everything's ok */
+
+       return true;
 }
 
 
-/* a stub consists of
+/* createcompilerstub **********************************************************
 
-+---------+
-|codeptr  |
-+---------+
-|maxlocals|
-+---------+
-|TRANSLATE|
-+---------+
-|methodinf|
-+---------+
+   Creates a stub routine which calls the compiler.
 
-codeptr points either to TRANSLATE or to the translated threaded code
+   A stub consists of:
 
-all methods are called indirectly through methodptr
-*/
+   +-------------+
+   | codeinfo *  |
+   +-------------+ <-- stub
+   | codeptr     |
+   +-------------+
+   | framesize   |  (in ptrint units, does not include return address)
+   +-------------+
+   | TRANSLATE   |
+   +-------------+
+   | methodinfo  |
+   +-------------+
 
-#define COMPILERSTUB_SIZE 4
+   codeptr points either to TRANSLATE or to the translated threaded code
 
-functionptr createcompilerstub (methodinfo *m)
+   all methods are called indirectly through methodptr
+
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE    2
+#define COMPILERSTUB_CODESIZE    4
+
+#define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
+
+
+u1 *intrp_createcompilerstub(methodinfo *m)
 {
        Inst        *s;
+       Inst        *d;
        codegendata *cd;
-       s4           dumpsize;
+       s4           stackframesize;
+       int32_t      dumpmarker;
 
        s = CNEW(Inst, COMPILERSTUB_SIZE);
 
+       /* set data pointer and code pointer */
+
+       d = s;
+       s = s + COMPILERSTUB_DATASIZE;
+
+       /* The codeinfo pointer is actually a pointer to the
+          methodinfo. This fakes a codeinfo structure. */
+
+       d[0] = (Inst *) m;
+       d[1] = (Inst *) &d[0];                                    /* fake code->m */
+
        /* mark start of dump memory area */
 
-       dumpsize = dump_size();
+       DMARKER;
        
        cd = DNEW(codegendata);
     cd->mcodeptr = (u1 *) s;
+       cd->lastinstwithoutdispatch = ~0;
+       cd->superstarts = NULL;
 
-       genarg_ainst((Inst **) cd, s + 2);
+       genarg_ainst(cd, s + 2);
 
        if (m->flags & ACC_NATIVE) {
-               genarg_i((Inst **) cd, m->parseddesc->paramslots);
-       } else {
-               genarg_i((Inst **) cd, m->maxlocals);
+               stackframesize = m->parseddesc->paramslots;
+       } 
+       else {
+               stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+               if (checksync && code_is_synchronized(code))
+                       stackframesize += 1;
+#endif
        }
 
+       genarg_i(cd, stackframesize);
+
        gen_BBSTART;
-       gen_TRANSLATE((Inst **) cd, m);
+       gen_TRANSLATE(cd, m);
+       gen_BBEND;
        
 #ifdef VM_PROFILING
        vm_block_insert(cd->mcodeptr);
 #endif
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_cstub_len += COMPILERSTUB_SIZE;
 #endif
 
        /* release dump area */
 
-       dump_release(dumpsize);
+       DRELEASE;
        
-       return (functionptr) s;
+       return (u1 *) s;
 }
 
 
+#if defined(WITH_FFI)
+static ffi_type *cacaotype2ffitype(s4 cacaotype)
+{
+       switch (cacaotype) {
+       case TYPE_INT:
+#if SIZEOF_VOID_P == 8
+               return &ffi_type_sint64;
+#else
+               return &ffi_type_sint32;
+#endif
+       case TYPE_LNG:
+               return &ffi_type_sint64;
+       case TYPE_FLT:
+               return &ffi_type_float;
+       case TYPE_DBL:
+               return &ffi_type_double;
+       case TYPE_ADR:
+               return &ffi_type_pointer;
+       case TYPE_VOID:
+               return &ffi_type_void;
+       default:
+               assert(false);
+       }
+}
+#endif
+
+
 /* native stub:
 +---------+
 |NATIVECALL|
@@ -1895,6 +1935,7 @@ functionptr createcompilerstub (methodinfo *m)
 +---------+
 */
 
+#if defined(WITH_FFI)
 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
 {
        methoddesc  *md = m->parseddesc; 
@@ -1924,114 +1965,302 @@ static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
 
        return pcif;
 }
+#endif
 
 
-functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
-                                                        registerdata *rd, methoddesc *nmd)
+u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 {
+       methodinfo   *m;
+       codeinfo     *code;
+       codegendata  *cd;
+       registerdata *rd;
+#if defined(WITH_FFI)
        ffi_cif *cif;
+#else
+       u1      *cif;
+#endif
+       s4            stackframesize;
 
-       cd->mcodeptr = cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* determine stackframe size (in units of ptrint) */
+
+       stackframesize = nmd->paramslots;
 
        /* create method header */
 
-       (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
-       (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize      */
-       (void) dseg_adds4(cd, 0);                               /* IsSync         */
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
+       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
+       (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
        dseg_addlinenumbertablesize(cd);
-       (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
+       (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
 
+#if defined(WITH_FFI)
        /* prepare ffi cif structure */
 
        cif = createnativecif(m, nmd);
+#else
+       cif = NULL;
+#endif
 
        gen_BBSTART;
 
-       if (runverbose)
-               gen_TRACECALL(((Inst **)cd));
+       if (opt_verbosecall)
+               gen_TRACECALL(cd, m);
 
        if (f == NULL) {
-               gen_PATCHER_NATIVECALL(((Inst **)cd), m, f, (u1 *)cif);
+               gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
        } else {
-               if (runverbose)
-                       gen_TRACENATIVECALL(((Inst **)cd), m, f, (u1 *)cif);
+               if (opt_verbosecall)
+                       gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
                else
-                       gen_NATIVECALL(((Inst **)cd), m, f, (u1 *)cif);
+                       gen_NATIVECALL(cd, m, f, (u1 *)cif);
        }
 
-       codegen_finish(m, cd, (s4) (cd->mcodeptr - cd->mcodebase));
+       gen_BBEND;
+
+       codegen_finish(jd);
 
 #ifdef VM_PROFILING
-       vm_block_insert(m->mcode + m->mcodelength);
+       vm_block_insert(jd->code->mcode + jd->code->mcodelength);
 #endif
 
-       return m->entrypoint;
+       return jd->code->entrypoint;
+}
+
+
+/* call jni function */
+Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
+{
+#if defined(WITH_FFCALL)
+       av_alist alist;
+       methoddesc *md;
+       Cell *p;
+       Cell *endsp;
+       s4 i;
+
+       struct {
+               stackframeinfo sfi;
+               localref_table lrt;
+       } s;
+
+       md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+               endsp = sp - 1 + md->paramslots;
+               av_start_long(alist, f, endsp);
+               break;
+       case TYPE_LNG:
+               endsp = sp - 2 + md->paramslots;
+               av_start_longlong(alist, f, endsp);
+               break;
+       case TYPE_FLT:
+               endsp = sp - 1 + md->paramslots;
+               av_start_float(alist, f, endsp);
+               break;
+       case TYPE_DBL:
+               endsp = sp - 2 + md->paramslots;
+               av_start_double(alist, f, endsp);
+               break;
+       case TYPE_ADR:
+               endsp = sp - 1 + md->paramslots;
+               av_start_ptr(alist, f, void *, endsp);
+               break;
+       case TYPE_VOID:
+               endsp = sp + md->paramslots;
+               av_start_void(alist, f);
+               break;
+       default:
+               assert(false);
+       }
+
+       av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
+
+       if (m->flags & ACC_STATIC)
+               av_ptr(alist, classinfo *, m->clazz);
+
+       for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
+               switch (md->paramtypes[i].type) {
+               case TYPE_INT:
+                       p -= 1;
+                       av_long(alist, *p);
+                       break;
+               case TYPE_LNG:
+                       p -= 2;
+                       av_longlong(alist, *(s8 *)p);
+                       break;
+               case TYPE_FLT:
+                       p -= 1;
+                       av_float(alist, *((float *) p));
+                       break;
+               case TYPE_DBL:
+                       p -= 2;
+                       av_double(alist, *(double *) p);
+                       break;
+               case TYPE_ADR:
+                       p -= 1;
+                       av_ptr(alist, void *, *(void **) p);
+                       break;
+               default:
+                       assert(false);
+               }
+       }
+
+       global_sp = sp;
+
+       /* create stackframe info structure */
+
+       codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
+                                                         (u1 *) fp, (u1 *) ra);
+
+       av_call(alist);
+
+       *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+
+       CLEAR_global_sp;
+
+       return endsp;
+#elif defined(WITH_FFI)
+       methoddesc  *md = m->parseddesc; 
+       ffi_cif     *pcif;
+       void        *values[md->paramcount + 2];
+       void       **pvalues = values;
+       Cell        *p;
+       Cell        *endsp;
+       s4           i;
+       _Jv_JNIEnv  *penv;
+
+       struct {
+               stackframeinfo sfi;
+               localref_table lrt;
+       } s;
+
+       pcif = (ffi_cif *) addrcif;
+
+       /* pass env pointer */
+
+       penv = (_Jv_JNIEnv *) VM_get_jnienv();
+       *pvalues++ = &penv;
+
+       /* for static methods, pass class pointer */
+
+       if (m->flags & ACC_STATIC)
+               *pvalues++ = &m->clazz;
+
+       /* pass parameter to native function */
+
+       for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
+               if (IS_2_WORD_TYPE(md->paramtypes[i].type))
+                       p -= 2;
+               else
+                       p--;
+
+               *pvalues++ = p;
+       }
+
+       /* calculate position of return value */
+
+       if (md->returntype.type == TYPE_VOID)
+               endsp = sp + md->paramslots;
+       else
+               endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
+
+       global_sp = sp;
+
+       /* create stackframe info structure */
+
+       codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
+                                                         (u1 *) fp, (u1 *) ra);
+
+       ffi_call(pcif, FFI_FN(f), endsp, values);
+
+       *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+
+       CLEAR_global_sp;
+
+       return endsp;
+#endif
 }
 
 
-functionptr createcalljavafunction(methodinfo *m)
+u1 *createcalljavafunction(methodinfo *m)
 {
        methodinfo         *tmpm;
-       functionptr         entrypoint;
+       u1                 *entrypoint;
+       jitdata            *jd;
        codegendata        *cd;
        registerdata       *rd;
-       t_inlining_globals *id;
-       s4                  dumpsize;
        methoddesc         *md;
+       int32_t             dumpmarker;
 
        /* mark dump memory */
 
-       dumpsize = dump_size();
+       DMARKER;
+
+       /* allocate memory */
+
+       jd = DNEW(jitdata);
 
        tmpm = DNEW(methodinfo);
        cd = DNEW(codegendata);
        rd = DNEW(registerdata);
-       id = DNEW(t_inlining_globals);
+
+       jd->m = tmpm;
+       jd->flags = 0;
+       jd->cd = cd;
+       jd->rd = rd;
+
+       /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+       jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
 
        /* setup code generation stuff */
 
        MSET(tmpm, 0, u1, sizeof(methodinfo));
 
-       inlining_setup(tmpm, id);
-       codegen_setup(tmpm, cd, id);
+       codegen_setup(jd);
 
        md = m->parseddesc;
 
-       cd->mcodeptr = cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
-
        /* create method header */
 
-       (void) dseg_addaddress(cd, NULL);                       /* MethodPointer  */
-       (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P);  /* FrameSize      */
-       (void) dseg_adds4(cd, 0);                               /* IsSync         */
-       (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
-       (void) dseg_adds4(cd, 0);                               /* IntSave        */
-       (void) dseg_adds4(cd, 0);                               /* FltSave        */
+       (void) dseg_add_unique_address(cd, NULL);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
+       (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
+       (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
        dseg_addlinenumbertablesize(cd);
-       (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
+       (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */
 
 
        /* generate code */
        
        gen_BBSTART;
-       gen_INVOKESTATIC(((Inst **)cd), (Inst **)m->stubroutine, md->paramslots, 0);
-       gen_END(((Inst **)cd));
-  
-       codegen_finish(tmpm, cd, (s4) (cd->mcodeptr - cd->mcodebase));
+       gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
+       gen_END(cd);
+
+       gen_BBEND;
+
+       codegen_finish(jd);
 
 #ifdef VM_PROFILING
-       vm_block_insert(tmpm->mcode + tmpm->mcodelength);
+       vm_block_insert(jd->code->mcode + jd->code->mcodelength);
 #endif
-       entrypoint = tmpm->entrypoint;
+       entrypoint = jd->code->entrypoint;
 
        /* release memory */
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return entrypoint;
 }
@@ -2048,4 +2277,5 @@ functionptr createcalljavafunction(methodinfo *m)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */