OSDN Git Service

* config/avr/avr.md (strlenhi): PARALLEL keyword removed.
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
index 2ecaf03..b121a1b 100644 (file)
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999  Cygnus Solutions
+/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -10,24 +10,18 @@ details.  */
 
 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
 
-/* define this to get instruction timings.  */
-/* #define TIME_MAINLOOP  */
-
 #include <config.h>
 
 #pragma implementation "java-interp.h"
 
-#include <cni.h>
 #include <jvm.h>
-#include <java-field.h>
 #include <java-cpool.h>
 #include <java-interp.h>
-#include <java/lang/fdlibm.h>
+// #include <java/lang/fdlibm.h>
 #include <java/lang/System.h>
 #include <java/lang/String.h>
 #include <java/lang/Integer.h>
 #include <java/lang/StringBuffer.h>
-#include <java/io/PrintStream.h>
 #include <java/lang/Class.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/lang/ClassCastException.h>
@@ -38,40 +32,10 @@ details.  */
 #include <java/lang/IncompatibleClassChangeError.h>
 #include <java-insns.h>
 #include <java-signal.h>
-#ifdef TIME_MAINLOOP
-#include <sys/time.h>
-#include <stdio.h>
-#endif
-
-#ifndef INTERPRETER
-
-#include <gnu/gcj/runtime/MethodInvocation.h>
-
-/* This should never happen. */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
-                                               gnu::gcj::RawData *)
-{
-  JvFail ("no interpreter");
-}
 
-#else
+#ifdef INTERPRETER
 
-#define ClassError _CL_Q34java4lang5Error
-extern java::lang::Class ClassError;
-
-static const int PUBLIC       = 0x001;
-static const int PRIVATE      = 0x002;
-static const int PROTECTED    = 0x004;
-static const int STATIC       = 0x008;
-static const int FINAL        = 0x010;
-static const int SYNCHRONIZED = 0x020;
-static const int VOLATILE     = 0x040;
-static const int TRANSIENT    = 0x080;
-static const int NATIVE       = 0x100;
-static const int INTERFACE    = 0x200;
-static const int ABSTRACT     = 0x400;
-static const int ALL_FLAGS    = 0x7FF; 
+#include <stdlib.h>
 
 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
 
@@ -79,17 +43,14 @@ static void throw_internal_error (char *msg)
   __attribute__ ((__noreturn__));
 static void throw_incompatible_class_change_error (jstring msg)
   __attribute__ ((__noreturn__));
-#if !HANDLE_SEGV
+#ifndef HANDLE_SEGV
 static void throw_null_pointer_exception ()
   __attribute__ ((__noreturn__));
 #endif
-#if !HANDLE_FPE
-static void throw_arithmetic_exception ()
-  __attribute__ ((__noreturn__));
-#endif
 
+extern "C" double __ieee754_fmod (double,double);
 
-static inline void dupx (_Jv_word *&sp, int n, int x)
+static inline void dupx (_Jv_word *sp, int n, int x)
 {
   // first "slide" n+x elements n to the right
   int top = n-1;
@@ -104,54 +65,71 @@ static inline void dupx (_Jv_word *&sp, int n, int x)
       sp[top-(n+x)-i] = sp[top-i];
     }
   
-  // the net effect
-  sp += n;
 };
 
 
 #define PUSHA(V)  (sp++)->o = (V)
 #define PUSHI(V)  (sp++)->i = (V)
 #define PUSHF(V)  (sp++)->f = (V)
-#define PUSHL(V)  ({ _Jv_word2 w2; w2.l=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; })
-#define PUSHD(V)  ({ _Jv_word2 w2; w2.d=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; })
+#if SIZEOF_VOID_P == 8
+# define PUSHL(V)   (sp->l = (V), sp += 2)
+# define PUSHD(V)   (sp->d = (V), sp += 2)
+#else
+# define PUSHL(V)  do { _Jv_word2 w2; w2.l=(V); \
+                        (sp++)->ia[0] = w2.ia[0]; \
+                        (sp++)->ia[0] = w2.ia[1]; } while (0)
+# define PUSHD(V)  do { _Jv_word2 w2; w2.d=(V); \
+                        (sp++)->ia[0] = w2.ia[0]; \
+                        (sp++)->ia[0] = w2.ia[1]; } while (0)
+#endif
 
 #define POPA()    ((--sp)->o)
 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
 #define POPF()    ((jfloat) (--sp)->f)
-#define POPL()    ({ _Jv_word2 w2; \
+#if SIZEOF_VOID_P == 8
+# define POPL()          (sp -= 2, (jlong) sp->l)
+# define POPD()          (sp -= 2, (jdouble) sp->d)
+#else
+# define POPL()    ({ _Jv_word2 w2; \
                      w2.ia[1] = (--sp)->ia[0]; \
                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
-#define POPD()    ({ _Jv_word2 w2; \
+# define POPD()    ({ _Jv_word2 w2; \
                      w2.ia[1] = (--sp)->ia[0]; \
                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
+#endif
 
 #define LOADA(I)  (sp++)->o = locals[I].o
 #define LOADI(I)  (sp++)->i = locals[I].i
 #define LOADF(I)  (sp++)->f = locals[I].f
-#define LOADL(I)  ({ jint __idx = (I); \
-    (sp++)->ia[0] = locals[__idx].ia[0]; \
-    (sp++)->ia[0] = locals[__idx+1].ia[0]; \
- })
-#define LOADD(I)  LOADL(I)
-
+#if SIZEOF_VOID_P == 8
+# define LOADL(I)  (sp->l = locals[I].l, sp += 2)
+# define LOADD(I)  (sp->d = locals[I].d, sp += 2)
+#else
+# define LOADL(I)  do { jint __idx = (I); \
+                       (sp++)->ia[0] = locals[__idx].ia[0]; \
+                       (sp++)->ia[0] = locals[__idx+1].ia[0]; \
+                  } while (0)
+# define LOADD(I)  LOADL(I)
+#endif
 
 #define STOREA(I) locals[I].o = (--sp)->o
 #define STOREI(I) locals[I].i = (--sp)->i
 #define STOREF(I) locals[I].f = (--sp)->f
-#define STOREL(I) ({ jint __idx = (I); \
-    locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    locals[__idx].ia[0] = (--sp)->ia[0]; \
- })
-#define STORED(I) STOREL(I)
+#if SIZEOF_VOID_P == 8
+# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
+# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+#else
+# define STOREL(I) do { jint __idx = (I); \
+                      locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+                      locals[__idx].ia[0] = (--sp)->ia[0]; \
+                  } while (0)
+# define STORED(I) STOREL(I)
+#endif
 
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  (*(jint*) (locals+(I)) = (V))
+#define POKEI(I,V)  ((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -202,19 +180,13 @@ static jint get4(unsigned char* loc) {
 }
 
 
