2001-08-22 Alexandre Petit-Bianco <apbianco@redhat.com>
[official-gcc.git] / libjava / interpret.cc
blobb121a1b7ebb2c2e6acf62178b8fc37a51b21fc27
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
13 #include <config.h>
15 #pragma implementation "java-interp.h"
17 #include <jvm.h>
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 // #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/StringBuffer.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/reflect/Modifier.h>
27 #include <java/lang/ClassCastException.h>
28 #include <java/lang/VirtualMachineError.h>
29 #include <java/lang/InternalError.h>
30 #include <java/lang/NullPointerException.h>
31 #include <java/lang/ArithmeticException.h>
32 #include <java/lang/IncompatibleClassChangeError.h>
33 #include <java-insns.h>
34 #include <java-signal.h>
36 #ifdef INTERPRETER
38 #include <stdlib.h>
40 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
42 static void throw_internal_error (char *msg)
43 __attribute__ ((__noreturn__));
44 static void throw_incompatible_class_change_error (jstring msg)
45 __attribute__ ((__noreturn__));
46 #ifndef HANDLE_SEGV
47 static void throw_null_pointer_exception ()
48 __attribute__ ((__noreturn__));
49 #endif
51 extern "C" double __ieee754_fmod (double,double);
53 static inline void dupx (_Jv_word *sp, int n, int x)
55 // first "slide" n+x elements n to the right
56 int top = n-1;
57 for (int i = 0; i < n+x; i++)
59 sp[(top-i)] = sp[(top-i)-n];
62 // next, copy the n top elements, n+x down
63 for (int i = 0; i < n; i++)
65 sp[top-(n+x)-i] = sp[top-i];
71 #define PUSHA(V) (sp++)->o = (V)
72 #define PUSHI(V) (sp++)->i = (V)
73 #define PUSHF(V) (sp++)->f = (V)
74 #if SIZEOF_VOID_P == 8
75 # define PUSHL(V) (sp->l = (V), sp += 2)
76 # define PUSHD(V) (sp->d = (V), sp += 2)
77 #else
78 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
79 (sp++)->ia[0] = w2.ia[0]; \
80 (sp++)->ia[0] = w2.ia[1]; } while (0)
81 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
82 (sp++)->ia[0] = w2.ia[0]; \
83 (sp++)->ia[0] = w2.ia[1]; } while (0)
84 #endif
86 #define POPA() ((--sp)->o)
87 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
88 #define POPF() ((jfloat) (--sp)->f)
89 #if SIZEOF_VOID_P == 8
90 # define POPL() (sp -= 2, (jlong) sp->l)
91 # define POPD() (sp -= 2, (jdouble) sp->d)
92 #else
93 # define POPL() ({ _Jv_word2 w2; \
94 w2.ia[1] = (--sp)->ia[0]; \
95 w2.ia[0] = (--sp)->ia[0]; w2.l; })
96 # define POPD() ({ _Jv_word2 w2; \
97 w2.ia[1] = (--sp)->ia[0]; \
98 w2.ia[0] = (--sp)->ia[0]; w2.d; })
99 #endif
101 #define LOADA(I) (sp++)->o = locals[I].o
102 #define LOADI(I) (sp++)->i = locals[I].i
103 #define LOADF(I) (sp++)->f = locals[I].f
104 #if SIZEOF_VOID_P == 8
105 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
106 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
107 #else
108 # define LOADL(I) do { jint __idx = (I); \
109 (sp++)->ia[0] = locals[__idx].ia[0]; \
110 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
111 } while (0)
112 # define LOADD(I) LOADL(I)
113 #endif
115 #define STOREA(I) locals[I].o = (--sp)->o
116 #define STOREI(I) locals[I].i = (--sp)->i
117 #define STOREF(I) locals[I].f = (--sp)->f
118 #if SIZEOF_VOID_P == 8
119 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
120 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
121 #else
122 # define STOREL(I) do { jint __idx = (I); \
123 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
124 locals[__idx].ia[0] = (--sp)->ia[0]; \
125 } while (0)
126 # define STORED(I) STOREL(I)
127 #endif
129 #define PEEKI(I) (locals+(I))->i
130 #define PEEKA(I) (locals+(I))->o
132 #define POKEI(I,V) ((locals+(I))->i = (V))
135 #define BINOPI(OP) { \
136 jint value2 = POPI(); \
137 jint value1 = POPI(); \
138 PUSHI(value1 OP value2); \
141 #define BINOPF(OP) { \
142 jfloat value2 = POPF(); \
143 jfloat value1 = POPF(); \
144 PUSHF(value1 OP value2); \
147 #define BINOPL(OP) { \
148 jlong value2 = POPL(); \
149 jlong value1 = POPL(); \
150 PUSHL(value1 OP value2); \
153 #define BINOPD(OP) { \
154 jdouble value2 = POPD(); \
155 jdouble value1 = POPD(); \
156 PUSHD(value1 OP value2); \
159 static inline jint get1s(unsigned char* loc) {
160 return *(signed char*)loc;
163 static inline jint get1u(unsigned char* loc) {
164 return *loc;
167 static inline jint get2s(unsigned char* loc) {
168 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
171 static inline jint get2u(unsigned char* loc) {
172 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
175 static jint get4(unsigned char* loc) {
176 return (((jint)(loc[0])) << 24)
177 | (((jint)(loc[1])) << 16)
178 | (((jint)(loc[2])) << 8)
179 | (((jint)(loc[3])) << 0);
183 #ifdef HANDLE_SEGV
184 #define NULLCHECK(X)
185 #else
186 #define NULLCHECK(X) \
187 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
188 #endif
191 // this method starts the actual running of the method. It is inlined
192 // in three different variants in the static methods run_normal,
193 // run_sync_object and run_sync_class (see below). Those static methods
194 // are installed directly in the stub for this method (by
195 // _Jv_InterpMethod::ncode, in resolve.cc).
197 inline jobject
198 _Jv_InterpMethod::run (ffi_cif* cif,
199 void *retp,
200 ffi_raw *args,
201 _Jv_InterpMethodInvocation *inv)
203 inv->running = this;
204 inv->pc = bytecode ();
205 inv->sp = inv->stack_base ();
206 _Jv_word *locals = inv->local_base ();
208 /* Go straight at it! the ffi raw format matches the internal
209 stack representation exactly. At least, that's the idea.
211 memcpy ((void*) locals, (void*) args, args_raw_size);
213 next_segment:
215 jobject ex = NULL;
219 continue1 (inv);
221 catch (java::lang::Throwable *ex2)
223 ex = ex2;
226 if (ex == 0) // no exception...
228 /* define sp locally, so the POP? macros will pick it up */
229 _Jv_word *sp = inv->sp;
230 int rtype = cif->rtype->type;
232 if (rtype == FFI_TYPE_POINTER)
234 jobject r = POPA();
235 *(jobject*) retp = r;
236 return 0;
238 else if (rtype == FFI_TYPE_SINT32)
240 jint r = POPI();
241 *(jint*)retp = r;
242 return 0;
244 else if (rtype == FFI_TYPE_VOID)
246 return 0;
248 else switch (rtype)
250 case FFI_TYPE_FLOAT:
252 jfloat r = POPF();
253 *(jfloat*)retp = r;
254 return 0;
257 case FFI_TYPE_DOUBLE:
259 jdouble r = POPD();
260 *(jdouble*)retp = r;
261 return 0;
264 case FFI_TYPE_UINT8:
265 case FFI_TYPE_UINT16:
266 case FFI_TYPE_UINT32:
267 case FFI_TYPE_SINT8:
268 case FFI_TYPE_SINT16:
270 jint r = POPI();
271 *(jint*)retp = r;
272 return 0;
275 case FFI_TYPE_SINT64:
277 jlong r = POPL();
278 *(jlong*)retp = r;
279 return 0;
282 default:
283 throw_internal_error ("unknown return type");
287 /** handle an exception */
288 if ( find_exception (ex, inv) )
289 goto next_segment;
291 return ex;
294 bool _Jv_InterpMethod::find_exception (jobject ex,
295 _Jv_InterpMethodInvocation *inv)
297 int logical_pc = inv->pc - bytecode ();
298 _Jv_InterpException *exc = exceptions ();
299 jclass exc_class = ex->getClass ();
301 for (int i = 0; i < exc_count; i++)
303 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
305 jclass handler;
307 if (exc[i].handler_type != 0)
308 handler = (_Jv_ResolvePoolEntry (defining_class,
309 exc[i].handler_type)).clazz;
310 else
311 handler = NULL;
313 if (handler==NULL || handler->isAssignableFrom (exc_class))
315 inv->pc = bytecode () + exc[i].handler_pc;
316 inv->sp = inv->stack_base (); // reset stack
317 (inv->sp++)->o = ex; // push exception
318 return true;
322 return false;
325 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
326 void* ret,
327 ffi_raw * args,
328 void* __this)
330 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
332 // we do the alloca of the method invocation here, to allow the method
333 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
334 int storage_size = _this->max_stack+_this->max_locals;
335 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
336 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
337 + storage_size * sizeof (_Jv_word));
339 jobject ex = _this->run (cif, ret, args, inv);
340 if (ex != 0) throw static_cast<jthrowable>(ex);
343 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
344 void* ret,
345 ffi_raw * args,
346 void* __this)
348 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
349 jobject rcv = (jobject)args[0].ptr;
351 int storage_size = _this->max_stack+_this->max_locals;
352 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
353 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
354 + storage_size * sizeof (_Jv_word));
356 _Jv_MonitorEnter (rcv);
357 jobject ex = _this->run (cif, ret, args, inv);
358 _Jv_MonitorExit (rcv);
360 if (ex != 0) throw static_cast<jthrowable>(ex);
363 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
364 void* ret,
365 ffi_raw * args,
366 void* __this)
368 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
369 jclass sync = _this->defining_class;
371 int storage_size = _this->max_stack+_this->max_locals;
372 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
373 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
374 + storage_size * sizeof (_Jv_word));
376 _Jv_MonitorEnter (sync);
377 jobject ex = _this->run (cif, ret, args, inv);
378 _Jv_MonitorExit (sync);
380 if (ex != 0) throw static_cast<jthrowable>(ex);
384 This proceeds execution, as designated in "inv". If an exception
385 happens, then it is simply thrown, and handled in Java. Thus, the pc
386 needs to be stored in the inv->pc at all times, so we can figure
387 out which handler (if any) to invoke.
389 One design issue, which I have not completely considered, is if it
390 should be possible to have interpreted classes linked in! Seldom used
391 (or non-critical) classes could reasonably be interpreted.
395 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
397 using namespace java::lang::reflect;
399 _Jv_word *sp = inv->sp;
400 unsigned char *pc = inv->pc;
401 _Jv_word *locals = inv->local_base ();
403 _Jv_word *pool_data = defining_class->constants.data;
405 /* these two are used in the invokeXXX instructions */
406 void (*fun)();
407 _Jv_ResolvedMethod* rmeth;
409 #define INSN_LABEL(op) &&insn_##op
410 #define GOTO_INSN(op) goto *(insn_target[op])
412 static const void *const insn_target[] =
414 INSN_LABEL(nop),
415 INSN_LABEL(aconst_null),
416 INSN_LABEL(iconst_m1),
417 INSN_LABEL(iconst_0),
418 INSN_LABEL(iconst_1),
419 INSN_LABEL(iconst_2),
420 INSN_LABEL(iconst_3),
421 INSN_LABEL(iconst_4),
422 INSN_LABEL(iconst_5),
423 INSN_LABEL(lconst_0),
424 INSN_LABEL(lconst_1),
425 INSN_LABEL(fconst_0),
426 INSN_LABEL(fconst_1),
427 INSN_LABEL(fconst_2),
428 INSN_LABEL(dconst_0),
429 INSN_LABEL(dconst_1),
430 INSN_LABEL(bipush),
431 INSN_LABEL(sipush),
432 INSN_LABEL(ldc),
433 INSN_LABEL(ldc_w),
434 INSN_LABEL(ldc2_w),
435 INSN_LABEL(iload),
436 INSN_LABEL(lload),
437 INSN_LABEL(fload),
438 INSN_LABEL(dload),
439 INSN_LABEL(aload),
440 INSN_LABEL(iload_0),
441 INSN_LABEL(iload_1),
442 INSN_LABEL(iload_2),
443 INSN_LABEL(iload_3),
444 INSN_LABEL(lload_0),
445 INSN_LABEL(lload_1),
446 INSN_LABEL(lload_2),
447 INSN_LABEL(lload_3),
448 INSN_LABEL(fload_0),
449 INSN_LABEL(fload_1),
450 INSN_LABEL(fload_2),
451 INSN_LABEL(fload_3),
452 INSN_LABEL(dload_0),
453 INSN_LABEL(dload_1),
454 INSN_LABEL(dload_2),
455 INSN_LABEL(dload_3),
456 INSN_LABEL(aload_0),
457 INSN_LABEL(aload_1),
458 INSN_LABEL(aload_2),
459 INSN_LABEL(aload_3),
460 INSN_LABEL(iaload),
461 INSN_LABEL(laload),
462 INSN_LABEL(faload),
463 INSN_LABEL(daload),
464 INSN_LABEL(aaload),
465 INSN_LABEL(baload),
466 INSN_LABEL(caload),
467 INSN_LABEL(saload),
468 INSN_LABEL(istore),
469 INSN_LABEL(lstore),
470 INSN_LABEL(fstore),
471 INSN_LABEL(dstore),
472 INSN_LABEL(astore),
473 INSN_LABEL(istore_0),
474 INSN_LABEL(istore_1),
475 INSN_LABEL(istore_2),
476 INSN_LABEL(istore_3),
477 INSN_LABEL(lstore_0),
478 INSN_LABEL(lstore_1),
479 INSN_LABEL(lstore_2),
480 INSN_LABEL(lstore_3),
481 INSN_LABEL(fstore_0),
482 INSN_LABEL(fstore_1),
483 INSN_LABEL(fstore_2),
484 INSN_LABEL(fstore_3),
485 INSN_LABEL(dstore_0),
486 INSN_LABEL(dstore_1),
487 INSN_LABEL(dstore_2),
488 INSN_LABEL(dstore_3),
489 INSN_LABEL(astore_0),
490 INSN_LABEL(astore_1),
491 INSN_LABEL(astore_2),
492 INSN_LABEL(astore_3),
493 INSN_LABEL(iastore),
494 INSN_LABEL(lastore),
495 INSN_LABEL(fastore),
496 INSN_LABEL(dastore),
497 INSN_LABEL(aastore),
498 INSN_LABEL(bastore),
499 INSN_LABEL(castore),
500 INSN_LABEL(sastore),
501 INSN_LABEL(pop),
502 INSN_LABEL(pop2),
503 INSN_LABEL(dup),
504 INSN_LABEL(dup_x1),
505 INSN_LABEL(dup_x2),
506 INSN_LABEL(dup2),
507 INSN_LABEL(dup2_x1),
508 INSN_LABEL(dup2_x2),
509 INSN_LABEL(swap),
510 INSN_LABEL(iadd),
511 INSN_LABEL(ladd),
512 INSN_LABEL(fadd),
513 INSN_LABEL(dadd),
514 INSN_LABEL(isub),
515 INSN_LABEL(lsub),
516 INSN_LABEL(fsub),
517 INSN_LABEL(dsub),
518 INSN_LABEL(imul),
519 INSN_LABEL(lmul),
520 INSN_LABEL(fmul),
521 INSN_LABEL(dmul),
522 INSN_LABEL(idiv),
523 INSN_LABEL(ldiv),
524 INSN_LABEL(fdiv),
525 INSN_LABEL(ddiv),
526 INSN_LABEL(irem),
527 INSN_LABEL(lrem),
528 INSN_LABEL(frem),
529 INSN_LABEL(drem),
530 INSN_LABEL(ineg),
531 INSN_LABEL(lneg),
532 INSN_LABEL(fneg),
533 INSN_LABEL(dneg),
534 INSN_LABEL(ishl),
535 INSN_LABEL(lshl),
536 INSN_LABEL(ishr),
537 INSN_LABEL(lshr),
538 INSN_LABEL(iushr),
539 INSN_LABEL(lushr),
540 INSN_LABEL(iand),
541 INSN_LABEL(land),
542 INSN_LABEL(ior),
543 INSN_LABEL(lor),
544 INSN_LABEL(ixor),
545 INSN_LABEL(lxor),
546 INSN_LABEL(iinc),
547 INSN_LABEL(i2l),
548 INSN_LABEL(i2f),
549 INSN_LABEL(i2d),
550 INSN_LABEL(l2i),
551 INSN_LABEL(l2f),
552 INSN_LABEL(l2d),
553 INSN_LABEL(f2i),
554 INSN_LABEL(f2l),
555 INSN_LABEL(f2d),
556 INSN_LABEL(d2i),
557 INSN_LABEL(d2l),
558 INSN_LABEL(d2f),
559 INSN_LABEL(i2b),
560 INSN_LABEL(i2c),
561 INSN_LABEL(i2s),
562 INSN_LABEL(lcmp),
563 INSN_LABEL(fcmpl),
564 INSN_LABEL(fcmpg),
565 INSN_LABEL(dcmpl),
566 INSN_LABEL(dcmpg),
567 INSN_LABEL(ifeq),
568 INSN_LABEL(ifne),
569 INSN_LABEL(iflt),
570 INSN_LABEL(ifge),
571 INSN_LABEL(ifgt),
572 INSN_LABEL(ifle),
573 INSN_LABEL(if_icmpeq),
574 INSN_LABEL(if_icmpne),
575 INSN_LABEL(if_icmplt),
576 INSN_LABEL(if_icmpge),
577 INSN_LABEL(if_icmpgt),
578 INSN_LABEL(if_icmple),
579 INSN_LABEL(if_acmpeq),
580 INSN_LABEL(if_acmpne),
581 INSN_LABEL(goto),
582 INSN_LABEL(jsr),
583 INSN_LABEL(ret),
584 INSN_LABEL(tableswitch),
585 INSN_LABEL(lookupswitch),
586 INSN_LABEL(ireturn),
587 INSN_LABEL(lreturn),
588 INSN_LABEL(freturn),
589 INSN_LABEL(dreturn),
590 INSN_LABEL(areturn),
591 INSN_LABEL(return),
592 INSN_LABEL(getstatic),
593 INSN_LABEL(putstatic),
594 INSN_LABEL(getfield),
595 INSN_LABEL(putfield),
596 INSN_LABEL(invokevirtual),
597 INSN_LABEL(invokespecial),
598 INSN_LABEL(invokestatic),
599 INSN_LABEL(invokeinterface),
600 0, /* op_xxxunusedxxx1, */
601 INSN_LABEL(new),
602 INSN_LABEL(newarray),
603 INSN_LABEL(anewarray),
604 INSN_LABEL(arraylength),
605 INSN_LABEL(athrow),
606 INSN_LABEL(checkcast),
607 INSN_LABEL(instanceof),
608 INSN_LABEL(monitorenter),
609 INSN_LABEL(monitorexit),
610 INSN_LABEL(wide),
611 INSN_LABEL(multianewarray),
612 INSN_LABEL(ifnull),
613 INSN_LABEL(ifnonnull),
614 INSN_LABEL(goto_w),
615 INSN_LABEL(jsr_w),
618 #define SAVE_PC inv->pc = pc-1
620 /* If the macro INLINE_SWITCH is not defined, then the main loop
621 operates as one big (normal) switch statement. If it is defined,
622 then the case selection is performed `inline' in the end of the
623 code for each case. The latter saves a native branch instruction
624 for each java-instruction, but expands the code size somewhat.
626 NOTE: On i386 defining INLINE_SWITCH improves over all
627 performance approximately seven percent, but it may be different
628 for other machines. At some point, this may be made into a proper
629 configuration parameter. */
631 #define INLINE_SWITCH
633 #ifdef INLINE_SWITCH
635 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
638 NEXT_INSN;
639 #else
641 #define NEXT_INSN goto next_insn
643 next_insn:
644 GOTO_INSN (*pc++);
646 #endif
648 /* The first few instructions here are ordered according to their
649 frequency, in the hope that this will improve code locality a
650 little. */
652 insn_aload_0: // 0x2a
653 LOADA(0);
654 NEXT_INSN;
656 insn_iload: // 0x15
657 LOADI (get1u (pc++));
658 NEXT_INSN;
660 insn_iload_1: // 0x1b
661 LOADI (1);
662 NEXT_INSN;
664 insn_invokevirtual: // 0xb6
665 SAVE_PC;
667 int index = get2u (pc); pc += 2;
669 /* _Jv_ResolvePoolEntry returns immediately if the value already
670 * is resolved. If we want to clutter up the code here to gain
671 * a little performance, then we can check the corresponding bit
672 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
673 * don't think it is worth it. */
675 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
677 sp -= rmeth->stack_item_count;
678 // We don't use NULLCHECK here because we can't rely on that
679 // working if the method is final. So instead we do an
680 // explicit test.
681 if (! sp[0].o)
682 throw new java::lang::NullPointerException;
684 if (rmeth->vtable_index == -1)
686 // final methods do not appear in the vtable,
687 // if it does not appear in the superclass.
688 fun = (void (*)()) rmeth->method->ncode;
690 else
692 jobject rcv = sp[0].o;
693 _Jv_VTable *table = *(_Jv_VTable**)rcv;
694 fun = (void (*)()) table->method[rmeth->vtable_index];
697 goto perform_invoke;
699 perform_invoke:
701 /* here goes the magic again... */
702 ffi_cif *cif = &rmeth->cif;
703 ffi_raw *raw = (ffi_raw*) sp;
705 jdouble rvalue;
707 #if FFI_NATIVE_RAW_API
708 /* We assume that this is only implemented if it's correct */
709 /* to use it here. On a 64 bit machine, it never is. */
710 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
711 #else
712 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
713 #endif
715 int rtype = cif->rtype->type;
717 /* the likelyhood of object, int, or void return is very high,
718 * so those are checked before the switch */
719 if (rtype == FFI_TYPE_POINTER)
721 PUSHA (*(jobject*)&rvalue);
723 else if (rtype == FFI_TYPE_SINT32)
725 PUSHI (*(jint*)&rvalue);
727 else if (rtype == FFI_TYPE_VOID)
729 /* skip */
731 else switch (rtype)
733 case FFI_TYPE_SINT8:
735 jbyte value = (*(jint*)&rvalue) & 0xff;
736 PUSHI (value);
738 break;
740 case FFI_TYPE_SINT16:
742 jshort value = (*(jint*)&rvalue) & 0xffff;
743 PUSHI (value);
745 break;
747 case FFI_TYPE_UINT16:
749 jint value = (*(jint*)&rvalue) & 0xffff;
750 PUSHI (value);
752 break;
754 case FFI_TYPE_FLOAT:
755 PUSHF (*(jfloat*)&rvalue);
756 break;
758 case FFI_TYPE_DOUBLE:
759 PUSHD (rvalue);
760 break;
762 case FFI_TYPE_SINT64:
763 PUSHL (*(jlong*)&rvalue);
764 break;
766 default:
767 throw_internal_error ("unknown return type in invokeXXX");
771 NEXT_INSN;
774 insn_nop:
775 NEXT_INSN;
777 insn_aconst_null:
778 PUSHA (NULL);
779 NEXT_INSN;
781 insn_iconst_m1:
782 PUSHI (-1);
783 NEXT_INSN;
785 insn_iconst_0:
786 PUSHI (0);
787 NEXT_INSN;
789 insn_iconst_1:
790 PUSHI (1);
791 NEXT_INSN;
793 insn_iconst_2:
794 PUSHI (2);
795 NEXT_INSN;
797 insn_iconst_3:
798 PUSHI (3);
799 NEXT_INSN;
801 insn_iconst_4:
802 PUSHI (4);
803 NEXT_INSN;
805 insn_iconst_5:
806 PUSHI (5);
807 NEXT_INSN;
809 insn_lconst_0:
810 PUSHL (0);
811 NEXT_INSN;
813 insn_lconst_1:
814 PUSHL (1);
815 NEXT_INSN;
817 insn_fconst_0:
818 PUSHF (0);
819 NEXT_INSN;
821 insn_fconst_1:
822 PUSHF (1);
823 NEXT_INSN;
825 insn_fconst_2:
826 PUSHF (2);
827 NEXT_INSN;
829 insn_dconst_0:
830 PUSHD (0);
831 NEXT_INSN;
833 insn_dconst_1:
834 PUSHD (1);
835 NEXT_INSN;
837 insn_bipush:
838 PUSHI (get1s(pc++));
839 NEXT_INSN;
841 insn_sipush:
842 PUSHI (get2s(pc)); pc += 2;
843 NEXT_INSN;
845 insn_ldc:
847 int index = get1u (pc++);
848 PUSHA(pool_data[index].o);
850 NEXT_INSN;
852 insn_ldc_w:
854 int index = get2u (pc); pc += 2;
855 PUSHA(pool_data[index].o);
857 NEXT_INSN;
859 insn_ldc2_w:
861 int index = get2u (pc); pc += 2;
862 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
863 sp += 2;
865 NEXT_INSN;
867 insn_lload:
868 LOADL (get1u (pc++));
869 NEXT_INSN;
871 insn_fload:
872 LOADF (get1u (pc++));
873 NEXT_INSN;
875 insn_dload:
876 LOADD (get1u (pc++));
877 NEXT_INSN;
879 insn_aload:
880 LOADA (get1u (pc++));
881 NEXT_INSN;
883 insn_iload_0:
884 LOADI (0);
885 NEXT_INSN;
887 insn_iload_2:
888 LOADI (2);
889 NEXT_INSN;
891 insn_iload_3:
892 LOADI (3);
893 NEXT_INSN;
895 insn_lload_0:
896 LOADL (0);
897 NEXT_INSN;
899 insn_lload_1:
900 LOADL (1);
901 NEXT_INSN;
903 insn_lload_2:
904 LOADL (2);
905 NEXT_INSN;
907 insn_lload_3:
908 LOADL (3);
909 NEXT_INSN;
911 insn_fload_0:
912 LOADF (0);
913 NEXT_INSN;
915 insn_fload_1:
916 LOADF (1);
917 NEXT_INSN;
919 insn_fload_2:
920 LOADF (2);
921 NEXT_INSN;
923 insn_fload_3:
924 LOADF (3);
925 NEXT_INSN;
927 insn_dload_0:
928 LOADD (0);
929 NEXT_INSN;
931 insn_dload_1:
932 LOADD (1);
933 NEXT_INSN;
935 insn_dload_2:
936 LOADD (2);
937 NEXT_INSN;
939 insn_dload_3:
940 LOADD (3);
941 NEXT_INSN;
943 insn_aload_1:
944 LOADA(1);
945 NEXT_INSN;
947 insn_aload_2:
948 LOADA(2);
949 NEXT_INSN;
951 insn_aload_3:
952 LOADA(3);
953 NEXT_INSN;
955 insn_iaload:
956 SAVE_PC;
958 jint index = POPI();
959 jintArray arr = (jintArray) POPA();
960 NULLCHECK (arr);
961 if (index < 0 || index >= arr->length)
963 _Jv_ThrowBadArrayIndex (index);
965 PUSHI( elements(arr)[index] );
967 NEXT_INSN;
969 insn_laload:
970 SAVE_PC;
972 jint index = POPI();
973 jlongArray arr = (jlongArray) POPA();
974 NULLCHECK (arr);
975 if (index < 0 || index >= arr->length)
977 _Jv_ThrowBadArrayIndex (index);
979 PUSHL( elements(arr)[index] );
981 NEXT_INSN;
983 insn_faload:
984 SAVE_PC;
986 jint index = POPI();
987 jfloatArray arr = (jfloatArray) POPA();
988 NULLCHECK (arr);
989 if (index < 0 || index >= arr->length)
991 _Jv_ThrowBadArrayIndex (index);
993 PUSHF( elements(arr)[index] );
995 NEXT_INSN;
997 insn_daload:
998 SAVE_PC;
1000 jint index = POPI();
1001 jdoubleArray arr = (jdoubleArray) POPA();
1002 NULLCHECK (arr);
1003 if (index < 0 || index >= arr->length)
1005 _Jv_ThrowBadArrayIndex (index);
1007 PUSHD( elements(arr)[index] );
1009 NEXT_INSN;
1011 insn_aaload:
1012 SAVE_PC;
1014 jint index = POPI();
1015 jobjectArray arr = (jobjectArray) POPA();
1016 NULLCHECK (arr);
1017 if (index < 0 || index >= arr->length)
1019 _Jv_ThrowBadArrayIndex (index);
1021 PUSHA( elements(arr)[index] );
1023 NEXT_INSN;
1025 insn_baload:
1026 SAVE_PC;
1028 jint index = POPI();
1029 jbyteArray arr = (jbyteArray) POPA();
1030 NULLCHECK (arr);
1031 if (index < 0 || index >= arr->length)
1033 _Jv_ThrowBadArrayIndex (index);
1035 PUSHI( elements(arr)[index] );
1037 NEXT_INSN;
1039 insn_caload:
1040 SAVE_PC;
1042 jint index = POPI();
1043 jcharArray arr = (jcharArray) POPA();
1044 NULLCHECK (arr);
1045 if (index < 0 || index >= arr->length)
1047 _Jv_ThrowBadArrayIndex (index);
1049 PUSHI( elements(arr)[index] );
1051 NEXT_INSN;
1053 insn_saload:
1054 SAVE_PC;
1056 jint index = POPI();
1057 jshortArray arr = (jshortArray) POPA();
1058 NULLCHECK (arr);
1059 if (index < 0 || index >= arr->length)
1061 _Jv_ThrowBadArrayIndex (index);
1063 PUSHI( elements(arr)[index] );
1065 NEXT_INSN;
1067 insn_istore:
1068 STOREI (get1u (pc++));
1069 NEXT_INSN;
1071 insn_lstore:
1072 STOREL (get1u (pc++));
1073 NEXT_INSN;
1075 insn_fstore:
1076 STOREF (get1u (pc++));
1077 NEXT_INSN;
1079 insn_dstore:
1080 STORED (get1u (pc++));
1081 NEXT_INSN;
1083 insn_astore:
1084 STOREA (get1u (pc++));
1085 NEXT_INSN;
1087 insn_istore_0:
1088 STOREI (0);
1089 NEXT_INSN;
1091 insn_istore_1:
1092 STOREI (1);
1093 NEXT_INSN;
1095 insn_istore_2:
1096 STOREI (2);
1097 NEXT_INSN;
1099 insn_istore_3:
1100 STOREI (3);
1101 NEXT_INSN;
1103 insn_lstore_0:
1104 STOREL (0);
1105 NEXT_INSN;
1107 insn_lstore_1:
1108 STOREL (1);
1109 NEXT_INSN;
1111 insn_lstore_2:
1112 STOREL (2);
1113 NEXT_INSN;
1115 insn_lstore_3:
1116 STOREL (3);
1117 NEXT_INSN;
1119 insn_fstore_0:
1120 STOREF (0);
1121 NEXT_INSN;
1123 insn_fstore_1:
1124 STOREF (1);
1125 NEXT_INSN;
1127 insn_fstore_2:
1128 STOREF (2);
1129 NEXT_INSN;
1131 insn_fstore_3:
1132 STOREF (3);
1133 NEXT_INSN;
1135 insn_dstore_0:
1136 STORED (0);
1137 NEXT_INSN;
1139 insn_dstore_1:
1140 STORED (1);
1141 NEXT_INSN;
1143 insn_dstore_2:
1144 STORED (2);
1145 NEXT_INSN;
1147 insn_dstore_3:
1148 STORED (3);
1149 NEXT_INSN;
1151 insn_astore_0:
1152 STOREA(0);
1153 NEXT_INSN;
1155 insn_astore_1:
1156 STOREA(1);
1157 NEXT_INSN;
1159 insn_astore_2:
1160 STOREA(2);
1161 NEXT_INSN;
1163 insn_astore_3:
1164 STOREA(3);
1165 NEXT_INSN;
1167 insn_iastore:
1168 SAVE_PC;
1170 jint value = POPI();
1171 jint index = POPI();
1172 jintArray arr = (jintArray) POPA();
1173 NULLCHECK (arr);
1174 if (index < 0 || index >= arr->length)
1176 _Jv_ThrowBadArrayIndex (index);
1178 elements(arr)[index] = value;
1180 NEXT_INSN;
1182 insn_lastore:
1183 SAVE_PC;
1185 jlong value = POPL();
1186 jint index = POPI();
1187 jlongArray arr = (jlongArray) POPA();
1188 NULLCHECK (arr);
1189 if (index < 0 || index >= arr->length)
1191 _Jv_ThrowBadArrayIndex (index);
1193 elements(arr)[index] = value;
1195 NEXT_INSN;
1197 insn_fastore:
1198 SAVE_PC;
1200 jfloat value = POPF();
1201 jint index = POPI();
1202 jfloatArray arr = (jfloatArray) POPA();
1203 NULLCHECK (arr);
1204 if (index < 0 || index >= arr->length)
1206 _Jv_ThrowBadArrayIndex (index);
1208 elements(arr)[index] = value;
1210 NEXT_INSN;
1212 insn_dastore:
1213 SAVE_PC;
1215 jdouble value = POPD();
1216 jint index = POPI();
1217 jdoubleArray arr = (jdoubleArray) POPA();
1218 NULLCHECK (arr);
1219 if (index < 0 || index >= arr->length)
1221 _Jv_ThrowBadArrayIndex (index);
1223 elements(arr)[index] = value;
1225 NEXT_INSN;
1227 insn_aastore:
1228 SAVE_PC;
1230 jobject value = POPA();
1231 jint index = POPI();
1232 jobjectArray arr = (jobjectArray) POPA();
1233 NULLCHECK (arr);
1234 if (index < 0 || index >= arr->length)
1236 _Jv_ThrowBadArrayIndex (index);
1238 _Jv_CheckArrayStore (arr, value);
1239 elements(arr)[index] = value;
1241 NEXT_INSN;
1243 insn_bastore:
1244 SAVE_PC;
1246 jbyte value = (jbyte) POPI();
1247 jint index = POPI();
1248 jbyteArray arr = (jbyteArray) POPA();
1249 NULLCHECK (arr);
1250 if (index < 0 || index >= arr->length)
1252 _Jv_ThrowBadArrayIndex (index);
1254 elements(arr)[index] = value;
1256 NEXT_INSN;
1258 insn_castore:
1259 SAVE_PC;
1261 jchar value = (jchar) POPI();
1262 jint index = POPI();
1263 jcharArray arr = (jcharArray) POPA();
1264 NULLCHECK (arr);
1265 if (index < 0 || index >= arr->length)
1267 _Jv_ThrowBadArrayIndex (index);
1269 elements(arr)[index] = value;
1271 NEXT_INSN;
1273 insn_sastore:
1274 SAVE_PC;
1276 jshort value = (jshort) POPI();
1277 jint index = POPI();
1278 jshortArray arr = (jshortArray) POPA();
1279 NULLCHECK (arr);
1280 if (index < 0 || index >= arr->length)
1282 _Jv_ThrowBadArrayIndex (index);
1284 elements(arr)[index] = value;
1286 NEXT_INSN;
1288 insn_pop:
1289 sp -= 1;
1290 NEXT_INSN;
1292 insn_pop2:
1293 sp -= 2;
1294 NEXT_INSN;
1296 insn_dup:
1297 sp[0] = sp[-1];
1298 sp += 1;
1299 NEXT_INSN;
1301 insn_dup_x1:
1302 dupx (sp, 1, 1); sp+=1;
1303 NEXT_INSN;
1305 insn_dup_x2:
1306 dupx (sp, 1, 2); sp+=1;
1307 NEXT_INSN;
1309 insn_dup2:
1310 sp[0] = sp[-2];
1311 sp[1] = sp[-1];
1312 sp += 2;
1313 NEXT_INSN;
1315 insn_dup2_x1:
1316 dupx (sp, 2, 1); sp+=2;
1317 NEXT_INSN;
1319 insn_dup2_x2:
1320 dupx (sp, 2, 2); sp+=2;
1321 NEXT_INSN;
1323 insn_swap:
1325 jobject tmp1 = POPA();
1326 jobject tmp2 = POPA();
1327 PUSHA (tmp1);
1328 PUSHA (tmp2);
1330 NEXT_INSN;
1332 insn_iadd:
1333 BINOPI(+);
1334 NEXT_INSN;
1336 insn_ladd:
1337 BINOPL(+);
1338 NEXT_INSN;
1340 insn_fadd:
1341 BINOPF(+);
1342 NEXT_INSN;
1344 insn_dadd:
1345 BINOPD(+);
1346 NEXT_INSN;
1348 insn_isub:
1349 BINOPI(-);
1350 NEXT_INSN;
1352 insn_lsub:
1353 BINOPL(-);
1354 NEXT_INSN;
1356 insn_fsub:
1357 BINOPF(-);
1358 NEXT_INSN;
1360 insn_dsub:
1361 BINOPD(-);
1362 NEXT_INSN;
1364 insn_imul:
1365 BINOPI(*);
1366 NEXT_INSN;
1368 insn_lmul:
1369 BINOPL(*);
1370 NEXT_INSN;
1372 insn_fmul:
1373 BINOPF(*);
1374 NEXT_INSN;
1376 insn_dmul:
1377 BINOPD(*);
1378 NEXT_INSN;
1380 insn_idiv:
1381 SAVE_PC;
1383 jint value2 = POPI();
1384 jint value1 = POPI();
1385 jint res = _Jv_divI (value1, value2);
1386 PUSHI (res);
1388 NEXT_INSN;
1390 insn_ldiv:
1391 SAVE_PC;
1393 jlong value2 = POPL();
1394 jlong value1 = POPL();
1395 jlong res = _Jv_divJ (value1, value2);
1396 PUSHL (res);
1398 NEXT_INSN;
1400 insn_fdiv:
1401 SAVE_PC;
1403 jfloat value2 = POPF();
1404 jfloat value1 = POPF();
1405 jfloat res = value1 / value2;
1406 PUSHF (res);
1408 NEXT_INSN;
1410 insn_ddiv:
1411 SAVE_PC;
1413 jdouble value2 = POPD();
1414 jdouble value1 = POPD();
1415 jdouble res = value1 / value2;
1416 PUSHD (res);
1418 NEXT_INSN;
1420 insn_irem:
1421 SAVE_PC;
1423 jint value2 = POPI();
1424 jint value1 = POPI();
1425 jint res = _Jv_remI (value1, value2);
1426 PUSHI (res);
1428 NEXT_INSN;
1430 insn_lrem:
1431 SAVE_PC;
1433 jlong value2 = POPL();
1434 jlong value1 = POPL();
1435 jlong res = _Jv_remJ (value1, value2);
1436 PUSHL (res);
1438 NEXT_INSN;
1440 insn_frem:
1441 SAVE_PC;
1443 jfloat value2 = POPF();
1444 jfloat value1 = POPF();
1445 jfloat res = __ieee754_fmod (value1, value2);
1446 PUSHF (res);
1448 NEXT_INSN;
1450 insn_drem:
1451 SAVE_PC;
1453 jdouble value2 = POPD();
1454 jdouble value1 = POPD();
1455 jdouble res = __ieee754_fmod (value1, value2);
1456 PUSHD (res);
1458 NEXT_INSN;
1460 insn_ineg:
1462 jint value = POPI();
1463 PUSHI (value * -1);
1465 NEXT_INSN;
1467 insn_lneg:
1469 jlong value = POPL();
1470 PUSHL (value * -1);
1472 NEXT_INSN;
1474 insn_fneg:
1476 jfloat value = POPF();
1477 PUSHF (value * -1);
1479 NEXT_INSN;
1481 insn_dneg:
1483 jdouble value = POPD();
1484 PUSHD (value * -1);
1486 NEXT_INSN;
1488 insn_ishl:
1490 jint shift = (POPI() & 0x1f);
1491 jint value = POPI();
1492 PUSHI (value << shift);
1494 NEXT_INSN;
1496 insn_lshl:
1498 jint shift = (POPI() & 0x3f);
1499 jlong value = POPL();
1500 PUSHL (value << shift);
1502 NEXT_INSN;
1504 insn_ishr:
1506 jint shift = (POPI() & 0x1f);
1507 jint value = POPI();
1508 PUSHI (value >> shift);
1510 NEXT_INSN;
1512 insn_lshr:
1514 jint shift = (POPI() & 0x3f);
1515 jlong value = POPL();
1516 PUSHL (value >> shift);
1518 NEXT_INSN;
1520 insn_iushr:
1522 jint shift = (POPI() & 0x1f);
1523 unsigned long value = POPI();
1524 PUSHI ((jint) (value >> shift));
1526 NEXT_INSN;
1528 insn_lushr:
1530 jint shift = (POPI() & 0x3f);
1531 UINT64 value = (UINT64) POPL();
1532 PUSHL ((value >> shift));
1534 NEXT_INSN;
1536 insn_iand:
1537 BINOPI (&);
1538 NEXT_INSN;
1540 insn_land:
1541 BINOPL (&);
1542 NEXT_INSN;
1544 insn_ior:
1545 BINOPI (|);
1546 NEXT_INSN;
1548 insn_lor:
1549 BINOPL (|);
1550 NEXT_INSN;
1552 insn_ixor:
1553 BINOPI (^);
1554 NEXT_INSN;
1556 insn_lxor:
1557 BINOPL (^);
1558 NEXT_INSN;
1560 insn_iinc:
1562 jint index = get1u (pc++);
1563 jint amount = get1s (pc++);
1564 locals[index].i += amount;
1566 NEXT_INSN;
1568 insn_i2l:
1569 {jlong value = POPI(); PUSHL (value);}
1570 NEXT_INSN;
1572 insn_i2f:
1573 {jfloat value = POPI(); PUSHF (value);}
1574 NEXT_INSN;
1576 insn_i2d:
1577 {jdouble value = POPI(); PUSHD (value);}
1578 NEXT_INSN;
1580 insn_l2i:
1581 {jint value = POPL(); PUSHI (value);}
1582 NEXT_INSN;
1584 insn_l2f:
1585 {jfloat value = POPL(); PUSHF (value);}
1586 NEXT_INSN;
1588 insn_l2d:
1589 {jdouble value = POPL(); PUSHD (value);}
1590 NEXT_INSN;
1592 insn_f2i:
1593 { jint value = (jint)POPF (); PUSHI(value); }
1594 NEXT_INSN;
1596 insn_f2l:
1597 { jlong value = (jlong)POPF (); PUSHL(value); }
1598 NEXT_INSN;
1600 insn_f2d:
1601 { jdouble value = POPF (); PUSHD(value); }
1602 NEXT_INSN;
1604 insn_d2i:
1605 { jint value = (jint)POPD (); PUSHI(value); }
1606 NEXT_INSN;
1608 insn_d2l:
1609 { jlong value = (jlong)POPD (); PUSHL(value); }
1610 NEXT_INSN;
1612 insn_d2f:
1613 { jfloat value = POPD (); PUSHF(value); }
1614 NEXT_INSN;
1616 insn_i2b:
1617 { jbyte value = POPI (); PUSHI(value); }
1618 NEXT_INSN;
1620 insn_i2c:
1621 { jchar value = POPI (); PUSHI(value); }
1622 NEXT_INSN;
1624 insn_i2s:
1625 { jshort value = POPI (); PUSHI(value); }
1626 NEXT_INSN;
1628 insn_lcmp:
1630 jlong value2 = POPL ();
1631 jlong value1 = POPL ();
1632 if (value1 > value2)
1633 { PUSHI (1); }
1634 else if (value1 == value2)
1635 { PUSHI (0); }
1636 else
1637 { PUSHI (-1); }
1639 NEXT_INSN;
1641 insn_fcmpl:
1642 insn_fcmpg:
1644 jfloat value2 = POPF ();
1645 jfloat value1 = POPF ();
1646 if (value1 > value2)
1647 PUSHI (1);
1648 else if (value1 == value2)
1649 PUSHI (0);
1650 else if (value1 < value2)
1651 PUSHI (-1);
1652 else if ((*(pc-1)) == op_fcmpg)
1653 PUSHI (1);
1654 else
1655 PUSHI (-1);
1657 NEXT_INSN;
1659 insn_dcmpl:
1660 insn_dcmpg:
1662 jdouble value2 = POPD ();
1663 jdouble value1 = POPD ();
1664 if (value1 > value2)
1665 PUSHI (1);
1666 else if (value1 == value2)
1667 PUSHI (0);
1668 else if (value1 < value2)
1669 PUSHI (-1);
1670 else if ((*(pc-1)) == op_dcmpg)
1671 PUSHI (1);
1672 else
1673 PUSHI (-1);
1675 NEXT_INSN;
1677 insn_ifeq:
1679 jint offset = get2s (pc);
1680 if (POPI() == 0)
1681 pc = pc-1+offset;
1682 else
1683 pc = pc+2;
1685 NEXT_INSN;
1687 insn_ifne:
1689 jint offset = get2s (pc);
1690 if (POPI() != 0)
1691 pc = pc-1+offset;
1692 else
1693 pc = pc+2;
1695 NEXT_INSN;
1697 insn_iflt:
1699 jint offset = get2s (pc);
1700 if (POPI() < 0)
1701 pc = pc-1+offset;
1702 else
1703 pc = pc+2;
1705 NEXT_INSN;
1707 insn_ifge:
1709 jint offset = get2s (pc);
1710 if (POPI() >= 0)
1711 pc = pc-1+offset;
1712 else
1713 pc = pc+2;
1715 NEXT_INSN;
1717 insn_ifgt:
1719 jint offset = get2s (pc);
1720 if (POPI() > 0)
1721 pc = pc-1+offset;
1722 else
1723 pc = pc+2;
1725 NEXT_INSN;
1727 insn_ifle:
1729 jint offset = get2s (pc);
1730 if (POPI() <= 0)
1731 pc = pc-1+offset;
1732 else
1733 pc = pc+2;
1735 NEXT_INSN;
1737 insn_if_icmpeq:
1739 jint offset = get2s (pc);
1740 jint value2 = POPI();
1741 jint value1 = POPI();
1742 if (value1 == value2)
1743 pc = pc-1+offset;
1744 else
1745 pc = pc+2;
1747 NEXT_INSN;
1749 insn_if_icmpne:
1751 jint offset = get2s (pc);
1752 jint value2 = POPI();
1753 jint value1 = POPI();
1754 if (value1 != value2)
1755 pc = pc-1+offset;
1756 else
1757 pc = pc+2;
1759 NEXT_INSN;
1761 insn_if_icmplt:
1763 jint offset = get2s (pc);
1764 jint value2 = POPI();
1765 jint value1 = POPI();
1766 if (value1 < value2)
1767 pc = pc-1+offset;
1768 else
1769 pc = pc+2;
1771 NEXT_INSN;
1773 insn_if_icmpge:
1775 jint offset = get2s (pc);
1776 jint value2 = POPI();
1777 jint value1 = POPI();
1778 if (value1 >= value2)
1779 pc = pc-1+offset;
1780 else
1781 pc = pc+2;
1783 NEXT_INSN;
1785 insn_if_icmpgt:
1787 jint offset = get2s (pc);
1788 jint value2 = POPI();
1789 jint value1 = POPI();
1790 if (value1 > value2)
1791 pc = pc-1+offset;
1792 else
1793 pc = pc+2;
1795 NEXT_INSN;
1797 insn_if_icmple:
1799 jint offset = get2s (pc);
1800 jint value2 = POPI();
1801 jint value1 = POPI();
1802 if (value1 <= value2)
1803 pc = pc-1+offset;
1804 else
1805 pc = pc+2;
1807 NEXT_INSN;
1809 insn_if_acmpeq:
1811 jint offset = get2s (pc);
1812 jobject value2 = POPA();
1813 jobject value1 = POPA();
1814 if (value1 == value2)
1815 pc = pc-1+offset;
1816 else
1817 pc = pc+2;
1819 NEXT_INSN;
1821 insn_if_acmpne:
1823 jint offset = get2s (pc);
1824 jobject value2 = POPA();
1825 jobject value1 = POPA();
1826 if (value1 != value2)
1827 pc = pc-1+offset;
1828 else
1829 pc = pc+2;
1831 NEXT_INSN;
1833 insn_goto:
1835 jint offset = get2s (pc);
1836 pc = pc-1+offset;
1838 NEXT_INSN;
1840 insn_jsr:
1842 unsigned char *base_pc = pc-1;
1843 jint offset = get2s (pc); pc += 2;
1844 PUSHA ((jobject)pc);
1845 pc = base_pc+offset;
1847 NEXT_INSN;
1849 insn_ret:
1851 jint index = get1u (pc);
1852 pc = (unsigned char*) PEEKA (index);
1854 NEXT_INSN;
1856 insn_tableswitch:
1858 unsigned char *base_pc = pc-1;
1859 int index = POPI();
1861 unsigned char* base = bytecode ();
1862 while ((pc-base) % 4 != 0)
1863 pc++;
1865 jint def = get4 (pc);
1866 jint low = get4 (pc+4);
1867 jint high = get4 (pc+8);
1869 if (index < low || index > high)
1870 pc = base_pc + def;
1871 else
1872 pc = base_pc + get4 (pc+4*(index-low+3));
1874 NEXT_INSN;
1876 insn_lookupswitch:
1878 unsigned char *base_pc = pc-1;
1879 int index = POPI();
1881 unsigned char* base = bytecode ();
1882 while ((pc-base) % 4 != 0)
1883 pc++;
1885 jint def = get4 (pc);
1886 jint npairs = get4 (pc+4);
1888 int max = npairs-1;
1889 int min = 0;
1891 // simple binary search...
1892 while (min < max)
1894 int half = (min+max)/2;
1895 int match = get4 (pc+ 4*(2 + 2*half));
1897 if (index == match)
1898 min = max = half;
1900 else if (index < match)
1901 max = half-1;
1903 else
1904 min = half+1;
1907 if (index == get4 (pc+ 4*(2 + 2*min)))
1908 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1909 else
1910 pc = base_pc + def;
1912 NEXT_INSN;
1914 /* on return, just save the sp and return to caller */
1915 insn_ireturn:
1916 insn_lreturn:
1917 insn_freturn:
1918 insn_dreturn:
1919 insn_areturn:
1920 insn_return:
1921 inv->sp = sp;
1922 return;
1924 insn_getstatic:
1925 SAVE_PC;
1927 jint fieldref_index = get2u (pc); pc += 2;
1928 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1929 _Jv_Field *field = pool_data[fieldref_index].field;
1931 if ((field->flags & Modifier::STATIC) == 0)
1932 throw_incompatible_class_change_error
1933 (JvNewStringLatin1 ("field no longer static"));
1935 jclass type = field->type;
1937 if (type->isPrimitive ())
1939 switch (type->size_in_bytes)
1941 case 1:
1942 PUSHI (*(jbyte*) (field->u.addr));
1943 break;
1945 case 2:
1946 if (type == JvPrimClass (char))
1947 PUSHI(*(jchar*) (field->u.addr));
1948 else
1949 PUSHI(*(jshort*) (field->u.addr));
1950 break;
1952 case 4:
1953 PUSHI(*(jint*) (field->u.addr));
1954 break;
1956 case 8:
1957 PUSHL(*(jlong*) (field->u.addr));
1958 break;
1961 else
1963 PUSHA(*(jobject*) (field->u.addr));
1966 NEXT_INSN;
1968 insn_getfield:
1969 SAVE_PC;
1971 jint fieldref_index = get2u (pc); pc += 2;
1972 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1973 _Jv_Field *field = pool_data[fieldref_index].field;
1975 if ((field->flags & Modifier::STATIC) != 0)
1976 throw_incompatible_class_change_error
1977 (JvNewStringLatin1 ("field is static"));
1979 jclass type = field->type;
1980 jint field_offset = field->u.boffset;
1981 if (field_offset > 0xffff)
1982 throw new java::lang::VirtualMachineError;
1984 jobject obj = POPA();
1985 NULLCHECK(obj);
1987 if (type->isPrimitive ())
1989 switch (type->size_in_bytes)
1991 case 1:
1992 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1993 break;
1995 case 2:
1996 if (type == JvPrimClass (char))
1997 PUSHI (*(jchar*) ((char*)obj + field_offset));
1998 else
1999 PUSHI (*(jshort*) ((char*)obj + field_offset));
2000 break;
2002 case 4:
2003 PUSHI (*(jint*) ((char*)obj + field_offset));
2004 break;
2006 case 8:
2007 PUSHL(*(jlong*) ((char*)obj + field_offset));
2008 break;
2011 else
2013 PUSHA(*(jobject*) ((char*)obj + field_offset));
2016 NEXT_INSN;
2018 insn_putstatic:
2019 SAVE_PC;
2021 jint fieldref_index = get2u (pc); pc += 2;
2022 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2023 _Jv_Field *field = pool_data[fieldref_index].field;
2025 jclass type = field->type;
2027 // ResolvePoolEntry cannot check this
2028 if ((field->flags & Modifier::STATIC) == 0)
2029 throw_incompatible_class_change_error
2030 (JvNewStringLatin1 ("field no longer static"));
2032 if (type->isPrimitive ())
2034 switch (type->size_in_bytes)
2036 case 1:
2038 jint value = POPI();
2039 *(jbyte*) (field->u.addr) = value;
2040 break;
2043 case 2:
2045 jint value = POPI();
2046 *(jchar*) (field->u.addr) = value;
2047 break;
2050 case 4:
2052 jint value = POPI();
2053 *(jint*) (field->u.addr) = value;
2054 break;
2057 case 8:
2059 jlong value = POPL();
2060 *(jlong*) (field->u.addr) = value;
2061 break;
2065 else
2067 jobject value = POPA();
2068 *(jobject*) (field->u.addr) = value;
2071 NEXT_INSN;
2074 insn_putfield:
2075 SAVE_PC;
2077 jint fieldref_index = get2u (pc); pc += 2;
2078 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2079 _Jv_Field *field = pool_data[fieldref_index].field;
2081 jclass type = field->type;
2083 if ((field->flags & Modifier::STATIC) != 0)
2084 throw_incompatible_class_change_error
2085 (JvNewStringLatin1 ("field is static"));
2087 jint field_offset = field->u.boffset;
2088 if (field_offset > 0xffff)
2089 throw new java::lang::VirtualMachineError;
2091 if (type->isPrimitive ())
2093 switch (type->size_in_bytes)
2095 case 1:
2097 jint value = POPI();
2098 jobject obj = POPA();
2099 NULLCHECK(obj);
2100 *(jbyte*) ((char*)obj + field_offset) = value;
2101 break;
2104 case 2:
2106 jint value = POPI();
2107 jobject obj = POPA();
2108 NULLCHECK(obj);
2109 *(jchar*) ((char*)obj + field_offset) = value;
2110 break;
2113 case 4:
2115 jint value = POPI();
2116 jobject obj = POPA();
2117 NULLCHECK(obj);
2118 *(jint*) ((char*)obj + field_offset) = value;
2119 break;
2122 case 8:
2124 jlong value = POPL();
2125 jobject obj = POPA();
2126 NULLCHECK(obj);
2127 *(jlong*) ((char*)obj + field_offset) = value;
2128 break;
2132 else
2134 jobject value = POPA();
2135 jobject obj = POPA();
2136 NULLCHECK(obj);
2137 *(jobject*) ((char*)obj + field_offset) = value;
2140 NEXT_INSN;
2142 insn_invokespecial:
2143 SAVE_PC;
2145 int index = get2u (pc); pc += 2;
2147 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2149 sp -= rmeth->stack_item_count;
2151 NULLCHECK (sp[0].o);
2153 fun = (void (*)()) rmeth->method->ncode;
2155 goto perform_invoke;
2157 insn_invokestatic:
2158 SAVE_PC;
2160 int index = get2u (pc); pc += 2;
2162 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2164 sp -= rmeth->stack_item_count;
2166 _Jv_InitClass (rmeth->klass);
2167 fun = (void (*)()) rmeth->method->ncode;
2169 goto perform_invoke;
2171 insn_invokeinterface:
2172 SAVE_PC;
2174 int index = get2u (pc); pc += 2;
2176 // invokeinterface has two unused bytes...
2177 pc += 2;
2179 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2181 sp -= rmeth->stack_item_count;
2183 jobject rcv = sp[0].o;
2185 NULLCHECK (rcv);
2187 fun = (void (*)())
2188 _Jv_LookupInterfaceMethod (rcv->getClass (),
2189 rmeth->method->name,
2190 rmeth->method->signature);
2192 goto perform_invoke;
2195 insn_new:
2196 SAVE_PC;
2198 int index = get2u (pc); pc += 2;
2199 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2200 _Jv_InitClass (klass);
2201 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2202 PUSHA (res);
2204 NEXT_INSN;
2206 insn_newarray:
2207 SAVE_PC;
2209 int atype = get1u (pc++);
2210 int size = POPI();
2211 jobject result = _Jv_NewArray (atype, size);
2212 PUSHA (result);
2214 NEXT_INSN;
2216 insn_anewarray:
2217 SAVE_PC;
2219 int index = get2u (pc); pc += 2;
2220 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2221 int size = POPI();
2222 _Jv_InitClass (klass);
2223 jobject result = _Jv_NewObjectArray (size, klass, 0);
2224 PUSHA (result);
2226 NEXT_INSN;
2228 insn_arraylength:
2229 SAVE_PC;
2231 __JArray *arr = (__JArray*)POPA();
2232 PUSHI (arr->length);
2234 NEXT_INSN;
2236 insn_athrow:
2237 SAVE_PC;
2239 jobject value = POPA();
2240 throw static_cast<jthrowable>(value);
2242 NEXT_INSN;
2244 insn_checkcast:
2245 SAVE_PC;
2247 jobject value = POPA();
2248 jint index = get2u (pc); pc += 2;
2249 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2251 if (value != NULL && ! to->isInstance (value))
2253 throw new java::lang::ClassCastException (to->getName());
2256 PUSHA (value);
2258 NEXT_INSN;
2260 insn_instanceof:
2261 SAVE_PC;
2263 jobject value = POPA();
2264 jint index = get2u (pc); pc += 2;
2265 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2266 PUSHI (to->isInstance (value));
2268 NEXT_INSN;
2270 insn_monitorenter:
2271 SAVE_PC;
2273 jobject value = POPA();
2274 NULLCHECK(value);
2275 _Jv_MonitorEnter (value);
2277 NEXT_INSN;
2279 insn_monitorexit:
2280 SAVE_PC;
2282 jobject value = POPA();
2283 NULLCHECK(value);
2284 _Jv_MonitorExit (value);
2286 NEXT_INSN;
2288 insn_ifnull:
2290 unsigned char* base_pc = pc-1;
2291 jint offset = get2s (pc); pc += 2;
2292 jobject val = POPA();
2293 if (val == NULL)
2294 pc = base_pc+offset;
2296 NEXT_INSN;
2298 insn_ifnonnull:
2300 unsigned char* base_pc = pc-1;
2301 jint offset = get2s (pc); pc += 2;
2302 jobject val = POPA();
2303 if (val != NULL)
2304 pc = base_pc+offset;
2306 NEXT_INSN;
2308 insn_wide:
2309 SAVE_PC;
2311 jint the_mod_op = get1u (pc++);
2312 jint wide = get2u (pc); pc += 2;
2314 switch (the_mod_op)
2316 case op_istore:
2317 STOREI (wide);
2318 NEXT_INSN;
2320 case op_fstore:
2321 STOREF (wide);
2322 NEXT_INSN;
2324 case op_astore:
2325 STOREA (wide);
2326 NEXT_INSN;
2328 case op_lload:
2329 LOADL (wide);
2330 NEXT_INSN;
2332 case op_dload:
2333 LOADD (wide);
2334 NEXT_INSN;
2336 case op_iload:
2337 LOADI (wide);
2338 NEXT_INSN;
2340 case op_aload:
2341 LOADA (wide);
2342 NEXT_INSN;
2344 case op_lstore:
2345 STOREL (wide);
2346 NEXT_INSN;
2348 case op_dstore:
2349 STORED (wide);
2350 NEXT_INSN;
2352 case op_ret:
2353 pc = (unsigned char*) PEEKA (wide);
2354 NEXT_INSN;
2356 case op_iinc:
2358 jint amount = get2s (pc); pc += 2;
2359 jint value = PEEKI (wide);
2360 POKEI (wide, value+amount);
2362 NEXT_INSN;
2364 default:
2365 throw_internal_error ("illegal bytecode modified by wide");
2370 insn_multianewarray:
2371 SAVE_PC;
2373 int kind_index = get2u (pc); pc += 2;
2374 int dim = get1u (pc); pc += 1;
2376 jclass type
2377 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2378 _Jv_InitClass (type);
2379 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2381 for (int i = dim - 1; i >= 0; i--)
2383 sizes[i] = POPI ();
2386 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2388 PUSHA (res);
2390 NEXT_INSN;
2392 insn_goto_w:
2394 unsigned char* base_pc = pc-1;
2395 int offset = get4 (pc); pc += 4;
2396 pc = base_pc+offset;
2398 NEXT_INSN;
2400 insn_jsr_w:
2402 unsigned char* base_pc = pc-1;
2403 int offset = get4 (pc); pc += 4;
2404 PUSHA((jobject)pc);
2405 pc = base_pc+offset;
2407 NEXT_INSN;
2411 static void
2412 throw_internal_error (char *msg)
2414 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
2417 static void
2418 throw_incompatible_class_change_error (jstring msg)
2420 throw new java::lang::IncompatibleClassChangeError (msg);
2423 #ifndef HANDLE_SEGV
2424 static java::lang::NullPointerException *null_pointer_exc;
2425 static void
2426 throw_null_pointer_exception ()
2428 if (null_pointer_exc == NULL)
2429 null_pointer_exc = new java::lang::NullPointerException;
2431 throw null_pointer_exc;
2433 #endif
2435 #endif // INTERPRETER