OSDN Git Service

* java/rmi/activation/ActivationDesc.java,
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
13 #include <config.h>
14
15 // Define this to get the direct-threaded interpreter.  If undefined,
16 // we revert to a basic bytecode interpreter.  The former is faster
17 // but uses more memory.
18 #define DIRECT_THREADED
19
20 #pragma implementation "java-interp.h"
21
22 #include <jvm.h>
23 #include <java-cpool.h>
24 #include <java-interp.h>
25 #include <java/lang/System.h>
26 #include <java/lang/String.h>
27 #include <java/lang/Integer.h>
28 #include <java/lang/Long.h>
29 #include <java/lang/StringBuffer.h>
30 #include <java/lang/Class.h>
31 #include <java/lang/reflect/Modifier.h>
32 #include <java/lang/ClassCastException.h>
33 #include <java/lang/VirtualMachineError.h>
34 #include <java/lang/InternalError.h>
35 #include <java/lang/NullPointerException.h>
36 #include <java/lang/ArithmeticException.h>
37 #include <java/lang/IncompatibleClassChangeError.h>
38 #include <java/lang/Thread.h>
39 #include <java-insns.h>
40 #include <java-signal.h>
41
42 #ifdef INTERPRETER
43
44 #include <stdlib.h>
45
46 using namespace gcj;
47
48 static void throw_internal_error (char *msg)
49   __attribute__ ((__noreturn__));
50 static void throw_incompatible_class_change_error (jstring msg)
51   __attribute__ ((__noreturn__));
52 #ifndef HANDLE_SEGV
53 static void throw_null_pointer_exception ()
54   __attribute__ ((__noreturn__));
55 #endif
56
57 extern "C" double __ieee754_fmod (double,double);
58
59 // This represents a single slot in the "compiled" form of the
60 // bytecode.
61 union insn_slot
62 {
63   // Address of code.
64   void *insn;
65   // An integer value used by an instruction.
66   jint int_val;
67   // A pointer value used by an instruction.
68   void *datum;
69 };
70
71 // The type of the PC depends on whether we're doing direct threading
72 // or a more ordinary bytecode interpreter.
73 #ifdef DIRECT_THREADED
74 typedef insn_slot *pc_t;
75 #else
76 typedef unsigned char *pc_t;
77 #endif
78
79 static inline void dupx (_Jv_word *sp, int n, int x)
80 {
81   // first "slide" n+x elements n to the right
82   int top = n-1;
83   for (int i = 0; i < n+x; i++)
84     {
85       sp[(top-i)] = sp[(top-i)-n];
86     }
87   
88   // next, copy the n top elements, n+x down
89   for (int i = 0; i < n; i++)
90     {
91       sp[top-(n+x)-i] = sp[top-i];
92     }
93   
94 };
95
96 // Used to convert from floating types to integral types.
97 template<typename TO, typename FROM>
98 static inline TO
99 convert (FROM val, TO min, TO max)
100 {
101   TO ret;
102   if (val >= (FROM) max)
103     ret = max;
104   else if (val <= (FROM) min)
105     ret = min;
106   else if (val != val)
107     ret = 0;
108   else
109     ret = (TO) val;
110   return ret;
111 }
112
113 #define PUSHA(V)  (sp++)->o = (V)
114 #define PUSHI(V)  (sp++)->i = (V)
115 #define PUSHF(V)  (sp++)->f = (V)
116 #if SIZEOF_VOID_P == 8
117 # define PUSHL(V)   (sp->l = (V), sp += 2)
118 # define PUSHD(V)   (sp->d = (V), sp += 2)
119 #else
120 # define PUSHL(V)  do { _Jv_word2 w2; w2.l=(V); \
121                         (sp++)->ia[0] = w2.ia[0]; \
122                         (sp++)->ia[0] = w2.ia[1]; } while (0)
123 # define PUSHD(V)  do { _Jv_word2 w2; w2.d=(V); \
124                         (sp++)->ia[0] = w2.ia[0]; \
125                         (sp++)->ia[0] = w2.ia[1]; } while (0)
126 #endif
127
128 #define POPA()    ((--sp)->o)
129 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
130 #define POPF()    ((jfloat) (--sp)->f)
131 #if SIZEOF_VOID_P == 8
132 # define POPL()   (sp -= 2, (jlong) sp->l)
133 # define POPD()   (sp -= 2, (jdouble) sp->d)
134 #else
135 # define POPL()    ({ _Jv_word2 w2; \
136                      w2.ia[1] = (--sp)->ia[0]; \
137                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
138 # define POPD()    ({ _Jv_word2 w2; \
139                      w2.ia[1] = (--sp)->ia[0]; \
140                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
141 #endif
142
143 #define LOADA(I)  (sp++)->o = locals[I].o
144 #define LOADI(I)  (sp++)->i = locals[I].i
145 #define LOADF(I)  (sp++)->f = locals[I].f
146 #if SIZEOF_VOID_P == 8
147 # define LOADL(I)  (sp->l = locals[I].l, sp += 2)
148 # define LOADD(I)  (sp->d = locals[I].d, sp += 2)
149 #else
150 # define LOADL(I)  do { jint __idx = (I); \
151                         (sp++)->ia[0] = locals[__idx].ia[0]; \
152                         (sp++)->ia[0] = locals[__idx+1].ia[0]; \
153                    } while (0)
154 # define LOADD(I)  LOADL(I)
155 #endif
156
157 #define STOREA(I) locals[I].o = (--sp)->o
158 #define STOREI(I) locals[I].i = (--sp)->i
159 #define STOREF(I) locals[I].f = (--sp)->f
160 #if SIZEOF_VOID_P == 8
161 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
162 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
163 #else
164 # define STOREL(I) do { jint __idx = (I); \
165                        locals[__idx+1].ia[0] = (--sp)->ia[0]; \
166                        locals[__idx].ia[0] = (--sp)->ia[0]; \
167                    } while (0)
168 # define STORED(I) STOREL(I)
169 #endif
170
171 #define PEEKI(I)  (locals+(I))->i
172 #define PEEKA(I)  (locals+(I))->o
173
174 #define POKEI(I,V)  ((locals+(I))->i = (V))
175
176
177 #define BINOPI(OP) { \
178    jint value2 = POPI(); \
179    jint value1 = POPI(); \
180    PUSHI(value1 OP value2); \
181 }
182
183 #define BINOPF(OP) { \
184    jfloat value2 = POPF(); \
185    jfloat value1 = POPF(); \
186    PUSHF(value1 OP value2); \
187 }
188
189 #define BINOPL(OP) { \
190    jlong value2 = POPL(); \
191    jlong value1 = POPL(); \
192    PUSHL(value1 OP value2); \
193 }
194
195 #define BINOPD(OP) { \
196    jdouble value2 = POPD(); \
197    jdouble value1 = POPD(); \
198    PUSHD(value1 OP value2); \
199 }
200
201 static inline jint get1s(unsigned char* loc) {
202   return *(signed char*)loc;
203 }
204
205 static inline jint get1u(unsigned char* loc) {
206   return *loc;
207 }
208
209 static inline jint get2s(unsigned char* loc) {
210   return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
211 }
212
213 static inline jint get2u(unsigned char* loc) {
214   return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
215 }
216
217 static jint get4(unsigned char* loc) {
218   return (((jint)(loc[0])) << 24) 
219        | (((jint)(loc[1])) << 16) 
220        | (((jint)(loc[2])) << 8) 
221        | (((jint)(loc[3])) << 0);
222 }
223
224
225 #ifdef HANDLE_SEGV
226 #define NULLCHECK(X) 
227 #define NULLARRAYCHECK(X)
228 #else
229 #define NULLCHECK(X) \
230   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
231 #define NULLARRAYCHECK(X) \
232   do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
233 #endif
234
235 #define ARRAYBOUNDSCHECK(array, index)                                        \
236   do                                                                          \
237     {                                                                         \
238       if (((unsigned) index) >= (unsigned) (array->length))                   \
239         _Jv_ThrowBadArrayIndex (index);                                       \
240     }                                                                         \
241   while (0)
242
243 void _Jv_InterpMethod::run_normal (ffi_cif *,
244                                    void* ret,
245                                    ffi_raw * args,
246                                    void* __this)
247 {
248   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
249   _this->run (ret, args);
250 }
251
252 void _Jv_InterpMethod::run_synch_object (ffi_cif *,
253                                          void* ret,
254                                          ffi_raw * args,
255                                          void* __this)
256 {
257   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
258
259   jobject rcv = (jobject) args[0].ptr;
260   JvSynchronize mutex (rcv);
261
262   _this->run (ret, args);
263 }
264
265 void _Jv_InterpMethod::run_synch_class (ffi_cif *,
266                                         void* ret,
267                                         ffi_raw * args,
268                                         void* __this)
269 {
270   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
271
272   jclass sync = _this->defining_class;
273   JvSynchronize mutex (sync);
274
275   _this->run (ret, args);
276 }
277
278 #ifdef DIRECT_THREADED
279 // "Compile" a method by turning it from bytecode to direct-threaded
280 // code.
281 void
282 _Jv_InterpMethod::compile (const void * const *insn_targets)
283 {
284   insn_slot *insns = NULL;
285   int next = 0;
286   unsigned char *codestart = bytecode ();
287   unsigned char *end = codestart + code_length;
288   _Jv_word *pool_data = defining_class->constants.data;
289
290 #define SET_ONE(Field, Value)                                                 \
291   do                                                                          \
292     {                                                                         \
293       if (first_pass)                                                         \
294         ++next;                                                               \
295       else                                                                    \
296         insns[next++].Field = Value;                                          \
297     }                                                                         \
298   while (0)
299
300 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
301 #define SET_INT(Value) SET_ONE (int_val, Value)
302 #define SET_DATUM(Value) SET_ONE (datum, Value)
303
304   // Map from bytecode PC to slot in INSNS.
305   int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
306   for (int i = 0; i < code_length; ++i)
307     pc_mapping[i] = -1;
308
309   for (int i = 0; i < 2; ++i)
310     {
311       jboolean first_pass = i == 0;
312
313       if (! first_pass)
314         {
315           insns = (insn_slot *) _Jv_Malloc (sizeof (insn_slot) * next);
316           next = 0;
317         }
318
319       unsigned char *pc = codestart;
320       while (pc < end)
321         {
322           int base_pc_val = pc - codestart;
323           if (first_pass)
324             pc_mapping[base_pc_val] = next;
325
326           java_opcode opcode = (java_opcode) *pc++;
327           // Just elide NOPs.
328           if (opcode == op_nop)
329             continue;
330           SET_INSN (insn_targets[opcode]);
331
332           switch (opcode)
333             {
334             case op_nop:
335             case op_aconst_null:
336             case op_iconst_m1:
337             case op_iconst_0:
338             case op_iconst_1:
339             case op_iconst_2:
340             case op_iconst_3:
341             case op_iconst_4:
342             case op_iconst_5:
343             case op_lconst_0:
344             case op_lconst_1:
345             case op_fconst_0:
346             case op_fconst_1:
347             case op_fconst_2:
348             case op_dconst_0:
349             case op_dconst_1:
350             case op_iload_0:
351             case op_iload_1:
352             case op_iload_2:
353             case op_iload_3:
354             case op_lload_0:
355             case op_lload_1:
356             case op_lload_2:
357             case op_lload_3:
358             case op_fload_0:
359             case op_fload_1:
360             case op_fload_2:
361             case op_fload_3:
362             case op_dload_0:
363             case op_dload_1:
364             case op_dload_2:
365             case op_dload_3:
366             case op_aload_0:
367             case op_aload_1:
368             case op_aload_2:
369             case op_aload_3:
370             case op_iaload:
371             case op_laload:
372             case op_faload:
373             case op_daload:
374             case op_aaload:
375             case op_baload:
376             case op_caload:
377             case op_saload:
378             case op_istore_0:
379             case op_istore_1:
380             case op_istore_2:
381             case op_istore_3:
382             case op_lstore_0:
383             case op_lstore_1:
384             case op_lstore_2:
385             case op_lstore_3:
386             case op_fstore_0:
387             case op_fstore_1:
388             case op_fstore_2:
389             case op_fstore_3:
390             case op_dstore_0:
391             case op_dstore_1:
392             case op_dstore_2:
393             case op_dstore_3:
394             case op_astore_0:
395             case op_astore_1:
396             case op_astore_2:
397             case op_astore_3:
398             case op_iastore:
399             case op_lastore:
400             case op_fastore:
401             case op_dastore:
402             case op_aastore:
403             case op_bastore:
404             case op_castore:
405             case op_sastore:
406             case op_pop:
407             case op_pop2:
408             case op_dup:
409             case op_dup_x1:
410             case op_dup_x2:
411             case op_dup2:
412             case op_dup2_x1:
413             case op_dup2_x2:
414             case op_swap:
415             case op_iadd:
416             case op_isub:
417             case op_imul:
418             case op_idiv:
419             case op_irem:
420             case op_ishl:
421             case op_ishr:
422             case op_iushr:
423             case op_iand:
424             case op_ior:
425             case op_ixor:
426             case op_ladd:
427             case op_lsub:
428             case op_lmul:
429             case op_ldiv:
430             case op_lrem:
431             case op_lshl:
432             case op_lshr:
433             case op_lushr:
434             case op_land:
435             case op_lor:
436             case op_lxor:
437             case op_fadd:
438             case op_fsub:
439             case op_fmul:
440             case op_fdiv:
441             case op_frem:
442             case op_dadd:
443             case op_dsub:
444             case op_dmul:
445             case op_ddiv:
446             case op_drem:
447             case op_ineg:
448             case op_i2b:
449             case op_i2c:
450             case op_i2s:
451             case op_lneg:
452             case op_fneg:
453             case op_dneg:
454             case op_i2l:
455             case op_i2f:
456             case op_i2d:
457             case op_l2i:
458             case op_l2f:
459             case op_l2d:
460             case op_f2i:
461             case op_f2l:
462             case op_f2d:
463             case op_d2i:
464             case op_d2l:
465             case op_d2f:
466             case op_lcmp:
467             case op_fcmpl:
468             case op_fcmpg:
469             case op_dcmpl:
470             case op_dcmpg:
471             case op_monitorenter:
472             case op_monitorexit:
473             case op_ireturn:
474             case op_lreturn:
475             case op_freturn:
476             case op_dreturn:
477             case op_areturn:
478             case op_return:
479             case op_athrow:
480             case op_arraylength:
481               // No argument, nothing else to do.
482               break;
483
484             case op_bipush:
485               SET_INT (get1s (pc));
486               ++pc;
487               break;
488
489             case op_ldc:
490               {
491                 int index = get1u (pc);
492                 ++pc;
493                 SET_DATUM (pool_data[index].o);
494               }
495               break;
496
497             case op_ret:
498             case op_iload:
499             case op_lload:
500             case op_fload:
501             case op_dload:
502             case op_aload:
503             case op_istore:
504             case op_lstore:
505             case op_fstore:
506             case op_dstore:
507             case op_astore:
508             case op_newarray:
509               SET_INT (get1u (pc));
510               ++pc;
511               break;
512
513             case op_iinc:
514               SET_INT (get1u (pc));
515               SET_INT (get1s (pc + 1));
516               pc += 2;
517               break;
518
519             case op_ldc_w:
520               {
521                 int index = get2u (pc);
522                 pc += 2;
523                 SET_DATUM (pool_data[index].o);
524               }
525               break;
526
527             case op_ldc2_w:
528               {
529                 int index = get2u (pc);
530                 pc += 2;
531                 SET_DATUM (&pool_data[index]);
532               }
533               break;
534
535             case op_sipush:
536               SET_INT (get2s (pc));
537               pc += 2;
538               break;
539
540             case op_new:
541             case op_getstatic:
542             case op_getfield:
543             case op_putfield:
544             case op_putstatic:
545             case op_anewarray:
546             case op_instanceof:
547             case op_checkcast:
548             case op_invokespecial:
549             case op_invokestatic:
550             case op_invokevirtual:
551               SET_INT (get2u (pc));
552               pc += 2;
553               break;
554
555             case op_multianewarray:
556               SET_INT (get2u (pc));
557               SET_INT (get1u (pc + 2));
558               pc += 3;
559               break;
560
561             case op_jsr:
562             case op_ifeq:
563             case op_ifne:
564             case op_iflt:
565             case op_ifge:
566             case op_ifgt:
567             case op_ifle:
568             case op_if_icmpeq:
569             case op_if_icmpne:
570             case op_if_icmplt:
571             case op_if_icmpge:
572             case op_if_icmpgt:
573             case op_if_icmple:
574             case op_if_acmpeq:
575             case op_if_acmpne:
576             case op_ifnull:
577             case op_ifnonnull:
578             case op_goto:
579               {
580                 int offset = get2s (pc);
581                 pc += 2;
582
583                 int new_pc = base_pc_val + offset;
584
585                 bool orig_was_goto = opcode == op_goto;
586
587                 // Thread jumps.  We limit the loop count; this lets
588                 // us avoid infinite loops if the bytecode contains
589                 // such.  `10' is arbitrary.
590                 int count = 10;
591                 while (codestart[new_pc] == op_goto && count-- > 0)
592                   new_pc += get2s (&codestart[new_pc + 1]);
593
594                 // If the jump takes us to a `return' instruction and
595                 // the original branch was an unconditional goto, then
596                 // we hoist the return.
597                 opcode = (java_opcode) codestart[new_pc];
598                 if (orig_was_goto
599                     && (opcode == op_ireturn || opcode == op_lreturn
600                         || opcode == op_freturn || opcode == op_dreturn
601                         || opcode == op_areturn || opcode == op_return))
602                   {
603                     --next;
604                     SET_INSN (insn_targets[opcode]);
605                   }
606                 else
607                   SET_DATUM (&insns[pc_mapping[new_pc]]);
608               }
609               break;
610
611             case op_tableswitch:
612               {
613                 while ((pc - codestart) % 4 != 0)
614                   ++pc;
615
616                 jint def = get4 (pc);
617                 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
618                 pc += 4;
619
620                 int low = get4 (pc);
621                 SET_INT (low);
622                 pc += 4;
623                 int high = get4 (pc);
624                 SET_INT (high);
625                 pc += 4;
626
627                 for (int i = low; i <= high; ++i)
628                   {
629                     SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
630                     pc += 4;
631                   }
632               }
633               break;
634
635             case op_lookupswitch:
636               {
637                 while ((pc - codestart) % 4 != 0)
638                   ++pc;
639
640                 jint def = get4 (pc);
641                 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
642                 pc += 4;
643
644                 jint npairs = get4 (pc);
645                 pc += 4;
646                 SET_INT (npairs);
647
648                 while (npairs-- > 0)
649                   {
650                     jint match = get4 (pc);
651                     jint offset = get4 (pc + 4);
652                     SET_INT (match);
653                     SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
654                     pc += 8;
655                   }
656               }
657               break;
658
659             case op_invokeinterface:
660               {
661                 jint index = get2u (pc);
662                 pc += 2;
663                 // We ignore the next two bytes.
664                 pc += 2;
665                 SET_INT (index);
666               }
667               break;
668
669             case op_wide:
670               {
671                 opcode = (java_opcode) get1u (pc);
672                 pc += 1;
673                 jint val = get2u (pc);
674                 pc += 2;
675
676                 // We implement narrow and wide instructions using the
677                 // same code in the interpreter.  So we rewrite the
678                 // instruction slot here.
679                 if (! first_pass)
680                   insns[next - 1].insn = (void *) insn_targets[opcode];
681                 SET_INT (val);
682
683                 if (opcode == op_iinc)
684                   {
685                     SET_INT (get2s (pc));
686                     pc += 2;
687                   }
688               }
689               break;
690
691             case op_jsr_w:
692             case op_goto_w:
693               {
694                 jint offset = get4 (pc);
695                 pc += 4;
696                 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
697               }
698               break;
699
700             // Some "can't happen" cases that we include for
701             // error-checking purposes.
702             case op_putfield_1:
703             case op_putfield_2:
704             case op_putfield_4:
705             case op_putfield_8:
706             case op_putfield_a:
707             case op_putstatic_1:
708             case op_putstatic_2:
709             case op_putstatic_4:
710             case op_putstatic_8:
711             case op_putstatic_a:
712             case op_getfield_1:
713             case op_getfield_2s:
714             case op_getfield_2u:
715             case op_getfield_4:
716             case op_getfield_8:
717             case op_getfield_a:
718             case op_getstatic_1:
719             case op_getstatic_2s:
720             case op_getstatic_2u:
721             case op_getstatic_4:
722             case op_getstatic_8:
723             case op_getstatic_a:
724             default:
725               // Fail somehow.
726               break;
727             }
728         }
729     }
730
731   // Now update exceptions.
732   _Jv_InterpException *exc = exceptions ();
733   for (int i = 0; i < exc_count; ++i)
734     {
735       exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
736       exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
737       exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
738       jclass handler = (_Jv_ResolvePoolEntry (defining_class,
739                                               exc[i].handler_type.i)).clazz;
740       exc[i].handler_type.p = handler;
741     }
742
743   prepared = insns;
744 }
745 #endif /* DIRECT_THREADED */
746
747 // This function exists so that the stack-tracing code can find the
748 // boundaries of the interpreter.
749 void
750 _Jv_StartOfInterpreter (void)
751 {
752 }
753
754 void
755 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
756 {
757   using namespace java::lang::reflect;
758
759   // FRAME_DESC registers this particular invocation as the top-most
760   // interpreter frame.  This lets the stack tracing code (for
761   // Throwable) print information about the method being interpreted
762   // rather than about the interpreter itself.  FRAME_DESC has a
763   // destructor so it cleans up automatically when the interpreter
764   // returns.
765   java::lang::Thread *thread = java::lang::Thread::currentThread();
766   _Jv_MethodChain frame_desc (this,
767                               (_Jv_MethodChain **) &thread->interp_frame);
768
769   _Jv_word stack[max_stack];
770   _Jv_word *sp = stack;
771
772   _Jv_word locals[max_locals];
773
774   /* Go straight at it!  the ffi raw format matches the internal
775      stack representation exactly.  At least, that's the idea.
776   */
777   memcpy ((void*) locals, (void*) args, args_raw_size);
778
779   _Jv_word *pool_data = defining_class->constants.data;
780
781   /* These three are temporaries for common code used by several
782      instructions.  */
783   void (*fun)();
784   _Jv_ResolvedMethod* rmeth;
785   int tmpval;
786
787 #define INSN_LABEL(op) &&insn_##op
788
789   static const void *const insn_target[] = 
790   {
791     INSN_LABEL(nop),
792     INSN_LABEL(aconst_null),
793     INSN_LABEL(iconst_m1),
794     INSN_LABEL(iconst_0),
795     INSN_LABEL(iconst_1),
796     INSN_LABEL(iconst_2),
797     INSN_LABEL(iconst_3),
798     INSN_LABEL(iconst_4),
799     INSN_LABEL(iconst_5),
800     INSN_LABEL(lconst_0),
801     INSN_LABEL(lconst_1),
802     INSN_LABEL(fconst_0),
803     INSN_LABEL(fconst_1),
804     INSN_LABEL(fconst_2),
805     INSN_LABEL(dconst_0),
806     INSN_LABEL(dconst_1),
807     INSN_LABEL(bipush),
808     INSN_LABEL(sipush),
809     INSN_LABEL(ldc),
810     INSN_LABEL(ldc_w),
811     INSN_LABEL(ldc2_w),
812     INSN_LABEL(iload),
813     INSN_LABEL(lload),
814     INSN_LABEL(fload),
815     INSN_LABEL(dload),
816     INSN_LABEL(aload),
817     INSN_LABEL(iload_0),
818     INSN_LABEL(iload_1),
819     INSN_LABEL(iload_2),
820     INSN_LABEL(iload_3),
821     INSN_LABEL(lload_0),
822     INSN_LABEL(lload_1),
823     INSN_LABEL(lload_2),
824     INSN_LABEL(lload_3),
825     INSN_LABEL(fload_0),
826     INSN_LABEL(fload_1),
827     INSN_LABEL(fload_2),
828     INSN_LABEL(fload_3),
829     INSN_LABEL(dload_0),
830     INSN_LABEL(dload_1),
831     INSN_LABEL(dload_2),
832     INSN_LABEL(dload_3),
833     INSN_LABEL(aload_0),
834     INSN_LABEL(aload_1),
835     INSN_LABEL(aload_2),
836     INSN_LABEL(aload_3),
837     INSN_LABEL(iaload),
838     INSN_LABEL(laload),
839     INSN_LABEL(faload),
840     INSN_LABEL(daload),
841     INSN_LABEL(aaload),
842     INSN_LABEL(baload),
843     INSN_LABEL(caload),
844     INSN_LABEL(saload),
845     INSN_LABEL(istore),
846     INSN_LABEL(lstore),
847     INSN_LABEL(fstore),
848     INSN_LABEL(dstore),
849     INSN_LABEL(astore),
850     INSN_LABEL(istore_0),
851     INSN_LABEL(istore_1),
852     INSN_LABEL(istore_2),
853     INSN_LABEL(istore_3),
854     INSN_LABEL(lstore_0),
855     INSN_LABEL(lstore_1),
856     INSN_LABEL(lstore_2),
857     INSN_LABEL(lstore_3),
858     INSN_LABEL(fstore_0),
859     INSN_LABEL(fstore_1),
860     INSN_LABEL(fstore_2),
861     INSN_LABEL(fstore_3),
862     INSN_LABEL(dstore_0),
863     INSN_LABEL(dstore_1),
864     INSN_LABEL(dstore_2),
865     INSN_LABEL(dstore_3),
866     INSN_LABEL(astore_0),
867     INSN_LABEL(astore_1),
868     INSN_LABEL(astore_2),
869     INSN_LABEL(astore_3),
870     INSN_LABEL(iastore),
871     INSN_LABEL(lastore),
872     INSN_LABEL(fastore),
873     INSN_LABEL(dastore),
874     INSN_LABEL(aastore),
875     INSN_LABEL(bastore),
876     INSN_LABEL(castore),
877     INSN_LABEL(sastore),
878     INSN_LABEL(pop),
879     INSN_LABEL(pop2),
880     INSN_LABEL(dup),
881     INSN_LABEL(dup_x1),
882     INSN_LABEL(dup_x2),
883     INSN_LABEL(dup2),
884     INSN_LABEL(dup2_x1),
885     INSN_LABEL(dup2_x2),
886     INSN_LABEL(swap),
887     INSN_LABEL(iadd),
888     INSN_LABEL(ladd),
889     INSN_LABEL(fadd),
890     INSN_LABEL(dadd),
891     INSN_LABEL(isub),
892     INSN_LABEL(lsub),
893     INSN_LABEL(fsub),
894     INSN_LABEL(dsub),
895     INSN_LABEL(imul),
896     INSN_LABEL(lmul),
897     INSN_LABEL(fmul),
898     INSN_LABEL(dmul),
899     INSN_LABEL(idiv),
900     INSN_LABEL(ldiv),
901     INSN_LABEL(fdiv),
902     INSN_LABEL(ddiv),
903     INSN_LABEL(irem),
904     INSN_LABEL(lrem),
905     INSN_LABEL(frem),
906     INSN_LABEL(drem),
907     INSN_LABEL(ineg),
908     INSN_LABEL(lneg),
909     INSN_LABEL(fneg),
910     INSN_LABEL(dneg),
911     INSN_LABEL(ishl),
912     INSN_LABEL(lshl),
913     INSN_LABEL(ishr),
914     INSN_LABEL(lshr),
915     INSN_LABEL(iushr),
916     INSN_LABEL(lushr),
917     INSN_LABEL(iand),
918     INSN_LABEL(land),
919     INSN_LABEL(ior),
920     INSN_LABEL(lor),
921     INSN_LABEL(ixor),
922     INSN_LABEL(lxor),
923     INSN_LABEL(iinc),
924     INSN_LABEL(i2l),
925     INSN_LABEL(i2f),
926     INSN_LABEL(i2d),
927     INSN_LABEL(l2i),
928     INSN_LABEL(l2f),
929     INSN_LABEL(l2d),
930     INSN_LABEL(f2i),
931     INSN_LABEL(f2l),
932     INSN_LABEL(f2d),
933     INSN_LABEL(d2i),
934     INSN_LABEL(d2l),
935     INSN_LABEL(d2f),
936     INSN_LABEL(i2b),
937     INSN_LABEL(i2c),
938     INSN_LABEL(i2s),
939     INSN_LABEL(lcmp),
940     INSN_LABEL(fcmpl),
941     INSN_LABEL(fcmpg),
942     INSN_LABEL(dcmpl),
943     INSN_LABEL(dcmpg),
944     INSN_LABEL(ifeq),
945     INSN_LABEL(ifne),
946     INSN_LABEL(iflt),
947     INSN_LABEL(ifge),
948     INSN_LABEL(ifgt),
949     INSN_LABEL(ifle),
950     INSN_LABEL(if_icmpeq),
951     INSN_LABEL(if_icmpne),
952     INSN_LABEL(if_icmplt),
953     INSN_LABEL(if_icmpge),
954     INSN_LABEL(if_icmpgt),
955     INSN_LABEL(if_icmple),
956     INSN_LABEL(if_acmpeq),
957     INSN_LABEL(if_acmpne),
958     INSN_LABEL(goto), 
959     INSN_LABEL(jsr),
960     INSN_LABEL(ret),
961     INSN_LABEL(tableswitch),
962     INSN_LABEL(lookupswitch),
963     INSN_LABEL(ireturn),
964     INSN_LABEL(lreturn),
965     INSN_LABEL(freturn),
966     INSN_LABEL(dreturn),
967     INSN_LABEL(areturn),
968     INSN_LABEL(return),
969     INSN_LABEL(getstatic),
970     INSN_LABEL(putstatic),
971     INSN_LABEL(getfield),
972     INSN_LABEL(putfield),
973     INSN_LABEL(invokevirtual),
974     INSN_LABEL(invokespecial),
975     INSN_LABEL(invokestatic),
976     INSN_LABEL(invokeinterface),
977     0, /* Unused.  */
978     INSN_LABEL(new),
979     INSN_LABEL(newarray),
980     INSN_LABEL(anewarray),
981     INSN_LABEL(arraylength),
982     INSN_LABEL(athrow),
983     INSN_LABEL(checkcast),
984     INSN_LABEL(instanceof),
985     INSN_LABEL(monitorenter),
986     INSN_LABEL(monitorexit),
987 #ifdef DIRECT_THREADED
988     0, // wide
989 #else
990     INSN_LABEL(wide),
991 #endif
992     INSN_LABEL(multianewarray),
993     INSN_LABEL(ifnull),
994     INSN_LABEL(ifnonnull),
995     INSN_LABEL(goto_w),
996     INSN_LABEL(jsr_w),
997     0
998   };
999
1000   pc_t pc;
1001
1002 #ifdef DIRECT_THREADED
1003
1004 #define NEXT_INSN goto *((pc++)->insn)
1005 #define INTVAL() ((pc++)->int_val)
1006 #define AVAL() ((pc++)->datum)
1007
1008 #define GET1S() INTVAL ()
1009 #define GET2S() INTVAL ()
1010 #define GET1U() INTVAL ()
1011 #define GET2U() INTVAL ()
1012 #define AVAL1U() AVAL ()
1013 #define AVAL2U() AVAL ()
1014 #define AVAL2UP() AVAL ()
1015 #define SKIP_GOTO ++pc
1016 #define GOTO_VAL() (insn_slot *) pc->datum
1017 #define PCVAL(unionval) unionval.p
1018 #define AMPAMP(label) &&label
1019
1020   // Compile if we must.
1021   if (prepared == NULL)
1022     compile (insn_target);
1023   pc = (insn_slot *) prepared;
1024
1025 #else
1026
1027 #define NEXT_INSN goto *(insn_target[*pc++])
1028
1029 #define GET1S() get1s (pc++)
1030 #define GET2S() (pc += 2, get2s (pc- 2))
1031 #define GET1U() get1u (pc++)
1032 #define GET2U() (pc += 2, get2u (pc - 2))
1033 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1034 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1035 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1036 #define SKIP_GOTO pc += 2
1037 #define GOTO_VAL() pc - 1 + get2s (pc)
1038 #define PCVAL(unionval) unionval.i
1039 #define AMPAMP(label) NULL
1040
1041   pc = bytecode ();
1042
1043 #endif /* DIRECT_THREADED */
1044
1045 #define TAKE_GOTO pc = GOTO_VAL ()
1046
1047   try
1048     {
1049       // We keep nop around.  It is used if we're interpreting the
1050       // bytecodes and not doing direct threading.
1051     insn_nop:
1052       NEXT_INSN;
1053
1054       /* The first few instructions here are ordered according to their
1055          frequency, in the hope that this will improve code locality a
1056          little.  */
1057
1058     insn_aload_0:               // 0x2a
1059       LOADA (0);
1060       NEXT_INSN;
1061
1062     insn_iload:         // 0x15
1063       LOADI (GET1U ());
1064       NEXT_INSN;
1065
1066     insn_iload_1:               // 0x1b
1067       LOADI (1);
1068       NEXT_INSN;
1069
1070     insn_invokevirtual: // 0xb6
1071       {
1072         int index = GET2U ();
1073
1074         /* _Jv_ResolvePoolEntry returns immediately if the value already
1075          * is resolved.  If we want to clutter up the code here to gain
1076          * a little performance, then we can check the corresponding bit
1077          * JV_CONSTANT_ResolvedFlag in the tag directly.  For now, I
1078          * don't think it is worth it.  */
1079
1080         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
1081
1082         sp -= rmeth->stack_item_count;
1083         // We don't use NULLCHECK here because we can't rely on that
1084         // working if the method is final.  So instead we do an
1085         // explicit test.
1086         if (! sp[0].o)
1087           throw new java::lang::NullPointerException;
1088
1089         if (rmeth->vtable_index == -1)
1090           {
1091             // final methods do not appear in the vtable,
1092             // if it does not appear in the superclass.
1093             fun = (void (*)()) rmeth->method->ncode;
1094           }
1095         else
1096           {
1097             jobject rcv = sp[0].o;
1098             _Jv_VTable *table = *(_Jv_VTable**) rcv;
1099             fun = (void (*)()) table->get_method (rmeth->vtable_index);
1100           }
1101
1102 #ifdef DIRECT_THREADED
1103         // Rewrite instruction so that we use a faster pre-resolved
1104         // method.
1105         pc[-2].insn = &&invokevirtual_resolved;
1106         pc[-1].datum = rmeth;
1107 #endif /* DIRECT_THREADED */
1108       }
1109       goto perform_invoke;
1110
1111 #ifdef DIRECT_THREADED
1112     invokevirtual_resolved:
1113       {
1114         rmeth = (_Jv_ResolvedMethod *) AVAL ();
1115         sp -= rmeth->stack_item_count;
1116         // We don't use NULLCHECK here because we can't rely on that
1117         // working if the method is final.  So instead we do an
1118         // explicit test.
1119         if (! sp[0].o)
1120           throw new java::lang::NullPointerException;
1121
1122         if (rmeth->vtable_index == -1)
1123           {
1124             // final methods do not appear in the vtable,
1125             // if it does not appear in the superclass.
1126             fun = (void (*)()) rmeth->method->ncode;
1127           }
1128         else
1129           {
1130             jobject rcv = sp[0].o;
1131             _Jv_VTable *table = *(_Jv_VTable**) rcv;
1132             fun = (void (*)()) table->get_method (rmeth->vtable_index);
1133           }
1134       }
1135       goto perform_invoke;
1136 #endif /* DIRECT_THREADED */
1137
1138     perform_invoke:
1139       {
1140         /* here goes the magic again... */
1141         ffi_cif *cif = &rmeth->cif;
1142         ffi_raw *raw = (ffi_raw*) sp;
1143
1144         jdouble rvalue;
1145
1146 #if FFI_NATIVE_RAW_API
1147         /* We assume that this is only implemented if it's correct      */
1148         /* to use it here.  On a 64 bit machine, it never is.           */
1149         ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1150 #else
1151         ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1152 #endif
1153
1154         int rtype = cif->rtype->type;
1155
1156         /* the likelyhood of object, int, or void return is very high,
1157          * so those are checked before the switch */
1158         if (rtype == FFI_TYPE_POINTER)
1159           {
1160             PUSHA (*(jobject*)&rvalue);
1161           }
1162         else if (rtype == FFI_TYPE_SINT32)
1163           {
1164             PUSHI (*(jint*)&rvalue);
1165           }
1166         else if (rtype == FFI_TYPE_VOID)
1167           {
1168             /* skip */
1169           }
1170         else
1171           {
1172             switch (rtype)
1173               {
1174               case FFI_TYPE_SINT8:
1175                 {
1176                   jbyte value = (*(jint*)&rvalue) & 0xff;
1177                   PUSHI (value);
1178                 }
1179                 break;
1180
1181               case FFI_TYPE_SINT16:
1182                 {
1183                   jshort value = (*(jint*)&rvalue) & 0xffff;
1184                   PUSHI (value);
1185                 }
1186                 break;
1187
1188               case FFI_TYPE_UINT16:
1189                 {
1190                   jint value = (*(jint*)&rvalue) & 0xffff;
1191                   PUSHI (value);
1192                 }
1193                 break;
1194
1195               case FFI_TYPE_FLOAT:
1196                 PUSHF (*(jfloat*)&rvalue);
1197                 break;
1198
1199               case FFI_TYPE_DOUBLE:
1200                 PUSHD (rvalue);
1201                 break;
1202
1203               case FFI_TYPE_SINT64:
1204                 PUSHL (*(jlong*)&rvalue);
1205                 break;
1206
1207               default:
1208                 throw_internal_error ("unknown return type in invokeXXX");
1209               }
1210           }
1211       }
1212       NEXT_INSN;
1213
1214     insn_aconst_null:
1215       PUSHA (NULL);
1216       NEXT_INSN;
1217
1218     insn_iconst_m1:
1219       PUSHI (-1);
1220       NEXT_INSN;
1221
1222     insn_iconst_0:
1223       PUSHI (0);
1224       NEXT_INSN;
1225
1226     insn_iconst_1:
1227       PUSHI (1);
1228       NEXT_INSN;
1229
1230     insn_iconst_2:
1231       PUSHI (2);
1232       NEXT_INSN;
1233
1234     insn_iconst_3:
1235       PUSHI (3);
1236       NEXT_INSN;
1237
1238     insn_iconst_4:
1239       PUSHI (4);
1240       NEXT_INSN;
1241
1242     insn_iconst_5:
1243       PUSHI (5);
1244       NEXT_INSN;
1245
1246     insn_lconst_0:
1247       PUSHL (0);
1248       NEXT_INSN;
1249
1250     insn_lconst_1:
1251       PUSHL (1);
1252       NEXT_INSN;
1253
1254     insn_fconst_0:
1255       PUSHF (0);
1256       NEXT_INSN;
1257
1258     insn_fconst_1:
1259       PUSHF (1);
1260       NEXT_INSN;
1261
1262     insn_fconst_2:
1263       PUSHF (2);
1264       NEXT_INSN;
1265
1266     insn_dconst_0:
1267       PUSHD (0);
1268       NEXT_INSN;
1269
1270     insn_dconst_1:
1271       PUSHD (1);
1272       NEXT_INSN;
1273
1274     insn_bipush:
1275       // For direct threaded, bipush and sipush are the same.
1276 #ifndef DIRECT_THREADED
1277       PUSHI (GET1S ());
1278       NEXT_INSN;
1279 #endif /* DIRECT_THREADED */
1280     insn_sipush:
1281       PUSHI (GET2S ());
1282       NEXT_INSN;
1283
1284     insn_ldc:
1285       // For direct threaded, ldc and ldc_w are the same.
1286 #ifndef DIRECT_THREADED
1287       PUSHA ((jobject) AVAL1U ());
1288       NEXT_INSN;
1289 #endif /* DIRECT_THREADED */
1290     insn_ldc_w:
1291       PUSHA ((jobject) AVAL2U ());
1292       NEXT_INSN;
1293
1294     insn_ldc2_w:
1295       {
1296         void *where = AVAL2UP ();
1297         memcpy (sp, where, 2*sizeof (_Jv_word));
1298         sp += 2;
1299       }
1300       NEXT_INSN;
1301
1302     insn_lload:
1303       LOADL (GET1U ());
1304       NEXT_INSN;
1305
1306     insn_fload:
1307       LOADF (GET1U ());
1308       NEXT_INSN;
1309
1310     insn_dload:
1311       LOADD (GET1U ());
1312       NEXT_INSN;
1313
1314     insn_aload:
1315       LOADA (GET1U ());
1316       NEXT_INSN;
1317
1318     insn_iload_0:
1319       LOADI (0);
1320       NEXT_INSN;
1321
1322     insn_iload_2:
1323       LOADI (2);
1324       NEXT_INSN;
1325
1326     insn_iload_3:
1327       LOADI (3);
1328       NEXT_INSN;
1329
1330     insn_lload_0:
1331       LOADL (0);
1332       NEXT_INSN;
1333
1334     insn_lload_1:
1335       LOADL (1);
1336       NEXT_INSN;
1337
1338     insn_lload_2:
1339       LOADL (2);
1340       NEXT_INSN;
1341
1342     insn_lload_3:
1343       LOADL (3);
1344       NEXT_INSN;
1345
1346     insn_fload_0:
1347       LOADF (0);
1348       NEXT_INSN;
1349
1350     insn_fload_1:
1351       LOADF (1);
1352       NEXT_INSN;
1353
1354     insn_fload_2:
1355       LOADF (2);
1356       NEXT_INSN;
1357
1358     insn_fload_3:
1359       LOADF (3);
1360       NEXT_INSN;
1361
1362     insn_dload_0:
1363       LOADD (0);
1364       NEXT_INSN;
1365
1366     insn_dload_1:
1367       LOADD (1);
1368       NEXT_INSN;
1369
1370     insn_dload_2:
1371       LOADD (2);
1372       NEXT_INSN;
1373
1374     insn_dload_3:
1375       LOADD (3);
1376       NEXT_INSN;
1377
1378     insn_aload_1:
1379       LOADA(1);
1380       NEXT_INSN;
1381
1382     insn_aload_2:
1383       LOADA(2);
1384       NEXT_INSN;
1385
1386     insn_aload_3:
1387       LOADA(3);
1388       NEXT_INSN;
1389
1390     insn_iaload:
1391       {
1392         jint index = POPI();
1393         jintArray arr = (jintArray) POPA();
1394         NULLARRAYCHECK (arr);
1395         ARRAYBOUNDSCHECK (arr, index);
1396         PUSHI( elements(arr)[index] );
1397       }
1398       NEXT_INSN;
1399
1400     insn_laload:
1401       {
1402         jint index = POPI();
1403         jlongArray arr = (jlongArray) POPA();
1404         NULLARRAYCHECK (arr);
1405         ARRAYBOUNDSCHECK (arr, index);
1406         PUSHL( elements(arr)[index] );
1407       }
1408       NEXT_INSN;
1409
1410     insn_faload:
1411       {
1412         jint index = POPI();
1413         jfloatArray arr = (jfloatArray) POPA();
1414         NULLARRAYCHECK (arr);
1415         ARRAYBOUNDSCHECK (arr, index);
1416         PUSHF( elements(arr)[index] );
1417       }
1418       NEXT_INSN;
1419
1420     insn_daload:
1421       {
1422         jint index = POPI();
1423         jdoubleArray arr = (jdoubleArray) POPA();
1424         NULLARRAYCHECK (arr);
1425         ARRAYBOUNDSCHECK (arr, index);
1426         PUSHD( elements(arr)[index] );
1427       }
1428       NEXT_INSN;
1429
1430     insn_aaload:
1431       {
1432         jint index = POPI();
1433         jobjectArray arr = (jobjectArray) POPA();
1434         NULLARRAYCHECK (arr);
1435         ARRAYBOUNDSCHECK (arr, index);
1436         PUSHA( elements(arr)[index] );
1437       }
1438       NEXT_INSN;
1439
1440     insn_baload:
1441       {
1442         jint index = POPI();
1443         jbyteArray arr = (jbyteArray) POPA();
1444         NULLARRAYCHECK (arr);
1445         ARRAYBOUNDSCHECK (arr, index);
1446         PUSHI( elements(arr)[index] );
1447       }
1448       NEXT_INSN;
1449
1450     insn_caload:
1451       {
1452         jint index = POPI();
1453         jcharArray arr = (jcharArray) POPA();
1454         NULLARRAYCHECK (arr);
1455         ARRAYBOUNDSCHECK (arr, index);
1456         PUSHI( elements(arr)[index] );
1457       }
1458       NEXT_INSN;
1459
1460     insn_saload:
1461       {
1462         jint index = POPI();
1463         jshortArray arr = (jshortArray) POPA();
1464         NULLARRAYCHECK (arr);
1465         ARRAYBOUNDSCHECK (arr, index);
1466         PUSHI( elements(arr)[index] );
1467       }
1468       NEXT_INSN;
1469
1470     insn_istore:
1471       STOREI (GET1U ());
1472       NEXT_INSN;
1473
1474     insn_lstore:
1475       STOREL (GET1U ());
1476       NEXT_INSN;
1477
1478     insn_fstore:
1479       STOREF (GET1U ());
1480       NEXT_INSN;
1481
1482     insn_dstore:
1483       STORED (GET1U ());
1484       NEXT_INSN;
1485
1486     insn_astore:
1487       STOREA (GET1U ());
1488       NEXT_INSN;
1489
1490     insn_istore_0:
1491       STOREI (0);
1492       NEXT_INSN;
1493
1494     insn_istore_1:
1495       STOREI (1);
1496       NEXT_INSN;
1497
1498     insn_istore_2:
1499       STOREI (2);
1500       NEXT_INSN;
1501
1502     insn_istore_3:
1503       STOREI (3);
1504       NEXT_INSN;
1505
1506     insn_lstore_0:
1507       STOREL (0);
1508       NEXT_INSN;
1509
1510     insn_lstore_1:
1511       STOREL (1);
1512       NEXT_INSN;
1513
1514     insn_lstore_2:
1515       STOREL (2);
1516       NEXT_INSN;
1517
1518     insn_lstore_3:
1519       STOREL (3);
1520       NEXT_INSN;
1521
1522     insn_fstore_0:
1523       STOREF (0);
1524       NEXT_INSN;
1525
1526     insn_fstore_1:
1527       STOREF (1);
1528       NEXT_INSN;
1529
1530     insn_fstore_2:
1531       STOREF (2);
1532       NEXT_INSN;
1533
1534     insn_fstore_3:
1535       STOREF (3);
1536       NEXT_INSN;
1537
1538     insn_dstore_0:
1539       STORED (0);
1540       NEXT_INSN;
1541
1542     insn_dstore_1:
1543       STORED (1);
1544       NEXT_INSN;
1545
1546     insn_dstore_2:
1547       STORED (2);
1548       NEXT_INSN;
1549
1550     insn_dstore_3:
1551       STORED (3);
1552       NEXT_INSN;
1553
1554     insn_astore_0:
1555       STOREA(0);
1556       NEXT_INSN;
1557
1558     insn_astore_1:
1559       STOREA(1);
1560       NEXT_INSN;
1561
1562     insn_astore_2:
1563       STOREA(2);
1564       NEXT_INSN;
1565
1566     insn_astore_3:
1567       STOREA(3);
1568       NEXT_INSN;
1569
1570     insn_iastore:
1571       {
1572         jint value = POPI();
1573         jint index  = POPI();
1574         jintArray arr = (jintArray) POPA();
1575         NULLARRAYCHECK (arr);
1576         ARRAYBOUNDSCHECK (arr, index);
1577         elements(arr)[index] = value;
1578       }
1579       NEXT_INSN;
1580
1581     insn_lastore:
1582       {
1583         jlong value = POPL();
1584         jint index  = POPI();
1585         jlongArray arr = (jlongArray) POPA();
1586         NULLARRAYCHECK (arr);
1587         ARRAYBOUNDSCHECK (arr, index);
1588         elements(arr)[index] = value;
1589       }
1590       NEXT_INSN;
1591
1592     insn_fastore:
1593       {
1594         jfloat value = POPF();
1595         jint index  = POPI();
1596         jfloatArray arr = (jfloatArray) POPA();
1597         NULLARRAYCHECK (arr);
1598         ARRAYBOUNDSCHECK (arr, index);
1599         elements(arr)[index] = value;
1600       }
1601       NEXT_INSN;
1602
1603     insn_dastore:
1604       {
1605         jdouble value = POPD();
1606         jint index  = POPI();
1607         jdoubleArray arr = (jdoubleArray) POPA();
1608         NULLARRAYCHECK (arr);
1609         ARRAYBOUNDSCHECK (arr, index);
1610         elements(arr)[index] = value;
1611       }
1612       NEXT_INSN;
1613
1614     insn_aastore:
1615       {
1616         jobject value = POPA();
1617         jint index  = POPI();
1618         jobjectArray arr = (jobjectArray) POPA();
1619         NULLARRAYCHECK (arr);
1620         ARRAYBOUNDSCHECK (arr, index);
1621         _Jv_CheckArrayStore (arr, value);
1622         elements(arr)[index] = value;
1623       }
1624       NEXT_INSN;
1625
1626     insn_bastore:
1627       {
1628         jbyte value = (jbyte) POPI();
1629         jint index  = POPI();
1630         jbyteArray arr = (jbyteArray) POPA();
1631         NULLARRAYCHECK (arr);
1632         ARRAYBOUNDSCHECK (arr, index);
1633         elements(arr)[index] = value;
1634       }
1635       NEXT_INSN;
1636
1637     insn_castore:
1638       {
1639         jchar value = (jchar) POPI();
1640         jint index  = POPI();
1641         jcharArray arr = (jcharArray) POPA();
1642         NULLARRAYCHECK (arr);
1643         ARRAYBOUNDSCHECK (arr, index);
1644         elements(arr)[index] = value;
1645       }
1646       NEXT_INSN;
1647
1648     insn_sastore:
1649       {
1650         jshort value = (jshort) POPI();
1651         jint index  = POPI();
1652         jshortArray arr = (jshortArray) POPA();
1653         NULLARRAYCHECK (arr);
1654         ARRAYBOUNDSCHECK (arr, index);
1655         elements(arr)[index] = value;
1656       }
1657       NEXT_INSN;
1658
1659     insn_pop:
1660       sp -= 1;
1661       NEXT_INSN;
1662
1663     insn_pop2:
1664       sp -= 2;
1665       NEXT_INSN;
1666
1667     insn_dup:
1668       sp[0] = sp[-1];
1669       sp += 1;
1670       NEXT_INSN;
1671
1672     insn_dup_x1:
1673       dupx (sp, 1, 1); sp+=1;
1674       NEXT_INSN;
1675
1676     insn_dup_x2:
1677       dupx (sp, 1, 2); sp+=1;
1678       NEXT_INSN;
1679
1680     insn_dup2:
1681       sp[0] = sp[-2];
1682       sp[1] = sp[-1];
1683       sp += 2;
1684       NEXT_INSN;
1685
1686     insn_dup2_x1:
1687       dupx (sp, 2, 1); sp+=2;
1688       NEXT_INSN;
1689
1690     insn_dup2_x2:
1691       dupx (sp, 2, 2); sp+=2;
1692       NEXT_INSN;
1693
1694     insn_swap:
1695       {
1696         jobject tmp1 = POPA();
1697         jobject tmp2 = POPA();
1698         PUSHA (tmp1);
1699         PUSHA (tmp2);
1700       }
1701       NEXT_INSN;
1702
1703     insn_iadd:
1704       BINOPI(+);
1705       NEXT_INSN;
1706
1707     insn_ladd:
1708       BINOPL(+);
1709       NEXT_INSN;
1710
1711     insn_fadd:
1712       BINOPF(+);
1713       NEXT_INSN;
1714
1715     insn_dadd:
1716       BINOPD(+);
1717       NEXT_INSN;
1718
1719     insn_isub:
1720       BINOPI(-);
1721       NEXT_INSN;
1722
1723     insn_lsub:
1724       BINOPL(-);
1725       NEXT_INSN;
1726
1727     insn_fsub:
1728       BINOPF(-);
1729       NEXT_INSN;
1730
1731     insn_dsub:
1732       BINOPD(-);
1733       NEXT_INSN;
1734
1735     insn_imul:
1736       BINOPI(*);
1737       NEXT_INSN;
1738
1739     insn_lmul:
1740       BINOPL(*);
1741       NEXT_INSN;
1742
1743     insn_fmul:
1744       BINOPF(*);
1745       NEXT_INSN;
1746
1747     insn_dmul:
1748       BINOPD(*);
1749       NEXT_INSN;
1750
1751     insn_idiv:
1752       {
1753         jint value2 = POPI();
1754         jint value1 = POPI();
1755         jint res = _Jv_divI (value1, value2);
1756         PUSHI (res);
1757       }
1758       NEXT_INSN;
1759
1760     insn_ldiv:
1761       {
1762         jlong value2 = POPL();
1763         jlong value1 = POPL();
1764         jlong res = _Jv_divJ (value1, value2);
1765         PUSHL (res);
1766       }
1767       NEXT_INSN;
1768
1769     insn_fdiv:
1770       {
1771         jfloat value2 = POPF();
1772         jfloat value1 = POPF();
1773         jfloat res = value1 / value2;
1774         PUSHF (res);
1775       }
1776       NEXT_INSN;
1777
1778     insn_ddiv:
1779       {
1780         jdouble value2 = POPD();
1781         jdouble value1 = POPD();
1782         jdouble res = value1 / value2;
1783         PUSHD (res);
1784       }
1785       NEXT_INSN;
1786
1787     insn_irem:
1788       {
1789         jint value2 = POPI();
1790         jint value1 =  POPI();
1791         jint res = _Jv_remI (value1, value2);
1792         PUSHI (res);
1793       }
1794       NEXT_INSN;
1795
1796     insn_lrem:
1797       {
1798         jlong value2 = POPL();
1799         jlong value1 = POPL();
1800         jlong res = _Jv_remJ (value1, value2);
1801         PUSHL (res);
1802       }
1803       NEXT_INSN;
1804
1805     insn_frem:
1806       {
1807         jfloat value2 = POPF();
1808         jfloat value1 = POPF();
1809         jfloat res    = __ieee754_fmod (value1, value2);
1810         PUSHF (res);
1811       }
1812       NEXT_INSN;
1813
1814     insn_drem:
1815       {
1816         jdouble value2 = POPD();
1817         jdouble value1 = POPD();
1818         jdouble res    = __ieee754_fmod (value1, value2);
1819         PUSHD (res);
1820       }
1821       NEXT_INSN;
1822
1823     insn_ineg:
1824       {
1825         jint value = POPI();
1826         PUSHI (value * -1);
1827       }
1828       NEXT_INSN;
1829
1830     insn_lneg:
1831       {
1832         jlong value = POPL();
1833         PUSHL (value * -1);
1834       }
1835       NEXT_INSN;
1836
1837     insn_fneg:
1838       {
1839         jfloat value = POPF();
1840         PUSHF (value * -1);
1841       }
1842       NEXT_INSN;
1843
1844     insn_dneg:
1845       {
1846         jdouble value = POPD();
1847         PUSHD (value * -1);
1848       }
1849       NEXT_INSN;
1850
1851     insn_ishl:
1852       {
1853         jint shift = (POPI() & 0x1f);
1854         jint value = POPI();
1855         PUSHI (value << shift);
1856       }
1857       NEXT_INSN;
1858
1859     insn_lshl:
1860       {
1861         jint shift = (POPI() & 0x3f);
1862         jlong value = POPL();
1863         PUSHL (value << shift);
1864       }
1865       NEXT_INSN;
1866
1867     insn_ishr:
1868       {
1869         jint shift = (POPI() & 0x1f);
1870         jint value = POPI();
1871         PUSHI (value >> shift);
1872       }
1873       NEXT_INSN;
1874
1875     insn_lshr:
1876       {
1877         jint shift = (POPI() & 0x3f);
1878         jlong value = POPL();
1879         PUSHL (value >> shift);
1880       }
1881       NEXT_INSN;
1882
1883     insn_iushr:
1884       {
1885         jint shift = (POPI() & 0x1f);
1886         unsigned long value = POPI();
1887         PUSHI ((jint) (value >> shift));
1888       }
1889       NEXT_INSN;
1890
1891     insn_lushr:
1892       {
1893         jint shift = (POPI() & 0x3f);
1894         UINT64 value = (UINT64) POPL();
1895         PUSHL ((value >> shift));
1896       }
1897       NEXT_INSN;
1898
1899     insn_iand:
1900       BINOPI (&);
1901       NEXT_INSN;
1902
1903     insn_land:
1904       BINOPL (&);
1905       NEXT_INSN;
1906
1907     insn_ior:
1908       BINOPI (|);
1909       NEXT_INSN;
1910
1911     insn_lor:
1912       BINOPL (|);
1913       NEXT_INSN;
1914
1915     insn_ixor:
1916       BINOPI (^);
1917       NEXT_INSN;
1918
1919     insn_lxor:
1920       BINOPL (^);
1921       NEXT_INSN;
1922
1923     insn_iinc:
1924       {
1925         jint index  = GET1U ();
1926         jint amount = GET1S ();
1927         locals[index].i += amount;
1928       }
1929       NEXT_INSN;
1930
1931     insn_i2l:
1932       {jlong value = POPI(); PUSHL (value);}
1933       NEXT_INSN;
1934
1935     insn_i2f:
1936       {jfloat value = POPI(); PUSHF (value);}
1937       NEXT_INSN;
1938
1939     insn_i2d:
1940       {jdouble value = POPI(); PUSHD (value);}
1941       NEXT_INSN;
1942
1943     insn_l2i:
1944       {jint value = POPL(); PUSHI (value);}
1945       NEXT_INSN;
1946
1947     insn_l2f:
1948       {jfloat value = POPL(); PUSHF (value);}
1949       NEXT_INSN;
1950
1951     insn_l2d:
1952       {jdouble value = POPL(); PUSHD (value);}
1953       NEXT_INSN;
1954
1955     insn_f2i:
1956       {
1957         using namespace java::lang;
1958         jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1959         PUSHI(value);
1960       }
1961       NEXT_INSN;
1962
1963     insn_f2l:
1964       {
1965         using namespace java::lang;
1966         jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1967         PUSHL(value);
1968       }
1969       NEXT_INSN;
1970
1971     insn_f2d:
1972       { jdouble value = POPF (); PUSHD(value); }
1973       NEXT_INSN;
1974
1975     insn_d2i:
1976       {
1977         using namespace java::lang;
1978         jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1979         PUSHI(value);
1980       }
1981       NEXT_INSN;
1982
1983     insn_d2l:
1984       {
1985         using namespace java::lang;
1986         jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1987         PUSHL(value);
1988       }
1989       NEXT_INSN;
1990
1991     insn_d2f:
1992       { jfloat value = POPD (); PUSHF(value); }
1993       NEXT_INSN;
1994
1995     insn_i2b:
1996       { jbyte value = POPI (); PUSHI(value); }
1997       NEXT_INSN;
1998
1999     insn_i2c:
2000       { jchar value = POPI (); PUSHI(value); }
2001       NEXT_INSN;
2002
2003     insn_i2s:
2004       { jshort value = POPI (); PUSHI(value); }
2005       NEXT_INSN;
2006
2007     insn_lcmp:
2008       {
2009         jlong value2 = POPL ();
2010         jlong value1 = POPL ();
2011         if (value1 > value2)
2012           { PUSHI (1); }
2013         else if (value1 == value2)
2014           { PUSHI (0); }
2015         else
2016           { PUSHI (-1); }
2017       }
2018       NEXT_INSN;
2019
2020     insn_fcmpl:
2021       tmpval = -1;
2022       goto fcmp;
2023
2024     insn_fcmpg:
2025       tmpval = 1;
2026
2027     fcmp:
2028       {
2029         jfloat value2 = POPF ();
2030         jfloat value1 = POPF ();
2031         if (value1 > value2)
2032           PUSHI (1);
2033         else if (value1 == value2)
2034           PUSHI (0);
2035         else if (value1 < value2)
2036           PUSHI (-1);
2037         else
2038           PUSHI (tmpval);
2039       }
2040       NEXT_INSN;
2041
2042     insn_dcmpl:
2043       tmpval = 1;
2044       goto dcmp;
2045
2046     insn_dcmpg:
2047       tmpval = -1;
2048
2049     dcmp:
2050       {
2051         jdouble value2 = POPD ();
2052         jdouble value1 = POPD ();
2053         if (value1 > value2)
2054           PUSHI (1);
2055         else if (value1 == value2)
2056           PUSHI (0);
2057         else if (value1 < value2)
2058           PUSHI (-1);
2059         else
2060           PUSHI (tmpval);
2061       }
2062       NEXT_INSN;
2063
2064     insn_ifeq:
2065       {
2066         if (POPI() == 0)
2067           TAKE_GOTO;
2068         else
2069           SKIP_GOTO;
2070       }
2071       NEXT_INSN;
2072
2073     insn_ifne:
2074       {
2075         if (POPI() != 0)
2076           TAKE_GOTO;
2077         else
2078           SKIP_GOTO;
2079       }
2080       NEXT_INSN;
2081
2082     insn_iflt:
2083       {
2084         if (POPI() < 0)
2085           TAKE_GOTO;
2086         else
2087           SKIP_GOTO;
2088       }
2089       NEXT_INSN;
2090
2091     insn_ifge:
2092       {
2093         if (POPI() >= 0)
2094           TAKE_GOTO;
2095         else
2096           SKIP_GOTO;
2097       }
2098       NEXT_INSN;
2099
2100     insn_ifgt:
2101       {
2102         if (POPI() > 0)
2103           TAKE_GOTO;
2104         else
2105           SKIP_GOTO;
2106       }
2107       NEXT_INSN;
2108
2109     insn_ifle:
2110       {
2111         if (POPI() <= 0)
2112           TAKE_GOTO;
2113         else
2114           SKIP_GOTO;
2115       }
2116       NEXT_INSN;
2117
2118     insn_if_icmpeq:
2119       {
2120         jint value2 = POPI();
2121         jint value1 = POPI();
2122         if (value1 == value2)
2123           TAKE_GOTO;
2124         else
2125           SKIP_GOTO;
2126       }
2127       NEXT_INSN;
2128
2129     insn_if_icmpne:
2130       {
2131         jint value2 = POPI();
2132         jint value1 = POPI();
2133         if (value1 != value2)
2134           TAKE_GOTO;
2135         else
2136           SKIP_GOTO;
2137       }
2138       NEXT_INSN;
2139
2140     insn_if_icmplt:
2141       {
2142         jint value2 = POPI();
2143         jint value1 = POPI();
2144         if (value1 < value2)
2145           TAKE_GOTO;
2146         else
2147           SKIP_GOTO;
2148       }
2149       NEXT_INSN;
2150
2151     insn_if_icmpge:
2152       {
2153         jint value2 = POPI();
2154         jint value1 = POPI();
2155         if (value1 >= value2)
2156           TAKE_GOTO;
2157         else
2158           SKIP_GOTO;
2159       }
2160       NEXT_INSN;
2161
2162     insn_if_icmpgt:
2163       {
2164         jint value2 = POPI();
2165         jint value1 = POPI();
2166         if (value1 > value2)
2167           TAKE_GOTO;
2168         else
2169           SKIP_GOTO;
2170       }
2171       NEXT_INSN;
2172
2173     insn_if_icmple:
2174       {
2175         jint value2 = POPI();
2176         jint value1 = POPI();
2177         if (value1 <= value2)
2178           TAKE_GOTO;
2179         else
2180           SKIP_GOTO;
2181       }
2182       NEXT_INSN;
2183
2184     insn_if_acmpeq:
2185       {
2186         jobject value2 = POPA();
2187         jobject value1 = POPA();
2188         if (value1 == value2)
2189           TAKE_GOTO;
2190         else
2191           SKIP_GOTO;
2192       }
2193       NEXT_INSN;
2194
2195     insn_if_acmpne:
2196       {
2197         jobject value2 = POPA();
2198         jobject value1 = POPA();
2199         if (value1 != value2)
2200           TAKE_GOTO;
2201         else
2202           SKIP_GOTO;
2203       }
2204       NEXT_INSN;
2205
2206     insn_goto_w:
2207 #ifndef DIRECT_THREADED
2208       // For direct threaded, goto and goto_w are the same.
2209       pc = pc - 1 + get4 (pc);
2210       NEXT_INSN;
2211 #endif /* DIRECT_THREADED */
2212     insn_goto:
2213       TAKE_GOTO;
2214       NEXT_INSN;
2215
2216     insn_jsr_w:
2217 #ifndef DIRECT_THREADED
2218       // For direct threaded, jsr and jsr_w are the same.
2219       {
2220         pc_t next = pc - 1 + get4 (pc);
2221         pc += 4;
2222         PUSHA ((jobject) pc);
2223         pc = next;
2224       }
2225       NEXT_INSN;
2226 #endif /* DIRECT_THREADED */
2227     insn_jsr:
2228       {
2229         pc_t next = GOTO_VAL();
2230         SKIP_GOTO;
2231         PUSHA ((jobject) pc);
2232         pc = next;
2233       }
2234       NEXT_INSN;
2235
2236     insn_ret:
2237       {
2238         jint index = GET1U ();
2239         pc = (pc_t) PEEKA (index);
2240       }
2241       NEXT_INSN;
2242
2243     insn_tableswitch:
2244       {
2245 #ifdef DIRECT_THREADED
2246         void *def = (pc++)->datum;
2247
2248         int index = POPI();
2249
2250         jint low = INTVAL ();
2251         jint high = INTVAL ();
2252
2253         if (index < low || index > high)
2254           pc = (insn_slot *) def;
2255         else
2256           pc = (insn_slot *) ((pc + index - low)->datum);
2257 #else
2258         pc_t base_pc = pc - 1;
2259         int index = POPI ();
2260
2261         pc_t base = (pc_t) bytecode ();
2262         while ((pc - base) % 4 != 0)
2263           ++pc;
2264
2265         jint def = get4 (pc);
2266         jint low = get4 (pc + 4);
2267         jint high = get4 (pc + 8);
2268         if (index < low || index > high)
2269           pc = base_pc + def;
2270         else
2271           pc = base_pc + get4 (pc + 4 * (index - low + 3));
2272 #endif /* DIRECT_THREADED */
2273       }
2274       NEXT_INSN;
2275
2276     insn_lookupswitch:
2277       {
2278 #ifdef DIRECT_THREADED
2279         void *def = (pc++)->insn;
2280
2281         int index = POPI();
2282
2283         jint npairs = INTVAL ();
2284
2285         int max = npairs - 1;
2286         int min = 0;
2287
2288         // Simple binary search...
2289         while (min < max)
2290           {
2291             int half = (min + max) / 2;
2292             int match = pc[2 * half].int_val;
2293
2294             if (index == match)
2295               {
2296                 // Found it.
2297                 pc = (insn_slot *) pc[2 * half + 1].datum;
2298                 NEXT_INSN;
2299               }
2300             else if (index < match)
2301               // We can use HALF - 1 here because we check again on
2302               // loop exit.
2303               max = half - 1;
2304             else
2305               // We can use HALF + 1 here because we check again on
2306               // loop exit.
2307               min = half + 1;
2308           }
2309         if (index == pc[2 * min].int_val)
2310           pc = (insn_slot *) pc[2 * min + 1].datum;
2311         else
2312           pc = (insn_slot *) def;
2313 #else
2314         unsigned char *base_pc = pc-1;
2315         int index = POPI();
2316
2317         unsigned char* base = bytecode ();
2318         while ((pc-base) % 4 != 0)
2319           ++pc;
2320
2321         jint def     = get4 (pc);
2322         jint npairs  = get4 (pc+4);
2323
2324         int max = npairs-1;
2325         int min = 0;
2326
2327         // Simple binary search...
2328         while (min < max)
2329           {
2330             int half = (min+max)/2;
2331             int match = get4 (pc+ 4*(2 + 2*half));
2332
2333             if (index == match)
2334               min = max = half;
2335             else if (index < match)
2336               // We can use HALF - 1 here because we check again on
2337               // loop exit.
2338               max = half - 1;
2339             else
2340               // We can use HALF + 1 here because we check again on
2341               // loop exit.
2342               min = half + 1;
2343           }
2344
2345         if (index == get4 (pc+ 4*(2 + 2*min)))
2346           pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2347         else
2348           pc = base_pc + def;    
2349 #endif /* DIRECT_THREADED */
2350       }
2351       NEXT_INSN;
2352
2353     insn_areturn:
2354       *(jobject *) retp = POPA ();
2355       return;
2356
2357     insn_lreturn:
2358       *(jlong *) retp = POPL ();
2359       return;
2360
2361     insn_freturn:
2362       *(jfloat *) retp = POPF ();
2363       return;
2364
2365     insn_dreturn:
2366       *(jdouble *) retp = POPD ();
2367       return;
2368
2369     insn_ireturn:
2370       *(jint *) retp = POPI ();
2371       return;
2372
2373     insn_return:
2374       return;
2375
2376     insn_getstatic:
2377       {
2378         jint fieldref_index = GET2U ();
2379         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2380         _Jv_Field *field = pool_data[fieldref_index].field;
2381
2382         if ((field->flags & Modifier::STATIC) == 0)
2383           throw_incompatible_class_change_error 
2384             (JvNewStringLatin1 ("field no longer static"));
2385
2386         jclass type = field->type;
2387
2388         // We rewrite the instruction once we discover what it refers
2389         // to.
2390         void *newinsn = NULL;
2391         if (type->isPrimitive ())
2392           {
2393             switch (type->size_in_bytes)
2394               {
2395               case 1:
2396                 PUSHI (*(jbyte*) (field->u.addr));
2397                 newinsn = AMPAMP (getstatic_resolved_1);
2398                 break;
2399
2400               case 2:
2401                 if (type == JvPrimClass (char))
2402                   {
2403                     PUSHI(*(jchar*) (field->u.addr));
2404                     newinsn = AMPAMP (getstatic_resolved_char);
2405                   }
2406                 else
2407                   {
2408                     PUSHI(*(jshort*) (field->u.addr));
2409                     newinsn = AMPAMP (getstatic_resolved_short);
2410                   }
2411                 break;
2412
2413               case 4:
2414                 PUSHI(*(jint*) (field->u.addr));
2415                 newinsn = AMPAMP (getstatic_resolved_4);
2416                 break;
2417
2418               case 8:
2419                 PUSHL(*(jlong*) (field->u.addr));
2420                 newinsn = AMPAMP (getstatic_resolved_8);
2421                 break;
2422               }
2423           }
2424         else
2425           {
2426             PUSHA(*(jobject*) (field->u.addr));
2427             newinsn = AMPAMP (getstatic_resolved_obj);
2428           }
2429
2430 #ifdef DIRECT_THREADED
2431         pc[-2].insn = newinsn;
2432         pc[-1].datum = field->u.addr;
2433 #endif /* DIRECT_THREADED */
2434       }
2435       NEXT_INSN;
2436
2437 #ifdef DIRECT_THREADED
2438     getstatic_resolved_1:
2439       PUSHI (*(jbyte *) AVAL ());
2440       NEXT_INSN;
2441
2442     getstatic_resolved_char:
2443       PUSHI (*(jchar *) AVAL ());
2444       NEXT_INSN;
2445
2446     getstatic_resolved_short:
2447       PUSHI (*(jshort *) AVAL ());
2448       NEXT_INSN;
2449
2450     getstatic_resolved_4:
2451       PUSHI (*(jint *) AVAL ());
2452       NEXT_INSN;
2453
2454     getstatic_resolved_8:
2455       PUSHL (*(jlong *) AVAL ());
2456       NEXT_INSN;
2457
2458     getstatic_resolved_obj:
2459       PUSHA (*(jobject *) AVAL ());
2460       NEXT_INSN;
2461 #endif /* DIRECT_THREADED */
2462
2463     insn_getfield:
2464       {
2465         jint fieldref_index = GET2U ();
2466         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2467         _Jv_Field *field = pool_data[fieldref_index].field;
2468
2469         if ((field->flags & Modifier::STATIC) != 0)
2470           throw_incompatible_class_change_error 
2471             (JvNewStringLatin1 ("field is static"));
2472
2473         jclass type = field->type;
2474         jint field_offset = field->u.boffset;
2475         if (field_offset > 0xffff)
2476           throw new java::lang::VirtualMachineError;
2477
2478         jobject obj   = POPA();
2479         NULLCHECK(obj);
2480
2481         void *newinsn = NULL;
2482         if (type->isPrimitive ())
2483           {
2484             switch (type->size_in_bytes)
2485               {
2486               case 1:
2487                 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2488                 newinsn = AMPAMP (getfield_resolved_1);
2489                 break;
2490
2491               case 2:
2492                 if (type == JvPrimClass (char))
2493                   {
2494                     PUSHI (*(jchar*) ((char*)obj + field_offset));
2495                     newinsn = AMPAMP (getfield_resolved_char);
2496                   }
2497                 else
2498                   {
2499                     PUSHI (*(jshort*) ((char*)obj + field_offset));
2500                     newinsn = AMPAMP (getfield_resolved_short);
2501                   }
2502                 break;
2503
2504               case 4:
2505                 PUSHI (*(jint*) ((char*)obj + field_offset));
2506                 newinsn = AMPAMP (getfield_resolved_4);
2507                 break;
2508
2509               case 8:
2510                 PUSHL(*(jlong*) ((char*)obj + field_offset));
2511                 newinsn = AMPAMP (getfield_resolved_8);
2512                 break;
2513               }
2514           }
2515         else
2516           {
2517             PUSHA(*(jobject*) ((char*)obj + field_offset));
2518             newinsn = AMPAMP (getfield_resolved_obj);
2519           }
2520
2521 #ifdef DIRECT_THREADED
2522         pc[-2].insn = newinsn;
2523         pc[-1].int_val = field_offset;
2524 #endif /* DIRECT_THREADED */
2525       }
2526       NEXT_INSN;
2527
2528 #ifdef DIRECT_THREADED
2529     getfield_resolved_1:
2530       {
2531         char *obj = (char *) POPA ();
2532         NULLCHECK (obj);
2533         PUSHI (*(jbyte *) (obj + INTVAL ()));
2534       }
2535       NEXT_INSN;
2536
2537     getfield_resolved_char:
2538       {
2539         char *obj = (char *) POPA ();
2540         NULLCHECK (obj);
2541         PUSHI (*(jchar *) (obj + INTVAL ()));
2542       }
2543       NEXT_INSN;
2544
2545     getfield_resolved_short:
2546       {
2547         char *obj = (char *) POPA ();
2548         NULLCHECK (obj);
2549         PUSHI (*(jshort *) (obj + INTVAL ()));
2550       }
2551       NEXT_INSN;
2552
2553     getfield_resolved_4:
2554       {
2555         char *obj = (char *) POPA ();
2556         NULLCHECK (obj);
2557         PUSHI (*(jint *) (obj + INTVAL ()));
2558       }
2559       NEXT_INSN;
2560
2561     getfield_resolved_8:
2562       {
2563         char *obj = (char *) POPA ();
2564         NULLCHECK (obj);
2565         PUSHL (*(jlong *) (obj + INTVAL ()));
2566       }
2567       NEXT_INSN;
2568
2569     getfield_resolved_obj:
2570       {
2571         char *obj = (char *) POPA ();
2572         NULLCHECK (obj);
2573         PUSHA (*(jobject *) (obj + INTVAL ()));
2574       }
2575       NEXT_INSN;
2576 #endif /* DIRECT_THREADED */
2577
2578     insn_putstatic:
2579       {
2580         jint fieldref_index = GET2U ();
2581         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2582         _Jv_Field *field = pool_data[fieldref_index].field;
2583
2584         jclass type = field->type;
2585
2586         // ResolvePoolEntry cannot check this
2587         if ((field->flags & Modifier::STATIC) == 0)
2588           throw_incompatible_class_change_error 
2589             (JvNewStringLatin1 ("field no longer static"));
2590
2591         void *newinsn = NULL;
2592         if (type->isPrimitive ())
2593           {
2594             switch (type->size_in_bytes) 
2595               {
2596               case 1:
2597                 {
2598                   jint value = POPI();
2599                   *(jbyte*) (field->u.addr) = value;
2600                   newinsn = AMPAMP (putstatic_resolved_1);
2601                   break;
2602                 }
2603
2604               case 2:
2605                 {
2606                   jint value = POPI();
2607                   *(jchar*) (field->u.addr) = value;
2608                   newinsn = AMPAMP (putstatic_resolved_2);
2609                   break;
2610                 }
2611
2612               case 4:
2613                 {
2614                   jint value = POPI();
2615                   *(jint*) (field->u.addr) = value;
2616                   newinsn = AMPAMP (putstatic_resolved_4);
2617                   break;
2618                 }
2619
2620               case 8:
2621                 {
2622                   jlong value = POPL();
2623                   *(jlong*) (field->u.addr) = value;
2624                   newinsn = AMPAMP (putstatic_resolved_8);
2625                   break;
2626                 }
2627               }
2628           }
2629         else
2630           {
2631             jobject value = POPA();
2632             *(jobject*) (field->u.addr) = value;
2633             newinsn = AMPAMP (putstatic_resolved_obj);
2634           }
2635
2636 #ifdef DIRECT_THREADED
2637         pc[-2].insn = newinsn;
2638         pc[-1].datum = field->u.addr;
2639 #endif /* DIRECT_THREADED */
2640       }
2641       NEXT_INSN;
2642
2643 #ifdef DIRECT_THREADED
2644     putstatic_resolved_1:
2645       *(jbyte *) AVAL () = POPI ();
2646       NEXT_INSN;
2647
2648     putstatic_resolved_2:
2649       *(jchar *) AVAL () = POPI ();
2650       NEXT_INSN;
2651
2652     putstatic_resolved_4:
2653       *(jint *) AVAL () = POPI ();
2654       NEXT_INSN;
2655
2656     putstatic_resolved_8:
2657       *(jlong *) AVAL () = POPL ();
2658       NEXT_INSN;
2659
2660     putstatic_resolved_obj:
2661       *(jobject *) AVAL () = POPA ();
2662       NEXT_INSN;
2663 #endif /* DIRECT_THREADED */
2664
2665     insn_putfield:
2666       {
2667         jint fieldref_index = GET2U ();
2668         _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2669         _Jv_Field *field = pool_data[fieldref_index].field;
2670
2671         jclass type = field->type;
2672
2673         if ((field->flags & Modifier::STATIC) != 0)
2674           throw_incompatible_class_change_error 
2675             (JvNewStringLatin1 ("field is static"));
2676
2677         jint field_offset = field->u.boffset;
2678         if (field_offset > 0xffff)
2679           throw new java::lang::VirtualMachineError;
2680
2681         void *newinsn = NULL;
2682         if (type->isPrimitive ())
2683           {
2684             switch (type->size_in_bytes) 
2685               {
2686               case 1:
2687                 {
2688                   jint    value = POPI();
2689                   jobject obj   = POPA();
2690                   NULLCHECK(obj);
2691                   *(jbyte*) ((char*)obj + field_offset) = value;
2692                   newinsn = AMPAMP (putfield_resolved_1);
2693                   break;
2694                 }
2695
2696               case 2:
2697                 {
2698                   jint    value = POPI();
2699                   jobject obj   = POPA();
2700                   NULLCHECK(obj);
2701                   *(jchar*) ((char*)obj + field_offset) = value;
2702                   newinsn = AMPAMP (putfield_resolved_2);
2703                   break;
2704                 }
2705
2706               case 4:
2707                 {
2708                   jint    value = POPI();
2709                   jobject obj   = POPA();
2710                   NULLCHECK(obj);
2711                   *(jint*) ((char*)obj + field_offset) = value;
2712                   newinsn = AMPAMP (putfield_resolved_4);
2713                   break;
2714                 }
2715
2716               case 8:
2717                 {
2718                   jlong   value = POPL();
2719                   jobject obj   = POPA();
2720                   NULLCHECK(obj);
2721                   *(jlong*) ((char*)obj + field_offset) = value;
2722                   newinsn = AMPAMP (putfield_resolved_8);
2723                   break;
2724                 }
2725               }
2726           }
2727         else
2728           {
2729             jobject value = POPA();
2730             jobject obj   = POPA();
2731             NULLCHECK(obj);
2732             *(jobject*) ((char*)obj + field_offset) = value;
2733             newinsn = AMPAMP (putfield_resolved_obj);
2734           }
2735
2736 #ifdef DIRECT_THREADED
2737         pc[-2].insn = newinsn;
2738         pc[-1].int_val = field_offset;
2739 #endif /* DIRECT_THREADED */
2740       }
2741       NEXT_INSN;
2742
2743 #ifdef DIRECT_THREADED
2744     putfield_resolved_1:
2745       {
2746         jint val = POPI ();
2747         char *obj = (char *) POPA ();
2748         NULLCHECK (obj);
2749         *(jbyte *) (obj + INTVAL ()) = val;
2750       }
2751       NEXT_INSN;
2752
2753     putfield_resolved_2:
2754       {
2755         jint val = POPI ();
2756         char *obj = (char *) POPA ();
2757         NULLCHECK (obj);
2758         *(jchar *) (obj + INTVAL ()) = val;
2759       }
2760       NEXT_INSN;
2761
2762     putfield_resolved_4:
2763       {
2764         jint val = POPI ();
2765         char *obj = (char *) POPA ();
2766         NULLCHECK (obj);
2767         *(jint *) (obj + INTVAL ()) = val;
2768       }
2769       NEXT_INSN;
2770
2771     putfield_resolved_8:
2772       {
2773         jlong val = POPL ();
2774         char *obj = (char *) POPA ();
2775         NULLCHECK (obj);
2776         *(jlong *) (obj + INTVAL ()) = val;
2777       }
2778       NEXT_INSN;
2779
2780     putfield_resolved_obj:
2781       {
2782         jobject val = POPA ();
2783         char *obj = (char *) POPA ();
2784         NULLCHECK (obj);
2785         *(jobject *) (obj + INTVAL ()) = val;
2786       }
2787       NEXT_INSN;
2788 #endif /* DIRECT_THREADED */
2789
2790     insn_invokespecial:
2791       {
2792         int index = GET2U ();
2793
2794         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2795
2796         sp -= rmeth->stack_item_count;
2797
2798         NULLCHECK (sp[0].o);
2799
2800         fun = (void (*)()) rmeth->method->ncode;
2801
2802 #ifdef DIRECT_THREADED
2803         // Rewrite instruction so that we use a faster pre-resolved
2804         // method.
2805         pc[-2].insn = &&invokespecial_resolved;
2806         pc[-1].datum = rmeth;
2807 #endif /* DIRECT_THREADED */
2808       }
2809       goto perform_invoke;
2810
2811 #ifdef DIRECT_THREADED
2812     invokespecial_resolved:
2813       {
2814         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2815         sp -= rmeth->stack_item_count;
2816         NULLCHECK (sp[0].o);
2817         fun = (void (*)()) rmeth->method->ncode;
2818       }
2819       goto perform_invoke;
2820 #endif /* DIRECT_THREADED */
2821
2822     insn_invokestatic:
2823       {
2824         int index = GET2U ();
2825
2826         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2827
2828         sp -= rmeth->stack_item_count;
2829
2830         _Jv_InitClass (rmeth->klass);
2831         fun = (void (*)()) rmeth->method->ncode;
2832
2833 #ifdef DIRECT_THREADED
2834         // Rewrite instruction so that we use a faster pre-resolved
2835         // method.
2836         pc[-2].insn = &&invokestatic_resolved;
2837         pc[-1].datum = rmeth;
2838 #endif /* DIRECT_THREADED */
2839       }
2840       goto perform_invoke;
2841
2842 #ifdef DIRECT_THREADED
2843     invokestatic_resolved:
2844       {
2845         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2846         sp -= rmeth->stack_item_count;
2847         fun = (void (*)()) rmeth->method->ncode;
2848       }
2849       goto perform_invoke;
2850 #endif /* DIRECT_THREADED */
2851
2852     insn_invokeinterface:
2853       {
2854         int index = GET2U ();
2855
2856         rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2857
2858         sp -= rmeth->stack_item_count;
2859
2860         jobject rcv = sp[0].o;
2861
2862         NULLCHECK (rcv);
2863
2864         fun = (void (*)())
2865           _Jv_LookupInterfaceMethod (rcv->getClass (),
2866                                      rmeth->method->name,
2867                                      rmeth->method->signature);
2868
2869 #ifdef DIRECT_THREADED
2870         // Rewrite instruction so that we use a faster pre-resolved
2871         // method.
2872         pc[-2].insn = &&invokeinterface_resolved;
2873         pc[-1].datum = rmeth;
2874 #else
2875         // Skip dummy bytes.
2876         pc += 2;
2877 #endif /* DIRECT_THREADED */
2878       }
2879       goto perform_invoke;
2880
2881 #ifdef DIRECT_THREADED
2882     invokeinterface_resolved:
2883       {
2884         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2885         sp -= rmeth->stack_item_count;
2886         jobject rcv = sp[0].o;
2887         NULLCHECK (rcv);
2888         fun = (void (*)())
2889           _Jv_LookupInterfaceMethod (rcv->getClass (),
2890                                      rmeth->method->name,
2891                                      rmeth->method->signature);
2892       }
2893       goto perform_invoke;
2894 #endif /* DIRECT_THREADED */
2895
2896     insn_new:
2897       {
2898         int index = GET2U ();
2899         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2900         _Jv_InitClass (klass);
2901         jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2902         PUSHA (res);
2903
2904 #ifdef DIRECT_THREADED
2905         pc[-2].insn = &&new_resolved;
2906         pc[-1].datum = klass;
2907 #endif /* DIRECT_THREADED */
2908       }
2909       NEXT_INSN;
2910
2911 #ifdef DIRECT_THREADED
2912     new_resolved:
2913       {
2914         jclass klass = (jclass) AVAL ();
2915         jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2916         PUSHA (res);
2917       }
2918       NEXT_INSN;
2919 #endif /* DIRECT_THREADED */
2920
2921     insn_newarray:
2922       {
2923         int atype = GET1U ();
2924         int size  = POPI();
2925         jobject result = _Jv_NewArray (atype, size);
2926         PUSHA (result);
2927       }
2928       NEXT_INSN;
2929
2930     insn_anewarray:
2931       {
2932         int index = GET2U ();
2933         jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2934         int size  = POPI();
2935         _Jv_InitClass (klass);
2936         jobject result = _Jv_NewObjectArray (size, klass, 0);
2937         PUSHA (result);
2938
2939 #ifdef DIRECT_THREADED
2940         pc[-2].insn = &&anewarray_resolved;
2941         pc[-1].datum = klass;
2942 #endif /* DIRECT_THREADED */
2943       }
2944       NEXT_INSN;
2945
2946 #ifdef DIRECT_THREADED
2947     anewarray_resolved:
2948       {
2949         jclass klass = (jclass) AVAL ();
2950         int size = POPI ();
2951         jobject result = _Jv_NewObjectArray (size, klass, 0);
2952         PUSHA (result);
2953       }
2954       NEXT_INSN;
2955 #endif /* DIRECT_THREADED */
2956
2957     insn_arraylength:
2958       {
2959         __JArray *arr = (__JArray*)POPA();
2960         NULLARRAYCHECK (arr);
2961         PUSHI (arr->length);
2962       }
2963       NEXT_INSN;
2964
2965     insn_athrow:
2966       {
2967         jobject value = POPA();
2968         throw static_cast<jthrowable>(value);
2969       }
2970       NEXT_INSN;
2971
2972     insn_checkcast:
2973       {
2974         jobject value = POPA();
2975         jint index = GET2U ();
2976         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2977
2978         if (value != NULL && ! to->isInstance (value))
2979           throw new java::lang::ClassCastException (to->getName());
2980
2981         PUSHA (value);
2982
2983 #ifdef DIRECT_THREADED
2984         pc[-2].insn = &&checkcast_resolved;
2985         pc[-1].datum = to;
2986 #endif /* DIRECT_THREADED */
2987       }
2988       NEXT_INSN;
2989
2990 #ifdef DIRECT_THREADED
2991     checkcast_resolved:
2992       {
2993         jobject value = POPA ();
2994         jclass to = (jclass) AVAL ();
2995         if (value != NULL && ! to->isInstance (value))
2996           throw new java::lang::ClassCastException (to->getName());
2997         PUSHA (value);
2998       }
2999       NEXT_INSN;
3000 #endif /* DIRECT_THREADED */
3001
3002     insn_instanceof:
3003       {
3004         jobject value = POPA();
3005         jint index = GET2U ();
3006         jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3007         PUSHI (to->isInstance (value));
3008
3009 #ifdef DIRECT_THREADED
3010         pc[-2].insn = &&instanceof_resolved;
3011         pc[-1].datum = to;
3012 #endif /* DIRECT_THREADED */
3013       }
3014       NEXT_INSN;
3015
3016 #ifdef DIRECT_THREADED
3017     instanceof_resolved:
3018       {
3019         jobject value = POPA ();
3020         jclass to = (jclass) AVAL ();
3021         PUSHI (to->isInstance (value));
3022       }
3023       NEXT_INSN;
3024 #endif /* DIRECT_THREADED */
3025
3026     insn_monitorenter:
3027       {
3028         jobject value = POPA();
3029         NULLCHECK(value);
3030         _Jv_MonitorEnter (value);
3031       }
3032       NEXT_INSN;
3033
3034     insn_monitorexit:
3035       {
3036         jobject value = POPA();
3037         NULLCHECK(value);
3038         _Jv_MonitorExit (value);
3039       }
3040       NEXT_INSN;
3041
3042     insn_ifnull:
3043       {
3044         jobject val = POPA();
3045         if (val == NULL)
3046           TAKE_GOTO;
3047         else
3048           SKIP_GOTO;
3049       }
3050       NEXT_INSN;
3051
3052     insn_ifnonnull:
3053       {
3054         jobject val = POPA();
3055         if (val != NULL)
3056           TAKE_GOTO;
3057         else
3058           SKIP_GOTO;
3059       }
3060       NEXT_INSN;
3061
3062     insn_multianewarray:
3063       {
3064         int kind_index = GET2U ();
3065         int dim        = GET1U ();
3066
3067         jclass type    
3068           = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
3069         _Jv_InitClass (type);
3070         jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
3071
3072         for (int i = dim - 1; i >= 0; i--)
3073           {
3074             sizes[i] = POPI ();
3075           }
3076
3077         jobject res    = _Jv_NewMultiArray (type,dim, sizes);
3078
3079         PUSHA (res);
3080       }
3081       NEXT_INSN;
3082
3083 #ifndef DIRECT_THREADED
3084     insn_wide:
3085       {
3086         jint the_mod_op = get1u (pc++);
3087         jint wide       = get2u (pc); pc += 2;
3088
3089         switch (the_mod_op)
3090           {
3091           case op_istore:
3092             STOREI (wide);
3093             NEXT_INSN;
3094
3095           case op_fstore:
3096             STOREF (wide);
3097             NEXT_INSN;
3098
3099           case op_astore:
3100             STOREA (wide);
3101             NEXT_INSN;
3102
3103           case op_lload:
3104             LOADL (wide);
3105             NEXT_INSN;
3106
3107           case op_dload:
3108             LOADD (wide);
3109             NEXT_INSN;
3110
3111           case op_iload:
3112             LOADI (wide);
3113             NEXT_INSN;
3114
3115           case op_aload:
3116             LOADA (wide);
3117             NEXT_INSN;
3118
3119           case op_lstore:
3120             STOREL (wide);
3121             NEXT_INSN;
3122
3123           case op_dstore:
3124             STORED (wide);
3125             NEXT_INSN;
3126
3127           case op_ret:
3128             pc = (unsigned char*) PEEKA (wide);
3129             NEXT_INSN;
3130
3131           case op_iinc:
3132             {
3133               jint amount = get2s (pc); pc += 2;
3134               jint value = PEEKI (wide);
3135               POKEI (wide, value+amount);
3136             }
3137             NEXT_INSN;
3138
3139           default:
3140             throw_internal_error ("illegal bytecode modified by wide");
3141           }
3142
3143       }
3144 #endif /* DIRECT_THREADED */
3145     }
3146   catch (java::lang::Throwable *ex)
3147     {
3148 #ifdef DIRECT_THREADED
3149       void *logical_pc = (void *) ((insn_slot *) pc - 1);
3150 #else
3151       int logical_pc = pc - 1 - bytecode ();
3152 #endif
3153       _Jv_InterpException *exc = exceptions ();
3154       jclass exc_class = ex->getClass ();
3155
3156       for (int i = 0; i < exc_count; i++)
3157         {
3158           if (PCVAL (exc[i].start_pc) <= logical_pc
3159               && logical_pc < PCVAL (exc[i].end_pc))
3160             {
3161 #ifdef DIRECT_THREADED
3162               jclass handler = (jclass) exc[i].handler_type.p;
3163 #else
3164               jclass handler = NULL;
3165               if (exc[i].handler_type.i != 0)
3166                 handler = (_Jv_ResolvePoolEntry (defining_class,
3167                                                  exc[i].handler_type.i)).clazz;
3168 #endif /* DIRECT_THREADED */
3169
3170               if (handler == NULL || handler->isAssignableFrom (exc_class))
3171                 {
3172 #ifdef DIRECT_THREADED
3173                   pc = (insn_slot *) exc[i].handler_pc.p;
3174 #else
3175                   pc = bytecode () + exc[i].handler_pc.i;
3176 #endif /* DIRECT_THREADED */
3177                   sp = stack;
3178                   sp++->o = ex; // Push exception.
3179                   NEXT_INSN;
3180                 }
3181             }
3182         }
3183
3184       // No handler, so re-throw.
3185       throw ex;
3186     }
3187 }
3188
3189 // This function exists so that the stack-tracing code can find the
3190 // boundaries of the interpreter.
3191 void
3192 _Jv_EndOfInterpreter (void)
3193 {
3194 }
3195
3196 static void
3197 throw_internal_error (char *msg)
3198 {
3199   throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3200 }
3201
3202 static void 
3203 throw_incompatible_class_change_error (jstring msg)
3204 {
3205   throw new java::lang::IncompatibleClassChangeError (msg);
3206 }
3207
3208 #ifndef HANDLE_SEGV
3209 static java::lang::NullPointerException *null_pointer_exc;
3210 static void 
3211 throw_null_pointer_exception ()
3212 {
3213   if (null_pointer_exc == NULL)
3214     null_pointer_exc = new java::lang::NullPointerException;
3215
3216   throw null_pointer_exc;
3217 }
3218 #endif
3219
3220 #endif // INTERPRETER