OSDN Git Service

581606e4047c9c963d3cc41c61392e685eeca764
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999  Cygnus Solutions
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
13 #include <config.h>
14
15 #pragma implementation "java-interp.h"
16
17 #include <jvm.h>
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/StringBuffer.h>
25 #include <java/io/PrintStream.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/ClassCastException.h>
29 #include <java/lang/VirtualMachineError.h>
30 #include <java/lang/InternalError.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/ArithmeticException.h>
33 #include <java/lang/IncompatibleClassChangeError.h>
34 #include <java-insns.h>
35 #include <java-signal.h>
36
37 #ifndef INTERPRETER
38
39 #include <gnu/gcj/runtime/MethodInvocation.h>
40
41 /* This should never happen. */
42 void 
43 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
44                                                 gnu::gcj::RawData *)
45 {
46   JvFail ("no interpreter");
47 }
48
49 #else
50
51 #define ClassError _CL_Q34java4lang5Error
52 extern java::lang::Class ClassError;
53
54 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
55
56 static void throw_internal_error (char *msg)
57   __attribute__ ((__noreturn__));
58 static void throw_incompatible_class_change_error (jstring msg)
59   __attribute__ ((__noreturn__));
60 #if !HANDLE_SEGV
61 static void throw_null_pointer_exception ()
62   __attribute__ ((__noreturn__));
63 #endif
64 #if !HANDLE_FPE
65 static void throw_arithmetic_exception ()
66   __attribute__ ((__noreturn__));
67 #endif
68
69
70 static inline void dupx (_Jv_word *sp, int n, int x)
71 {
72   // first "slide" n+x elements n to the right
73   int top = n-1;
74   for (int i = 0; i < n+x; i++)
75     {
76       sp[(top-i)] = sp[(top-i)-n];
77     }
78   
79   // next, copy the n top elements, n+x down
80   for (int i = 0; i < n; i++)
81     {
82       sp[top-(n+x)-i] = sp[top-i];
83     }
84   
85 };
86
87
88 #define PUSHA(V)  (sp++)->o = (V)
89 #define PUSHI(V)  (sp++)->i = (V)
90 #define PUSHF(V)  (sp++)->f = (V)
91 #define PUSHL(V)  ({ _Jv_word2 w2; w2.l=(V); \
92                      (sp++)->ia[0] = w2.ia[0]; \
93                      (sp++)->ia[0] = w2.ia[1]; })
94 #define PUSHD(V)  ({ _Jv_word2 w2; w2.d=(V); \
95                      (sp++)->ia[0] = w2.ia[0]; \
96                      (sp++)->ia[0] = w2.ia[1]; })
97
98 #define POPA()    ((--sp)->o)
99 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
100 #define POPF()    ((jfloat) (--sp)->f)
101 #define POPL()    ({ _Jv_word2 w2; \
102                      w2.ia[1] = (--sp)->ia[0]; \
103                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
104 #define POPD()    ({ _Jv_word2 w2; \
105                      w2.ia[1] = (--sp)->ia[0]; \
106                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
107
108 #define LOADA(I)  (sp++)->o = locals[I].o
109 #define LOADI(I)  (sp++)->i = locals[I].i
110 #define LOADF(I)  (sp++)->f = locals[I].f
111 #define LOADL(I)  ({ jint __idx = (I); \
112     (sp++)->ia[0] = locals[__idx].ia[0]; \
113     (sp++)->ia[0] = locals[__idx+1].ia[0]; \
114  })
115 #define LOADD(I)  LOADL(I)
116
117
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #define STOREL(I) ({ jint __idx = (I); \
122     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
123     locals[__idx].ia[0] = (--sp)->ia[0]; \
124  })
125 #define STORED(I) STOREL(I)
126
127 #define PEEKI(I)  (locals+(I))->i
128 #define PEEKA(I)  (locals+(I))->o
129
130 #define POKEI(I,V)  ((locals+(I))->i = (V))
131
132
133 #define BINOPI(OP) { \
134    jint value2 = POPI(); \
135    jint value1 = POPI(); \
136    PUSHI(value1 OP value2); \
137 }
138
139 #define BINOPF(OP) { \
140    jfloat value2 = POPF(); \
141    jfloat value1 = POPF(); \
142    PUSHF(value1 OP value2); \
143 }
144
145 #define BINOPL(OP) { \
146    jlong value2 = POPL(); \
147    jlong value1 = POPL(); \
148    PUSHL(value1 OP value2); \
149 }
150
151 #define BINOPD(OP) { \
152    jdouble value2 = POPD(); \
153    jdouble value1 = POPD(); \
154    PUSHD(value1 OP value2); \
155 }
156
157 static inline jint get1s(unsigned char* loc) {
158   return *(signed char*)loc;
159 }
160
161 static inline jint get1u(unsigned char* loc) {
162   return *loc;
163 }
164
165 static inline jint get2s(unsigned char* loc) {
166   return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
167 }
168
169 static inline jint get2u(unsigned char* loc) {
170   return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
171 }
172
173 static jint get4(unsigned char* loc) {
174   return (((jint)(loc[0])) << 24) 
175        | (((jint)(loc[1])) << 16) 
176        | (((jint)(loc[2])) << 8) 
177        | (((jint)(loc[3])) << 0);
178 }
179
180
181 #if HANDLE_SEGV
182 #define NULLCHECK(X) 
183 #else
184 #define NULLCHECK(X) \
185   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
186 #endif
187
188 #if HANDLE_FPE
189 #define ZEROCHECK(X)
190 #else
191 #define ZEROCHECK(X) \
192   do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
193 #endif
194
195 // this method starts the actual running of the method.  It is inlined
196 // in three different variants in the static methods run_normal,
197 // run_sync_object and run_sync_class (see below).  Those static methods
198 // are installed directly in the stub for this method (by
199 // _Jv_InterpMethod::ncode, in resolve.cc).
200
201 inline jobject
202 _Jv_InterpMethod::run (ffi_cif* cif,
203                        void *retp,
204                        ffi_raw *args,
205                        _Jv_InterpMethodInvocation *inv)
206 {
207   inv->running  = this;
208   inv->pc       = bytecode ();
209   inv->sp       = inv->stack_base ();
210   _Jv_word *locals = inv->local_base ();
211
212   /* Go straight at it!  the ffi raw format matches the internal
213      stack representation exactly.  At leat, that's the idea.
214   */
215   memcpy ((void*) locals, (void*) args, args_raw_size);
216
217  next_segment:
218   /* this will call the method _Jv_InterpMethod::continue0, see below */
219   jobject ex = 
220     gnu::gcj::runtime::MethodInvocation::continue0
221     ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
222
223   if (ex == 0)                  // no exception...
224     {
225       /* define sp locally, so the POP? macros will pick it up */
226       _Jv_word *sp = inv->sp;
227       int rtype = cif->rtype->type;
228
229       if (rtype == FFI_TYPE_POINTER)
230         {
231           jobject r = POPA();
232           *(jobject*) retp = r;
233           return 0;
234         }
235       else if (rtype == FFI_TYPE_SINT32)
236         {
237           jint r = POPI();
238           *(jint*)retp = r;
239           return 0;
240         }
241       else if (rtype == FFI_TYPE_VOID)
242         {
243           return 0;
244         }
245       else switch (rtype)
246         {
247         case FFI_TYPE_FLOAT:
248           {
249             jfloat r = POPF();
250             *(jfloat*)retp = r;
251             return 0;
252           }
253       
254         case FFI_TYPE_DOUBLE:
255           {
256             jdouble r = POPD();
257             *(jdouble*)retp = r;
258             return 0;
259           }
260
261         case FFI_TYPE_UINT8:
262         case FFI_TYPE_UINT16:
263         case FFI_TYPE_UINT32:
264         case FFI_TYPE_SINT8:
265         case FFI_TYPE_SINT16:
266           {
267             jint r = POPI();
268             *(jint*)retp = r;
269             return 0;
270           }
271       
272         case FFI_TYPE_SINT64:
273           {
274             jlong r = POPL();
275             *(jlong*)retp = r;
276             return 0;
277           }
278         
279         default:
280           throw_internal_error ("unknown return type");
281         }
282
283     }
284
285   /** handle an exception */
286   if ( find_exception (ex, inv) )
287     goto next_segment;
288
289   java::lang::System::out->println 
290     (_Jv_NewStringUTF (self->name->data));
291
292   return ex;
293 }
294
295 bool _Jv_InterpMethod::find_exception (jobject ex,
296                                        _Jv_InterpMethodInvocation *inv)
297 {
298   int logical_pc = inv->pc - bytecode ();
299   _Jv_InterpException *exc = exceptions ();
300   jclass exc_class = ex->getClass ();
301
302   for (int i = 0; i < exc_count; i++)
303     {
304       if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
305         {       
306           jclass handler;
307
308           if (exc[i].handler_type != 0)
309             handler = (_Jv_ResolvePoolEntry (defining_class, 
310                                              exc[i].handler_type)).clazz;
311           else
312             handler = NULL;
313           
314           if (handler==NULL || handler->isAssignableFrom (exc_class))
315             {
316               inv->pc = bytecode () + exc[i].handler_pc;
317               inv->sp = inv->stack_base (); // reset stack
318               (inv->sp++)->o = ex; // push exception
319               return true;
320             }
321         }
322     }
323   return false;
324 }
325
326 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327                                    void* ret,
328                                    ffi_raw * args,
329                                    void* __this)
330 {
331   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
332
333   // we do the alloca of the method invocation here, to allow the method
334   // "run" ro be inlined.  Otherwise gcc will ignore the inline directive.
335   int storage_size = _this->max_stack+_this->max_locals;
336   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
337     alloca (sizeof (_Jv_InterpMethodInvocation)
338             + storage_size * sizeof (_Jv_word));
339
340   jobject ex = _this->run (cif, ret, args, inv);
341   if (ex != 0) _Jv_Throw (ex);
342 }
343
344 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345                                          void* ret,
346                                          ffi_raw * args,
347                                          void* __this)
348 {
349   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
350   jobject rcv = (jobject)args[0].ptr;
351
352   int storage_size = _this->max_stack+_this->max_locals;
353   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
354     alloca (sizeof (_Jv_InterpMethodInvocation)
355             + storage_size * sizeof (_Jv_word));
356
357   _Jv_MonitorEnter (rcv);
358   jobject ex = _this->run (cif, ret, args, inv);
359   _Jv_MonitorExit (rcv);
360
361   if (ex != 0) _Jv_Throw (ex);
362 }
363
364 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365                                         void* ret,
366                                         ffi_raw * args,
367                                         void* __this)
368 {
369   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
370   jclass  sync = _this->defining_class;
371
372   int storage_size = _this->max_stack+_this->max_locals;
373   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
374     alloca (sizeof (_Jv_InterpMethodInvocation)
375             + storage_size * sizeof (_Jv_word));
376
377   _Jv_MonitorEnter (sync);
378   jobject ex = _this->run (cif, ret, args, inv);
379   _Jv_MonitorExit (sync);
380
381   if (ex != 0) _Jv_Throw (ex);
382 }
383
384 /* this is the exception handler hack, for the interpreter */
385 void 
386 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
387                                                 gnu::gcj::RawData *inv)
388 {
389   _Jv_InterpMethod           *meth0 = (_Jv_InterpMethod*)meth;
390   _Jv_InterpMethodInvocation *inv0  = (_Jv_InterpMethodInvocation*)inv;
391   meth0->continue1 (inv0);
392 }
393
394 /*
395   This proceeds execution, as designated in "inv".  If an exception
396   happens, then it is simply thrown, and handled in Java.  Thus, the pc
397   needs to be stored in the inv->pc at all times, so we can figure
398   out which handler (if any) to invoke.
399
400   One design issue, which I have not completely considered, is if it
401   should be possible to have interpreted classes linked in!  Seldom used
402   (or non-critical) classes could reasonably be interpreted.  
403 */
404
405
406 #ifdef __i386__
407 #define PC_REGISTER_ASM  asm("%esi")
408 #else
409 #define PC_REGISTER_ASM
410 #endif
411
412 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
413 {
414   using namespace java::lang::reflect;
415
416   register _Jv_word      *sp                  = inv->sp;
417   register unsigned char *pc PC_REGISTER_ASM  = inv->pc;
418   _Jv_word               *locals              = inv->local_base ();
419
420   _Jv_word *pool_data   = defining_class->constants.data;
421   
422   /* these two are used in the invokeXXX instructions */
423   void (*fun)(...);
424   _Jv_ResolvedMethod* rmeth;
425
426 #define INSN_LABEL(op) &&insn_##op
427 #define GOTO_INSN(op) goto *(insn_target[op])
428
429   static const void *const insn_target[] = 
430   {
431     INSN_LABEL(nop),
432     INSN_LABEL(aconst_null),
433     INSN_LABEL(iconst_m1),
434     INSN_LABEL(iconst_0),
435     INSN_LABEL(iconst_1),
436     INSN_LABEL(iconst_2),
437     INSN_LABEL(iconst_3),
438     INSN_LABEL(iconst_4),
439     INSN_LABEL(iconst_5),
440     INSN_LABEL(lconst_0),
441     INSN_LABEL(lconst_1),
442     INSN_LABEL(fconst_0),
443     INSN_LABEL(fconst_1),
444     INSN_LABEL(fconst_2),
445     INSN_LABEL(dconst_0),
446     INSN_LABEL(dconst_1),
447     INSN_LABEL(bipush),
448     INSN_LABEL(sipush),
449     INSN_LABEL(ldc),
450     INSN_LABEL(ldc_w),
451     INSN_LABEL(ldc2_w),
452     INSN_LABEL(iload),
453     INSN_LABEL(lload),
454     INSN_LABEL(fload),
455     INSN_LABEL(dload),
456     INSN_LABEL(aload),
457     INSN_LABEL(iload_0),
458     INSN_LABEL(iload_1),
459     INSN_LABEL(iload_2),
460     INSN_LABEL(iload_3),
461     INSN_LABEL(lload_0),
462     INSN_LABEL(lload_1),
463     INSN_LABEL(lload_2),
464     INSN_LABEL(lload_3),
465     INSN_LABEL(fload_0),
466     INSN_LABEL(fload_1),
467     INSN_LABEL(fload_2),
468     INSN_LABEL(fload_3),
469     INSN_LABEL(dload_0),
470     INSN_LABEL(dload_1),
471     INSN_LABEL(dload_2),
472     INSN_LABEL(dload_3),
473     INSN_LABEL(aload_0),
474     INSN_LABEL(aload_1),
475     INSN_LABEL(aload_2),
476     INSN_LABEL(aload_3),
477     INSN_LABEL(iaload),
478     INSN_LABEL(laload),
479     INSN_LABEL(faload),
480     INSN_LABEL(daload),
481     INSN_LABEL(aaload),
482     INSN_LABEL(baload),
483     INSN_LABEL(caload),
484     INSN_LABEL(saload),
485     INSN_LABEL(istore),
486     INSN_LABEL(lstore),
487     INSN_LABEL(fstore),
488     INSN_LABEL(dstore),
489     INSN_LABEL(astore),
490     INSN_LABEL(istore_0),
491     INSN_LABEL(istore_1),
492     INSN_LABEL(istore_2),
493     INSN_LABEL(istore_3),
494     INSN_LABEL(lstore_0),
495     INSN_LABEL(lstore_1),
496     INSN_LABEL(lstore_2),
497     INSN_LABEL(lstore_3),
498     INSN_LABEL(fstore_0),
499     INSN_LABEL(fstore_1),
500     INSN_LABEL(fstore_2),
501     INSN_LABEL(fstore_3),
502     INSN_LABEL(dstore_0),
503     INSN_LABEL(dstore_1),
504     INSN_LABEL(dstore_2),
505     INSN_LABEL(dstore_3),
506     INSN_LABEL(astore_0),
507     INSN_LABEL(astore_1),
508     INSN_LABEL(astore_2),
509     INSN_LABEL(astore_3),
510     INSN_LABEL(iastore),
511     INSN_LABEL(lastore),
512     INSN_LABEL(fastore),
513     INSN_LABEL(dastore),
514     INSN_LABEL(aastore),
515     INSN_LABEL(bastore),
516     INSN_LABEL(castore),
517     INSN_LABEL(sastore),
518     INSN_LABEL(pop),
519     INSN_LABEL(pop2),
520     INSN_LABEL(dup),
521     INSN_LABEL(dup_x1),
522     INSN_LABEL(dup_x2),
523     INSN_LABEL(dup2),
524     INSN_LABEL(dup2_x1),
525     INSN_LABEL(dup2_x2),
526     INSN_LABEL(swap),
527     INSN_LABEL(iadd),
528     INSN_LABEL(ladd),
529     INSN_LABEL(fadd),
530     INSN_LABEL(dadd),
531     INSN_LABEL(isub),
532     INSN_LABEL(lsub),
533     INSN_LABEL(fsub),
534     INSN_LABEL(dsub),
535     INSN_LABEL(imul),
536     INSN_LABEL(lmul),
537     INSN_LABEL(fmul),
538     INSN_LABEL(dmul),
539     INSN_LABEL(idiv),
540     INSN_LABEL(ldiv),
541     INSN_LABEL(fdiv),
542     INSN_LABEL(ddiv),
543     INSN_LABEL(irem),
544     INSN_LABEL(lrem),
545     INSN_LABEL(frem),
546     INSN_LABEL(drem),
547     INSN_LABEL(ineg),
548     INSN_LABEL(lneg),
549     INSN_LABEL(fneg),
550     INSN_LABEL(dneg),
551     INSN_LABEL(ishl),
552     INSN_LABEL(lshl),
553     INSN_LABEL(ishr),
554     INSN_LABEL(lshr),
555     INSN_LABEL(iushr),
556     INSN_LABEL(lushr),
557     INSN_LABEL(iand),
558     INSN_LABEL(land),
559     INSN_LABEL(ior),
560     INSN_LABEL(lor),
561     INSN_LABEL(ixor),
562     INSN_LABEL(lxor),
563     INSN_LABEL(iinc),
564     INSN_LABEL(i2l),
565     INSN_LABEL(i2f),
566     INSN_LABEL(i2d),
567     INSN_LABEL(l2i),
568     INSN_LABEL(l2f),
569     INSN_LABEL(l2d),
570     INSN_LABEL(f2i),
571     INSN_LABEL(f2l),
572     INSN_LABEL(f2d),
573     INSN_LABEL(d2i),
574     INSN_LABEL(d2l),
575     INSN_LABEL(d2f),
576     INSN_LABEL(i2b),
577     INSN_LABEL(i2c),
578     INSN_LABEL(i2s),
579     INSN_LABEL(lcmp),
580     INSN_LABEL(fcmpl),
581     INSN_LABEL(fcmpg),
582     INSN_LABEL(dcmpl),
583     INSN_LABEL(dcmpg),
584     INSN_LABEL(ifeq),
585     INSN_LABEL(ifne),
586     INSN_LABEL(iflt),
587     INSN_LABEL(ifge),
588     INSN_LABEL(ifgt),
589     INSN_LABEL(ifle),
590     INSN_LABEL(if_icmpeq),
591     INSN_LABEL(if_icmpne),
592     INSN_LABEL(if_icmplt),
593     INSN_LABEL(if_icmpge),
594     INSN_LABEL(if_icmpgt),
595     INSN_LABEL(if_icmple),
596     INSN_LABEL(if_acmpeq),
597     INSN_LABEL(if_acmpne),
598     INSN_LABEL(goto), 
599     INSN_LABEL(jsr),
600     INSN_LABEL(ret),
601     INSN_LABEL(tableswitch),
602     INSN_LABEL(lookupswitch),
603     INSN_LABEL(ireturn),
604     INSN_LABEL(lreturn),
605     INSN_LABEL(freturn),
606     INSN_LABEL(dreturn),
607     INSN_LABEL(areturn),
608     INSN_LABEL(return),
609     INSN_LABEL(getstatic),
610     INSN_LABEL(putstatic),
611     INSN_LABEL(getfield),
612     INSN_LABEL(putfield),
613     INSN_LABEL(invokevirtual),
614     INSN_LABEL(invokespecial),
615     INSN_LABEL(invokestatic),
616     INSN_LABEL(invokeinterface),
617     0, /* op_xxxunusedxxx1, */
618     INSN_LABEL(new),
619     INSN_LABEL(newarray),
620     INSN_LABEL(anewarray),
621     INSN_LABEL(arraylength),
622     INSN_LABEL(athrow),
623     INSN_LABEL(checkcast),
624     INSN_LABEL(instanceof),
625     INSN_LABEL(monitorenter),
626     INSN_LABEL(monitorexit),
627     INSN_LABEL(wide),
628     INSN_LABEL(multianewarray),
629     INSN_LABEL(ifnull),
630     INSN_LABEL(ifnonnull),
631     INSN_LABEL(goto_w),
632     INSN_LABEL(jsr_w),
633
634     INSN_LABEL(putfield_1),
635     INSN_LABEL(putfield_2),
636     INSN_LABEL(putfield_4),
637     INSN_LABEL(putfield_8),
638     INSN_LABEL(putfield_a),
639
640     INSN_LABEL(putstatic_1),
641     INSN_LABEL(putstatic_2),
642     INSN_LABEL(putstatic_4),
643     INSN_LABEL(putstatic_8),
644     INSN_LABEL(putstatic_a),
645
646     INSN_LABEL(getfield_1),
647     INSN_LABEL(getfield_2s),
648     INSN_LABEL(getfield_2u),
649     INSN_LABEL(getfield_4),
650     INSN_LABEL(getfield_8),
651     INSN_LABEL(getfield_a),
652
653     INSN_LABEL(getstatic_1),
654     INSN_LABEL(getstatic_2s),
655     INSN_LABEL(getstatic_2u),
656     INSN_LABEL(getstatic_4),
657     INSN_LABEL(getstatic_8),
658     INSN_LABEL(getstatic_a),
659   };
660
661 #define SAVE_PC   inv->pc = pc-1
662
663   /* If the macro INLINE_SWITCH is not defined, then the main loop
664      operates as one big (normal) switch statement.  If it is defined,
665      then the case selection is performed `inline' in the end of the
666      code for each case.  The latter saves a native branch instruction
667      for each java-instruction, but expands the code size somewhat.
668
669      NOTE: On i386 defining INLINE_SWITCH improves over all
670      performance approximately seven percent, but it may be different
671      for other machines.  At some point, this may be made into a proper
672      configuration parameter.  */
673
674 #define INLINE_SWITCH 
675
676 #ifdef  INLINE_SWITCH
677
678 #define NEXT_INSN GOTO_INSN(*pc++)
679   NEXT_INSN;
680 #else
681
682 #define NEXT_INSN goto next_insn
683
684  next_insn:
685   GOTO_INSN (*pc++);
686
687 #endif
688
689   /* The first few instructions here are ordered according to their
690      frequency, in the hope that this will improve code locality a
691      little.  */
692
693      insn_aload_0:              // 0x2a
694       LOADA(0);
695       NEXT_INSN;
696
697      insn_iload:                // 0x15
698       LOADI (get1u (pc++));
699       NEXT_INSN;
700
701      insn_getfield_4:           // 0xd8
702       SAVE_PC;
703       {
704         jobject obj   = POPA();
705         NULLCHECK(obj);
706         jint field_offset = get2u (pc); pc += 2;
707         PUSHI (*(jint*) ((char*)obj + field_offset));
708       }
709       NEXT_INSN;
710
711      insn_iload_1:              // 0x1b
712       LOADI (1);
713       NEXT_INSN;
714
715      insn_getfield_a:           // 0xda
716       SAVE_PC;
717       {
718         jobject obj   = POPA();
719         NULLCHECK(obj);
720         jint field_offset = get2u (pc); pc += 2;
721         PUSHA(*(jobject*) ((char*)obj + field_offset));
722       }
723       NEXT_INSN;
724
725      insn_invokevirtual:        // 0xb6
726       SAVE_PC;
727       {
728         int index = get2u (pc); pc += 2;
729
730         /* _Jv_ResolvePoolEntry returns immediately if the value already
731          * is resolved.  If we want to clutter up the code here to gain
732          * a little performance, then we can check the corresponding bit
733          * JV_CONSTANT_ResolvedFlag in the tag directly.  For now, I
734          * don't think it is worth it.  */
735
736         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
737
738         sp -= rmeth->stack_item_count;
739         NULLCHECK(sp[0]);
740
741         if (rmeth->vtable_index == -1)
742           {
743             // final methods do not appear in the vtable,
744             // if it does not appear in the superclass.
745             fun = (void (*) (...)) rmeth->method->ncode;
746           }
747         else
748           {
749             jobject rcv = sp[0].o;
750             _Jv_VTable *table = *(_Jv_VTable**)rcv;
751             fun = (void (*) (...))table->method[rmeth->vtable_index];
752           }
753       }
754       goto perform_invoke;
755
756      perform_invoke:
757       {
758         /* here goes the magic again... */
759         ffi_cif *cif = &rmeth->cif;
760         ffi_raw *raw = (ffi_raw*) sp;
761
762         jdouble rvalue;
763
764         ffi_raw_call (cif, fun, (void*)&rvalue, raw);
765
766         int rtype = cif->rtype->type;
767
768         /* the likelyhood of object, int, or void return is very high,
769          * so those are checked before the switch */
770         if (rtype == FFI_TYPE_POINTER)
771           {
772             PUSHA (*(jobject*)&rvalue);
773           }
774         else if (rtype == FFI_TYPE_SINT32)
775           {
776             PUSHI (*(jint*)&rvalue);
777           }
778         else if (rtype == FFI_TYPE_VOID)
779           {
780             /* skip */
781           }
782         else switch (rtype) 
783           {
784           case FFI_TYPE_SINT8:
785             {
786               jbyte value = (*(jint*)&rvalue) & 0xff;
787               PUSHI (value);
788             }
789             break;
790
791           case FFI_TYPE_SINT16:
792             {
793               jshort value = (*(jint*)&rvalue) & 0xffff;
794               PUSHI (value);
795             }
796             break;
797
798           case FFI_TYPE_UINT16:
799             {
800               jint value = (*(jint*)&rvalue) & 0xffff;
801               PUSHI (value);
802             }
803             break;
804
805           case FFI_TYPE_FLOAT:
806             PUSHF (*(jfloat*)&rvalue);
807             break;
808
809           case FFI_TYPE_DOUBLE:
810             PUSHD (rvalue);
811             break;
812
813           case FFI_TYPE_SINT64:
814             PUSHL (*(jlong*)&rvalue);
815             break;
816
817           default:
818             throw_internal_error ("unknown return type in invokeXXX");
819           }
820
821       }
822       NEXT_INSN;
823
824
825      insn_nop:
826       NEXT_INSN;
827
828      insn_aconst_null:
829       PUSHA (NULL);
830       NEXT_INSN;
831
832      insn_iconst_m1:
833       PUSHI (-1);
834       NEXT_INSN;
835
836      insn_iconst_0:
837       PUSHI (0);
838       NEXT_INSN;
839
840      insn_iconst_1:
841       PUSHI (1);
842       NEXT_INSN;
843
844      insn_iconst_2:
845       PUSHI (2);
846       NEXT_INSN;
847
848      insn_iconst_3:
849       PUSHI (3);
850       NEXT_INSN;
851
852      insn_iconst_4:
853       PUSHI (4);
854       NEXT_INSN;
855
856      insn_iconst_5:
857       PUSHI (5);
858       NEXT_INSN;
859
860      insn_lconst_0:
861       PUSHL (0);
862       NEXT_INSN;
863
864      insn_lconst_1:
865       PUSHL (1);
866       NEXT_INSN;
867
868      insn_fconst_0:
869       PUSHF (0);
870       NEXT_INSN;
871
872      insn_fconst_1:
873       PUSHF (1);
874       NEXT_INSN;
875
876      insn_fconst_2:
877       PUSHF (2);
878       NEXT_INSN;
879
880      insn_dconst_0:
881       PUSHD (0);
882       NEXT_INSN;
883
884      insn_dconst_1:
885       PUSHD (1);
886       NEXT_INSN;
887
888      insn_bipush:
889       PUSHI (get1s(pc++));
890       NEXT_INSN;
891
892      insn_sipush:
893       PUSHI (get2s(pc)); pc += 2;
894       NEXT_INSN;
895
896      insn_ldc:
897       {
898         int index = get1u (pc++);
899         PUSHA(pool_data[index].o);
900       }
901       NEXT_INSN;
902
903      insn_ldc_w:
904       {
905         int index = get2u (pc); pc += 2;
906         PUSHA(pool_data[index].o);
907       }
908       NEXT_INSN;
909
910      insn_ldc2_w:
911       {
912         int index = get2u (pc); pc += 2;
913         memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
914         sp += 2;
915       }
916       NEXT_INSN;
917
918      insn_lload:
919       LOADL (get1u (pc++));
920       NEXT_INSN;
921
922      insn_fload:
923       LOADF (get1u (pc++));
924       NEXT_INSN;
925
926      insn_dload:
927       LOADD (get1u (pc++));
928       NEXT_INSN;
929
930      insn_aload:
931       LOADA (get1u (pc++));
932       NEXT_INSN;
933
934      insn_iload_0:
935       LOADI (0);
936       NEXT_INSN;
937
938      insn_iload_2:
939       LOADI (2);
940       NEXT_INSN;
941
942      insn_iload_3:
943       LOADI (3);
944       NEXT_INSN;
945
946      insn_lload_0:
947       LOADL (0);
948       NEXT_INSN;
949
950      insn_lload_1:
951       LOADL (1);
952       NEXT_INSN;
953
954      insn_lload_2:
955       LOADL (2);
956       NEXT_INSN;
957
958      insn_lload_3:
959       LOADL (3);
960       NEXT_INSN;
961
962      insn_fload_0:
963       LOADF (0);
964       NEXT_INSN;
965
966      insn_fload_1:
967       LOADF (1);
968       NEXT_INSN;
969
970      insn_fload_2:
971       LOADF (2);
972       NEXT_INSN;
973
974      insn_fload_3:
975       LOADF (3);
976       NEXT_INSN;
977
978      insn_dload_0:
979       LOADD (0);
980       NEXT_INSN;
981
982      insn_dload_1:
983       LOADD (1);
984       NEXT_INSN;
985
986      insn_dload_2:
987       LOADD (2);
988       NEXT_INSN;
989
990      insn_dload_3:
991       LOADD (3);
992       NEXT_INSN;
993
994      insn_aload_1:
995       LOADA(1);
996       NEXT_INSN;
997
998      insn_aload_2:
999       LOADA(2);
1000       NEXT_INSN;
1001
1002      insn_aload_3:
1003       LOADA(3);
1004       NEXT_INSN;
1005
1006      insn_iaload:
1007       SAVE_PC;
1008       {
1009         jint index = POPI();
1010         jintArray arr = (jintArray) POPA();
1011         NULLCHECK (arr);
1012         if (index < 0 || index >= arr->length)
1013           {
1014             _Jv_ThrowBadArrayIndex (index);
1015           }
1016         PUSHI( elements(arr)[index] );
1017       }
1018       NEXT_INSN;
1019
1020      insn_laload:
1021       SAVE_PC;
1022       {
1023         jint index = POPI();
1024         jlongArray arr = (jlongArray) POPA();
1025         NULLCHECK (arr);
1026         if (index < 0 || index >= arr->length)
1027           {
1028             _Jv_ThrowBadArrayIndex (index);
1029           }
1030         PUSHL( elements(arr)[index] );
1031       }
1032       NEXT_INSN;
1033
1034      insn_faload:
1035       SAVE_PC;
1036       {
1037         jint index = POPI();
1038         jfloatArray arr = (jfloatArray) POPA();
1039         NULLCHECK (arr);
1040         if (index < 0 || index >= arr->length)
1041           {
1042             _Jv_ThrowBadArrayIndex (index);
1043           }
1044         PUSHF( elements(arr)[index] );
1045       }
1046       NEXT_INSN;
1047
1048      insn_daload:
1049       SAVE_PC;
1050       {
1051         jint index = POPI();
1052         jdoubleArray arr = (jdoubleArray) POPA();
1053         NULLCHECK (arr);
1054         if (index < 0 || index >= arr->length)
1055           {
1056             _Jv_ThrowBadArrayIndex (index);
1057           }
1058         PUSHD( elements(arr)[index] );
1059       }
1060       NEXT_INSN;
1061
1062      insn_aaload:
1063       SAVE_PC;
1064       {
1065         jint index = POPI();
1066         jobjectArray arr = (jobjectArray) POPA();
1067         NULLCHECK (arr);
1068         if (index < 0 || index >= arr->length)
1069           {
1070             _Jv_ThrowBadArrayIndex (index);
1071           }
1072         PUSHA( elements(arr)[index] );
1073       }
1074       NEXT_INSN;
1075
1076      insn_baload:
1077       SAVE_PC;
1078       {
1079         jint index = POPI();
1080         jbyteArray arr = (jbyteArray) POPA();
1081         NULLCHECK (arr);
1082         if (index < 0 || index >= arr->length)
1083           {
1084             _Jv_ThrowBadArrayIndex (index);
1085           }
1086         PUSHI( elements(arr)[index] );
1087       }
1088       NEXT_INSN;
1089
1090      insn_caload:
1091       SAVE_PC;
1092       {
1093         jint index = POPI();
1094         jcharArray arr = (jcharArray) POPA();
1095         NULLCHECK (arr);
1096         if (index < 0 || index >= arr->length)
1097           {
1098             _Jv_ThrowBadArrayIndex (index);
1099           }
1100         PUSHI( elements(arr)[index] );
1101       }
1102       NEXT_INSN;
1103
1104      insn_saload:
1105       SAVE_PC;
1106       {
1107         jint index = POPI();
1108         jshortArray arr = (jshortArray) POPA();
1109         NULLCHECK (arr);
1110         if (index < 0 || index >= arr->length)
1111           {
1112             _Jv_ThrowBadArrayIndex (index);
1113           }
1114         PUSHI( elements(arr)[index] );
1115       }
1116       NEXT_INSN;
1117
1118      insn_istore:
1119       STOREI (get1u (pc++));
1120       NEXT_INSN;
1121
1122      insn_lstore:
1123       STOREL (get1u (pc++));
1124       NEXT_INSN;
1125
1126      insn_fstore:
1127       STOREF (get1u (pc++));
1128       NEXT_INSN;
1129
1130      insn_dstore:
1131       STORED (get1u (pc++));
1132       NEXT_INSN;
1133
1134      insn_astore:
1135       STOREI (get1u (pc++));
1136       NEXT_INSN;
1137
1138      insn_istore_0:
1139       STOREI (0);
1140       NEXT_INSN;
1141
1142      insn_istore_1:
1143       STOREI (1);
1144       NEXT_INSN;
1145
1146      insn_istore_2:
1147       STOREI (2);
1148       NEXT_INSN;
1149
1150      insn_istore_3:
1151       STOREI (3);
1152       NEXT_INSN;
1153
1154      insn_lstore_0:
1155       STOREL (0);
1156       NEXT_INSN;
1157
1158      insn_lstore_1:
1159       STOREL (1);
1160       NEXT_INSN;
1161
1162      insn_lstore_2:
1163       STOREL (2);
1164       NEXT_INSN;
1165
1166      insn_lstore_3:
1167       STOREL (3);
1168       NEXT_INSN;
1169
1170      insn_fstore_0:
1171       STOREF (0);
1172       NEXT_INSN;
1173
1174      insn_fstore_1:
1175       STOREF (1);
1176       NEXT_INSN;
1177
1178      insn_fstore_2:
1179       STOREF (2);
1180       NEXT_INSN;
1181
1182      insn_fstore_3:
1183       STOREF (3);
1184       NEXT_INSN;
1185
1186      insn_dstore_0:
1187       STORED (0);
1188       NEXT_INSN;
1189
1190      insn_dstore_1:
1191       STORED (1);
1192       NEXT_INSN;
1193
1194      insn_dstore_2:
1195       STORED (2);
1196       NEXT_INSN;
1197
1198      insn_dstore_3:
1199       STORED (3);
1200       NEXT_INSN;
1201
1202      insn_astore_0:
1203       STOREA(0);
1204       NEXT_INSN;
1205
1206      insn_astore_1:
1207       STOREA(1);
1208       NEXT_INSN;
1209
1210      insn_astore_2:
1211       STOREA(2);
1212       NEXT_INSN;
1213
1214      insn_astore_3:
1215       STOREA(3);
1216       NEXT_INSN;
1217
1218      insn_iastore:
1219       SAVE_PC;
1220       {
1221         jint value = POPI();
1222         jint index  = POPI();
1223         jintArray arr = (jintArray) POPA();
1224         NULLCHECK (arr);
1225         if (index < 0 || index >= arr->length)
1226           {
1227             _Jv_ThrowBadArrayIndex (index);
1228           }
1229         elements(arr)[index] = value;
1230       }
1231       NEXT_INSN;
1232
1233      insn_lastore:
1234       SAVE_PC;
1235       {
1236         jlong value = POPL();
1237         jint index  = POPI();
1238         jlongArray arr = (jlongArray) POPA();
1239         NULLCHECK (arr);
1240         if (index < 0 || index >= arr->length)
1241           {
1242             _Jv_ThrowBadArrayIndex (index);
1243           }
1244         elements(arr)[index] = value;
1245       }
1246       NEXT_INSN;
1247
1248      insn_fastore:
1249       SAVE_PC;
1250       {
1251         jfloat value = POPF();
1252         jint index  = POPI();
1253         jfloatArray arr = (jfloatArray) POPA();
1254         NULLCHECK (arr);
1255         if (index < 0 || index >= arr->length)
1256           {
1257             _Jv_ThrowBadArrayIndex (index);
1258           }
1259         elements(arr)[index] = value;
1260       }
1261       NEXT_INSN;
1262
1263      insn_dastore:
1264       SAVE_PC;
1265       {
1266         jdouble value = POPD();
1267         jint index  = POPI();
1268         jdoubleArray arr = (jdoubleArray) POPA();
1269         NULLCHECK (arr);
1270         if (index < 0 || index >= arr->length)
1271           {
1272             _Jv_ThrowBadArrayIndex (index);
1273           }
1274         elements(arr)[index] = value;
1275       }
1276       NEXT_INSN;
1277
1278      insn_aastore:
1279       SAVE_PC;
1280       {
1281         jobject value = POPA();
1282         jint index  = POPI();
1283         jobjectArray arr = (jobjectArray) POPA();
1284         NULLCHECK (arr);
1285         if (index < 0 || index >= arr->length)
1286           {
1287             _Jv_ThrowBadArrayIndex (index);
1288           }
1289         _Jv_CheckArrayStore (arr, value);
1290         elements(arr)[index] = value;
1291       }
1292       NEXT_INSN;
1293
1294      insn_bastore:
1295       SAVE_PC;
1296       {
1297         jbyte value = (jbyte) POPI();
1298         jint index  = POPI();
1299         jbyteArray arr = (jbyteArray) POPA();
1300         NULLCHECK (arr);
1301         if (index < 0 || index >= arr->length)
1302           {
1303             _Jv_ThrowBadArrayIndex (index);
1304           }
1305         elements(arr)[index] = value;
1306       }
1307       NEXT_INSN;
1308
1309      insn_castore:
1310       SAVE_PC;
1311       {
1312         jchar value = (jchar) POPI();
1313         jint index  = POPI();
1314         jcharArray arr = (jcharArray) POPA();
1315         NULLCHECK (arr);
1316         if (index < 0 || index >= arr->length)
1317           {
1318             _Jv_ThrowBadArrayIndex (index);
1319           }
1320         elements(arr)[index] = value;
1321       }
1322       NEXT_INSN;
1323
1324      insn_sastore:
1325       SAVE_PC;
1326       {
1327         jshort value = (jshort) POPI();
1328         jint index  = POPI();
1329         jshortArray arr = (jshortArray) POPA();
1330         NULLCHECK (arr);
1331         if (index < 0 || index >= arr->length)
1332           {
1333             _Jv_ThrowBadArrayIndex (index);
1334           }
1335         elements(arr)[index] = value;
1336       }
1337       NEXT_INSN;
1338
1339      insn_pop:
1340       sp -= 1;
1341       NEXT_INSN;
1342
1343      insn_pop2:
1344       sp -= 2;
1345       NEXT_INSN;
1346
1347      insn_dup:
1348       sp[0] = sp[-1];
1349       sp += 1;
1350       NEXT_INSN;
1351
1352      insn_dup_x1:
1353       dupx (sp, 1, 1); sp+=1;
1354       NEXT_INSN;
1355
1356      insn_dup_x2:
1357       dupx (sp, 1, 2); sp+=1;
1358       NEXT_INSN;
1359
1360      insn_dup2:
1361       sp[0] = sp[-2];
1362       sp[1] = sp[-1];
1363       sp += 2;
1364       NEXT_INSN;
1365
1366      insn_dup2_x1:
1367       dupx (sp, 2, 1); sp+=2;
1368       NEXT_INSN;
1369
1370      insn_dup2_x2:
1371       dupx (sp, 2, 2); sp+=2;
1372       NEXT_INSN;
1373
1374      insn_swap:
1375       {
1376         jobject tmp1 = POPA();
1377         jobject tmp2 = POPA();
1378         PUSHA (tmp1);
1379         PUSHA (tmp2);
1380       }
1381       NEXT_INSN;
1382
1383      insn_iadd:
1384       BINOPI(+);
1385       NEXT_INSN;
1386
1387      insn_ladd:
1388       BINOPL(+);
1389       NEXT_INSN;
1390
1391      insn_fadd:
1392       BINOPF(+);
1393       NEXT_INSN;
1394
1395      insn_dadd:
1396       BINOPD(+);
1397       NEXT_INSN;
1398
1399      insn_isub:
1400       BINOPI(-);
1401       NEXT_INSN;
1402
1403      insn_lsub:
1404       BINOPL(-);
1405       NEXT_INSN;
1406
1407      insn_fsub:
1408       BINOPF(-);
1409       NEXT_INSN;
1410
1411      insn_dsub:
1412       BINOPD(-);
1413       NEXT_INSN;
1414
1415      insn_imul:
1416       BINOPI(*);
1417       NEXT_INSN;
1418
1419      insn_lmul:
1420       BINOPL(*);
1421       NEXT_INSN;
1422
1423      insn_fmul:
1424       BINOPF(*);
1425       NEXT_INSN;
1426
1427      insn_dmul:
1428       BINOPD(*);
1429       NEXT_INSN;
1430
1431      insn_idiv:
1432       SAVE_PC;
1433       {
1434         jint value2 = POPI();
1435         jint value1 = POPI();
1436         ZEROCHECK (value2);
1437         jint res = value1 / value2;
1438         PUSHI (res);
1439       }
1440       NEXT_INSN;
1441
1442      insn_ldiv:
1443       SAVE_PC;
1444       {
1445         jlong value2 = POPL();
1446         jlong value1 = POPL();
1447         ZEROCHECK (value2);
1448         jlong res = value1 / value2;
1449         PUSHL (res);
1450       }
1451       NEXT_INSN;
1452
1453      insn_fdiv:
1454       SAVE_PC;
1455       {
1456         jfloat value2 = POPF();
1457         jfloat value1 = POPF();
1458         ZEROCHECK (value2);
1459         jfloat res = value1 / value2;
1460         PUSHF (res);
1461       }
1462       NEXT_INSN;
1463
1464      insn_ddiv:
1465       SAVE_PC;
1466       {
1467         jdouble value2 = POPD();
1468         jdouble value1 = POPD();
1469         ZEROCHECK (value2);
1470         jdouble res = value1 / value2;
1471         PUSHD (res);
1472       }
1473       NEXT_INSN;
1474
1475      insn_irem:
1476       SAVE_PC;
1477       {
1478         jint value2 = POPI();
1479         jint value1 = POPI();
1480         ZEROCHECK (value2);     
1481         jint res = value1 % value2;
1482         PUSHI (res);
1483       }
1484       NEXT_INSN;
1485
1486      insn_lrem:
1487       SAVE_PC;
1488       {
1489         jlong value2 = POPL();
1490         jlong value1 = POPL();
1491         ZEROCHECK (value2);
1492         jlong res = value1 % value2;
1493         PUSHL (res);
1494       }
1495       NEXT_INSN;
1496
1497      insn_frem:
1498       SAVE_PC;
1499       {
1500         jfloat value2 = POPF();
1501         jfloat value1 = POPF();
1502         ZEROCHECK (value2);
1503         jfloat res    = __ieee754_fmod (value1, value2);
1504         PUSHF (res);
1505       }
1506       NEXT_INSN;
1507
1508      insn_drem:
1509       SAVE_PC;
1510       {
1511         jdouble value2 = POPD();
1512         jdouble value1 = POPD();
1513         ZEROCHECK (value2);
1514         jdouble res    = __ieee754_fmod (value1, value2);
1515         PUSHD (res);
1516       }
1517       NEXT_INSN;
1518
1519      insn_ineg:
1520       {
1521         jint value = POPI();
1522         PUSHI (value * -1);
1523       }
1524       NEXT_INSN;
1525
1526      insn_lneg:
1527       {
1528         jlong value = POPL();
1529         PUSHL (value * -1);
1530       }
1531       NEXT_INSN;
1532
1533      insn_fneg:
1534       {
1535         jfloat value = POPF();
1536         PUSHF (value * -1);
1537       }
1538       NEXT_INSN;
1539
1540      insn_dneg:
1541       {
1542         jdouble value = POPD();
1543         PUSHD (value * -1);
1544       }
1545       NEXT_INSN;
1546
1547      insn_ishl:
1548       {
1549         jint shift = (POPI() & 0x1f);
1550         jint value = POPI();
1551         PUSHI (value << shift);
1552       }
1553       NEXT_INSN;
1554
1555      insn_lshl:
1556       {
1557         jint shift = (POPI() & 0x3f);
1558         jlong value = POPL();
1559         PUSHL (value << shift);
1560       }
1561       NEXT_INSN;
1562
1563      insn_ishr:
1564       {
1565         jint shift = (POPI() & 0x1f);
1566         jint value = POPI();
1567         PUSHI (value >> shift);
1568       }
1569       NEXT_INSN;
1570
1571      insn_lshr:
1572       {
1573         jint shift = (POPI() & 0x3f);
1574         jlong value = POPL();
1575         PUSHL (value >> shift);
1576       }
1577       NEXT_INSN;
1578
1579      insn_iushr:
1580       {
1581         jint shift = (POPI() & 0x1f);
1582         unsigned long value = POPI();
1583         PUSHI ((jint) (value >> shift));
1584       }
1585       NEXT_INSN;
1586
1587      insn_lushr:
1588       {
1589         jint shift = (POPI() & 0x3f);
1590         UINT64 value = (UINT64) POPL();
1591         PUSHL ((value >> shift));
1592       }
1593       NEXT_INSN;
1594
1595      insn_iand:
1596       BINOPI (&);
1597       NEXT_INSN;
1598
1599      insn_land:
1600       BINOPL (&);
1601       NEXT_INSN;
1602
1603      insn_ior:
1604       BINOPI (|);
1605       NEXT_INSN;
1606
1607      insn_lor:
1608       BINOPL (|);
1609       NEXT_INSN;
1610
1611      insn_ixor:
1612       BINOPI (^);
1613       NEXT_INSN;
1614
1615      insn_lxor:
1616       BINOPL (^);
1617       NEXT_INSN;
1618
1619      insn_iinc:
1620       {
1621         jint index  = get1u (pc++);
1622         jint amount = get1s (pc++);
1623         locals[index].i += amount;
1624       }
1625       NEXT_INSN;
1626
1627      insn_i2l:
1628       {jlong value = POPI(); PUSHL (value);}
1629       NEXT_INSN;
1630
1631      insn_i2f:
1632       {jfloat value = POPI(); PUSHF (value);}
1633       NEXT_INSN;
1634
1635      insn_i2d:
1636       {jdouble value = POPI(); PUSHD (value);}
1637       NEXT_INSN;
1638
1639      insn_l2i:
1640       {jint value = POPL(); PUSHI (value);}
1641       NEXT_INSN;
1642
1643      insn_l2f:
1644       {jfloat value = POPL(); PUSHF (value);}
1645       NEXT_INSN;
1646
1647      insn_l2d:
1648       {jdouble value = POPL(); PUSHD (value);}
1649       NEXT_INSN;
1650
1651      insn_f2i:
1652       { jint value = (jint)POPF (); PUSHI(value); }
1653       NEXT_INSN;
1654
1655      insn_f2l:
1656       { jlong value = (jlong)POPF (); PUSHL(value); }
1657       NEXT_INSN;
1658
1659      insn_f2d:
1660       { jdouble value = POPF (); PUSHD(value); }
1661       NEXT_INSN;
1662
1663      insn_d2i:
1664       { jint value = (jint)POPD (); PUSHI(value); }
1665       NEXT_INSN;
1666
1667      insn_d2l:
1668       { jlong value = (jlong)POPD (); PUSHL(value); }
1669       NEXT_INSN;
1670
1671      insn_d2f:
1672       { jfloat value = POPD (); PUSHF(value); }
1673       NEXT_INSN;
1674
1675      insn_i2b:
1676       { jbyte value = POPI (); PUSHI(value); }
1677       NEXT_INSN;
1678
1679      insn_i2c:
1680       { jchar value = POPI (); PUSHI(value); }
1681       NEXT_INSN;
1682
1683      insn_i2s:
1684       { jshort value = POPI (); PUSHI(value); }
1685       NEXT_INSN;
1686
1687      insn_lcmp:
1688       {
1689         jlong value2 = POPL ();
1690         jlong value1 = POPL ();
1691         if (value1 > value2)
1692           { PUSHI (1); }
1693         else if (value1 == value2)
1694           { PUSHI (0); }
1695         else
1696           { PUSHI (-1); }
1697       }
1698       NEXT_INSN;
1699
1700      insn_fcmpl:
1701      insn_fcmpg:
1702       {
1703         jfloat value2 = POPF ();
1704         jfloat value1 = POPF ();
1705         if (value1 > value2)
1706           PUSHI (1);
1707         else if (value1 == value2)
1708           PUSHI (0);
1709         else if (value1 < value2)
1710           PUSHI (-1);
1711         else if ((*(pc-1)) == op_fcmpg)
1712           PUSHI (1);
1713         else
1714           PUSHI (-1);
1715       }
1716       NEXT_INSN;
1717
1718      insn_dcmpl:
1719      insn_dcmpg:
1720       {
1721         jdouble value2 = POPD ();
1722         jdouble value1 = POPD ();
1723         if (value1 > value2)
1724           PUSHI (1);
1725         else if (value1 == value2)
1726           PUSHI (0);
1727         else if (value1 < value2)
1728           PUSHI (-1);
1729         else if ((*(pc-1)) == op_dcmpg)
1730           PUSHI (1);
1731         else
1732           PUSHI (-1);
1733       }
1734       NEXT_INSN;
1735
1736      insn_ifeq:
1737       {
1738         jint offset = get2s (pc); 
1739         if (POPI() == 0)
1740           pc = pc-1+offset;
1741         else
1742           pc = pc+2;
1743       }
1744       NEXT_INSN;
1745
1746      insn_ifne:
1747       {
1748         jint offset = get2s (pc); 
1749         if (POPI() != 0)
1750           pc = pc-1+offset;
1751         else
1752           pc = pc+2;
1753       }
1754       NEXT_INSN;
1755
1756      insn_iflt:
1757       {
1758         jint offset = get2s (pc); 
1759         if (POPI() < 0)
1760           pc = pc-1+offset;
1761         else
1762           pc = pc+2;
1763       }
1764       NEXT_INSN;
1765
1766      insn_ifge:
1767       {
1768         jint offset = get2s (pc); 
1769         if (POPI() >= 0)
1770           pc = pc-1+offset;
1771         else
1772           pc = pc+2;
1773       }
1774       NEXT_INSN;
1775
1776      insn_ifgt:
1777       {
1778         jint offset = get2s (pc); 
1779         if (POPI() > 0)
1780           pc = pc-1+offset;
1781         else
1782           pc = pc+2;
1783       }
1784       NEXT_INSN;
1785
1786      insn_ifle:
1787       {
1788         jint offset = get2s (pc); 
1789         if (POPI() <= 0)
1790           pc = pc-1+offset;
1791         else
1792           pc = pc+2;
1793       }
1794       NEXT_INSN;
1795
1796      insn_if_icmpeq:
1797       {
1798         jint offset = get2s (pc); 
1799         jint value2 = POPI();
1800         jint value1 = POPI();
1801         if (value1 == value2)
1802           pc = pc-1+offset;
1803         else
1804           pc = pc+2;
1805       }
1806       NEXT_INSN;
1807
1808      insn_if_icmpne:
1809       {
1810         jint offset = get2s (pc); 
1811         jint value2 = POPI();
1812         jint value1 = POPI();
1813         if (value1 != value2)
1814           pc = pc-1+offset;
1815         else
1816           pc = pc+2;
1817       }
1818       NEXT_INSN;
1819
1820      insn_if_icmplt:
1821       {
1822         jint offset = get2s (pc); 
1823         jint value2 = POPI();
1824         jint value1 = POPI();
1825         if (value1 < value2)
1826           pc = pc-1+offset;
1827         else
1828           pc = pc+2;
1829       }
1830       NEXT_INSN;
1831
1832      insn_if_icmpge:
1833       {
1834         jint offset = get2s (pc); 
1835         jint value2 = POPI();
1836         jint value1 = POPI();
1837         if (value1 >= value2)
1838           pc = pc-1+offset;
1839         else
1840           pc = pc+2;
1841       }
1842       NEXT_INSN;
1843
1844      insn_if_icmpgt:
1845       {
1846         jint offset = get2s (pc); 
1847         jint value2 = POPI();
1848         jint value1 = POPI();
1849         if (value1 > value2)
1850           pc = pc-1+offset;
1851         else
1852           pc = pc+2;
1853       }
1854       NEXT_INSN;
1855
1856      insn_if_icmple:
1857       {
1858         jint offset = get2s (pc); 
1859         jint value2 = POPI();
1860         jint value1 = POPI();
1861         if (value1 <= value2)
1862           pc = pc-1+offset;
1863         else
1864           pc = pc+2;
1865       }
1866       NEXT_INSN;
1867
1868      insn_if_acmpeq:
1869       {
1870         jint offset = get2s (pc); 
1871         jobject value2 = POPA();
1872         jobject value1 = POPA();
1873         if (value1 == value2)
1874           pc = pc-1+offset;
1875         else
1876           pc = pc+2;
1877       }
1878       NEXT_INSN;
1879
1880      insn_if_acmpne:
1881       {
1882         jint offset = get2s (pc); 
1883         jobject value2 = POPA();
1884         jobject value1 = POPA();
1885         if (value1 != value2)
1886           pc = pc-1+offset;
1887         else
1888           pc = pc+2;
1889       }
1890       NEXT_INSN;
1891
1892      insn_goto: 
1893       {
1894         jint offset = get2s (pc);
1895         pc = pc-1+offset;
1896       }
1897       NEXT_INSN;
1898
1899      insn_jsr:
1900       {
1901         unsigned char *base_pc = pc-1;
1902         jint offset = get2s (pc); pc += 2;
1903         PUSHA ((jobject)pc);
1904         pc = base_pc+offset;
1905       }
1906       NEXT_INSN;
1907
1908      insn_ret:
1909       {
1910         jint index = get1u (pc);
1911         pc = (unsigned char*) PEEKA (index);
1912       }
1913       NEXT_INSN;
1914
1915      insn_tableswitch:
1916       {
1917         unsigned char *base_pc = pc-1;
1918         int index = POPI();
1919
1920         unsigned char* base = bytecode ();
1921         while ((pc-base) % 4 != 0)
1922           pc++;
1923
1924         jint def     = get4 (pc);
1925         jint low     = get4 (pc+4);
1926         jint high    = get4 (pc+8);
1927
1928         if (index < low || index > high)
1929           pc = base_pc + def;    
1930         else
1931           pc = base_pc + get4 (pc+4*(index-low+3));
1932       }
1933       NEXT_INSN;
1934
1935      insn_lookupswitch:
1936       {
1937         unsigned char *base_pc = pc-1;
1938         int index = POPI();
1939
1940         unsigned char* base = bytecode ();
1941         while ((pc-base) % 4 != 0)
1942           pc++;
1943
1944         jint def     = get4 (pc);
1945         jint npairs  = get4 (pc+4);
1946
1947         int max = npairs-1;
1948         int min = 0;
1949
1950         // simple binary search...
1951         while (min < max)
1952           {
1953             int half = (min+max)/2;
1954             int match = get4 (pc+ 4*(2 + 2*half));
1955
1956             if (index == match)
1957               min = max = half;
1958
1959             else if (index < match)
1960               max = half-1;
1961
1962             else
1963               min = half+1;
1964           }
1965
1966         if (index == get4 (pc+ 4*(2 + 2*min)))
1967           pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1968         else
1969           pc = base_pc + def;    
1970       }
1971       NEXT_INSN;
1972
1973       /* on return, just save the sp and return to caller */
1974      insn_ireturn:
1975      insn_lreturn:
1976      insn_freturn:
1977      insn_dreturn:
1978      insn_areturn:
1979      insn_return:
1980       inv->sp = sp;
1981       return;
1982
1983      insn_getstatic:
1984       SAVE_PC;
1985       {
1986         unsigned char *base_pc = pc-1;
1987         jint fieldref_index = get2u (pc); pc += 2;
1988         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1989         _Jv_Field *field = pool_data[fieldref_index].field;
1990
1991         if ((field->flags & Modifier::STATIC) == 0)
1992           throw_incompatible_class_change_error 
1993             (JvNewStringLatin1 ("field no longer static"));
1994
1995         jclass type = field->type;
1996
1997         if (type->isPrimitive ())
1998           {
1999             switch (type->size_in_bytes)
2000               {
2001               case 1:
2002                 *base_pc = op_getstatic_1;
2003                 break;
2004
2005               case 2:
2006                 if (type == JvPrimClass (char))
2007                   *base_pc = op_getstatic_2u;
2008                 else
2009                   *base_pc = op_getstatic_2s;
2010                 break;
2011
2012               case 4:
2013                 *base_pc = op_getstatic_4;
2014                 break;
2015
2016               case 8:
2017                 *base_pc = op_getstatic_8;
2018                 break;
2019               }
2020           }
2021         else
2022           {
2023             *base_pc = op_getstatic_a;
2024           }
2025
2026         pc = base_pc;
2027       }
2028       NEXT_INSN;
2029
2030      insn_getfield:
2031       SAVE_PC;
2032       {
2033         unsigned char *base_pc = pc-1;
2034         jint fieldref_index = get2u (pc); pc += 2;
2035         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2036         _Jv_Field *field = pool_data[fieldref_index].field;
2037
2038         if ((field->flags & Modifier::STATIC) != 0)
2039           throw_incompatible_class_change_error 
2040             (JvNewStringLatin1 ("field is static"));
2041
2042         jclass type = field->type;
2043
2044         if (type->isPrimitive ())
2045           {
2046             switch (type->size_in_bytes)
2047               {
2048               case 1:
2049                 *base_pc = op_getfield_1;
2050                 break;
2051
2052               case 2:
2053                 if (type == JvPrimClass (char))
2054                   *base_pc = op_getfield_2u;
2055                 else
2056                   *base_pc = op_getfield_2s;
2057                 break;
2058
2059               case 4:
2060                 *base_pc = op_getfield_4;
2061                 break;
2062
2063               case 8:
2064                 *base_pc = op_getfield_8;
2065                 break;
2066               }
2067           }
2068         else
2069           {
2070             *base_pc = op_getfield_a;
2071           }
2072
2073         if (field->u.boffset > 0xffff)
2074           JvThrow (new java::lang::VirtualMachineError);
2075
2076         base_pc[1] = (field->u.boffset>>8) & 0xff;
2077         base_pc[2] = field->u.boffset & 0xff;
2078
2079         pc = base_pc;
2080       }
2081       NEXT_INSN;
2082
2083      insn_putstatic:
2084       SAVE_PC;
2085       {
2086         unsigned char* base_pc = pc-1;
2087         jint fieldref_index = get2u (pc); pc += 2;
2088         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2089         _Jv_Field *field = pool_data[fieldref_index].field;
2090
2091         jclass type = field->type;
2092
2093         // ResolvePoolEntry cannot check this
2094         if ((field->flags & Modifier::STATIC) == 0)
2095           throw_incompatible_class_change_error 
2096             (JvNewStringLatin1 ("field no longer static"));
2097
2098         /* if this is patented, then maybe we could install
2099            a function in the constant pool, to do the right thing */
2100
2101         if (type->isPrimitive ())
2102           {
2103             switch (type->size_in_bytes) 
2104               {
2105               case 1:
2106                 *base_pc = op_putstatic_1;
2107                 break;
2108
2109               case 2:
2110                 *base_pc = op_putstatic_2;
2111                 break;
2112
2113               case 4:
2114                 *base_pc = op_putstatic_4;
2115                 break;
2116
2117               case 8:
2118                 *base_pc = op_putstatic_8;
2119                 break;
2120               }
2121           }
2122         else
2123           {
2124             *base_pc = op_putstatic_a;
2125           }
2126
2127         // do the instruction again!
2128         pc = base_pc;
2129       }
2130       NEXT_INSN;
2131
2132
2133      insn_putfield:
2134       SAVE_PC;
2135       {
2136         unsigned char* base_pc = pc-1;
2137         jint fieldref_index = get2u (pc); pc += 2;
2138         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2139         _Jv_Field *field = pool_data[fieldref_index].field;
2140
2141         jclass type = field->type;
2142
2143         if ((field->flags & Modifier::STATIC) != 0)
2144           throw_incompatible_class_change_error 
2145             (JvNewStringLatin1 ("field is static"));
2146
2147         if (type->isPrimitive ())
2148           {
2149             switch (type->size_in_bytes) 
2150               {
2151               case 1:
2152                 *base_pc = op_putfield_1;
2153                 break;
2154
2155               case 2:
2156                 *base_pc = op_putfield_2;
2157                 break;
2158
2159               case 4:
2160                 *base_pc = op_putfield_4;
2161                 break;
2162
2163               case 8:
2164                 *base_pc = op_putfield_8;
2165                 break;
2166               }
2167           }
2168         else
2169           {
2170             *base_pc = op_putfield_a;
2171           }
2172
2173         if (field->u.boffset > 0xffff)
2174           JvThrow (new java::lang::VirtualMachineError);
2175
2176         base_pc[1] = (field->u.boffset>>8) & 0xff;
2177         base_pc[2] = field->u.boffset & 0xff;
2178
2179         // do the instruction again!
2180         pc = base_pc;
2181       }
2182       NEXT_INSN;
2183
2184
2185      insn_getfield_1:
2186       SAVE_PC;
2187       {
2188         jobject obj   = POPA();
2189         NULLCHECK(obj);
2190         jint field_offset = get2u (pc); pc += 2;
2191         PUSHI (*(jbyte*) ((char*)obj + field_offset));
2192       }
2193       NEXT_INSN;
2194
2195      insn_getfield_2s:
2196       SAVE_PC;
2197       {
2198         jobject obj   = POPA();
2199         NULLCHECK(obj);
2200         jint field_offset = get2u (pc); pc += 2;
2201         PUSHI (*(jshort*) ((char*)obj + field_offset));
2202       }
2203       NEXT_INSN;
2204
2205      insn_getfield_2u:
2206       SAVE_PC;
2207       {
2208         jobject obj   = POPA();
2209         NULLCHECK(obj);
2210         jint field_offset = get2u (pc); pc += 2;
2211         PUSHI (*(jchar*) ((char*)obj + field_offset));
2212       }
2213       NEXT_INSN;
2214
2215      insn_getfield_8:
2216       SAVE_PC;
2217       {
2218         jobject obj   = POPA();
2219         NULLCHECK(obj);
2220         jint field_offset = get2u (pc); pc += 2;
2221         PUSHL(*(jlong*) ((char*)obj + field_offset));
2222       }
2223       NEXT_INSN;
2224
2225      insn_getstatic_1:
2226       {
2227         jint fieldref_index = get2u (pc); pc += 2;
2228         _Jv_Field *field = pool_data[fieldref_index].field;
2229         PUSHI (*(jbyte*) (field->u.addr));
2230       }
2231       NEXT_INSN;
2232
2233      insn_getstatic_2s:
2234       {
2235         jint fieldref_index = get2u (pc); pc += 2;
2236         _Jv_Field *field = pool_data[fieldref_index].field;
2237         PUSHI(*(jshort*) (field->u.addr));
2238       }
2239       NEXT_INSN;
2240
2241      insn_getstatic_2u:
2242       {
2243         jint fieldref_index = get2u (pc); pc += 2;
2244         _Jv_Field *field = pool_data[fieldref_index].field;
2245         PUSHI(*(jchar*) (field->u.addr));
2246       }
2247       NEXT_INSN;
2248
2249      insn_getstatic_4:
2250       {
2251         jint fieldref_index = get2u (pc); pc += 2;
2252         _Jv_Field *field = pool_data[fieldref_index].field;
2253         PUSHI(*(jint*) (field->u.addr));
2254       }
2255       NEXT_INSN;
2256
2257      insn_getstatic_8:
2258       {
2259         jint fieldref_index = get2u (pc); pc += 2;
2260         _Jv_Field *field = pool_data[fieldref_index].field;
2261         PUSHL(*(jlong*) (field->u.addr));
2262       }
2263       NEXT_INSN;
2264
2265      insn_getstatic_a:
2266       {
2267         jint fieldref_index = get2u (pc); pc += 2;
2268         _Jv_Field *field = pool_data[fieldref_index].field;
2269         PUSHA(*(jobject*) (field->u.addr));
2270       }
2271       NEXT_INSN;
2272
2273      insn_putfield_1:
2274       SAVE_PC;
2275       {
2276         jint    value = POPI();
2277         jobject obj   = POPA();
2278         NULLCHECK(obj);
2279         jint field_offset = get2u (pc); pc += 2;
2280         *(jbyte*) ((char*)obj + field_offset) = value;
2281       }
2282       NEXT_INSN;
2283
2284      insn_putfield_2:
2285       SAVE_PC;
2286       {
2287         jint    value = POPI();
2288         jobject obj   = POPA();
2289         NULLCHECK(obj);
2290         jint field_offset = get2u (pc); pc += 2;
2291         *(jchar*) ((char*)obj + field_offset) = value;
2292       }
2293       NEXT_INSN;
2294
2295      insn_putfield_4:
2296       SAVE_PC;
2297       {
2298         jint    value = POPI();
2299         jobject obj   = POPA();
2300         NULLCHECK(obj);
2301         jint field_offset = get2u (pc); pc += 2;
2302         *(jint*) ((char*)obj + field_offset) = value;
2303       }
2304       NEXT_INSN;
2305
2306      insn_putfield_8:
2307       SAVE_PC;
2308       {
2309         jlong   value = POPL();
2310         jobject obj   = POPA();
2311         NULLCHECK(obj);
2312         jint field_offset = get2u (pc); pc += 2;
2313         *(jlong*) ((char*)obj + field_offset) = value;
2314       }
2315       NEXT_INSN;
2316
2317      insn_putfield_a:
2318       SAVE_PC;
2319       {
2320         jobject value = POPA();
2321         jobject obj   = POPA();
2322         NULLCHECK(obj);
2323         jint field_offset = get2u (pc); pc += 2;
2324         *(jobject*) ((char*)obj + field_offset) = value;
2325       }
2326       NEXT_INSN;
2327
2328      insn_putstatic_1:
2329       {
2330         jint    value = POPI();
2331         jint fieldref_index = get2u (pc); pc += 2;
2332         _Jv_Field *field = pool_data[fieldref_index].field;
2333         *(jbyte*) (field->u.addr) = value;
2334       }
2335       NEXT_INSN;
2336
2337      insn_putstatic_2:
2338       {
2339         jint    value = POPI();
2340         jint fieldref_index = get2u (pc); pc += 2;
2341         _Jv_Field *field = pool_data[fieldref_index].field;
2342         *(jchar*) (field->u.addr) = value;
2343       }
2344       NEXT_INSN;
2345
2346      insn_putstatic_4:
2347       {
2348         jint    value = POPI();
2349         jint fieldref_index = get2u (pc); pc += 2;
2350         _Jv_Field *field = pool_data[fieldref_index].field;
2351         *(jint*) (field->u.addr) = value;
2352       }
2353       NEXT_INSN;
2354
2355      insn_putstatic_8:
2356       {
2357         jlong    value = POPL();
2358         jint fieldref_index = get2u (pc); pc += 2;
2359         _Jv_Field *field = pool_data[fieldref_index].field;
2360         *(jlong*) (field->u.addr) = value;
2361       }
2362       NEXT_INSN;
2363
2364      insn_putstatic_a:
2365       {
2366         jobject value = POPA();
2367         jint fieldref_index = get2u (pc); pc += 2;
2368         _Jv_Field *field = pool_data[fieldref_index].field;
2369         *(jobject*) (field->u.addr) = value;
2370       }
2371       NEXT_INSN;
2372
2373      insn_invokespecial:
2374       SAVE_PC;
2375       {
2376         int index = get2u (pc); pc += 2;
2377
2378         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2379
2380         sp -= rmeth->stack_item_count;
2381
2382         NULLCHECK(sp[0]);
2383
2384         fun = (void (*) (...))rmeth->method->ncode;
2385       }
2386       goto perform_invoke;
2387
2388      insn_invokestatic:
2389       SAVE_PC;
2390       {
2391         int index = get2u (pc); pc += 2;
2392
2393         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2394
2395         sp -= rmeth->stack_item_count;
2396
2397         _Jv_InitClass (rmeth->klass);
2398         fun = (void (*) (...))rmeth->method->ncode;
2399       }
2400       goto perform_invoke;
2401
2402      insn_invokeinterface:
2403       SAVE_PC;
2404       {
2405         int index = get2u (pc); pc += 2;
2406
2407         // invokeinterface has two unused bytes...
2408         pc += 2;
2409
2410         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2411
2412         sp -= rmeth->stack_item_count;
2413         NULLCHECK(sp[0]);
2414
2415         jobject rcv = sp[0].o;
2416
2417         fun = (void (*) (...))
2418           _Jv_LookupInterfaceMethod (rcv->getClass (),
2419                                      rmeth->method->name,
2420                                      rmeth->method->signature);
2421       }
2422       goto perform_invoke;
2423
2424
2425      insn_new:
2426       SAVE_PC;
2427       {
2428         int index = get2u (pc); pc += 2;
2429         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2430         _Jv_InitClass (klass);
2431         jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2432         PUSHA (res);
2433       }
2434       NEXT_INSN;
2435
2436      insn_newarray:
2437       SAVE_PC;
2438       {
2439         int atype = get1u (pc++);
2440         int size  = POPI();
2441         jobject result = _Jv_NewArray (atype, size);
2442         PUSHA (result);
2443       }
2444       NEXT_INSN;
2445
2446      insn_anewarray:
2447       SAVE_PC;
2448       {
2449         int index = get2u (pc); pc += 2;
2450         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2451         int size  = POPI();
2452         _Jv_InitClass (klass);
2453         jobject result = _Jv_NewObjectArray (size, klass, 0);
2454         PUSHA (result);
2455       }
2456       NEXT_INSN;
2457
2458      insn_arraylength:
2459       SAVE_PC;
2460       {
2461         __JArray *arr = (__JArray*)POPA();
2462         PUSHI (arr->length);
2463       }
2464       NEXT_INSN;
2465
2466      insn_athrow:
2467       SAVE_PC;
2468       {
2469         jobject value = POPA();
2470         JvThrow (value);
2471       }
2472       NEXT_INSN;
2473
2474      insn_checkcast:
2475       SAVE_PC;
2476       {
2477         jobject value = POPA();
2478         jint index = get2u (pc); pc += 2;
2479         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2480
2481         if (value != NULL && ! to->isInstance (value))
2482           {
2483             JvThrow (new java::lang::ClassCastException
2484                      (to->getName()));
2485           }
2486
2487         PUSHA (value);
2488       }
2489       NEXT_INSN;
2490
2491      insn_instanceof:
2492       SAVE_PC;
2493       {
2494         jobject value = POPA();
2495         jint index = get2u (pc); pc += 2;
2496         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2497         PUSHI (to->isInstance (value));
2498       }
2499       NEXT_INSN;
2500
2501      insn_monitorenter:
2502       SAVE_PC;
2503       {
2504         jobject value = POPA();
2505         NULLCHECK(value);
2506         _Jv_MonitorEnter (value);
2507       }
2508       NEXT_INSN;
2509
2510      insn_monitorexit:
2511       SAVE_PC;
2512       {
2513         jobject value = POPA();
2514         NULLCHECK(value);
2515         _Jv_MonitorExit (value);
2516       }
2517       NEXT_INSN;
2518
2519      insn_ifnull:
2520       {
2521         unsigned char* base_pc = pc-1;
2522         jint offset = get2s (pc); pc += 2;
2523         jobject val = POPA();
2524         if (val == NULL)
2525           pc = base_pc+offset;
2526       }
2527       NEXT_INSN;
2528
2529      insn_ifnonnull:
2530       {
2531         unsigned char* base_pc = pc-1;
2532         jint offset = get2s (pc); pc += 2;
2533         jobject val = POPA();
2534         if (val != NULL)
2535           pc = base_pc+offset;
2536       }
2537       NEXT_INSN;
2538
2539      insn_wide:
2540       SAVE_PC;
2541       {
2542         jint the_mod_op = get1u (pc++);
2543         jint wide       = get2u (pc); pc += 2;
2544
2545         switch (the_mod_op)
2546           {
2547           case op_istore:
2548             STOREI (wide);
2549             NEXT_INSN;
2550
2551           case op_fstore:
2552             STOREF (wide);
2553             NEXT_INSN;
2554
2555           case op_astore:
2556             STOREA (wide);
2557             NEXT_INSN;
2558
2559           case op_lload:
2560             LOADL (wide);
2561             NEXT_INSN;
2562
2563           case op_dload:
2564             LOADD (wide);
2565             NEXT_INSN;
2566
2567           case op_iload:
2568             LOADI (wide);
2569             NEXT_INSN;
2570
2571           case op_aload:
2572             LOADA (wide);
2573             NEXT_INSN;
2574
2575           case op_lstore:
2576             STOREL (wide);
2577             NEXT_INSN;
2578
2579           case op_dstore:
2580             STORED (wide);
2581             NEXT_INSN;
2582
2583           case op_ret:
2584             pc = (unsigned char*) PEEKA (wide);
2585             NEXT_INSN;
2586
2587           case op_iinc:
2588             {
2589               jint amount = get2s (pc); pc += 2;
2590               jint value = PEEKI (wide);
2591               POKEI (wide, value+amount);
2592             }
2593             NEXT_INSN;
2594
2595           default:
2596             throw_internal_error ("illegal bytecode modified by wide");
2597           }
2598
2599       }
2600
2601      insn_multianewarray:
2602       SAVE_PC;
2603       {
2604         int kind_index = get2u (pc); pc += 2;
2605         int dim        = get1u (pc); pc += 1;
2606
2607         jclass type    
2608           = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2609         _Jv_InitClass (type);
2610         jint *sizes    = (jint*) alloca (sizeof (jint)*dim);
2611
2612         for (int i = dim - 1; i >= 0; i--)
2613           {
2614             sizes[i] = POPI ();
2615           }
2616
2617         jobject res    = _Jv_NewMultiArray (type,dim, sizes);
2618
2619         PUSHA (res);
2620       }
2621       NEXT_INSN;
2622
2623      insn_goto_w:
2624       {
2625         unsigned char* base_pc = pc-1;
2626         int offset = get4 (pc); pc += 4;
2627         pc = base_pc+offset;
2628       }
2629       NEXT_INSN;
2630
2631      insn_jsr_w:
2632       {
2633         unsigned char* base_pc = pc-1;
2634         int offset = get4 (pc); pc += 4;
2635         PUSHA((jobject)pc);
2636         pc = base_pc+offset;
2637       }
2638       NEXT_INSN;
2639 }
2640
2641
2642 static void
2643 throw_internal_error (char *msg)
2644 {
2645   JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2646 }
2647
2648 static void 
2649 throw_incompatible_class_change_error (jstring msg)
2650 {
2651   JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2652 }
2653
2654 #if !HANDLE_SEGV
2655 static java::lang::NullPointerException *null_pointer_exc;
2656 static void 
2657 throw_null_pointer_exception ()
2658 {
2659   if (null_pointer_exc == NULL)
2660     null_pointer_exc = new java::lang::NullPointerException;
2661
2662   JvThrow (null_pointer_exc);
2663 }
2664 #endif
2665
2666 #if !HANDLE_FPE
2667 static java::lang::ArithmeticException *arithmetic_exc;
2668 static void 
2669 throw_arithmetic_exception ()
2670 {
2671   if (arithmetic_exc == NULL)
2672     arithmetic_exc = new java::lang::ArithmeticException
2673       (JvNewStringLatin1 ("/ by zero"));
2674
2675   JvThrow (arithmetic_exc);
2676 }
2677 #endif
2678
2679
2680 #endif // INTERPRETER