Allow HIGH/LO_SUM in the prologue
[official-gcc.git] / libjava / interpret.cc
blob6fd1fa6e43ceae2260ed6f0a980760d2e989c63e
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 #define ClassError _CL_Q34java4lang5Error
39 extern java::lang::Class ClassError;
41 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
43 static void throw_internal_error (char *msg)
44 __attribute__ ((__noreturn__));
45 static void throw_incompatible_class_change_error (jstring msg)
46 __attribute__ ((__noreturn__));
47 #ifndef HANDLE_SEGV
48 static void throw_null_pointer_exception ()
49 __attribute__ ((__noreturn__));
50 #endif
52 extern "C" double __ieee754_fmod __P((double,double));
54 static inline void dupx (_Jv_word *sp, int n, int x)
56 // first "slide" n+x elements n to the right
57 int top = n-1;
58 for (int i = 0; i < n+x; i++)
60 sp[(top-i)] = sp[(top-i)-n];
63 // next, copy the n top elements, n+x down
64 for (int i = 0; i < n; i++)
66 sp[top-(n+x)-i] = sp[top-i];
72 #define PUSHA(V) (sp++)->o = (V)
73 #define PUSHI(V) (sp++)->i = (V)
74 #define PUSHF(V) (sp++)->f = (V)
75 #if SIZEOF_VOID_P == 8
76 # define PUSHL(V) (sp->l = (V), sp += 2)
77 # define PUSHD(V) (sp->d = (V), sp += 2)
78 #else
79 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
80 (sp++)->ia[0] = w2.ia[0]; \
81 (sp++)->ia[0] = w2.ia[1]; } while (0)
82 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
83 (sp++)->ia[0] = w2.ia[0]; \
84 (sp++)->ia[0] = w2.ia[1]; } while (0)
85 #endif
87 #define POPA() ((--sp)->o)
88 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
89 #define POPF() ((jfloat) (--sp)->f)
90 #if SIZEOF_VOID_P == 8
91 # define POPL() (sp -= 2, (jlong) sp->l)
92 # define POPD() (sp -= 2, (jdouble) sp->d)
93 #else
94 # define POPL() ({ _Jv_word2 w2; \
95 w2.ia[1] = (--sp)->ia[0]; \
96 w2.ia[0] = (--sp)->ia[0]; w2.l; })
97 # define POPD() ({ _Jv_word2 w2; \
98 w2.ia[1] = (--sp)->ia[0]; \
99 w2.ia[0] = (--sp)->ia[0]; w2.d; })
100 #endif
102 #define LOADA(I) (sp++)->o = locals[I].o
103 #define LOADI(I) (sp++)->i = locals[I].i
104 #define LOADF(I) (sp++)->f = locals[I].f
105 #if SIZEOF_VOID_P == 8
106 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
107 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
108 #else
109 # define LOADL(I) do { jint __idx = (I); \
110 (sp++)->ia[0] = locals[__idx].ia[0]; \
111 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
112 } while (0)
113 # define LOADD(I) LOADL(I)
114 #endif
116 #define STOREA(I) locals[I].o = (--sp)->o
117 #define STOREI(I) locals[I].i = (--sp)->i
118 #define STOREF(I) locals[I].f = (--sp)->f
119 #if SIZEOF_VOID_P == 8
120 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
121 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
122 #else
123 # define STOREL(I) do { jint __idx = (I); \
124 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
125 locals[__idx].ia[0] = (--sp)->ia[0]; \
126 } while (0)
127 # define STORED(I) STOREL(I)
128 #endif
130 #define PEEKI(I) (locals+(I))->i
131 #define PEEKA(I) (locals+(I))->o
133 #define POKEI(I,V) ((locals+(I))->i = (V))
136 #define BINOPI(OP) { \
137 jint value2 = POPI(); \
138 jint value1 = POPI(); \
139 PUSHI(value1 OP value2); \
142 #define BINOPF(OP) { \
143 jfloat value2 = POPF(); \
144 jfloat value1 = POPF(); \
145 PUSHF(value1 OP value2); \
148 #define BINOPL(OP) { \
149 jlong value2 = POPL(); \
150 jlong value1 = POPL(); \
151 PUSHL(value1 OP value2); \
154 #define BINOPD(OP) { \
155 jdouble value2 = POPD(); \
156 jdouble value1 = POPD(); \
157 PUSHD(value1 OP value2); \
160 static inline jint get1s(unsigned char* loc) {
161 return *(signed char*)loc;
164 static inline jint get1u(unsigned char* loc) {
165 return *loc;
168 static inline jint get2s(unsigned char* loc) {
169 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
172 static inline jint get2u(unsigned char* loc) {
173 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
176 static jint get4(unsigned char* loc) {
177 return (((jint)(loc[0])) << 24)
178 | (((jint)(loc[1])) << 16)
179 | (((jint)(loc[2])) << 8)
180 | (((jint)(loc[3])) << 0);
184 #ifdef HANDLE_SEGV
185 #define NULLCHECK(X)
186 #else
187 #define NULLCHECK(X) \
188 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
189 #endif
192 // this method starts the actual running of the method. It is inlined
193 // in three different variants in the static methods run_normal,
194 // run_sync_object and run_sync_class (see below). Those static methods
195 // are installed directly in the stub for this method (by
196 // _Jv_InterpMethod::ncode, in resolve.cc).
198 inline jobject
199 _Jv_InterpMethod::run (ffi_cif* cif,
200 void *retp,
201 ffi_raw *args,
202 _Jv_InterpMethodInvocation *inv)
204 inv->running = this;
205 inv->pc = bytecode ();
206 inv->sp = inv->stack_base ();
207 _Jv_word *locals = inv->local_base ();
209 /* Go straight at it! the ffi raw format matches the internal
210 stack representation exactly. At least, that's the idea.
212 memcpy ((void*) locals, (void*) args, args_raw_size);
214 next_segment:
216 jobject ex = NULL;
220 continue1 (inv);
222 catch (java::lang::Throwable *ex2)
224 ex = ex2;
227 if (ex == 0) // no exception...
229 /* define sp locally, so the POP? macros will pick it up */
230 _Jv_word *sp = inv->sp;
231 int rtype = cif->rtype->type;
233 if (rtype == FFI_TYPE_POINTER)
235 jobject r = POPA();
236 *(jobject*) retp = r;
237 return 0;
239 else if (rtype == FFI_TYPE_SINT32)
241 jint r = POPI();
242 *(jint*)retp = r;
243 return 0;
245 else if (rtype == FFI_TYPE_VOID)
247 return 0;
249 else switch (rtype)
251 case FFI_TYPE_FLOAT:
253 jfloat r = POPF();
254 *(jfloat*)retp = r;
255 return 0;
258 case FFI_TYPE_DOUBLE:
260 jdouble r = POPD();
261 *(jdouble*)retp = r;
262 return 0;
265 case FFI_TYPE_UINT8:
266 case FFI_TYPE_UINT16:
267 case FFI_TYPE_UINT32:
268 case FFI_TYPE_SINT8:
269 case FFI_TYPE_SINT16:
271 jint r = POPI();
272 *(jint*)retp = r;
273 return 0;
276 case FFI_TYPE_SINT64:
278 jlong r = POPL();
279 *(jlong*)retp = r;
280 return 0;
283 default:
284 throw_internal_error ("unknown return type");
288 /** handle an exception */
289 if ( find_exception (ex, inv) )
290 goto next_segment;
292 return ex;
295 bool _Jv_InterpMethod::find_exception (jobject ex,
296 _Jv_InterpMethodInvocation *inv)
298 int logical_pc = inv->pc - bytecode ();
299 _Jv_InterpException *exc = exceptions ();
300 jclass exc_class = ex->getClass ();
302 for (int i = 0; i < exc_count; i++)
304 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
306 jclass handler;
308 if (exc[i].handler_type != 0)
309 handler = (_Jv_ResolvePoolEntry (defining_class,
310 exc[i].handler_type)).clazz;
311 else
312 handler = NULL;
314 if (handler==NULL || handler->isAssignableFrom (exc_class))
316 inv->pc = bytecode () + exc[i].handler_pc;
317 inv->sp = inv->stack_base (); // reset stack
318 (inv->sp++)->o = ex; // push exception
319 return true;
323 return false;
326 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327 void* ret,
328 ffi_raw * args,
329 void* __this)
331 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
333 // we do the alloca of the method invocation here, to allow the method
334 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
335 int storage_size = _this->max_stack+_this->max_locals;
336 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
337 alloca (sizeof (_Jv_InterpMethodInvocation)
338 + storage_size * sizeof (_Jv_word));
340 jobject ex = _this->run (cif, ret, args, inv);
341 if (ex != 0) _Jv_Throw (ex);
344 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345 void* ret,
346 ffi_raw * args,
347 void* __this)
349 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
350 jobject rcv = (jobject)args[0].ptr;
352 int storage_size = _this->max_stack+_this->max_locals;
353 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
354 alloca (sizeof (_Jv_InterpMethodInvocation)
355 + storage_size * sizeof (_Jv_word));
357 _Jv_MonitorEnter (rcv);
358 jobject ex = _this->run (cif, ret, args, inv);
359 _Jv_MonitorExit (rcv);
361 if (ex != 0) _Jv_Throw (ex);
364 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365 void* ret,
366 ffi_raw * args,
367 void* __this)
369 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
370 jclass sync = _this->defining_class;
372 int storage_size = _this->max_stack+_this->max_locals;
373 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
374 alloca (sizeof (_Jv_InterpMethodInvocation)
375 + storage_size * sizeof (_Jv_word));
377 _Jv_MonitorEnter (sync);
378 jobject ex = _this->run (cif, ret, args, inv);
379 _Jv_MonitorExit (sync);
381 if (ex != 0) _Jv_Throw (ex);
385 This proceeds execution, as designated in "inv". If an exception
386 happens, then it is simply thrown, and handled in Java. Thus, the pc
387 needs to be stored in the inv->pc at all times, so we can figure
388 out which handler (if any) to invoke.
390 One design issue, which I have not completely considered, is if it
391 should be possible to have interpreted classes linked in! Seldom used
392 (or non-critical) classes could reasonably be interpreted.
396 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
398 using namespace java::lang::reflect;
400 _Jv_word *sp = inv->sp;
401 unsigned char *pc = inv->pc;
402 _Jv_word *locals = inv->local_base ();
404 _Jv_word *pool_data = defining_class->constants.data;
406 /* these two are used in the invokeXXX instructions */
407 void (*fun)(...);
408 _Jv_ResolvedMethod* rmeth;
410 #define INSN_LABEL(op) &&insn_##op
411 #define GOTO_INSN(op) goto *(insn_target[op])
413 static const void *const insn_target[] =
415 INSN_LABEL(nop),
416 INSN_LABEL(aconst_null),
417 INSN_LABEL(iconst_m1),
418 INSN_LABEL(iconst_0),
419 INSN_LABEL(iconst_1),
420 INSN_LABEL(iconst_2),
421 INSN_LABEL(iconst_3),
422 INSN_LABEL(iconst_4),
423 INSN_LABEL(iconst_5),
424 INSN_LABEL(lconst_0),
425 INSN_LABEL(lconst_1),
426 INSN_LABEL(fconst_0),
427 INSN_LABEL(fconst_1),
428 INSN_LABEL(fconst_2),
429 INSN_LABEL(dconst_0),
430 INSN_LABEL(dconst_1),
431 INSN_LABEL(bipush),
432 INSN_LABEL(sipush),
433 INSN_LABEL(ldc),
434 INSN_LABEL(ldc_w),
435 INSN_LABEL(ldc2_w),
436 INSN_LABEL(iload),
437 INSN_LABEL(lload),
438 INSN_LABEL(fload),
439 INSN_LABEL(dload),
440 INSN_LABEL(aload),
441 INSN_LABEL(iload_0),
442 INSN_LABEL(iload_1),
443 INSN_LABEL(iload_2),
444 INSN_LABEL(iload_3),
445 INSN_LABEL(lload_0),
446 INSN_LABEL(lload_1),
447 INSN_LABEL(lload_2),
448 INSN_LABEL(lload_3),
449 INSN_LABEL(fload_0),
450 INSN_LABEL(fload_1),
451 INSN_LABEL(fload_2),
452 INSN_LABEL(fload_3),
453 INSN_LABEL(dload_0),
454 INSN_LABEL(dload_1),
455 INSN_LABEL(dload_2),
456 INSN_LABEL(dload_3),
457 INSN_LABEL(aload_0),
458 INSN_LABEL(aload_1),
459 INSN_LABEL(aload_2),
460 INSN_LABEL(aload_3),
461 INSN_LABEL(iaload),
462 INSN_LABEL(laload),
463 INSN_LABEL(faload),
464 INSN_LABEL(daload),
465 INSN_LABEL(aaload),
466 INSN_LABEL(baload),
467 INSN_LABEL(caload),
468 INSN_LABEL(saload),
469 INSN_LABEL(istore),
470 INSN_LABEL(lstore),
471 INSN_LABEL(fstore),
472 INSN_LABEL(dstore),
473 INSN_LABEL(astore),
474 INSN_LABEL(istore_0),
475 INSN_LABEL(istore_1),
476 INSN_LABEL(istore_2),
477 INSN_LABEL(istore_3),
478 INSN_LABEL(lstore_0),
479 INSN_LABEL(lstore_1),
480 INSN_LABEL(lstore_2),
481 INSN_LABEL(lstore_3),
482 INSN_LABEL(fstore_0),
483 INSN_LABEL(fstore_1),
484 INSN_LABEL(fstore_2),
485 INSN_LABEL(fstore_3),
486 INSN_LABEL(dstore_0),
487 INSN_LABEL(dstore_1),
488 INSN_LABEL(dstore_2),
489 INSN_LABEL(dstore_3),
490 INSN_LABEL(astore_0),
491 INSN_LABEL(astore_1),
492 INSN_LABEL(astore_2),
493 INSN_LABEL(astore_3),
494 INSN_LABEL(iastore),
495 INSN_LABEL(lastore),
496 INSN_LABEL(fastore),
497 INSN_LABEL(dastore),
498 INSN_LABEL(aastore),
499 INSN_LABEL(bastore),
500 INSN_LABEL(castore),
501 INSN_LABEL(sastore),
502 INSN_LABEL(pop),
503 INSN_LABEL(pop2),
504 INSN_LABEL(dup),
505 INSN_LABEL(dup_x1),
506 INSN_LABEL(dup_x2),
507 INSN_LABEL(dup2),
508 INSN_LABEL(dup2_x1),
509 INSN_LABEL(dup2_x2),
510 INSN_LABEL(swap),
511 INSN_LABEL(iadd),
512 INSN_LABEL(ladd),
513 INSN_LABEL(fadd),
514 INSN_LABEL(dadd),
515 INSN_LABEL(isub),
516 INSN_LABEL(lsub),
517 INSN_LABEL(fsub),
518 INSN_LABEL(dsub),
519 INSN_LABEL(imul),
520 INSN_LABEL(lmul),
521 INSN_LABEL(fmul),
522 INSN_LABEL(dmul),
523 INSN_LABEL(idiv),
524 INSN_LABEL(ldiv),
525 INSN_LABEL(fdiv),
526 INSN_LABEL(ddiv),
527 INSN_LABEL(irem),
528 INSN_LABEL(lrem),
529 INSN_LABEL(frem),
530 INSN_LABEL(drem),
531 INSN_LABEL(ineg),
532 INSN_LABEL(lneg),
533 INSN_LABEL(fneg),
534 INSN_LABEL(dneg),
535 INSN_LABEL(ishl),
536 INSN_LABEL(lshl),
537 INSN_LABEL(ishr),
538 INSN_LABEL(lshr),
539 INSN_LABEL(iushr),
540 INSN_LABEL(lushr),
541 INSN_LABEL(iand),
542 INSN_LABEL(land),
543 INSN_LABEL(ior),
544 INSN_LABEL(lor),
545 INSN_LABEL(ixor),
546 INSN_LABEL(lxor),
547 INSN_LABEL(iinc),
548 INSN_LABEL(i2l),
549 INSN_LABEL(i2f),
550 INSN_LABEL(i2d),
551 INSN_LABEL(l2i),
552 INSN_LABEL(l2f),
553 INSN_LABEL(l2d),
554 INSN_LABEL(f2i),
555 INSN_LABEL(f2l),
556 INSN_LABEL(f2d),
557 INSN_LABEL(d2i),
558 INSN_LABEL(d2l),
559 INSN_LABEL(d2f),
560 INSN_LABEL(i2b),
561 INSN_LABEL(i2c),
562 INSN_LABEL(i2s),
563 INSN_LABEL(lcmp),
564 INSN_LABEL(fcmpl),
565 INSN_LABEL(fcmpg),
566 INSN_LABEL(dcmpl),
567 INSN_LABEL(dcmpg),
568 INSN_LABEL(ifeq),
569 INSN_LABEL(ifne),
570 INSN_LABEL(iflt),
571 INSN_LABEL(ifge),
572 INSN_LABEL(ifgt),
573 INSN_LABEL(ifle),
574 INSN_LABEL(if_icmpeq),
575 INSN_LABEL(if_icmpne),
576 INSN_LABEL(if_icmplt),
577 INSN_LABEL(if_icmpge),
578 INSN_LABEL(if_icmpgt),
579 INSN_LABEL(if_icmple),
580 INSN_LABEL(if_acmpeq),
581 INSN_LABEL(if_acmpne),
582 INSN_LABEL(goto),
583 INSN_LABEL(jsr),
584 INSN_LABEL(ret),
585 INSN_LABEL(tableswitch),
586 INSN_LABEL(lookupswitch),
587 INSN_LABEL(ireturn),
588 INSN_LABEL(lreturn),
589 INSN_LABEL(freturn),
590 INSN_LABEL(dreturn),
591 INSN_LABEL(areturn),
592 INSN_LABEL(return),
593 INSN_LABEL(getstatic),
594 INSN_LABEL(putstatic),
595 INSN_LABEL(getfield),
596 INSN_LABEL(putfield),
597 INSN_LABEL(invokevirtual),
598 INSN_LABEL(invokespecial),
599 INSN_LABEL(invokestatic),
600 INSN_LABEL(invokeinterface),
601 0, /* op_xxxunusedxxx1, */
602 INSN_LABEL(new),
603 INSN_LABEL(newarray),
604 INSN_LABEL(anewarray),
605 INSN_LABEL(arraylength),
606 INSN_LABEL(athrow),
607 INSN_LABEL(checkcast),
608 INSN_LABEL(instanceof),
609 INSN_LABEL(monitorenter),
610 INSN_LABEL(monitorexit),
611 INSN_LABEL(wide),
612 INSN_LABEL(multianewarray),
613 INSN_LABEL(ifnull),
614 INSN_LABEL(ifnonnull),
615 INSN_LABEL(goto_w),
616 INSN_LABEL(jsr_w),
619 #define SAVE_PC inv->pc = pc-1
621 /* If the macro INLINE_SWITCH is not defined, then the main loop
622 operates as one big (normal) switch statement. If it is defined,
623 then the case selection is performed `inline' in the end of the
624 code for each case. The latter saves a native branch instruction
625 for each java-instruction, but expands the code size somewhat.
627 NOTE: On i386 defining INLINE_SWITCH improves over all
628 performance approximately seven percent, but it may be different
629 for other machines. At some point, this may be made into a proper
630 configuration parameter. */
632 #define INLINE_SWITCH
634 #ifdef INLINE_SWITCH
636 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
639 NEXT_INSN;
640 #else
642 #define NEXT_INSN goto next_insn
644 next_insn:
645 GOTO_INSN (*pc++);
647 #endif
649 /* The first few instructions here are ordered according to their
650 frequency, in the hope that this will improve code locality a
651 little. */
653 insn_aload_0: // 0x2a
654 LOADA(0);
655 NEXT_INSN;
657 insn_iload: // 0x15
658 LOADI (get1u (pc++));
659 NEXT_INSN;
661 insn_iload_1: // 0x1b
662 LOADI (1);
663 NEXT_INSN;
665 insn_invokevirtual: // 0xb6
666 SAVE_PC;
668 int index = get2u (pc); pc += 2;
670 /* _Jv_ResolvePoolEntry returns immediately if the value already
671 * is resolved. If we want to clutter up the code here to gain
672 * a little performance, then we can check the corresponding bit
673 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
674 * don't think it is worth it. */
676 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
678 sp -= rmeth->stack_item_count;
679 NULLCHECK(sp[0]);
681 if (rmeth->vtable_index == -1)
683 // final methods do not appear in the vtable,
684 // if it does not appear in the superclass.
685 fun = (void (*) (...)) rmeth->method->ncode;
687 else
689 jobject rcv = sp[0].o;
690 _Jv_VTable *table = *(_Jv_VTable**)rcv;
691 fun = (void (*) (...))table->method[rmeth->vtable_index];
694 goto perform_invoke;
696 perform_invoke:
698 /* here goes the magic again... */
699 ffi_cif *cif = &rmeth->cif;
700 ffi_raw *raw = (ffi_raw*) sp;
702 jdouble rvalue;
704 #if FFI_NATIVE_RAW_API
705 /* We assume that this is only implemented if it's correct */
706 /* to use it here. On a 64 bit machine, it never is. */
707 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
708 #else
709 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
710 #endif
712 int rtype = cif->rtype->type;
714 /* the likelyhood of object, int, or void return is very high,
715 * so those are checked before the switch */
716 if (rtype == FFI_TYPE_POINTER)
718 PUSHA (*(jobject*)&rvalue);
720 else if (rtype == FFI_TYPE_SINT32)
722 PUSHI (*(jint*)&rvalue);
724 else if (rtype == FFI_TYPE_VOID)
726 /* skip */
728 else switch (rtype)
730 case FFI_TYPE_SINT8:
732 jbyte value = (*(jint*)&rvalue) & 0xff;
733 PUSHI (value);
735 break;
737 case FFI_TYPE_SINT16:
739 jshort value = (*(jint*)&rvalue) & 0xffff;
740 PUSHI (value);
742 break;
744 case FFI_TYPE_UINT16:
746 jint value = (*(jint*)&rvalue) & 0xffff;
747 PUSHI (value);
749 break;
751 case FFI_TYPE_FLOAT:
752 PUSHF (*(jfloat*)&rvalue);
753 break;
755 case FFI_TYPE_DOUBLE:
756 PUSHD (rvalue);
757 break;
759 case FFI_TYPE_SINT64:
760 PUSHL (*(jlong*)&rvalue);
761 break;
763 default:
764 throw_internal_error ("unknown return type in invokeXXX");
768 NEXT_INSN;
771 insn_nop:
772 NEXT_INSN;
774 insn_aconst_null:
775 PUSHA (NULL);
776 NEXT_INSN;
778 insn_iconst_m1:
779 PUSHI (-1);
780 NEXT_INSN;
782 insn_iconst_0:
783 PUSHI (0);
784 NEXT_INSN;
786 insn_iconst_1:
787 PUSHI (1);
788 NEXT_INSN;
790 insn_iconst_2:
791 PUSHI (2);
792 NEXT_INSN;
794 insn_iconst_3:
795 PUSHI (3);
796 NEXT_INSN;
798 insn_iconst_4:
799 PUSHI (4);
800 NEXT_INSN;
802 insn_iconst_5:
803 PUSHI (5);
804 NEXT_INSN;
806 insn_lconst_0:
807 PUSHL (0);
808 NEXT_INSN;
810 insn_lconst_1:
811 PUSHL (1);
812 NEXT_INSN;
814 insn_fconst_0:
815 PUSHF (0);
816 NEXT_INSN;
818 insn_fconst_1:
819 PUSHF (1);
820 NEXT_INSN;
822 insn_fconst_2:
823 PUSHF (2);
824 NEXT_INSN;
826 insn_dconst_0:
827 PUSHD (0);
828 NEXT_INSN;
830 insn_dconst_1:
831 PUSHD (1);
832 NEXT_INSN;
834 insn_bipush:
835 PUSHI (get1s(pc++));
836 NEXT_INSN;
838 insn_sipush:
839 PUSHI (get2s(pc)); pc += 2;
840 NEXT_INSN;
842 insn_ldc:
844 int index = get1u (pc++);
845 PUSHA(pool_data[index].o);
847 NEXT_INSN;
849 insn_ldc_w:
851 int index = get2u (pc); pc += 2;
852 PUSHA(pool_data[index].o);
854 NEXT_INSN;
856 insn_ldc2_w:
858 int index = get2u (pc); pc += 2;
859 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
860 sp += 2;
862 NEXT_INSN;
864 insn_lload:
865 LOADL (get1u (pc++));
866 NEXT_INSN;
868 insn_fload:
869 LOADF (get1u (pc++));
870 NEXT_INSN;
872 insn_dload:
873 LOADD (get1u (pc++));
874 NEXT_INSN;
876 insn_aload:
877 LOADA (get1u (pc++));
878 NEXT_INSN;
880 insn_iload_0:
881 LOADI (0);
882 NEXT_INSN;
884 insn_iload_2:
885 LOADI (2);
886 NEXT_INSN;
888 insn_iload_3:
889 LOADI (3);
890 NEXT_INSN;
892 insn_lload_0:
893 LOADL (0);
894 NEXT_INSN;
896 insn_lload_1:
897 LOADL (1);
898 NEXT_INSN;
900 insn_lload_2:
901 LOADL (2);
902 NEXT_INSN;
904 insn_lload_3:
905 LOADL (3);
906 NEXT_INSN;
908 insn_fload_0:
909 LOADF (0);
910 NEXT_INSN;
912 insn_fload_1:
913 LOADF (1);
914 NEXT_INSN;
916 insn_fload_2:
917 LOADF (2);
918 NEXT_INSN;
920 insn_fload_3:
921 LOADF (3);
922 NEXT_INSN;
924 insn_dload_0:
925 LOADD (0);
926 NEXT_INSN;
928 insn_dload_1:
929 LOADD (1);
930 NEXT_INSN;
932 insn_dload_2:
933 LOADD (2);
934 NEXT_INSN;
936 insn_dload_3:
937 LOADD (3);
938 NEXT_INSN;
940 insn_aload_1:
941 LOADA(1);
942 NEXT_INSN;
944 insn_aload_2:
945 LOADA(2);
946 NEXT_INSN;
948 insn_aload_3:
949 LOADA(3);
950 NEXT_INSN;
952 insn_iaload:
953 SAVE_PC;
955 jint index = POPI();
956 jintArray arr = (jintArray) POPA();
957 NULLCHECK (arr);
958 if (index < 0 || index >= arr->length)
960 _Jv_ThrowBadArrayIndex (index);
962 PUSHI( elements(arr)[index] );
964 NEXT_INSN;
966 insn_laload:
967 SAVE_PC;
969 jint index = POPI();
970 jlongArray arr = (jlongArray) POPA();
971 NULLCHECK (arr);
972 if (index < 0 || index >= arr->length)
974 _Jv_ThrowBadArrayIndex (index);
976 PUSHL( elements(arr)[index] );
978 NEXT_INSN;
980 insn_faload:
981 SAVE_PC;
983 jint index = POPI();
984 jfloatArray arr = (jfloatArray) POPA();
985 NULLCHECK (arr);
986 if (index < 0 || index >= arr->length)
988 _Jv_ThrowBadArrayIndex (index);
990 PUSHF( elements(arr)[index] );
992 NEXT_INSN;
994 insn_daload:
995 SAVE_PC;
997 jint index = POPI();
998 jdoubleArray arr = (jdoubleArray) POPA();
999 NULLCHECK (arr);
1000 if (index < 0 || index >= arr->length)
1002 _Jv_ThrowBadArrayIndex (index);
1004 PUSHD( elements(arr)[index] );
1006 NEXT_INSN;
1008 insn_aaload:
1009 SAVE_PC;
1011 jint index = POPI();
1012 jobjectArray arr = (jobjectArray) POPA();
1013 NULLCHECK (arr);
1014 if (index < 0 || index >= arr->length)
1016 _Jv_ThrowBadArrayIndex (index);
1018 PUSHA( elements(arr)[index] );
1020 NEXT_INSN;
1022 insn_baload:
1023 SAVE_PC;
1025 jint index = POPI();
1026 jbyteArray arr = (jbyteArray) POPA();
1027 NULLCHECK (arr);
1028 if (index < 0 || index >= arr->length)
1030 _Jv_ThrowBadArrayIndex (index);
1032 PUSHI( elements(arr)[index] );
1034 NEXT_INSN;
1036 insn_caload:
1037 SAVE_PC;
1039 jint index = POPI();
1040 jcharArray arr = (jcharArray) POPA();
1041 NULLCHECK (arr);
1042 if (index < 0 || index >= arr->length)
1044 _Jv_ThrowBadArrayIndex (index);
1046 PUSHI( elements(arr)[index] );
1048 NEXT_INSN;
1050 insn_saload:
1051 SAVE_PC;
1053 jint index = POPI();
1054 jshortArray arr = (jshortArray) POPA();
1055 NULLCHECK (arr);
1056 if (index < 0 || index >= arr->length)
1058 _Jv_ThrowBadArrayIndex (index);
1060 PUSHI( elements(arr)[index] );
1062 NEXT_INSN;
1064 insn_istore:
1065 STOREI (get1u (pc++));
1066 NEXT_INSN;
1068 insn_lstore:
1069 STOREL (get1u (pc++));
1070 NEXT_INSN;
1072 insn_fstore:
1073 STOREF (get1u (pc++));
1074 NEXT_INSN;
1076 insn_dstore:
1077 STORED (get1u (pc++));
1078 NEXT_INSN;
1080 insn_astore:
1081 STOREA (get1u (pc++));
1082 NEXT_INSN;
1084 insn_istore_0:
1085 STOREI (0);
1086 NEXT_INSN;
1088 insn_istore_1:
1089 STOREI (1);
1090 NEXT_INSN;
1092 insn_istore_2:
1093 STOREI (2);
1094 NEXT_INSN;
1096 insn_istore_3:
1097 STOREI (3);
1098 NEXT_INSN;
1100 insn_lstore_0:
1101 STOREL (0);
1102 NEXT_INSN;
1104 insn_lstore_1:
1105 STOREL (1);
1106 NEXT_INSN;
1108 insn_lstore_2:
1109 STOREL (2);
1110 NEXT_INSN;
1112 insn_lstore_3:
1113 STOREL (3);
1114 NEXT_INSN;
1116 insn_fstore_0:
1117 STOREF (0);
1118 NEXT_INSN;
1120 insn_fstore_1:
1121 STOREF (1);
1122 NEXT_INSN;
1124 insn_fstore_2:
1125 STOREF (2);
1126 NEXT_INSN;
1128 insn_fstore_3:
1129 STOREF (3);
1130 NEXT_INSN;
1132 insn_dstore_0:
1133 STORED (0);
1134 NEXT_INSN;
1136 insn_dstore_1:
1137 STORED (1);
1138 NEXT_INSN;
1140 insn_dstore_2:
1141 STORED (2);
1142 NEXT_INSN;
1144 insn_dstore_3:
1145 STORED (3);
1146 NEXT_INSN;
1148 insn_astore_0:
1149 STOREA(0);
1150 NEXT_INSN;
1152 insn_astore_1:
1153 STOREA(1);
1154 NEXT_INSN;
1156 insn_astore_2:
1157 STOREA(2);
1158 NEXT_INSN;
1160 insn_astore_3:
1161 STOREA(3);
1162 NEXT_INSN;
1164 insn_iastore:
1165 SAVE_PC;
1167 jint value = POPI();
1168 jint index = POPI();
1169 jintArray arr = (jintArray) POPA();
1170 NULLCHECK (arr);
1171 if (index < 0 || index >= arr->length)
1173 _Jv_ThrowBadArrayIndex (index);
1175 elements(arr)[index] = value;
1177 NEXT_INSN;
1179 insn_lastore:
1180 SAVE_PC;
1182 jlong value = POPL();
1183 jint index = POPI();
1184 jlongArray arr = (jlongArray) POPA();
1185 NULLCHECK (arr);
1186 if (index < 0 || index >= arr->length)
1188 _Jv_ThrowBadArrayIndex (index);
1190 elements(arr)[index] = value;
1192 NEXT_INSN;
1194 insn_fastore:
1195 SAVE_PC;
1197 jfloat value = POPF();
1198 jint index = POPI();
1199 jfloatArray arr = (jfloatArray) POPA();
1200 NULLCHECK (arr);
1201 if (index < 0 || index >= arr->length)
1203 _Jv_ThrowBadArrayIndex (index);
1205 elements(arr)[index] = value;
1207 NEXT_INSN;
1209 insn_dastore:
1210 SAVE_PC;
1212 jdouble value = POPD();
1213 jint index = POPI();
1214 jdoubleArray arr = (jdoubleArray) POPA();
1215 NULLCHECK (arr);
1216 if (index < 0 || index >= arr->length)
1218 _Jv_ThrowBadArrayIndex (index);
1220 elements(arr)[index] = value;
1222 NEXT_INSN;
1224 insn_aastore:
1225 SAVE_PC;
1227 jobject value = POPA();
1228 jint index = POPI();
1229 jobjectArray arr = (jobjectArray) POPA();
1230 NULLCHECK (arr);
1231 if (index < 0 || index >= arr->length)
1233 _Jv_ThrowBadArrayIndex (index);
1235 _Jv_CheckArrayStore (arr, value);
1236 elements(arr)[index] = value;
1238 NEXT_INSN;
1240 insn_bastore:
1241 SAVE_PC;
1243 jbyte value = (jbyte) POPI();
1244 jint index = POPI();
1245 jbyteArray arr = (jbyteArray) POPA();
1246 NULLCHECK (arr);
1247 if (index < 0 || index >= arr->length)
1249 _Jv_ThrowBadArrayIndex (index);
1251 elements(arr)[index] = value;
1253 NEXT_INSN;
1255 insn_castore:
1256 SAVE_PC;
1258 jchar value = (jchar) POPI();
1259 jint index = POPI();
1260 jcharArray arr = (jcharArray) POPA();
1261 NULLCHECK (arr);
1262 if (index < 0 || index >= arr->length)
1264 _Jv_ThrowBadArrayIndex (index);
1266 elements(arr)[index] = value;
1268 NEXT_INSN;
1270 insn_sastore:
1271 SAVE_PC;
1273 jshort value = (jshort) POPI();
1274 jint index = POPI();
1275 jshortArray arr = (jshortArray) POPA();
1276 NULLCHECK (arr);
1277 if (index < 0 || index >= arr->length)
1279 _Jv_ThrowBadArrayIndex (index);
1281 elements(arr)[index] = value;
1283 NEXT_INSN;
1285 insn_pop:
1286 sp -= 1;
1287 NEXT_INSN;
1289 insn_pop2:
1290 sp -= 2;
1291 NEXT_INSN;
1293 insn_dup:
1294 sp[0] = sp[-1];
1295 sp += 1;
1296 NEXT_INSN;
1298 insn_dup_x1:
1299 dupx (sp, 1, 1); sp+=1;
1300 NEXT_INSN;
1302 insn_dup_x2:
1303 dupx (sp, 1, 2); sp+=1;
1304 NEXT_INSN;
1306 insn_dup2:
1307 sp[0] = sp[-2];
1308 sp[1] = sp[-1];
1309 sp += 2;
1310 NEXT_INSN;
1312 insn_dup2_x1:
1313 dupx (sp, 2, 1); sp+=2;
1314 NEXT_INSN;
1316 insn_dup2_x2:
1317 dupx (sp, 2, 2); sp+=2;
1318 NEXT_INSN;
1320 insn_swap:
1322 jobject tmp1 = POPA();
1323 jobject tmp2 = POPA();
1324 PUSHA (tmp1);
1325 PUSHA (tmp2);
1327 NEXT_INSN;
1329 insn_iadd:
1330 BINOPI(+);
1331 NEXT_INSN;
1333 insn_ladd:
1334 BINOPL(+);
1335 NEXT_INSN;
1337 insn_fadd:
1338 BINOPF(+);
1339 NEXT_INSN;
1341 insn_dadd:
1342 BINOPD(+);
1343 NEXT_INSN;
1345 insn_isub:
1346 BINOPI(-);
1347 NEXT_INSN;
1349 insn_lsub:
1350 BINOPL(-);
1351 NEXT_INSN;
1353 insn_fsub:
1354 BINOPF(-);
1355 NEXT_INSN;
1357 insn_dsub:
1358 BINOPD(-);
1359 NEXT_INSN;
1361 insn_imul:
1362 BINOPI(*);
1363 NEXT_INSN;
1365 insn_lmul:
1366 BINOPL(*);
1367 NEXT_INSN;
1369 insn_fmul:
1370 BINOPF(*);
1371 NEXT_INSN;
1373 insn_dmul:
1374 BINOPD(*);
1375 NEXT_INSN;
1377 insn_idiv:
1378 SAVE_PC;
1380 jint value2 = POPI();
1381 jint value1 = POPI();
1382 jint res = _Jv_divI (value1, value2);
1383 PUSHI (res);
1385 NEXT_INSN;
1387 insn_ldiv:
1388 SAVE_PC;
1390 jlong value2 = POPL();
1391 jlong value1 = POPL();
1392 jlong res = _Jv_divJ (value1, value2);
1393 PUSHL (res);
1395 NEXT_INSN;
1397 insn_fdiv:
1398 SAVE_PC;
1400 jfloat value2 = POPF();
1401 jfloat value1 = POPF();
1402 jfloat res = value1 / value2;
1403 PUSHF (res);
1405 NEXT_INSN;
1407 insn_ddiv:
1408 SAVE_PC;
1410 jdouble value2 = POPD();
1411 jdouble value1 = POPD();
1412 jdouble res = value1 / value2;
1413 PUSHD (res);
1415 NEXT_INSN;
1417 insn_irem:
1418 SAVE_PC;
1420 jint value2 = POPI();
1421 jint value1 = POPI();
1422 jint res = _Jv_remI (value1, value2);
1423 PUSHI (res);
1425 NEXT_INSN;
1427 insn_lrem:
1428 SAVE_PC;
1430 jlong value2 = POPL();
1431 jlong value1 = POPL();
1432 jlong res = _Jv_remJ (value1, value2);
1433 PUSHL (res);
1435 NEXT_INSN;
1437 insn_frem:
1438 SAVE_PC;
1440 jfloat value2 = POPF();
1441 jfloat value1 = POPF();
1442 jfloat res = __ieee754_fmod (value1, value2);
1443 PUSHF (res);
1445 NEXT_INSN;
1447 insn_drem:
1448 SAVE_PC;
1450 jdouble value2 = POPD();
1451 jdouble value1 = POPD();
1452 jdouble res = __ieee754_fmod (value1, value2);
1453 PUSHD (res);
1455 NEXT_INSN;
1457 insn_ineg:
1459 jint value = POPI();
1460 PUSHI (value * -1);
1462 NEXT_INSN;
1464 insn_lneg:
1466 jlong value = POPL();
1467 PUSHL (value * -1);
1469 NEXT_INSN;
1471 insn_fneg:
1473 jfloat value = POPF();
1474 PUSHF (value * -1);
1476 NEXT_INSN;
1478 insn_dneg:
1480 jdouble value = POPD();
1481 PUSHD (value * -1);
1483 NEXT_INSN;
1485 insn_ishl:
1487 jint shift = (POPI() & 0x1f);
1488 jint value = POPI();
1489 PUSHI (value << shift);
1491 NEXT_INSN;
1493 insn_lshl:
1495 jint shift = (POPI() & 0x3f);
1496 jlong value = POPL();
1497 PUSHL (value << shift);
1499 NEXT_INSN;
1501 insn_ishr:
1503 jint shift = (POPI() & 0x1f);
1504 jint value = POPI();
1505 PUSHI (value >> shift);
1507 NEXT_INSN;
1509 insn_lshr:
1511 jint shift = (POPI() & 0x3f);
1512 jlong value = POPL();
1513 PUSHL (value >> shift);
1515 NEXT_INSN;
1517 insn_iushr:
1519 jint shift = (POPI() & 0x1f);
1520 unsigned long value = POPI();
1521 PUSHI ((jint) (value >> shift));
1523 NEXT_INSN;
1525 insn_lushr:
1527 jint shift = (POPI() & 0x3f);
1528 UINT64 value = (UINT64) POPL();
1529 PUSHL ((value >> shift));
1531 NEXT_INSN;
1533 insn_iand:
1534 BINOPI (&);
1535 NEXT_INSN;
1537 insn_land:
1538 BINOPL (&);
1539 NEXT_INSN;
1541 insn_ior:
1542 BINOPI (|);
1543 NEXT_INSN;
1545 insn_lor:
1546 BINOPL (|);
1547 NEXT_INSN;
1549 insn_ixor:
1550 BINOPI (^);
1551 NEXT_INSN;
1553 insn_lxor:
1554 BINOPL (^);
1555 NEXT_INSN;
1557 insn_iinc:
1559 jint index = get1u (pc++);
1560 jint amount = get1s (pc++);
1561 locals[index].i += amount;
1563 NEXT_INSN;
1565 insn_i2l:
1566 {jlong value = POPI(); PUSHL (value);}
1567 NEXT_INSN;
1569 insn_i2f:
1570 {jfloat value = POPI(); PUSHF (value);}
1571 NEXT_INSN;
1573 insn_i2d:
1574 {jdouble value = POPI(); PUSHD (value);}
1575 NEXT_INSN;
1577 insn_l2i:
1578 {jint value = POPL(); PUSHI (value);}
1579 NEXT_INSN;
1581 insn_l2f:
1582 {jfloat value = POPL(); PUSHF (value);}
1583 NEXT_INSN;
1585 insn_l2d:
1586 {jdouble value = POPL(); PUSHD (value);}
1587 NEXT_INSN;
1589 insn_f2i:
1590 { jint value = (jint)POPF (); PUSHI(value); }
1591 NEXT_INSN;
1593 insn_f2l:
1594 { jlong value = (jlong)POPF (); PUSHL(value); }
1595 NEXT_INSN;
1597 insn_f2d:
1598 { jdouble value = POPF (); PUSHD(value); }
1599 NEXT_INSN;
1601 insn_d2i:
1602 { jint value = (jint)POPD (); PUSHI(value); }
1603 NEXT_INSN;
1605 insn_d2l:
1606 { jlong value = (jlong)POPD (); PUSHL(value); }
1607 NEXT_INSN;
1609 insn_d2f:
1610 { jfloat value = POPD (); PUSHF(value); }
1611 NEXT_INSN;
1613 insn_i2b:
1614 { jbyte value = POPI (); PUSHI(value); }
1615 NEXT_INSN;
1617 insn_i2c:
1618 { jchar value = POPI (); PUSHI(value); }
1619 NEXT_INSN;
1621 insn_i2s:
1622 { jshort value = POPI (); PUSHI(value); }
1623 NEXT_INSN;
1625 insn_lcmp:
1627 jlong value2 = POPL ();
1628 jlong value1 = POPL ();
1629 if (value1 > value2)
1630 { PUSHI (1); }
1631 else if (value1 == value2)
1632 { PUSHI (0); }
1633 else
1634 { PUSHI (-1); }
1636 NEXT_INSN;
1638 insn_fcmpl:
1639 insn_fcmpg:
1641 jfloat value2 = POPF ();
1642 jfloat value1 = POPF ();
1643 if (value1 > value2)
1644 PUSHI (1);
1645 else if (value1 == value2)
1646 PUSHI (0);
1647 else if (value1 < value2)
1648 PUSHI (-1);
1649 else if ((*(pc-1)) == op_fcmpg)
1650 PUSHI (1);
1651 else
1652 PUSHI (-1);
1654 NEXT_INSN;
1656 insn_dcmpl:
1657 insn_dcmpg:
1659 jdouble value2 = POPD ();
1660 jdouble value1 = POPD ();
1661 if (value1 > value2)
1662 PUSHI (1);
1663 else if (value1 == value2)
1664 PUSHI (0);
1665 else if (value1 < value2)
1666 PUSHI (-1);
1667 else if ((*(pc-1)) == op_dcmpg)
1668 PUSHI (1);
1669 else
1670 PUSHI (-1);
1672 NEXT_INSN;
1674 insn_ifeq:
1676 jint offset = get2s (pc);
1677 if (POPI() == 0)
1678 pc = pc-1+offset;
1679 else
1680 pc = pc+2;
1682 NEXT_INSN;
1684 insn_ifne:
1686 jint offset = get2s (pc);
1687 if (POPI() != 0)
1688 pc = pc-1+offset;
1689 else
1690 pc = pc+2;
1692 NEXT_INSN;
1694 insn_iflt:
1696 jint offset = get2s (pc);
1697 if (POPI() < 0)
1698 pc = pc-1+offset;
1699 else
1700 pc = pc+2;
1702 NEXT_INSN;
1704 insn_ifge:
1706 jint offset = get2s (pc);
1707 if (POPI() >= 0)
1708 pc = pc-1+offset;
1709 else
1710 pc = pc+2;
1712 NEXT_INSN;
1714 insn_ifgt:
1716 jint offset = get2s (pc);
1717 if (POPI() > 0)
1718 pc = pc-1+offset;
1719 else
1720 pc = pc+2;
1722 NEXT_INSN;
1724 insn_ifle:
1726 jint offset = get2s (pc);
1727 if (POPI() <= 0)
1728 pc = pc-1+offset;
1729 else
1730 pc = pc+2;
1732 NEXT_INSN;
1734 insn_if_icmpeq:
1736 jint offset = get2s (pc);
1737 jint value2 = POPI();
1738 jint value1 = POPI();
1739 if (value1 == value2)
1740 pc = pc-1+offset;
1741 else
1742 pc = pc+2;
1744 NEXT_INSN;
1746 insn_if_icmpne:
1748 jint offset = get2s (pc);
1749 jint value2 = POPI();
1750 jint value1 = POPI();
1751 if (value1 != value2)
1752 pc = pc-1+offset;
1753 else
1754 pc = pc+2;
1756 NEXT_INSN;
1758 insn_if_icmplt:
1760 jint offset = get2s (pc);
1761 jint value2 = POPI();
1762 jint value1 = POPI();
1763 if (value1 < value2)
1764 pc = pc-1+offset;
1765 else
1766 pc = pc+2;
1768 NEXT_INSN;
1770 insn_if_icmpge:
1772 jint offset = get2s (pc);
1773 jint value2 = POPI();
1774 jint value1 = POPI();
1775 if (value1 >= value2)
1776 pc = pc-1+offset;
1777 else
1778 pc = pc+2;
1780 NEXT_INSN;
1782 insn_if_icmpgt:
1784 jint offset = get2s (pc);
1785 jint value2 = POPI();
1786 jint value1 = POPI();
1787 if (value1 > value2)
1788 pc = pc-1+offset;
1789 else
1790 pc = pc+2;
1792 NEXT_INSN;
1794 insn_if_icmple:
1796 jint offset = get2s (pc);
1797 jint value2 = POPI();
1798 jint value1 = POPI();
1799 if (value1 <= value2)
1800 pc = pc-1+offset;
1801 else
1802 pc = pc+2;
1804 NEXT_INSN;
1806 insn_if_acmpeq:
1808 jint offset = get2s (pc);
1809 jobject value2 = POPA();
1810 jobject value1 = POPA();
1811 if (value1 == value2)
1812 pc = pc-1+offset;
1813 else
1814 pc = pc+2;
1816 NEXT_INSN;
1818 insn_if_acmpne:
1820 jint offset = get2s (pc);
1821 jobject value2 = POPA();
1822 jobject value1 = POPA();
1823 if (value1 != value2)
1824 pc = pc-1+offset;
1825 else
1826 pc = pc+2;
1828 NEXT_INSN;
1830 insn_goto:
1832 jint offset = get2s (pc);
1833 pc = pc-1+offset;
1835 NEXT_INSN;
1837 insn_jsr:
1839 unsigned char *base_pc = pc-1;
1840 jint offset = get2s (pc); pc += 2;
1841 PUSHA ((jobject)pc);
1842 pc = base_pc+offset;
1844 NEXT_INSN;
1846 insn_ret:
1848 jint index = get1u (pc);
1849 pc = (unsigned char*) PEEKA (index);
1851 NEXT_INSN;
1853 insn_tableswitch:
1855 unsigned char *base_pc = pc-1;
1856 int index = POPI();
1858 unsigned char* base = bytecode ();
1859 while ((pc-base) % 4 != 0)
1860 pc++;
1862 jint def = get4 (pc);
1863 jint low = get4 (pc+4);
1864 jint high = get4 (pc+8);
1866 if (index < low || index > high)
1867 pc = base_pc + def;
1868 else
1869 pc = base_pc + get4 (pc+4*(index-low+3));
1871 NEXT_INSN;
1873 insn_lookupswitch:
1875 unsigned char *base_pc = pc-1;
1876 int index = POPI();
1878 unsigned char* base = bytecode ();
1879 while ((pc-base) % 4 != 0)
1880 pc++;
1882 jint def = get4 (pc);
1883 jint npairs = get4 (pc+4);
1885 int max = npairs-1;
1886 int min = 0;
1888 // simple binary search...
1889 while (min < max)
1891 int half = (min+max)/2;
1892 int match = get4 (pc+ 4*(2 + 2*half));
1894 if (index == match)
1895 min = max = half;
1897 else if (index < match)
1898 max = half-1;
1900 else
1901 min = half+1;
1904 if (index == get4 (pc+ 4*(2 + 2*min)))
1905 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1906 else
1907 pc = base_pc + def;
1909 NEXT_INSN;
1911 /* on return, just save the sp and return to caller */
1912 insn_ireturn:
1913 insn_lreturn:
1914 insn_freturn:
1915 insn_dreturn:
1916 insn_areturn:
1917 insn_return:
1918 inv->sp = sp;
1919 return;
1921 insn_getstatic:
1922 SAVE_PC;
1924 jint fieldref_index = get2u (pc); pc += 2;
1925 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1926 _Jv_Field *field = pool_data[fieldref_index].field;
1928 if ((field->flags & Modifier::STATIC) == 0)
1929 throw_incompatible_class_change_error
1930 (JvNewStringLatin1 ("field no longer static"));
1932 jclass type = field->type;
1934 if (type->isPrimitive ())
1936 switch (type->size_in_bytes)
1938 case 1:
1939 PUSHI (*(jbyte*) (field->u.addr));
1941 case 2:
1942 if (type == JvPrimClass (char))
1943 PUSHI(*(jchar*) (field->u.addr));
1944 else
1945 PUSHI(*(jshort*) (field->u.addr));
1946 break;
1948 case 4:
1949 PUSHI(*(jint*) (field->u.addr));
1950 break;
1952 case 8:
1953 PUSHL(*(jlong*) (field->u.addr));
1954 break;
1957 else
1959 PUSHA(*(jobject*) (field->u.addr));
1962 NEXT_INSN;
1964 insn_getfield:
1965 SAVE_PC;
1967 jint fieldref_index = get2u (pc); pc += 2;
1968 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1969 _Jv_Field *field = pool_data[fieldref_index].field;
1971 if ((field->flags & Modifier::STATIC) != 0)
1972 throw_incompatible_class_change_error
1973 (JvNewStringLatin1 ("field is static"));
1975 jclass type = field->type;
1976 jint field_offset = field->u.boffset;
1977 if (field_offset > 0xffff)
1978 JvThrow (new java::lang::VirtualMachineError);
1980 jobject obj = POPA();
1981 NULLCHECK(obj);
1983 if (type->isPrimitive ())
1985 switch (type->size_in_bytes)
1987 case 1:
1988 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1989 break;
1991 case 2:
1992 if (type == JvPrimClass (char))
1993 PUSHI (*(jchar*) ((char*)obj + field_offset));
1994 else
1995 PUSHI (*(jshort*) ((char*)obj + field_offset));
1996 break;
1998 case 4:
1999 PUSHI (*(jint*) ((char*)obj + field_offset));
2000 break;
2002 case 8:
2003 PUSHL(*(jlong*) ((char*)obj + field_offset));
2004 break;
2007 else
2009 PUSHA(*(jobject*) ((char*)obj + field_offset));
2012 NEXT_INSN;
2014 insn_putstatic:
2015 SAVE_PC;
2017 jint fieldref_index = get2u (pc); pc += 2;
2018 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2019 _Jv_Field *field = pool_data[fieldref_index].field;
2021 jclass type = field->type;
2023 // ResolvePoolEntry cannot check this
2024 if ((field->flags & Modifier::STATIC) == 0)
2025 throw_incompatible_class_change_error
2026 (JvNewStringLatin1 ("field no longer static"));
2028 if (type->isPrimitive ())
2030 switch (type->size_in_bytes)
2032 case 1:
2034 jint value = POPI();
2035 *(jbyte*) (field->u.addr) = value;
2036 break;
2039 case 2:
2041 jint value = POPI();
2042 *(jchar*) (field->u.addr) = value;
2043 break;
2046 case 4:
2048 jint value = POPI();
2049 *(jint*) (field->u.addr) = value;
2050 break;
2053 case 8:
2055 jlong value = POPL();
2056 *(jlong*) (field->u.addr) = value;
2057 break;
2061 else
2063 jobject value = POPA();
2064 *(jobject*) (field->u.addr) = value;
2067 NEXT_INSN;
2070 insn_putfield:
2071 SAVE_PC;
2073 jint fieldref_index = get2u (pc); pc += 2;
2074 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2075 _Jv_Field *field = pool_data[fieldref_index].field;
2077 jclass type = field->type;
2079 if ((field->flags & Modifier::STATIC) != 0)
2080 throw_incompatible_class_change_error
2081 (JvNewStringLatin1 ("field is static"));
2083 jint field_offset = field->u.boffset;
2084 if (field_offset > 0xffff)
2085 JvThrow (new java::lang::VirtualMachineError);
2087 if (type->isPrimitive ())
2089 switch (type->size_in_bytes)
2091 case 1:
2093 jint value = POPI();
2094 jobject obj = POPA();
2095 NULLCHECK(obj);
2096 *(jbyte*) ((char*)obj + field_offset) = value;
2097 break;
2100 case 2:
2102 jint value = POPI();
2103 jobject obj = POPA();
2104 NULLCHECK(obj);
2105 *(jchar*) ((char*)obj + field_offset) = value;
2106 break;
2109 case 4:
2111 jint value = POPI();
2112 jobject obj = POPA();
2113 NULLCHECK(obj);
2114 *(jint*) ((char*)obj + field_offset) = value;
2115 break;
2118 case 8:
2120 jlong value = POPL();
2121 jobject obj = POPA();
2122 NULLCHECK(obj);
2123 *(jlong*) ((char*)obj + field_offset) = value;
2124 break;
2128 else
2130 jobject value = POPA();
2131 jobject obj = POPA();
2132 NULLCHECK(obj);
2133 *(jobject*) ((char*)obj + field_offset) = value;
2136 NEXT_INSN;
2138 insn_invokespecial:
2139 SAVE_PC;
2141 int index = get2u (pc); pc += 2;
2143 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2145 sp -= rmeth->stack_item_count;
2147 NULLCHECK(sp[0]);
2149 fun = (void (*) (...))rmeth->method->ncode;
2151 goto perform_invoke;
2153 insn_invokestatic:
2154 SAVE_PC;
2156 int index = get2u (pc); pc += 2;
2158 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2160 sp -= rmeth->stack_item_count;
2162 _Jv_InitClass (rmeth->klass);
2163 fun = (void (*) (...))rmeth->method->ncode;
2165 goto perform_invoke;
2167 insn_invokeinterface:
2168 SAVE_PC;
2170 int index = get2u (pc); pc += 2;
2172 // invokeinterface has two unused bytes...
2173 pc += 2;
2175 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2177 sp -= rmeth->stack_item_count;
2178 NULLCHECK(sp[0]);
2180 jobject rcv = sp[0].o;
2182 fun = (void (*) (...))
2183 _Jv_LookupInterfaceMethod (rcv->getClass (),
2184 rmeth->method->name,
2185 rmeth->method->signature);
2187 goto perform_invoke;
2190 insn_new:
2191 SAVE_PC;
2193 int index = get2u (pc); pc += 2;
2194 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2195 _Jv_InitClass (klass);
2196 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2197 PUSHA (res);
2199 NEXT_INSN;
2201 insn_newarray:
2202 SAVE_PC;
2204 int atype = get1u (pc++);
2205 int size = POPI();
2206 jobject result = _Jv_NewArray (atype, size);
2207 PUSHA (result);
2209 NEXT_INSN;
2211 insn_anewarray:
2212 SAVE_PC;
2214 int index = get2u (pc); pc += 2;
2215 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2216 int size = POPI();
2217 _Jv_InitClass (klass);
2218 jobject result = _Jv_NewObjectArray (size, klass, 0);
2219 PUSHA (result);
2221 NEXT_INSN;
2223 insn_arraylength:
2224 SAVE_PC;
2226 __JArray *arr = (__JArray*)POPA();
2227 PUSHI (arr->length);
2229 NEXT_INSN;
2231 insn_athrow:
2232 SAVE_PC;
2234 jobject value = POPA();
2235 JvThrow (value);
2237 NEXT_INSN;
2239 insn_checkcast:
2240 SAVE_PC;
2242 jobject value = POPA();
2243 jint index = get2u (pc); pc += 2;
2244 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2246 if (value != NULL && ! to->isInstance (value))
2248 JvThrow (new java::lang::ClassCastException
2249 (to->getName()));
2252 PUSHA (value);
2254 NEXT_INSN;
2256 insn_instanceof:
2257 SAVE_PC;
2259 jobject value = POPA();
2260 jint index = get2u (pc); pc += 2;
2261 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2262 PUSHI (to->isInstance (value));
2264 NEXT_INSN;
2266 insn_monitorenter:
2267 SAVE_PC;
2269 jobject value = POPA();
2270 NULLCHECK(value);
2271 _Jv_MonitorEnter (value);
2273 NEXT_INSN;
2275 insn_monitorexit:
2276 SAVE_PC;
2278 jobject value = POPA();
2279 NULLCHECK(value);
2280 _Jv_MonitorExit (value);
2282 NEXT_INSN;
2284 insn_ifnull:
2286 unsigned char* base_pc = pc-1;
2287 jint offset = get2s (pc); pc += 2;
2288 jobject val = POPA();
2289 if (val == NULL)
2290 pc = base_pc+offset;
2292 NEXT_INSN;
2294 insn_ifnonnull:
2296 unsigned char* base_pc = pc-1;
2297 jint offset = get2s (pc); pc += 2;
2298 jobject val = POPA();
2299 if (val != NULL)
2300 pc = base_pc+offset;
2302 NEXT_INSN;
2304 insn_wide:
2305 SAVE_PC;
2307 jint the_mod_op = get1u (pc++);
2308 jint wide = get2u (pc); pc += 2;
2310 switch (the_mod_op)
2312 case op_istore:
2313 STOREI (wide);
2314 NEXT_INSN;
2316 case op_fstore:
2317 STOREF (wide);
2318 NEXT_INSN;
2320 case op_astore:
2321 STOREA (wide);
2322 NEXT_INSN;
2324 case op_lload:
2325 LOADL (wide);
2326 NEXT_INSN;
2328 case op_dload:
2329 LOADD (wide);
2330 NEXT_INSN;
2332 case op_iload:
2333 LOADI (wide);
2334 NEXT_INSN;
2336 case op_aload:
2337 LOADA (wide);
2338 NEXT_INSN;
2340 case op_lstore:
2341 STOREL (wide);
2342 NEXT_INSN;
2344 case op_dstore:
2345 STORED (wide);
2346 NEXT_INSN;
2348 case op_ret:
2349 pc = (unsigned char*) PEEKA (wide);
2350 NEXT_INSN;
2352 case op_iinc:
2354 jint amount = get2s (pc); pc += 2;
2355 jint value = PEEKI (wide);
2356 POKEI (wide, value+amount);
2358 NEXT_INSN;
2360 default:
2361 throw_internal_error ("illegal bytecode modified by wide");
2366 insn_multianewarray:
2367 SAVE_PC;
2369 int kind_index = get2u (pc); pc += 2;
2370 int dim = get1u (pc); pc += 1;
2372 jclass type
2373 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2374 _Jv_InitClass (type);
2375 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2377 for (int i = dim - 1; i >= 0; i--)
2379 sizes[i] = POPI ();
2382 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2384 PUSHA (res);
2386 NEXT_INSN;
2388 insn_goto_w:
2390 unsigned char* base_pc = pc-1;
2391 int offset = get4 (pc); pc += 4;
2392 pc = base_pc+offset;
2394 NEXT_INSN;
2396 insn_jsr_w:
2398 unsigned char* base_pc = pc-1;
2399 int offset = get4 (pc); pc += 4;
2400 PUSHA((jobject)pc);
2401 pc = base_pc+offset;
2403 NEXT_INSN;
2407 static void
2408 throw_internal_error (char *msg)
2410 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2413 static void
2414 throw_incompatible_class_change_error (jstring msg)
2416 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2419 #ifndef HANDLE_SEGV
2420 static java::lang::NullPointerException *null_pointer_exc;
2421 static void
2422 throw_null_pointer_exception ()
2424 if (null_pointer_exc == NULL)
2425 null_pointer_exc = new java::lang::NullPointerException;
2427 JvThrow (null_pointer_exc);
2429 #endif
2431 #endif // INTERPRETER