2000-05-31 Alexandre Petit-Bianco <apbianco@cygnus.com>
[official-gcc.git] / libjava / interpret.cc
blobf9fbd3df9fd557a95dd7747cd3710466138e8886
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000 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 <alloca.h>
40 #define ClassError _CL_Q34java4lang5Error
41 extern java::lang::Class ClassError;
43 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
45 static void throw_internal_error (char *msg)
46 __attribute__ ((__noreturn__));
47 static void throw_incompatible_class_change_error (jstring msg)
48 __attribute__ ((__noreturn__));
49 #ifndef HANDLE_SEGV
50 static void throw_null_pointer_exception ()
51 __attribute__ ((__noreturn__));
52 #endif
54 extern "C" double __ieee754_fmod __P((double,double));
56 static inline void dupx (_Jv_word *sp, int n, int x)
58 // first "slide" n+x elements n to the right
59 int top = n-1;
60 for (int i = 0; i < n+x; i++)
62 sp[(top-i)] = sp[(top-i)-n];
65 // next, copy the n top elements, n+x down
66 for (int i = 0; i < n; i++)
68 sp[top-(n+x)-i] = sp[top-i];
74 #define PUSHA(V) (sp++)->o = (V)
75 #define PUSHI(V) (sp++)->i = (V)
76 #define PUSHF(V) (sp++)->f = (V)
77 #if SIZEOF_VOID_P == 8
78 # define PUSHL(V) (sp->l = (V), sp += 2)
79 # define PUSHD(V) (sp->d = (V), sp += 2)
80 #else
81 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
82 (sp++)->ia[0] = w2.ia[0]; \
83 (sp++)->ia[0] = w2.ia[1]; } while (0)
84 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
85 (sp++)->ia[0] = w2.ia[0]; \
86 (sp++)->ia[0] = w2.ia[1]; } while (0)
87 #endif
89 #define POPA() ((--sp)->o)
90 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
91 #define POPF() ((jfloat) (--sp)->f)
92 #if SIZEOF_VOID_P == 8
93 # define POPL() (sp -= 2, (jlong) sp->l)
94 # define POPD() (sp -= 2, (jdouble) sp->d)
95 #else
96 # define POPL() ({ _Jv_word2 w2; \
97 w2.ia[1] = (--sp)->ia[0]; \
98 w2.ia[0] = (--sp)->ia[0]; w2.l; })
99 # define POPD() ({ _Jv_word2 w2; \
100 w2.ia[1] = (--sp)->ia[0]; \
101 w2.ia[0] = (--sp)->ia[0]; w2.d; })
102 #endif
104 #define LOADA(I) (sp++)->o = locals[I].o
105 #define LOADI(I) (sp++)->i = locals[I].i
106 #define LOADF(I) (sp++)->f = locals[I].f
107 #if SIZEOF_VOID_P == 8
108 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
109 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
110 #else
111 # define LOADL(I) do { jint __idx = (I); \
112 (sp++)->ia[0] = locals[__idx].ia[0]; \
113 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
114 } while (0)
115 # define LOADD(I) LOADL(I)
116 #endif
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #if SIZEOF_VOID_P == 8
122 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
123 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
124 #else
125 # define STOREL(I) do { jint __idx = (I); \
126 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
127 locals[__idx].ia[0] = (--sp)->ia[0]; \
128 } while (0)
129 # define STORED(I) STOREL(I)
130 #endif
132 #define PEEKI(I) (locals+(I))->i
133 #define PEEKA(I) (locals+(I))->o
135 #define POKEI(I,V) ((locals+(I))->i = (V))
138 #define BINOPI(OP) { \
139 jint value2 = POPI(); \
140 jint value1 = POPI(); \
141 PUSHI(value1 OP value2); \
144 #define BINOPF(OP) { \
145 jfloat value2 = POPF(); \
146 jfloat value1 = POPF(); \
147 PUSHF(value1 OP value2); \
150 #define BINOPL(OP) { \
151 jlong value2 = POPL(); \
152 jlong value1 = POPL(); \
153 PUSHL(value1 OP value2); \
156 #define BINOPD(OP) { \
157 jdouble value2 = POPD(); \
158 jdouble value1 = POPD(); \
159 PUSHD(value1 OP value2); \
162 static inline jint get1s(unsigned char* loc) {
163 return *(signed char*)loc;
166 static inline jint get1u(unsigned char* loc) {
167 return *loc;
170 static inline jint get2s(unsigned char* loc) {
171 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
174 static inline jint get2u(unsigned char* loc) {
175 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
178 static jint get4(unsigned char* loc) {
179 return (((jint)(loc[0])) << 24)
180 | (((jint)(loc[1])) << 16)
181 | (((jint)(loc[2])) << 8)
182 | (((jint)(loc[3])) << 0);
186 #ifdef HANDLE_SEGV
187 #define NULLCHECK(X)
188 #else
189 #define NULLCHECK(X) \
190 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
191 #endif
194 // this method starts the actual running of the method. It is inlined
195 // in three different variants in the static methods run_normal,
196 // run_sync_object and run_sync_class (see below). Those static methods
197 // are installed directly in the stub for this method (by
198 // _Jv_InterpMethod::ncode, in resolve.cc).
200 inline jobject
201 _Jv_InterpMethod::run (ffi_cif* cif,
202 void *retp,
203 ffi_raw *args,
204 _Jv_InterpMethodInvocation *inv)
206 inv->running = this;
207 inv->pc = bytecode ();
208 inv->sp = inv->stack_base ();
209 _Jv_word *locals = inv->local_base ();
211 /* Go straight at it! the ffi raw format matches the internal
212 stack representation exactly. At least, that's the idea.
214 memcpy ((void*) locals, (void*) args, args_raw_size);
216 next_segment:
218 jobject ex = NULL;
222 continue1 (inv);
224 catch (java::lang::Throwable *ex2)
226 ex = ex2;
229 if (ex == 0) // no exception...
231 /* define sp locally, so the POP? macros will pick it up */
232 _Jv_word *sp = inv->sp;
233 int rtype = cif->rtype->type;
235 if (rtype == FFI_TYPE_POINTER)
237 jobject r = POPA();
238 *(jobject*) retp = r;
239 return 0;
241 else if (rtype == FFI_TYPE_SINT32)
243 jint r = POPI();
244 *(jint*)retp = r;
245 return 0;
247 else if (rtype == FFI_TYPE_VOID)
249 return 0;
251 else switch (rtype)
253 case FFI_TYPE_FLOAT:
255 jfloat r = POPF();
256 *(jfloat*)retp = r;
257 return 0;
260 case FFI_TYPE_DOUBLE:
262 jdouble r = POPD();
263 *(jdouble*)retp = r;
264 return 0;
267 case FFI_TYPE_UINT8:
268 case FFI_TYPE_UINT16:
269 case FFI_TYPE_UINT32:
270 case FFI_TYPE_SINT8:
271 case FFI_TYPE_SINT16:
273 jint r = POPI();
274 *(jint*)retp = r;
275 return 0;
278 case FFI_TYPE_SINT64:
280 jlong r = POPL();
281 *(jlong*)retp = r;
282 return 0;
285 default:
286 throw_internal_error ("unknown return type");
290 /** handle an exception */
291 if ( find_exception (ex, inv) )
292 goto next_segment;
294 return ex;
297 bool _Jv_InterpMethod::find_exception (jobject ex,
298 _Jv_InterpMethodInvocation *inv)
300 int logical_pc = inv->pc - bytecode ();
301 _Jv_InterpException *exc = exceptions ();
302 jclass exc_class = ex->getClass ();
304 for (int i = 0; i < exc_count; i++)
306 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
308 jclass handler;
310 if (exc[i].handler_type != 0)
311 handler = (_Jv_ResolvePoolEntry (defining_class,
312 exc[i].handler_type)).clazz;
313 else
314 handler = NULL;
316 if (handler==NULL || handler->isAssignableFrom (exc_class))
318 inv->pc = bytecode () + exc[i].handler_pc;
319 inv->sp = inv->stack_base (); // reset stack
320 (inv->sp++)->o = ex; // push exception
321 return true;
325 return false;
328 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
329 void* ret,
330 ffi_raw * args,
331 void* __this)
333 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
335 // we do the alloca of the method invocation here, to allow the method
336 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
337 int storage_size = _this->max_stack+_this->max_locals;
338 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
339 alloca (sizeof (_Jv_InterpMethodInvocation)
340 + storage_size * sizeof (_Jv_word));
342 jobject ex = _this->run (cif, ret, args, inv);
343 if (ex != 0) _Jv_Throw (ex);
346 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
347 void* ret,
348 ffi_raw * args,
349 void* __this)
351 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
352 jobject rcv = (jobject)args[0].ptr;
354 int storage_size = _this->max_stack+_this->max_locals;
355 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
356 alloca (sizeof (_Jv_InterpMethodInvocation)
357 + storage_size * sizeof (_Jv_word));
359 _Jv_MonitorEnter (rcv);
360 jobject ex = _this->run (cif, ret, args, inv);
361 _Jv_MonitorExit (rcv);
363 if (ex != 0) _Jv_Throw (ex);
366 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
367 void* ret,
368 ffi_raw * args,
369 void* __this)
371 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
372 jclass sync = _this->defining_class;
374 int storage_size = _this->max_stack+_this->max_locals;
375 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
376 alloca (sizeof (_Jv_InterpMethodInvocation)
377 + storage_size * sizeof (_Jv_word));
379 _Jv_MonitorEnter (sync);
380 jobject ex = _this->run (cif, ret, args, inv);
381 _Jv_MonitorExit (sync);
383 if (ex != 0) _Jv_Throw (ex);
387 This proceeds execution, as designated in "inv". If an exception
388 happens, then it is simply thrown, and handled in Java. Thus, the pc
389 needs to be stored in the inv->pc at all times, so we can figure
390 out which handler (if any) to invoke.
392 One design issue, which I have not completely considered, is if it
393 should be possible to have interpreted classes linked in! Seldom used
394 (or non-critical) classes could reasonably be interpreted.
398 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
400 using namespace java::lang::reflect;
402 _Jv_word *sp = inv->sp;
403 unsigned char *pc = inv->pc;
404 _Jv_word *locals = inv->local_base ();
406 _Jv_word *pool_data = defining_class->constants.data;
408 /* these two are used in the invokeXXX instructions */
409 void (*fun)(...);
410 _Jv_ResolvedMethod* rmeth;
412 #define INSN_LABEL(op) &&insn_##op
413 #define GOTO_INSN(op) goto *(insn_target[op])
415 static const void *const insn_target[] =
417 INSN_LABEL(nop),
418 INSN_LABEL(aconst_null),
419 INSN_LABEL(iconst_m1),
420 INSN_LABEL(iconst_0),
421 INSN_LABEL(iconst_1),
422 INSN_LABEL(iconst_2),
423 INSN_LABEL(iconst_3),
424 INSN_LABEL(iconst_4),
425 INSN_LABEL(iconst_5),
426 INSN_LABEL(lconst_0),
427 INSN_LABEL(lconst_1),
428 INSN_LABEL(fconst_0),
429 INSN_LABEL(fconst_1),
430 INSN_LABEL(fconst_2),
431 INSN_LABEL(dconst_0),
432 INSN_LABEL(dconst_1),
433 INSN_LABEL(bipush),
434 INSN_LABEL(sipush),
435 INSN_LABEL(ldc),
436 INSN_LABEL(ldc_w),
437 INSN_LABEL(ldc2_w),
438 INSN_LABEL(iload),
439 INSN_LABEL(lload),
440 INSN_LABEL(fload),
441 INSN_LABEL(dload),
442 INSN_LABEL(aload),
443 INSN_LABEL(iload_0),
444 INSN_LABEL(iload_1),
445 INSN_LABEL(iload_2),
446 INSN_LABEL(iload_3),
447 INSN_LABEL(lload_0),
448 INSN_LABEL(lload_1),
449 INSN_LABEL(lload_2),
450 INSN_LABEL(lload_3),
451 INSN_LABEL(fload_0),
452 INSN_LABEL(fload_1),
453 INSN_LABEL(fload_2),
454 INSN_LABEL(fload_3),
455 INSN_LABEL(dload_0),
456 INSN_LABEL(dload_1),
457 INSN_LABEL(dload_2),
458 INSN_LABEL(dload_3),
459 INSN_LABEL(aload_0),
460 INSN_LABEL(aload_1),
461 INSN_LABEL(aload_2),
462 INSN_LABEL(aload_3),
463 INSN_LABEL(iaload),
464 INSN_LABEL(laload),
465 INSN_LABEL(faload),
466 INSN_LABEL(daload),
467 INSN_LABEL(aaload),
468 INSN_LABEL(baload),
469 INSN_LABEL(caload),
470 INSN_LABEL(saload),
471 INSN_LABEL(istore),
472 INSN_LABEL(lstore),
473 INSN_LABEL(fstore),
474 INSN_LABEL(dstore),
475 INSN_LABEL(astore),
476 INSN_LABEL(istore_0),
477 INSN_LABEL(istore_1),
478 INSN_LABEL(istore_2),
479 INSN_LABEL(istore_3),
480 INSN_LABEL(lstore_0),
481 INSN_LABEL(lstore_1),
482 INSN_LABEL(lstore_2),
483 INSN_LABEL(lstore_3),
484 INSN_LABEL(fstore_0),
485 INSN_LABEL(fstore_1),
486 INSN_LABEL(fstore_2),
487 INSN_LABEL(fstore_3),
488 INSN_LABEL(dstore_0),
489 INSN_LABEL(dstore_1),
490 INSN_LABEL(dstore_2),
491 INSN_LABEL(dstore_3),
492 INSN_LABEL(astore_0),
493 INSN_LABEL(astore_1),
494 INSN_LABEL(astore_2),
495 INSN_LABEL(astore_3),
496 INSN_LABEL(iastore),
497 INSN_LABEL(lastore),
498 INSN_LABEL(fastore),
499 INSN_LABEL(dastore),
500 INSN_LABEL(aastore),
501 INSN_LABEL(bastore),
502 INSN_LABEL(castore),
503 INSN_LABEL(sastore),
504 INSN_LABEL(pop),
505 INSN_LABEL(pop2),
506 INSN_LABEL(dup),
507 INSN_LABEL(dup_x1),
508 INSN_LABEL(dup_x2),
509 INSN_LABEL(dup2),
510 INSN_LABEL(dup2_x1),
511 INSN_LABEL(dup2_x2),
512 INSN_LABEL(swap),
513 INSN_LABEL(iadd),
514 INSN_LABEL(ladd),
515 INSN_LABEL(fadd),
516 INSN_LABEL(dadd),
517 INSN_LABEL(isub),
518 INSN_LABEL(lsub),
519 INSN_LABEL(fsub),
520 INSN_LABEL(dsub),
521 INSN_LABEL(imul),
522 INSN_LABEL(lmul),
523 INSN_LABEL(fmul),
524 INSN_LABEL(dmul),
525 INSN_LABEL(idiv),
526 INSN_LABEL(ldiv),
527 INSN_LABEL(fdiv),
528 INSN_LABEL(ddiv),
529 INSN_LABEL(irem),
530 INSN_LABEL(lrem),
531 INSN_LABEL(frem),
532 INSN_LABEL(drem),
533 INSN_LABEL(ineg),
534 INSN_LABEL(lneg),
535 INSN_LABEL(fneg),
536 INSN_LABEL(dneg),
537 INSN_LABEL(ishl),
538 INSN_LABEL(lshl),
539 INSN_LABEL(ishr),
540 INSN_LABEL(lshr),
541 INSN_LABEL(iushr),
542 INSN_LABEL(lushr),
543 INSN_LABEL(iand),
544 INSN_LABEL(land),
545 INSN_LABEL(ior),
546 INSN_LABEL(lor),
547 INSN_LABEL(ixor),
548 INSN_LABEL(lxor),
549 INSN_LABEL(iinc),
550 INSN_LABEL(i2l),
551 INSN_LABEL(i2f),
552 INSN_LABEL(i2d),
553 INSN_LABEL(l2i),
554 INSN_LABEL(l2f),
555 INSN_LABEL(l2d),
556 INSN_LABEL(f2i),
557 INSN_LABEL(f2l),
558 INSN_LABEL(f2d),
559 INSN_LABEL(d2i),
560 INSN_LABEL(d2l),
561 INSN_LABEL(d2f),
562 INSN_LABEL(i2b),
563 INSN_LABEL(i2c),
564 INSN_LABEL(i2s),
565 INSN_LABEL(lcmp),
566 INSN_LABEL(fcmpl),
567 INSN_LABEL(fcmpg),
568 INSN_LABEL(dcmpl),
569 INSN_LABEL(dcmpg),
570 INSN_LABEL(ifeq),
571 INSN_LABEL(ifne),
572 INSN_LABEL(iflt),
573 INSN_LABEL(ifge),
574 INSN_LABEL(ifgt),
575 INSN_LABEL(ifle),
576 INSN_LABEL(if_icmpeq),
577 INSN_LABEL(if_icmpne),
578 INSN_LABEL(if_icmplt),
579 INSN_LABEL(if_icmpge),
580 INSN_LABEL(if_icmpgt),
581 INSN_LABEL(if_icmple),
582 INSN_LABEL(if_acmpeq),
583 INSN_LABEL(if_acmpne),
584 INSN_LABEL(goto),
585 INSN_LABEL(jsr),
586 INSN_LABEL(ret),
587 INSN_LABEL(tableswitch),
588 INSN_LABEL(lookupswitch),
589 INSN_LABEL(ireturn),
590 INSN_LABEL(lreturn),
591 INSN_LABEL(freturn),
592 INSN_LABEL(dreturn),
593 INSN_LABEL(areturn),
594 INSN_LABEL(return),
595 INSN_LABEL(getstatic),
596 INSN_LABEL(putstatic),
597 INSN_LABEL(getfield),
598 INSN_LABEL(putfield),
599 INSN_LABEL(invokevirtual),
600 INSN_LABEL(invokespecial),
601 INSN_LABEL(invokestatic),
602 INSN_LABEL(invokeinterface),
603 0, /* op_xxxunusedxxx1, */
604 INSN_LABEL(new),
605 INSN_LABEL(newarray),
606 INSN_LABEL(anewarray),
607 INSN_LABEL(arraylength),
608 INSN_LABEL(athrow),
609 INSN_LABEL(checkcast),
610 INSN_LABEL(instanceof),
611 INSN_LABEL(monitorenter),
612 INSN_LABEL(monitorexit),
613 INSN_LABEL(wide),
614 INSN_LABEL(multianewarray),
615 INSN_LABEL(ifnull),
616 INSN_LABEL(ifnonnull),
617 INSN_LABEL(goto_w),
618 INSN_LABEL(jsr_w),
621 #define SAVE_PC inv->pc = pc-1
623 /* If the macro INLINE_SWITCH is not defined, then the main loop
624 operates as one big (normal) switch statement. If it is defined,
625 then the case selection is performed `inline' in the end of the
626 code for each case. The latter saves a native branch instruction
627 for each java-instruction, but expands the code size somewhat.
629 NOTE: On i386 defining INLINE_SWITCH improves over all
630 performance approximately seven percent, but it may be different
631 for other machines. At some point, this may be made into a proper
632 configuration parameter. */
634 #define INLINE_SWITCH
636 #ifdef INLINE_SWITCH
638 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
641 NEXT_INSN;
642 #else
644 #define NEXT_INSN goto next_insn
646 next_insn:
647 GOTO_INSN (*pc++);
649 #endif
651 /* The first few instructions here are ordered according to their
652 frequency, in the hope that this will improve code locality a
653 little. */
655 insn_aload_0: // 0x2a
656 LOADA(0);
657 NEXT_INSN;
659 insn_iload: // 0x15
660 LOADI (get1u (pc++));
661 NEXT_INSN;
663 insn_iload_1: // 0x1b
664 LOADI (1);
665 NEXT_INSN;
667 insn_invokevirtual: // 0xb6
668 SAVE_PC;
670 int index = get2u (pc); pc += 2;
672 /* _Jv_ResolvePoolEntry returns immediately if the value already
673 * is resolved. If we want to clutter up the code here to gain
674 * a little performance, then we can check the corresponding bit
675 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
676 * don't think it is worth it. */
678 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
680 sp -= rmeth->stack_item_count;
681 NULLCHECK(sp[0]);
683 if (rmeth->vtable_index == -1)
685 // final methods do not appear in the vtable,
686 // if it does not appear in the superclass.
687 fun = (void (*) (...)) rmeth->method->ncode;
689 else
691 jobject rcv = sp[0].o;
692 _Jv_VTable *table = *(_Jv_VTable**)rcv;
693 fun = (void (*) (...))table->method[rmeth->vtable_index];
696 goto perform_invoke;
698 perform_invoke:
700 /* here goes the magic again... */
701 ffi_cif *cif = &rmeth->cif;
702 ffi_raw *raw = (ffi_raw*) sp;
704 jdouble rvalue;
706 #if FFI_NATIVE_RAW_API
707 /* We assume that this is only implemented if it's correct */
708 /* to use it here. On a 64 bit machine, it never is. */
709 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
710 #else
711 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
712 #endif
714 int rtype = cif->rtype->type;
716 /* the likelyhood of object, int, or void return is very high,
717 * so those are checked before the switch */
718 if (rtype == FFI_TYPE_POINTER)
720 PUSHA (*(jobject*)&rvalue);
722 else if (rtype == FFI_TYPE_SINT32)
724 PUSHI (*(jint*)&rvalue);
726 else if (rtype == FFI_TYPE_VOID)
728 /* skip */
730 else switch (rtype)
732 case FFI_TYPE_SINT8:
734 jbyte value = (*(jint*)&rvalue) & 0xff;
735 PUSHI (value);
737 break;
739 case FFI_TYPE_SINT16:
741 jshort value = (*(jint*)&rvalue) & 0xffff;
742 PUSHI (value);
744 break;
746 case FFI_TYPE_UINT16:
748 jint value = (*(jint*)&rvalue) & 0xffff;
749 PUSHI (value);
751 break;
753 case FFI_TYPE_FLOAT:
754 PUSHF (*(jfloat*)&rvalue);
755 break;
757 case FFI_TYPE_DOUBLE:
758 PUSHD (rvalue);
759 break;
761 case FFI_TYPE_SINT64:
762 PUSHL (*(jlong*)&rvalue);
763 break;
765 default:
766 throw_internal_error ("unknown return type in invokeXXX");
770 NEXT_INSN;
773 insn_nop:
774 NEXT_INSN;
776 insn_aconst_null:
777 PUSHA (NULL);
778 NEXT_INSN;
780 insn_iconst_m1:
781 PUSHI (-1);
782 NEXT_INSN;
784 insn_iconst_0:
785 PUSHI (0);
786 NEXT_INSN;
788 insn_iconst_1:
789 PUSHI (1);
790 NEXT_INSN;
792 insn_iconst_2:
793 PUSHI (2);
794 NEXT_INSN;
796 insn_iconst_3:
797 PUSHI (3);
798 NEXT_INSN;
800 insn_iconst_4:
801 PUSHI (4);
802 NEXT_INSN;
804 insn_iconst_5:
805 PUSHI (5);
806 NEXT_INSN;
808 insn_lconst_0:
809 PUSHL (0);
810 NEXT_INSN;
812 insn_lconst_1:
813 PUSHL (1);
814 NEXT_INSN;
816 insn_fconst_0:
817 PUSHF (0);
818 NEXT_INSN;
820 insn_fconst_1:
821 PUSHF (1);
822 NEXT_INSN;
824 insn_fconst_2:
825 PUSHF (2);
826 NEXT_INSN;
828 insn_dconst_0:
829 PUSHD (0);
830 NEXT_INSN;
832 insn_dconst_1:
833 PUSHD (1);
834 NEXT_INSN;
836 insn_bipush:
837 PUSHI (get1s(pc++));
838 NEXT_INSN;
840 insn_sipush:
841 PUSHI (get2s(pc)); pc += 2;
842 NEXT_INSN;
844 insn_ldc:
846 int index = get1u (pc++);
847 PUSHA(pool_data[index].o);
849 NEXT_INSN;
851 insn_ldc_w:
853 int index = get2u (pc); pc += 2;
854 PUSHA(pool_data[index].o);
856 NEXT_INSN;
858 insn_ldc2_w:
860 int index = get2u (pc); pc += 2;
861 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
862 sp += 2;
864 NEXT_INSN;
866 insn_lload:
867 LOADL (get1u (pc++));
868 NEXT_INSN;
870 insn_fload:
871 LOADF (get1u (pc++));
872 NEXT_INSN;
874 insn_dload:
875 LOADD (get1u (pc++));
876 NEXT_INSN;
878 insn_aload:
879 LOADA (get1u (pc++));
880 NEXT_INSN;
882 insn_iload_0:
883 LOADI (0);
884 NEXT_INSN;
886 insn_iload_2:
887 LOADI (2);
888 NEXT_INSN;
890 insn_iload_3:
891 LOADI (3);
892 NEXT_INSN;
894 insn_lload_0:
895 LOADL (0);
896 NEXT_INSN;
898 insn_lload_1:
899 LOADL (1);
900 NEXT_INSN;
902 insn_lload_2:
903 LOADL (2);
904 NEXT_INSN;
906 insn_lload_3:
907 LOADL (3);
908 NEXT_INSN;
910 insn_fload_0:
911 LOADF (0);
912 NEXT_INSN;
914 insn_fload_1:
915 LOADF (1);
916 NEXT_INSN;
918 insn_fload_2:
919 LOADF (2);
920 NEXT_INSN;
922 insn_fload_3:
923 LOADF (3);
924 NEXT_INSN;
926 insn_dload_0:
927 LOADD (0);
928 NEXT_INSN;
930 insn_dload_1:
931 LOADD (1);
932 NEXT_INSN;
934 insn_dload_2:
935 LOADD (2);
936 NEXT_INSN;
938 insn_dload_3:
939 LOADD (3);
940 NEXT_INSN;
942 insn_aload_1:
943 LOADA(1);
944 NEXT_INSN;
946 insn_aload_2:
947 LOADA(2);
948 NEXT_INSN;
950 insn_aload_3:
951 LOADA(3);
952 NEXT_INSN;
954 insn_iaload:
955 SAVE_PC;
957 jint index = POPI();
958 jintArray arr = (jintArray) POPA();
959 NULLCHECK (arr);
960 if (index < 0 || index >= arr->length)
962 _Jv_ThrowBadArrayIndex (index);
964 PUSHI( elements(arr)[index] );
966 NEXT_INSN;
968 insn_laload:
969 SAVE_PC;
971 jint index = POPI();
972 jlongArray arr = (jlongArray) POPA();
973 NULLCHECK (arr);
974 if (index < 0 || index >= arr->length)
976 _Jv_ThrowBadArrayIndex (index);
978 PUSHL( elements(arr)[index] );
980 NEXT_INSN;
982 insn_faload:
983 SAVE_PC;
985 jint index = POPI();
986 jfloatArray arr = (jfloatArray) POPA();
987 NULLCHECK (arr);
988 if (index < 0 || index >= arr->length)
990 _Jv_ThrowBadArrayIndex (index);
992 PUSHF( elements(arr)[index] );
994 NEXT_INSN;
996 insn_daload:
997 SAVE_PC;
999 jint index = POPI();
1000 jdoubleArray arr = (jdoubleArray) POPA();
1001 NULLCHECK (arr);
1002 if (index < 0 || index >= arr->length)
1004 _Jv_ThrowBadArrayIndex (index);
1006 PUSHD( elements(arr)[index] );
1008 NEXT_INSN;
1010 insn_aaload:
1011 SAVE_PC;
1013 jint index = POPI();
1014 jobjectArray arr = (jobjectArray) POPA();
1015 NULLCHECK (arr);
1016 if (index < 0 || index >= arr->length)
1018 _Jv_ThrowBadArrayIndex (index);
1020 PUSHA( elements(arr)[index] );
1022 NEXT_INSN;
1024 insn_baload:
1025 SAVE_PC;
1027 jint index = POPI();
1028 jbyteArray arr = (jbyteArray) POPA();
1029 NULLCHECK (arr);
1030 if (index < 0 || index >= arr->length)
1032 _Jv_ThrowBadArrayIndex (index);
1034 PUSHI( elements(arr)[index] );
1036 NEXT_INSN;
1038 insn_caload:
1039 SAVE_PC;
1041 jint index = POPI();
1042 jcharArray arr = (jcharArray) POPA();
1043 NULLCHECK (arr);
1044 if (index < 0 || index >= arr->length)
1046 _Jv_ThrowBadArrayIndex (index);
1048 PUSHI( elements(arr)[index] );
1050 NEXT_INSN;
1052 insn_saload:
1053 SAVE_PC;
1055 jint index = POPI();
1056 jshortArray arr = (jshortArray) POPA();
1057 NULLCHECK (arr);
1058 if (index < 0 || index >= arr->length)
1060 _Jv_ThrowBadArrayIndex (index);
1062 PUSHI( elements(arr)[index] );
1064 NEXT_INSN;
1066 insn_istore:
1067 STOREI (get1u (pc++));
1068 NEXT_INSN;
1070 insn_lstore:
1071 STOREL (get1u (pc++));
1072 NEXT_INSN;
1074 insn_fstore:
1075 STOREF (get1u (pc++));
1076 NEXT_INSN;
1078 insn_dstore:
1079 STORED (get1u (pc++));
1080 NEXT_INSN;
1082 insn_astore:
1083 STOREA (get1u (pc++));
1084 NEXT_INSN;
1086 insn_istore_0:
1087 STOREI (0);
1088 NEXT_INSN;
1090 insn_istore_1:
1091 STOREI (1);
1092 NEXT_INSN;
1094 insn_istore_2:
1095 STOREI (2);
1096 NEXT_INSN;
1098 insn_istore_3:
1099 STOREI (3);
1100 NEXT_INSN;
1102 insn_lstore_0:
1103 STOREL (0);
1104 NEXT_INSN;
1106 insn_lstore_1:
1107 STOREL (1);
1108 NEXT_INSN;
1110 insn_lstore_2:
1111 STOREL (2);
1112 NEXT_INSN;
1114 insn_lstore_3:
1115 STOREL (3);
1116 NEXT_INSN;
1118 insn_fstore_0:
1119 STOREF (0);
1120 NEXT_INSN;
1122 insn_fstore_1:
1123 STOREF (1);
1124 NEXT_INSN;
1126 insn_fstore_2:
1127 STOREF (2);
1128 NEXT_INSN;
1130 insn_fstore_3:
1131 STOREF (3);
1132 NEXT_INSN;
1134 insn_dstore_0:
1135 STORED (0);
1136 NEXT_INSN;
1138 insn_dstore_1:
1139 STORED (1);
1140 NEXT_INSN;
1142 insn_dstore_2:
1143 STORED (2);
1144 NEXT_INSN;
1146 insn_dstore_3:
1147 STORED (3);
1148 NEXT_INSN;
1150 insn_astore_0:
1151 STOREA(0);
1152 NEXT_INSN;
1154 insn_astore_1:
1155 STOREA(1);
1156 NEXT_INSN;
1158 insn_astore_2:
1159 STOREA(2);
1160 NEXT_INSN;
1162 insn_astore_3:
1163 STOREA(3);
1164 NEXT_INSN;
1166 insn_iastore:
1167 SAVE_PC;
1169 jint value = POPI();
1170 jint index = POPI();
1171 jintArray arr = (jintArray) POPA();
1172 NULLCHECK (arr);
1173 if (index < 0 || index >= arr->length)
1175 _Jv_ThrowBadArrayIndex (index);
1177 elements(arr)[index] = value;
1179 NEXT_INSN;
1181 insn_lastore:
1182 SAVE_PC;
1184 jlong value = POPL();
1185 jint index = POPI();
1186 jlongArray arr = (jlongArray) POPA();
1187 NULLCHECK (arr);
1188 if (index < 0 || index >= arr->length)
1190 _Jv_ThrowBadArrayIndex (index);
1192 elements(arr)[index] = value;
1194 NEXT_INSN;
1196 insn_fastore:
1197 SAVE_PC;
1199 jfloat value = POPF();
1200 jint index = POPI();
1201 jfloatArray arr = (jfloatArray) POPA();
1202 NULLCHECK (arr);
1203 if (index < 0 || index >= arr->length)
1205 _Jv_ThrowBadArrayIndex (index);
1207 elements(arr)[index] = value;
1209 NEXT_INSN;
1211 insn_dastore:
1212 SAVE_PC;
1214 jdouble value = POPD();
1215 jint index = POPI();
1216 jdoubleArray arr = (jdoubleArray) POPA();
1217 NULLCHECK (arr);
1218 if (index < 0 || index >= arr->length)
1220 _Jv_ThrowBadArrayIndex (index);
1222 elements(arr)[index] = value;
1224 NEXT_INSN;
1226 insn_aastore:
1227 SAVE_PC;
1229 jobject value = POPA();
1230 jint index = POPI();
1231 jobjectArray arr = (jobjectArray) POPA();
1232 NULLCHECK (arr);
1233 if (index < 0 || index >= arr->length)
1235 _Jv_ThrowBadArrayIndex (index);
1237 _Jv_CheckArrayStore (arr, value);
1238 elements(arr)[index] = value;
1240 NEXT_INSN;
1242 insn_bastore:
1243 SAVE_PC;
1245 jbyte value = (jbyte) POPI();
1246 jint index = POPI();
1247 jbyteArray arr = (jbyteArray) POPA();
1248 NULLCHECK (arr);
1249 if (index < 0 || index >= arr->length)
1251 _Jv_ThrowBadArrayIndex (index);
1253 elements(arr)[index] = value;
1255 NEXT_INSN;
1257 insn_castore:
1258 SAVE_PC;
1260 jchar value = (jchar) POPI();
1261 jint index = POPI();
1262 jcharArray arr = (jcharArray) POPA();
1263 NULLCHECK (arr);
1264 if (index < 0 || index >= arr->length)
1266 _Jv_ThrowBadArrayIndex (index);
1268 elements(arr)[index] = value;
1270 NEXT_INSN;
1272 insn_sastore:
1273 SAVE_PC;
1275 jshort value = (jshort) POPI();
1276 jint index = POPI();
1277 jshortArray arr = (jshortArray) POPA();
1278 NULLCHECK (arr);
1279 if (index < 0 || index >= arr->length)
1281 _Jv_ThrowBadArrayIndex (index);
1283 elements(arr)[index] = value;
1285 NEXT_INSN;
1287 insn_pop:
1288 sp -= 1;
1289 NEXT_INSN;
1291 insn_pop2:
1292 sp -= 2;
1293 NEXT_INSN;
1295 insn_dup:
1296 sp[0] = sp[-1];
1297 sp += 1;
1298 NEXT_INSN;
1300 insn_dup_x1:
1301 dupx (sp, 1, 1); sp+=1;
1302 NEXT_INSN;
1304 insn_dup_x2:
1305 dupx (sp, 1, 2); sp+=1;
1306 NEXT_INSN;
1308 insn_dup2:
1309 sp[0] = sp[-2];
1310 sp[1] = sp[-1];
1311 sp += 2;
1312 NEXT_INSN;
1314 insn_dup2_x1:
1315 dupx (sp, 2, 1); sp+=2;
1316 NEXT_INSN;
1318 insn_dup2_x2:
1319 dupx (sp, 2, 2); sp+=2;
1320 NEXT_INSN;
1322 insn_swap:
1324 jobject tmp1 = POPA();
1325 jobject tmp2 = POPA();
1326 PUSHA (tmp1);
1327 PUSHA (tmp2);
1329 NEXT_INSN;
1331 insn_iadd:
1332 BINOPI(+);
1333 NEXT_INSN;
1335 insn_ladd:
1336 BINOPL(+);
1337 NEXT_INSN;
1339 insn_fadd:
1340 BINOPF(+);
1341 NEXT_INSN;
1343 insn_dadd:
1344 BINOPD(+);
1345 NEXT_INSN;
1347 insn_isub:
1348 BINOPI(-);
1349 NEXT_INSN;
1351 insn_lsub:
1352 BINOPL(-);
1353 NEXT_INSN;
1355 insn_fsub:
1356 BINOPF(-);
1357 NEXT_INSN;
1359 insn_dsub:
1360 BINOPD(-);
1361 NEXT_INSN;
1363 insn_imul:
1364 BINOPI(*);
1365 NEXT_INSN;
1367 insn_lmul:
1368 BINOPL(*);
1369 NEXT_INSN;
1371 insn_fmul:
1372 BINOPF(*);
1373 NEXT_INSN;
1375 insn_dmul:
1376 BINOPD(*);
1377 NEXT_INSN;
1379 insn_idiv:
1380 SAVE_PC;
1382 jint value2 = POPI();
1383 jint value1 = POPI();
1384 jint res = _Jv_divI (value1, value2);
1385 PUSHI (res);
1387 NEXT_INSN;
1389 insn_ldiv:
1390 SAVE_PC;
1392 jlong value2 = POPL();
1393 jlong value1 = POPL();
1394 jlong res = _Jv_divJ (value1, value2);
1395 PUSHL (res);
1397 NEXT_INSN;
1399 insn_fdiv:
1400 SAVE_PC;
1402 jfloat value2 = POPF();
1403 jfloat value1 = POPF();
1404 jfloat res = value1 / value2;
1405 PUSHF (res);
1407 NEXT_INSN;
1409 insn_ddiv:
1410 SAVE_PC;
1412 jdouble value2 = POPD();
1413 jdouble value1 = POPD();
1414 jdouble res = value1 / value2;
1415 PUSHD (res);
1417 NEXT_INSN;
1419 insn_irem:
1420 SAVE_PC;
1422 jint value2 = POPI();
1423 jint value1 = POPI();
1424 jint res = _Jv_remI (value1, value2);
1425 PUSHI (res);
1427 NEXT_INSN;
1429 insn_lrem:
1430 SAVE_PC;
1432 jlong value2 = POPL();
1433 jlong value1 = POPL();
1434 jlong res = _Jv_remJ (value1, value2);
1435 PUSHL (res);
1437 NEXT_INSN;
1439 insn_frem:
1440 SAVE_PC;
1442 jfloat value2 = POPF();
1443 jfloat value1 = POPF();
1444 jfloat res = __ieee754_fmod (value1, value2);
1445 PUSHF (res);
1447 NEXT_INSN;
1449 insn_drem:
1450 SAVE_PC;
1452 jdouble value2 = POPD();
1453 jdouble value1 = POPD();
1454 jdouble res = __ieee754_fmod (value1, value2);
1455 PUSHD (res);
1457 NEXT_INSN;
1459 insn_ineg:
1461 jint value = POPI();
1462 PUSHI (value * -1);
1464 NEXT_INSN;
1466 insn_lneg:
1468 jlong value = POPL();
1469 PUSHL (value * -1);
1471 NEXT_INSN;
1473 insn_fneg:
1475 jfloat value = POPF();
1476 PUSHF (value * -1);
1478 NEXT_INSN;
1480 insn_dneg:
1482 jdouble value = POPD();
1483 PUSHD (value * -1);
1485 NEXT_INSN;
1487 insn_ishl:
1489 jint shift = (POPI() & 0x1f);
1490 jint value = POPI();
1491 PUSHI (value << shift);
1493 NEXT_INSN;
1495 insn_lshl:
1497 jint shift = (POPI() & 0x3f);
1498 jlong value = POPL();
1499 PUSHL (value << shift);
1501 NEXT_INSN;
1503 insn_ishr:
1505 jint shift = (POPI() & 0x1f);
1506 jint value = POPI();
1507 PUSHI (value >> shift);
1509 NEXT_INSN;
1511 insn_lshr:
1513 jint shift = (POPI() & 0x3f);
1514 jlong value = POPL();
1515 PUSHL (value >> shift);
1517 NEXT_INSN;
1519 insn_iushr:
1521 jint shift = (POPI() & 0x1f);
1522 unsigned long value = POPI();
1523 PUSHI ((jint) (value >> shift));
1525 NEXT_INSN;
1527 insn_lushr:
1529 jint shift = (POPI() & 0x3f);
1530 UINT64 value = (UINT64) POPL();
1531 PUSHL ((value >> shift));
1533 NEXT_INSN;
1535 insn_iand:
1536 BINOPI (&);
1537 NEXT_INSN;
1539 insn_land:
1540 BINOPL (&);
1541 NEXT_INSN;
1543 insn_ior:
1544 BINOPI (|);
1545 NEXT_INSN;
1547 insn_lor:
1548 BINOPL (|);
1549 NEXT_INSN;
1551 insn_ixor:
1552 BINOPI (^);
1553 NEXT_INSN;
1555 insn_lxor:
1556 BINOPL (^);
1557 NEXT_INSN;
1559 insn_iinc:
1561 jint index = get1u (pc++);
1562 jint amount = get1s (pc++);
1563 locals[index].i += amount;
1565 NEXT_INSN;
1567 insn_i2l:
1568 {jlong value = POPI(); PUSHL (value);}
1569 NEXT_INSN;
1571 insn_i2f:
1572 {jfloat value = POPI(); PUSHF (value);}
1573 NEXT_INSN;
1575 insn_i2d:
1576 {jdouble value = POPI(); PUSHD (value);}
1577 NEXT_INSN;
1579 insn_l2i:
1580 {jint value = POPL(); PUSHI (value);}
1581 NEXT_INSN;
1583 insn_l2f:
1584 {jfloat value = POPL(); PUSHF (value);}
1585 NEXT_INSN;
1587 insn_l2d:
1588 {jdouble value = POPL(); PUSHD (value);}
1589 NEXT_INSN;
1591 insn_f2i:
1592 { jint value = (jint)POPF (); PUSHI(value); }
1593 NEXT_INSN;
1595 insn_f2l:
1596 { jlong value = (jlong)POPF (); PUSHL(value); }
1597 NEXT_INSN;
1599 insn_f2d:
1600 { jdouble value = POPF (); PUSHD(value); }
1601 NEXT_INSN;
1603 insn_d2i:
1604 { jint value = (jint)POPD (); PUSHI(value); }
1605 NEXT_INSN;
1607 insn_d2l:
1608 { jlong value = (jlong)POPD (); PUSHL(value); }
1609 NEXT_INSN;
1611 insn_d2f:
1612 { jfloat value = POPD (); PUSHF(value); }
1613 NEXT_INSN;
1615 insn_i2b:
1616 { jbyte value = POPI (); PUSHI(value); }
1617 NEXT_INSN;
1619 insn_i2c:
1620 { jchar value = POPI (); PUSHI(value); }
1621 NEXT_INSN;
1623 insn_i2s:
1624 { jshort value = POPI (); PUSHI(value); }
1625 NEXT_INSN;
1627 insn_lcmp:
1629 jlong value2 = POPL ();
1630 jlong value1 = POPL ();
1631 if (value1 > value2)
1632 { PUSHI (1); }
1633 else if (value1 == value2)
1634 { PUSHI (0); }
1635 else
1636 { PUSHI (-1); }
1638 NEXT_INSN;
1640 insn_fcmpl:
1641 insn_fcmpg:
1643 jfloat value2 = POPF ();
1644 jfloat value1 = POPF ();
1645 if (value1 > value2)
1646 PUSHI (1);
1647 else if (value1 == value2)
1648 PUSHI (0);
1649 else if (value1 < value2)
1650 PUSHI (-1);
1651 else if ((*(pc-1)) == op_fcmpg)
1652 PUSHI (1);
1653 else
1654 PUSHI (-1);
1656 NEXT_INSN;
1658 insn_dcmpl:
1659 insn_dcmpg:
1661 jdouble value2 = POPD ();
1662 jdouble value1 = POPD ();
1663 if (value1 > value2)
1664 PUSHI (1);
1665 else if (value1 == value2)
1666 PUSHI (0);
1667 else if (value1 < value2)
1668 PUSHI (-1);
1669 else if ((*(pc-1)) == op_dcmpg)
1670 PUSHI (1);
1671 else
1672 PUSHI (-1);
1674 NEXT_INSN;
1676 insn_ifeq:
1678 jint offset = get2s (pc);
1679 if (POPI() == 0)
1680 pc = pc-1+offset;
1681 else
1682 pc = pc+2;
1684 NEXT_INSN;
1686 insn_ifne:
1688 jint offset = get2s (pc);
1689 if (POPI() != 0)
1690 pc = pc-1+offset;
1691 else
1692 pc = pc+2;
1694 NEXT_INSN;
1696 insn_iflt:
1698 jint offset = get2s (pc);
1699 if (POPI() < 0)
1700 pc = pc-1+offset;
1701 else
1702 pc = pc+2;
1704 NEXT_INSN;
1706 insn_ifge:
1708 jint offset = get2s (pc);
1709 if (POPI() >= 0)
1710 pc = pc-1+offset;
1711 else
1712 pc = pc+2;
1714 NEXT_INSN;
1716 insn_ifgt:
1718 jint offset = get2s (pc);
1719 if (POPI() > 0)
1720 pc = pc-1+offset;
1721 else
1722 pc = pc+2;
1724 NEXT_INSN;
1726 insn_ifle:
1728 jint offset = get2s (pc);
1729 if (POPI() <= 0)
1730 pc = pc-1+offset;
1731 else
1732 pc = pc+2;
1734 NEXT_INSN;
1736 insn_if_icmpeq:
1738 jint offset = get2s (pc);
1739 jint value2 = POPI();
1740 jint value1 = POPI();
1741 if (value1 == value2)
1742 pc = pc-1+offset;
1743 else
1744 pc = pc+2;
1746 NEXT_INSN;
1748 insn_if_icmpne:
1750 jint offset = get2s (pc);
1751 jint value2 = POPI();
1752 jint value1 = POPI();
1753 if (value1 != value2)
1754 pc = pc-1+offset;
1755 else
1756 pc = pc+2;
1758 NEXT_INSN;
1760 insn_if_icmplt:
1762 jint offset = get2s (pc);
1763 jint value2 = POPI();
1764 jint value1 = POPI();
1765 if (value1 < value2)
1766 pc = pc-1+offset;
1767 else
1768 pc = pc+2;
1770 NEXT_INSN;
1772 insn_if_icmpge:
1774 jint offset = get2s (pc);
1775 jint value2 = POPI();
1776 jint value1 = POPI();
1777 if (value1 >= value2)
1778 pc = pc-1+offset;
1779 else
1780 pc = pc+2;
1782 NEXT_INSN;
1784 insn_if_icmpgt:
1786 jint offset = get2s (pc);
1787 jint value2 = POPI();
1788 jint value1 = POPI();
1789 if (value1 > value2)
1790 pc = pc-1+offset;
1791 else
1792 pc = pc+2;
1794 NEXT_INSN;
1796 insn_if_icmple:
1798 jint offset = get2s (pc);
1799 jint value2 = POPI();
1800 jint value1 = POPI();
1801 if (value1 <= value2)
1802 pc = pc-1+offset;
1803 else
1804 pc = pc+2;
1806 NEXT_INSN;
1808 insn_if_acmpeq:
1810 jint offset = get2s (pc);
1811 jobject value2 = POPA();
1812 jobject value1 = POPA();
1813 if (value1 == value2)
1814 pc = pc-1+offset;
1815 else
1816 pc = pc+2;
1818 NEXT_INSN;
1820 insn_if_acmpne:
1822 jint offset = get2s (pc);
1823 jobject value2 = POPA();
1824 jobject value1 = POPA();
1825 if (value1 != value2)
1826 pc = pc-1+offset;
1827 else
1828 pc = pc+2;
1830 NEXT_INSN;
1832 insn_goto:
1834 jint offset = get2s (pc);
1835 pc = pc-1+offset;
1837 NEXT_INSN;
1839 insn_jsr:
1841 unsigned char *base_pc = pc-1;
1842 jint offset = get2s (pc); pc += 2;
1843 PUSHA ((jobject)pc);
1844 pc = base_pc+offset;
1846 NEXT_INSN;
1848 insn_ret:
1850 jint index = get1u (pc);
1851 pc = (unsigned char*) PEEKA (index);
1853 NEXT_INSN;
1855 insn_tableswitch:
1857 unsigned char *base_pc = pc-1;
1858 int index = POPI();
1860 unsigned char* base = bytecode ();
1861 while ((pc-base) % 4 != 0)
1862 pc++;
1864 jint def = get4 (pc);
1865 jint low = get4 (pc+4);
1866 jint high = get4 (pc+8);
1868 if (index < low || index > high)
1869 pc = base_pc + def;
1870 else
1871 pc = base_pc + get4 (pc+4*(index-low+3));
1873 NEXT_INSN;
1875 insn_lookupswitch:
1877 unsigned char *base_pc = pc-1;
1878 int index = POPI();
1880 unsigned char* base = bytecode ();
1881 while ((pc-base) % 4 != 0)
1882 pc++;
1884 jint def = get4 (pc);
1885 jint npairs = get4 (pc+4);
1887 int max = npairs-1;
1888 int min = 0;
1890 // simple binary search...
1891 while (min < max)
1893 int half = (min+max)/2;
1894 int match = get4 (pc+ 4*(2 + 2*half));
1896 if (index == match)
1897 min = max = half;
1899 else if (index < match)
1900 max = half-1;
1902 else
1903 min = half+1;
1906 if (index == get4 (pc+ 4*(2 + 2*min)))
1907 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1908 else
1909 pc = base_pc + def;
1911 NEXT_INSN;
1913 /* on return, just save the sp and return to caller */
1914 insn_ireturn:
1915 insn_lreturn:
1916 insn_freturn:
1917 insn_dreturn:
1918 insn_areturn:
1919 insn_return:
1920 inv->sp = sp;
1921 return;
1923 insn_getstatic:
1924 SAVE_PC;
1926 jint fieldref_index = get2u (pc); pc += 2;
1927 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1928 _Jv_Field *field = pool_data[fieldref_index].field;
1930 if ((field->flags & Modifier::STATIC) == 0)
1931 throw_incompatible_class_change_error
1932 (JvNewStringLatin1 ("field no longer static"));
1934 jclass type = field->type;
1936 if (type->isPrimitive ())
1938 switch (type->size_in_bytes)
1940 case 1:
1941 PUSHI (*(jbyte*) (field->u.addr));
1943 case 2:
1944 if (type == JvPrimClass (char))
1945 PUSHI(*(jchar*) (field->u.addr));
1946 else
1947 PUSHI(*(jshort*) (field->u.addr));
1948 break;
1950 case 4:
1951 PUSHI(*(jint*) (field->u.addr));
1952 break;
1954 case 8:
1955 PUSHL(*(jlong*) (field->u.addr));
1956 break;
1959 else
1961 PUSHA(*(jobject*) (field->u.addr));
1964 NEXT_INSN;
1966 insn_getfield:
1967 SAVE_PC;
1969 jint fieldref_index = get2u (pc); pc += 2;
1970 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1971 _Jv_Field *field = pool_data[fieldref_index].field;
1973 if ((field->flags & Modifier::STATIC) != 0)
1974 throw_incompatible_class_change_error
1975 (JvNewStringLatin1 ("field is static"));
1977 jclass type = field->type;
1978 jint field_offset = field->u.boffset;
1979 if (field_offset > 0xffff)
1980 JvThrow (new java::lang::VirtualMachineError);
1982 jobject obj = POPA();
1983 NULLCHECK(obj);
1985 if (type->isPrimitive ())
1987 switch (type->size_in_bytes)
1989 case 1:
1990 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1991 break;
1993 case 2:
1994 if (type == JvPrimClass (char))
1995 PUSHI (*(jchar*) ((char*)obj + field_offset));
1996 else
1997 PUSHI (*(jshort*) ((char*)obj + field_offset));
1998 break;
2000 case 4:
2001 PUSHI (*(jint*) ((char*)obj + field_offset));
2002 break;
2004 case 8:
2005 PUSHL(*(jlong*) ((char*)obj + field_offset));
2006 break;
2009 else
2011 PUSHA(*(jobject*) ((char*)obj + field_offset));
2014 NEXT_INSN;
2016 insn_putstatic:
2017 SAVE_PC;
2019 jint fieldref_index = get2u (pc); pc += 2;
2020 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2021 _Jv_Field *field = pool_data[fieldref_index].field;
2023 jclass type = field->type;
2025 // ResolvePoolEntry cannot check this
2026 if ((field->flags & Modifier::STATIC) == 0)
2027 throw_incompatible_class_change_error
2028 (JvNewStringLatin1 ("field no longer static"));
2030 if (type->isPrimitive ())
2032 switch (type->size_in_bytes)
2034 case 1:
2036 jint value = POPI();
2037 *(jbyte*) (field->u.addr) = value;
2038 break;
2041 case 2:
2043 jint value = POPI();
2044 *(jchar*) (field->u.addr) = value;
2045 break;
2048 case 4:
2050 jint value = POPI();
2051 *(jint*) (field->u.addr) = value;
2052 break;
2055 case 8:
2057 jlong value = POPL();
2058 *(jlong*) (field->u.addr) = value;
2059 break;
2063 else
2065 jobject value = POPA();
2066 *(jobject*) (field->u.addr) = value;
2069 NEXT_INSN;
2072 insn_putfield:
2073 SAVE_PC;
2075 jint fieldref_index = get2u (pc); pc += 2;
2076 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2077 _Jv_Field *field = pool_data[fieldref_index].field;
2079 jclass type = field->type;
2081 if ((field->flags & Modifier::STATIC) != 0)
2082 throw_incompatible_class_change_error
2083 (JvNewStringLatin1 ("field is static"));
2085 jint field_offset = field->u.boffset;
2086 if (field_offset > 0xffff)
2087 JvThrow (new java::lang::VirtualMachineError);
2089 if (type->isPrimitive ())
2091 switch (type->size_in_bytes)
2093 case 1:
2095 jint value = POPI();
2096 jobject obj = POPA();
2097 NULLCHECK(obj);
2098 *(jbyte*) ((char*)obj + field_offset) = value;
2099 break;
2102 case 2:
2104 jint value = POPI();
2105 jobject obj = POPA();
2106 NULLCHECK(obj);
2107 *(jchar*) ((char*)obj + field_offset) = value;
2108 break;
2111 case 4:
2113 jint value = POPI();
2114 jobject obj = POPA();
2115 NULLCHECK(obj);
2116 *(jint*) ((char*)obj + field_offset) = value;
2117 break;
2120 case 8:
2122 jlong value = POPL();
2123 jobject obj = POPA();
2124 NULLCHECK(obj);
2125 *(jlong*) ((char*)obj + field_offset) = value;
2126 break;
2130 else
2132 jobject value = POPA();
2133 jobject obj = POPA();
2134 NULLCHECK(obj);
2135 *(jobject*) ((char*)obj + field_offset) = value;
2138 NEXT_INSN;
2140 insn_invokespecial:
2141 SAVE_PC;
2143 int index = get2u (pc); pc += 2;
2145 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2147 sp -= rmeth->stack_item_count;
2149 NULLCHECK(sp[0]);
2151 fun = (void (*) (...))rmeth->method->ncode;
2153 goto perform_invoke;
2155 insn_invokestatic:
2156 SAVE_PC;
2158 int index = get2u (pc); pc += 2;
2160 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2162 sp -= rmeth->stack_item_count;
2164 _Jv_InitClass (rmeth->klass);
2165 fun = (void (*) (...))rmeth->method->ncode;
2167 goto perform_invoke;
2169 insn_invokeinterface:
2170 SAVE_PC;
2172 int index = get2u (pc); pc += 2;
2174 // invokeinterface has two unused bytes...
2175 pc += 2;
2177 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2179 sp -= rmeth->stack_item_count;
2180 NULLCHECK(sp[0]);
2182 jobject rcv = sp[0].o;
2184 fun = (void (*) (...))
2185 _Jv_LookupInterfaceMethod (rcv->getClass (),
2186 rmeth->method->name,
2187 rmeth->method->signature);
2189 goto perform_invoke;
2192 insn_new:
2193 SAVE_PC;
2195 int index = get2u (pc); pc += 2;
2196 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2197 _Jv_InitClass (klass);
2198 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2199 PUSHA (res);
2201 NEXT_INSN;
2203 insn_newarray:
2204 SAVE_PC;
2206 int atype = get1u (pc++);
2207 int size = POPI();
2208 jobject result = _Jv_NewArray (atype, size);
2209 PUSHA (result);
2211 NEXT_INSN;
2213 insn_anewarray:
2214 SAVE_PC;
2216 int index = get2u (pc); pc += 2;
2217 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2218 int size = POPI();
2219 _Jv_InitClass (klass);
2220 jobject result = _Jv_NewObjectArray (size, klass, 0);
2221 PUSHA (result);
2223 NEXT_INSN;
2225 insn_arraylength:
2226 SAVE_PC;
2228 __JArray *arr = (__JArray*)POPA();
2229 PUSHI (arr->length);
2231 NEXT_INSN;
2233 insn_athrow:
2234 SAVE_PC;
2236 jobject value = POPA();
2237 JvThrow (value);
2239 NEXT_INSN;
2241 insn_checkcast:
2242 SAVE_PC;
2244 jobject value = POPA();
2245 jint index = get2u (pc); pc += 2;
2246 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2248 if (value != NULL && ! to->isInstance (value))
2250 JvThrow (new java::lang::ClassCastException
2251 (to->getName()));
2254 PUSHA (value);
2256 NEXT_INSN;
2258 insn_instanceof:
2259 SAVE_PC;
2261 jobject value = POPA();
2262 jint index = get2u (pc); pc += 2;
2263 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2264 PUSHI (to->isInstance (value));
2266 NEXT_INSN;
2268 insn_monitorenter:
2269 SAVE_PC;
2271 jobject value = POPA();
2272 NULLCHECK(value);
2273 _Jv_MonitorEnter (value);
2275 NEXT_INSN;
2277 insn_monitorexit:
2278 SAVE_PC;
2280 jobject value = POPA();
2281 NULLCHECK(value);
2282 _Jv_MonitorExit (value);
2284 NEXT_INSN;
2286 insn_ifnull:
2288 unsigned char* base_pc = pc-1;
2289 jint offset = get2s (pc); pc += 2;
2290 jobject val = POPA();
2291 if (val == NULL)
2292 pc = base_pc+offset;
2294 NEXT_INSN;
2296 insn_ifnonnull:
2298 unsigned char* base_pc = pc-1;
2299 jint offset = get2s (pc); pc += 2;
2300 jobject val = POPA();
2301 if (val != NULL)
2302 pc = base_pc+offset;
2304 NEXT_INSN;
2306 insn_wide:
2307 SAVE_PC;
2309 jint the_mod_op = get1u (pc++);
2310 jint wide = get2u (pc); pc += 2;
2312 switch (the_mod_op)
2314 case op_istore:
2315 STOREI (wide);
2316 NEXT_INSN;
2318 case op_fstore:
2319 STOREF (wide);
2320 NEXT_INSN;
2322 case op_astore:
2323 STOREA (wide);
2324 NEXT_INSN;
2326 case op_lload:
2327 LOADL (wide);
2328 NEXT_INSN;
2330 case op_dload:
2331 LOADD (wide);
2332 NEXT_INSN;
2334 case op_iload:
2335 LOADI (wide);
2336 NEXT_INSN;
2338 case op_aload:
2339 LOADA (wide);
2340 NEXT_INSN;
2342 case op_lstore:
2343 STOREL (wide);
2344 NEXT_INSN;
2346 case op_dstore:
2347 STORED (wide);
2348 NEXT_INSN;
2350 case op_ret:
2351 pc = (unsigned char*) PEEKA (wide);
2352 NEXT_INSN;
2354 case op_iinc:
2356 jint amount = get2s (pc); pc += 2;
2357 jint value = PEEKI (wide);
2358 POKEI (wide, value+amount);
2360 NEXT_INSN;
2362 default:
2363 throw_internal_error ("illegal bytecode modified by wide");
2368 insn_multianewarray:
2369 SAVE_PC;
2371 int kind_index = get2u (pc); pc += 2;
2372 int dim = get1u (pc); pc += 1;
2374 jclass type
2375 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2376 _Jv_InitClass (type);
2377 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2379 for (int i = dim - 1; i >= 0; i--)
2381 sizes[i] = POPI ();
2384 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2386 PUSHA (res);
2388 NEXT_INSN;
2390 insn_goto_w:
2392 unsigned char* base_pc = pc-1;
2393 int offset = get4 (pc); pc += 4;
2394 pc = base_pc+offset;
2396 NEXT_INSN;
2398 insn_jsr_w:
2400 unsigned char* base_pc = pc-1;
2401 int offset = get4 (pc); pc += 4;
2402 PUSHA((jobject)pc);
2403 pc = base_pc+offset;
2405 NEXT_INSN;
2409 static void
2410 throw_internal_error (char *msg)
2412 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2415 static void
2416 throw_incompatible_class_change_error (jstring msg)
2418 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2421 #ifndef HANDLE_SEGV
2422 static java::lang::NullPointerException *null_pointer_exc;
2423 static void
2424 throw_null_pointer_exception ()
2426 if (null_pointer_exc == NULL)
2427 null_pointer_exc = new java::lang::NullPointerException;
2429 JvThrow (null_pointer_exc);
2431 #endif
2433 #endif // INTERPRETER