-#if HANDLE_SEGV
+#ifdef HANDLE_SEGV
 #define NULLCHECK(X) 
 #else
 #define NULLCHECK(X) \
   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
 #endif
 
-#if HANDLE_FPE
-#define ZEROCHECK(X)
-#else
-#define ZEROCHECK(X) \
-  do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
-#endif
 
 // this method starts the actual running of the method.  It is inlined
 // in three different variants in the static methods run_normal,
@@ -234,15 +206,22 @@ _Jv_InterpMethod::run (ffi_cif* cif,
   _Jv_word *locals = inv->local_base ();
 
   /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At leat, that's the idea.
+     stack representation exactly.  At least, that's the idea.
   */
   memcpy ((void*) locals, (void*) args, args_raw_size);
 
  next_segment:
-  /* this will call the method _Jv_InterpMethod::continue0, see below */
-  jobject ex = 
-    gnu::gcj::runtime::MethodInvocation::continue0
-    ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
+
+  jobject ex = NULL;
+
+  try
+    {
+      continue1 (inv);
+    }
+  catch (java::lang::Throwable *ex2)
+    {
+      ex = ex2;
+    }
 
   if (ex == 0)                 // no exception...
     {
@@ -303,16 +282,12 @@ _Jv_InterpMethod::run (ffi_cif* cif,
        default:
          throw_internal_error ("unknown return type");
        }
-
     }
 
   /** handle an exception */
   if ( find_exception (ex, inv) )
     goto next_segment;
 
-  java::lang::System::out->println 
-    (_Jv_NewStringUTF (self->name->data));
-
   return ex;
 }
 
@@ -358,11 +333,11 @@ void _Jv_InterpMethod::run_normal (ffi_cif* cif,
   // "run" ro be inlined.  Otherwise gcc will ignore the inline directive.
   int storage_size = _this->max_stack+_this->max_locals;
   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    alloca (sizeof (_Jv_InterpMethodInvocation)
-           + storage_size * sizeof (_Jv_word));
+    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+                     + storage_size * sizeof (_Jv_word));
 
   jobject ex = _this->run (cif, ret, args, inv);
-  if (ex != 0) _Jv_Throw (ex);
+  if (ex != 0) throw static_cast<jthrowable>(ex);
 }
 
 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
@@ -375,14 +350,14 @@ void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
 
   int storage_size = _this->max_stack+_this->max_locals;
   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    alloca (sizeof (_Jv_InterpMethodInvocation)
-           + storage_size * sizeof (_Jv_word));
+    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+                     + storage_size * sizeof (_Jv_word));
 
   _Jv_MonitorEnter (rcv);
   jobject ex = _this->run (cif, ret, args, inv);
   _Jv_MonitorExit (rcv);
 
-  if (ex != 0) _Jv_Throw (ex);
+  if (ex != 0) throw static_cast<jthrowable>(ex);
 }
 
 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
@@ -395,30 +370,20 @@ void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
 
   int storage_size = _this->max_stack+_this->max_locals;
   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    alloca (sizeof (_Jv_InterpMethodInvocation)
-           + storage_size * sizeof (_Jv_word));
+    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+                     + storage_size * sizeof (_Jv_word));
 
   _Jv_MonitorEnter (sync);
   jobject ex = _this->run (cif, ret, args, inv);
   _Jv_MonitorExit (sync);
 
-  if (ex != 0) _Jv_Throw (ex);
-}
-
-/* this is the exception handler hack, for the interpreter */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
-                                               gnu::gcj::RawData *inv)
-{
-  _Jv_InterpMethod           *meth0 = (_Jv_InterpMethod*)meth;
-  _Jv_InterpMethodInvocation *inv0  = (_Jv_InterpMethodInvocation*)inv;
-  meth0->continue1 (inv0);
+  if (ex != 0) throw static_cast<jthrowable>(ex);
 }
 
 /*
   This proceeds execution, as designated in "inv".  If an exception
   happens, then it is simply thrown, and handled in Java.  Thus, the pc
-  needs to be stored in the invocation at all times, so we can figure
+  needs to be stored in the inv->pc at all times, so we can figure
   out which handler (if any) to invoke.
 
   One design issue, which I have not completely considered, is if it
@@ -427,146 +392,277 @@ gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
 */
 
 
-#ifdef TIME_MAINLOOP
-static jlong insn_time [256] = { 0 };
-static jlong insn_count[256] = { 0 };
-
-static void
-dump_time ()
-{
-  double total_all = 0;
-  for (int i = 0; i < 256; i++)
-    {
-      total_all += insn_time[i];
-    }
-
-  for (int i = 0; i < 256; i++)
-    {
-      jlong total  = insn_time[i];
-      jlong count  = insn_count[i];
-
-      if (count == 0) continue;
-
-      jlong amount = total/count;
-
-      printf ("in 0x%02x: %7Li %7Li %7Li %2.1f%%\n", i,
-             (long long)count, (long long)total, (long long)amount,
-             (float) (100.0*(double)total/total_all)
-             );
-    }
-}
-#endif
-  
 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 {
+  using namespace java::lang::reflect;
+
   _Jv_word      *sp     = inv->sp;
   unsigned char *pc     = inv->pc;
-  _Jv_word      *locals = inv->local_base ();
-  int            opcode;
+  _Jv_word               *locals = inv->local_base ();
 
-  jclass defining_class = this->defining_class;
   _Jv_word *pool_data   = defining_class->constants.data;
   
   /* these two are used in the invokeXXX instructions */
-  void (*fun)(...);
+  void (*fun)();
   _Jv_ResolvedMethod* rmeth;
 
-#ifdef TIME_MAINLOOP
-  struct timeval tv;
-  int   last_opcode;
-  jlong last_time;
-  static jlong time_warp = 0;
-
-#define USEC(TV) \
-   ((jlong) (TV).tv_sec * 1000000LL + (jlong)(TV).tv_usec)
-
-
-  if (time_warp == 0) 
-    {
-      struct timeval tv2;
-
-      gettimeofday (&tv, 0); 
-      for (int i = 0; i < 100; i++)
-       gettimeofday (&tv2, 0); 
-      
-      jlong then = USEC(tv); 
-      jlong now = USEC(tv2);
-      time_warp = (now - then) / 100;
-
-      if (time_warp == 0)
-       time_warp = 1;
-    }    
-
-#define TIME_SUSPEND do { \
-  gettimeofday (&tv, 0); \
-  jlong now = USEC(tv); \
-  insn_time[last_opcode] += (now - last_time) - time_warp; \
-} while(0)
-
-#define TIME_RESUME do { \
-  gettimeofday (&tv, 0); \
-  last_time = USEC(tv); \
-} while(0)
-
-  last_opcode = 0; 
-  gettimeofday (&tv, 0); 
-  last_time = (jlong)tv.tv_sec * 1000000LL + (jlong)tv.tv_usec; 
-
+#define INSN_LABEL(op) &&insn_##op
+#define GOTO_INSN(op) goto *(insn_target[op])
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* op_xxxunusedxxx1, */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+    INSN_LABEL(wide),
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+  };
+
+#define SAVE_PC   inv->pc = pc-1
+
+  /* If the macro INLINE_SWITCH is not defined, then the main loop
+     operates as one big (normal) switch statement.  If it is defined,
+     then the case selection is performed `inline' in the end of the
+     code for each case.  The latter saves a native branch instruction
+     for each java-instruction, but expands the code size somewhat.
+
+     NOTE: On i386 defining INLINE_SWITCH improves over all
+     performance approximately seven percent, but it may be different
+     for other machines.  At some point, this may be made into a proper
+     configuration parameter.  */
+
+#define INLINE_SWITCH 
+
+#ifdef  INLINE_SWITCH
+
+#define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
+
+
+  NEXT_INSN;
 #else
 
