Daily bump.
[official-gcc.git] / libjava / interpret.cc
blob7a847c5c363b66341cbd610d698a6427917a3bc3
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
13 #include <config.h>
15 #pragma implementation "java-interp.h"
17 #include <jvm.h>
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 // #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/StringBuffer.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/reflect/Modifier.h>
27 #include <java/lang/ClassCastException.h>
28 #include <java/lang/VirtualMachineError.h>
29 #include <java/lang/InternalError.h>
30 #include <java/lang/NullPointerException.h>
31 #include <java/lang/ArithmeticException.h>
32 #include <java/lang/IncompatibleClassChangeError.h>
33 #include <java-insns.h>
34 #include <java-signal.h>
36 #ifdef INTERPRETER
38 #include <stdlib.h>
40 using namespace gcj;
42 static void throw_internal_error (char *msg)
43 __attribute__ ((__noreturn__));
44 static void throw_incompatible_class_change_error (jstring msg)
45 __attribute__ ((__noreturn__));
46 #ifndef HANDLE_SEGV
47 static void throw_null_pointer_exception ()
48 __attribute__ ((__noreturn__));
49 #endif
51 extern "C" double __ieee754_fmod (double,double);
53 static inline void dupx (_Jv_word *sp, int n, int x)
55 // first "slide" n+x elements n to the right
56 int top = n-1;
57 for (int i = 0; i < n+x; i++)
59 sp[(top-i)] = sp[(top-i)-n];
62 // next, copy the n top elements, n+x down
63 for (int i = 0; i < n; i++)
65 sp[top-(n+x)-i] = sp[top-i];
71 #define PUSHA(V) (sp++)->o = (V)
72 #define PUSHI(V) (sp++)->i = (V)
73 #define PUSHF(V) (sp++)->f = (V)
74 #if SIZEOF_VOID_P == 8
75 # define PUSHL(V) (sp->l = (V), sp += 2)
76 # define PUSHD(V) (sp->d = (V), sp += 2)
77 #else
78 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
79 (sp++)->ia[0] = w2.ia[0]; \
80 (sp++)->ia[0] = w2.ia[1]; } while (0)
81 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
82 (sp++)->ia[0] = w2.ia[0]; \
83 (sp++)->ia[0] = w2.ia[1]; } while (0)
84 #endif
86 #define POPA() ((--sp)->o)
87 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
88 #define POPF() ((jfloat) (--sp)->f)
89 #if SIZEOF_VOID_P == 8
90 # define POPL() (sp -= 2, (jlong) sp->l)
91 # define POPD() (sp -= 2, (jdouble) sp->d)
92 #else
93 # define POPL() ({ _Jv_word2 w2; \
94 w2.ia[1] = (--sp)->ia[0]; \
95 w2.ia[0] = (--sp)->ia[0]; w2.l; })
96 # define POPD() ({ _Jv_word2 w2; \
97 w2.ia[1] = (--sp)->ia[0]; \
98 w2.ia[0] = (--sp)->ia[0]; w2.d; })
99 #endif
101 #define LOADA(I) (sp++)->o = locals[I].o
102 #define LOADI(I) (sp++)->i = locals[I].i
103 #define LOADF(I) (sp++)->f = locals[I].f
104 #if SIZEOF_VOID_P == 8
105 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
106 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
107 #else
108 # define LOADL(I) do { jint __idx = (I); \
109 (sp++)->ia[0] = locals[__idx].ia[0]; \
110 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
111 } while (0)
112 # define LOADD(I) LOADL(I)
113 #endif
115 #define STOREA(I) locals[I].o = (--sp)->o
116 #define STOREI(I) locals[I].i = (--sp)->i
117 #define STOREF(I) locals[I].f = (--sp)->f
118 #if SIZEOF_VOID_P == 8
119 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
120 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
121 #else
122 # define STOREL(I) do { jint __idx = (I); \
123 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
124 locals[__idx].ia[0] = (--sp)->ia[0]; \
125 } while (0)
126 # define STORED(I) STOREL(I)
127 #endif
129 #define PEEKI(I) (locals+(I))->i
130 #define PEEKA(I) (locals+(I))->o
132 #define POKEI(I,V) ((locals+(I))->i = (V))
135 #define BINOPI(OP) { \
136 jint value2 = POPI(); \
137 jint value1 = POPI(); \
138 PUSHI(value1 OP value2); \
141 #define BINOPF(OP) { \
142 jfloat value2 = POPF(); \
143 jfloat value1 = POPF(); \
144 PUSHF(value1 OP value2); \
147 #define BINOPL(OP) { \
148 jlong value2 = POPL(); \
149 jlong value1 = POPL(); \
150 PUSHL(value1 OP value2); \
153 #define BINOPD(OP) { \
154 jdouble value2 = POPD(); \
155 jdouble value1 = POPD(); \
156 PUSHD(value1 OP value2); \
159 static inline jint get1s(unsigned char* loc) {
160 return *(signed char*)loc;
163 static inline jint get1u(unsigned char* loc) {
164 return *loc;
167 static inline jint get2s(unsigned char* loc) {
168 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
171 static inline jint get2u(unsigned char* loc) {
172 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
175 static jint get4(unsigned char* loc) {
176 return (((jint)(loc[0])) << 24)
177 | (((jint)(loc[1])) << 16)
178 | (((jint)(loc[2])) << 8)
179 | (((jint)(loc[3])) << 0);
183 #ifdef HANDLE_SEGV
184 #define NULLCHECK(X)
185 #define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
186 #else
187 #define NULLCHECK(X) \
188 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
189 #define NULLARRAYCHECK(X) \
190 do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
191 #endif
193 #define ARRAYBOUNDSCHECK(array, index) \
194 do \
196 if (((unsigned) index) >= (unsigned) (array->length)) \
197 _Jv_ThrowBadArrayIndex (index); \
199 while (0)
201 // this method starts the actual running of the method. It is inlined
202 // in three different variants in the static methods run_normal,
203 // run_sync_object and run_sync_class (see below). Those static methods
204 // are installed directly in the stub for this method (by
205 // _Jv_InterpMethod::ncode, in resolve.cc).
207 inline jobject
208 _Jv_InterpMethod::run (ffi_cif* cif,
209 void *retp,
210 ffi_raw *args,
211 _Jv_InterpMethodInvocation *inv)
213 inv->running = this;
214 inv->pc = bytecode ();
215 inv->sp = inv->stack_base ();
216 _Jv_word *locals = inv->local_base ();
218 /* Go straight at it! the ffi raw format matches the internal
219 stack representation exactly. At least, that's the idea.
221 memcpy ((void*) locals, (void*) args, args_raw_size);
223 next_segment:
225 jobject ex = NULL;
229 continue1 (inv);
231 catch (java::lang::Throwable *ex2)
233 ex = ex2;
236 if (ex == 0) // no exception...
238 /* define sp locally, so the POP? macros will pick it up */
239 _Jv_word *sp = inv->sp;
240 int rtype = cif->rtype->type;
242 if (rtype == FFI_TYPE_POINTER)
244 jobject r = POPA();
245 *(jobject*) retp = r;
246 return 0;
248 else if (rtype == FFI_TYPE_SINT32)
250 jint r = POPI();
251 *(jint*)retp = r;
252 return 0;
254 else if (rtype == FFI_TYPE_VOID)
256 return 0;
258 else switch (rtype)
260 case FFI_TYPE_FLOAT:
262 jfloat r = POPF();
263 *(jfloat*)retp = r;
264 return 0;
267 case FFI_TYPE_DOUBLE:
269 jdouble r = POPD();
270 *(jdouble*)retp = r;
271 return 0;
274 case FFI_TYPE_UINT8:
275 case FFI_TYPE_UINT16:
276 case FFI_TYPE_UINT32:
277 case FFI_TYPE_SINT8:
278 case FFI_TYPE_SINT16:
280 jint r = POPI();
281 *(jint*)retp = r;
282 return 0;
285 case FFI_TYPE_SINT64:
287 jlong r = POPL();
288 *(jlong*)retp = r;
289 return 0;
292 default:
293 throw_internal_error ("unknown return type");
297 /** handle an exception */
298 if ( find_exception (ex, inv) )
299 goto next_segment;
301 return ex;
304 #define SAVE_PC inv->pc = pc
306 bool _Jv_InterpMethod::find_exception (jobject ex,
307 _Jv_InterpMethodInvocation *inv)
309 // We subtract one because the PC was incremented before it was
310 // saved.
311 int logical_pc = inv->pc - 1 - bytecode ();
312 _Jv_InterpException *exc = exceptions ();
313 jclass exc_class = ex->getClass ();
315 for (int i = 0; i < exc_count; i++)
317 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
319 jclass handler;
321 if (exc[i].handler_type != 0)
322 handler = (_Jv_ResolvePoolEntry (defining_class,
323 exc[i].handler_type)).clazz;
324 else
325 handler = NULL;
327 if (handler==NULL || handler->isAssignableFrom (exc_class))
329 inv->pc = bytecode () + exc[i].handler_pc;
330 inv->sp = inv->stack_base (); // reset stack
331 (inv->sp++)->o = ex; // push exception
332 return true;
336 return false;
339 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
340 void* ret,
341 ffi_raw * args,
342 void* __this)
344 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
346 // we do the alloca of the method invocation here, to allow the method
347 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
348 int storage_size = _this->max_stack+_this->max_locals;
349 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
350 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
351 + storage_size * sizeof (_Jv_word));
353 jobject ex = _this->run (cif, ret, args, inv);
354 if (ex != 0) throw static_cast<jthrowable>(ex);
357 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
358 void* ret,
359 ffi_raw * args,
360 void* __this)
362 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
363 jobject rcv = (jobject)args[0].ptr;
365 int storage_size = _this->max_stack+_this->max_locals;
366 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
367 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
368 + storage_size * sizeof (_Jv_word));
370 _Jv_MonitorEnter (rcv);
371 jobject ex = _this->run (cif, ret, args, inv);
372 _Jv_MonitorExit (rcv);
374 if (ex != 0) throw static_cast<jthrowable>(ex);
377 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
378 void* ret,
379 ffi_raw * args,
380 void* __this)
382 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
383 jclass sync = _this->defining_class;
385 int storage_size = _this->max_stack+_this->max_locals;
386 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
387 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
388 + storage_size * sizeof (_Jv_word));
390 _Jv_MonitorEnter (sync);
391 jobject ex = _this->run (cif, ret, args, inv);
392 _Jv_MonitorExit (sync);
394 if (ex != 0) throw static_cast<jthrowable>(ex);
398 This proceeds execution, as designated in "inv". If an exception
399 happens, then it is simply thrown, and handled in Java. Thus, the pc
400 needs to be stored in the inv->pc at all times, so we can figure
401 out which handler (if any) to invoke.
403 One design issue, which I have not completely considered, is if it
404 should be possible to have interpreted classes linked in! Seldom used
405 (or non-critical) classes could reasonably be interpreted.
409 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
411 using namespace java::lang::reflect;
413 _Jv_word *sp = inv->sp;
414 unsigned char *pc = inv->pc;
415 _Jv_word *locals = inv->local_base ();
417 _Jv_word *pool_data = defining_class->constants.data;
419 /* these two are used in the invokeXXX instructions */
420 void (*fun)();
421 _Jv_ResolvedMethod* rmeth;
423 #define INSN_LABEL(op) &&insn_##op
424 #define GOTO_INSN(op) goto *(insn_target[op])
426 static const void *const insn_target[] =
428 INSN_LABEL(nop),
429 INSN_LABEL(aconst_null),
430 INSN_LABEL(iconst_m1),
431 INSN_LABEL(iconst_0),
432 INSN_LABEL(iconst_1),
433 INSN_LABEL(iconst_2),
434 INSN_LABEL(iconst_3),
435 INSN_LABEL(iconst_4),
436 INSN_LABEL(iconst_5),
437 INSN_LABEL(lconst_0),
438 INSN_LABEL(lconst_1),
439 INSN_LABEL(fconst_0),
440 INSN_LABEL(fconst_1),
441 INSN_LABEL(fconst_2),
442 INSN_LABEL(dconst_0),
443 INSN_LABEL(dconst_1),
444 INSN_LABEL(bipush),
445 INSN_LABEL(sipush),
446 INSN_LABEL(ldc),
447 INSN_LABEL(ldc_w),
448 INSN_LABEL(ldc2_w),
449 INSN_LABEL(iload),
450 INSN_LABEL(lload),
451 INSN_LABEL(fload),
452 INSN_LABEL(dload),
453 INSN_LABEL(aload),
454 INSN_LABEL(iload_0),
455 INSN_LABEL(iload_1),
456 INSN_LABEL(iload_2),
457 INSN_LABEL(iload_3),
458 INSN_LABEL(lload_0),
459 INSN_LABEL(lload_1),
460 INSN_LABEL(lload_2),
461 INSN_LABEL(lload_3),
462 INSN_LABEL(fload_0),
463 INSN_LABEL(fload_1),
464 INSN_LABEL(fload_2),
465 INSN_LABEL(fload_3),
466 INSN_LABEL(dload_0),
467 INSN_LABEL(dload_1),
468 INSN_LABEL(dload_2),
469 INSN_LABEL(dload_3),
470 INSN_LABEL(aload_0),
471 INSN_LABEL(aload_1),
472 INSN_LABEL(aload_2),
473 INSN_LABEL(aload_3),
474 INSN_LABEL(iaload),
475 INSN_LABEL(laload),
476 INSN_LABEL(faload),
477 INSN_LABEL(daload),
478 INSN_LABEL(aaload),
479 INSN_LABEL(baload),
480 INSN_LABEL(caload),
481 INSN_LABEL(saload),
482 INSN_LABEL(istore),
483 INSN_LABEL(lstore),
484 INSN_LABEL(fstore),
485 INSN_LABEL(dstore),
486 INSN_LABEL(astore),
487 INSN_LABEL(istore_0),
488 INSN_LABEL(istore_1),
489 INSN_LABEL(istore_2),
490 INSN_LABEL(istore_3),
491 INSN_LABEL(lstore_0),
492 INSN_LABEL(lstore_1),
493 INSN_LABEL(lstore_2),
494 INSN_LABEL(lstore_3),
495 INSN_LABEL(fstore_0),
496 INSN_LABEL(fstore_1),
497 INSN_LABEL(fstore_2),
498 INSN_LABEL(fstore_3),
499 INSN_LABEL(dstore_0),
500 INSN_LABEL(dstore_1),
501 INSN_LABEL(dstore_2),
502 INSN_LABEL(dstore_3),
503 INSN_LABEL(astore_0),
504 INSN_LABEL(astore_1),
505 INSN_LABEL(astore_2),
506 INSN_LABEL(astore_3),
507 INSN_LABEL(iastore),
508 INSN_LABEL(lastore),
509 INSN_LABEL(fastore),
510 INSN_LABEL(dastore),
511 INSN_LABEL(aastore),
512 INSN_LABEL(bastore),
513 INSN_LABEL(castore),
514 INSN_LABEL(sastore),
515 INSN_LABEL(pop),
516 INSN_LABEL(pop2),
517 INSN_LABEL(dup),
518 INSN_LABEL(dup_x1),
519 INSN_LABEL(dup_x2),
520 INSN_LABEL(dup2),
521 INSN_LABEL(dup2_x1),
522 INSN_LABEL(dup2_x2),
523 INSN_LABEL(swap),
524 INSN_LABEL(iadd),
525 INSN_LABEL(ladd),
526 INSN_LABEL(fadd),
527 INSN_LABEL(dadd),
528 INSN_LABEL(isub),
529 INSN_LABEL(lsub),
530 INSN_LABEL(fsub),
531 INSN_LABEL(dsub),
532 INSN_LABEL(imul),
533 INSN_LABEL(lmul),
534 INSN_LABEL(fmul),
535 INSN_LABEL(dmul),
536 INSN_LABEL(idiv),
537 INSN_LABEL(ldiv),
538 INSN_LABEL(fdiv),
539 INSN_LABEL(ddiv),
540 INSN_LABEL(irem),
541 INSN_LABEL(lrem),
542 INSN_LABEL(frem),
543 INSN_LABEL(drem),
544 INSN_LABEL(ineg),
545 INSN_LABEL(lneg),
546 INSN_LABEL(fneg),
547 INSN_LABEL(dneg),
548 INSN_LABEL(ishl),
549 INSN_LABEL(lshl),
550 INSN_LABEL(ishr),
551 INSN_LABEL(lshr),
552 INSN_LABEL(iushr),
553 INSN_LABEL(lushr),
554 INSN_LABEL(iand),
555 INSN_LABEL(land),
556 INSN_LABEL(ior),
557 INSN_LABEL(lor),
558 INSN_LABEL(ixor),
559 INSN_LABEL(lxor),
560 INSN_LABEL(iinc),
561 INSN_LABEL(i2l),
562 INSN_LABEL(i2f),
563 INSN_LABEL(i2d),
564 INSN_LABEL(l2i),
565 INSN_LABEL(l2f),
566 INSN_LABEL(l2d),
567 INSN_LABEL(f2i),
568 INSN_LABEL(f2l),
569 INSN_LABEL(f2d),
570 INSN_LABEL(d2i),
571 INSN_LABEL(d2l),
572 INSN_LABEL(d2f),
573 INSN_LABEL(i2b),
574 INSN_LABEL(i2c),
575 INSN_LABEL(i2s),
576 INSN_LABEL(lcmp),
577 INSN_LABEL(fcmpl),
578 INSN_LABEL(fcmpg),
579 INSN_LABEL(dcmpl),
580 INSN_LABEL(dcmpg),
581 INSN_LABEL(ifeq),
582 INSN_LABEL(ifne),
583 INSN_LABEL(iflt),
584 INSN_LABEL(ifge),
585 INSN_LABEL(ifgt),
586 INSN_LABEL(ifle),
587 INSN_LABEL(if_icmpeq),
588 INSN_LABEL(if_icmpne),
589 INSN_LABEL(if_icmplt),
590 INSN_LABEL(if_icmpge),
591 INSN_LABEL(if_icmpgt),
592 INSN_LABEL(if_icmple),
593 INSN_LABEL(if_acmpeq),
594 INSN_LABEL(if_acmpne),
595 INSN_LABEL(goto),
596 INSN_LABEL(jsr),
597 INSN_LABEL(ret),
598 INSN_LABEL(tableswitch),
599 INSN_LABEL(lookupswitch),
600 INSN_LABEL(ireturn),
601 INSN_LABEL(lreturn),
602 INSN_LABEL(freturn),
603 INSN_LABEL(dreturn),
604 INSN_LABEL(areturn),
605 INSN_LABEL(return),
606 INSN_LABEL(getstatic),
607 INSN_LABEL(putstatic),
608 INSN_LABEL(getfield),
609 INSN_LABEL(putfield),
610 INSN_LABEL(invokevirtual),
611 INSN_LABEL(invokespecial),
612 INSN_LABEL(invokestatic),
613 INSN_LABEL(invokeinterface),
614 0, /* op_xxxunusedxxx1, */
615 INSN_LABEL(new),
616 INSN_LABEL(newarray),
617 INSN_LABEL(anewarray),
618 INSN_LABEL(arraylength),
619 INSN_LABEL(athrow),
620 INSN_LABEL(checkcast),
621 INSN_LABEL(instanceof),
622 INSN_LABEL(monitorenter),
623 INSN_LABEL(monitorexit),
624 INSN_LABEL(wide),
625 INSN_LABEL(multianewarray),
626 INSN_LABEL(ifnull),
627 INSN_LABEL(ifnonnull),
628 INSN_LABEL(goto_w),
629 INSN_LABEL(jsr_w),
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 // We don't use NULLCHECK here because we can't rely on that
691 // working if the method is final. So instead we do an
692 // explicit test.
693 if (! sp[0].o)
694 throw new java::lang::NullPointerException;
696 if (rmeth->vtable_index == -1)
698 // final methods do not appear in the vtable,
699 // if it does not appear in the superclass.
700 fun = (void (*)()) rmeth->method->ncode;
702 else
704 jobject rcv = sp[0].o;
705 _Jv_VTable *table = *(_Jv_VTable**)rcv;
706 fun = (void (*)()) table->get_method(rmeth->vtable_index);
709 goto perform_invoke;
711 perform_invoke:
713 /* here goes the magic again... */
714 ffi_cif *cif = &rmeth->cif;
715 ffi_raw *raw = (ffi_raw*) sp;
717 jdouble rvalue;
719 #if FFI_NATIVE_RAW_API
720 /* We assume that this is only implemented if it's correct */
721 /* to use it here. On a 64 bit machine, it never is. */
722 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
723 #else
724 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
725 #endif
727 int rtype = cif->rtype->type;
729 /* the likelyhood of object, int, or void return is very high,
730 * so those are checked before the switch */
731 if (rtype == FFI_TYPE_POINTER)
733 PUSHA (*(jobject*)&rvalue);
735 else if (rtype == FFI_TYPE_SINT32)
737 PUSHI (*(jint*)&rvalue);
739 else if (rtype == FFI_TYPE_VOID)
741 /* skip */
743 else switch (rtype)
745 case FFI_TYPE_SINT8:
747 jbyte value = (*(jint*)&rvalue) & 0xff;
748 PUSHI (value);
750 break;
752 case FFI_TYPE_SINT16:
754 jshort value = (*(jint*)&rvalue) & 0xffff;
755 PUSHI (value);
757 break;
759 case FFI_TYPE_UINT16:
761 jint value = (*(jint*)&rvalue) & 0xffff;
762 PUSHI (value);
764 break;
766 case FFI_TYPE_FLOAT:
767 PUSHF (*(jfloat*)&rvalue);
768 break;
770 case FFI_TYPE_DOUBLE:
771 PUSHD (rvalue);
772 break;
774 case FFI_TYPE_SINT64:
775 PUSHL (*(jlong*)&rvalue);
776 break;
778 default:
779 throw_internal_error ("unknown return type in invokeXXX");
783 NEXT_INSN;
786 insn_nop:
787 NEXT_INSN;
789 insn_aconst_null:
790 PUSHA (NULL);
791 NEXT_INSN;
793 insn_iconst_m1:
794 PUSHI (-1);
795 NEXT_INSN;
797 insn_iconst_0:
798 PUSHI (0);
799 NEXT_INSN;
801 insn_iconst_1:
802 PUSHI (1);
803 NEXT_INSN;
805 insn_iconst_2:
806 PUSHI (2);
807 NEXT_INSN;
809 insn_iconst_3:
810 PUSHI (3);
811 NEXT_INSN;
813 insn_iconst_4:
814 PUSHI (4);
815 NEXT_INSN;
817 insn_iconst_5:
818 PUSHI (5);
819 NEXT_INSN;
821 insn_lconst_0:
822 PUSHL (0);
823 NEXT_INSN;
825 insn_lconst_1:
826 PUSHL (1);
827 NEXT_INSN;
829 insn_fconst_0:
830 PUSHF (0);
831 NEXT_INSN;
833 insn_fconst_1:
834 PUSHF (1);
835 NEXT_INSN;
837 insn_fconst_2:
838 PUSHF (2);
839 NEXT_INSN;
841 insn_dconst_0:
842 PUSHD (0);
843 NEXT_INSN;
845 insn_dconst_1:
846 PUSHD (1);
847 NEXT_INSN;
849 insn_bipush:
850 PUSHI (get1s(pc++));
851 NEXT_INSN;
853 insn_sipush:
854 PUSHI (get2s(pc)); pc += 2;
855 NEXT_INSN;
857 insn_ldc:
859 int index = get1u (pc++);
860 PUSHA(pool_data[index].o);
862 NEXT_INSN;
864 insn_ldc_w:
866 int index = get2u (pc); pc += 2;
867 PUSHA(pool_data[index].o);
869 NEXT_INSN;
871 insn_ldc2_w:
873 int index = get2u (pc); pc += 2;
874 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
875 sp += 2;
877 NEXT_INSN;
879 insn_lload:
880 LOADL (get1u (pc++));
881 NEXT_INSN;
883 insn_fload:
884 LOADF (get1u (pc++));
885 NEXT_INSN;
887 insn_dload:
888 LOADD (get1u (pc++));
889 NEXT_INSN;
891 insn_aload:
892 LOADA (get1u (pc++));
893 NEXT_INSN;
895 insn_iload_0:
896 LOADI (0);
897 NEXT_INSN;
899 insn_iload_2:
900 LOADI (2);
901 NEXT_INSN;
903 insn_iload_3:
904 LOADI (3);
905 NEXT_INSN;
907 insn_lload_0:
908 LOADL (0);
909 NEXT_INSN;
911 insn_lload_1:
912 LOADL (1);
913 NEXT_INSN;
915 insn_lload_2:
916 LOADL (2);
917 NEXT_INSN;
919 insn_lload_3:
920 LOADL (3);
921 NEXT_INSN;
923 insn_fload_0:
924 LOADF (0);
925 NEXT_INSN;
927 insn_fload_1:
928 LOADF (1);
929 NEXT_INSN;
931 insn_fload_2:
932 LOADF (2);
933 NEXT_INSN;
935 insn_fload_3:
936 LOADF (3);
937 NEXT_INSN;
939 insn_dload_0:
940 LOADD (0);
941 NEXT_INSN;
943 insn_dload_1:
944 LOADD (1);
945 NEXT_INSN;
947 insn_dload_2:
948 LOADD (2);
949 NEXT_INSN;
951 insn_dload_3:
952 LOADD (3);
953 NEXT_INSN;
955 insn_aload_1:
956 LOADA(1);
957 NEXT_INSN;
959 insn_aload_2:
960 LOADA(2);
961 NEXT_INSN;
963 insn_aload_3:
964 LOADA(3);
965 NEXT_INSN;
967 insn_iaload:
969 jint index = POPI();
970 jintArray arr = (jintArray) POPA();
971 NULLARRAYCHECK (arr);
972 ARRAYBOUNDSCHECK (arr, index);
973 PUSHI( elements(arr)[index] );
975 NEXT_INSN;
977 insn_laload:
979 jint index = POPI();
980 jlongArray arr = (jlongArray) POPA();
981 NULLARRAYCHECK (arr);
982 ARRAYBOUNDSCHECK (arr, index);
983 PUSHL( elements(arr)[index] );
985 NEXT_INSN;
987 insn_faload:
989 jint index = POPI();
990 jfloatArray arr = (jfloatArray) POPA();
991 NULLARRAYCHECK (arr);
992 ARRAYBOUNDSCHECK (arr, index);
993 PUSHF( elements(arr)[index] );
995 NEXT_INSN;
997 insn_daload:
999 jint index = POPI();
1000 jdoubleArray arr = (jdoubleArray) POPA();
1001 NULLARRAYCHECK (arr);
1002 ARRAYBOUNDSCHECK (arr, index);
1003 PUSHD( elements(arr)[index] );
1005 NEXT_INSN;
1007 insn_aaload:
1009 jint index = POPI();
1010 jobjectArray arr = (jobjectArray) POPA();
1011 NULLARRAYCHECK (arr);
1012 ARRAYBOUNDSCHECK (arr, index);
1013 PUSHA( elements(arr)[index] );
1015 NEXT_INSN;
1017 insn_baload:
1019 jint index = POPI();
1020 jbyteArray arr = (jbyteArray) POPA();
1021 NULLARRAYCHECK (arr);
1022 ARRAYBOUNDSCHECK (arr, index);
1023 PUSHI( elements(arr)[index] );
1025 NEXT_INSN;
1027 insn_caload:
1029 jint index = POPI();
1030 jcharArray arr = (jcharArray) POPA();
1031 NULLARRAYCHECK (arr);
1032 ARRAYBOUNDSCHECK (arr, index);
1033 PUSHI( elements(arr)[index] );
1035 NEXT_INSN;
1037 insn_saload:
1039 jint index = POPI();
1040 jshortArray arr = (jshortArray) POPA();
1041 NULLARRAYCHECK (arr);
1042 ARRAYBOUNDSCHECK (arr, index);
1043 PUSHI( elements(arr)[index] );
1045 NEXT_INSN;
1047 insn_istore:
1048 STOREI (get1u (pc++));
1049 NEXT_INSN;
1051 insn_lstore:
1052 STOREL (get1u (pc++));
1053 NEXT_INSN;
1055 insn_fstore:
1056 STOREF (get1u (pc++));
1057 NEXT_INSN;
1059 insn_dstore:
1060 STORED (get1u (pc++));
1061 NEXT_INSN;
1063 insn_astore:
1064 STOREA (get1u (pc++));
1065 NEXT_INSN;
1067 insn_istore_0:
1068 STOREI (0);
1069 NEXT_INSN;
1071 insn_istore_1:
1072 STOREI (1);
1073 NEXT_INSN;
1075 insn_istore_2:
1076 STOREI (2);
1077 NEXT_INSN;
1079 insn_istore_3:
1080 STOREI (3);
1081 NEXT_INSN;
1083 insn_lstore_0:
1084 STOREL (0);
1085 NEXT_INSN;
1087 insn_lstore_1:
1088 STOREL (1);
1089 NEXT_INSN;
1091 insn_lstore_2:
1092 STOREL (2);
1093 NEXT_INSN;
1095 insn_lstore_3:
1096 STOREL (3);
1097 NEXT_INSN;
1099 insn_fstore_0:
1100 STOREF (0);
1101 NEXT_INSN;
1103 insn_fstore_1:
1104 STOREF (1);
1105 NEXT_INSN;
1107 insn_fstore_2:
1108 STOREF (2);
1109 NEXT_INSN;
1111 insn_fstore_3:
1112 STOREF (3);
1113 NEXT_INSN;
1115 insn_dstore_0:
1116 STORED (0);
1117 NEXT_INSN;
1119 insn_dstore_1:
1120 STORED (1);
1121 NEXT_INSN;
1123 insn_dstore_2:
1124 STORED (2);
1125 NEXT_INSN;
1127 insn_dstore_3:
1128 STORED (3);
1129 NEXT_INSN;
1131 insn_astore_0:
1132 STOREA(0);
1133 NEXT_INSN;
1135 insn_astore_1:
1136 STOREA(1);
1137 NEXT_INSN;
1139 insn_astore_2:
1140 STOREA(2);
1141 NEXT_INSN;
1143 insn_astore_3:
1144 STOREA(3);
1145 NEXT_INSN;
1147 insn_iastore:
1149 jint value = POPI();
1150 jint index = POPI();
1151 jintArray arr = (jintArray) POPA();
1152 NULLARRAYCHECK (arr);
1153 ARRAYBOUNDSCHECK (arr, index);
1154 elements(arr)[index] = value;
1156 NEXT_INSN;
1158 insn_lastore:
1160 jlong value = POPL();
1161 jint index = POPI();
1162 jlongArray arr = (jlongArray) POPA();
1163 NULLARRAYCHECK (arr);
1164 ARRAYBOUNDSCHECK (arr, index);
1165 elements(arr)[index] = value;
1167 NEXT_INSN;
1169 insn_fastore:
1171 jfloat value = POPF();
1172 jint index = POPI();
1173 jfloatArray arr = (jfloatArray) POPA();
1174 NULLARRAYCHECK (arr);
1175 ARRAYBOUNDSCHECK (arr, index);
1176 elements(arr)[index] = value;
1178 NEXT_INSN;
1180 insn_dastore:
1182 jdouble value = POPD();
1183 jint index = POPI();
1184 jdoubleArray arr = (jdoubleArray) POPA();
1185 NULLARRAYCHECK (arr);
1186 ARRAYBOUNDSCHECK (arr, index);
1187 elements(arr)[index] = value;
1189 NEXT_INSN;
1191 insn_aastore:
1193 jobject value = POPA();
1194 jint index = POPI();
1195 jobjectArray arr = (jobjectArray) POPA();
1196 NULLARRAYCHECK (arr);
1197 ARRAYBOUNDSCHECK (arr, index);
1198 _Jv_CheckArrayStore (arr, value);
1199 elements(arr)[index] = value;
1201 NEXT_INSN;
1203 insn_bastore:
1205 jbyte value = (jbyte) POPI();
1206 jint index = POPI();
1207 jbyteArray arr = (jbyteArray) POPA();
1208 NULLARRAYCHECK (arr);
1209 ARRAYBOUNDSCHECK (arr, index);
1210 elements(arr)[index] = value;
1212 NEXT_INSN;
1214 insn_castore:
1216 jchar value = (jchar) POPI();
1217 jint index = POPI();
1218 jcharArray arr = (jcharArray) POPA();
1219 NULLARRAYCHECK (arr);
1220 ARRAYBOUNDSCHECK (arr, index);
1221 elements(arr)[index] = value;
1223 NEXT_INSN;
1225 insn_sastore:
1227 jshort value = (jshort) POPI();
1228 jint index = POPI();
1229 jshortArray arr = (jshortArray) POPA();
1230 NULLARRAYCHECK (arr);
1231 ARRAYBOUNDSCHECK (arr, index);
1232 elements(arr)[index] = value;
1234 NEXT_INSN;
1236 insn_pop:
1237 sp -= 1;
1238 NEXT_INSN;
1240 insn_pop2:
1241 sp -= 2;
1242 NEXT_INSN;
1244 insn_dup:
1245 sp[0] = sp[-1];
1246 sp += 1;
1247 NEXT_INSN;
1249 insn_dup_x1:
1250 dupx (sp, 1, 1); sp+=1;
1251 NEXT_INSN;
1253 insn_dup_x2:
1254 dupx (sp, 1, 2); sp+=1;
1255 NEXT_INSN;
1257 insn_dup2:
1258 sp[0] = sp[-2];
1259 sp[1] = sp[-1];
1260 sp += 2;
1261 NEXT_INSN;
1263 insn_dup2_x1:
1264 dupx (sp, 2, 1); sp+=2;
1265 NEXT_INSN;
1267 insn_dup2_x2:
1268 dupx (sp, 2, 2); sp+=2;
1269 NEXT_INSN;
1271 insn_swap:
1273 jobject tmp1 = POPA();
1274 jobject tmp2 = POPA();
1275 PUSHA (tmp1);
1276 PUSHA (tmp2);
1278 NEXT_INSN;
1280 insn_iadd:
1281 BINOPI(+);
1282 NEXT_INSN;
1284 insn_ladd:
1285 BINOPL(+);
1286 NEXT_INSN;
1288 insn_fadd:
1289 BINOPF(+);
1290 NEXT_INSN;
1292 insn_dadd:
1293 BINOPD(+);
1294 NEXT_INSN;
1296 insn_isub:
1297 BINOPI(-);
1298 NEXT_INSN;
1300 insn_lsub:
1301 BINOPL(-);
1302 NEXT_INSN;
1304 insn_fsub:
1305 BINOPF(-);
1306 NEXT_INSN;
1308 insn_dsub:
1309 BINOPD(-);
1310 NEXT_INSN;
1312 insn_imul:
1313 BINOPI(*);
1314 NEXT_INSN;
1316 insn_lmul:
1317 BINOPL(*);
1318 NEXT_INSN;
1320 insn_fmul:
1321 BINOPF(*);
1322 NEXT_INSN;
1324 insn_dmul:
1325 BINOPD(*);
1326 NEXT_INSN;
1328 insn_idiv:
1329 SAVE_PC;
1331 jint value2 = POPI();
1332 jint value1 = POPI();
1333 jint res = _Jv_divI (value1, value2);
1334 PUSHI (res);
1336 NEXT_INSN;
1338 insn_ldiv:
1339 SAVE_PC;
1341 jlong value2 = POPL();
1342 jlong value1 = POPL();
1343 jlong res = _Jv_divJ (value1, value2);
1344 PUSHL (res);
1346 NEXT_INSN;
1348 insn_fdiv:
1350 jfloat value2 = POPF();
1351 jfloat value1 = POPF();
1352 jfloat res = value1 / value2;
1353 PUSHF (res);
1355 NEXT_INSN;
1357 insn_ddiv:
1359 jdouble value2 = POPD();
1360 jdouble value1 = POPD();
1361 jdouble res = value1 / value2;
1362 PUSHD (res);
1364 NEXT_INSN;
1366 insn_irem:
1367 SAVE_PC;
1369 jint value2 = POPI();
1370 jint value1 = POPI();
1371 jint res = _Jv_remI (value1, value2);
1372 PUSHI (res);
1374 NEXT_INSN;
1376 insn_lrem:
1377 SAVE_PC;
1379 jlong value2 = POPL();
1380 jlong value1 = POPL();
1381 jlong res = _Jv_remJ (value1, value2);
1382 PUSHL (res);
1384 NEXT_INSN;
1386 insn_frem:
1388 jfloat value2 = POPF();
1389 jfloat value1 = POPF();
1390 jfloat res = __ieee754_fmod (value1, value2);
1391 PUSHF (res);
1393 NEXT_INSN;
1395 insn_drem:
1397 jdouble value2 = POPD();
1398 jdouble value1 = POPD();
1399 jdouble res = __ieee754_fmod (value1, value2);
1400 PUSHD (res);
1402 NEXT_INSN;
1404 insn_ineg:
1406 jint value = POPI();
1407 PUSHI (value * -1);
1409 NEXT_INSN;
1411 insn_lneg:
1413 jlong value = POPL();
1414 PUSHL (value * -1);
1416 NEXT_INSN;
1418 insn_fneg:
1420 jfloat value = POPF();
1421 PUSHF (value * -1);
1423 NEXT_INSN;
1425 insn_dneg:
1427 jdouble value = POPD();
1428 PUSHD (value * -1);
1430 NEXT_INSN;
1432 insn_ishl:
1434 jint shift = (POPI() & 0x1f);
1435 jint value = POPI();
1436 PUSHI (value << shift);
1438 NEXT_INSN;
1440 insn_lshl:
1442 jint shift = (POPI() & 0x3f);
1443 jlong value = POPL();
1444 PUSHL (value << shift);
1446 NEXT_INSN;
1448 insn_ishr:
1450 jint shift = (POPI() & 0x1f);
1451 jint value = POPI();
1452 PUSHI (value >> shift);
1454 NEXT_INSN;
1456 insn_lshr:
1458 jint shift = (POPI() & 0x3f);
1459 jlong value = POPL();
1460 PUSHL (value >> shift);
1462 NEXT_INSN;
1464 insn_iushr:
1466 jint shift = (POPI() & 0x1f);
1467 unsigned long value = POPI();
1468 PUSHI ((jint) (value >> shift));
1470 NEXT_INSN;
1472 insn_lushr:
1474 jint shift = (POPI() & 0x3f);
1475 UINT64 value = (UINT64) POPL();
1476 PUSHL ((value >> shift));
1478 NEXT_INSN;
1480 insn_iand:
1481 BINOPI (&);
1482 NEXT_INSN;
1484 insn_land:
1485 BINOPL (&);
1486 NEXT_INSN;
1488 insn_ior:
1489 BINOPI (|);
1490 NEXT_INSN;
1492 insn_lor:
1493 BINOPL (|);
1494 NEXT_INSN;
1496 insn_ixor:
1497 BINOPI (^);
1498 NEXT_INSN;
1500 insn_lxor:
1501 BINOPL (^);
1502 NEXT_INSN;
1504 insn_iinc:
1506 jint index = get1u (pc++);
1507 jint amount = get1s (pc++);
1508 locals[index].i += amount;
1510 NEXT_INSN;
1512 insn_i2l:
1513 {jlong value = POPI(); PUSHL (value);}
1514 NEXT_INSN;
1516 insn_i2f:
1517 {jfloat value = POPI(); PUSHF (value);}
1518 NEXT_INSN;
1520 insn_i2d:
1521 {jdouble value = POPI(); PUSHD (value);}
1522 NEXT_INSN;
1524 insn_l2i:
1525 {jint value = POPL(); PUSHI (value);}
1526 NEXT_INSN;
1528 insn_l2f:
1529 {jfloat value = POPL(); PUSHF (value);}
1530 NEXT_INSN;
1532 insn_l2d:
1533 {jdouble value = POPL(); PUSHD (value);}
1534 NEXT_INSN;
1536 insn_f2i:
1537 { jint value = (jint)POPF (); PUSHI(value); }
1538 NEXT_INSN;
1540 insn_f2l:
1541 { jlong value = (jlong)POPF (); PUSHL(value); }
1542 NEXT_INSN;
1544 insn_f2d:
1545 { jdouble value = POPF (); PUSHD(value); }
1546 NEXT_INSN;
1548 insn_d2i:
1549 { jint value = (jint)POPD (); PUSHI(value); }
1550 NEXT_INSN;
1552 insn_d2l:
1553 { jlong value = (jlong)POPD (); PUSHL(value); }
1554 NEXT_INSN;
1556 insn_d2f:
1557 { jfloat value = POPD (); PUSHF(value); }
1558 NEXT_INSN;
1560 insn_i2b:
1561 { jbyte value = POPI (); PUSHI(value); }
1562 NEXT_INSN;
1564 insn_i2c:
1565 { jchar value = POPI (); PUSHI(value); }
1566 NEXT_INSN;
1568 insn_i2s:
1569 { jshort value = POPI (); PUSHI(value); }
1570 NEXT_INSN;
1572 insn_lcmp:
1574 jlong value2 = POPL ();
1575 jlong value1 = POPL ();
1576 if (value1 > value2)
1577 { PUSHI (1); }
1578 else if (value1 == value2)
1579 { PUSHI (0); }
1580 else
1581 { PUSHI (-1); }
1583 NEXT_INSN;
1585 insn_fcmpl:
1586 insn_fcmpg:
1588 jfloat value2 = POPF ();
1589 jfloat value1 = POPF ();
1590 if (value1 > value2)
1591 PUSHI (1);
1592 else if (value1 == value2)
1593 PUSHI (0);
1594 else if (value1 < value2)
1595 PUSHI (-1);
1596 else if ((*(pc-1)) == op_fcmpg)
1597 PUSHI (1);
1598 else
1599 PUSHI (-1);
1601 NEXT_INSN;
1603 insn_dcmpl:
1604 insn_dcmpg:
1606 jdouble value2 = POPD ();
1607 jdouble value1 = POPD ();
1608 if (value1 > value2)
1609 PUSHI (1);
1610 else if (value1 == value2)
1611 PUSHI (0);
1612 else if (value1 < value2)
1613 PUSHI (-1);
1614 else if ((*(pc-1)) == op_dcmpg)
1615 PUSHI (1);
1616 else
1617 PUSHI (-1);
1619 NEXT_INSN;
1621 insn_ifeq:
1623 jint offset = get2s (pc);
1624 if (POPI() == 0)
1625 pc = pc-1+offset;
1626 else
1627 pc = pc+2;
1629 NEXT_INSN;
1631 insn_ifne:
1633 jint offset = get2s (pc);
1634 if (POPI() != 0)
1635 pc = pc-1+offset;
1636 else
1637 pc = pc+2;
1639 NEXT_INSN;
1641 insn_iflt:
1643 jint offset = get2s (pc);
1644 if (POPI() < 0)
1645 pc = pc-1+offset;
1646 else
1647 pc = pc+2;
1649 NEXT_INSN;
1651 insn_ifge:
1653 jint offset = get2s (pc);
1654 if (POPI() >= 0)
1655 pc = pc-1+offset;
1656 else
1657 pc = pc+2;
1659 NEXT_INSN;
1661 insn_ifgt:
1663 jint offset = get2s (pc);
1664 if (POPI() > 0)
1665 pc = pc-1+offset;
1666 else
1667 pc = pc+2;
1669 NEXT_INSN;
1671 insn_ifle:
1673 jint offset = get2s (pc);
1674 if (POPI() <= 0)
1675 pc = pc-1+offset;
1676 else
1677 pc = pc+2;
1679 NEXT_INSN;
1681 insn_if_icmpeq:
1683 jint offset = get2s (pc);
1684 jint value2 = POPI();
1685 jint value1 = POPI();
1686 if (value1 == value2)
1687 pc = pc-1+offset;
1688 else
1689 pc = pc+2;
1691 NEXT_INSN;
1693 insn_if_icmpne:
1695 jint offset = get2s (pc);
1696 jint value2 = POPI();
1697 jint value1 = POPI();
1698 if (value1 != value2)
1699 pc = pc-1+offset;
1700 else
1701 pc = pc+2;
1703 NEXT_INSN;
1705 insn_if_icmplt:
1707 jint offset = get2s (pc);
1708 jint value2 = POPI();
1709 jint value1 = POPI();
1710 if (value1 < value2)
1711 pc = pc-1+offset;
1712 else
1713 pc = pc+2;
1715 NEXT_INSN;
1717 insn_if_icmpge:
1719 jint offset = get2s (pc);
1720 jint value2 = POPI();
1721 jint value1 = POPI();
1722 if (value1 >= value2)
1723 pc = pc-1+offset;
1724 else
1725 pc = pc+2;
1727 NEXT_INSN;
1729 insn_if_icmpgt:
1731 jint offset = get2s (pc);
1732 jint value2 = POPI();
1733 jint value1 = POPI();
1734 if (value1 > value2)
1735 pc = pc-1+offset;
1736 else
1737 pc = pc+2;
1739 NEXT_INSN;
1741 insn_if_icmple:
1743 jint offset = get2s (pc);
1744 jint value2 = POPI();
1745 jint value1 = POPI();
1746 if (value1 <= value2)
1747 pc = pc-1+offset;
1748 else
1749 pc = pc+2;
1751 NEXT_INSN;
1753 insn_if_acmpeq:
1755 jint offset = get2s (pc);
1756 jobject value2 = POPA();
1757 jobject value1 = POPA();
1758 if (value1 == value2)
1759 pc = pc-1+offset;
1760 else
1761 pc = pc+2;
1763 NEXT_INSN;
1765 insn_if_acmpne:
1767 jint offset = get2s (pc);
1768 jobject value2 = POPA();
1769 jobject value1 = POPA();
1770 if (value1 != value2)
1771 pc = pc-1+offset;
1772 else
1773 pc = pc+2;
1775 NEXT_INSN;
1777 insn_goto:
1779 jint offset = get2s (pc);
1780 pc = pc-1+offset;
1782 NEXT_INSN;
1784 insn_jsr:
1786 unsigned char *base_pc = pc-1;
1787 jint offset = get2s (pc); pc += 2;
1788 PUSHA ((jobject)pc);
1789 pc = base_pc+offset;
1791 NEXT_INSN;
1793 insn_ret:
1795 jint index = get1u (pc);
1796 pc = (unsigned char*) PEEKA (index);
1798 NEXT_INSN;
1800 insn_tableswitch:
1802 unsigned char *base_pc = pc-1;
1803 int index = POPI();
1805 unsigned char* base = bytecode ();
1806 while ((pc-base) % 4 != 0)
1807 pc++;
1809 jint def = get4 (pc);
1810 jint low = get4 (pc+4);
1811 jint high = get4 (pc+8);
1813 if (index < low || index > high)
1814 pc = base_pc + def;
1815 else
1816 pc = base_pc + get4 (pc+4*(index-low+3));
1818 NEXT_INSN;
1820 insn_lookupswitch:
1822 unsigned char *base_pc = pc-1;
1823 int index = POPI();
1825 unsigned char* base = bytecode ();
1826 while ((pc-base) % 4 != 0)
1827 pc++;
1829 jint def = get4 (pc);
1830 jint npairs = get4 (pc+4);
1832 int max = npairs-1;
1833 int min = 0;
1835 // simple binary search...
1836 while (min < max)
1838 int half = (min+max)/2;
1839 int match = get4 (pc+ 4*(2 + 2*half));
1841 if (index == match)
1842 min = max = half;
1844 else if (index < match)
1845 max = half-1;
1847 else
1848 min = half+1;
1851 if (index == get4 (pc+ 4*(2 + 2*min)))
1852 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1853 else
1854 pc = base_pc + def;
1856 NEXT_INSN;
1858 /* on return, just save the sp and return to caller */
1859 insn_ireturn:
1860 insn_lreturn:
1861 insn_freturn:
1862 insn_dreturn:
1863 insn_areturn:
1864 insn_return:
1865 inv->sp = sp;
1866 return;
1868 insn_getstatic:
1869 SAVE_PC;
1871 jint fieldref_index = get2u (pc); pc += 2;
1872 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1873 _Jv_Field *field = pool_data[fieldref_index].field;
1875 if ((field->flags & Modifier::STATIC) == 0)
1876 throw_incompatible_class_change_error
1877 (JvNewStringLatin1 ("field no longer static"));
1879 jclass type = field->type;
1881 if (type->isPrimitive ())
1883 switch (type->size_in_bytes)
1885 case 1:
1886 PUSHI (*(jbyte*) (field->u.addr));
1887 break;
1889 case 2:
1890 if (type == JvPrimClass (char))
1891 PUSHI(*(jchar*) (field->u.addr));
1892 else
1893 PUSHI(*(jshort*) (field->u.addr));
1894 break;
1896 case 4:
1897 PUSHI(*(jint*) (field->u.addr));
1898 break;
1900 case 8:
1901 PUSHL(*(jlong*) (field->u.addr));
1902 break;
1905 else
1907 PUSHA(*(jobject*) (field->u.addr));
1910 NEXT_INSN;
1912 insn_getfield:
1913 SAVE_PC;
1915 jint fieldref_index = get2u (pc); pc += 2;
1916 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1917 _Jv_Field *field = pool_data[fieldref_index].field;
1919 if ((field->flags & Modifier::STATIC) != 0)
1920 throw_incompatible_class_change_error
1921 (JvNewStringLatin1 ("field is static"));
1923 jclass type = field->type;
1924 jint field_offset = field->u.boffset;
1925 if (field_offset > 0xffff)
1926 throw new java::lang::VirtualMachineError;
1928 jobject obj = POPA();
1929 NULLCHECK(obj);
1931 if (type->isPrimitive ())
1933 switch (type->size_in_bytes)
1935 case 1:
1936 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1937 break;
1939 case 2:
1940 if (type == JvPrimClass (char))
1941 PUSHI (*(jchar*) ((char*)obj + field_offset));
1942 else
1943 PUSHI (*(jshort*) ((char*)obj + field_offset));
1944 break;
1946 case 4:
1947 PUSHI (*(jint*) ((char*)obj + field_offset));
1948 break;
1950 case 8:
1951 PUSHL(*(jlong*) ((char*)obj + field_offset));
1952 break;
1955 else
1957 PUSHA(*(jobject*) ((char*)obj + field_offset));
1960 NEXT_INSN;
1962 insn_putstatic:
1963 SAVE_PC;
1965 jint fieldref_index = get2u (pc); pc += 2;
1966 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1967 _Jv_Field *field = pool_data[fieldref_index].field;
1969 jclass type = field->type;
1971 // ResolvePoolEntry cannot check this
1972 if ((field->flags & Modifier::STATIC) == 0)
1973 throw_incompatible_class_change_error
1974 (JvNewStringLatin1 ("field no longer static"));
1976 if (type->isPrimitive ())
1978 switch (type->size_in_bytes)
1980 case 1:
1982 jint value = POPI();
1983 *(jbyte*) (field->u.addr) = value;
1984 break;
1987 case 2:
1989 jint value = POPI();
1990 *(jchar*) (field->u.addr) = value;
1991 break;
1994 case 4:
1996 jint value = POPI();
1997 *(jint*) (field->u.addr) = value;
1998 break;
2001 case 8:
2003 jlong value = POPL();
2004 *(jlong*) (field->u.addr) = value;
2005 break;
2009 else
2011 jobject value = POPA();
2012 *(jobject*) (field->u.addr) = value;
2015 NEXT_INSN;
2018 insn_putfield:
2019 SAVE_PC;
2021 jint fieldref_index = get2u (pc); pc += 2;
2022 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2023 _Jv_Field *field = pool_data[fieldref_index].field;
2025 jclass type = field->type;
2027 if ((field->flags & Modifier::STATIC) != 0)
2028 throw_incompatible_class_change_error
2029 (JvNewStringLatin1 ("field is static"));
2031 jint field_offset = field->u.boffset;
2032 if (field_offset > 0xffff)
2033 throw new java::lang::VirtualMachineError;
2035 if (type->isPrimitive ())
2037 switch (type->size_in_bytes)
2039 case 1:
2041 jint value = POPI();
2042 jobject obj = POPA();
2043 NULLCHECK(obj);
2044 *(jbyte*) ((char*)obj + field_offset) = value;
2045 break;
2048 case 2:
2050 jint value = POPI();
2051 jobject obj = POPA();
2052 NULLCHECK(obj);
2053 *(jchar*) ((char*)obj + field_offset) = value;
2054 break;
2057 case 4:
2059 jint value = POPI();
2060 jobject obj = POPA();
2061 NULLCHECK(obj);
2062 *(jint*) ((char*)obj + field_offset) = value;
2063 break;
2066 case 8:
2068 jlong value = POPL();
2069 jobject obj = POPA();
2070 NULLCHECK(obj);
2071 *(jlong*) ((char*)obj + field_offset) = value;
2072 break;
2076 else
2078 jobject value = POPA();
2079 jobject obj = POPA();
2080 NULLCHECK(obj);
2081 *(jobject*) ((char*)obj + field_offset) = value;
2084 NEXT_INSN;
2086 insn_invokespecial:
2087 SAVE_PC;
2089 int index = get2u (pc); pc += 2;
2091 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2093 sp -= rmeth->stack_item_count;
2095 NULLCHECK (sp[0].o);
2097 fun = (void (*)()) rmeth->method->ncode;
2099 goto perform_invoke;
2101 insn_invokestatic:
2102 SAVE_PC;
2104 int index = get2u (pc); pc += 2;
2106 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2108 sp -= rmeth->stack_item_count;
2110 _Jv_InitClass (rmeth->klass);
2111 fun = (void (*)()) rmeth->method->ncode;
2113 goto perform_invoke;
2115 insn_invokeinterface:
2116 SAVE_PC;
2118 int index = get2u (pc); pc += 2;
2120 // invokeinterface has two unused bytes...
2121 pc += 2;
2123 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2125 sp -= rmeth->stack_item_count;
2127 jobject rcv = sp[0].o;
2129 NULLCHECK (rcv);
2131 fun = (void (*)())
2132 _Jv_LookupInterfaceMethod (rcv->getClass (),
2133 rmeth->method->name,
2134 rmeth->method->signature);
2136 goto perform_invoke;
2139 insn_new:
2140 SAVE_PC;
2142 int index = get2u (pc); pc += 2;
2143 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2144 _Jv_InitClass (klass);
2145 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2146 PUSHA (res);
2148 NEXT_INSN;
2150 insn_newarray:
2151 SAVE_PC;
2153 int atype = get1u (pc++);
2154 int size = POPI();
2155 jobject result = _Jv_NewArray (atype, size);
2156 PUSHA (result);
2158 NEXT_INSN;
2160 insn_anewarray:
2161 SAVE_PC;
2163 int index = get2u (pc); pc += 2;
2164 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2165 int size = POPI();
2166 _Jv_InitClass (klass);
2167 jobject result = _Jv_NewObjectArray (size, klass, 0);
2168 PUSHA (result);
2170 NEXT_INSN;
2172 insn_arraylength:
2174 __JArray *arr = (__JArray*)POPA();
2175 NULLARRAYCHECK (arr);
2176 PUSHI (arr->length);
2178 NEXT_INSN;
2180 insn_athrow:
2181 SAVE_PC;
2183 jobject value = POPA();
2184 throw static_cast<jthrowable>(value);
2186 NEXT_INSN;
2188 insn_checkcast:
2189 SAVE_PC;
2191 jobject value = POPA();
2192 jint index = get2u (pc); pc += 2;
2193 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2195 if (value != NULL && ! to->isInstance (value))
2197 throw new java::lang::ClassCastException (to->getName());
2200 PUSHA (value);
2202 NEXT_INSN;
2204 insn_instanceof:
2205 SAVE_PC;
2207 jobject value = POPA();
2208 jint index = get2u (pc); pc += 2;
2209 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2210 PUSHI (to->isInstance (value));
2212 NEXT_INSN;
2214 insn_monitorenter:
2215 SAVE_PC;
2217 jobject value = POPA();
2218 NULLCHECK(value);
2219 _Jv_MonitorEnter (value);
2221 NEXT_INSN;
2223 insn_monitorexit:
2224 SAVE_PC;
2226 jobject value = POPA();
2227 NULLCHECK(value);
2228 _Jv_MonitorExit (value);
2230 NEXT_INSN;
2232 insn_ifnull:
2234 unsigned char* base_pc = pc-1;
2235 jint offset = get2s (pc); pc += 2;
2236 jobject val = POPA();
2237 if (val == NULL)
2238 pc = base_pc+offset;
2240 NEXT_INSN;
2242 insn_ifnonnull:
2244 unsigned char* base_pc = pc-1;
2245 jint offset = get2s (pc); pc += 2;
2246 jobject val = POPA();
2247 if (val != NULL)
2248 pc = base_pc+offset;
2250 NEXT_INSN;
2252 insn_wide:
2253 SAVE_PC;
2255 jint the_mod_op = get1u (pc++);
2256 jint wide = get2u (pc); pc += 2;
2258 switch (the_mod_op)
2260 case op_istore:
2261 STOREI (wide);
2262 NEXT_INSN;
2264 case op_fstore:
2265 STOREF (wide);
2266 NEXT_INSN;
2268 case op_astore:
2269 STOREA (wide);
2270 NEXT_INSN;
2272 case op_lload:
2273 LOADL (wide);
2274 NEXT_INSN;
2276 case op_dload:
2277 LOADD (wide);
2278 NEXT_INSN;
2280 case op_iload:
2281 LOADI (wide);
2282 NEXT_INSN;
2284 case op_aload:
2285 LOADA (wide);
2286 NEXT_INSN;
2288 case op_lstore:
2289 STOREL (wide);
2290 NEXT_INSN;
2292 case op_dstore:
2293 STORED (wide);
2294 NEXT_INSN;
2296 case op_ret:
2297 pc = (unsigned char*) PEEKA (wide);
2298 NEXT_INSN;
2300 case op_iinc:
2302 jint amount = get2s (pc); pc += 2;
2303 jint value = PEEKI (wide);
2304 POKEI (wide, value+amount);
2306 NEXT_INSN;
2308 default:
2309 throw_internal_error ("illegal bytecode modified by wide");
2314 insn_multianewarray:
2315 SAVE_PC;
2317 int kind_index = get2u (pc); pc += 2;
2318 int dim = get1u (pc); pc += 1;
2320 jclass type
2321 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2322 _Jv_InitClass (type);
2323 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2325 for (int i = dim - 1; i >= 0; i--)
2327 sizes[i] = POPI ();
2330 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2332 PUSHA (res);
2334 NEXT_INSN;
2336 insn_goto_w:
2338 unsigned char* base_pc = pc-1;
2339 int offset = get4 (pc); pc += 4;
2340 pc = base_pc+offset;
2342 NEXT_INSN;
2344 insn_jsr_w:
2346 unsigned char* base_pc = pc-1;
2347 int offset = get4 (pc); pc += 4;
2348 PUSHA((jobject)pc);
2349 pc = base_pc+offset;
2351 NEXT_INSN;
2355 static void
2356 throw_internal_error (char *msg)
2358 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
2361 static void
2362 throw_incompatible_class_change_error (jstring msg)
2364 throw new java::lang::IncompatibleClassChangeError (msg);
2367 #ifndef HANDLE_SEGV
2368 static java::lang::NullPointerException *null_pointer_exc;
2369 static void
2370 throw_null_pointer_exception ()
2372 if (null_pointer_exc == NULL)
2373 null_pointer_exc = new java::lang::NullPointerException;
2375 throw null_pointer_exc;
2377 #endif
2379 #endif // INTERPRETER