OSDN Git Service

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