OSDN Git Service

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