Add support for XScale target
[official-gcc.git] / libjava / interpret.cc
blob0a069ac4e1cc2efcefce87e0738c521e625190b0
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 <stdlib.h>
39 #if HAVE_ALLOCA_H
40 #include <alloca.h>
41 #endif
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 (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].o);
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));
1942 break;
1944 case 2:
1945 if (type == JvPrimClass (char))
1946 PUSHI(*(jchar*) (field->u.addr));
1947 else
1948 PUSHI(*(jshort*) (field->u.addr));
1949 break;
1951 case 4:
1952 PUSHI(*(jint*) (field->u.addr));
1953 break;
1955 case 8:
1956 PUSHL(*(jlong*) (field->u.addr));
1957 break;
1960 else
1962 PUSHA(*(jobject*) (field->u.addr));
1965 NEXT_INSN;
1967 insn_getfield:
1968 SAVE_PC;
1970 jint fieldref_index = get2u (pc); pc += 2;
1971 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1972 _Jv_Field *field = pool_data[fieldref_index].field;
1974 if ((field->flags & Modifier::STATIC) != 0)
1975 throw_incompatible_class_change_error
1976 (JvNewStringLatin1 ("field is static"));
1978 jclass type = field->type;
1979 jint field_offset = field->u.boffset;
1980 if (field_offset > 0xffff)
1981 JvThrow (new java::lang::VirtualMachineError);
1983 jobject obj = POPA();
1984 NULLCHECK(obj);
1986 if (type->isPrimitive ())
1988 switch (type->size_in_bytes)
1990 case 1:
1991 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1992 break;
1994 case 2:
1995 if (type == JvPrimClass (char))
1996 PUSHI (*(jchar*) ((char*)obj + field_offset));
1997 else
1998 PUSHI (*(jshort*) ((char*)obj + field_offset));
1999 break;
2001 case 4:
2002 PUSHI (*(jint*) ((char*)obj + field_offset));
2003 break;
2005 case 8:
2006 PUSHL(*(jlong*) ((char*)obj + field_offset));
2007 break;
2010 else
2012 PUSHA(*(jobject*) ((char*)obj + field_offset));
2015 NEXT_INSN;
2017 insn_putstatic:
2018 SAVE_PC;
2020 jint fieldref_index = get2u (pc); pc += 2;
2021 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2022 _Jv_Field *field = pool_data[fieldref_index].field;
2024 jclass type = field->type;
2026 // ResolvePoolEntry cannot check this
2027 if ((field->flags & Modifier::STATIC) == 0)
2028 throw_incompatible_class_change_error
2029 (JvNewStringLatin1 ("field no longer static"));
2031 if (type->isPrimitive ())
2033 switch (type->size_in_bytes)
2035 case 1:
2037 jint value = POPI();
2038 *(jbyte*) (field->u.addr) = value;
2039 break;
2042 case 2:
2044 jint value = POPI();
2045 *(jchar*) (field->u.addr) = value;
2046 break;
2049 case 4:
2051 jint value = POPI();
2052 *(jint*) (field->u.addr) = value;
2053 break;
2056 case 8:
2058 jlong value = POPL();
2059 *(jlong*) (field->u.addr) = value;
2060 break;
2064 else
2066 jobject value = POPA();
2067 *(jobject*) (field->u.addr) = value;
2070 NEXT_INSN;
2073 insn_putfield:
2074 SAVE_PC;
2076 jint fieldref_index = get2u (pc); pc += 2;
2077 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2078 _Jv_Field *field = pool_data[fieldref_index].field;
2080 jclass type = field->type;
2082 if ((field->flags & Modifier::STATIC) != 0)
2083 throw_incompatible_class_change_error
2084 (JvNewStringLatin1 ("field is static"));
2086 jint field_offset = field->u.boffset;
2087 if (field_offset > 0xffff)
2088 JvThrow (new java::lang::VirtualMachineError);
2090 if (type->isPrimitive ())
2092 switch (type->size_in_bytes)
2094 case 1:
2096 jint value = POPI();
2097 jobject obj = POPA();
2098 NULLCHECK(obj);
2099 *(jbyte*) ((char*)obj + field_offset) = value;
2100 break;
2103 case 2:
2105 jint value = POPI();
2106 jobject obj = POPA();
2107 NULLCHECK(obj);
2108 *(jchar*) ((char*)obj + field_offset) = value;
2109 break;
2112 case 4:
2114 jint value = POPI();
2115 jobject obj = POPA();
2116 NULLCHECK(obj);
2117 *(jint*) ((char*)obj + field_offset) = value;
2118 break;
2121 case 8:
2123 jlong value = POPL();
2124 jobject obj = POPA();
2125 NULLCHECK(obj);
2126 *(jlong*) ((char*)obj + field_offset) = value;
2127 break;
2131 else
2133 jobject value = POPA();
2134 jobject obj = POPA();
2135 NULLCHECK(obj);
2136 *(jobject*) ((char*)obj + field_offset) = value;
2139 NEXT_INSN;
2141 insn_invokespecial:
2142 SAVE_PC;
2144 int index = get2u (pc); pc += 2;
2146 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2148 sp -= rmeth->stack_item_count;
2150 NULLCHECK (sp[0].o);
2152 fun = (void (*)()) rmeth->method->ncode;
2154 goto perform_invoke;
2156 insn_invokestatic:
2157 SAVE_PC;
2159 int index = get2u (pc); pc += 2;
2161 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2163 sp -= rmeth->stack_item_count;
2165 _Jv_InitClass (rmeth->klass);
2166 fun = (void (*)()) rmeth->method->ncode;
2168 goto perform_invoke;
2170 insn_invokeinterface:
2171 SAVE_PC;
2173 int index = get2u (pc); pc += 2;
2175 // invokeinterface has two unused bytes...
2176 pc += 2;
2178 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2180 sp -= rmeth->stack_item_count;
2182 jobject rcv = sp[0].o;
2184 NULLCHECK (rcv);
2186 fun = (void (*)())
2187 _Jv_LookupInterfaceMethod (rcv->getClass (),
2188 rmeth->method->name,
2189 rmeth->method->signature);
2191 goto perform_invoke;
2194 insn_new:
2195 SAVE_PC;
2197 int index = get2u (pc); pc += 2;
2198 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2199 _Jv_InitClass (klass);
2200 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2201 PUSHA (res);
2203 NEXT_INSN;
2205 insn_newarray:
2206 SAVE_PC;
2208 int atype = get1u (pc++);
2209 int size = POPI();
2210 jobject result = _Jv_NewArray (atype, size);
2211 PUSHA (result);
2213 NEXT_INSN;
2215 insn_anewarray:
2216 SAVE_PC;
2218 int index = get2u (pc); pc += 2;
2219 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2220 int size = POPI();
2221 _Jv_InitClass (klass);
2222 jobject result = _Jv_NewObjectArray (size, klass, 0);
2223 PUSHA (result);
2225 NEXT_INSN;
2227 insn_arraylength:
2228 SAVE_PC;
2230 __JArray *arr = (__JArray*)POPA();
2231 PUSHI (arr->length);
2233 NEXT_INSN;
2235 insn_athrow:
2236 SAVE_PC;
2238 jobject value = POPA();
2239 JvThrow (value);
2241 NEXT_INSN;
2243 insn_checkcast:
2244 SAVE_PC;
2246 jobject value = POPA();
2247 jint index = get2u (pc); pc += 2;
2248 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2250 if (value != NULL && ! to->isInstance (value))
2252 JvThrow (new java::lang::ClassCastException
2253 (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*) 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 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2417 static void
2418 throw_incompatible_class_change_error (jstring msg)
2420 JvThrow (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 JvThrow (null_pointer_exc);
2433 #endif
2435 #endif // INTERPRETER