OSDN Git Service

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