OSDN Git Service

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