Daily bump.
[official-gcc.git] / libjava / interpret.cc
blobd6d29582ec909da882707cae5a2405e3c31c5ab9
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
51 #ifndef HANDLE_FPE
52 static void throw_arithmetic_exception ()
53 __attribute__ ((__noreturn__));
54 #endif
57 extern "C" double __ieee754_fmod __P((double,double));
59 static inline void dupx (_Jv_word *sp, int n, int x)
61 // first "slide" n+x elements n to the right
62 int top = n-1;
63 for (int i = 0; i < n+x; i++)
65 sp[(top-i)] = sp[(top-i)-n];
68 // next, copy the n top elements, n+x down
69 for (int i = 0; i < n; i++)
71 sp[top-(n+x)-i] = sp[top-i];
77 #define PUSHA(V) (sp++)->o = (V)
78 #define PUSHI(V) (sp++)->i = (V)
79 #define PUSHF(V) (sp++)->f = (V)
80 #if SIZEOF_VOID_P == 8
81 # define PUSHL(V) (sp->l = (V), sp += 2)
82 # define PUSHD(V) (sp->d = (V), sp += 2)
83 #else
84 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
85 (sp++)->ia[0] = w2.ia[0]; \
86 (sp++)->ia[0] = w2.ia[1]; } while (0)
87 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
88 (sp++)->ia[0] = w2.ia[0]; \
89 (sp++)->ia[0] = w2.ia[1]; } while (0)
90 #endif
92 #define POPA() ((--sp)->o)
93 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
94 #define POPF() ((jfloat) (--sp)->f)
95 #if SIZEOF_VOID_P == 8
96 # define POPL() (sp -= 2, (jlong) sp->l)
97 # define POPD() (sp -= 2, (jdouble) sp->d)
98 #else
99 # define POPL() ({ _Jv_word2 w2; \
100 w2.ia[1] = (--sp)->ia[0]; \
101 w2.ia[0] = (--sp)->ia[0]; w2.l; })
102 # define POPD() ({ _Jv_word2 w2; \
103 w2.ia[1] = (--sp)->ia[0]; \
104 w2.ia[0] = (--sp)->ia[0]; w2.d; })
105 #endif
107 #define LOADA(I) (sp++)->o = locals[I].o
108 #define LOADI(I) (sp++)->i = locals[I].i
109 #define LOADF(I) (sp++)->f = locals[I].f
110 #if SIZEOF_VOID_P == 8
111 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
112 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
113 #else
114 # define LOADL(I) do { jint __idx = (I); \
115 (sp++)->ia[0] = locals[__idx].ia[0]; \
116 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
117 } while (0)
118 # define LOADD(I) LOADL(I)
119 #endif
121 #define STOREA(I) locals[I].o = (--sp)->o
122 #define STOREI(I) locals[I].i = (--sp)->i
123 #define STOREF(I) locals[I].f = (--sp)->f
124 #if SIZEOF_VOID_P == 8
125 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
126 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
127 #else
128 # define STOREL(I) do { jint __idx = (I); \
129 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
130 locals[__idx].ia[0] = (--sp)->ia[0]; \
131 } while (0)
132 # define STORED(I) STOREL(I)
133 #endif
135 #define PEEKI(I) (locals+(I))->i
136 #define PEEKA(I) (locals+(I))->o
138 #define POKEI(I,V) ((locals+(I))->i = (V))
141 #define BINOPI(OP) { \
142 jint value2 = POPI(); \
143 jint value1 = POPI(); \
144 PUSHI(value1 OP value2); \
147 #define BINOPF(OP) { \
148 jfloat value2 = POPF(); \
149 jfloat value1 = POPF(); \
150 PUSHF(value1 OP value2); \
153 #define BINOPL(OP) { \
154 jlong value2 = POPL(); \
155 jlong value1 = POPL(); \
156 PUSHL(value1 OP value2); \
159 #define BINOPD(OP) { \
160 jdouble value2 = POPD(); \
161 jdouble value1 = POPD(); \
162 PUSHD(value1 OP value2); \
165 static inline jint get1s(unsigned char* loc) {
166 return *(signed char*)loc;
169 static inline jint get1u(unsigned char* loc) {
170 return *loc;
173 static inline jint get2s(unsigned char* loc) {
174 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
177 static inline jint get2u(unsigned char* loc) {
178 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
181 static jint get4(unsigned char* loc) {
182 return (((jint)(loc[0])) << 24)
183 | (((jint)(loc[1])) << 16)
184 | (((jint)(loc[2])) << 8)
185 | (((jint)(loc[3])) << 0);
189 #ifdef HANDLE_SEGV
190 #define NULLCHECK(X)
191 #else
192 #define NULLCHECK(X) \
193 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
194 #endif
196 #ifdef HANDLE_FPE
197 #define ZEROCHECK(X)
198 #else
199 #define ZEROCHECK(X) \
200 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
201 #endif
203 // this method starts the actual running of the method. It is inlined
204 // in three different variants in the static methods run_normal,
205 // run_sync_object and run_sync_class (see below). Those static methods
206 // are installed directly in the stub for this method (by
207 // _Jv_InterpMethod::ncode, in resolve.cc).
209 inline jobject
210 _Jv_InterpMethod::run (ffi_cif* cif,
211 void *retp,
212 ffi_raw *args,
213 _Jv_InterpMethodInvocation *inv)
215 inv->running = this;
216 inv->pc = bytecode ();
217 inv->sp = inv->stack_base ();
218 _Jv_word *locals = inv->local_base ();
220 /* Go straight at it! the ffi raw format matches the internal
221 stack representation exactly. At least, that's the idea.
223 memcpy ((void*) locals, (void*) args, args_raw_size);
225 next_segment:
227 jobject ex = NULL;
231 continue1 (inv);
233 catch (java::lang::Throwable *ex2)
235 ex = ex2;
238 if (ex == 0) // no exception...
240 /* define sp locally, so the POP? macros will pick it up */
241 _Jv_word *sp = inv->sp;
242 int rtype = cif->rtype->type;
244 if (rtype == FFI_TYPE_POINTER)
246 jobject r = POPA();
247 *(jobject*) retp = r;
248 return 0;
250 else if (rtype == FFI_TYPE_SINT32)
252 jint r = POPI();
253 *(jint*)retp = r;
254 return 0;
256 else if (rtype == FFI_TYPE_VOID)
258 return 0;
260 else switch (rtype)
262 case FFI_TYPE_FLOAT:
264 jfloat r = POPF();
265 *(jfloat*)retp = r;
266 return 0;
269 case FFI_TYPE_DOUBLE:
271 jdouble r = POPD();
272 *(jdouble*)retp = r;
273 return 0;
276 case FFI_TYPE_UINT8:
277 case FFI_TYPE_UINT16:
278 case FFI_TYPE_UINT32:
279 case FFI_TYPE_SINT8:
280 case FFI_TYPE_SINT16:
282 jint r = POPI();
283 *(jint*)retp = r;
284 return 0;
287 case FFI_TYPE_SINT64:
289 jlong r = POPL();
290 *(jlong*)retp = r;
291 return 0;
294 default:
295 throw_internal_error ("unknown return type");
299 /** handle an exception */
300 if ( find_exception (ex, inv) )
301 goto next_segment;
303 return ex;
306 bool _Jv_InterpMethod::find_exception (jobject ex,
307 _Jv_InterpMethodInvocation *inv)
309 int logical_pc = inv->pc - bytecode ();
310 _Jv_InterpException *exc = exceptions ();
311 jclass exc_class = ex->getClass ();
313 for (int i = 0; i < exc_count; i++)
315 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
317 jclass handler;
319 if (exc[i].handler_type != 0)
320 handler = (_Jv_ResolvePoolEntry (defining_class,
321 exc[i].handler_type)).clazz;
322 else
323 handler = NULL;
325 if (handler==NULL || handler->isAssignableFrom (exc_class))
327 inv->pc = bytecode () + exc[i].handler_pc;
328 inv->sp = inv->stack_base (); // reset stack
329 (inv->sp++)->o = ex; // push exception
330 return true;
334 return false;
337 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
338 void* ret,
339 ffi_raw * args,
340 void* __this)
342 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
344 // we do the alloca of the method invocation here, to allow the method
345 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
346 int storage_size = _this->max_stack+_this->max_locals;
347 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
348 alloca (sizeof (_Jv_InterpMethodInvocation)
349 + storage_size * sizeof (_Jv_word));
351 jobject ex = _this->run (cif, ret, args, inv);
352 if (ex != 0) _Jv_Throw (ex);
355 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
356 void* ret,
357 ffi_raw * args,
358 void* __this)
360 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
361 jobject rcv = (jobject)args[0].ptr;
363 int storage_size = _this->max_stack+_this->max_locals;
364 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
365 alloca (sizeof (_Jv_InterpMethodInvocation)
366 + storage_size * sizeof (_Jv_word));
368 _Jv_MonitorEnter (rcv);
369 jobject ex = _this->run (cif, ret, args, inv);
370 _Jv_MonitorExit (rcv);
372 if (ex != 0) _Jv_Throw (ex);
375 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
376 void* ret,
377 ffi_raw * args,
378 void* __this)
380 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
381 jclass sync = _this->defining_class;
383 int storage_size = _this->max_stack+_this->max_locals;
384 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
385 alloca (sizeof (_Jv_InterpMethodInvocation)
386 + storage_size * sizeof (_Jv_word));
388 _Jv_MonitorEnter (sync);
389 jobject ex = _this->run (cif, ret, args, inv);
390 _Jv_MonitorExit (sync);
392 if (ex != 0) _Jv_Throw (ex);
396 This proceeds execution, as designated in "inv". If an exception
397 happens, then it is simply thrown, and handled in Java. Thus, the pc
398 needs to be stored in the inv->pc at all times, so we can figure
399 out which handler (if any) to invoke.
401 One design issue, which I have not completely considered, is if it
402 should be possible to have interpreted classes linked in! Seldom used
403 (or non-critical) classes could reasonably be interpreted.
407 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
409 using namespace java::lang::reflect;
411 register _Jv_word *sp = inv->sp;
412 register unsigned char *pc = inv->pc;
413 _Jv_word *locals = inv->local_base ();
415 _Jv_word *pool_data = defining_class->constants.data;
417 /* these two are used in the invokeXXX instructions */
418 void (*fun)(...);
419 _Jv_ResolvedMethod* rmeth;
421 #define INSN_LABEL(op) &&insn_##op
422 #define GOTO_INSN(op) goto *(insn_target[op])
424 static const void *const insn_target[] =
426 INSN_LABEL(nop),
427 INSN_LABEL(aconst_null),
428 INSN_LABEL(iconst_m1),
429 INSN_LABEL(iconst_0),
430 INSN_LABEL(iconst_1),
431 INSN_LABEL(iconst_2),
432 INSN_LABEL(iconst_3),
433 INSN_LABEL(iconst_4),
434 INSN_LABEL(iconst_5),
435 INSN_LABEL(lconst_0),
436 INSN_LABEL(lconst_1),
437 INSN_LABEL(fconst_0),
438 INSN_LABEL(fconst_1),
439 INSN_LABEL(fconst_2),
440 INSN_LABEL(dconst_0),
441 INSN_LABEL(dconst_1),
442 INSN_LABEL(bipush),
443 INSN_LABEL(sipush),
444 INSN_LABEL(ldc),
445 INSN_LABEL(ldc_w),
446 INSN_LABEL(ldc2_w),
447 INSN_LABEL(iload),
448 INSN_LABEL(lload),
449 INSN_LABEL(fload),
450 INSN_LABEL(dload),
451 INSN_LABEL(aload),
452 INSN_LABEL(iload_0),
453 INSN_LABEL(iload_1),
454 INSN_LABEL(iload_2),
455 INSN_LABEL(iload_3),
456 INSN_LABEL(lload_0),
457 INSN_LABEL(lload_1),
458 INSN_LABEL(lload_2),
459 INSN_LABEL(lload_3),
460 INSN_LABEL(fload_0),
461 INSN_LABEL(fload_1),
462 INSN_LABEL(fload_2),
463 INSN_LABEL(fload_3),
464 INSN_LABEL(dload_0),
465 INSN_LABEL(dload_1),
466 INSN_LABEL(dload_2),
467 INSN_LABEL(dload_3),
468 INSN_LABEL(aload_0),
469 INSN_LABEL(aload_1),
470 INSN_LABEL(aload_2),
471 INSN_LABEL(aload_3),
472 INSN_LABEL(iaload),
473 INSN_LABEL(laload),
474 INSN_LABEL(faload),
475 INSN_LABEL(daload),
476 INSN_LABEL(aaload),
477 INSN_LABEL(baload),
478 INSN_LABEL(caload),
479 INSN_LABEL(saload),
480 INSN_LABEL(istore),
481 INSN_LABEL(lstore),
482 INSN_LABEL(fstore),
483 INSN_LABEL(dstore),
484 INSN_LABEL(astore),
485 INSN_LABEL(istore_0),
486 INSN_LABEL(istore_1),
487 INSN_LABEL(istore_2),
488 INSN_LABEL(istore_3),
489 INSN_LABEL(lstore_0),
490 INSN_LABEL(lstore_1),
491 INSN_LABEL(lstore_2),
492 INSN_LABEL(lstore_3),
493 INSN_LABEL(fstore_0),
494 INSN_LABEL(fstore_1),
495 INSN_LABEL(fstore_2),
496 INSN_LABEL(fstore_3),
497 INSN_LABEL(dstore_0),
498 INSN_LABEL(dstore_1),
499 INSN_LABEL(dstore_2),
500 INSN_LABEL(dstore_3),
501 INSN_LABEL(astore_0),
502 INSN_LABEL(astore_1),
503 INSN_LABEL(astore_2),
504 INSN_LABEL(astore_3),
505 INSN_LABEL(iastore),
506 INSN_LABEL(lastore),
507 INSN_LABEL(fastore),
508 INSN_LABEL(dastore),
509 INSN_LABEL(aastore),
510 INSN_LABEL(bastore),
511 INSN_LABEL(castore),
512 INSN_LABEL(sastore),
513 INSN_LABEL(pop),
514 INSN_LABEL(pop2),
515 INSN_LABEL(dup),
516 INSN_LABEL(dup_x1),
517 INSN_LABEL(dup_x2),
518 INSN_LABEL(dup2),
519 INSN_LABEL(dup2_x1),
520 INSN_LABEL(dup2_x2),
521 INSN_LABEL(swap),
522 INSN_LABEL(iadd),
523 INSN_LABEL(ladd),
524 INSN_LABEL(fadd),
525 INSN_LABEL(dadd),
526 INSN_LABEL(isub),
527 INSN_LABEL(lsub),
528 INSN_LABEL(fsub),
529 INSN_LABEL(dsub),
530 INSN_LABEL(imul),
531 INSN_LABEL(lmul),
532 INSN_LABEL(fmul),
533 INSN_LABEL(dmul),
534 INSN_LABEL(idiv),
535 INSN_LABEL(ldiv),
536 INSN_LABEL(fdiv),
537 INSN_LABEL(ddiv),
538 INSN_LABEL(irem),
539 INSN_LABEL(lrem),
540 INSN_LABEL(frem),
541 INSN_LABEL(drem),
542 INSN_LABEL(ineg),
543 INSN_LABEL(lneg),
544 INSN_LABEL(fneg),
545 INSN_LABEL(dneg),
546 INSN_LABEL(ishl),
547 INSN_LABEL(lshl),
548 INSN_LABEL(ishr),
549 INSN_LABEL(lshr),
550 INSN_LABEL(iushr),
551 INSN_LABEL(lushr),
552 INSN_LABEL(iand),
553 INSN_LABEL(land),
554 INSN_LABEL(ior),
555 INSN_LABEL(lor),
556 INSN_LABEL(ixor),
557 INSN_LABEL(lxor),
558 INSN_LABEL(iinc),
559 INSN_LABEL(i2l),
560 INSN_LABEL(i2f),
561 INSN_LABEL(i2d),
562 INSN_LABEL(l2i),
563 INSN_LABEL(l2f),
564 INSN_LABEL(l2d),
565 INSN_LABEL(f2i),
566 INSN_LABEL(f2l),
567 INSN_LABEL(f2d),
568 INSN_LABEL(d2i),
569 INSN_LABEL(d2l),
570 INSN_LABEL(d2f),
571 INSN_LABEL(i2b),
572 INSN_LABEL(i2c),
573 INSN_LABEL(i2s),
574 INSN_LABEL(lcmp),
575 INSN_LABEL(fcmpl),
576 INSN_LABEL(fcmpg),
577 INSN_LABEL(dcmpl),
578 INSN_LABEL(dcmpg),
579 INSN_LABEL(ifeq),
580 INSN_LABEL(ifne),
581 INSN_LABEL(iflt),
582 INSN_LABEL(ifge),
583 INSN_LABEL(ifgt),
584 INSN_LABEL(ifle),
585 INSN_LABEL(if_icmpeq),
586 INSN_LABEL(if_icmpne),
587 INSN_LABEL(if_icmplt),
588 INSN_LABEL(if_icmpge),
589 INSN_LABEL(if_icmpgt),
590 INSN_LABEL(if_icmple),
591 INSN_LABEL(if_acmpeq),
592 INSN_LABEL(if_acmpne),
593 INSN_LABEL(goto),
594 INSN_LABEL(jsr),
595 INSN_LABEL(ret),
596 INSN_LABEL(tableswitch),
597 INSN_LABEL(lookupswitch),
598 INSN_LABEL(ireturn),
599 INSN_LABEL(lreturn),
600 INSN_LABEL(freturn),
601 INSN_LABEL(dreturn),
602 INSN_LABEL(areturn),
603 INSN_LABEL(return),
604 INSN_LABEL(getstatic),
605 INSN_LABEL(putstatic),
606 INSN_LABEL(getfield),
607 INSN_LABEL(putfield),
608 INSN_LABEL(invokevirtual),
609 INSN_LABEL(invokespecial),
610 INSN_LABEL(invokestatic),
611 INSN_LABEL(invokeinterface),
612 0, /* op_xxxunusedxxx1, */
613 INSN_LABEL(new),
614 INSN_LABEL(newarray),
615 INSN_LABEL(anewarray),
616 INSN_LABEL(arraylength),
617 INSN_LABEL(athrow),
618 INSN_LABEL(checkcast),
619 INSN_LABEL(instanceof),
620 INSN_LABEL(monitorenter),
621 INSN_LABEL(monitorexit),
622 INSN_LABEL(wide),
623 INSN_LABEL(multianewarray),
624 INSN_LABEL(ifnull),
625 INSN_LABEL(ifnonnull),
626 INSN_LABEL(goto_w),
627 INSN_LABEL(jsr_w),
630 #define SAVE_PC inv->pc = pc-1
632 /* If the macro INLINE_SWITCH is not defined, then the main loop
633 operates as one big (normal) switch statement. If it is defined,
634 then the case selection is performed `inline' in the end of the
635 code for each case. The latter saves a native branch instruction
636 for each java-instruction, but expands the code size somewhat.
638 NOTE: On i386 defining INLINE_SWITCH improves over all
639 performance approximately seven percent, but it may be different
640 for other machines. At some point, this may be made into a proper
641 configuration parameter. */
643 #define INLINE_SWITCH
645 #ifdef INLINE_SWITCH
647 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
650 NEXT_INSN;
651 #else
653 #define NEXT_INSN goto next_insn
655 next_insn:
656 GOTO_INSN (*pc++);
658 #endif
660 /* The first few instructions here are ordered according to their
661 frequency, in the hope that this will improve code locality a
662 little. */
664 insn_aload_0: // 0x2a
665 LOADA(0);
666 NEXT_INSN;
668 insn_iload: // 0x15
669 LOADI (get1u (pc++));
670 NEXT_INSN;
672 insn_iload_1: // 0x1b
673 LOADI (1);
674 NEXT_INSN;
676 insn_invokevirtual: // 0xb6
677 SAVE_PC;
679 int index = get2u (pc); pc += 2;
681 /* _Jv_ResolvePoolEntry returns immediately if the value already
682 * is resolved. If we want to clutter up the code here to gain
683 * a little performance, then we can check the corresponding bit
684 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
685 * don't think it is worth it. */
687 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
689 sp -= rmeth->stack_item_count;
690 NULLCHECK(sp[0]);
692 if (rmeth->vtable_index == -1)
694 // final methods do not appear in the vtable,
695 // if it does not appear in the superclass.
696 fun = (void (*) (...)) rmeth->method->ncode;
698 else
700 jobject rcv = sp[0].o;
701 _Jv_VTable *table = *(_Jv_VTable**)rcv;
702 fun = (void (*) (...))table->method[rmeth->vtable_index];
705 goto perform_invoke;
707 perform_invoke:
709 /* here goes the magic again... */
710 ffi_cif *cif = &rmeth->cif;
711 ffi_raw *raw = (ffi_raw*) sp;
713 jdouble rvalue;
715 #if FFI_NATIVE_RAW_API
716 /* We assume that this is only implemented if it's correct */
717 /* to use it here. On a 64 bit machine, it never is. */
718 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
719 #else
720 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
721 #endif
723 int rtype = cif->rtype->type;
725 /* the likelyhood of object, int, or void return is very high,
726 * so those are checked before the switch */
727 if (rtype == FFI_TYPE_POINTER)
729 PUSHA (*(jobject*)&rvalue);
731 else if (rtype == FFI_TYPE_SINT32)
733 PUSHI (*(jint*)&rvalue);
735 else if (rtype == FFI_TYPE_VOID)
737 /* skip */
739 else switch (rtype)
741 case FFI_TYPE_SINT8:
743 jbyte value = (*(jint*)&rvalue) & 0xff;
744 PUSHI (value);
746 break;
748 case FFI_TYPE_SINT16:
750 jshort value = (*(jint*)&rvalue) & 0xffff;
751 PUSHI (value);
753 break;
755 case FFI_TYPE_UINT16:
757 jint value = (*(jint*)&rvalue) & 0xffff;
758 PUSHI (value);
760 break;
762 case FFI_TYPE_FLOAT:
763 PUSHF (*(jfloat*)&rvalue);
764 break;
766 case FFI_TYPE_DOUBLE:
767 PUSHD (rvalue);
768 break;
770 case FFI_TYPE_SINT64:
771 PUSHL (*(jlong*)&rvalue);
772 break;
774 default:
775 throw_internal_error ("unknown return type in invokeXXX");
779 NEXT_INSN;
782 insn_nop:
783 NEXT_INSN;
785 insn_aconst_null:
786 PUSHA (NULL);
787 NEXT_INSN;
789 insn_iconst_m1:
790 PUSHI (-1);
791 NEXT_INSN;
793 insn_iconst_0:
794 PUSHI (0);
795 NEXT_INSN;
797 insn_iconst_1:
798 PUSHI (1);
799 NEXT_INSN;
801 insn_iconst_2:
802 PUSHI (2);
803 NEXT_INSN;
805 insn_iconst_3:
806 PUSHI (3);
807 NEXT_INSN;
809 insn_iconst_4:
810 PUSHI (4);
811 NEXT_INSN;
813 insn_iconst_5:
814 PUSHI (5);
815 NEXT_INSN;
817 insn_lconst_0:
818 PUSHL (0);
819 NEXT_INSN;
821 insn_lconst_1:
822 PUSHL (1);
823 NEXT_INSN;
825 insn_fconst_0:
826 PUSHF (0);
827 NEXT_INSN;
829 insn_fconst_1:
830 PUSHF (1);
831 NEXT_INSN;
833 insn_fconst_2:
834 PUSHF (2);
835 NEXT_INSN;
837 insn_dconst_0:
838 PUSHD (0);
839 NEXT_INSN;
841 insn_dconst_1:
842 PUSHD (1);
843 NEXT_INSN;
845 insn_bipush:
846 PUSHI (get1s(pc++));
847 NEXT_INSN;
849 insn_sipush:
850 PUSHI (get2s(pc)); pc += 2;
851 NEXT_INSN;
853 insn_ldc:
855 int index = get1u (pc++);
856 PUSHA(pool_data[index].o);
858 NEXT_INSN;
860 insn_ldc_w:
862 int index = get2u (pc); pc += 2;
863 PUSHA(pool_data[index].o);
865 NEXT_INSN;
867 insn_ldc2_w:
869 int index = get2u (pc); pc += 2;
870 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
871 sp += 2;
873 NEXT_INSN;
875 insn_lload:
876 LOADL (get1u (pc++));
877 NEXT_INSN;
879 insn_fload:
880 LOADF (get1u (pc++));
881 NEXT_INSN;
883 insn_dload:
884 LOADD (get1u (pc++));
885 NEXT_INSN;
887 insn_aload:
888 LOADA (get1u (pc++));
889 NEXT_INSN;
891 insn_iload_0:
892 LOADI (0);
893 NEXT_INSN;
895 insn_iload_2:
896 LOADI (2);
897 NEXT_INSN;
899 insn_iload_3:
900 LOADI (3);
901 NEXT_INSN;
903 insn_lload_0:
904 LOADL (0);
905 NEXT_INSN;
907 insn_lload_1:
908 LOADL (1);
909 NEXT_INSN;
911 insn_lload_2:
912 LOADL (2);
913 NEXT_INSN;
915 insn_lload_3:
916 LOADL (3);
917 NEXT_INSN;
919 insn_fload_0:
920 LOADF (0);
921 NEXT_INSN;
923 insn_fload_1:
924 LOADF (1);
925 NEXT_INSN;
927 insn_fload_2:
928 LOADF (2);
929 NEXT_INSN;
931 insn_fload_3:
932 LOADF (3);
933 NEXT_INSN;
935 insn_dload_0:
936 LOADD (0);
937 NEXT_INSN;
939 insn_dload_1:
940 LOADD (1);
941 NEXT_INSN;
943 insn_dload_2:
944 LOADD (2);
945 NEXT_INSN;
947 insn_dload_3:
948 LOADD (3);
949 NEXT_INSN;
951 insn_aload_1:
952 LOADA(1);
953 NEXT_INSN;
955 insn_aload_2:
956 LOADA(2);
957 NEXT_INSN;
959 insn_aload_3:
960 LOADA(3);
961 NEXT_INSN;
963 insn_iaload:
964 SAVE_PC;
966 jint index = POPI();
967 jintArray arr = (jintArray) POPA();
968 NULLCHECK (arr);
969 if (index < 0 || index >= arr->length)
971 _Jv_ThrowBadArrayIndex (index);
973 PUSHI( elements(arr)[index] );
975 NEXT_INSN;
977 insn_laload:
978 SAVE_PC;
980 jint index = POPI();
981 jlongArray arr = (jlongArray) POPA();
982 NULLCHECK (arr);
983 if (index < 0 || index >= arr->length)
985 _Jv_ThrowBadArrayIndex (index);
987 PUSHL( elements(arr)[index] );
989 NEXT_INSN;
991 insn_faload:
992 SAVE_PC;
994 jint index = POPI();
995 jfloatArray arr = (jfloatArray) POPA();
996 NULLCHECK (arr);
997 if (index < 0 || index >= arr->length)
999 _Jv_ThrowBadArrayIndex (index);
1001 PUSHF( elements(arr)[index] );
1003 NEXT_INSN;
1005 insn_daload:
1006 SAVE_PC;
1008 jint index = POPI();
1009 jdoubleArray arr = (jdoubleArray) POPA();
1010 NULLCHECK (arr);
1011 if (index < 0 || index >= arr->length)
1013 _Jv_ThrowBadArrayIndex (index);
1015 PUSHD( elements(arr)[index] );
1017 NEXT_INSN;
1019 insn_aaload:
1020 SAVE_PC;
1022 jint index = POPI();
1023 jobjectArray arr = (jobjectArray) POPA();
1024 NULLCHECK (arr);
1025 if (index < 0 || index >= arr->length)
1027 _Jv_ThrowBadArrayIndex (index);
1029 PUSHA( elements(arr)[index] );
1031 NEXT_INSN;
1033 insn_baload:
1034 SAVE_PC;
1036 jint index = POPI();
1037 jbyteArray arr = (jbyteArray) POPA();
1038 NULLCHECK (arr);
1039 if (index < 0 || index >= arr->length)
1041 _Jv_ThrowBadArrayIndex (index);
1043 PUSHI( elements(arr)[index] );
1045 NEXT_INSN;
1047 insn_caload:
1048 SAVE_PC;
1050 jint index = POPI();
1051 jcharArray arr = (jcharArray) POPA();
1052 NULLCHECK (arr);
1053 if (index < 0 || index >= arr->length)
1055 _Jv_ThrowBadArrayIndex (index);
1057 PUSHI( elements(arr)[index] );
1059 NEXT_INSN;
1061 insn_saload:
1062 SAVE_PC;
1064 jint index = POPI();
1065 jshortArray arr = (jshortArray) POPA();
1066 NULLCHECK (arr);
1067 if (index < 0 || index >= arr->length)
1069 _Jv_ThrowBadArrayIndex (index);
1071 PUSHI( elements(arr)[index] );
1073 NEXT_INSN;
1075 insn_istore:
1076 STOREI (get1u (pc++));
1077 NEXT_INSN;
1079 insn_lstore:
1080 STOREL (get1u (pc++));
1081 NEXT_INSN;
1083 insn_fstore:
1084 STOREF (get1u (pc++));
1085 NEXT_INSN;
1087 insn_dstore:
1088 STORED (get1u (pc++));
1089 NEXT_INSN;
1091 insn_astore:
1092 STOREA (get1u (pc++));
1093 NEXT_INSN;
1095 insn_istore_0:
1096 STOREI (0);
1097 NEXT_INSN;
1099 insn_istore_1:
1100 STOREI (1);
1101 NEXT_INSN;
1103 insn_istore_2:
1104 STOREI (2);
1105 NEXT_INSN;
1107 insn_istore_3:
1108 STOREI (3);
1109 NEXT_INSN;
1111 insn_lstore_0:
1112 STOREL (0);
1113 NEXT_INSN;
1115 insn_lstore_1:
1116 STOREL (1);
1117 NEXT_INSN;
1119 insn_lstore_2:
1120 STOREL (2);
1121 NEXT_INSN;
1123 insn_lstore_3:
1124 STOREL (3);
1125 NEXT_INSN;
1127 insn_fstore_0:
1128 STOREF (0);
1129 NEXT_INSN;
1131 insn_fstore_1:
1132 STOREF (1);
1133 NEXT_INSN;
1135 insn_fstore_2:
1136 STOREF (2);
1137 NEXT_INSN;
1139 insn_fstore_3:
1140 STOREF (3);
1141 NEXT_INSN;
1143 insn_dstore_0:
1144 STORED (0);
1145 NEXT_INSN;
1147 insn_dstore_1:
1148 STORED (1);
1149 NEXT_INSN;
1151 insn_dstore_2:
1152 STORED (2);
1153 NEXT_INSN;
1155 insn_dstore_3:
1156 STORED (3);
1157 NEXT_INSN;
1159 insn_astore_0:
1160 STOREA(0);
1161 NEXT_INSN;
1163 insn_astore_1:
1164 STOREA(1);
1165 NEXT_INSN;
1167 insn_astore_2:
1168 STOREA(2);
1169 NEXT_INSN;
1171 insn_astore_3:
1172 STOREA(3);
1173 NEXT_INSN;
1175 insn_iastore:
1176 SAVE_PC;
1178 jint value = POPI();
1179 jint index = POPI();
1180 jintArray arr = (jintArray) POPA();
1181 NULLCHECK (arr);
1182 if (index < 0 || index >= arr->length)
1184 _Jv_ThrowBadArrayIndex (index);
1186 elements(arr)[index] = value;
1188 NEXT_INSN;
1190 insn_lastore:
1191 SAVE_PC;
1193 jlong value = POPL();
1194 jint index = POPI();
1195 jlongArray arr = (jlongArray) POPA();
1196 NULLCHECK (arr);
1197 if (index < 0 || index >= arr->length)
1199 _Jv_ThrowBadArrayIndex (index);
1201 elements(arr)[index] = value;
1203 NEXT_INSN;
1205 insn_fastore:
1206 SAVE_PC;
1208 jfloat value = POPF();
1209 jint index = POPI();
1210 jfloatArray arr = (jfloatArray) POPA();
1211 NULLCHECK (arr);
1212 if (index < 0 || index >= arr->length)
1214 _Jv_ThrowBadArrayIndex (index);
1216 elements(arr)[index] = value;
1218 NEXT_INSN;
1220 insn_dastore:
1221 SAVE_PC;
1223 jdouble value = POPD();
1224 jint index = POPI();
1225 jdoubleArray arr = (jdoubleArray) POPA();
1226 NULLCHECK (arr);
1227 if (index < 0 || index >= arr->length)
1229 _Jv_ThrowBadArrayIndex (index);
1231 elements(arr)[index] = value;
1233 NEXT_INSN;
1235 insn_aastore:
1236 SAVE_PC;
1238 jobject value = POPA();
1239 jint index = POPI();
1240 jobjectArray arr = (jobjectArray) POPA();
1241 NULLCHECK (arr);
1242 if (index < 0 || index >= arr->length)
1244 _Jv_ThrowBadArrayIndex (index);
1246 _Jv_CheckArrayStore (arr, value);
1247 elements(arr)[index] = value;
1249 NEXT_INSN;
1251 insn_bastore:
1252 SAVE_PC;
1254 jbyte value = (jbyte) POPI();
1255 jint index = POPI();
1256 jbyteArray arr = (jbyteArray) POPA();
1257 NULLCHECK (arr);
1258 if (index < 0 || index >= arr->length)
1260 _Jv_ThrowBadArrayIndex (index);
1262 elements(arr)[index] = value;
1264 NEXT_INSN;
1266 insn_castore:
1267 SAVE_PC;
1269 jchar value = (jchar) POPI();
1270 jint index = POPI();
1271 jcharArray arr = (jcharArray) POPA();
1272 NULLCHECK (arr);
1273 if (index < 0 || index >= arr->length)
1275 _Jv_ThrowBadArrayIndex (index);
1277 elements(arr)[index] = value;
1279 NEXT_INSN;
1281 insn_sastore:
1282 SAVE_PC;
1284 jshort value = (jshort) POPI();
1285 jint index = POPI();
1286 jshortArray arr = (jshortArray) POPA();
1287 NULLCHECK (arr);
1288 if (index < 0 || index >= arr->length)
1290 _Jv_ThrowBadArrayIndex (index);
1292 elements(arr)[index] = value;
1294 NEXT_INSN;
1296 insn_pop:
1297 sp -= 1;
1298 NEXT_INSN;
1300 insn_pop2:
1301 sp -= 2;
1302 NEXT_INSN;
1304 insn_dup:
1305 sp[0] = sp[-1];
1306 sp += 1;
1307 NEXT_INSN;
1309 insn_dup_x1:
1310 dupx (sp, 1, 1); sp+=1;
1311 NEXT_INSN;
1313 insn_dup_x2:
1314 dupx (sp, 1, 2); sp+=1;
1315 NEXT_INSN;
1317 insn_dup2:
1318 sp[0] = sp[-2];
1319 sp[1] = sp[-1];
1320 sp += 2;
1321 NEXT_INSN;
1323 insn_dup2_x1:
1324 dupx (sp, 2, 1); sp+=2;
1325 NEXT_INSN;
1327 insn_dup2_x2:
1328 dupx (sp, 2, 2); sp+=2;
1329 NEXT_INSN;
1331 insn_swap:
1333 jobject tmp1 = POPA();
1334 jobject tmp2 = POPA();
1335 PUSHA (tmp1);
1336 PUSHA (tmp2);
1338 NEXT_INSN;
1340 insn_iadd:
1341 BINOPI(+);
1342 NEXT_INSN;
1344 insn_ladd:
1345 BINOPL(+);
1346 NEXT_INSN;
1348 insn_fadd:
1349 BINOPF(+);
1350 NEXT_INSN;
1352 insn_dadd:
1353 BINOPD(+);
1354 NEXT_INSN;
1356 insn_isub:
1357 BINOPI(-);
1358 NEXT_INSN;
1360 insn_lsub:
1361 BINOPL(-);
1362 NEXT_INSN;
1364 insn_fsub:
1365 BINOPF(-);
1366 NEXT_INSN;
1368 insn_dsub:
1369 BINOPD(-);
1370 NEXT_INSN;
1372 insn_imul:
1373 BINOPI(*);
1374 NEXT_INSN;
1376 insn_lmul:
1377 BINOPL(*);
1378 NEXT_INSN;
1380 insn_fmul:
1381 BINOPF(*);
1382 NEXT_INSN;
1384 insn_dmul:
1385 BINOPD(*);
1386 NEXT_INSN;
1388 insn_idiv:
1389 SAVE_PC;
1391 jint value2 = POPI();
1392 jint value1 = POPI();
1393 ZEROCHECK (value2);
1394 jint res = value1 / value2;
1395 PUSHI (res);
1397 NEXT_INSN;
1399 insn_ldiv:
1400 SAVE_PC;
1402 jlong value2 = POPL();
1403 jlong value1 = POPL();
1404 ZEROCHECK (value2);
1405 jlong res = value1 / value2;
1406 PUSHL (res);
1408 NEXT_INSN;
1410 insn_fdiv:
1411 SAVE_PC;
1413 jfloat value2 = POPF();
1414 jfloat value1 = POPF();
1415 ZEROCHECK (value2);
1416 jfloat res = value1 / value2;
1417 PUSHF (res);
1419 NEXT_INSN;
1421 insn_ddiv:
1422 SAVE_PC;
1424 jdouble value2 = POPD();
1425 jdouble value1 = POPD();
1426 ZEROCHECK (value2);
1427 jdouble res = value1 / value2;
1428 PUSHD (res);
1430 NEXT_INSN;
1432 insn_irem:
1433 SAVE_PC;
1435 jint value2 = POPI();
1436 jint value1 = POPI();
1437 ZEROCHECK (value2);
1438 jint res = value1 % value2;
1439 PUSHI (res);
1441 NEXT_INSN;
1443 insn_lrem:
1444 SAVE_PC;
1446 jlong value2 = POPL();
1447 jlong value1 = POPL();
1448 ZEROCHECK (value2);
1449 jlong res = value1 % value2;
1450 PUSHL (res);
1452 NEXT_INSN;
1454 insn_frem:
1455 SAVE_PC;
1457 jfloat value2 = POPF();
1458 jfloat value1 = POPF();
1459 ZEROCHECK (value2);
1460 jfloat res = __ieee754_fmod (value1, value2);
1461 PUSHF (res);
1463 NEXT_INSN;
1465 insn_drem:
1466 SAVE_PC;
1468 jdouble value2 = POPD();
1469 jdouble value1 = POPD();
1470 ZEROCHECK (value2);
1471 jdouble res = __ieee754_fmod (value1, value2);
1472 PUSHD (res);
1474 NEXT_INSN;
1476 insn_ineg:
1478 jint value = POPI();
1479 PUSHI (value * -1);
1481 NEXT_INSN;
1483 insn_lneg:
1485 jlong value = POPL();
1486 PUSHL (value * -1);
1488 NEXT_INSN;
1490 insn_fneg:
1492 jfloat value = POPF();
1493 PUSHF (value * -1);
1495 NEXT_INSN;
1497 insn_dneg:
1499 jdouble value = POPD();
1500 PUSHD (value * -1);
1502 NEXT_INSN;
1504 insn_ishl:
1506 jint shift = (POPI() & 0x1f);
1507 jint value = POPI();
1508 PUSHI (value << shift);
1510 NEXT_INSN;
1512 insn_lshl:
1514 jint shift = (POPI() & 0x3f);
1515 jlong value = POPL();
1516 PUSHL (value << shift);
1518 NEXT_INSN;
1520 insn_ishr:
1522 jint shift = (POPI() & 0x1f);
1523 jint value = POPI();
1524 PUSHI (value >> shift);
1526 NEXT_INSN;
1528 insn_lshr:
1530 jint shift = (POPI() & 0x3f);
1531 jlong value = POPL();
1532 PUSHL (value >> shift);
1534 NEXT_INSN;
1536 insn_iushr:
1538 jint shift = (POPI() & 0x1f);
1539 unsigned long value = POPI();
1540 PUSHI ((jint) (value >> shift));
1542 NEXT_INSN;
1544 insn_lushr:
1546 jint shift = (POPI() & 0x3f);
1547 UINT64 value = (UINT64) POPL();
1548 PUSHL ((value >> shift));
1550 NEXT_INSN;
1552 insn_iand:
1553 BINOPI (&);
1554 NEXT_INSN;
1556 insn_land:
1557 BINOPL (&);
1558 NEXT_INSN;
1560 insn_ior:
1561 BINOPI (|);
1562 NEXT_INSN;
1564 insn_lor:
1565 BINOPL (|);
1566 NEXT_INSN;
1568 insn_ixor:
1569 BINOPI (^);
1570 NEXT_INSN;
1572 insn_lxor:
1573 BINOPL (^);
1574 NEXT_INSN;
1576 insn_iinc:
1578 jint index = get1u (pc++);
1579 jint amount = get1s (pc++);
1580 locals[index].i += amount;
1582 NEXT_INSN;
1584 insn_i2l:
1585 {jlong value = POPI(); PUSHL (value);}
1586 NEXT_INSN;
1588 insn_i2f:
1589 {jfloat value = POPI(); PUSHF (value);}
1590 NEXT_INSN;
1592 insn_i2d:
1593 {jdouble value = POPI(); PUSHD (value);}
1594 NEXT_INSN;
1596 insn_l2i:
1597 {jint value = POPL(); PUSHI (value);}
1598 NEXT_INSN;
1600 insn_l2f:
1601 {jfloat value = POPL(); PUSHF (value);}
1602 NEXT_INSN;
1604 insn_l2d:
1605 {jdouble value = POPL(); PUSHD (value);}
1606 NEXT_INSN;
1608 insn_f2i:
1609 { jint value = (jint)POPF (); PUSHI(value); }
1610 NEXT_INSN;
1612 insn_f2l:
1613 { jlong value = (jlong)POPF (); PUSHL(value); }
1614 NEXT_INSN;
1616 insn_f2d:
1617 { jdouble value = POPF (); PUSHD(value); }
1618 NEXT_INSN;
1620 insn_d2i:
1621 { jint value = (jint)POPD (); PUSHI(value); }
1622 NEXT_INSN;
1624 insn_d2l:
1625 { jlong value = (jlong)POPD (); PUSHL(value); }
1626 NEXT_INSN;
1628 insn_d2f:
1629 { jfloat value = POPD (); PUSHF(value); }
1630 NEXT_INSN;
1632 insn_i2b:
1633 { jbyte value = POPI (); PUSHI(value); }
1634 NEXT_INSN;
1636 insn_i2c:
1637 { jchar value = POPI (); PUSHI(value); }
1638 NEXT_INSN;
1640 insn_i2s:
1641 { jshort value = POPI (); PUSHI(value); }
1642 NEXT_INSN;
1644 insn_lcmp:
1646 jlong value2 = POPL ();
1647 jlong value1 = POPL ();
1648 if (value1 > value2)
1649 { PUSHI (1); }
1650 else if (value1 == value2)
1651 { PUSHI (0); }
1652 else
1653 { PUSHI (-1); }
1655 NEXT_INSN;
1657 insn_fcmpl:
1658 insn_fcmpg:
1660 jfloat value2 = POPF ();
1661 jfloat value1 = POPF ();
1662 if (value1 > value2)
1663 PUSHI (1);
1664 else if (value1 == value2)
1665 PUSHI (0);
1666 else if (value1 < value2)
1667 PUSHI (-1);
1668 else if ((*(pc-1)) == op_fcmpg)
1669 PUSHI (1);
1670 else
1671 PUSHI (-1);
1673 NEXT_INSN;
1675 insn_dcmpl:
1676 insn_dcmpg:
1678 jdouble value2 = POPD ();
1679 jdouble value1 = POPD ();
1680 if (value1 > value2)
1681 PUSHI (1);
1682 else if (value1 == value2)
1683 PUSHI (0);
1684 else if (value1 < value2)
1685 PUSHI (-1);
1686 else if ((*(pc-1)) == op_dcmpg)
1687 PUSHI (1);
1688 else
1689 PUSHI (-1);
1691 NEXT_INSN;
1693 insn_ifeq:
1695 jint offset = get2s (pc);
1696 if (POPI() == 0)
1697 pc = pc-1+offset;
1698 else
1699 pc = pc+2;
1701 NEXT_INSN;
1703 insn_ifne:
1705 jint offset = get2s (pc);
1706 if (POPI() != 0)
1707 pc = pc-1+offset;
1708 else
1709 pc = pc+2;
1711 NEXT_INSN;
1713 insn_iflt:
1715 jint offset = get2s (pc);
1716 if (POPI() < 0)
1717 pc = pc-1+offset;
1718 else
1719 pc = pc+2;
1721 NEXT_INSN;
1723 insn_ifge:
1725 jint offset = get2s (pc);
1726 if (POPI() >= 0)
1727 pc = pc-1+offset;
1728 else
1729 pc = pc+2;
1731 NEXT_INSN;
1733 insn_ifgt:
1735 jint offset = get2s (pc);
1736 if (POPI() > 0)
1737 pc = pc-1+offset;
1738 else
1739 pc = pc+2;
1741 NEXT_INSN;
1743 insn_ifle:
1745 jint offset = get2s (pc);
1746 if (POPI() <= 0)
1747 pc = pc-1+offset;
1748 else
1749 pc = pc+2;
1751 NEXT_INSN;
1753 insn_if_icmpeq:
1755 jint offset = get2s (pc);
1756 jint value2 = POPI();
1757 jint value1 = POPI();
1758 if (value1 == value2)
1759 pc = pc-1+offset;
1760 else
1761 pc = pc+2;
1763 NEXT_INSN;
1765 insn_if_icmpne:
1767 jint offset = get2s (pc);
1768 jint value2 = POPI();
1769 jint value1 = POPI();
1770 if (value1 != value2)
1771 pc = pc-1+offset;
1772 else
1773 pc = pc+2;
1775 NEXT_INSN;
1777 insn_if_icmplt:
1779 jint offset = get2s (pc);
1780 jint value2 = POPI();
1781 jint value1 = POPI();
1782 if (value1 < value2)
1783 pc = pc-1+offset;
1784 else
1785 pc = pc+2;
1787 NEXT_INSN;
1789 insn_if_icmpge:
1791 jint offset = get2s (pc);
1792 jint value2 = POPI();
1793 jint value1 = POPI();
1794 if (value1 >= value2)
1795 pc = pc-1+offset;
1796 else
1797 pc = pc+2;
1799 NEXT_INSN;
1801 insn_if_icmpgt:
1803 jint offset = get2s (pc);
1804 jint value2 = POPI();
1805 jint value1 = POPI();
1806 if (value1 > value2)
1807 pc = pc-1+offset;
1808 else
1809 pc = pc+2;
1811 NEXT_INSN;
1813 insn_if_icmple:
1815 jint offset = get2s (pc);
1816 jint value2 = POPI();
1817 jint value1 = POPI();
1818 if (value1 <= value2)
1819 pc = pc-1+offset;
1820 else
1821 pc = pc+2;
1823 NEXT_INSN;
1825 insn_if_acmpeq:
1827 jint offset = get2s (pc);
1828 jobject value2 = POPA();
1829 jobject value1 = POPA();
1830 if (value1 == value2)
1831 pc = pc-1+offset;
1832 else
1833 pc = pc+2;
1835 NEXT_INSN;
1837 insn_if_acmpne:
1839 jint offset = get2s (pc);
1840 jobject value2 = POPA();
1841 jobject value1 = POPA();
1842 if (value1 != value2)
1843 pc = pc-1+offset;
1844 else
1845 pc = pc+2;
1847 NEXT_INSN;
1849 insn_goto:
1851 jint offset = get2s (pc);
1852 pc = pc-1+offset;
1854 NEXT_INSN;
1856 insn_jsr:
1858 unsigned char *base_pc = pc-1;
1859 jint offset = get2s (pc); pc += 2;
1860 PUSHA ((jobject)pc);
1861 pc = base_pc+offset;
1863 NEXT_INSN;
1865 insn_ret:
1867 jint index = get1u (pc);
1868 pc = (unsigned char*) PEEKA (index);
1870 NEXT_INSN;
1872 insn_tableswitch:
1874 unsigned char *base_pc = pc-1;
1875 int index = POPI();
1877 unsigned char* base = bytecode ();
1878 while ((pc-base) % 4 != 0)
1879 pc++;
1881 jint def = get4 (pc);
1882 jint low = get4 (pc+4);
1883 jint high = get4 (pc+8);
1885 if (index < low || index > high)
1886 pc = base_pc + def;
1887 else
1888 pc = base_pc + get4 (pc+4*(index-low+3));
1890 NEXT_INSN;
1892 insn_lookupswitch:
1894 unsigned char *base_pc = pc-1;
1895 int index = POPI();
1897 unsigned char* base = bytecode ();
1898 while ((pc-base) % 4 != 0)
1899 pc++;
1901 jint def = get4 (pc);
1902 jint npairs = get4 (pc+4);
1904 int max = npairs-1;
1905 int min = 0;
1907 // simple binary search...
1908 while (min < max)
1910 int half = (min+max)/2;
1911 int match = get4 (pc+ 4*(2 + 2*half));
1913 if (index == match)
1914 min = max = half;
1916 else if (index < match)
1917 max = half-1;
1919 else
1920 min = half+1;
1923 if (index == get4 (pc+ 4*(2 + 2*min)))
1924 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1925 else
1926 pc = base_pc + def;
1928 NEXT_INSN;
1930 /* on return, just save the sp and return to caller */
1931 insn_ireturn:
1932 insn_lreturn:
1933 insn_freturn:
1934 insn_dreturn:
1935 insn_areturn:
1936 insn_return:
1937 inv->sp = sp;
1938 return;
1940 insn_getstatic:
1941 SAVE_PC;
1943 jint fieldref_index = get2u (pc); pc += 2;
1944 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1945 _Jv_Field *field = pool_data[fieldref_index].field;
1947 if ((field->flags & Modifier::STATIC) == 0)
1948 throw_incompatible_class_change_error
1949 (JvNewStringLatin1 ("field no longer static"));
1951 jclass type = field->type;
1953 if (type->isPrimitive ())
1955 switch (type->size_in_bytes)
1957 case 1:
1958 PUSHI (*(jbyte*) (field->u.addr));
1960 case 2:
1961 if (type == JvPrimClass (char))
1962 PUSHI(*(jchar*) (field->u.addr));
1963 else
1964 PUSHI(*(jshort*) (field->u.addr));
1965 break;
1967 case 4:
1968 PUSHI(*(jint*) (field->u.addr));
1969 break;
1971 case 8:
1972 PUSHL(*(jlong*) (field->u.addr));
1973 break;
1976 else
1978 PUSHA(*(jobject*) (field->u.addr));
1981 NEXT_INSN;
1983 insn_getfield:
1984 SAVE_PC;
1986 jint fieldref_index = get2u (pc); pc += 2;
1987 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1988 _Jv_Field *field = pool_data[fieldref_index].field;
1990 if ((field->flags & Modifier::STATIC) != 0)
1991 throw_incompatible_class_change_error
1992 (JvNewStringLatin1 ("field is static"));
1994 jclass type = field->type;
1995 jint field_offset = field->u.boffset;
1996 if (field_offset > 0xffff)
1997 JvThrow (new java::lang::VirtualMachineError);
1999 jobject obj = POPA();
2000 NULLCHECK(obj);
2002 if (type->isPrimitive ())
2004 switch (type->size_in_bytes)
2006 case 1:
2007 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2008 break;
2010 case 2:
2011 if (type == JvPrimClass (char))
2012 PUSHI (*(jchar*) ((char*)obj + field_offset));
2013 else
2014 PUSHI (*(jshort*) ((char*)obj + field_offset));
2015 break;
2017 case 4:
2018 PUSHI (*(jint*) ((char*)obj + field_offset));
2019 break;
2021 case 8:
2022 PUSHL(*(jlong*) ((char*)obj + field_offset));
2023 break;
2026 else
2028 PUSHA(*(jobject*) ((char*)obj + field_offset));
2031 NEXT_INSN;
2033 insn_putstatic:
2034 SAVE_PC;
2036 jint fieldref_index = get2u (pc); pc += 2;
2037 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2038 _Jv_Field *field = pool_data[fieldref_index].field;
2040 jclass type = field->type;
2042 // ResolvePoolEntry cannot check this
2043 if ((field->flags & Modifier::STATIC) == 0)
2044 throw_incompatible_class_change_error
2045 (JvNewStringLatin1 ("field no longer static"));
2047 if (type->isPrimitive ())
2049 switch (type->size_in_bytes)
2051 case 1:
2053 jint value = POPI();
2054 *(jbyte*) (field->u.addr) = value;
2055 break;
2058 case 2:
2060 jint value = POPI();
2061 *(jchar*) (field->u.addr) = value;
2062 break;
2065 case 4:
2067 jint value = POPI();
2068 *(jint*) (field->u.addr) = value;
2069 break;
2072 case 8:
2074 jlong value = POPL();
2075 *(jlong*) (field->u.addr) = value;
2076 break;
2080 else
2082 jobject value = POPA();
2083 *(jobject*) (field->u.addr) = value;
2086 NEXT_INSN;
2089 insn_putfield:
2090 SAVE_PC;
2092 jint fieldref_index = get2u (pc); pc += 2;
2093 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2094 _Jv_Field *field = pool_data[fieldref_index].field;
2096 jclass type = field->type;
2098 if ((field->flags & Modifier::STATIC) != 0)
2099 throw_incompatible_class_change_error
2100 (JvNewStringLatin1 ("field is static"));
2102 jint field_offset = field->u.boffset;
2103 if (field_offset > 0xffff)
2104 JvThrow (new java::lang::VirtualMachineError);
2106 if (type->isPrimitive ())
2108 switch (type->size_in_bytes)
2110 case 1:
2112 jint value = POPI();
2113 jobject obj = POPA();
2114 NULLCHECK(obj);
2115 *(jbyte*) ((char*)obj + field_offset) = value;
2116 break;
2119 case 2:
2121 jint value = POPI();
2122 jobject obj = POPA();
2123 NULLCHECK(obj);
2124 *(jchar*) ((char*)obj + field_offset) = value;
2125 break;
2128 case 4:
2130 jint value = POPI();
2131 jobject obj = POPA();
2132 NULLCHECK(obj);
2133 *(jint*) ((char*)obj + field_offset) = value;
2134 break;
2137 case 8:
2139 jlong value = POPL();
2140 jobject obj = POPA();
2141 NULLCHECK(obj);
2142 *(jlong*) ((char*)obj + field_offset) = value;
2143 break;
2147 else
2149 jobject value = POPA();
2150 jobject obj = POPA();
2151 NULLCHECK(obj);
2152 *(jobject*) ((char*)obj + field_offset) = value;
2155 NEXT_INSN;
2157 insn_invokespecial:
2158 SAVE_PC;
2160 int index = get2u (pc); pc += 2;
2162 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2164 sp -= rmeth->stack_item_count;
2166 NULLCHECK(sp[0]);
2168 fun = (void (*) (...))rmeth->method->ncode;
2170 goto perform_invoke;
2172 insn_invokestatic:
2173 SAVE_PC;
2175 int index = get2u (pc); pc += 2;
2177 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2179 sp -= rmeth->stack_item_count;
2181 _Jv_InitClass (rmeth->klass);
2182 fun = (void (*) (...))rmeth->method->ncode;
2184 goto perform_invoke;
2186 insn_invokeinterface:
2187 SAVE_PC;
2189 int index = get2u (pc); pc += 2;
2191 // invokeinterface has two unused bytes...
2192 pc += 2;
2194 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2196 sp -= rmeth->stack_item_count;
2197 NULLCHECK(sp[0]);
2199 jobject rcv = sp[0].o;
2201 fun = (void (*) (...))
2202 _Jv_LookupInterfaceMethod (rcv->getClass (),
2203 rmeth->method->name,
2204 rmeth->method->signature);
2206 goto perform_invoke;
2209 insn_new:
2210 SAVE_PC;
2212 int index = get2u (pc); pc += 2;
2213 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2214 _Jv_InitClass (klass);
2215 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2216 PUSHA (res);
2218 NEXT_INSN;
2220 insn_newarray:
2221 SAVE_PC;
2223 int atype = get1u (pc++);
2224 int size = POPI();
2225 jobject result = _Jv_NewArray (atype, size);
2226 PUSHA (result);
2228 NEXT_INSN;
2230 insn_anewarray:
2231 SAVE_PC;
2233 int index = get2u (pc); pc += 2;
2234 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2235 int size = POPI();
2236 _Jv_InitClass (klass);
2237 jobject result = _Jv_NewObjectArray (size, klass, 0);
2238 PUSHA (result);
2240 NEXT_INSN;
2242 insn_arraylength:
2243 SAVE_PC;
2245 __JArray *arr = (__JArray*)POPA();
2246 PUSHI (arr->length);
2248 NEXT_INSN;
2250 insn_athrow:
2251 SAVE_PC;
2253 jobject value = POPA();
2254 JvThrow (value);
2256 NEXT_INSN;
2258 insn_checkcast:
2259 SAVE_PC;
2261 jobject value = POPA();
2262 jint index = get2u (pc); pc += 2;
2263 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2265 if (value != NULL && ! to->isInstance (value))
2267 JvThrow (new java::lang::ClassCastException
2268 (to->getName()));
2271 PUSHA (value);
2273 NEXT_INSN;
2275 insn_instanceof:
2276 SAVE_PC;
2278 jobject value = POPA();
2279 jint index = get2u (pc); pc += 2;
2280 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2281 PUSHI (to->isInstance (value));
2283 NEXT_INSN;
2285 insn_monitorenter:
2286 SAVE_PC;
2288 jobject value = POPA();
2289 NULLCHECK(value);
2290 _Jv_MonitorEnter (value);
2292 NEXT_INSN;
2294 insn_monitorexit:
2295 SAVE_PC;
2297 jobject value = POPA();
2298 NULLCHECK(value);
2299 _Jv_MonitorExit (value);
2301 NEXT_INSN;
2303 insn_ifnull:
2305 unsigned char* base_pc = pc-1;
2306 jint offset = get2s (pc); pc += 2;
2307 jobject val = POPA();
2308 if (val == NULL)
2309 pc = base_pc+offset;
2311 NEXT_INSN;
2313 insn_ifnonnull:
2315 unsigned char* base_pc = pc-1;
2316 jint offset = get2s (pc); pc += 2;
2317 jobject val = POPA();
2318 if (val != NULL)
2319 pc = base_pc+offset;
2321 NEXT_INSN;
2323 insn_wide:
2324 SAVE_PC;
2326 jint the_mod_op = get1u (pc++);
2327 jint wide = get2u (pc); pc += 2;
2329 switch (the_mod_op)
2331 case op_istore:
2332 STOREI (wide);
2333 NEXT_INSN;
2335 case op_fstore:
2336 STOREF (wide);
2337 NEXT_INSN;
2339 case op_astore:
2340 STOREA (wide);
2341 NEXT_INSN;
2343 case op_lload:
2344 LOADL (wide);
2345 NEXT_INSN;
2347 case op_dload:
2348 LOADD (wide);
2349 NEXT_INSN;
2351 case op_iload:
2352 LOADI (wide);
2353 NEXT_INSN;
2355 case op_aload:
2356 LOADA (wide);
2357 NEXT_INSN;
2359 case op_lstore:
2360 STOREL (wide);
2361 NEXT_INSN;
2363 case op_dstore:
2364 STORED (wide);
2365 NEXT_INSN;
2367 case op_ret:
2368 pc = (unsigned char*) PEEKA (wide);
2369 NEXT_INSN;
2371 case op_iinc:
2373 jint amount = get2s (pc); pc += 2;
2374 jint value = PEEKI (wide);
2375 POKEI (wide, value+amount);
2377 NEXT_INSN;
2379 default:
2380 throw_internal_error ("illegal bytecode modified by wide");
2385 insn_multianewarray:
2386 SAVE_PC;
2388 int kind_index = get2u (pc); pc += 2;
2389 int dim = get1u (pc); pc += 1;
2391 jclass type
2392 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2393 _Jv_InitClass (type);
2394 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2396 for (int i = dim - 1; i >= 0; i--)
2398 sizes[i] = POPI ();
2401 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2403 PUSHA (res);
2405 NEXT_INSN;
2407 insn_goto_w:
2409 unsigned char* base_pc = pc-1;
2410 int offset = get4 (pc); pc += 4;
2411 pc = base_pc+offset;
2413 NEXT_INSN;
2415 insn_jsr_w:
2417 unsigned char* base_pc = pc-1;
2418 int offset = get4 (pc); pc += 4;
2419 PUSHA((jobject)pc);
2420 pc = base_pc+offset;
2422 NEXT_INSN;
2426 static void
2427 throw_internal_error (char *msg)
2429 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2432 static void
2433 throw_incompatible_class_change_error (jstring msg)
2435 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2438 #ifndef HANDLE_SEGV
2439 static java::lang::NullPointerException *null_pointer_exc;
2440 static void
2441 throw_null_pointer_exception ()
2443 if (null_pointer_exc == NULL)
2444 null_pointer_exc = new java::lang::NullPointerException;
2446 JvThrow (null_pointer_exc);
2448 #endif
2450 #ifndef HANDLE_FPE
2451 static java::lang::ArithmeticException *arithmetic_exc;
2452 static void
2453 throw_arithmetic_exception ()
2455 if (arithmetic_exc == NULL)
2456 arithmetic_exc = new java::lang::ArithmeticException
2457 (JvNewStringLatin1 ("/ by zero"));
2459 JvThrow (arithmetic_exc);
2461 #endif
2464 #endif // INTERPRETER