-#define TIME_SUSPEND 
-#define TIME_RESUME
-
-#endif
+#define NEXT_INSN goto next_insn
 
  next_insn:
-  inv->pc = pc;
-
-#ifdef TIME_MAINLOOP
-
-  gettimeofday (&tv, 0); 
-  jlong now = USEC(tv); 
-  insn_time[last_opcode] += (now - last_time) - time_warp; 
-  last_time = now; 
-  last_opcode = *pc; 
-  insn_count[last_opcode] += 1;
+  GOTO_INSN (*pc++);
 
 #endif
-  opcode = *pc++;
 
-  switch (opcode)
-    {
-    case op_aload_0:           // 0x2a
+  /* The first few instructions here are ordered according to their
+     frequency, in the hope that this will improve code locality a
+     little.  */
+
+     insn_aload_0:             // 0x2a
       LOADA(0);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iload:             // 0x15
+     insn_iload:               // 0x15
       LOADI (get1u (pc++));
-      goto next_insn;
-
-    case op_getfield_4:                // 0xd8
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jint*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iload_1:           // 0x1b
+     insn_iload_1:             // 0x1b
       LOADI (1);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_getfield_a:                // 0xda
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHA(*(jobject*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
-
-    case op_invokevirtual:     // 0xb6
+     insn_invokevirtual:       // 0xb6
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
 
@@ -579,24 +675,28 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
        sp -= rmeth->stack_item_count;
-       NULLCHECK(sp[0]);
+       // We don't use NULLCHECK here because we can't rely on that
+       // working if the method is final.  So instead we do an
+       // explicit test.
+       if (! sp[0].o)
+         throw new java::lang::NullPointerException;
 
        if (rmeth->vtable_index == -1)
          {
            // final methods do not appear in the vtable,
            // if it does not appear in the superclass.
-           fun = (void (*) (...)) rmeth->method->ncode;
+           fun = (void (*)()) rmeth->method->ncode;
          }
        else
          {
            jobject rcv = sp[0].o;
            _Jv_VTable *table = *(_Jv_VTable**)rcv;
-           fun = (void (*) (...))table->method[rmeth->vtable_index];
+           fun = (void (*)()) table->method[rmeth->vtable_index];
          }
       }
       goto perform_invoke;
 
-    perform_invoke:
+     perform_invoke:
       {
        /* here goes the magic again... */
        ffi_cif *cif = &rmeth->cif;
@@ -604,9 +704,13 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        jdouble rvalue;
 
-       TIME_SUSPEND;
+#if FFI_NATIVE_RAW_API
+       /* We assume that this is only implemented if it's correct      */
+       /* to use it here.  On a 64 bit machine, it never is.           */
        ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-       TIME_RESUME;
+#else
+       ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
 
        int rtype = cif->rtype->type;
 
@@ -658,756 +762,870 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
          case FFI_TYPE_SINT64:
            PUSHL (*(jlong*)&rvalue);
            break;
-       
+
          default:
            throw_internal_error ("unknown return type in invokeXXX");
          }
-       
+
       }
-      goto next_insn;
+      NEXT_INSN;
 
 
-    case op_nop:
-      goto next_insn;
+     insn_nop:
+      NEXT_INSN;
 
-    case op_aconst_null:
+     insn_aconst_null:
       PUSHA (NULL);
-      goto next_insn;
-
-    case op_iconst_m1:
-    case op_iconst_0:
-    case op_iconst_1:
-    case op_iconst_2:
-    case op_iconst_3:
-    case op_iconst_4:
-    case op_iconst_5:
-      PUSHI (opcode-op_iconst_0);
-      goto next_insn;
-
-    case op_lconst_0:
-    case op_lconst_1:
-      PUSHL ((jlong) (opcode-op_lconst_0));
-      goto next_insn;
-      
-    case op_fconst_0:
-    case op_fconst_1:
-    case op_fconst_2:
-      PUSHF ((jfloat) (opcode-op_fconst_0));
-      goto next_insn;
-
-    case op_dconst_0:
-    case op_dconst_1:
-      PUSHD ((jdouble) (opcode-op_dconst_0));
-      goto next_insn;
-
-    case op_bipush:
+      NEXT_INSN;
+
+     insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+     insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+     insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+     insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+     insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+     insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+     insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+     insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+     insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+     insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+     insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+     insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+     insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+     insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+     insn_bipush:
       PUSHI (get1s(pc++));
-      goto next_insn;
-      
-    case op_sipush:
+      NEXT_INSN;
+
+     insn_sipush:
       PUSHI (get2s(pc)); pc += 2;
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ldc:
+     insn_ldc:
       {
        int index = get1u (pc++);
        PUSHA(pool_data[index].o);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ldc_w:
+     insn_ldc_w:
       {
        int index = get2u (pc); pc += 2;
        PUSHA(pool_data[index].o);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ldc2_w:
+     insn_ldc2_w:
       {
        int index = get2u (pc); pc += 2;
        memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
        sp += 2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lload:
+     insn_lload:
       LOADL (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fload:
+     insn_fload:
       LOADF (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dload:
+     insn_dload:
       LOADD (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_aload:
+     insn_aload:
       LOADA (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iload_0:
+     insn_iload_0:
       LOADI (0);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iload_2:
+     insn_iload_2:
       LOADI (2);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iload_3:
+     insn_iload_3:
       LOADI (3);
-      goto next_insn;
-
-    case op_lload_0:
-    case op_lload_1:
-    case op_lload_2:
-    case op_lload_3:
-      LOADL (opcode-op_lload_0);
-      goto next_insn;
-
-    case op_fload_0:
-    case op_fload_1:
-    case op_fload_2:
-    case op_fload_3:
-      LOADF (opcode-op_fload_0);
-      goto next_insn;
-
-    case op_dload_0:
-    case op_dload_1:
-    case op_dload_2:
-    case op_dload_3:
-      LOADD (opcode-op_dload_0);
-      goto next_insn;
-
-    case op_aload_1:
+      NEXT_INSN;
+
+     insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+     insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+     insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+     insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+     insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+     insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+     insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+     insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+     insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+     insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+     insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+     insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+     insn_aload_1:
       LOADA(1);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_aload_2:
+     insn_aload_2:
       LOADA(2);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_aload_3:
+     insn_aload_3:
       LOADA(3);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iaload:
+     insn_iaload:
+      SAVE_PC;
       {
        jint index = POPI();
        jintArray arr = (jintArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHI( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_laload:
+     insn_laload:
+      SAVE_PC;
       {
        jint index = POPI();
        jlongArray arr = (jlongArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHL( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_faload:
+     insn_faload:
+      SAVE_PC;
       {
        jint index = POPI();
        jfloatArray arr = (jfloatArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHF( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_daload:
+     insn_daload:
+      SAVE_PC;
       {
        jint index = POPI();
        jdoubleArray arr = (jdoubleArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHD( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_aaload:
+     insn_aaload:
+      SAVE_PC;
       {
        jint index = POPI();
        jobjectArray arr = (jobjectArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHA( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_baload:
+     insn_baload:
+      SAVE_PC;
       {
        jint index = POPI();
        jbyteArray arr = (jbyteArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHI( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_caload:
+     insn_caload:
+      SAVE_PC;
       {
        jint index = POPI();
        jcharArray arr = (jcharArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHI( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_saload:
+     insn_saload:
+      SAVE_PC;
       {
        jint index = POPI();
        jshortArray arr = (jshortArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        PUSHI( elements(arr)[index] );
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_istore:
+     insn_istore:
       STOREI (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lstore:
+     insn_lstore:
       STOREL (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fstore:
+     insn_fstore:
       STOREF (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dstore:
+     insn_dstore:
       STORED (get1u (pc++));
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_astore:
-      STOREI (get1u (pc++));
-      goto next_insn;
-
-    case op_istore_0:
-    case op_istore_1:
-    case op_istore_2:
-    case op_istore_3:
-      STOREI (opcode-op_istore_0);
-      goto next_insn;
-
-    case op_lstore_0:
-    case op_lstore_1:
-    case op_lstore_2:
-    case op_lstore_3:
-      STOREL (opcode-op_lstore_0);
-      goto next_insn;
-
-    case op_fstore_0:
-    case op_fstore_1:
-    case op_fstore_2:
-    case op_fstore_3:
-      STOREF (opcode-op_fstore_0);
-      goto next_insn;
-
-    case op_dstore_0:
-    case op_dstore_1:
-    case op_dstore_2:
-    case op_dstore_3:
-      STORED (opcode-op_dstore_0);
-      goto next_insn;
-
-    case op_astore_0:
-    case op_astore_1:
-    case op_astore_2:
-    case op_astore_3:
-      STOREA (opcode-op_astore_0);
-      goto next_insn;
-
-    case op_iastore:
+     insn_astore:
+      STOREA (get1u (pc++));
+      NEXT_INSN;
+
+     insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+     insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+     insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+     insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+     insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+     insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+     insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+     insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+     insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+     insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+     insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+     insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+     insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+     insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+     insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+     insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+     insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+     insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+     insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+     insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+     insn_iastore:
+      SAVE_PC;
       {
        jint value = POPI();
        jint index  = POPI();
        jintArray arr = (jintArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lastore:
+     insn_lastore:
+      SAVE_PC;
       {
        jlong value = POPL();
        jint index  = POPI();
        jlongArray arr = (jlongArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fastore:
+     insn_fastore:
+      SAVE_PC;
       {
        jfloat value = POPF();
        jint index  = POPI();
        jfloatArray arr = (jfloatArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dastore:
+     insn_dastore:
+      SAVE_PC;
       {
        jdouble value = POPD();
        jint index  = POPI();
        jdoubleArray arr = (jdoubleArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_aastore:
+     insn_aastore:
+      SAVE_PC;
       {
        jobject value = POPA();
        jint index  = POPI();
        jobjectArray arr = (jobjectArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        _Jv_CheckArrayStore (arr, value);
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_bastore:
+     insn_bastore:
+      SAVE_PC;
       {
        jbyte value = (jbyte) POPI();
        jint index  = POPI();
        jbyteArray arr = (jbyteArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_castore:
+     insn_castore:
+      SAVE_PC;
       {
        jchar value = (jchar) POPI();
        jint index  = POPI();
        jcharArray arr = (jcharArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_sastore:
+     insn_sastore:
+      SAVE_PC;
       {
        jshort value = (jshort) POPI();
        jint index  = POPI();
        jshortArray arr = (jshortArray) POPA();
        NULLCHECK (arr);
        if (index < 0 || index >= arr->length)
-         {
-           TIME_SUSPEND;
+         {
            _Jv_ThrowBadArrayIndex (index);
          }
        elements(arr)[index] = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_pop:
+     insn_pop:
       sp -= 1;
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_pop2:
+     insn_pop2:
       sp -= 2;
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dup:
+     insn_dup:
       sp[0] = sp[-1];
       sp += 1;
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dup_x1:
-      dupx (sp, 1, 1);
-      goto next_insn;
+     insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
 
-    case op_dup_x2:
-      dupx (sp, 1, 2);
-      goto next_insn;
+     insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
 
-    case op_dup2:
+     insn_dup2:
       sp[0] = sp[-2];
       sp[1] = sp[-1];
       sp += 2;
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dup2_x1:
-      dupx (sp, 2, 1);
-      goto next_insn;
+     insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
 
-    case op_dup2_x2:
-      dupx (sp, 2, 2);
-      goto next_insn;
+     insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
 
-    case op_swap:
+     insn_swap:
       {
        jobject tmp1 = POPA();
        jobject tmp2 = POPA();
        PUSHA (tmp1);
        PUSHA (tmp2);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iadd:
+     insn_iadd:
       BINOPI(+);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ladd:
+     insn_ladd:
       BINOPL(+);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fadd:
+     insn_fadd:
       BINOPF(+);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dadd:
+     insn_dadd:
       BINOPD(+);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_isub:
+     insn_isub:
       BINOPI(-);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lsub:
+     insn_lsub:
       BINOPL(-);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fsub:
+     insn_fsub:
       BINOPF(-);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dsub:
+     insn_dsub:
       BINOPD(-);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_imul:
+     insn_imul:
       BINOPI(*);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lmul:
+     insn_lmul:
       BINOPL(*);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fmul:
+     insn_fmul:
       BINOPF(*);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dmul:
+     insn_dmul:
       BINOPD(*);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_idiv:
+     insn_idiv:
+      SAVE_PC;
       {
        jint value2 = POPI();
        jint value1 = POPI();
-       ZEROCHECK (value2);
-       jint res = value1 / value2;
+       jint res = _Jv_divI (value1, value2);
        PUSHI (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ldiv:
-       {
+     insn_ldiv:
+      SAVE_PC;
+      {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 / value2;
+       jlong res = _Jv_divJ (value1, value2);
        PUSHL (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fdiv:
+     insn_fdiv:
+      SAVE_PC;
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res = value1 / value2;
        PUSHF (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ddiv:
+     insn_ddiv:
+      SAVE_PC;
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res = value1 / value2;
        PUSHD (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_irem:
+     insn_irem:
+      SAVE_PC;
       {
        jint value2 = POPI();
-       jint value1 = POPI();
-       ZEROCHECK (value2);     
-       jint res = value1 % value2;
+       jint value1 =  POPI();
+       jint res = _Jv_remI (value1, value2);
        PUSHI (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lrem:
-       {
+     insn_lrem:
+      SAVE_PC;
+      {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 % value2;
+       jlong res = _Jv_remJ (value1, value2);
        PUSHL (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_frem:
+     insn_frem:
+      SAVE_PC;
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res    = __ieee754_fmod (value1, value2);
        PUSHF (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_drem:
+     insn_drem:
+      SAVE_PC;
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res    = __ieee754_fmod (value1, value2);
        PUSHD (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ineg:
-      *(jint*) (sp-1) *= -1;
-      goto next_insn;
+     insn_ineg:
+      {
+       jint value = POPI();
+       PUSHI (value * -1);
+      }
+      NEXT_INSN;
 
-    case op_lneg:
-      *(jlong*) (sp-1) *= -1;
-      goto next_insn;
+     insn_lneg:
+      {
+       jlong value = POPL();
+       PUSHL (value * -1);
+      }
+      NEXT_INSN;
 
-    case op_fneg:
-      *(jfloat*) (sp-1) *= -1;
-      goto next_insn;
+     insn_fneg:
+      {
+       jfloat value = POPF();
+       PUSHF (value * -1);
+      }
+      NEXT_INSN;
 
-    case op_dneg:
-      *(jdouble*) (sp-1) *= -1;
-      goto next_insn;
+     insn_dneg:
+      {
+       jdouble value = POPD();
+       PUSHD (value * -1);
+      }
+      NEXT_INSN;
 
-    case op_ishl:
+     insn_ishl:
       {
        jint shift = (POPI() & 0x1f);
        jint value = POPI();
        PUSHI (value << shift);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lshl:
+     insn_lshl:
       {
        jint shift = (POPI() & 0x3f);
        jlong value = POPL();
        PUSHL (value << shift);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ishr:
+     insn_ishr:
       {
        jint shift = (POPI() & 0x1f);
        jint value = POPI();
        PUSHI (value >> shift);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lshr:
+     insn_lshr:
       {
        jint shift = (POPI() & 0x3f);
        jlong value = POPL();
        PUSHL (value >> shift);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iushr:
+     insn_iushr:
       {
        jint shift = (POPI() & 0x1f);
        unsigned long value = POPI();
        PUSHI ((jint) (value >> shift));
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lushr:
+     insn_lushr:
       {
        jint shift = (POPI() & 0x3f);
        UINT64 value = (UINT64) POPL();
        PUSHL ((value >> shift));
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iand:
+     insn_iand:
       BINOPI (&);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_land:
+     insn_land:
       BINOPL (&);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ior:
+     insn_ior:
       BINOPI (|);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lor:
+     insn_lor:
       BINOPL (|);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ixor:
+     insn_ixor:
       BINOPI (^);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lxor:
+     insn_lxor:
       BINOPL (^);
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iinc:
+     insn_iinc:
       {
        jint index  = get1u (pc++);
        jint amount = get1s (pc++);
-       *(jint*) (locals + index) += amount;
+       locals[index].i += amount;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2l:
+     insn_i2l:
       {jlong value = POPI(); PUSHL (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2f:
+     insn_i2f:
       {jfloat value = POPI(); PUSHF (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2d:
+     insn_i2d:
       {jdouble value = POPI(); PUSHD (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_l2i:
+     insn_l2i:
       {jint value = POPL(); PUSHI (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_l2f:
+     insn_l2f:
       {jfloat value = POPL(); PUSHF (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_l2d:
+     insn_l2d:
       {jdouble value = POPL(); PUSHD (value);}
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_f2i:
+     insn_f2i:
       { jint value = (jint)POPF (); PUSHI(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_f2l:
+     insn_f2l:
       { jlong value = (jlong)POPF (); PUSHL(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_f2d:
+     insn_f2d:
       { jdouble value = POPF (); PUSHD(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_d2i:
+     insn_d2i:
       { jint value = (jint)POPD (); PUSHI(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_d2l:
+     insn_d2l:
       { jlong value = (jlong)POPD (); PUSHL(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_d2f:
+     insn_d2f:
       { jfloat value = POPD (); PUSHF(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2b:
+     insn_i2b:
       { jbyte value = POPI (); PUSHI(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2c:
+     insn_i2c:
       { jchar value = POPI (); PUSHI(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_i2s:
+     insn_i2s:
       { jshort value = POPI (); PUSHI(value); }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lcmp:
+     insn_lcmp:
       {
        jlong value2 = POPL ();
        jlong value1 = POPL ();
@@ -1418,10 +1636,10 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          { PUSHI (-1); }
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_fcmpl:
-    case op_fcmpg:
+     insn_fcmpl:
+     insn_fcmpg:
       {
        jfloat value2 = POPF ();
        jfloat value1 = POPF ();
@@ -1431,15 +1649,15 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
          PUSHI (0);
        else if (value1 < value2)
          PUSHI (-1);
-       else if (opcode == op_fcmpg)
+       else if ((*(pc-1)) == op_fcmpg)
          PUSHI (1);
        else
          PUSHI (-1);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_dcmpl:
-    case op_dcmpg:
+     insn_dcmpl:
+     insn_dcmpg:
       {
        jdouble value2 = POPD ();
        jdouble value1 = POPD ();
@@ -1449,14 +1667,14 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
          PUSHI (0);
        else if (value1 < value2)
          PUSHI (-1);
-       else if (opcode == op_dcmpg)
+       else if ((*(pc-1)) == op_dcmpg)
          PUSHI (1);
        else
          PUSHI (-1);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifeq:
+     insn_ifeq:
       {
        jint offset = get2s (pc); 
        if (POPI() == 0)
@@ -1464,9 +1682,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifne:
+     insn_ifne:
       {
        jint offset = get2s (pc); 
        if (POPI() != 0)
@@ -1474,9 +1692,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_iflt:
+     insn_iflt:
       {
        jint offset = get2s (pc); 
        if (POPI() < 0)
@@ -1484,9 +1702,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifge:
+     insn_ifge:
       {
        jint offset = get2s (pc); 
        if (POPI() >= 0)
@@ -1494,9 +1712,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifgt:
+     insn_ifgt:
       {
        jint offset = get2s (pc); 
        if (POPI() > 0)
@@ -1504,9 +1722,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifle:
+     insn_ifle:
       {
        jint offset = get2s (pc); 
        if (POPI() <= 0)
@@ -1514,9 +1732,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmpeq:
+     insn_if_icmpeq:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1526,9 +1744,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmpne:
+     insn_if_icmpne:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1538,9 +1756,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmplt:
+     insn_if_icmplt:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1550,9 +1768,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmpge:
+     insn_if_icmpge:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1562,9 +1780,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmpgt:
+     insn_if_icmpgt:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1574,9 +1792,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_icmple:
+     insn_if_icmple:
       {
        jint offset = get2s (pc); 
        jint value2 = POPI();
@@ -1586,9 +1804,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_acmpeq:
+     insn_if_acmpeq:
       {
        jint offset = get2s (pc); 
        jobject value2 = POPA();
@@ -1598,9 +1816,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_if_acmpne:
+     insn_if_acmpne:
       {
        jint offset = get2s (pc); 
        jobject value2 = POPA();
@@ -1610,36 +1828,36 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = pc+2;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_goto: 
+     insn_goto: 
       {
        jint offset = get2s (pc);
        pc = pc-1+offset;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_jsr:
+     insn_jsr:
       {
        unsigned char *base_pc = pc-1;
        jint offset = get2s (pc); pc += 2;
        PUSHA ((jobject)pc);
        pc = base_pc+offset;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ret:
+     insn_ret:
       {
        jint index = get1u (pc);
        pc = (unsigned char*) PEEKA (index);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_tableswitch:
+     insn_tableswitch:
       {
        unsigned char *base_pc = pc-1;
        int index = POPI();
-       
+
        unsigned char* base = bytecode ();
        while ((pc-base) % 4 != 0)
          pc++;
@@ -1653,20 +1871,20 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        else
          pc = base_pc + get4 (pc+4*(index-low+3));
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_lookupswitch:
+     insn_lookupswitch:
       {
        unsigned char *base_pc = pc-1;
        int index = POPI();
-       
+
        unsigned char* base = bytecode ();
        while ((pc-base) % 4 != 0)
          pc++;
-       
+
        jint def     = get4 (pc);
        jint npairs  = get4 (pc+4);
-       
+
        int max = npairs-1;
        int min = 0;
 
@@ -1681,37 +1899,36 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
            else if (index < match)
              max = half-1;
-           
+
            else
              min = half+1;
          }
-       
+
        if (index == get4 (pc+ 4*(2 + 2*min)))
          pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
        else
          pc = base_pc + def;    
       }
-      goto next_insn;
+      NEXT_INSN;
 
       /* on return, just save the sp and return to caller */
-    case op_ireturn:
-    case op_lreturn:
-    case op_freturn:
-    case op_dreturn:
-    case op_areturn:
-    case op_return:
+     insn_ireturn:
+     insn_lreturn:
+     insn_freturn:
+     insn_dreturn:
+     insn_areturn:
+     insn_return:
       inv->sp = sp;
-      TIME_SUSPEND;
       return;
 
-    case op_getstatic:
+     insn_getstatic:
+      SAVE_PC;
       {
-       unsigned char *base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
-       if ((field->flags & STATIC) == 0)
+       if ((field->flags & Modifier::STATIC) == 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field no longer static"));
 
@@ -1722,89 +1939,85 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
            switch (type->size_in_bytes)
              {
              case 1:
-               *base_pc = op_getstatic_1;
+               PUSHI (*(jbyte*) (field->u.addr));
                break;
-           
+
              case 2:
                if (type == JvPrimClass (char))
-                 *base_pc = op_getstatic_2u;
+                 PUSHI(*(jchar*) (field->u.addr));
                else
-                 *base_pc = op_getstatic_2s;
+                 PUSHI(*(jshort*) (field->u.addr));
                break;
 
              case 4:
-               *base_pc = op_getstatic_4;
+               PUSHI(*(jint*) (field->u.addr));
                break;
 
              case 8:
-               *base_pc = op_getstatic_8;
+               PUSHL(*(jlong*) (field->u.addr));
                break;
              }
          }
        else
          {
-           *base_pc = op_getstatic_a;
+           PUSHA(*(jobject*) (field->u.addr));
          }
-       
-       pc = base_pc;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_getfield:
+     insn_getfield:
+      SAVE_PC;
       {
-       unsigned char *base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
-       if ((field->flags & STATIC) != 0)
+       if ((field->flags & Modifier::STATIC) != 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field is static"));
 
        jclass type = field->type;
+       jint field_offset = field->u.boffset;
+       if (field_offset > 0xffff)
+         throw new java::lang::VirtualMachineError;
+
+       jobject obj   = POPA();
+       NULLCHECK(obj);
 
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes)
              {
              case 1:
-               *base_pc = op_getfield_1;
+               PUSHI (*(jbyte*) ((char*)obj + field_offset));
                break;
-           
+
              case 2:
                if (type == JvPrimClass (char))
-                 *base_pc = op_getfield_2u;
+                 PUSHI (*(jchar*) ((char*)obj + field_offset));
                else
-                 *base_pc = op_getfield_2s;
+                 PUSHI (*(jshort*) ((char*)obj + field_offset));
                break;
 
              case 4:
-               *base_pc = op_getfield_4;
+               PUSHI (*(jint*) ((char*)obj + field_offset));
                break;
 
              case 8:
-               *base_pc = op_getfield_8;
+               PUSHL(*(jlong*) ((char*)obj + field_offset));
                break;
              }
          }
        else
          {
-           *base_pc = op_getfield_a;
+           PUSHA(*(jobject*) ((char*)obj + field_offset));
          }
-       
-       if (field->u.boffset > 0xffff)
-         JvThrow (new java::lang::VirtualMachineError);
-
-       base_pc[1] = (field->u.boffset>>8) & 0xff;
-       base_pc[2] = field->u.boffset & 0xff;
-
-       pc = base_pc;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_putstatic:
+     insn_putstatic:
+      SAVE_PC;
       {
-       unsigned char* base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
@@ -1812,303 +2025,151 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        jclass type = field->type;
 
        // ResolvePoolEntry cannot check this
-       if ((field->flags & STATIC) == 0)
+       if ((field->flags & Modifier::STATIC) == 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field no longer static"));
 
-       /* if this is patented, then maybe we could install
-          a function in the constant pool, to do the right thing */
-
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes) 
              {
              case 1:
-               *base_pc = op_putstatic_1;
-               break;
+               {
+                 jint value = POPI();
+                 *(jbyte*) (field->u.addr) = value;
+                 break;
+               }
 
              case 2:
-               *base_pc = op_putstatic_2;
-               break;
-               
+               {
+                 jint value = POPI();
+                 *(jchar*) (field->u.addr) = value;
+                 break;
+               }
+
              case 4:
-               *base_pc = op_putstatic_4;
-               break;
-               
+               {
+                 jint value = POPI();
+                 *(jint*) (field->u.addr) = value;
+                 break;
+               }
+
              case 8:
-               *base_pc = op_putstatic_8;
-               break;
+               {
+                 jlong value = POPL();
+                 *(jlong*) (field->u.addr) = value;
+                 break;
+               }
              }
          }
        else
          {
-           *base_pc = op_putstatic_a;
+           jobject value = POPA();
+           *(jobject*) (field->u.addr) = value;
          }
-
-       // do the instruction again!
-       pc = base_pc;
       }
-      goto next_insn;
+      NEXT_INSN;
 
 
-    case op_putfield:
+     insn_putfield:
+      SAVE_PC;
       {
-       unsigned char* base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
        jclass type = field->type;
 
-       if ((field->flags & STATIC) != 0)
+       if ((field->flags & Modifier::STATIC) != 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field is static"));
 
+       jint field_offset = field->u.boffset;
+       if (field_offset > 0xffff)
+         throw new java::lang::VirtualMachineError;
+
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes) 
              {
              case 1:
-               *base_pc = op_putfield_1;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jbyte*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 2:
-               *base_pc = op_putfield_2;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jchar*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 4:
-               *base_pc = op_putfield_4;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jint*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 8:
-               *base_pc = op_putfield_8;
-               break;
+               {
+                 jlong   value = POPL();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jlong*) ((char*)obj + field_offset) = value;
+                 break;
+               }
              }
          }
        else
          {
-           *base_pc = op_putfield_a;
+           jobject value = POPA();
+           jobject obj   = POPA();
+           NULLCHECK(obj);
+           *(jobject*) ((char*)obj + field_offset) = value;
          }
-
-       if (field->u.boffset > 0xffff)
-         JvThrow (new java::lang::VirtualMachineError);
-
-       base_pc[1] = (field->u.boffset>>8) & 0xff;
-       base_pc[2] = field->u.boffset & 0xff;
-
-       // do the instruction again!
-       pc = base_pc;
-      }
-      goto next_insn;
-
-
-    case op_getfield_1:
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jbyte*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
-
-    case op_getfield_2s:
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jshort*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
-
-    case op_getfield_2u:
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jchar*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
-
-    case op_getfield_8:
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHL(*(jlong*) ((char*)obj + field_offset));
-      }
-      goto next_insn;
-
-    case op_getstatic_1:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI (*(jbyte*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_getstatic_2s:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jshort*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_getstatic_2u:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jchar*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_getstatic_4:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jint*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_getstatic_8:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHL(*(jlong*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_getstatic_a:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHA(*(jobject*) (field->u.addr));
-      }
-      goto next_insn;
-
-    case op_putfield_1:
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jbyte*) ((char*)obj + field_offset) = value;
-      }
-      goto next_insn;
-
-    case op_putfield_2:
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jchar*) ((char*)obj + field_offset) = value;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_putfield_4:
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jint*) ((char*)obj + field_offset) = value;
-      }
-      goto next_insn;
-
-    case op_putfield_8:
-      {
-       jlong   value = POPL();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jlong*) ((char*)obj + field_offset) = value;
-      }
-      goto next_insn;
-
-    case op_putfield_a:
-      {
-       jobject value = POPA();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jobject*) ((char*)obj + field_offset) = value;
-      }
-      goto next_insn;
-
-    case op_putstatic_1:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jbyte*) (field->u.addr) = value;
-      }
-      goto next_insn;
-
-    case op_putstatic_2:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jchar*) (field->u.addr) = value;
-      }
-      goto next_insn;
-
-    case op_putstatic_4:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jint*) (field->u.addr) = value;
-      }
-      goto next_insn;
-
-    case op_putstatic_8:
-      {
-       jlong    value = POPL();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jlong*) (field->u.addr) = value;
-      }
-      goto next_insn;
-
-    case op_putstatic_a:
-      {
-       jobject value = POPA();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jobject*) (field->u.addr) = value;
-      }
-      goto next_insn;
-
-    case op_invokespecial:
+     insn_invokespecial:
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
 
        rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
        sp -= rmeth->stack_item_count;
-       
-       NULLCHECK(sp[0]);
 
-       fun = (void (*) (...))rmeth->method->ncode;
+       NULLCHECK (sp[0].o);
+
+       fun = (void (*)()) rmeth->method->ncode;
       }
       goto perform_invoke;
 
-    case op_invokestatic:
+     insn_invokestatic:
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
 
        rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
        sp -= rmeth->stack_item_count;
-       
+
        _Jv_InitClass (rmeth->klass);
-       fun = (void (*) (...))rmeth->method->ncode;
+       fun = (void (*)()) rmeth->method->ncode;
       }
       goto perform_invoke;
 
-    case op_invokeinterface:
+     insn_invokeinterface:
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
 
@@ -2118,11 +2179,12 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
        sp -= rmeth->stack_item_count;
-       NULLCHECK(sp[0]);
-       
+
        jobject rcv = sp[0].o;
 
-       fun = (void (*) (...))
+       NULLCHECK (rcv);
+
+       fun = (void (*)())
          _Jv_LookupInterfaceMethod (rcv->getClass (),
                                     rmeth->method->name,
                                     rmeth->method->signature);
@@ -2130,7 +2192,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       goto perform_invoke;
 
 
-    case op_new:
+     insn_new:
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
        jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
@@ -2138,18 +2201,20 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
        PUSHA (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_newarray:
+     insn_newarray:
+      SAVE_PC;
       {
        int atype = get1u (pc++);
        int size  = POPI();
        jobject result = _Jv_NewArray (atype, size);
        PUSHA (result);
       }
-      goto next_insn;
-      
-    case op_anewarray:
+      NEXT_INSN;
+
+     insn_anewarray:
+      SAVE_PC;
       {
        int index = get2u (pc); pc += 2;
        jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
@@ -2158,24 +2223,26 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        jobject result = _Jv_NewObjectArray (size, klass, 0);
        PUSHA (result);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_arraylength:
+     insn_arraylength:
+      SAVE_PC;
       {
        __JArray *arr = (__JArray*)POPA();
        PUSHI (arr->length);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_athrow:
+     insn_athrow:
+      SAVE_PC;
       {
        jobject value = POPA();
-       TIME_SUSPEND;
-       JvThrow (value);
+       throw static_cast<jthrowable>(value);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_checkcast:
+     insn_checkcast:
+      SAVE_PC;
       {
        jobject value = POPA();
        jint index = get2u (pc); pc += 2;
@@ -2183,41 +2250,42 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        if (value != NULL && ! to->isInstance (value))
          {
-           TIME_SUSPEND;
-           JvThrow (new java::lang::ClassCastException
-                    (to->getName()));
+           throw new java::lang::ClassCastException (to->getName());
          }
 
        PUSHA (value);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_instanceof:
+     insn_instanceof:
+      SAVE_PC;
       {
        jobject value = POPA();
        jint index = get2u (pc); pc += 2;
        jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
        PUSHI (to->isInstance (value));
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_monitorenter:
+     insn_monitorenter:
+      SAVE_PC;
       {
        jobject value = POPA();
        NULLCHECK(value);
        _Jv_MonitorEnter (value);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_monitorexit:
+     insn_monitorexit:
+      SAVE_PC;
       {
        jobject value = POPA();
        NULLCHECK(value);
        _Jv_MonitorExit (value);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifnull:
+     insn_ifnull:
       {
        unsigned char* base_pc = pc-1;
        jint offset = get2s (pc); pc += 2;
@@ -2225,9 +2293,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        if (val == NULL)
          pc = base_pc+offset;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_ifnonnull:
+     insn_ifnonnull:
       {
        unsigned char* base_pc = pc-1;
        jint offset = get2s (pc); pc += 2;
@@ -2235,9 +2303,10 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        if (val != NULL)
          pc = base_pc+offset;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_wide:
+     insn_wide:
+      SAVE_PC;
       {
        jint the_mod_op = get1u (pc++);
        jint wide       = get2u (pc); pc += 2;
@@ -2246,43 +2315,43 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
          {
          case op_istore:
            STOREI (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_fstore:
            STOREF (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_astore:
            STOREA (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_lload:
            LOADL (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_dload:
            LOADD (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_iload:
            LOADI (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_aload:
            LOADA (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_lstore:
            STOREL (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_dstore:
            STORED (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_ret:
            pc = (unsigned char*) PEEKA (wide);
-           goto next_insn;
+           NEXT_INSN;
 
          case op_iinc:
            {
@@ -2290,7 +2359,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
              jint value = PEEKI (wide);
              POKEI (wide, value+amount);
            }
-           goto next_insn;
+           NEXT_INSN;
 
          default:
            throw_internal_error ("illegal bytecode modified by wide");
@@ -2298,7 +2367,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
       }
 
-    case op_multianewarray:
+     insn_multianewarray:
+      SAVE_PC;
       {
        int kind_index = get2u (pc); pc += 2;
        int dim        = get1u (pc); pc += 1;
@@ -2306,57 +2376,51 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        jclass type    
          = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
        _Jv_InitClass (type);
-       jint *sizes    = (jint*) alloca (sizeof (jint)*dim);
+       jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
 
        for (int i = dim - 1; i >= 0; i--)
          {
            sizes[i] = POPI ();
          }
-       
+
        jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-       
+
        PUSHA (res);
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_goto_w:
+     insn_goto_w:
       {
        unsigned char* base_pc = pc-1;
        int offset = get4 (pc); pc += 4;
        pc = base_pc+offset;
       }
-      goto next_insn;
+      NEXT_INSN;
 
-    case op_jsr_w:
+     insn_jsr_w:
       {
        unsigned char* base_pc = pc-1;
        int offset = get4 (pc); pc += 4;
        PUSHA((jobject)pc);
        pc = base_pc+offset;
       }
-      goto next_insn;
-
-    default:
-      throw_internal_error ("opcode not implemented");
-
-    }
-  goto next_insn;
+      NEXT_INSN;
 }
 
 
 static void
 throw_internal_error (char *msg)
 {
-  JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
 }
 
 static void 
 throw_incompatible_class_change_error (jstring msg)
 {
-  JvThrow (new java::lang::IncompatibleClassChangeError (msg));
+  throw new java::lang::IncompatibleClassChangeError (msg);
 }
 
-#if !HANDLE_SEGV
+#ifndef HANDLE_SEGV
 static java::lang::NullPointerException *null_pointer_exc;
 static void 
 throw_null_pointer_exception ()
@@ -2364,74 +2428,8 @@ throw_null_pointer_exception ()
   if (null_pointer_exc == NULL)
     null_pointer_exc = new java::lang::NullPointerException;
 
-  JvThrow (null_pointer_exc);
-}
-#endif
-
-#if !HANDLE_FPE
-static java::lang::ArithmeticException *arithmetic_exc;
-static void 
-throw_arithmetic_exception ()
-{
-  if (arithmetic_exc == NULL)
-    arithmetic_exc = new java::lang::ArithmeticException
-      (JvNewStringLatin1 ("/ by zero"));
-
-  JvThrow (arithmetic_exc);
-}
-#endif
-
-void
-jvdump(jobject o)
-{
-  _Jv_InterpMethod::dump_object(o);
+  throw null_pointer_exc;
 }
-
-/* FIXME: This is not finished! */
-void
-_Jv_InterpMethod::dump_object(jobject o)
-{
-  java::io::PrintStream *out = java::lang::System::out;
-
-  if (o == NULL)
-    {
-      out->println (JvNewStringLatin1 ("<null>"));
-      return;
-    }
-
-  jclass klass = o->getClass ();
-
-  out->print (klass->getName ());
-  out->print (JvNewStringLatin1 ("@0x"));
-  out->print (java::lang::Integer::toHexString ((jint)o));
-  out->print (JvNewStringLatin1 ("{"));
-#if 0
-  while (klass && klass != &ObjectClass)
-    {
-      _Jv_Field *fields = klass->fields;
-      int max           = klass->field_count;
-      
-      for (int i = 0; i < max; ++i)
-       {
-         out->print (_Jv_NewStringUTF (field->name->data));
-         out->print (JvNewStringLatin1 ("="));
-
-         if (JvFieldIsRef (field))
-           {
-             if (field->flags & STATIC)
-               out->print (JvGetSt)
-           }
-         field = field->getNextInstanceField ();
-
-         if (i+1 < max && klass->getSuperclass () != null)
-           out->print (JvNewStringLatin1 ("; "));
-       }
-
-      klass = klass->getSuperclass();
-    }
 #endif
-  out->print (JvNewStringLatin1 ("}\n"));
-
-}
 
 #endif // INTERPRETER