* More interpreter files (important ones).
authortwisti <none@none>
Fri, 2 Sep 2005 15:17:20 +0000 (15:17 +0000)
committertwisti <none@none>
Fri, 2 Sep 2005 15:17:20 +0000 (15:17 +0000)
src/vm/jit/intrp/codegen.c [new file with mode: 0644]
src/vm/jit/intrp/intrp.h [new file with mode: 0644]
src/vm/jit/intrp/java.vmg [new file with mode: 0644]

diff --git a/src/vm/jit/intrp/codegen.c b/src/vm/jit/intrp/codegen.c
new file mode 100644 (file)
index 0000000..8c2830f
--- /dev/null
@@ -0,0 +1,1840 @@
+/* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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: Joseph Wenninger
+            Christian Thalinger
+            Christian Ullrich
+
+   $Id: codegen.c 3140 2005-09-02 15:17:20Z twisti $
+
+*/
+
+
+#include <stdio.h>
+
+#include "config.h"
+
+#include "machine-instr.h"
+
+#include "vm/jit/intrp/arch.h"
+#include "vm/jit/intrp/codegen.h"
+#include "vm/jit/intrp/types.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 "vm/jit/parse.h"
+#include "vm/jit/patcher.h"
+
+#include "vm/jit/intrp/intrp.h"
+
+#define gen_branch(_inst) { \
+  gen_##_inst(&mcodeptr, 0); \
+  codegen_addreference(cd, (basicblock *) (iptr->target), mcodeptr); \
+}
+
+
+/* functions used by cacao-gen.i */
+
+void
+genarg_v(Inst ** ptr2current_threaded, Cell v)
+{
+  *((Cell *) *ptr2current_threaded) = v;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_i(Inst ** ptr2cur_threaded, s4 i)
+{
+  *((Cell *) *ptr2cur_threaded) = i;
+  (*ptr2cur_threaded)++;
+}
+
+void
+genarg_b(Inst ** ptr2cur_threaded, s4 i)
+{
+  genarg_i(ptr2cur_threaded, i);
+}
+
+void
+genarg_f(Inst ** ptr2cur_threaded, float f)
+{
+       s4 fi;
+
+       vm_f2Cell(f,fi);
+       genarg_i(ptr2cur_threaded, fi);
+}
+
+void
+genarg_l(Inst ** ptr2cur_threaded, s8 l)
+{
+  vm_l2twoCell(l, ((Cell*)*ptr2cur_threaded)[1], ((Cell*)*ptr2cur_threaded)[0]);
+  (*ptr2cur_threaded) +=2;
+}
+
+void
+genarg_aRef(Inst ** ptr2current_threaded, java_objectheader *a)
+{
+  *((java_objectheader **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_aArray(Inst ** ptr2current_threaded, java_arrayheader *a)
+{
+  *((java_arrayheader **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_aaTarget(Inst ** ptr2current_threaded, Inst **a)
+{
+  *((Inst ***) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_aClass(Inst ** ptr2current_threaded, classinfo *a)
+{
+  *((classinfo **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_acr(Inst ** ptr2current_threaded, constant_classref *a)
+{
+  *((constant_classref **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_addr(Inst ** ptr2current_threaded, u1 *a)
+{
+  *((u1 **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_af(Inst ** ptr2current_threaded, functionptr a)
+{
+  *((functionptr *) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_am(Inst ** ptr2current_threaded, methodinfo *a)
+{
+  *((methodinfo **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_acell(Inst ** ptr2current_threaded, Cell *a)
+{
+  *((Cell **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_ainst(Inst ** ptr2current_threaded, Inst *a)
+{
+  *((Inst **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_auf(Inst ** ptr2current_threaded, unresolved_field *a)
+{
+  *((unresolved_field **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_aum(Inst ** ptr2current_threaded, unresolved_method *a)
+{
+  *((unresolved_method **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+void
+genarg_avftbl(Inst ** ptr2current_threaded, vftbl_t *a)
+{
+  *((vftbl_t **) *ptr2current_threaded) = a;
+  (*ptr2current_threaded)++;
+}
+
+
+/* include the interpreter generation functions *******************************/
+
+#include "vm/jit/intrp/java-gen.i"
+
+
+typedef void (*genfunctionptr) (Inst **);
+
+typedef struct builtin_gen builtin_gen;
+
+struct builtin_gen {
+       functionptr builtin;
+       genfunctionptr gen;
+};
+
+struct builtin_gen builtin_gen_table[] = {
+    {BUILTIN_new,                     gen_NEW,             }, 
+    {BUILTIN_newarray,                gen_NEWARRAY,        },
+    {BUILTIN_newarray_boolean,        gen_NEWARRAY_BOOLEAN,},
+    {BUILTIN_newarray_byte,           gen_NEWARRAY_BYTE,   },
+    {BUILTIN_newarray_char,           gen_NEWARRAY_CHAR,   },
+    {BUILTIN_newarray_short,          gen_NEWARRAY_SHORT,  },    
+    {BUILTIN_newarray_int,            gen_NEWARRAY_INT,    },
+    {BUILTIN_newarray_long,           gen_NEWARRAY_LONG,   },
+    {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,     },
+#endif
+};
+
+/*
+  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 *********************************************************************
+
+   Generates machine code.
+
+*******************************************************************************/
+
+void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
+{
+       s4                  i, len, s1, s2, d;
+       Inst               *mcodeptr;
+       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;
+
+       /* prevent compiler warnings */
+
+       d = 0;
+       currentline = 0;
+       lm = NULL;
+       bte = NULL;
+
+       /* create method header */
+
+       (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
+
+#if defined(USE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               (void) dseg_adds4(cd, 1);                           /* IsSync         */
+       else
+#endif
+               (void) dseg_adds4(cd, 0);                           /* IsSync         */
+                                              
+       dseg_addlinenumbertablesize(cd);
+
+       (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
+
+       /* create exception table */
+
+       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);
+       }
+       
+       /* initialize mcode variables */
+       
+       mcodeptr = (s4 *) cd->mcodebase;
+       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+
+       if (runverbose)
+               gen_TRACECALL(&mcodeptr);
+
+       /* walk through all basic blocks */
+
+       for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+
+               bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
+
+               if (bptr->flags >= BBREACHED) {
+
+               /* walk through all instructions */
+               
+               src = bptr->instack;
+               len = bptr->icount;
+
+               for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
+                       if (iptr->line != currentline) {
+                               dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
+                               currentline = iptr->line;
+                       }
+
+               MCODECHECK(64);       /* an instruction usually needs < 64 words      */
+               switch (iptr->opc) {
+
+               case ICMD_INLINE_START:
+               case ICMD_INLINE_END:
+                       break;
+
+               case ICMD_NOP:        /* ...  ==> ...                                 */
+                       break;
+
+               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+
+                       gen_CHECKNULL(&mcodeptr);
+                       break;
+
+               /* constant operations ************************************************/
+
+               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.i = constant                    */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       break;
+
+               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.l = constant                    */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       break;
+
+               case ICMD_FCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.f = constant                    */
+                       {
+                               s4 fi;
+
+                               vm_f2Cell(iptr->val.f, fi);
+                               gen_ICONST(&mcodeptr, fi);
+                       }
+                       break;
+                       
+               case ICMD_DCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.d = constant                    */
+
+                       gen_LCONST(&mcodeptr, *(s8 *)&(iptr->val.d));
+                       break;
+
+               case ICMD_ACONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.a = constant                    */
+
+                       gen_ACONST(&mcodeptr, iptr->val.a);
+                       break;
+
+
+               /* load/store operations **********************************************/
+
+               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       gen_ILOAD(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       gen_LLOAD(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       gen_ALOAD(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       gen_ILOAD(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       gen_LLOAD(&mcodeptr, iptr->op1);
+                       break;
+
+
+               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       gen_ISTORE(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_LSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       gen_LSTORE(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_ASTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       gen_ASTORE(&mcodeptr, iptr->op1);
+                       break;
+
+
+               case ICMD_FSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       gen_ISTORE(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_DSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       gen_LSTORE(&mcodeptr, iptr->op1);
+                       break;
+
+
+               /* pop/dup/swap operations ********************************************/
+
+               /* attention: double and longs are only one entry in CACAO ICMDs      */
+
+               case ICMD_POP:        /* ..., value  ==> ...                          */
+
+                       gen_POP(&mcodeptr);
+                       break;
+
+               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
+
+                       gen_POP2(&mcodeptr);
+                       break;
+
+               case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
+
+                       gen_DUP(&mcodeptr);
+                       break;
+
+               case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
+
+                       gen_DUP_X1(&mcodeptr);
+                       break;
+
+               case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
+
+                       gen_DUP_X1(&mcodeptr);
+                       break;
+
+               case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
+
+                       gen_DUP2(&mcodeptr);
+                       break;
+
+               case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
+
+                       gen_DUP2_X1(&mcodeptr);
+                       break;
+
+               case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
+
+                       gen_DUP2_X2(&mcodeptr);
+                       break;
+
+               case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
+
+                       gen_SWAP(&mcodeptr);
+                       break;
+
+
+               /* integer operations *************************************************/
+
+               case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
+
+                       gen_INEG(&mcodeptr);
+                       break;
+
+               case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
+
+                       gen_LNEG(&mcodeptr);
+                       break;
+
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+
+                       gen_I2L(&mcodeptr);
+                       break;
+
+               case ICMD_L2I:        /* ..., value  ==> ..., value                   */
+
+                       gen_L2I(&mcodeptr);
+                       break;
+
+               case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
+
+                       gen_INT2BYTE(&mcodeptr);
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+
+                       gen_INT2CHAR(&mcodeptr);
+                       break;
+
+               case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
+
+                       gen_INT2SHORT(&mcodeptr);
+                       break;
+
+
+               case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       gen_IADD(&mcodeptr);
+                       break;
+
+               case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IADD(&mcodeptr);
+                       break;
+
+               case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       gen_LADD(&mcodeptr);
+                       break;
+
+               case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LADD(&mcodeptr);
+                       break;
+
+               case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       gen_ISUB(&mcodeptr);
+                       break;
+
+               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_ISUB(&mcodeptr);
+                       break;
+
+               case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       gen_LSUB(&mcodeptr);
+                       break;
+
+               case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LSUB(&mcodeptr);
+                       break;
+
+               case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       gen_IMUL(&mcodeptr);
+                       break;
+
+               case ICMD_IMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IMUL(&mcodeptr);
+                       break;
+
+               case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       gen_LMUL(&mcodeptr);
+                       break;
+
+               case ICMD_LMULCONST:  /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LMUL(&mcodeptr);
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       gen_IDIV(&mcodeptr);
+                       break;
+
+               case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       gen_IREM(&mcodeptr);
+                       break;
+
+               case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       gen_LDIV(&mcodeptr);
+                       break;
+
+               case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       gen_LREM(&mcodeptr);
+                       break;
+
+               case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
+                                     
+                       gen_IDIVPOW2(&mcodeptr, iptr->val.i);
+                       break;
+
+               case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* val.i = constant                             */
+
+                       gen_IREMPOW2(&mcodeptr, iptr->val.i);
+                       break;
+
+               case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
+                                     
+                       gen_LDIVPOW2(&mcodeptr, iptr->val.i);
+                       break;
+
+               case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LREMPOW2(&mcodeptr, iptr->val.i);
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+
+                       gen_ISHL(&mcodeptr);
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_ISHL(&mcodeptr);
+                       break;
+
+               case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+
+                       gen_ISHR(&mcodeptr);
+                       break;
+
+               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_ISHR(&mcodeptr);
+                       break;
+
+               case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+
+                       gen_IUSHR(&mcodeptr);
+                       break;
+
+               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IUSHR(&mcodeptr);
+                       break;
+
+               case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+
+                       gen_LSHL(&mcodeptr);
+                       break;
+
+               case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_LSHL(&mcodeptr);
+                       break;
+
+               case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+
+                       gen_LSHR(&mcodeptr);
+                       break;
+
+               case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_LSHR(&mcodeptr);
+                       break;
+
+               case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+
+                       gen_LUSHR(&mcodeptr);
+                       break;
+
+               case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_LUSHR(&mcodeptr);
+                       break;
+
+               case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       gen_IAND(&mcodeptr);
+                       break;
+
+               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IAND(&mcodeptr);
+                       break;
+
+               case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       gen_LAND(&mcodeptr);
+                       break;
+
+               case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LAND(&mcodeptr);
+                       break;
+
+               case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
+
+                       gen_IOR(&mcodeptr);
+                       break;
+
+               case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IOR(&mcodeptr);
+                       break;
+
+               case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
+
+                       gen_LOR(&mcodeptr);
+                       break;
+
+               case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LOR(&mcodeptr);
+                       break;
+
+               case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
+
+                       gen_IXOR(&mcodeptr);
+                       break;
+
+               case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* val.i = constant                             */
+
+                       gen_ICONST(&mcodeptr, iptr->val.i);
+                       gen_IXOR(&mcodeptr);
+                       break;
+
+               case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
+
+                       gen_LXOR(&mcodeptr);
+                       break;
+
+               case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* val.l = constant                             */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_LXOR(&mcodeptr);
+                       break;
+
+
+               case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
+
+                       gen_LCMP(&mcodeptr);
+                       break;
+
+
+               case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
+                                     /* op1 = variable, val.i = constant             */
+
+                       gen_IINC(&mcodeptr, iptr->op1, iptr->val.i);
+                       break;
+
+
+               /* floating operations ************************************************/
+
+               case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
+
+                       gen_FNEG(&mcodeptr);
+                       break;
+
+               case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
+
+                       gen_DNEG(&mcodeptr);
+                       break;
+
+               case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       gen_FADD(&mcodeptr);
+                       break;
+
+               case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       gen_DADD(&mcodeptr);
+                       break;
+
+               case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       gen_FSUB(&mcodeptr);
+                       break;
+
+               case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       gen_DSUB(&mcodeptr);
+                       break;
+
+               case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       gen_FMUL(&mcodeptr);
+                       break;
+
+               case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */
+
+                       gen_DMUL(&mcodeptr);
+                       break;
+
+               case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       gen_FDIV(&mcodeptr);
+                       break;
+
+               case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       gen_DDIV(&mcodeptr);
+                       break;
+               
+               case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
+
+                       gen_I2F(&mcodeptr);
+                       break;
+
+               case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
+
+                       gen_L2F(&mcodeptr);
+                       break;
+
+               case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
+
+                       gen_I2D(&mcodeptr);
+                       break;
+                       
+               case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
+
+                       gen_L2D(&mcodeptr);
+                       break;
+                       
+               case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
+
+                       gen_F2I(&mcodeptr);
+                       break;
+               
+               case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
+
+                       gen_D2I(&mcodeptr);
+                       break;
+               
+               case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
+
+                       gen_F2L(&mcodeptr);
+                       break;
+
+               case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
+
+                       gen_D2L(&mcodeptr);
+                       break;
+
+               case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
+
+                       gen_F2D(&mcodeptr);
+                       break;
+                                       
+               case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
+
+                       gen_D2F(&mcodeptr);
+                       break;
+               
+               case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
+
+                       gen_FCMPL(&mcodeptr);
+                       break;
+                       
+               case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
+
+                       gen_DCMPL(&mcodeptr);
+                       break;
+                       
+               case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
+
+                       gen_FCMPG(&mcodeptr);
+                       break;
+
+               case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
+
+                       gen_DCMPG(&mcodeptr);
+                       break;
+
+
+               /* memory operations **************************************************/
+
+               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
+
+                       gen_ARRAYLENGTH(&mcodeptr);
+                       break;
+
+               case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_BALOAD(&mcodeptr);
+                       break;
+
+               case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_CALOAD(&mcodeptr);
+                       break;                  
+
+               case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_SALOAD(&mcodeptr);
+                       break;
+
+               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+               case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_IALOAD(&mcodeptr);
+                       break;
+
+               case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
+               case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_LALOAD(&mcodeptr);
+                       break;
+
+               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       gen_AALOAD(&mcodeptr);
+                       break;
+
+
+               case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_BASTORE(&mcodeptr);
+                       break;
+
+               case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
+               case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_CASTORE(&mcodeptr);
+                       break;
+
+               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+               case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_IASTORE(&mcodeptr);
+                       break;
+
+               case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
+               case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_LASTORE(&mcodeptr);
+                       break;
+
+               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       gen_AASTORE(&mcodeptr);
+                       break;
+
+
+               case ICMD_GETSTATIC:  /* ...  ==> ..., 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_GETSTATIC_INT(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_GETSTATIC_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_GETSTATIC_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
+                               }
+                               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(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_PUTSTATIC_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_PUTSTATIC_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
+                               }
+                               break;
+                       }
+                       }
+                       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) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_PUTSTATIC_INT(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               gen_LCONST(&mcodeptr, iptr->val.l);
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_PUTSTATIC_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               gen_ACONST(&mcodeptr, iptr->val.a);
+                               if (fi == NULL || !fi->class->initialized) {
+                                       gen_PATCHER_PUTSTATIC_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
+                               }
+                               break;
+                       }
+                       }
+                       break;
+
+
+               case ICMD_GETFIELD:   /* ...  ==> ..., 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_GETFIELD_INT(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETFIELD_INT(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               if (fi == NULL) {
+                                       gen_PATCHER_GETFIELD_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETFIELD_LONG(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               if (fi == NULL) {
+                                       gen_PATCHER_GETFIELD_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_GETFIELD_CELL(&mcodeptr, fi->offset, uf);
+                               }
+                               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(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_INT(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               if (fi == NULL) {
+                                       gen_PATCHER_PUTFIELD_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_LONG(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               if (fi == NULL) {
+                                       gen_PATCHER_PUTFIELD_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_CELL(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       }
+                       }
+                       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) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               if (fi == NULL) {
+                                       gen_PATCHER_PUTFIELD_INT(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_INT(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_DBL:
+                               gen_LCONST(&mcodeptr, iptr->val.l);
+                               if (fi == NULL) {
+                                       gen_PATCHER_PUTFIELD_LONG(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_LONG(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               gen_ACONST(&mcodeptr, iptr->val.a);
+                               if (fi == NULL) {
+                                       gen_PATCHER_PUTFIELD_CELL(&mcodeptr, 0, uf);
+                               } else {
+                                       gen_PUTFIELD_CELL(&mcodeptr, fi->offset, uf);
+                               }
+                               break;
+                       }
+                       }
+                       break;
+
+
+               /* branch operations **************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+
+                       gen_ATHROW(&mcodeptr);
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+                       gen_branch(GOTO);
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+                       gen_branch(JSR);
+                       break;
+                       
+               case ICMD_RET:          /* ... ==> ...                                */
+                                       /* op1 = local variable                       */
+
+                       gen_RET(&mcodeptr, iptr->op1);
+                       break;
+
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IFNULL);
+                       break;
+
+               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IFNONNULL);
+                       break;
+
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFEQ);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPEQ);
+                       }
+                       break;
+
+               case ICMD_IFLT:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFLT);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPLT);
+                       }
+                       break;
+
+               case ICMD_IFLE:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFLE);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPLE);
+                       }
+                       break;
+
+               case ICMD_IFNE:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFNE);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPNE);
+                       }
+                       break;
+
+               case ICMD_IFGT:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFGT);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPGT);
+                       }
+                       break;
+
+               case ICMD_IFGE:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       if (iptr->val.i == 0) {
+                               gen_branch(IFGE);
+                       } else {
+                               gen_ICONST(&mcodeptr, iptr->val.i);
+                               gen_branch(IF_ICMPGE);
+                       }
+                       break;
+
+               case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPEQ);
+                       break;
+
+               case ICMD_IF_LLT:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPLT);
+                       break;
+
+               case ICMD_IF_LLE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPLE);
+                       break;
+
+               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPNE);
+                       break;
+
+               case ICMD_IF_LGT:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPGT);
+                       break;
+
+               case ICMD_IF_LGE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       gen_LCONST(&mcodeptr, iptr->val.l);
+                       gen_branch(IF_LCMPGE);
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPEQ);
+                       break;
+
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPEQ);
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ACMPEQ);
+                       break;
+
+               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPNE);
+                       break;
+
+               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPNE);
+                       break;
+
+               case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ACMPNE);
+                       break;
+
+               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPLT);
+                       break;
+
+               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPLT);
+                       break;
+
+               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPGT);
+                       break;
+
+               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPGT);
+                       break;
+
+               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPLE);
+                       break;
+
+               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPLE);
+                       break;
+
+               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_ICMPGE);
+                       break;
+
+               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       gen_branch(IF_LCMPGE);
+                       break;
+
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
+
+#if defined(USE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               if (m->flags & ACC_STATIC) {
+                                       gen_ACONST(&mcodeptr, m->class);
+                               } else {
+                                       gen_ALOAD(&mcodeptr, 0);
+                               }
+                               gen_MONITOREXIT(&mcodeptr);
+                       }
+#endif
+                       if (runverbose)
+                               gen_TRACERETURN(&mcodeptr);
+
+                       gen_IRETURN(&mcodeptr, cd->maxlocals);
+                       break;
+
+               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */
+
+#if defined(USE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               if (m->flags & ACC_STATIC) {
+                                       gen_ACONST(&mcodeptr, m->class);
+                               } else {
+                                       gen_ALOAD(&mcodeptr, 0);
+                               }
+                               gen_MONITOREXIT(&mcodeptr);
+                       }
+#endif
+                       if (runverbose)
+                               gen_TRACELRETURN(&mcodeptr);
+
+                       gen_LRETURN(&mcodeptr, cd->maxlocals);
+                       break;
+
+               case ICMD_RETURN:       /* ...  ==> ...                               */
+
+#if defined(USE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               if (m->flags & ACC_STATIC) {
+                                       gen_ACONST(&mcodeptr, m->class);
+                               } else {
+                                       gen_ALOAD(&mcodeptr, 0);
+                               }
+                               gen_MONITOREXIT(&mcodeptr);
+                       }
+#endif
+                       if (runverbose)
+                               gen_TRACERETURN(&mcodeptr);
+
+                       gen_RETURN(&mcodeptr, cd->maxlocals);
+                       break;
+
+
+               case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
+                       {
+                       s4 i, l, *s4ptr;
+                       void **tptr;
+
+                       tptr = (void **) iptr->target;
+
+                       s4ptr = iptr->val.a;
+                       l = s4ptr[1];                          /* low     */
+                       i = s4ptr[2];                          /* high    */
+                       
+                       i = i - l + 1;
+
+                       /* arguments: low, range, datasegment address, table offset in     */
+                       /* datasegment, default target                                    */
+                       gen_TABLESWITCH(&mcodeptr, l, i, NULL, 0, NULL);
+                       dseg_adddata(cd, (u1 *) (mcodeptr - 2)); /* actually mcodeptr[-3] */
+                       codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
+
+                       /* build jump table top down and use address of lowest entry */
+
+                       tptr += i;
+
+                       while (--i >= 0) {
+                               dseg_addtarget(cd, (basicblock *) tptr[0]); 
+                               --tptr;
+                       }
+                       }
+
+                       /* length of dataseg after last dseg_addtarget is used by load */
+                       mcodeptr[-2] = (Inst) (ptrint) -(cd->dseglen);
+                       break;
+
+
+               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
+                       {
+                       s4 i, *s4ptr;
+                       void **tptr;
+
+                       tptr = (void **) iptr->target;
+
+                       s4ptr = iptr->val.a;
+
+                       /* s4ptr[0] is equal to tptr[0] */
+                       i = s4ptr[1];                          /* count    */
+                       
+                       /* arguments: count, datasegment address, table offset in         */
+                       /* datasegment, default target                                    */
+                       gen_LOOKUPSWITCH(&mcodeptr, i, NULL, 0, NULL);
+                       dseg_adddata(cd, (u1 *) (mcodeptr - 2)); /* actually mcodeptr[-3] */
+                       codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
+
+                       /* build jump table top down and use address of lowest entry */
+
+                       tptr += i;
+                       s4ptr += i * 2;
+
+                       while (--i >= 0) {
+                               dseg_addtarget(cd, (basicblock *) tptr[0]); 
+                               dseg_addaddress(cd, s4ptr[0]);
+                               --tptr;
+                               s4ptr -= 2;
+                       }
+                       }
+
+                       /* length of dataseg after last dseg_addtarget is used by load */
+                       mcodeptr[-2] = (Inst) (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(&mcodeptr, 0);
+                       } else if (bte->fp == PATCHER_builtin_newarray) {
+                               gen_PATCHER_NEWARRAY(&mcodeptr, 0);
+                       } else if (bte->fp == PATCHER_builtin_arrayinstanceof) {
+                               gen_PATCHER_ARRAYINSTANCEOF(&mcodeptr, 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)(&mcodeptr);
+                                               break;
+                                       }
+                               }
+                       }
+                       break;
+
+               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
+                                       /* op1 = arg count, val.a = method pointer    */
+
+                       lm = iptr->val.a;
+                       um = iptr->target;
+
+                       if (lm == NULL) {
+                               md = um->methodref->parseddesc.md;
+                               gen_PATCHER_INVOKESTATIC(&mcodeptr, 0, md->paramslots, um);
+
+                       } else {
+                               md = lm->parseddesc;
+                               gen_INVOKESTATIC(&mcodeptr, (Inst **)lm->stubroutine, md->paramslots, um);
+                       }
+                       break;
+
+               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
+
+                       lm = iptr->val.a;
+                       um = iptr->target;
+
+                       if (lm == NULL) {
+                               md = um->methodref->parseddesc.md;
+                               gen_PATCHER_INVOKESPECIAL(&mcodeptr, 0, md->paramslots, um);
+
+                       } else {
+                               md = lm->parseddesc;
+                               gen_INVOKESPECIAL(&mcodeptr, (Inst **)lm->stubroutine, md->paramslots, um);
+                       }
+                       break;
+
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+
+                       lm = iptr->val.a;
+                       um = iptr->target;
+
+                       if (lm == NULL) {
+                               md = um->methodref->parseddesc.md;
+                               gen_PATCHER_INVOKEVIRTUAL(&mcodeptr, 0, md->paramslots, um);
+
+                       } else {
+                               md = lm->parseddesc;
+
+                               s1 = OFFSET(vftbl_t, table[0]) +
+                                       sizeof(methodptr) * lm->vftblindex;
+
+                               gen_INVOKEVIRTUAL(&mcodeptr, s1, md->paramslots, um);
+                       }
+                       break;
+
+               case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */
+
+                       lm = iptr->val.a;
+                       um = iptr->target;
+
+                       if (lm == NULL) {
+                               md = um->methodref->parseddesc.md;
+                               gen_PATCHER_INVOKEINTERFACE(&mcodeptr, 0, 0, md->paramslots, um);
+
+                       } else {
+                               md = lm->parseddesc;
+
+                               s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                       sizeof(methodptr*) * lm->class->index;
+
+                               s2 = sizeof(methodptr) * (lm - lm->class->methods);
+
+                               gen_INVOKEINTERFACE(&mcodeptr, s1, s2, md->paramslots, um);
+                       }
+                       break;
+
+
+               case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
+                                     /* op1:   0 == array, 1 == class                */
+                                     /* val.a: (classinfo *) superclass              */
+
+                       if (iptr->val.a == NULL) {
+                               gen_PATCHER_CHECKCAST(&mcodeptr, 0, iptr->target);
+
+                       } else {
+                               gen_CHECKCAST(&mcodeptr, iptr->val.a, iptr->target);
+                       }
+                       
+                       break;
+
+               case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref        */
+                                         /* op1: 1... resolved, 0... not resolved    */
+
+                       if (iptr->op1 == 0) {
+                               gen_PATCHER_ARRAYCHECKCAST(&mcodeptr, 0, iptr->target);
+                       } else {
+                               gen_ARRAYCHECKCAST(&mcodeptr, iptr->target, 0);
+                       }
+                       break;
+
+               case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* op1:   0 == array, 1 == class                */
+                                     /* val.a: (classinfo *) superclass              */
+
+                       if (iptr->val.a == NULL) {
+                               gen_PATCHER_INSTANCEOF(&mcodeptr, 0, iptr->target);
+                       } else {
+                               gen_INSTANCEOF(&mcodeptr, iptr->val.a, iptr->target);
+                       }
+                       
+                       break;
+
+
+               case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
+
+                       /* XXX remove me! */
+                       break;
+
+               case ICMD_CHECKEXCEPTION:    /* ..., objectref ==> ..., objectref     */
+
+                       gen_CHECKEXCEPTION(&mcodeptr);
+                       break;
+
+               case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
+                                     /* op1 = dimension, val.a = array descriptor    */
+
+                       if (iptr->target) {
+                               gen_PATCHER_MULTIANEWARRAY(&mcodeptr, 0, iptr->op1, iptr->val.a);
+                       } else {
+                               gen_MULTIANEWARRAY(&mcodeptr, iptr->val.a, iptr->op1, 0);
+                       }
+                       break;
+
+               default:
+                       throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                          "Unknown ICMD %d", iptr->opc);
+       } /* switch */
+               
+       } /* for instruction */
+               
+       } /* if (bptr -> flags >= BBREACHED) */
+       } /* for basic block */
+
+       codegen_createlinenumbertable(cd);
+
+       codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
+
+
+       /* branch resolving (walk through all basic blocks) */
+
+       for (bptr = m->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);
+               }
+       }
+}
+
+
+/* a stub consists of
+
++---------+
+|codeptr  |
++---------+
+|maxlocals|
++---------+
+|TRANSLATE|
++---------+
+|methodinf|
++---------+
+
+codeptr points either to TRANSLATE or to the translated threaded code
+
+all methods are called indirectly through methodptr
+*/
+
+#define STUBSIZE 4
+
+functionptr createcompilerstub (methodinfo *m)
+{
+       Inst * t = CNEW(Inst, STUBSIZE);
+       Inst * codeptr=t;
+       genarg_ainst(&t, t+2);
+
+       if (m->flags & ACC_NATIVE) {
+               genarg_i(&t, m->parseddesc->paramslots);
+       } else {
+               genarg_i(&t, m->maxlocals);
+       }
+
+       gen_TRANSLATE(&t, m);
+       return (functionptr)codeptr;
+}
+
+
+/* native stub:
++---------+
+|NATIVECALL|
++---------+
+|methodinf|
++---------+
+|function |
++---------+
+
+where maxlocals==paramslots
+*/
+
+#define NATIVE_STUBSIZE 5
+
+functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
+                                                        registerdata *rd, methoddesc *md)
+{
+       Inst *mcodeptr;
+
+       mcodeptr = (s4 *) cd->mcodebase;
+       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+
+       /* create method header */
+
+       (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
+       (void) dseg_adds4(cd, 0);                               /* IsSync         */
+       dseg_addlinenumbertablesize(cd);
+       (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
+
+       if (runverbose)
+               gen_TRACECALL(&mcodeptr);
+
+       if (f == NULL) {
+               gen_PATCHER_NATIVECALL(&mcodeptr, m, f);
+       } else {
+               if (runverbose)
+                       gen_TRACENATIVECALL(&mcodeptr, m, f);
+               else
+                       gen_NATIVECALL(&mcodeptr, m, f);
+       }
+
+       codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
+
+       return m->entrypoint;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/intrp/intrp.h b/src/vm/jit/intrp/intrp.h
new file mode 100644 (file)
index 0000000..039afb3
--- /dev/null
@@ -0,0 +1,209 @@
+/* src/vm/jit/intrp/intrp.h - definitions 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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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: Christian Thalinger
+            Anton Ertl
+
+   Changes:
+
+   $Id: intrp.h 3140 2005-09-02 15:17:20Z twisti $
+
+*/
+
+
+#ifndef _INTRP_H
+#define _INTRP_H
+
+#include <stdio.h>
+
+#include "vm/jit/intrp/arch.h"
+#include "vm/jit/intrp/types.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
+
+typedef void *Inst;
+typedef ptrint Cell;
+
+#if 1
+#define MAYBE_UNUSED __attribute__((unused))
+#else
+#define MAYBE_UNUSED
+#endif
+
+#if SIZEOF_VOID_P==4
+typedef union {
+    struct {
+               UCell low;
+               Cell high;
+    } cells;
+    s8 l;
+    double d;
+} Double_Store;
+
+#define FETCH_DCELL_T(d_,lo,hi,t_)     ({ \
+                                    Double_Store _d; \
+                                    _d.cells.low = (lo); \
+                                    _d.cells.high = (hi); \
+                                    (d_) = _d.t_; \
+                                })
+
+#define STORE_DCELL_T(d_,lo,hi,t_)     ({ \
+                                    Double_Store _d; \
+                                    _d.t_ = (d_); \
+                                    (lo) = _d.cells.low; \
+                                    (hi) = _d.cells.high; \
+                                })
+
+#else /* 64-bit */
+typedef union {
+  Cell low;
+  s8 l;
+  double d;
+} Double_Store;
+
+
+#define FETCH_DCELL_T(d_,lo,hi,t_)     ({ (d_) = ((Double_Store)(lo)).t_; })
+#define STORE_DCELL_T(d_,lo,hi,t_)     ({ (lo) = ((Double_Store)(d_)).low; })
+#endif /* 64-bit */
+
+#define vm_twoCell2l(hi,lo,d_)  FETCH_DCELL_T(d_,lo,hi,l);
+#define vm_twoCell2d(hi,lo,d_)  FETCH_DCELL_T(d_,lo,hi,d);
+                                                                                                
+#define vm_l2twoCell(d_,hi,lo)  STORE_DCELL_T(d_,lo,hi,l);
+#define vm_d2twoCell(d_,hi,lo)  STORE_DCELL_T(d_,lo,hi,d);
+
+#define vm_Cell2v(cell, v) ((v)=(Cell)(cell))
+#define vm_Cell2b(cell, b) ((b)=(u1)(Cell)(cell))
+#define vm_Cell2i(cell, i) ((i)=(s4)(Cell)(cell))
+
+#define vm_Cell2aRef(x1,x2)       ((x2) = (java_objectheader *)(x1))
+#define vm_Cell2aArray(x1,x2)     ((x2) = (java_arrayheader * )(x1))
+#define vm_Cell2aaTarget(x1,x2)   ((x2) = (Inst **            )(x1))
+#define vm_Cell2aClass(x1,x2)     ((x2) = (classinfo *        )(x1))
+#define vm_Cell2acr(x1,x2)        ((x2) = (constant_classref *)(x1))
+#define vm_Cell2addr(x1,x2)       ((x2) = (u1 *               )(x1))
+#define vm_Cell2af(x1,x2)         ((x2) = (functionptr        )(x1))
+#define vm_Cell2am(x1,x2)         ((x2) = (methodinfo *       )(x1))
+#define vm_Cell2acell(x1,x2)      ((x2) = (Cell *             )(x1))
+#define vm_Cell2ainst(x1,x2)      ((x2) = (Inst *             )(x1))
+#define vm_Cell2auf(x1,x2)        ((x2) = (unresolved_field * )(x1))
+#define vm_Cell2aum(x1,x2)        ((x2) = (unresolved_method *)(x1))
+#define vm_Cell2avftbl(x1,x2)     ((x2) = (vftbl_t *          )(x1))
+
+#define vm_ui2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_v2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_b2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_s2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_i2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_aRef2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_aArray2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_aaTarget2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_aClass2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_acr2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_addr2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_af2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_am2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_acell2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_ainst2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_auf2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_aum2Cell(x1,x2) ((x2) = (Cell)(x1))
+#define vm_avftbl2Cell(x1,x2) ((x2) = (Cell)(x1))
+
+#define vm_Cell2Cell(x1,x2) ((x2)=(Cell)(x1))
+
+#define IMM_ARG(access,value)          (access)
+
+/* for disassembler and tracer */
+#define VM_IS_INST(inst, n) ((inst) == vm_prim[n])
+
+
+union Cell_float {
+    Cell cell;
+    float f;
+};
+
+#define vm_f2Cell(x1,x2)       ((x2) =(((union Cell_float)(x1)).cell))
+#define vm_Cell2f(x1,x2)       ((x2) =(((union Cell_float)(x1)).f))
+
+extern Inst *vm_prim;
+extern Cell peeptable;
+extern FILE *vm_out;
+
+void init_peeptable(void);
+Inst peephole_opt(Inst inst1, Inst inst2, Cell peeptable);
+void vm_disassemble(Inst *ip, Inst *endp, Inst vm_prim[]);
+
+java_objectheader *engine(Inst *ip0, Cell * sp, Cell * fp);
+
+/* print types for disassembler and tracer */
+void printarg_ui      (u4                 ui      );
+void printarg_v       (Cell               v       );
+void printarg_b       (s4                 b       );
+void printarg_s       (s4                 s       );
+void printarg_i       (s4                 i       );
+void printarg_l       (s8                 l       );
+void printarg_f       (float              f       );
+void printarg_d       (double             d       );
+void printarg_aRef    (java_objectheader *aRef    );
+void printarg_aArray  (java_arrayheader * aArray  );
+void printarg_aaTarget(Inst **            aaTarget);
+void printarg_aClass  (classinfo *        aClass  );
+void printarg_acr     (constant_classref *acr     );
+void printarg_addr    (u1 *               addr    );
+void printarg_af      (functionptr        af      );
+void printarg_am      (methodinfo *       am      );
+void printarg_acell   (Cell *             acell   );
+void printarg_ainst   (Inst *             ainst   );
+void printarg_auf     (unresolved_field * auf     );
+void printarg_aum     (unresolved_method *aum     );
+void printarg_avftbl  (vftbl_t *          avftbl  );
+void printarg_Cell    (Cell               x       );
+
+/* gen_... functions used in engine.c */
+void gen_INVOKESTATIC(Inst **ctp, Inst ** aaTarget, s4 iNargs, unresolved_method * aum);
+void gen_END(Inst **ctp);
+
+void vm_uncount_block(Inst *ip);
+
+#endif /* _INTRP_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/intrp/java.vmg b/src/vm/jit/intrp/java.vmg
new file mode 100644 (file)
index 0000000..06e18b3
--- /dev/null
@@ -0,0 +1,1439 @@
+\
+\ JVM instruction specs
+\
+\ This file contains primitive specifications in the following format:
+\ 
+\ name ( stack effect ) [ number ]
+\ [""glossary entry""]
+\ C code
+\ [:
+\ Forth code]
+\ 
+\ Note: Fields in brackets are optional.  Word specifications have to
+\ be separated by at least one empty line
+\
+\ Both name and stack items (in the stack effect) must
+\ conform to the C identifier syntax or the C compiler will complain.
+\ The branch field can be one of "branch", "cond", "indirect", or empty.
+\ 
+\ These specifications are automatically translated into C-code for the
+\ interpreter and into some other files. I hope that your C compiler has
+\ decent optimization, otherwise the automatically generated code will
+\ be somewhat slow. The Forth version of the code is included for manual
+\ compilers, so they will need to compile only the important words.
+\ 
+\ Note that stack pointer adjustment is performed according to stack
+\ effect by automatically generated code and NEXT is automatically
+\ appended to the C code. Also, you can use the names in the stack
+\ effect in the C code. Stack access is automatic. One exception: if
+\ your code does not fall through, the results are not stored into the
+\ stack. Use different names on both sides of the '--', if you change a
+\ value (some stores to the stack are optimized away).
+\ 
+
+\E stack data-stack sp Cell
+\E
+\E s" u4"                  single data-stack type-prefix ui
+\E s" Cell"                single data-stack type-prefix v
+\E s" s4"                  single data-stack type-prefix b \ byte
+\E s" s4"                  single data-stack type-prefix s \ short
+\E s" s4"                  single data-stack type-prefix i
+\E s" s8"                  double data-stack type-prefix l
+\E s" float"               single data-stack type-prefix f
+\E s" double"              double data-stack type-prefix d
+
+\ we use a lot of types for the former "a" (address) type; this gives
+\ better typechecking in the C code, and allows better output from the
+\ disassembler and the tracer.
+
+\E s" java_objectheader *" single data-stack type-prefix aRef
+\E s" java_arrayheader *"  single data-stack type-prefix aArray
+\E s" Inst **"             single data-stack type-prefix aaTarget
+\E s" classinfo *"         single data-stack type-prefix aClass
+\E s" constant_classref *" single data-stack type-prefix acr
+\E s" u1 *"                single data-stack type-prefix addr
+\E s" functionptr"         single data-stack type-prefix af
+\E s" methodinfo *"        single data-stack type-prefix am
+\E s" Cell *"              single data-stack type-prefix acell
+\E s" Inst *"              single data-stack type-prefix ainst
+\E s" unresolved_field *"  single data-stack type-prefix auf
+\E s" unresolved_method *" single data-stack type-prefix aum
+\E s" vftbl_t *"           single data-stack type-prefix avftbl
+\E inst-stream  stack-prefix #
+
+\ The stack variables have the following types:
+\ 
+\ name matches  type
+\ i.*           jint
+\ l.*           jlong
+\ s.*           Jshort
+\ b.*           Jbyte
+\ c.*           Jchar
+\ f.*           jfloat
+\ d.*           jdouble
+\ a.*           jref
+\ r.*           Jretaddr
+\
+\ 
+\ Starting a name with # indicates an inline argument instead of a stack
+\ argument; the rest of the name matches as usual.
+\ 
+\
+\ Questions:
+\      How does prims2x know the length of each instruction,
+\      where the instruction has immediate operands. We need
+\      some way to communicate this or compute it.
+\
+\      Some instructions don't care about the type of the
+\      values that they work with. For example, POP doesn't
+\      care what type the value on the top of the stack is.
+\      We need to communicate this.
+\      I'll add a type v (for void, or variable, whichever you
+\      prefer) which just means there's one element of the normal
+\      size on the stack, and we don't care what its type is.
+\
+\
+\ /*
+\ Define the following macros before including this file.
+\
+\ # define instr(name,opcode,label,len,syntax,body) 
+\ # define undef(name,opcode,label,len,syntax,body) 
+\ # define custm(name,opcode,label,len,syntax,body) 
+\
+\
+\ To avoid race conditions, rewriting proceeds as follows: 
+\  1) the needed operands are fetched from the orignal byte code 
+\  2) the new operands are written
+\  3) the new operator is written
+\  4) the quick-version of the instruction is executed.
+\
+\ Note: the byte code remains unchanged.
+\ 
+\ */
+
+\ This is stub code for methods that we have not yet translated.
+\ Initially, the code for each method is set to this stub. The
+\ first time the method is called, the code in the stub runs, which
+\ translates the bytecode, and replaces the stub with the threaded code.
+
+\ instr(NOP, 0, nop, 1, op, {})
+
+ICONST ( #vConst -- vConst ) opt
+
+LCONST ( #l -- l ) opt
+
+ACONST ( #aRef -- aRef ) opt
+
+ILOAD ( #bLocal -- vResult ) 0x15
+{
+  vResult = access_local_int(bLocal);
+}
+
+LLOAD ( #bLocal -- lResult ) 0x16
+{
+  vm_twoCell2l(access_local_cell(bLocal), access_local_cell(bLocal+1), lResult);
+}
+
+ALOAD ( #bLocal -- aRef ) 0x19
+{
+  aRef = (java_objectheader *)access_local_cell(bLocal);
+}
+
+IALOAD ( aArray iIndex -- iResult ) 0x2e
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  iResult = access_array_int(aArray, iIndex);
+}
+
+LALOAD ( aArray iIndex -- lResult ) 0x2f
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  lResult = access_array_long(aArray, iIndex);
+}
+
+AALOAD ( aArray iIndex -- aRef ) 0x32
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  aRef = access_array_addr(aArray, iIndex);
+}
+
+BALOAD ( aArray iIndex -- iResult ) 0x33
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  iResult = access_array_byte(aArray, iIndex);
+}
+
+CALOAD ( aArray iIndex -- iResult ) 0x34
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  iResult = access_array_char(aArray, iIndex);
+}
+
+SALOAD ( aArray iIndex -- iResult ) 0x35
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  iResult = access_array_short(aArray, iIndex);
+}
+
+ISTORE ( #bLocal vValue -- ) 0x36
+{
+  access_local_int(bLocal) = vValue;
+}
+
+LSTORE ( #bLocal lValue -- ) 0x37
+{
+  vm_l2twoCell(lValue, access_local_cell(bLocal), access_local_cell(bLocal+1));
+}
+
+ASTORE ( #bLocal aRef -- ) 0x3a
+{
+  access_local_cell(bLocal) = (Cell)aRef;
+}
+
+IASTORE ( aArray iIndex iValue -- ) 0x4f
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  access_array_int(aArray, iIndex) = iValue;
+}
+
+LASTORE ( aArray iIndex lValue -- ) 0x50
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  access_array_long(aArray, iIndex) = lValue;
+}
+
+AASTORE ( aArray iIndex aRef -- ) 0x53
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  if (!builtin_canstore((java_objectarray *)aArray, aRef))
+       THROW(arraystoreexception);
+  access_array_addr(aArray, iIndex) = aRef;
+}
+
+BASTORE ( aArray iIndex iValue -- ) 0x54
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  access_array_byte(aArray, iIndex) = iValue;
+}
+
+CASTORE ( aArray iIndex iValue -- ) 0x55
+{
+  CHECK_NULL_PTR(aArray);
+  CHECK_OUT_OF_BOUNDS(aArray, iIndex);
+  ;
+  access_array_char(aArray, iIndex) = iValue;
+}
+
+POP ( vValue -- ) 0x57
+
+POP2 ( vValue vValue -- ) 0x58
+
+DUP ( vValue -- vValue vValue ) 0x59
+
+DUP_X1 ( vValue2 vValue1 -- vValue1 vValue2 vValue1 ) 0x5a
+
+DUP_X2 ( vValue3 vValue2 vValue1 -- vValue1 vValue3 vValue2 vValue1 ) 0x5b
+
+DUP2 ( vValue2 vValue1 -- vValue2 vValue1 vValue2 vValue1 ) 0x5c
+
+DUP2_X1 (vValue3 vValue2 vValue1 -- vValue2 vValue1 vValue3 vValue2 vValue1 ) 0x5d
+
+DUP2_X2 ( vValue4 vValue3 vValue2 vValue1 -- vValue2 vValue1 vValue4 vValue3 vValue2 vValue1 ) 0x5e
+
+SWAP ( vValue2 vValue1 -- vValue1 vValue2 ) 0x5f
+
+IADD ( iValue1 iValue2 -- iResult ) 0x60
+{
+  iResult = iValue1 + iValue2;
+}
+
+LADD ( lValue1 lValue2 -- lResult ) 0x61
+{
+  lResult = lValue1 + lValue2;
+}
+
+FADD ( fValue1 fValue2 -- fResult ) 0x62
+{
+  fResult = fValue1 + fValue2;
+}
+
+DADD ( dValue1 dValue2 -- dResult ) 0x63
+{
+  dResult = dValue1 + dValue2;
+}
+
+ISUB ( iValue1 iValue2 -- iResult ) 0x64
+{
+  iResult = iValue1 - iValue2;
+}
+
+LSUB ( lValue1 lValue2 -- lResult ) 0x65
+{
+  lResult = lValue1 - lValue2;
+}
+
+FSUB ( fValue1 fValue2 -- fResult ) 0x66
+{
+  fResult = fValue1 - fValue2;
+}
+
+DSUB ( dValue1 dValue2 -- dResult ) 0x67
+{
+  dResult = dValue1 - dValue2;
+}
+
+IMUL ( iValue1 iValue2 -- iResult ) 0x68
+{
+  iResult = iValue1 * iValue2;
+}
+
+LMUL ( lValue1 lValue2 -- lResult ) 0x69
+{
+  lResult = lValue1 * lValue2;
+}
+
+FMUL ( fValue1 fValue2 -- fResult ) 0x6a
+{
+  fResult = fValue1 * fValue2;
+}
+
+DMUL ( dValue1 dValue2 -- dResult ) 0x6b
+{
+  dResult = dValue1 * dValue2;
+}
+
+IDIV ( iValue1 iValue2 -- iResult ) 0x6c
+{
+  CHECK_ZERO_DIVISOR(iValue2);
+  ;
+  iResult = iValue1 / iValue2;
+}
+
+IDIVPOW2 ( i1 #ishift -- i2 ) opt
+{
+  u4 sign = i1>>31;
+  s4 offset = sign >> (32-ishift);
+  i2=(i1+offset)>>ishift;
+}
+
+LDIV ( lValue1 lValue2 -- lResult ) 0x6d
+{
+  CHECK_ZERO_DIVISOR(lValue2);
+  ;
+  lResult = lValue1 / lValue2;
+}
+
+LDIVPOW2 ( l1 #ishift -- l2 )
+{
+  u8 sign = l1>>63;
+  s8 offset = sign >> (64-ishift);
+  l2=(l1+offset)>>ishift;
+}
+
+FDIV ( fValue1 fValue2 -- fResult ) 0x6e
+{
+  fResult = fValue1 / fValue2;
+}
+
+DDIV ( dValue1 dValue2 -- dResult ) 0x6f
+{
+  dResult = dValue1 / dValue2;
+}
+
+
+IREM ( iValue1 iValue2 -- iResult ) 0x70
+{
+  CHECK_ZERO_DIVISOR(iValue2);
+  iResult = iValue1 % iValue2;
+}
+
+IREMPOW2 ( i1 #imask -- i2 )
+s4 x = i1;
+if (i1<0)
+  x += imask;
+x &= ~imask;
+i2 = i1-x;
+
+LREM ( lValue1 lValue2 -- lResult ) 0x71
+{
+  CHECK_ZERO_DIVISOR(lValue2);
+  lResult = lValue1 % lValue2;
+}
+
+LREMPOW2 ( l1 #lmask -- l2 )
+s8 x = l1;
+if (l1<0)
+  x += lmask;
+x &= ~lmask;
+l2 = l1-x;
+
+FREM ( fValue1 fValue2 -- fResult ) 0x72
+{
+  fResult = builtin_frem(fValue1, fValue2);
+}
+
+DREM ( dValue1 dValue2 -- dResult ) 0x73
+{
+  dResult = builtin_drem(dValue1, dValue2);
+}
+
+INEG ( iValue -- iResult ) 0x74
+{
+  iResult = -iValue;
+}
+
+LNEG ( lValue -- lResult ) 0x75
+{
+  lResult = -lValue;
+}
+
+FNEG ( fValue -- fResult ) 0x76
+{
+  fResult = -fValue;
+}
+
+DNEG ( dValue -- dResult ) 0x77
+{
+  dResult = -dValue;
+}
+
+ISHL ( iValue1 iValue2 -- iResult ) 0x78
+{
+  iResult = iValue1 << (iValue2 & 31);
+}
+
+LSHL ( lValue1 iValue2 -- lResult ) 0x79
+{
+  lResult = lValue1 << (iValue2 & 63);
+}
+
+ISHR ( iValue1 iValue2 -- iResult ) 0x7a
+{
+  iResult = iValue1 >> (iValue2 & 31);
+}
+
+LSHR ( lValue1 iValue2 -- lResult ) 0x7b
+{
+  lResult = lValue1 >> (iValue2 & 63);
+}
+
+IUSHR ( iValue1 iValue2 -- iResult ) 0x7c
+{
+  iResult = ((unsigned) iValue1) >> (iValue2 & 31);
+}
+
+LUSHR ( lValue1 iValue2 -- lResult ) 0x7d
+{
+  lResult = (unsigned long long) lValue1 >> (iValue2 & 63);
+}
+
+IAND ( iValue1 iValue2 -- iResult ) 0x7e
+{
+  iResult = iValue1 & iValue2;
+}
+
+LAND ( lValue1 lValue2 -- lResult ) 0x7f
+{
+  lResult = lValue1 & lValue2;
+}
+
+IOR ( iValue1 iValue2 -- iResult ) 0x80
+{
+  iResult = iValue1 | iValue2;
+}
+
+LOR ( lValue1 lValue2 -- lResult ) 0x81
+{
+  lResult = lValue1 | lValue2;
+}
+
+IXOR ( iValue1 iValue2 -- iResult ) 0x82
+{
+  iResult = iValue1 ^ iValue2;
+}
+
+LXOR ( lValue1 lValue2 -- lResult ) 0x83
+{
+  lResult = lValue1 ^ lValue2;
+}
+
+IINC ( #bIndex #iConst  -- ) 0x84
+{
+  access_local_int((unsigned)bIndex) =
+                 access_local_int((unsigned)bIndex) + iConst;
+}
+
+I2L ( iValue -- lValue ) 0x85
+{
+  lValue = iValue;
+}
+
+I2F ( iValue -- fValue ) 0x86
+{
+  fValue = (float) iValue;
+}
+
+I2D ( iValue -- dValue ) 0x87
+{
+  dValue = (double) iValue;
+}
+
+L2I ( lValue -- iValue ) 0x88
+{
+  iValue = lValue;
+}
+
+L2F ( lValue -- fValue ) 0x89
+{
+  fValue = (float) lValue;
+}
+
+L2D ( lValue -- dValue ) 0x8a
+{
+  dValue = (double) lValue;
+}
+
+F2I ( fValue -- iValue ) 0x8b
+{
+    iValue = builtin_f2i(fValue);
+}
+
+F2L ( fValue -- lValue ) 0x8c
+{
+    lValue = builtin_f2l(fValue);
+}
+
+F2D ( fValue -- dValue ) 0x8d
+{
+  dValue = fValue;
+}
+
+D2I ( dValue -- iValue ) 0x8e
+{
+  iValue = builtin_d2i(dValue);
+}
+
+D2L ( dValue -- lValue ) 0x8f
+{
+  lValue = builtin_d2l(dValue);
+}
+
+D2F ( dValue -- fValue ) 0x90
+{
+  fValue = dValue;
+}
+
+INT2BYTE ( iValue -- iResult ) 0x91
+{
+  iResult = (iValue << 24) >> 24; /* XXX: try "(s1)iValue" */
+}
+
+
+INT2CHAR ( iValue -- iResult ) 0x92
+{
+  iResult = iValue & 0xFFFF;
+}
+
+INT2SHORT ( iValue -- iResult ) 0x93
+{
+  iResult = (iValue << 16) >> 16; /* XXX: try "(s2)iValue" */
+}
+
+LCMP ( lValue1 lValue2 -- iResult ) 0x94
+{
+  iResult = lValue1 < lValue2 ? -1 : lValue1 > lValue2 ? 1 : 0;
+}
+
+FCMPL ( fValue1 fValue2 -- iResult ) 0x95
+{
+  iResult = builtin_fcmpl(fValue1, fValue2);
+}
+
+FCMPG ( fValue1 fValue2 -- iResult ) 0x96
+{
+  iResult = builtin_fcmpg(fValue1, fValue2);
+}
+
+DCMPL ( dValue1 dValue2 -- iResult ) 0x97
+{
+  iResult = builtin_dcmpl(dValue1, dValue2);
+}
+
+DCMPG ( dValue1 dValue2 -- iResult ) 0x98
+{
+  iResult = builtin_dcmpg(dValue1, dValue2);
+}
+
+IFEQ ( #ainstTarget iValue -- ) 0x99
+{
+  if ( iValue == 0 ) {
+    SET_IP(ainstTarget); INST_TAIL;
+  }
+}
+
+IFNE ( #ainstTarget iValue -- ) 0x9a
+{
+  if ( iValue != 0 ) {
+    SET_IP(ainstTarget); INST_TAIL;
+  }
+}
+
+IFLT ( #ainstTarget iValue -- ) 0x9b
+{
+  if ( iValue < 0 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IFGE ( #ainstTarget iValue -- ) 0x9c
+{
+  if ( iValue >= 0 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IFGT ( #ainstTarget iValue -- ) 0x9d
+{
+  if ( iValue > 0 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IFLE ( #ainstTarget iValue -- ) 0x9e
+{
+  if ( iValue <= 0 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPEQ ( #ainstTarget iValue1 iValue2 -- ) 0x9f
+{
+  if ( iValue1 == iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPNE  ( #ainstTarget iValue1 iValue2 -- ) 0xa0
+{
+  if ( iValue1 != iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPLT  ( #ainstTarget iValue1 iValue2 -- ) 0xa1
+{
+  if ( iValue1 < iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPGE  ( #ainstTarget iValue1 iValue2 -- ) 0xa2
+{
+  if ( iValue1 >= iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPGT  ( #ainstTarget iValue1 iValue2 -- ) 0xa3
+{
+  if ( iValue1 > iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ICMPLE  ( #ainstTarget iValue1 iValue2 -- ) 0xa4
+{
+  if ( iValue1 <= iValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPEQ ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 == lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPNE  ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 != lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPLT  ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 < lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPGE  ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 >= lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPGT  ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 > lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_LCMPLE  ( #ainstTarget lValue1 lValue2 -- ) opt
+{
+  if ( lValue1 <= lValue2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ACMPEQ  ( #ainstTarget aRef1 aRef2 -- ) 0xa5
+{
+  if ( aRef1 == aRef2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+IF_ACMPNE  ( #ainstTarget aRef1 aRef2 -- ) 0xa6
+{
+  if ( aRef1 != aRef2 )
+    SET_IP(ainstTarget); INST_TAIL;
+}
+
+GOTO (  #ainstTarget -- ) 0xa7
+{
+  SET_IP(ainstTarget);
+}
+
+JSR (  #ainstTarget -- ainstRA ) 0xa8
+{
+    /* Warning: The generator already adds 1 to the IP
+       because there is an inline parameter. Thus, instead
+       of writing IP + 1, we write...*/
+  ainstRA = IP;
+  SET_IP(ainstTarget);
+}
+
+RET ( #bIndex -- ) 0xa9
+{
+  Inst * saved_ip;
+  saved_ip = access_local_ref((unsigned) bIndex);
+  SET_IP(saved_ip);
+}
+
+TABLESWITCH ( #iLow #iRange #addrSegment #iOffset #ainstDefault iIndex -- ) 0xaa
+{
+  s4 idx = iIndex - iLow;
+  if ( ((u4) idx) >= iRange ) {
+    SET_IP(ainstDefault); INST_TAIL;
+  }
+  else {
+    SET_IP(((Inst **)(addrSegment+iOffset))[idx]); INST_TAIL;
+  }
+}
+
+LOOKUPSWITCH ( #iNpairs #addrSegment #iOffset #ainstDefault iKey -- ) 0xab
+{
+  /* Note: This code should use a binary search, as
+     the table is sorted. Note also, we reversed the order
+     of the parms */
+  unsigned i;
+  for ( i = 0; i < iNpairs; i++ ) {
+    Cell *table = (Cell *)(addrSegment+iOffset);
+    if ( iKey == (s4)(table[2 * i]) ) {
+      SET_IP((Inst *)(table[2 * i + 1])); INST_TAIL;
+    }
+  }
+  /* falls through if no match */
+  SET_IP(ainstDefault);
+}
+
+
+\ Our stack works like this:
+\ The stack holds locals, the operand stack and the return address stack.
+\ When we invoke a method, the paramaters are the top N elements
+\ on the stack. These become the first N local variables.
+\ Next we have space for the rest of the local variables.
+\ Next comes a single position on the stack which holds
+\ the value of the frame pointer for the calling function.
+\ Another position holds the instruction pointer of the caller.
+\ Finally, we have space for the elements of the operand stack.
+
+\ fp points to the bottom local; since the stack grows downwards, the
+\ upper end of the frame is fp+1, not fp.  That's why the sp updates
+\ in the returns look like they are off by one.
+
+\ fp -> local0
+\       local1
+\       ...
+\       oldfp
+\ sp -> oldip ; at the start, empty stack
+\       stack0 ;once there is something on the stack
+\       ...
+
+IRETURN ( #iIndexFP vValue -- vResult ) 0xac
+{
+  Inst *new_ip;
+  new_ip = (Inst *)access_local_cell(iIndexFP + 1);
+  sp = fp;
+  fp = (Cell *)access_local_cell(iIndexFP);
+  vResult = vValue;
+  SET_IP(new_ip);
+}
+
+LRETURN ( #iIndexFP lValue -- lResult ) 0xad
+{
+  Inst *new_ip = (Inst *)access_local_cell(iIndexFP + 1);
+  sp = fp - 1;
+  fp = (Cell *)access_local_cell(iIndexFP);
+  lResult = lValue;
+  SET_IP(new_ip);
+}
+
+RETURN ( #iIndexFP -- ) 0xb1
+{
+  Inst *new_ip;
+  IF_spTOS(sp[0] = spTOS);
+  new_ip = (Inst *)access_local_cell(iIndexFP + 1);
+  sp = fp+1;
+  fp = (Cell *)access_local_cell(iIndexFP);
+  SET_IP(new_ip);
+  IF_spTOS(spTOS = sp[0]);
+}
+
+GETSTATIC_CELL ( #addr #auf -- vResult ) opt
+{
+  vResult = *(Cell *)addr;
+}
+
+GETSTATIC_INT ( #addr #auf -- iResult ) opt
+{
+  iResult = *(s4 *)addr;
+}
+
+GETSTATIC_LONG ( #addr #auf -- lResult ) opt
+{
+  lResult = *((s8 *) addr);
+}
+
+PUTSTATIC_CELL ( #addr #auf vValue -- ) opt
+{
+  *((Cell *) addr) = vValue;
+}
+
+PUTSTATIC_INT ( #addr #auf iValue -- ) opt
+{
+  *((s4 *) addr) = iValue;
+}
+
+PUTSTATIC_LONG ( #addr #auf lValue -- ) opt
+{
+  *((s8 *) addr) = lValue;
+}
+
+GETFIELD_CELL ( #iOffset #auf aRef -- vResult ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  vResult = *((Cell *) (((u1 *)aRef) + iOffset));
+}
+
+GETFIELD_INT ( #iOffset #auf aRef -- iResult ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  iResult = *((s4 *) (((u1 *)aRef) + iOffset));
+}
+
+GETFIELD_LONG ( #iOffset #auf aRef -- lResult ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  lResult = *((s8 *) (((u1 *)aRef) + iOffset));
+}
+
+
+PUTFIELD_CELL ( #iOffset #auf aRef vValue -- ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  *((Cell *) (((u1 *)aRef) + iOffset)) = vValue;
+}
+
+PUTFIELD_INT ( #iOffset #auf aRef iValue -- ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  *((s4 *) (((u1 *)aRef) + iOffset)) = iValue;
+}
+
+PUTFIELD_LONG ( #iOffset #auf aRef lValue -- ) opt
+{
+  CHECK_NULL_PTR(aRef);
+  *((s8 *) (((u1 *)aRef) + iOffset)) = lValue;
+}
+
+\ !! called methods have the number of locals at offset -1.
+\ methods are always called indirectly through the codeptr in the stub 
+\   (see createcompilerstub and TRANSLATE).
+
+INVOKEVIRTUAL ( #iOffset #iNargs #aum -- acelloldfp ainstoldip ) 0xd8
+{
+  java_objectheader *aRef = (java_objectheader *)(sp[iNargs + 1]); /* corrected for sp change by vmg */
+  char *v;
+  Inst **stub;
+  Inst *target;
+  CHECK_NULL_PTR(aRef);
+  v = (char *)(aRef->vftbl);
+  stub = *(Inst ***)(v+iOffset);
+  target = *stub;
+  acelloldfp = fp;
+  ainstoldip = IP;
+  fp = sp + 1 + iNargs;
+  sp = fp - MAXLOCALS(stub) - 1;
+  SET_IP(target);
+}
+
+INVOKESTATIC ( #aaTarget #iNargs #aum -- acelloldfp ainstoldip ) 0xb8
+/* an indirect pointer to target is passed to avoid references to uncompiled code */
+{
+  Inst *target = *aaTarget;
+  acelloldfp = fp;
+  ainstoldip = IP;
+  /* sp is already updated by the generator, so we have to compensate for that */
+  fp = sp + 1 + iNargs; /* !! scale nargs at translation time */
+  sp = fp - MAXLOCALS(aaTarget) - 1;
+  SET_IP(target);
+}
+
+INVOKESPECIAL ( #aaTarget #iNargs #aum -- acelloldfp ainstoldip ) 0xb7
+/* an indirect pointer to target is passed to avoid references to uncompiled code */
+{
+  java_objectheader *aRef = (java_objectheader *)(sp[iNargs + 1]); /* corrected for sp change by vmg */
+  Inst *target = *aaTarget;
+  CHECK_NULL_PTR(aRef);
+  acelloldfp = fp;
+  ainstoldip = IP;
+  /* sp is already updated by the generator, so we have to compensate for that */
+  fp = sp + 1 + iNargs; /* !! scale nargs at translation time */
+  sp = fp - MAXLOCALS(aaTarget) - 1;
+  SET_IP(target);
+}
+
+INVOKEINTERFACE ( #iInterfaceOffset #iOffset #iNargs #aum -- acelloldfp ainstoldip ) 0xd8
+{
+  java_objectheader *aRef;
+  char   *v, *t;
+  Inst **stub;
+  Inst *target;
+  ;
+  aRef = (java_objectheader *)sp[iNargs + 1];
+  CHECK_NULL_PTR(aRef);
+  v = (char *)(aRef->vftbl);
+  t = *(char **)(v + iInterfaceOffset);
+  stub = *(Inst ***)(t+iOffset);
+  target = *stub;
+  acelloldfp = fp;
+  ainstoldip = IP;
+  fp = sp + 1 + iNargs;
+  sp = fp - MAXLOCALS(stub) - 1;
+  SET_IP(target);
+}
+
+\ the BUILTIN functions like NEW get their parameters on the stack
+\ instead of through immediate arguments.
+
+NEW ( aClass -- aRef ) 0xbb
+{
+  /* fprintf(stderr,"new: class %lx, class-state=%d\n",(long)aClass,((Hjava_lang_Class*)aClass)->state); */
+  global_sp=sp;
+  aRef = builtin_new((classinfo *)aClass);
+  CLEAR_global_sp;
+}
+
+\ !! use a macro
+
+NEWARRAY_BOOLEAN ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_boolean(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_CHAR ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_char(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_FLOAT ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_float(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_DOUBLE ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_double(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_BYTE ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_byte(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_SHORT ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_short(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_INT ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_int(iSize);
+CLEAR_global_sp;
+
+NEWARRAY_LONG ( iSize -- aArray )
+global_sp=sp;
+aArray = (java_arrayheader *)builtin_newarray_long(iSize);
+CLEAR_global_sp;
+
+NEWARRAY ( iSize avftbl -- aArray ) 0xbd
+{
+  global_sp=sp;
+  aArray = (java_arrayheader *)builtin_newarray(iSize, (vftbl_t *)avftbl);
+  CLEAR_global_sp;
+}
+
+ARRAYLENGTH ( aArray -- iResult ) 0xbe
+{
+  CHECK_NULL_PTR(aArray);
+  iResult = length_array(aArray);
+}
+
+ATHROW ( aRef -- aRef1 ) 0xbf
+{
+  Cell *new_sp, *new_fp;
+  Inst *new_ip;
+  CHECK_NULL_PTR(aRef);
+  goto athrow;
+throw:
+  CLEAR_global_sp;
+  /* IF_spTOS(sp[0] = spTOS); */
+  aRef = *exceptionptr;
+  *exceptionptr = NULL;
+athrow:
+  new_ip = builtin_throw(IP,aRef,fp,&new_sp,&new_fp);
+  if (new_ip==NULL) {
+    /* !! sp = new_sp; ? */
+    IF_spTOS(sp[0] = spTOS);  /* !! correct? even for superinstructions? */
+    global_sp = sp;
+    SUPER_END; /* ATHROW may end a basic block */
+    return aRef;
+  }
+  SET_IP(new_ip);
+  aRef1 = aRef;
+  sp=new_sp-1;
+  fp=new_fp;
+  /* IF_spTOS(spTOS = sp[0]); */
+}
+
+CHECKCAST ( #aClass #acr aRef -- aRef ) 0xc0
+{
+  if (!builtin_checkcast((java_objectheader *)aRef, (classinfo *)aClass))
+    THROW(classcastexception);
+}
+
+ARRAYCHECKCAST ( #avftbl #acr aRef -- aRef ) 0xc0
+{
+  if (!builtin_arraycheckcast(aRef, avftbl))
+    THROW(classcastexception);
+}
+
+INSTANCEOF ( #aClass #acr aRef  -- iResult ) 0xc1
+{
+  iResult = builtin_instanceof(aRef, aClass);
+}
+
+ARRAYINSTANCEOF ( aRef avftbl  -- iResult ) 0xc1
+{
+  iResult = builtin_arrayinstanceof(aRef, avftbl);
+}
+
+MONITORENTER ( aRef -- ) 0xc2
+{
+#if defined(USE_THREADS)
+  /* CHECK_NULL_PTR(aRef); is now done explicitly */
+  builtin_monitorenter(aRef);
+#endif
+}
+
+MONITOREXIT ( aRef -- ) 0xc3
+{
+#if defined(USE_THREADS)
+  /* CHECK_NULL_PTR(aRef); cannot happen */
+  builtin_monitorexit(aRef);
+#endif
+}
+
+CHECKNULL ( aRef -- aRef ) 0xc3
+{
+  CHECK_NULL_PTR(aRef);
+}
+
+MULTIANEWARRAY ( #avftbl #iSize #acr -- aRef ) 197
+{
+  long dims[iSize];
+  int i;
+  IF_spTOS(sp[0] = spTOS);
+  for (i=0; i<iSize; i++) {
+    dims[i]=sp[iSize-i-1];
+  }
+  global_sp=sp;
+  aRef = (java_objectheader *)builtin_multianewarray(iSize, avftbl, dims);
+  CLEAR_global_sp;
+  sp += iSize;
+  IF_spTOS(spTOS = sp[0]);
+}
+
+IFNULL ( #ainstTarget aRef -- )  0xc6
+{
+  if ( aRef == NULL ) {
+    SET_IP(ainstTarget); INST_TAIL;
+  }
+}
+
+IFNONNULL ( #ainstTarget aRef -- ) 0xc7
+{
+  if ( aRef != NULL ) {
+    SET_IP(ainstTarget); INST_TAIL;
+  }
+}
+
+\ patchers for stuff that is unknown at compile time (unloaded classes)
+
+PATCHER_GETSTATIC_INT ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETSTATIC_INT);
+SET_IP(IP-3);
+
+PATCHER_GETSTATIC_LONG ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETSTATIC_LONG);
+SET_IP(IP-3);
+
+PATCHER_GETSTATIC_CELL ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETSTATIC_CELL);
+SET_IP(IP-3);
+
+PATCHER_PUTSTATIC_INT ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTSTATIC_INT);
+SET_IP(IP-3);
+
+PATCHER_PUTSTATIC_LONG ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTSTATIC_LONG);
+SET_IP(IP-3);
+
+PATCHER_PUTSTATIC_CELL ( #aRef #auf -- )
+global_sp = sp;
+if (!patcher_get_putstatic((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTSTATIC_CELL);
+SET_IP(IP-3);
+
+PATCHER_GETFIELD_INT ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETFIELD_INT);
+SET_IP(IP-3);
+
+PATCHER_GETFIELD_LONG ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETFIELD_LONG);
+SET_IP(IP-3);
+
+PATCHER_GETFIELD_CELL ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(GETFIELD_CELL);
+SET_IP(IP-3);
+
+PATCHER_PUTFIELD_INT ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTFIELD_INT);
+SET_IP(IP-3);
+
+PATCHER_PUTFIELD_LONG ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTFIELD_LONG);
+SET_IP(IP-3);
+
+PATCHER_PUTFIELD_CELL ( #iOffset #auf -- )
+global_sp = sp;
+if (!patcher_get_putfield((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(PUTFIELD_CELL);
+SET_IP(IP-3);
+
+NEW1 ( #aClass acrUnused -- aRef ) 0xbb
+{
+  /* fprintf(stderr,"new: class %lx, class-state=%d\n",(long)aClass,((Hjava_lang_Class*)aClass)->state); */
+  global_sp=sp;
+  aRef = builtin_new((classinfo *)aClass);
+  CLEAR_global_sp;
+}
+
+PATCHER_NEW ( #aClass -- )
+/* the unresolved class is in the cell right before this VM instruction;
+   our code generator guarantees thus */
+global_sp = sp;
+if (!patcher_builtin_new((u1 *)(IP-2)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-2] = INST_ADDR(NEW1);
+SET_IP(IP-2);
+
+NEWARRAY1 ( iSize #avftbl avftblUnused -- aRef ) 0xbd
+{
+  global_sp=sp;
+  aRef = (java_objectheader *)builtin_newarray(iSize, (vftbl_t *)avftbl);
+  CLEAR_global_sp;
+}
+
+PATCHER_NEWARRAY ( #avftbl -- )
+/* the unresolved class is in the cell right before this VM instruction;
+   our code generator guarantees thus */
+global_sp = sp;
+if (!patcher_builtin_newarray((u1 *)(IP-2)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-2] = INST_ADDR(NEWARRAY1);
+SET_IP(IP-2);
+
+PATCHER_MULTIANEWARRAY ( #avftbl #iSize #acr -- )
+global_sp = sp;
+if (!patcher_builtin_multianewarray((u1 *)(IP-4)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-4] = INST_ADDR(MULTIANEWARRAY);
+SET_IP(IP-4);
+
+ARRAYINSTANCEOF1 ( aRef #avftbl avftblUnused -- iResult ) 0xc1
+{
+  iResult = builtin_arrayinstanceof(aRef, avftbl);
+}
+
+PATCHER_ARRAYINSTANCEOF ( #avftbl -- )
+/* the unresolved class is in the cell right before this VM instruction;
+   our code generator guarantees thus */
+global_sp = sp;
+if (!patcher_builtin_newarray((u1 *)(IP-2)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-2] = INST_ADDR(ARRAYINSTANCEOF1);
+SET_IP(IP-2);
+
+PATCHER_INVOKESTATIC ( #aaTarget #iNargs #aum -- ) 0xd8
+global_sp = sp;
+if (!patcher_invokestatic_special((u1 *)(IP-4)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-4] = INST_ADDR(INVOKESTATIC);
+SET_IP(IP-4);
+
+PATCHER_INVOKESPECIAL ( #aaTarget #iNargs #aum -- ) 0xd8
+global_sp = sp;
+if (!patcher_invokestatic_special((u1 *)(IP-4)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-4] = INST_ADDR(INVOKESPECIAL);
+SET_IP(IP-4);
+
+PATCHER_INVOKEVIRTUAL ( #iOffset #iNargs #aum -- ) 0xd8
+global_sp = sp;
+if (!patcher_invokevirtual((u1 *)(IP-4)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-4] = INST_ADDR(INVOKEVIRTUAL);
+SET_IP(IP-4);
+
+PATCHER_INVOKEINTERFACE ( #iInterfaceoffset #iOffset #iNargs #aum -- ) 0xd8
+global_sp = sp;
+if (!patcher_invokeinterface((u1 *)(IP-5)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-5] = INST_ADDR(INVOKEINTERFACE);
+SET_IP(IP-5);
+
+PATCHER_CHECKCAST ( #aClass #acr -- ) 0xc
+global_sp = sp;
+if (!patcher_checkcast_instanceof((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(CHECKCAST);
+SET_IP(IP-3);
+
+PATCHER_ARRAYCHECKCAST ( #avftbl #acr -- ) 0xc0
+global_sp = sp;
+if (!patcher_builtin_arraycheckcast((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(ARRAYCHECKCAST);
+SET_IP(IP-3);
+
+PATCHER_INSTANCEOF ( #aClass #acr -- ) 0xc1
+global_sp = sp;
+if (!patcher_checkcast_instanceof((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = INST_ADDR(INSTANCEOF);
+SET_IP(IP-3);
+
+\ CHECKEXCEPTION could be integrated into NEW etc., but that's not as
+\ nice to maintain.
+
+CHECKEXCEPTION ( aRef -- aRef )
+if (aRef==NULL)
+  THROW0;
+
+\ This is stub code for methods that we have not yet translated.
+\ Initially, the code for each method is set to this stub. The
+\ first time the method is called, the code in the stub runs, which
+\ translates the bytecode, and replaces the stub with the threaded code.
+
+TRANSLATE ( #am -- )
+{
+  Inst *codeptr;
+  ;
+  IF_spTOS(sp[0] = spTOS);
+  global_sp = sp;
+  codeptr = (Inst *)jit_compile(am);
+  CLEAR_global_sp;
+  IP[-4] = codeptr;
+  SET_IP(codeptr);
+}
+
+NATIVECALL ( #am #af acelloldfp ainstoldip -- )
+sp = nativecall(af, am, sp);
+IF_spTOS(spTOS = sp[0]);
+fp = acelloldfp;
+SET_IP(ainstoldip);
+
+TRACENATIVECALL ( #am #af acelloldfp ainstoldip -- )
+sp = nativecall(af, am, sp);
+IF_spTOS(spTOS = sp[0]);
+fp = acelloldfp;
+SET_IP(ainstoldip);
+{
+Cell v = spTOS;
+functionptr fp = codegen_findmethod((functionptr)(IP-1));
+methodinfo *m = ((methodinfo **) fp)[-1];
+float f;
+vm_Cell2f(v,f);
+builtin_displaymethodstop(m, (s8)v, f, f);
+}
+
+PATCHER_NATIVECALL ( #am #af -- )
+#if !defined(ENABLE_STATICVM)
+global_sp = sp;
+if (!patcher_resolve_native((u1 *)(IP-3)))
+  THROW0;
+CLEAR_global_sp;
+STORE_ORDER_BARRIER();
+IP[-3] = runverbose ? INST_ADDR(TRACENATIVECALL) : INST_ADDR(NATIVECALL);
+SET_IP(IP-3);
+#else
+assert(false);
+#endif
+
+TRACECALL ( -- )
+functionptr f = codegen_findmethod((functionptr)(IP-1));
+methodinfo *m = ((methodinfo **) f)[-1];
+builtin_trace_args(
+       access_local_cell(0),
+       access_local_cell(1),
+       access_local_cell(2),
+       access_local_cell(3),
+#if TRACE_ARGS_NUM > 4
+       access_local_cell(4),
+       access_local_cell(5),
+#endif
+#if TRACE_ARGS_NUM == 8
+       access_local_cell(6),
+       access_local_cell(7),
+#endif
+       m);
+
+TRACERETURN ( v -- v )
+functionptr fp = codegen_findmethod((functionptr)(IP-1));
+methodinfo *m = ((methodinfo **) fp)[-1];
+float f;
+vm_Cell2f(v,f);
+builtin_displaymethodstop(m, (s8)v, f, f);
+
+TRACELRETURN ( l -- l )
+functionptr fp = codegen_findmethod((functionptr)(IP-1));
+methodinfo *m = ((methodinfo **) fp)[-1];
+Double_Store ds;
+ds.l = l;
+builtin_displaymethodstop(m, l, ds.d, ds.d);
+
+END ( -- )
+IF_spTOS(sp[0] = spTOS);
+global_sp = sp;
+SUPER_END;
+vm_uncount_block(IP); /* undo the count part of SUPER_END,
+                        because there is no fallthrough */
+return NULL;
+
+ICONST_ISTORE = ICONST ISTORE