OSDN Git Service

* java/lang/natClassLoader.cc (_Jv_PrepareCompiledClass): Renamed
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999  Cygnus Solutions
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
13 /* define this to get instruction timings.  */
14 /* #define TIME_MAINLOOP  */
15
16 #include <config.h>
17
18 #pragma implementation "java-interp.h"
19
20 #include <cni.h>
21 #include <jvm.h>
22 #include <java-field.h>
23 #include <java-cpool.h>
24 #include <java-interp.h>
25 #include <java/lang/fdlibm.h>
26 #include <java/lang/System.h>
27 #include <java/lang/String.h>
28 #include <java/lang/Integer.h>
29 #include <java/lang/StringBuffer.h>
30 #include <java/io/PrintStream.h>
31 #include <java/lang/Class.h>
32 #include <java/lang/reflect/Modifier.h>
33 #include <java/lang/ClassCastException.h>
34 #include <java/lang/VirtualMachineError.h>
35 #include <java/lang/InternalError.h>
36 #include <java/lang/NullPointerException.h>
37 #include <java/lang/ArithmeticException.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java-insns.h>
40 #include <java-signal.h>
41 #ifdef TIME_MAINLOOP
42 #include <sys/time.h>
43 #include <stdio.h>
44 #endif
45
46 #ifndef INTERPRETER
47
48 #include <gnu/gcj/runtime/MethodInvocation.h>
49
50 /* This should never happen. */
51 void 
52 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
53                                                 gnu::gcj::RawData *)
54 {
55   JvFail ("no interpreter");
56 }
57
58 #else
59
60 #define ClassError _CL_Q34java4lang5Error
61 extern java::lang::Class ClassError;
62
63 static const int PUBLIC       = 0x001;
64 static const int PRIVATE      = 0x002;
65 static const int PROTECTED    = 0x004;
66 static const int STATIC       = 0x008;
67 static const int FINAL        = 0x010;
68 static const int SYNCHRONIZED = 0x020;
69 static const int VOLATILE     = 0x040;
70 static const int TRANSIENT    = 0x080;
71 static const int NATIVE       = 0x100;
72 static const int INTERFACE    = 0x200;
73 static const int ABSTRACT     = 0x400;
74 static const int ALL_FLAGS    = 0x7FF; 
75
76 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
77
78 static void throw_internal_error (char *msg)
79   __attribute__ ((__noreturn__));
80 static void throw_incompatible_class_change_error (jstring msg)
81   __attribute__ ((__noreturn__));
82 #if !HANDLE_SEGV
83 static void throw_null_pointer_exception ()
84   __attribute__ ((__noreturn__));
85 #endif
86 #if !HANDLE_FPE
87 static void throw_arithmetic_exception ()
88   __attribute__ ((__noreturn__));
89 #endif
90
91
92 static inline void dupx (_Jv_word *&sp, int n, int x)
93 {
94   // first "slide" n+x elements n to the right
95   int top = n-1;
96   for (int i = 0; i < n+x; i++)
97     {
98       sp[(top-i)] = sp[(top-i)-n];
99     }
100   
101   // next, copy the n top elements, n+x down
102   for (int i = 0; i < n; i++)
103     {
104       sp[top-(n+x)-i] = sp[top-i];
105     }
106   
107   // the net effect
108   sp += n;
109 };
110
111
112 #define PUSHA(V)  (sp++)->o = (V)
113 #define PUSHI(V)  (sp++)->i = (V)
114 #define PUSHF(V)  (sp++)->f = (V)
115 #define PUSHL(V)  ({ _Jv_word2 w2; w2.l=(V); \
116                      (sp++)->ia[0] = w2.ia[0]; \
117                      (sp++)->ia[0] = w2.ia[1]; })
118 #define PUSHD(V)  ({ _Jv_word2 w2; w2.d=(V); \
119                      (sp++)->ia[0] = w2.ia[0]; \
120                      (sp++)->ia[0] = w2.ia[1]; })
121
122 #define POPA()    ((--sp)->o)
123 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
124 #define POPF()    ((jfloat) (--sp)->f)
125 #define POPL()    ({ _Jv_word2 w2; \
126                      w2.ia[1] = (--sp)->ia[0]; \
127                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
128 #define POPD()    ({ _Jv_word2 w2; \
129                      w2.ia[1] = (--sp)->ia[0]; \
130                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
131
132 #define LOADA(I)  (sp++)->o = locals[I].o
133 #define LOADI(I)  (sp++)->i = locals[I].i
134 #define LOADF(I)  (sp++)->f = locals[I].f
135 #define LOADL(I)  ({ jint __idx = (I); \
136     (sp++)->ia[0] = locals[__idx].ia[0]; \
137     (sp++)->ia[0] = locals[__idx+1].ia[0]; \
138  })
139 #define LOADD(I)  LOADL(I)
140
141
142 #define STOREA(I) locals[I].o = (--sp)->o
143 #define STOREI(I) locals[I].i = (--sp)->i
144 #define STOREF(I) locals[I].f = (--sp)->f
145 #define STOREL(I) ({ jint __idx = (I); \
146     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
147     locals[__idx].ia[0] = (--sp)->ia[0]; \
148  })
149 #define STORED(I) STOREL(I)
150
151 #define PEEKI(I)  (locals+(I))->i
152 #define PEEKA(I)  (locals+(I))->o
153
154 #define POKEI(I,V)  (*(jint*) (locals+(I)) = (V))
155
156
157 #define BINOPI(OP) { \
158    jint value2 = POPI(); \
159    jint value1 = POPI(); \
160    PUSHI(value1 OP value2); \
161 }
162
163 #define BINOPF(OP) { \
164    jfloat value2 = POPF(); \
165    jfloat value1 = POPF(); \
166    PUSHF(value1 OP value2); \
167 }
168
169 #define BINOPL(OP) { \
170    jlong value2 = POPL(); \
171    jlong value1 = POPL(); \
172    PUSHL(value1 OP value2); \
173 }
174
175 #define BINOPD(OP) { \
176    jdouble value2 = POPD(); \
177    jdouble value1 = POPD(); \
178    PUSHD(value1 OP value2); \
179 }
180
181 static inline jint get1s(unsigned char* loc) {
182   return *(signed char*)loc;
183 }
184
185 static inline jint get1u(unsigned char* loc) {
186   return *loc;
187 }
188
189 static inline jint get2s(unsigned char* loc) {
190   return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
191 }
192
193 static inline jint get2u(unsigned char* loc) {
194   return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
195 }
196
197 static jint get4(unsigned char* loc) {
198   return (((jint)(loc[0])) << 24) 
199        | (((jint)(loc[1])) << 16) 
200        | (((jint)(loc[2])) << 8) 
201        | (((jint)(loc[3])) << 0);
202 }
203
204
205 #if HANDLE_SEGV
206 #define NULLCHECK(X) 
207 #else
208 #define NULLCHECK(X) \
209   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
210 #endif
211
212 #if HANDLE_FPE
213 #define ZEROCHECK(X)
214 #else
215 #define ZEROCHECK(X) \
216   do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
217 #endif
218
219 // this method starts the actual running of the method.  It is inlined
220 // in three different variants in the static methods run_normal,
221 // run_sync_object and run_sync_class (see below).  Those static methods
222 // are installed directly in the stub for this method (by
223 // _Jv_InterpMethod::ncode, in resolve.cc).
224
225 inline jobject
226 _Jv_InterpMethod::run (ffi_cif* cif,
227                        void *retp,
228                        ffi_raw *args,
229                        _Jv_InterpMethodInvocation *inv)
230 {
231   inv->running  = this;
232   inv->pc       = bytecode ();
233   inv->sp       = inv->stack_base ();
234   _Jv_word *locals = inv->local_base ();
235
236   /* Go straight at it!  the ffi raw format matches the internal
237      stack representation exactly.  At leat, that's the idea.
238   */
239   memcpy ((void*) locals, (void*) args, args_raw_size);
240
241  next_segment:
242   /* this will call the method _Jv_InterpMethod::continue0, see below */
243   jobject ex = 
244     gnu::gcj::runtime::MethodInvocation::continue0
245     ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
246
247   if (ex == 0)                  // no exception...
248     {
249       /* define sp locally, so the POP? macros will pick it up */
250       _Jv_word *sp = inv->sp;
251       int rtype = cif->rtype->type;
252
253       if (rtype == FFI_TYPE_POINTER)
254         {
255           jobject r = POPA();
256           *(jobject*) retp = r;
257           return 0;
258         }
259       else if (rtype == FFI_TYPE_SINT32)
260         {
261           jint r = POPI();
262           *(jint*)retp = r;
263           return 0;
264         }
265       else if (rtype == FFI_TYPE_VOID)
266         {
267           return 0;
268         }
269       else switch (rtype)
270         {
271         case FFI_TYPE_FLOAT:
272           {
273             jfloat r = POPF();
274             *(jfloat*)retp = r;
275             return 0;
276           }
277       
278         case FFI_TYPE_DOUBLE:
279           {
280             jdouble r = POPD();
281             *(jdouble*)retp = r;
282             return 0;
283           }
284
285         case FFI_TYPE_UINT8:
286         case FFI_TYPE_UINT16:
287         case FFI_TYPE_UINT32:
288         case FFI_TYPE_SINT8:
289         case FFI_TYPE_SINT16:
290           {
291             jint r = POPI();
292             *(jint*)retp = r;
293             return 0;
294           }
295       
296         case FFI_TYPE_SINT64:
297           {
298             jlong r = POPL();
299             *(jlong*)retp = r;
300             return 0;
301           }
302         
303         default:
304           throw_internal_error ("unknown return type");
305         }
306
307     }
308
309   /** handle an exception */
310   if ( find_exception (ex, inv) )
311     goto next_segment;
312
313   java::lang::System::out->println 
314     (_Jv_NewStringUTF (self->name->data));
315
316   return ex;
317 }
318
319 bool _Jv_InterpMethod::find_exception (jobject ex,
320                                        _Jv_InterpMethodInvocation *inv)
321 {
322   int logical_pc = inv->pc - bytecode ();
323   _Jv_InterpException *exc = exceptions ();
324   jclass exc_class = ex->getClass ();
325
326   for (int i = 0; i < exc_count; i++)
327     {
328       if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
329         {       
330           jclass handler;
331
332           if (exc[i].handler_type != 0)
333             handler = (_Jv_ResolvePoolEntry (defining_class, 
334                                              exc[i].handler_type)).clazz;
335           else
336             handler = NULL;
337           
338           if (handler==NULL || handler->isAssignableFrom (exc_class))
339             {
340               inv->pc = bytecode () + exc[i].handler_pc;
341               inv->sp = inv->stack_base (); // reset stack
342               (inv->sp++)->o = ex; // push exception
343               return true;
344             }
345         }
346     }
347   return false;
348 }
349
350 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
351                                    void* ret,
352                                    ffi_raw * args,
353                                    void* __this)
354 {
355   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
356
357   // we do the alloca of the method invocation here, to allow the method
358   // "run" ro be inlined.  Otherwise gcc will ignore the inline directive.
359   int storage_size = _this->max_stack+_this->max_locals;
360   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
361     alloca (sizeof (_Jv_InterpMethodInvocation)
362             + storage_size * sizeof (_Jv_word));
363
364   jobject ex = _this->run (cif, ret, args, inv);
365   if (ex != 0) _Jv_Throw (ex);
366 }
367
368 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
369                                          void* ret,
370                                          ffi_raw * args,
371                                          void* __this)
372 {
373   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
374   jobject rcv = (jobject)args[0].ptr;
375
376   int storage_size = _this->max_stack+_this->max_locals;
377   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
378     alloca (sizeof (_Jv_InterpMethodInvocation)
379             + storage_size * sizeof (_Jv_word));
380
381   _Jv_MonitorEnter (rcv);
382   jobject ex = _this->run (cif, ret, args, inv);
383   _Jv_MonitorExit (rcv);
384
385   if (ex != 0) _Jv_Throw (ex);
386 }
387
388 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
389                                         void* ret,
390                                         ffi_raw * args,
391                                         void* __this)
392 {
393   _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
394   jclass  sync = _this->defining_class;
395
396   int storage_size = _this->max_stack+_this->max_locals;
397   _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
398     alloca (sizeof (_Jv_InterpMethodInvocation)
399             + storage_size * sizeof (_Jv_word));
400
401   _Jv_MonitorEnter (sync);
402   jobject ex = _this->run (cif, ret, args, inv);
403   _Jv_MonitorExit (sync);
404
405   if (ex != 0) _Jv_Throw (ex);
406 }
407
408 /* this is the exception handler hack, for the interpreter */
409 void 
410 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
411                                                 gnu::gcj::RawData *inv)
412 {
413   _Jv_InterpMethod           *meth0 = (_Jv_InterpMethod*)meth;
414   _Jv_InterpMethodInvocation *inv0  = (_Jv_InterpMethodInvocation*)inv;
415   meth0->continue1 (inv0);
416 }
417
418 /*
419   This proceeds execution, as designated in "inv".  If an exception
420   happens, then it is simply thrown, and handled in Java.  Thus, the pc
421   needs to be stored in the invocation at all times, so we can figure
422   out which handler (if any) to invoke.
423
424   One design issue, which I have not completely considered, is if it
425   should be possible to have interpreted classes linked in!  Seldom used
426   (or non-critical) classes could reasonably be interpreted.  
427 */
428
429
430 #ifdef TIME_MAINLOOP
431 static jlong insn_time [256] = { 0 };
432 static jlong insn_count[256] = { 0 };
433
434 static void
435 dump_time ()
436 {
437   double total_all = 0;
438   for (int i = 0; i < 256; i++)
439     {
440       total_all += insn_time[i];
441     }
442
443   for (int i = 0; i < 256; i++)
444     {
445       jlong total  = insn_time[i];
446       jlong count  = insn_count[i];
447
448       if (count == 0) continue;
449
450       jlong amount = total/count;
451
452       printf ("in 0x%02x: %7Li %7Li %7Li %2.1f%%\n", i,
453               (long long)count, (long long)total, (long long)amount,
454               (float) (100.0*(double)total/total_all)
455               );
456     }
457 }
458 #endif
459   
460 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
461 {
462   _Jv_word      *sp     = inv->sp;
463   unsigned char *pc     = inv->pc;
464   _Jv_word      *locals = inv->local_base ();
465   int            opcode;
466
467   jclass defining_class = this->defining_class;
468   _Jv_word *pool_data   = defining_class->constants.data;
469   
470   /* these two are used in the invokeXXX instructions */
471   void (*fun)(...);
472   _Jv_ResolvedMethod* rmeth;
473
474 #ifdef TIME_MAINLOOP
475   struct timeval tv;
476   int   last_opcode;
477   jlong last_time;
478   static jlong time_warp = 0;
479
480 #define USEC(TV) \
481    ((jlong) (TV).tv_sec * 1000000LL + (jlong)(TV).tv_usec)
482
483
484   if (time_warp == 0) 
485     {
486       struct timeval tv2;
487
488       gettimeofday (&tv, 0); 
489       for (int i = 0; i < 100; i++)
490         gettimeofday (&tv2, 0); 
491       
492       jlong then = USEC(tv); 
493       jlong now = USEC(tv2);
494       time_warp = (now - then) / 100;
495
496       if (time_warp == 0)
497         time_warp = 1;
498     }    
499
500 #define TIME_SUSPEND do { \
501   gettimeofday (&tv, 0); \
502   jlong now = USEC(tv); \
503   insn_time[last_opcode] += (now - last_time) - time_warp; \
504 } while(0)
505
506 #define TIME_RESUME do { \
507   gettimeofday (&tv, 0); \
508   last_time = USEC(tv); \
509 } while(0)
510
511   last_opcode = 0; 
512   gettimeofday (&tv, 0); 
513   last_time = (jlong)tv.tv_sec * 1000000LL + (jlong)tv.tv_usec; 
514
515 #else
516
517 #define TIME_SUSPEND 
518 #define TIME_RESUME
519
520 #endif
521
522  next_insn:
523   inv->pc = pc;
524
525 #ifdef TIME_MAINLOOP
526
527   gettimeofday (&tv, 0); 
528   jlong now = USEC(tv); 
529   insn_time[last_opcode] += (now - last_time) - time_warp; 
530   last_time = now; 
531   last_opcode = *pc; 
532   insn_count[last_opcode] += 1;
533
534 #endif
535   opcode = *pc++;
536
537   switch (opcode)
538     {
539     case op_aload_0:            // 0x2a
540       LOADA(0);
541       goto next_insn;
542
543     case op_iload:              // 0x15
544       LOADI (get1u (pc++));
545       goto next_insn;
546
547     case op_getfield_4:         // 0xd8
548       {
549         jobject obj   = POPA();
550         NULLCHECK(obj);
551         jint field_offset = get2u (pc); pc += 2;
552         PUSHI (*(jint*) ((char*)obj + field_offset));
553       }
554       goto next_insn;
555
556     case op_iload_1:            // 0x1b
557       LOADI (1);
558       goto next_insn;
559
560     case op_getfield_a:         // 0xda
561       {
562         jobject obj   = POPA();
563         NULLCHECK(obj);
564         jint field_offset = get2u (pc); pc += 2;
565         PUSHA(*(jobject*) ((char*)obj + field_offset));
566       }
567       goto next_insn;
568
569     case op_invokevirtual:      // 0xb6
570       {
571         int index = get2u (pc); pc += 2;
572
573         /* _Jv_ResolvePoolEntry returns immediately if the value already
574          * is resolved.  If we want to clutter up the code here to gain
575          * a little performance, then we can check the corresponding bit
576          * JV_CONSTANT_ResolvedFlag in the tag directly.  For now, I
577          * don't think it is worth it.  */
578
579         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
580
581         sp -= rmeth->stack_item_count;
582         NULLCHECK(sp[0]);
583
584         if (rmeth->vtable_index == -1)
585           {
586             // final methods do not appear in the vtable,
587             // if it does not appear in the superclass.
588             fun = (void (*) (...)) rmeth->method->ncode;
589           }
590         else
591           {
592             jobject rcv = sp[0].o;
593             _Jv_VTable *table = *(_Jv_VTable**)rcv;
594             fun = (void (*) (...))table->method[rmeth->vtable_index];
595           }
596       }
597       goto perform_invoke;
598
599     perform_invoke:
600       {
601         /* here goes the magic again... */
602         ffi_cif *cif = &rmeth->cif;
603         ffi_raw *raw = (ffi_raw*) sp;
604
605         jdouble rvalue;
606
607         TIME_SUSPEND;
608         ffi_raw_call (cif, fun, (void*)&rvalue, raw);
609         TIME_RESUME;
610
611         int rtype = cif->rtype->type;
612
613         /* the likelyhood of object, int, or void return is very high,
614          * so those are checked before the switch */
615         if (rtype == FFI_TYPE_POINTER)
616           {
617             PUSHA (*(jobject*)&rvalue);
618           }
619         else if (rtype == FFI_TYPE_SINT32)
620           {
621             PUSHI (*(jint*)&rvalue);
622           }
623         else if (rtype == FFI_TYPE_VOID)
624           {
625             /* skip */
626           }
627         else switch (rtype) 
628           {
629           case FFI_TYPE_SINT8:
630             {
631               jbyte value = (*(jint*)&rvalue) & 0xff;
632               PUSHI (value);
633             }
634             break;
635
636           case FFI_TYPE_SINT16:
637             {
638               jshort value = (*(jint*)&rvalue) & 0xffff;
639               PUSHI (value);
640             }
641             break;
642
643           case FFI_TYPE_UINT16:
644             {
645               jint value = (*(jint*)&rvalue) & 0xffff;
646               PUSHI (value);
647             }
648             break;
649
650           case FFI_TYPE_FLOAT:
651             PUSHF (*(jfloat*)&rvalue);
652             break;
653
654           case FFI_TYPE_DOUBLE:
655             PUSHD (rvalue);
656             break;
657
658           case FFI_TYPE_SINT64:
659             PUSHL (*(jlong*)&rvalue);
660             break;
661         
662           default:
663             throw_internal_error ("unknown return type in invokeXXX");
664           }
665         
666       }
667       goto next_insn;
668
669
670     case op_nop:
671       goto next_insn;
672
673     case op_aconst_null:
674       PUSHA (NULL);
675       goto next_insn;
676
677     case op_iconst_m1:
678     case op_iconst_0:
679     case op_iconst_1:
680     case op_iconst_2:
681     case op_iconst_3:
682     case op_iconst_4:
683     case op_iconst_5:
684       PUSHI (opcode-op_iconst_0);
685       goto next_insn;
686
687     case op_lconst_0:
688     case op_lconst_1:
689       PUSHL ((jlong) (opcode-op_lconst_0));
690       goto next_insn;
691       
692     case op_fconst_0:
693     case op_fconst_1:
694     case op_fconst_2:
695       PUSHF ((jfloat) (opcode-op_fconst_0));
696       goto next_insn;
697
698     case op_dconst_0:
699     case op_dconst_1:
700       PUSHD ((jdouble) (opcode-op_dconst_0));
701       goto next_insn;
702
703     case op_bipush:
704       PUSHI (get1s(pc++));
705       goto next_insn;
706       
707     case op_sipush:
708       PUSHI (get2s(pc)); pc += 2;
709       goto next_insn;
710
711     case op_ldc:
712       {
713         int index = get1u (pc++);
714         PUSHA(pool_data[index].o);
715       }
716       goto next_insn;
717
718     case op_ldc_w:
719       {
720         int index = get2u (pc); pc += 2;
721         PUSHA(pool_data[index].o);
722       }
723       goto next_insn;
724
725     case op_ldc2_w:
726       {
727         int index = get2u (pc); pc += 2;
728         memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
729         sp += 2;
730       }
731       goto next_insn;
732
733     case op_lload:
734       LOADL (get1u (pc++));
735       goto next_insn;
736
737     case op_fload:
738       LOADF (get1u (pc++));
739       goto next_insn;
740
741     case op_dload:
742       LOADD (get1u (pc++));
743       goto next_insn;
744
745     case op_aload:
746       LOADA (get1u (pc++));
747       goto next_insn;
748
749     case op_iload_0:
750       LOADI (0);
751       goto next_insn;
752
753     case op_iload_2:
754       LOADI (2);
755       goto next_insn;
756
757     case op_iload_3:
758       LOADI (3);
759       goto next_insn;
760
761     case op_lload_0:
762     case op_lload_1:
763     case op_lload_2:
764     case op_lload_3:
765       LOADL (opcode-op_lload_0);
766       goto next_insn;
767
768     case op_fload_0:
769     case op_fload_1:
770     case op_fload_2:
771     case op_fload_3:
772       LOADF (opcode-op_fload_0);
773       goto next_insn;
774
775     case op_dload_0:
776     case op_dload_1:
777     case op_dload_2:
778     case op_dload_3:
779       LOADD (opcode-op_dload_0);
780       goto next_insn;
781
782     case op_aload_1:
783       LOADA(1);
784       goto next_insn;
785
786     case op_aload_2:
787       LOADA(2);
788       goto next_insn;
789
790     case op_aload_3:
791       LOADA(3);
792       goto next_insn;
793
794     case op_iaload:
795       {
796         jint index = POPI();
797         jintArray arr = (jintArray) POPA();
798         NULLCHECK (arr);
799         if (index < 0 || index >= arr->length)
800           {
801             TIME_SUSPEND;
802             _Jv_ThrowBadArrayIndex (index);
803           }
804         PUSHI( elements(arr)[index] );
805       }
806       goto next_insn;
807
808     case op_laload:
809       {
810         jint index = POPI();
811         jlongArray arr = (jlongArray) POPA();
812         NULLCHECK (arr);
813         if (index < 0 || index >= arr->length)
814           {
815             TIME_SUSPEND;
816             _Jv_ThrowBadArrayIndex (index);
817           }
818         PUSHL( elements(arr)[index] );
819       }
820       goto next_insn;
821
822     case op_faload:
823       {
824         jint index = POPI();
825         jfloatArray arr = (jfloatArray) POPA();
826         NULLCHECK (arr);
827         if (index < 0 || index >= arr->length)
828           {
829             TIME_SUSPEND;
830             _Jv_ThrowBadArrayIndex (index);
831           }
832         PUSHF( elements(arr)[index] );
833       }
834       goto next_insn;
835
836     case op_daload:
837       {
838         jint index = POPI();
839         jdoubleArray arr = (jdoubleArray) POPA();
840         NULLCHECK (arr);
841         if (index < 0 || index >= arr->length)
842           {
843             TIME_SUSPEND;
844             _Jv_ThrowBadArrayIndex (index);
845           }
846         PUSHD( elements(arr)[index] );
847       }
848       goto next_insn;
849
850     case op_aaload:
851       {
852         jint index = POPI();
853         jobjectArray arr = (jobjectArray) POPA();
854         NULLCHECK (arr);
855         if (index < 0 || index >= arr->length)
856           {
857             TIME_SUSPEND;
858             _Jv_ThrowBadArrayIndex (index);
859           }
860         PUSHA( elements(arr)[index] );
861       }
862       goto next_insn;
863
864     case op_baload:
865       {
866         jint index = POPI();
867         jbyteArray arr = (jbyteArray) POPA();
868         NULLCHECK (arr);
869         if (index < 0 || index >= arr->length)
870           {
871             TIME_SUSPEND;
872             _Jv_ThrowBadArrayIndex (index);
873           }
874         PUSHI( elements(arr)[index] );
875       }
876       goto next_insn;
877
878     case op_caload:
879       {
880         jint index = POPI();
881         jcharArray arr = (jcharArray) POPA();
882         NULLCHECK (arr);
883         if (index < 0 || index >= arr->length)
884           {
885             TIME_SUSPEND;
886             _Jv_ThrowBadArrayIndex (index);
887           }
888         PUSHI( elements(arr)[index] );
889       }
890       goto next_insn;
891
892     case op_saload:
893       {
894         jint index = POPI();
895         jshortArray arr = (jshortArray) POPA();
896         NULLCHECK (arr);
897         if (index < 0 || index >= arr->length)
898           {
899             TIME_SUSPEND;
900             _Jv_ThrowBadArrayIndex (index);
901           }
902         PUSHI( elements(arr)[index] );
903       }
904       goto next_insn;
905
906     case op_istore:
907       STOREI (get1u (pc++));
908       goto next_insn;
909
910     case op_lstore:
911       STOREL (get1u (pc++));
912       goto next_insn;
913
914     case op_fstore:
915       STOREF (get1u (pc++));
916       goto next_insn;
917
918     case op_dstore:
919       STORED (get1u (pc++));
920       goto next_insn;
921
922     case op_astore:
923       STOREI (get1u (pc++));
924       goto next_insn;
925
926     case op_istore_0:
927     case op_istore_1:
928     case op_istore_2:
929     case op_istore_3:
930       STOREI (opcode-op_istore_0);
931       goto next_insn;
932
933     case op_lstore_0:
934     case op_lstore_1:
935     case op_lstore_2:
936     case op_lstore_3:
937       STOREL (opcode-op_lstore_0);
938       goto next_insn;
939
940     case op_fstore_0:
941     case op_fstore_1:
942     case op_fstore_2:
943     case op_fstore_3:
944       STOREF (opcode-op_fstore_0);
945       goto next_insn;
946
947     case op_dstore_0:
948     case op_dstore_1:
949     case op_dstore_2:
950     case op_dstore_3:
951       STORED (opcode-op_dstore_0);
952       goto next_insn;
953
954     case op_astore_0:
955     case op_astore_1:
956     case op_astore_2:
957     case op_astore_3:
958       STOREA (opcode-op_astore_0);
959       goto next_insn;
960
961     case op_iastore:
962       {
963         jint value = POPI();
964         jint index  = POPI();
965         jintArray arr = (jintArray) POPA();
966         NULLCHECK (arr);
967         if (index < 0 || index >= arr->length)
968           {
969             TIME_SUSPEND;
970             _Jv_ThrowBadArrayIndex (index);
971           }
972         elements(arr)[index] = value;
973       }
974       goto next_insn;
975
976     case op_lastore:
977       {
978         jlong value = POPL();
979         jint index  = POPI();
980         jlongArray arr = (jlongArray) POPA();
981         NULLCHECK (arr);
982         if (index < 0 || index >= arr->length)
983           {
984             TIME_SUSPEND;
985             _Jv_ThrowBadArrayIndex (index);
986           }
987         elements(arr)[index] = value;
988       }
989       goto next_insn;
990
991     case op_fastore:
992       {
993         jfloat value = POPF();
994         jint index  = POPI();
995         jfloatArray arr = (jfloatArray) POPA();
996         NULLCHECK (arr);
997         if (index < 0 || index >= arr->length)
998           {
999             TIME_SUSPEND;
1000             _Jv_ThrowBadArrayIndex (index);
1001           }
1002         elements(arr)[index] = value;
1003       }
1004       goto next_insn;
1005
1006     case op_dastore:
1007       {
1008         jdouble value = POPD();
1009         jint index  = POPI();
1010         jdoubleArray arr = (jdoubleArray) POPA();
1011         NULLCHECK (arr);
1012         if (index < 0 || index >= arr->length)
1013           {
1014             TIME_SUSPEND;
1015             _Jv_ThrowBadArrayIndex (index);
1016           }
1017         elements(arr)[index] = value;
1018       }
1019       goto next_insn;
1020
1021     case op_aastore:
1022       {
1023         jobject value = POPA();
1024         jint index  = POPI();
1025         jobjectArray arr = (jobjectArray) POPA();
1026         NULLCHECK (arr);
1027         if (index < 0 || index >= arr->length)
1028           {
1029             TIME_SUSPEND;
1030             _Jv_ThrowBadArrayIndex (index);
1031           }
1032         _Jv_CheckArrayStore (arr, value);
1033         elements(arr)[index] = value;
1034       }
1035       goto next_insn;
1036
1037     case op_bastore:
1038       {
1039         jbyte value = (jbyte) POPI();
1040         jint index  = POPI();
1041         jbyteArray arr = (jbyteArray) POPA();
1042         NULLCHECK (arr);
1043         if (index < 0 || index >= arr->length)
1044           {
1045             TIME_SUSPEND;
1046             _Jv_ThrowBadArrayIndex (index);
1047           }
1048         elements(arr)[index] = value;
1049       }
1050       goto next_insn;
1051
1052     case op_castore:
1053       {
1054         jchar value = (jchar) POPI();
1055         jint index  = POPI();
1056         jcharArray arr = (jcharArray) POPA();
1057         NULLCHECK (arr);
1058         if (index < 0 || index >= arr->length)
1059           {
1060             TIME_SUSPEND;
1061             _Jv_ThrowBadArrayIndex (index);
1062           }
1063         elements(arr)[index] = value;
1064       }
1065       goto next_insn;
1066
1067     case op_sastore:
1068       {
1069         jshort value = (jshort) POPI();
1070         jint index  = POPI();
1071         jshortArray arr = (jshortArray) POPA();
1072         NULLCHECK (arr);
1073         if (index < 0 || index >= arr->length)
1074           {
1075             TIME_SUSPEND;
1076             _Jv_ThrowBadArrayIndex (index);
1077           }
1078         elements(arr)[index] = value;
1079       }
1080       goto next_insn;
1081
1082     case op_pop:
1083       sp -= 1;
1084       goto next_insn;
1085
1086     case op_pop2:
1087       sp -= 2;
1088       goto next_insn;
1089
1090     case op_dup:
1091       sp[0] = sp[-1];
1092       sp += 1;
1093       goto next_insn;
1094
1095     case op_dup_x1:
1096       dupx (sp, 1, 1);
1097       goto next_insn;
1098
1099     case op_dup_x2:
1100       dupx (sp, 1, 2);
1101       goto next_insn;
1102
1103     case op_dup2:
1104       sp[0] = sp[-2];
1105       sp[1] = sp[-1];
1106       sp += 2;
1107       goto next_insn;
1108
1109     case op_dup2_x1:
1110       dupx (sp, 2, 1);
1111       goto next_insn;
1112
1113     case op_dup2_x2:
1114       dupx (sp, 2, 2);
1115       goto next_insn;
1116
1117     case op_swap:
1118       {
1119         jobject tmp1 = POPA();
1120         jobject tmp2 = POPA();
1121         PUSHA (tmp1);
1122         PUSHA (tmp2);
1123       }
1124       goto next_insn;
1125
1126     case op_iadd:
1127       BINOPI(+);
1128       goto next_insn;
1129
1130     case op_ladd:
1131       BINOPL(+);
1132       goto next_insn;
1133
1134     case op_fadd:
1135       BINOPF(+);
1136       goto next_insn;
1137
1138     case op_dadd:
1139       BINOPD(+);
1140       goto next_insn;
1141
1142     case op_isub:
1143       BINOPI(-);
1144       goto next_insn;
1145
1146     case op_lsub:
1147       BINOPL(-);
1148       goto next_insn;
1149
1150     case op_fsub:
1151       BINOPF(-);
1152       goto next_insn;
1153
1154     case op_dsub:
1155       BINOPD(-);
1156       goto next_insn;
1157
1158     case op_imul:
1159       BINOPI(*);
1160       goto next_insn;
1161
1162     case op_lmul:
1163       BINOPL(*);
1164       goto next_insn;
1165
1166     case op_fmul:
1167       BINOPF(*);
1168       goto next_insn;
1169
1170     case op_dmul:
1171       BINOPD(*);
1172       goto next_insn;
1173
1174     case op_idiv:
1175       {
1176         jint value2 = POPI();
1177         jint value1 = POPI();
1178         ZEROCHECK (value2);
1179         jint res = value1 / value2;
1180         PUSHI (res);
1181       }
1182       goto next_insn;
1183
1184     case op_ldiv:
1185        {
1186         jlong value2 = POPL();
1187         jlong value1 = POPL();
1188         ZEROCHECK (value2);
1189         jlong res = value1 / value2;
1190         PUSHL (res);
1191       }
1192       goto next_insn;
1193
1194     case op_fdiv:
1195       {
1196         jfloat value2 = POPF();
1197         jfloat value1 = POPF();
1198         ZEROCHECK (value2);
1199         jfloat res = value1 / value2;
1200         PUSHF (res);
1201       }
1202       goto next_insn;
1203
1204     case op_ddiv:
1205       {
1206         jdouble value2 = POPD();
1207         jdouble value1 = POPD();
1208         ZEROCHECK (value2);
1209         jdouble res = value1 / value2;
1210         PUSHD (res);
1211       }
1212       goto next_insn;
1213
1214     case op_irem:
1215       {
1216         jint value2 = POPI();
1217         jint value1 = POPI();
1218         ZEROCHECK (value2);     
1219         jint res = value1 % value2;
1220         PUSHI (res);
1221       }
1222       goto next_insn;
1223
1224     case op_lrem:
1225        {
1226         jlong value2 = POPL();
1227         jlong value1 = POPL();
1228         ZEROCHECK (value2);
1229         jlong res = value1 % value2;
1230         PUSHL (res);
1231       }
1232       goto next_insn;
1233
1234     case op_frem:
1235       {
1236         jfloat value2 = POPF();
1237         jfloat value1 = POPF();
1238         ZEROCHECK (value2);
1239         jfloat res    = __ieee754_fmod (value1, value2);
1240         PUSHF (res);
1241       }
1242       goto next_insn;
1243
1244     case op_drem:
1245       {
1246         jdouble value2 = POPD();
1247         jdouble value1 = POPD();
1248         ZEROCHECK (value2);
1249         jdouble res    = __ieee754_fmod (value1, value2);
1250         PUSHD (res);
1251       }
1252       goto next_insn;
1253
1254     case op_ineg:
1255       *(jint*) (sp-1) *= -1;
1256       goto next_insn;
1257
1258     case op_lneg:
1259       *(jlong*) (sp-1) *= -1;
1260       goto next_insn;
1261
1262     case op_fneg:
1263       *(jfloat*) (sp-1) *= -1;
1264       goto next_insn;
1265
1266     case op_dneg:
1267       *(jdouble*) (sp-1) *= -1;
1268       goto next_insn;
1269
1270     case op_ishl:
1271       {
1272         jint shift = (POPI() & 0x1f);
1273         jint value = POPI();
1274         PUSHI (value << shift);
1275       }
1276       goto next_insn;
1277
1278     case op_lshl:
1279       {
1280         jint shift = (POPI() & 0x3f);
1281         jlong value = POPL();
1282         PUSHL (value << shift);
1283       }
1284       goto next_insn;
1285
1286     case op_ishr:
1287       {
1288         jint shift = (POPI() & 0x1f);
1289         jint value = POPI();
1290         PUSHI (value >> shift);
1291       }
1292       goto next_insn;
1293
1294     case op_lshr:
1295       {
1296         jint shift = (POPI() & 0x3f);
1297         jlong value = POPL();
1298         PUSHL (value >> shift);
1299       }
1300       goto next_insn;
1301
1302     case op_iushr:
1303       {
1304         jint shift = (POPI() & 0x1f);
1305         unsigned long value = POPI();
1306         PUSHI ((jint) (value >> shift));
1307       }
1308       goto next_insn;
1309
1310     case op_lushr:
1311       {
1312         jint shift = (POPI() & 0x3f);
1313         UINT64 value = (UINT64) POPL();
1314         PUSHL ((value >> shift));
1315       }
1316       goto next_insn;
1317
1318     case op_iand:
1319       BINOPI (&);
1320       goto next_insn;
1321
1322     case op_land:
1323       BINOPL (&);
1324       goto next_insn;
1325
1326     case op_ior:
1327       BINOPI (|);
1328       goto next_insn;
1329
1330     case op_lor:
1331       BINOPL (|);
1332       goto next_insn;
1333
1334     case op_ixor:
1335       BINOPI (^);
1336       goto next_insn;
1337
1338     case op_lxor:
1339       BINOPL (^);
1340       goto next_insn;
1341
1342     case op_iinc:
1343       {
1344         jint index  = get1u (pc++);
1345         jint amount = get1s (pc++);
1346         *(jint*) (locals + index) += amount;
1347       }
1348       goto next_insn;
1349
1350     case op_i2l:
1351       {jlong value = POPI(); PUSHL (value);}
1352       goto next_insn;
1353
1354     case op_i2f:
1355       {jfloat value = POPI(); PUSHF (value);}
1356       goto next_insn;
1357
1358     case op_i2d:
1359       {jdouble value = POPI(); PUSHD (value);}
1360       goto next_insn;
1361
1362     case op_l2i:
1363       {jint value = POPL(); PUSHI (value);}
1364       goto next_insn;
1365
1366     case op_l2f:
1367       {jfloat value = POPL(); PUSHF (value);}
1368       goto next_insn;
1369
1370     case op_l2d:
1371       {jdouble value = POPL(); PUSHD (value);}
1372       goto next_insn;
1373
1374     case op_f2i:
1375       { jint value = (jint)POPF (); PUSHI(value); }
1376       goto next_insn;
1377
1378     case op_f2l:
1379       { jlong value = (jlong)POPF (); PUSHL(value); }
1380       goto next_insn;
1381
1382     case op_f2d:
1383       { jdouble value = POPF (); PUSHD(value); }
1384       goto next_insn;
1385
1386     case op_d2i:
1387       { jint value = (jint)POPD (); PUSHI(value); }
1388       goto next_insn;
1389
1390     case op_d2l:
1391       { jlong value = (jlong)POPD (); PUSHL(value); }
1392       goto next_insn;
1393
1394     case op_d2f:
1395       { jfloat value = POPD (); PUSHF(value); }
1396       goto next_insn;
1397
1398     case op_i2b:
1399       { jbyte value = POPI (); PUSHI(value); }
1400       goto next_insn;
1401
1402     case op_i2c:
1403       { jchar value = POPI (); PUSHI(value); }
1404       goto next_insn;
1405
1406     case op_i2s:
1407       { jshort value = POPI (); PUSHI(value); }
1408       goto next_insn;
1409
1410     case op_lcmp:
1411       {
1412         jlong value2 = POPL ();
1413         jlong value1 = POPL ();
1414         if (value1 > value2)
1415           { PUSHI (1); }
1416         else if (value1 == value2)
1417           { PUSHI (0); }
1418         else
1419           { PUSHI (-1); }
1420       }
1421       goto next_insn;
1422
1423     case op_fcmpl:
1424     case op_fcmpg:
1425       {
1426         jfloat value2 = POPF ();
1427         jfloat value1 = POPF ();
1428         if (value1 > value2)
1429           PUSHI (1);
1430         else if (value1 == value2)
1431           PUSHI (0);
1432         else if (value1 < value2)
1433           PUSHI (-1);
1434         else if (opcode == op_fcmpg)
1435           PUSHI (1);
1436         else
1437           PUSHI (-1);
1438       }
1439       goto next_insn;
1440
1441     case op_dcmpl:
1442     case op_dcmpg:
1443       {
1444         jdouble value2 = POPD ();
1445         jdouble value1 = POPD ();
1446         if (value1 > value2)
1447           PUSHI (1);
1448         else if (value1 == value2)
1449           PUSHI (0);
1450         else if (value1 < value2)
1451           PUSHI (-1);
1452         else if (opcode == op_dcmpg)
1453           PUSHI (1);
1454         else
1455           PUSHI (-1);
1456       }
1457       goto next_insn;
1458
1459     case op_ifeq:
1460       {
1461         jint offset = get2s (pc); 
1462         if (POPI() == 0)
1463           pc = pc-1+offset;
1464         else
1465           pc = pc+2;
1466       }
1467       goto next_insn;
1468
1469     case op_ifne:
1470       {
1471         jint offset = get2s (pc); 
1472         if (POPI() != 0)
1473           pc = pc-1+offset;
1474         else
1475           pc = pc+2;
1476       }
1477       goto next_insn;
1478
1479     case op_iflt:
1480       {
1481         jint offset = get2s (pc); 
1482         if (POPI() < 0)
1483           pc = pc-1+offset;
1484         else
1485           pc = pc+2;
1486       }
1487       goto next_insn;
1488
1489     case op_ifge:
1490       {
1491         jint offset = get2s (pc); 
1492         if (POPI() >= 0)
1493           pc = pc-1+offset;
1494         else
1495           pc = pc+2;
1496       }
1497       goto next_insn;
1498
1499     case op_ifgt:
1500       {
1501         jint offset = get2s (pc); 
1502         if (POPI() > 0)
1503           pc = pc-1+offset;
1504         else
1505           pc = pc+2;
1506       }
1507       goto next_insn;
1508
1509     case op_ifle:
1510       {
1511         jint offset = get2s (pc); 
1512         if (POPI() <= 0)
1513           pc = pc-1+offset;
1514         else
1515           pc = pc+2;
1516       }
1517       goto next_insn;
1518
1519     case op_if_icmpeq:
1520       {
1521         jint offset = get2s (pc); 
1522         jint value2 = POPI();
1523         jint value1 = POPI();
1524         if (value1 == value2)
1525           pc = pc-1+offset;
1526         else
1527           pc = pc+2;
1528       }
1529       goto next_insn;
1530
1531     case op_if_icmpne:
1532       {
1533         jint offset = get2s (pc); 
1534         jint value2 = POPI();
1535         jint value1 = POPI();
1536         if (value1 != value2)
1537           pc = pc-1+offset;
1538         else
1539           pc = pc+2;
1540       }
1541       goto next_insn;
1542
1543     case op_if_icmplt:
1544       {
1545         jint offset = get2s (pc); 
1546         jint value2 = POPI();
1547         jint value1 = POPI();
1548         if (value1 < value2)
1549           pc = pc-1+offset;
1550         else
1551           pc = pc+2;
1552       }
1553       goto next_insn;
1554
1555     case op_if_icmpge:
1556       {
1557         jint offset = get2s (pc); 
1558         jint value2 = POPI();
1559         jint value1 = POPI();
1560         if (value1 >= value2)
1561           pc = pc-1+offset;
1562         else
1563           pc = pc+2;
1564       }
1565       goto next_insn;
1566
1567     case op_if_icmpgt:
1568       {
1569         jint offset = get2s (pc); 
1570         jint value2 = POPI();
1571         jint value1 = POPI();
1572         if (value1 > value2)
1573           pc = pc-1+offset;
1574         else
1575           pc = pc+2;
1576       }
1577       goto next_insn;
1578
1579     case op_if_icmple:
1580       {
1581         jint offset = get2s (pc); 
1582         jint value2 = POPI();
1583         jint value1 = POPI();
1584         if (value1 <= value2)
1585           pc = pc-1+offset;
1586         else
1587           pc = pc+2;
1588       }
1589       goto next_insn;
1590
1591     case op_if_acmpeq:
1592       {
1593         jint offset = get2s (pc); 
1594         jobject value2 = POPA();
1595         jobject value1 = POPA();
1596         if (value1 == value2)
1597           pc = pc-1+offset;
1598         else
1599           pc = pc+2;
1600       }
1601       goto next_insn;
1602
1603     case op_if_acmpne:
1604       {
1605         jint offset = get2s (pc); 
1606         jobject value2 = POPA();
1607         jobject value1 = POPA();
1608         if (value1 != value2)
1609           pc = pc-1+offset;
1610         else
1611           pc = pc+2;
1612       }
1613       goto next_insn;
1614
1615     case op_goto: 
1616       {
1617         jint offset = get2s (pc);
1618         pc = pc-1+offset;
1619       }
1620       goto next_insn;
1621
1622     case op_jsr:
1623       {
1624         unsigned char *base_pc = pc-1;
1625         jint offset = get2s (pc); pc += 2;
1626         PUSHA ((jobject)pc);
1627         pc = base_pc+offset;
1628       }
1629       goto next_insn;
1630
1631     case op_ret:
1632       {
1633         jint index = get1u (pc);
1634         pc = (unsigned char*) PEEKA (index);
1635       }
1636       goto next_insn;
1637
1638     case op_tableswitch:
1639       {
1640         unsigned char *base_pc = pc-1;
1641         int index = POPI();
1642         
1643         unsigned char* base = bytecode ();
1644         while ((pc-base) % 4 != 0)
1645           pc++;
1646
1647         jint def     = get4 (pc);
1648         jint low     = get4 (pc+4);
1649         jint high    = get4 (pc+8);
1650
1651         if (index < low || index > high)
1652           pc = base_pc + def;    
1653         else
1654           pc = base_pc + get4 (pc+4*(index-low+3));
1655       }
1656       goto next_insn;
1657
1658     case op_lookupswitch:
1659       {
1660         unsigned char *base_pc = pc-1;
1661         int index = POPI();
1662         
1663         unsigned char* base = bytecode ();
1664         while ((pc-base) % 4 != 0)
1665           pc++;
1666         
1667         jint def     = get4 (pc);
1668         jint npairs  = get4 (pc+4);
1669         
1670         int max = npairs-1;
1671         int min = 0;
1672
1673         // simple binary search...
1674         while (min < max)
1675           {
1676             int half = (min+max)/2;
1677             int match = get4 (pc+ 4*(2 + 2*half));
1678
1679             if (index == match)
1680               min = max = half;
1681
1682             else if (index < match)
1683               max = half-1;
1684             
1685             else
1686               min = half+1;
1687           }
1688         
1689         if (index == get4 (pc+ 4*(2 + 2*min)))
1690           pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1691         else
1692           pc = base_pc + def;    
1693       }
1694       goto next_insn;
1695
1696       /* on return, just save the sp and return to caller */
1697     case op_ireturn:
1698     case op_lreturn:
1699     case op_freturn:
1700     case op_dreturn:
1701     case op_areturn:
1702     case op_return:
1703       inv->sp = sp;
1704       TIME_SUSPEND;
1705       return;
1706
1707     case op_getstatic:
1708       {
1709         unsigned char *base_pc = pc-1;
1710         jint fieldref_index = get2u (pc); pc += 2;
1711         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1712         _Jv_Field *field = pool_data[fieldref_index].field;
1713
1714         if ((field->flags & STATIC) == 0)
1715           throw_incompatible_class_change_error 
1716             (JvNewStringLatin1 ("field no longer static"));
1717
1718         jclass type = field->type;
1719
1720         if (type->isPrimitive ())
1721           {
1722             switch (type->size_in_bytes)
1723               {
1724               case 1:
1725                 *base_pc = op_getstatic_1;
1726                 break;
1727             
1728               case 2:
1729                 if (type == JvPrimClass (char))
1730                   *base_pc = op_getstatic_2u;
1731                 else
1732                   *base_pc = op_getstatic_2s;
1733                 break;
1734
1735               case 4:
1736                 *base_pc = op_getstatic_4;
1737                 break;
1738
1739               case 8:
1740                 *base_pc = op_getstatic_8;
1741                 break;
1742               }
1743           }
1744         else
1745           {
1746             *base_pc = op_getstatic_a;
1747           }
1748         
1749         pc = base_pc;
1750       }
1751       goto next_insn;
1752
1753     case op_getfield:
1754       {
1755         unsigned char *base_pc = pc-1;
1756         jint fieldref_index = get2u (pc); pc += 2;
1757         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1758         _Jv_Field *field = pool_data[fieldref_index].field;
1759
1760         if ((field->flags & STATIC) != 0)
1761           throw_incompatible_class_change_error 
1762             (JvNewStringLatin1 ("field is static"));
1763
1764         jclass type = field->type;
1765
1766         if (type->isPrimitive ())
1767           {
1768             switch (type->size_in_bytes)
1769               {
1770               case 1:
1771                 *base_pc = op_getfield_1;
1772                 break;
1773             
1774               case 2:
1775                 if (type == JvPrimClass (char))
1776                   *base_pc = op_getfield_2u;
1777                 else
1778                   *base_pc = op_getfield_2s;
1779                 break;
1780
1781               case 4:
1782                 *base_pc = op_getfield_4;
1783                 break;
1784
1785               case 8:
1786                 *base_pc = op_getfield_8;
1787                 break;
1788               }
1789           }
1790         else
1791           {
1792             *base_pc = op_getfield_a;
1793           }
1794         
1795         if (field->u.boffset > 0xffff)
1796           JvThrow (new java::lang::VirtualMachineError);
1797
1798         base_pc[1] = (field->u.boffset>>8) & 0xff;
1799         base_pc[2] = field->u.boffset & 0xff;
1800
1801         pc = base_pc;
1802       }
1803       goto next_insn;
1804
1805     case op_putstatic:
1806       {
1807         unsigned char* base_pc = pc-1;
1808         jint fieldref_index = get2u (pc); pc += 2;
1809         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1810         _Jv_Field *field = pool_data[fieldref_index].field;
1811
1812         jclass type = field->type;
1813
1814         // ResolvePoolEntry cannot check this
1815         if ((field->flags & STATIC) == 0)
1816           throw_incompatible_class_change_error 
1817             (JvNewStringLatin1 ("field no longer static"));
1818
1819         /* if this is patented, then maybe we could install
1820            a function in the constant pool, to do the right thing */
1821
1822         if (type->isPrimitive ())
1823           {
1824             switch (type->size_in_bytes) 
1825               {
1826               case 1:
1827                 *base_pc = op_putstatic_1;
1828                 break;
1829
1830               case 2:
1831                 *base_pc = op_putstatic_2;
1832                 break;
1833                 
1834               case 4:
1835                 *base_pc = op_putstatic_4;
1836                 break;
1837                 
1838               case 8:
1839                 *base_pc = op_putstatic_8;
1840                 break;
1841               }
1842           }
1843         else
1844           {
1845             *base_pc = op_putstatic_a;
1846           }
1847
1848         // do the instruction again!
1849         pc = base_pc;
1850       }
1851       goto next_insn;
1852
1853
1854     case op_putfield:
1855       {
1856         unsigned char* base_pc = pc-1;
1857         jint fieldref_index = get2u (pc); pc += 2;
1858         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1859         _Jv_Field *field = pool_data[fieldref_index].field;
1860
1861         jclass type = field->type;
1862
1863         if ((field->flags & STATIC) != 0)
1864           throw_incompatible_class_change_error 
1865             (JvNewStringLatin1 ("field is static"));
1866
1867         if (type->isPrimitive ())
1868           {
1869             switch (type->size_in_bytes) 
1870               {
1871               case 1:
1872                 *base_pc = op_putfield_1;
1873                 break;
1874
1875               case 2:
1876                 *base_pc = op_putfield_2;
1877                 break;
1878
1879               case 4:
1880                 *base_pc = op_putfield_4;
1881                 break;
1882
1883               case 8:
1884                 *base_pc = op_putfield_8;
1885                 break;
1886               }
1887           }
1888         else
1889           {
1890             *base_pc = op_putfield_a;
1891           }
1892
1893         if (field->u.boffset > 0xffff)
1894           JvThrow (new java::lang::VirtualMachineError);
1895
1896         base_pc[1] = (field->u.boffset>>8) & 0xff;
1897         base_pc[2] = field->u.boffset & 0xff;
1898
1899         // do the instruction again!
1900         pc = base_pc;
1901       }
1902       goto next_insn;
1903
1904
1905     case op_getfield_1:
1906       {
1907         jobject obj   = POPA();
1908         NULLCHECK(obj);
1909         jint field_offset = get2u (pc); pc += 2;
1910         PUSHI (*(jbyte*) ((char*)obj + field_offset));
1911       }
1912       goto next_insn;
1913
1914     case op_getfield_2s:
1915       {
1916         jobject obj   = POPA();
1917         NULLCHECK(obj);
1918         jint field_offset = get2u (pc); pc += 2;
1919         PUSHI (*(jshort*) ((char*)obj + field_offset));
1920       }
1921       goto next_insn;
1922
1923     case op_getfield_2u:
1924       {
1925         jobject obj   = POPA();
1926         NULLCHECK(obj);
1927         jint field_offset = get2u (pc); pc += 2;
1928         PUSHI (*(jchar*) ((char*)obj + field_offset));
1929       }
1930       goto next_insn;
1931
1932     case op_getfield_8:
1933       {
1934         jobject obj   = POPA();
1935         NULLCHECK(obj);
1936         jint field_offset = get2u (pc); pc += 2;
1937         PUSHL(*(jlong*) ((char*)obj + field_offset));
1938       }
1939       goto next_insn;
1940
1941     case op_getstatic_1:
1942       {
1943         jint fieldref_index = get2u (pc); pc += 2;
1944         _Jv_Field *field = pool_data[fieldref_index].field;
1945         PUSHI (*(jbyte*) (field->u.addr));
1946       }
1947       goto next_insn;
1948
1949     case op_getstatic_2s:
1950       {
1951         jint fieldref_index = get2u (pc); pc += 2;
1952         _Jv_Field *field = pool_data[fieldref_index].field;
1953         PUSHI(*(jshort*) (field->u.addr));
1954       }
1955       goto next_insn;
1956
1957     case op_getstatic_2u:
1958       {
1959         jint fieldref_index = get2u (pc); pc += 2;
1960         _Jv_Field *field = pool_data[fieldref_index].field;
1961         PUSHI(*(jchar*) (field->u.addr));
1962       }
1963       goto next_insn;
1964
1965     case op_getstatic_4:
1966       {
1967         jint fieldref_index = get2u (pc); pc += 2;
1968         _Jv_Field *field = pool_data[fieldref_index].field;
1969         PUSHI(*(jint*) (field->u.addr));
1970       }
1971       goto next_insn;
1972
1973     case op_getstatic_8:
1974       {
1975         jint fieldref_index = get2u (pc); pc += 2;
1976         _Jv_Field *field = pool_data[fieldref_index].field;
1977         PUSHL(*(jlong*) (field->u.addr));
1978       }
1979       goto next_insn;
1980
1981     case op_getstatic_a:
1982       {
1983         jint fieldref_index = get2u (pc); pc += 2;
1984         _Jv_Field *field = pool_data[fieldref_index].field;
1985         PUSHA(*(jobject*) (field->u.addr));
1986       }
1987       goto next_insn;
1988
1989     case op_putfield_1:
1990       {
1991         jint    value = POPI();
1992         jobject obj   = POPA();
1993         NULLCHECK(obj);
1994         jint field_offset = get2u (pc); pc += 2;
1995         *(jbyte*) ((char*)obj + field_offset) = value;
1996       }
1997       goto next_insn;
1998
1999     case op_putfield_2:
2000       {
2001         jint    value = POPI();
2002         jobject obj   = POPA();
2003         NULLCHECK(obj);
2004         jint field_offset = get2u (pc); pc += 2;
2005         *(jchar*) ((char*)obj + field_offset) = value;
2006       }
2007       goto next_insn;
2008
2009     case op_putfield_4:
2010       {
2011         jint    value = POPI();
2012         jobject obj   = POPA();
2013         NULLCHECK(obj);
2014         jint field_offset = get2u (pc); pc += 2;
2015         *(jint*) ((char*)obj + field_offset) = value;
2016       }
2017       goto next_insn;
2018
2019     case op_putfield_8:
2020       {
2021         jlong   value = POPL();
2022         jobject obj   = POPA();
2023         NULLCHECK(obj);
2024         jint field_offset = get2u (pc); pc += 2;
2025         *(jlong*) ((char*)obj + field_offset) = value;
2026       }
2027       goto next_insn;
2028
2029     case op_putfield_a:
2030       {
2031         jobject value = POPA();
2032         jobject obj   = POPA();
2033         NULLCHECK(obj);
2034         jint field_offset = get2u (pc); pc += 2;
2035         *(jobject*) ((char*)obj + field_offset) = value;
2036       }
2037       goto next_insn;
2038
2039     case op_putstatic_1:
2040       {
2041         jint    value = POPI();
2042         jint fieldref_index = get2u (pc); pc += 2;
2043         _Jv_Field *field = pool_data[fieldref_index].field;
2044         *(jbyte*) (field->u.addr) = value;
2045       }
2046       goto next_insn;
2047
2048     case op_putstatic_2:
2049       {
2050         jint    value = POPI();
2051         jint fieldref_index = get2u (pc); pc += 2;
2052         _Jv_Field *field = pool_data[fieldref_index].field;
2053         *(jchar*) (field->u.addr) = value;
2054       }
2055       goto next_insn;
2056
2057     case op_putstatic_4:
2058       {
2059         jint    value = POPI();
2060         jint fieldref_index = get2u (pc); pc += 2;
2061         _Jv_Field *field = pool_data[fieldref_index].field;
2062         *(jint*) (field->u.addr) = value;
2063       }
2064       goto next_insn;
2065
2066     case op_putstatic_8:
2067       {
2068         jlong    value = POPL();
2069         jint fieldref_index = get2u (pc); pc += 2;
2070         _Jv_Field *field = pool_data[fieldref_index].field;
2071         *(jlong*) (field->u.addr) = value;
2072       }
2073       goto next_insn;
2074
2075     case op_putstatic_a:
2076       {
2077         jobject value = POPA();
2078         jint fieldref_index = get2u (pc); pc += 2;
2079         _Jv_Field *field = pool_data[fieldref_index].field;
2080         *(jobject*) (field->u.addr) = value;
2081       }
2082       goto next_insn;
2083
2084     case op_invokespecial:
2085       {
2086         int index = get2u (pc); pc += 2;
2087
2088         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2089
2090         sp -= rmeth->stack_item_count;
2091         
2092         NULLCHECK(sp[0]);
2093
2094         fun = (void (*) (...))rmeth->method->ncode;
2095       }
2096       goto perform_invoke;
2097
2098     case op_invokestatic:
2099       {
2100         int index = get2u (pc); pc += 2;
2101
2102         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2103
2104         sp -= rmeth->stack_item_count;
2105         
2106         _Jv_InitClass (rmeth->klass);
2107         fun = (void (*) (...))rmeth->method->ncode;
2108       }
2109       goto perform_invoke;
2110
2111     case op_invokeinterface:
2112       {
2113         int index = get2u (pc); pc += 2;
2114
2115         // invokeinterface has two unused bytes...
2116         pc += 2;
2117
2118         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2119
2120         sp -= rmeth->stack_item_count;
2121         NULLCHECK(sp[0]);
2122         
2123         jobject rcv = sp[0].o;
2124
2125         fun = (void (*) (...))
2126           _Jv_LookupInterfaceMethod (rcv->getClass (),
2127                                      rmeth->method->name,
2128                                      rmeth->method->signature);
2129       }
2130       goto perform_invoke;
2131
2132
2133     case op_new:
2134       {
2135         int index = get2u (pc); pc += 2;
2136         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2137         _Jv_InitClass (klass);
2138         jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2139         PUSHA (res);
2140       }
2141       goto next_insn;
2142
2143     case op_newarray:
2144       {
2145         int atype = get1u (pc++);
2146         int size  = POPI();
2147         jobject result = _Jv_NewArray (atype, size);
2148         PUSHA (result);
2149       }
2150       goto next_insn;
2151       
2152     case op_anewarray:
2153       {
2154         int index = get2u (pc); pc += 2;
2155         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2156         int size  = POPI();
2157         _Jv_InitClass (klass);
2158         jobject result = _Jv_NewObjectArray (size, klass, 0);
2159         PUSHA (result);
2160       }
2161       goto next_insn;
2162
2163     case op_arraylength:
2164       {
2165         __JArray *arr = (__JArray*)POPA();
2166         PUSHI (arr->length);
2167       }
2168       goto next_insn;
2169
2170     case op_athrow:
2171       {
2172         jobject value = POPA();
2173         TIME_SUSPEND;
2174         JvThrow (value);
2175       }
2176       goto next_insn;
2177
2178     case op_checkcast:
2179       {
2180         jobject value = POPA();
2181         jint index = get2u (pc); pc += 2;
2182         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2183
2184         if (value != NULL && ! to->isInstance (value))
2185           {
2186             TIME_SUSPEND;
2187             JvThrow (new java::lang::ClassCastException
2188                      (to->getName()));
2189           }
2190
2191         PUSHA (value);
2192       }
2193       goto next_insn;
2194
2195     case op_instanceof:
2196       {
2197         jobject value = POPA();
2198         jint index = get2u (pc); pc += 2;
2199         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2200         PUSHI (to->isInstance (value));
2201       }
2202       goto next_insn;
2203
2204     case op_monitorenter:
2205       {
2206         jobject value = POPA();
2207         NULLCHECK(value);
2208         _Jv_MonitorEnter (value);
2209       }
2210       goto next_insn;
2211
2212     case op_monitorexit:
2213       {
2214         jobject value = POPA();
2215         NULLCHECK(value);
2216         _Jv_MonitorExit (value);
2217       }
2218       goto next_insn;
2219
2220     case op_ifnull:
2221       {
2222         unsigned char* base_pc = pc-1;
2223         jint offset = get2s (pc); pc += 2;
2224         jobject val = POPA();
2225         if (val == NULL)
2226           pc = base_pc+offset;
2227       }
2228       goto next_insn;
2229
2230     case op_ifnonnull:
2231       {
2232         unsigned char* base_pc = pc-1;
2233         jint offset = get2s (pc); pc += 2;
2234         jobject val = POPA();
2235         if (val != NULL)
2236           pc = base_pc+offset;
2237       }
2238       goto next_insn;
2239
2240     case op_wide:
2241       {
2242         jint the_mod_op = get1u (pc++);
2243         jint wide       = get2u (pc); pc += 2;
2244
2245         switch (the_mod_op)
2246           {
2247           case op_istore:
2248             STOREI (wide);
2249             goto next_insn;
2250
2251           case op_fstore:
2252             STOREF (wide);
2253             goto next_insn;
2254
2255           case op_astore:
2256             STOREA (wide);
2257             goto next_insn;
2258
2259           case op_lload:
2260             LOADL (wide);
2261             goto next_insn;
2262
2263           case op_dload:
2264             LOADD (wide);
2265             goto next_insn;
2266
2267           case op_iload:
2268             LOADI (wide);
2269             goto next_insn;
2270
2271           case op_aload:
2272             LOADA (wide);
2273             goto next_insn;
2274
2275           case op_lstore:
2276             STOREL (wide);
2277             goto next_insn;
2278
2279           case op_dstore:
2280             STORED (wide);
2281             goto next_insn;
2282
2283           case op_ret:
2284             pc = (unsigned char*) PEEKA (wide);
2285             goto next_insn;
2286
2287           case op_iinc:
2288             {
2289               jint amount = get2s (pc); pc += 2;
2290               jint value = PEEKI (wide);
2291               POKEI (wide, value+amount);
2292             }
2293             goto next_insn;
2294
2295           default:
2296             throw_internal_error ("illegal bytecode modified by wide");
2297           }
2298
2299       }
2300
2301     case op_multianewarray:
2302       {
2303         int kind_index = get2u (pc); pc += 2;
2304         int dim        = get1u (pc); pc += 1;
2305
2306         jclass type    
2307           = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2308         _Jv_InitClass (type);
2309         jint *sizes    = (jint*) alloca (sizeof (jint)*dim);
2310
2311         for (int i = dim - 1; i >= 0; i--)
2312           {
2313             sizes[i] = POPI ();
2314           }
2315         
2316         jobject res    = _Jv_NewMultiArray (type,dim, sizes);
2317         
2318         PUSHA (res);
2319       }
2320       goto next_insn;
2321
2322     case op_goto_w:
2323       {
2324         unsigned char* base_pc = pc-1;
2325         int offset = get4 (pc); pc += 4;
2326         pc = base_pc+offset;
2327       }
2328       goto next_insn;
2329
2330     case op_jsr_w:
2331       {
2332         unsigned char* base_pc = pc-1;
2333         int offset = get4 (pc); pc += 4;
2334         PUSHA((jobject)pc);
2335         pc = base_pc+offset;
2336       }
2337       goto next_insn;
2338
2339     default:
2340       throw_internal_error ("opcode not implemented");
2341
2342     }
2343   goto next_insn;
2344 }
2345
2346
2347 static void
2348 throw_internal_error (char *msg)
2349 {
2350   JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2351 }
2352
2353 static void 
2354 throw_incompatible_class_change_error (jstring msg)
2355 {
2356   JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2357 }
2358
2359 #if !HANDLE_SEGV
2360 static java::lang::NullPointerException *null_pointer_exc;
2361 static void 
2362 throw_null_pointer_exception ()
2363 {
2364   if (null_pointer_exc == NULL)
2365     null_pointer_exc = new java::lang::NullPointerException;
2366
2367   JvThrow (null_pointer_exc);
2368 }
2369 #endif
2370
2371 #if !HANDLE_FPE
2372 static java::lang::ArithmeticException *arithmetic_exc;
2373 static void 
2374 throw_arithmetic_exception ()
2375 {
2376   if (arithmetic_exc == NULL)
2377     arithmetic_exc = new java::lang::ArithmeticException
2378       (JvNewStringLatin1 ("/ by zero"));
2379
2380   JvThrow (arithmetic_exc);
2381 }
2382 #endif
2383
2384 void
2385 jvdump(jobject o)
2386 {
2387   _Jv_InterpMethod::dump_object(o);
2388 }
2389
2390 /* FIXME: This is not finished! */
2391 void
2392 _Jv_InterpMethod::dump_object(jobject o)
2393 {
2394   java::io::PrintStream *out = java::lang::System::out;
2395
2396   if (o == NULL)
2397     {
2398       out->println (JvNewStringLatin1 ("<null>"));
2399       return;
2400     }
2401
2402   jclass klass = o->getClass ();
2403
2404   out->print (klass->getName ());
2405   out->print (JvNewStringLatin1 ("@0x"));
2406   out->print (java::lang::Integer::toHexString ((jint)o));
2407   out->print (JvNewStringLatin1 ("{"));
2408 #if 0
2409   while (klass && klass != &ObjectClass)
2410     {
2411       _Jv_Field *fields = klass->fields;
2412       int max           = klass->field_count;
2413       
2414       for (int i = 0; i < max; ++i)
2415         {
2416           out->print (_Jv_NewStringUTF (field->name->data));
2417           out->print (JvNewStringLatin1 ("="));
2418
2419           if (JvFieldIsRef (field))
2420             {
2421               if (field->flags & STATIC)
2422                 out->print (JvGetSt)
2423             }
2424           field = field->getNextInstanceField ();
2425
2426           if (i+1 < max && klass->getSuperclass () != null)
2427             out->print (JvNewStringLatin1 ("; "));
2428         }
2429
2430       klass = klass->getSuperclass();
2431     }
2432 #endif
2433   out->print (JvNewStringLatin1 ("}\n"));
2434
2435 }
2436
2437 #endif // INTERPRETER