allow all arm targets to use -mstructure-size-boundary=XX
[official-gcc.git] / libjava / interpret.cc
blob581606e4047c9c963d3cc41c61392e685eeca764
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999 Cygnus Solutions
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/io/PrintStream.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/ClassCastException.h>
29 #include <java/lang/VirtualMachineError.h>
30 #include <java/lang/InternalError.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/ArithmeticException.h>
33 #include <java/lang/IncompatibleClassChangeError.h>
34 #include <java-insns.h>
35 #include <java-signal.h>
37 #ifndef INTERPRETER
39 #include <gnu/gcj/runtime/MethodInvocation.h>
41 /* This should never happen. */
42 void
43 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
44 gnu::gcj::RawData *)
46 JvFail ("no interpreter");
49 #else
51 #define ClassError _CL_Q34java4lang5Error
52 extern java::lang::Class ClassError;
54 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
56 static void throw_internal_error (char *msg)
57 __attribute__ ((__noreturn__));
58 static void throw_incompatible_class_change_error (jstring msg)
59 __attribute__ ((__noreturn__));
60 #if !HANDLE_SEGV
61 static void throw_null_pointer_exception ()
62 __attribute__ ((__noreturn__));
63 #endif
64 #if !HANDLE_FPE
65 static void throw_arithmetic_exception ()
66 __attribute__ ((__noreturn__));
67 #endif
70 static inline void dupx (_Jv_word *sp, int n, int x)
72 // first "slide" n+x elements n to the right
73 int top = n-1;
74 for (int i = 0; i < n+x; i++)
76 sp[(top-i)] = sp[(top-i)-n];
79 // next, copy the n top elements, n+x down
80 for (int i = 0; i < n; i++)
82 sp[top-(n+x)-i] = sp[top-i];
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #define PUSHL(V) ({ _Jv_word2 w2; w2.l=(V); \
92 (sp++)->ia[0] = w2.ia[0]; \
93 (sp++)->ia[0] = w2.ia[1]; })
94 #define PUSHD(V) ({ _Jv_word2 w2; w2.d=(V); \
95 (sp++)->ia[0] = w2.ia[0]; \
96 (sp++)->ia[0] = w2.ia[1]; })
98 #define POPA() ((--sp)->o)
99 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
100 #define POPF() ((jfloat) (--sp)->f)
101 #define POPL() ({ _Jv_word2 w2; \
102 w2.ia[1] = (--sp)->ia[0]; \
103 w2.ia[0] = (--sp)->ia[0]; w2.l; })
104 #define POPD() ({ _Jv_word2 w2; \
105 w2.ia[1] = (--sp)->ia[0]; \
106 w2.ia[0] = (--sp)->ia[0]; w2.d; })
108 #define LOADA(I) (sp++)->o = locals[I].o
109 #define LOADI(I) (sp++)->i = locals[I].i
110 #define LOADF(I) (sp++)->f = locals[I].f
111 #define LOADL(I) ({ jint __idx = (I); \
112 (sp++)->ia[0] = locals[__idx].ia[0]; \
113 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
115 #define LOADD(I) LOADL(I)
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #define STOREL(I) ({ jint __idx = (I); \
122 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
123 locals[__idx].ia[0] = (--sp)->ia[0]; \
125 #define STORED(I) STOREL(I)
127 #define PEEKI(I) (locals+(I))->i
128 #define PEEKA(I) (locals+(I))->o
130 #define POKEI(I,V) ((locals+(I))->i = (V))
133 #define BINOPI(OP) { \
134 jint value2 = POPI(); \
135 jint value1 = POPI(); \
136 PUSHI(value1 OP value2); \
139 #define BINOPF(OP) { \
140 jfloat value2 = POPF(); \
141 jfloat value1 = POPF(); \
142 PUSHF(value1 OP value2); \
145 #define BINOPL(OP) { \
146 jlong value2 = POPL(); \
147 jlong value1 = POPL(); \
148 PUSHL(value1 OP value2); \
151 #define BINOPD(OP) { \
152 jdouble value2 = POPD(); \
153 jdouble value1 = POPD(); \
154 PUSHD(value1 OP value2); \
157 static inline jint get1s(unsigned char* loc) {
158 return *(signed char*)loc;
161 static inline jint get1u(unsigned char* loc) {
162 return *loc;
165 static inline jint get2s(unsigned char* loc) {
166 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
169 static inline jint get2u(unsigned char* loc) {
170 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
173 static jint get4(unsigned char* loc) {
174 return (((jint)(loc[0])) << 24)
175 | (((jint)(loc[1])) << 16)
176 | (((jint)(loc[2])) << 8)
177 | (((jint)(loc[3])) << 0);
181 #if HANDLE_SEGV
182 #define NULLCHECK(X)
183 #else
184 #define NULLCHECK(X) \
185 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
186 #endif
188 #if HANDLE_FPE
189 #define ZEROCHECK(X)
190 #else
191 #define ZEROCHECK(X) \
192 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
193 #endif
195 // this method starts the actual running of the method. It is inlined
196 // in three different variants in the static methods run_normal,
197 // run_sync_object and run_sync_class (see below). Those static methods
198 // are installed directly in the stub for this method (by
199 // _Jv_InterpMethod::ncode, in resolve.cc).
201 inline jobject
202 _Jv_InterpMethod::run (ffi_cif* cif,
203 void *retp,
204 ffi_raw *args,
205 _Jv_InterpMethodInvocation *inv)
207 inv->running = this;
208 inv->pc = bytecode ();
209 inv->sp = inv->stack_base ();
210 _Jv_word *locals = inv->local_base ();
212 /* Go straight at it! the ffi raw format matches the internal
213 stack representation exactly. At leat, that's the idea.
215 memcpy ((void*) locals, (void*) args, args_raw_size);
217 next_segment:
218 /* this will call the method _Jv_InterpMethod::continue0, see below */
219 jobject ex =
220 gnu::gcj::runtime::MethodInvocation::continue0
221 ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
223 if (ex == 0) // no exception...
225 /* define sp locally, so the POP? macros will pick it up */
226 _Jv_word *sp = inv->sp;
227 int rtype = cif->rtype->type;
229 if (rtype == FFI_TYPE_POINTER)
231 jobject r = POPA();
232 *(jobject*) retp = r;
233 return 0;
235 else if (rtype == FFI_TYPE_SINT32)
237 jint r = POPI();
238 *(jint*)retp = r;
239 return 0;
241 else if (rtype == FFI_TYPE_VOID)
243 return 0;
245 else switch (rtype)
247 case FFI_TYPE_FLOAT:
249 jfloat r = POPF();
250 *(jfloat*)retp = r;
251 return 0;
254 case FFI_TYPE_DOUBLE:
256 jdouble r = POPD();
257 *(jdouble*)retp = r;
258 return 0;
261 case FFI_TYPE_UINT8:
262 case FFI_TYPE_UINT16:
263 case FFI_TYPE_UINT32:
264 case FFI_TYPE_SINT8:
265 case FFI_TYPE_SINT16:
267 jint r = POPI();
268 *(jint*)retp = r;
269 return 0;
272 case FFI_TYPE_SINT64:
274 jlong r = POPL();
275 *(jlong*)retp = r;
276 return 0;
279 default:
280 throw_internal_error ("unknown return type");
285 /** handle an exception */
286 if ( find_exception (ex, inv) )
287 goto next_segment;
289 java::lang::System::out->println
290 (_Jv_NewStringUTF (self->name->data));
292 return ex;
295 bool _Jv_InterpMethod::find_exception (jobject ex,
296 _Jv_InterpMethodInvocation *inv)
298 int logical_pc = inv->pc - bytecode ();
299 _Jv_InterpException *exc = exceptions ();
300 jclass exc_class = ex->getClass ();
302 for (int i = 0; i < exc_count; i++)
304 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
306 jclass handler;
308 if (exc[i].handler_type != 0)
309 handler = (_Jv_ResolvePoolEntry (defining_class,
310 exc[i].handler_type)).clazz;
311 else
312 handler = NULL;
314 if (handler==NULL || handler->isAssignableFrom (exc_class))
316 inv->pc = bytecode () + exc[i].handler_pc;
317 inv->sp = inv->stack_base (); // reset stack
318 (inv->sp++)->o = ex; // push exception
319 return true;
323 return false;
326 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327 void* ret,
328 ffi_raw * args,
329 void* __this)
331 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
333 // we do the alloca of the method invocation here, to allow the method
334 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
335 int storage_size = _this->max_stack+_this->max_locals;
336 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
337 alloca (sizeof (_Jv_InterpMethodInvocation)
338 + storage_size * sizeof (_Jv_word));
340 jobject ex = _this->run (cif, ret, args, inv);
341 if (ex != 0) _Jv_Throw (ex);
344 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345 void* ret,
346 ffi_raw * args,
347 void* __this)
349 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
350 jobject rcv = (jobject)args[0].ptr;
352 int storage_size = _this->max_stack+_this->max_locals;
353 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
354 alloca (sizeof (_Jv_InterpMethodInvocation)
355 + storage_size * sizeof (_Jv_word));
357 _Jv_MonitorEnter (rcv);
358 jobject ex = _this->run (cif, ret, args, inv);
359 _Jv_MonitorExit (rcv);
361 if (ex != 0) _Jv_Throw (ex);
364 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365 void* ret,
366 ffi_raw * args,
367 void* __this)
369 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
370 jclass sync = _this->defining_class;
372 int storage_size = _this->max_stack+_this->max_locals;
373 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
374 alloca (sizeof (_Jv_InterpMethodInvocation)
375 + storage_size * sizeof (_Jv_word));
377 _Jv_MonitorEnter (sync);
378 jobject ex = _this->run (cif, ret, args, inv);
379 _Jv_MonitorExit (sync);
381 if (ex != 0) _Jv_Throw (ex);
384 /* this is the exception handler hack, for the interpreter */
385 void
386 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
387 gnu::gcj::RawData *inv)
389 _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
390 _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
391 meth0->continue1 (inv0);
395 This proceeds execution, as designated in "inv". If an exception
396 happens, then it is simply thrown, and handled in Java. Thus, the pc
397 needs to be stored in the inv->pc at all times, so we can figure
398 out which handler (if any) to invoke.
400 One design issue, which I have not completely considered, is if it
401 should be possible to have interpreted classes linked in! Seldom used
402 (or non-critical) classes could reasonably be interpreted.
406 #ifdef __i386__
407 #define PC_REGISTER_ASM asm("%esi")
408 #else
409 #define PC_REGISTER_ASM
410 #endif
412 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
414 using namespace java::lang::reflect;
416 register _Jv_word *sp = inv->sp;
417 register unsigned char *pc PC_REGISTER_ASM = inv->pc;
418 _Jv_word *locals = inv->local_base ();
420 _Jv_word *pool_data = defining_class->constants.data;
422 /* these two are used in the invokeXXX instructions */
423 void (*fun)(...);
424 _Jv_ResolvedMethod* rmeth;
426 #define INSN_LABEL(op) &&insn_##op
427 #define GOTO_INSN(op) goto *(insn_target[op])
429 static const void *const insn_target[] =
431 INSN_LABEL(nop),
432 INSN_LABEL(aconst_null),
433 INSN_LABEL(iconst_m1),
434 INSN_LABEL(iconst_0),
435 INSN_LABEL(iconst_1),
436 INSN_LABEL(iconst_2),
437 INSN_LABEL(iconst_3),
438 INSN_LABEL(iconst_4),
439 INSN_LABEL(iconst_5),
440 INSN_LABEL(lconst_0),
441 INSN_LABEL(lconst_1),
442 INSN_LABEL(fconst_0),
443 INSN_LABEL(fconst_1),
444 INSN_LABEL(fconst_2),
445 INSN_LABEL(dconst_0),
446 INSN_LABEL(dconst_1),
447 INSN_LABEL(bipush),
448 INSN_LABEL(sipush),
449 INSN_LABEL(ldc),
450 INSN_LABEL(ldc_w),
451 INSN_LABEL(ldc2_w),
452 INSN_LABEL(iload),
453 INSN_LABEL(lload),
454 INSN_LABEL(fload),
455 INSN_LABEL(dload),
456 INSN_LABEL(aload),
457 INSN_LABEL(iload_0),
458 INSN_LABEL(iload_1),
459 INSN_LABEL(iload_2),
460 INSN_LABEL(iload_3),
461 INSN_LABEL(lload_0),
462 INSN_LABEL(lload_1),
463 INSN_LABEL(lload_2),
464 INSN_LABEL(lload_3),
465 INSN_LABEL(fload_0),
466 INSN_LABEL(fload_1),
467 INSN_LABEL(fload_2),
468 INSN_LABEL(fload_3),
469 INSN_LABEL(dload_0),
470 INSN_LABEL(dload_1),
471 INSN_LABEL(dload_2),
472 INSN_LABEL(dload_3),
473 INSN_LABEL(aload_0),
474 INSN_LABEL(aload_1),
475 INSN_LABEL(aload_2),
476 INSN_LABEL(aload_3),
477 INSN_LABEL(iaload),
478 INSN_LABEL(laload),
479 INSN_LABEL(faload),
480 INSN_LABEL(daload),
481 INSN_LABEL(aaload),
482 INSN_LABEL(baload),
483 INSN_LABEL(caload),
484 INSN_LABEL(saload),
485 INSN_LABEL(istore),
486 INSN_LABEL(lstore),
487 INSN_LABEL(fstore),
488 INSN_LABEL(dstore),
489 INSN_LABEL(astore),
490 INSN_LABEL(istore_0),
491 INSN_LABEL(istore_1),
492 INSN_LABEL(istore_2),
493 INSN_LABEL(istore_3),
494 INSN_LABEL(lstore_0),
495 INSN_LABEL(lstore_1),
496 INSN_LABEL(lstore_2),
497 INSN_LABEL(lstore_3),
498 INSN_LABEL(fstore_0),
499 INSN_LABEL(fstore_1),
500 INSN_LABEL(fstore_2),
501 INSN_LABEL(fstore_3),
502 INSN_LABEL(dstore_0),
503 INSN_LABEL(dstore_1),
504 INSN_LABEL(dstore_2),
505 INSN_LABEL(dstore_3),
506 INSN_LABEL(astore_0),
507 INSN_LABEL(astore_1),
508 INSN_LABEL(astore_2),
509 INSN_LABEL(astore_3),
510 INSN_LABEL(iastore),
511 INSN_LABEL(lastore),
512 INSN_LABEL(fastore),
513 INSN_LABEL(dastore),
514 INSN_LABEL(aastore),
515 INSN_LABEL(bastore),
516 INSN_LABEL(castore),
517 INSN_LABEL(sastore),
518 INSN_LABEL(pop),
519 INSN_LABEL(pop2),
520 INSN_LABEL(dup),
521 INSN_LABEL(dup_x1),
522 INSN_LABEL(dup_x2),
523 INSN_LABEL(dup2),
524 INSN_LABEL(dup2_x1),
525 INSN_LABEL(dup2_x2),
526 INSN_LABEL(swap),
527 INSN_LABEL(iadd),
528 INSN_LABEL(ladd),
529 INSN_LABEL(fadd),
530 INSN_LABEL(dadd),
531 INSN_LABEL(isub),
532 INSN_LABEL(lsub),
533 INSN_LABEL(fsub),
534 INSN_LABEL(dsub),
535 INSN_LABEL(imul),
536 INSN_LABEL(lmul),
537 INSN_LABEL(fmul),
538 INSN_LABEL(dmul),
539 INSN_LABEL(idiv),
540 INSN_LABEL(ldiv),
541 INSN_LABEL(fdiv),
542 INSN_LABEL(ddiv),
543 INSN_LABEL(irem),
544 INSN_LABEL(lrem),
545 INSN_LABEL(frem),
546 INSN_LABEL(drem),
547 INSN_LABEL(ineg),
548 INSN_LABEL(lneg),
549 INSN_LABEL(fneg),
550 INSN_LABEL(dneg),
551 INSN_LABEL(ishl),
552 INSN_LABEL(lshl),
553 INSN_LABEL(ishr),
554 INSN_LABEL(lshr),
555 INSN_LABEL(iushr),
556 INSN_LABEL(lushr),
557 INSN_LABEL(iand),
558 INSN_LABEL(land),
559 INSN_LABEL(ior),
560 INSN_LABEL(lor),
561 INSN_LABEL(ixor),
562 INSN_LABEL(lxor),
563 INSN_LABEL(iinc),
564 INSN_LABEL(i2l),
565 INSN_LABEL(i2f),
566 INSN_LABEL(i2d),
567 INSN_LABEL(l2i),
568 INSN_LABEL(l2f),
569 INSN_LABEL(l2d),
570 INSN_LABEL(f2i),
571 INSN_LABEL(f2l),
572 INSN_LABEL(f2d),
573 INSN_LABEL(d2i),
574 INSN_LABEL(d2l),
575 INSN_LABEL(d2f),
576 INSN_LABEL(i2b),
577 INSN_LABEL(i2c),
578 INSN_LABEL(i2s),
579 INSN_LABEL(lcmp),
580 INSN_LABEL(fcmpl),
581 INSN_LABEL(fcmpg),
582 INSN_LABEL(dcmpl),
583 INSN_LABEL(dcmpg),
584 INSN_LABEL(ifeq),
585 INSN_LABEL(ifne),
586 INSN_LABEL(iflt),
587 INSN_LABEL(ifge),
588 INSN_LABEL(ifgt),
589 INSN_LABEL(ifle),
590 INSN_LABEL(if_icmpeq),
591 INSN_LABEL(if_icmpne),
592 INSN_LABEL(if_icmplt),
593 INSN_LABEL(if_icmpge),
594 INSN_LABEL(if_icmpgt),
595 INSN_LABEL(if_icmple),
596 INSN_LABEL(if_acmpeq),
597 INSN_LABEL(if_acmpne),
598 INSN_LABEL(goto),
599 INSN_LABEL(jsr),
600 INSN_LABEL(ret),
601 INSN_LABEL(tableswitch),
602 INSN_LABEL(lookupswitch),
603 INSN_LABEL(ireturn),
604 INSN_LABEL(lreturn),
605 INSN_LABEL(freturn),
606 INSN_LABEL(dreturn),
607 INSN_LABEL(areturn),
608 INSN_LABEL(return),
609 INSN_LABEL(getstatic),
610 INSN_LABEL(putstatic),
611 INSN_LABEL(getfield),
612 INSN_LABEL(putfield),
613 INSN_LABEL(invokevirtual),
614 INSN_LABEL(invokespecial),
615 INSN_LABEL(invokestatic),
616 INSN_LABEL(invokeinterface),
617 0, /* op_xxxunusedxxx1, */
618 INSN_LABEL(new),
619 INSN_LABEL(newarray),
620 INSN_LABEL(anewarray),
621 INSN_LABEL(arraylength),
622 INSN_LABEL(athrow),
623 INSN_LABEL(checkcast),
624 INSN_LABEL(instanceof),
625 INSN_LABEL(monitorenter),
626 INSN_LABEL(monitorexit),
627 INSN_LABEL(wide),
628 INSN_LABEL(multianewarray),
629 INSN_LABEL(ifnull),
630 INSN_LABEL(ifnonnull),
631 INSN_LABEL(goto_w),
632 INSN_LABEL(jsr_w),
634 INSN_LABEL(putfield_1),
635 INSN_LABEL(putfield_2),
636 INSN_LABEL(putfield_4),
637 INSN_LABEL(putfield_8),
638 INSN_LABEL(putfield_a),
640 INSN_LABEL(putstatic_1),
641 INSN_LABEL(putstatic_2),
642 INSN_LABEL(putstatic_4),
643 INSN_LABEL(putstatic_8),
644 INSN_LABEL(putstatic_a),
646 INSN_LABEL(getfield_1),
647 INSN_LABEL(getfield_2s),
648 INSN_LABEL(getfield_2u),
649 INSN_LABEL(getfield_4),
650 INSN_LABEL(getfield_8),
651 INSN_LABEL(getfield_a),
653 INSN_LABEL(getstatic_1),
654 INSN_LABEL(getstatic_2s),
655 INSN_LABEL(getstatic_2u),
656 INSN_LABEL(getstatic_4),
657 INSN_LABEL(getstatic_8),
658 INSN_LABEL(getstatic_a),
661 #define SAVE_PC inv->pc = pc-1
663 /* If the macro INLINE_SWITCH is not defined, then the main loop
664 operates as one big (normal) switch statement. If it is defined,
665 then the case selection is performed `inline' in the end of the
666 code for each case. The latter saves a native branch instruction
667 for each java-instruction, but expands the code size somewhat.
669 NOTE: On i386 defining INLINE_SWITCH improves over all
670 performance approximately seven percent, but it may be different
671 for other machines. At some point, this may be made into a proper
672 configuration parameter. */
674 #define INLINE_SWITCH
676 #ifdef INLINE_SWITCH
678 #define NEXT_INSN GOTO_INSN(*pc++)
679 NEXT_INSN;
680 #else
682 #define NEXT_INSN goto next_insn
684 next_insn:
685 GOTO_INSN (*pc++);
687 #endif
689 /* The first few instructions here are ordered according to their
690 frequency, in the hope that this will improve code locality a
691 little. */
693 insn_aload_0: // 0x2a
694 LOADA(0);
695 NEXT_INSN;
697 insn_iload: // 0x15
698 LOADI (get1u (pc++));
699 NEXT_INSN;
701 insn_getfield_4: // 0xd8
702 SAVE_PC;
704 jobject obj = POPA();
705 NULLCHECK(obj);
706 jint field_offset = get2u (pc); pc += 2;
707 PUSHI (*(jint*) ((char*)obj + field_offset));
709 NEXT_INSN;
711 insn_iload_1: // 0x1b
712 LOADI (1);
713 NEXT_INSN;
715 insn_getfield_a: // 0xda
716 SAVE_PC;
718 jobject obj = POPA();
719 NULLCHECK(obj);
720 jint field_offset = get2u (pc); pc += 2;
721 PUSHA(*(jobject*) ((char*)obj + field_offset));
723 NEXT_INSN;
725 insn_invokevirtual: // 0xb6
726 SAVE_PC;
728 int index = get2u (pc); pc += 2;
730 /* _Jv_ResolvePoolEntry returns immediately if the value already
731 * is resolved. If we want to clutter up the code here to gain
732 * a little performance, then we can check the corresponding bit
733 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
734 * don't think it is worth it. */
736 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
738 sp -= rmeth->stack_item_count;
739 NULLCHECK(sp[0]);
741 if (rmeth->vtable_index == -1)
743 // final methods do not appear in the vtable,
744 // if it does not appear in the superclass.
745 fun = (void (*) (...)) rmeth->method->ncode;
747 else
749 jobject rcv = sp[0].o;
750 _Jv_VTable *table = *(_Jv_VTable**)rcv;
751 fun = (void (*) (...))table->method[rmeth->vtable_index];
754 goto perform_invoke;
756 perform_invoke:
758 /* here goes the magic again... */
759 ffi_cif *cif = &rmeth->cif;
760 ffi_raw *raw = (ffi_raw*) sp;
762 jdouble rvalue;
764 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
766 int rtype = cif->rtype->type;
768 /* the likelyhood of object, int, or void return is very high,
769 * so those are checked before the switch */
770 if (rtype == FFI_TYPE_POINTER)
772 PUSHA (*(jobject*)&rvalue);
774 else if (rtype == FFI_TYPE_SINT32)
776 PUSHI (*(jint*)&rvalue);
778 else if (rtype == FFI_TYPE_VOID)
780 /* skip */
782 else switch (rtype)
784 case FFI_TYPE_SINT8:
786 jbyte value = (*(jint*)&rvalue) & 0xff;
787 PUSHI (value);
789 break;
791 case FFI_TYPE_SINT16:
793 jshort value = (*(jint*)&rvalue) & 0xffff;
794 PUSHI (value);
796 break;
798 case FFI_TYPE_UINT16:
800 jint value = (*(jint*)&rvalue) & 0xffff;
801 PUSHI (value);
803 break;
805 case FFI_TYPE_FLOAT:
806 PUSHF (*(jfloat*)&rvalue);
807 break;
809 case FFI_TYPE_DOUBLE:
810 PUSHD (rvalue);
811 break;
813 case FFI_TYPE_SINT64:
814 PUSHL (*(jlong*)&rvalue);
815 break;
817 default:
818 throw_internal_error ("unknown return type in invokeXXX");
822 NEXT_INSN;
825 insn_nop:
826 NEXT_INSN;
828 insn_aconst_null:
829 PUSHA (NULL);
830 NEXT_INSN;
832 insn_iconst_m1:
833 PUSHI (-1);
834 NEXT_INSN;
836 insn_iconst_0:
837 PUSHI (0);
838 NEXT_INSN;
840 insn_iconst_1:
841 PUSHI (1);
842 NEXT_INSN;
844 insn_iconst_2:
845 PUSHI (2);
846 NEXT_INSN;
848 insn_iconst_3:
849 PUSHI (3);
850 NEXT_INSN;
852 insn_iconst_4:
853 PUSHI (4);
854 NEXT_INSN;
856 insn_iconst_5:
857 PUSHI (5);
858 NEXT_INSN;
860 insn_lconst_0:
861 PUSHL (0);
862 NEXT_INSN;
864 insn_lconst_1:
865 PUSHL (1);
866 NEXT_INSN;
868 insn_fconst_0:
869 PUSHF (0);
870 NEXT_INSN;
872 insn_fconst_1:
873 PUSHF (1);
874 NEXT_INSN;
876 insn_fconst_2:
877 PUSHF (2);
878 NEXT_INSN;
880 insn_dconst_0:
881 PUSHD (0);
882 NEXT_INSN;
884 insn_dconst_1:
885 PUSHD (1);
886 NEXT_INSN;
888 insn_bipush:
889 PUSHI (get1s(pc++));
890 NEXT_INSN;
892 insn_sipush:
893 PUSHI (get2s(pc)); pc += 2;
894 NEXT_INSN;
896 insn_ldc:
898 int index = get1u (pc++);
899 PUSHA(pool_data[index].o);
901 NEXT_INSN;
903 insn_ldc_w:
905 int index = get2u (pc); pc += 2;
906 PUSHA(pool_data[index].o);
908 NEXT_INSN;
910 insn_ldc2_w:
912 int index = get2u (pc); pc += 2;
913 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
914 sp += 2;
916 NEXT_INSN;
918 insn_lload:
919 LOADL (get1u (pc++));
920 NEXT_INSN;
922 insn_fload:
923 LOADF (get1u (pc++));
924 NEXT_INSN;
926 insn_dload:
927 LOADD (get1u (pc++));
928 NEXT_INSN;
930 insn_aload:
931 LOADA (get1u (pc++));
932 NEXT_INSN;
934 insn_iload_0:
935 LOADI (0);
936 NEXT_INSN;
938 insn_iload_2:
939 LOADI (2);
940 NEXT_INSN;
942 insn_iload_3:
943 LOADI (3);
944 NEXT_INSN;
946 insn_lload_0:
947 LOADL (0);
948 NEXT_INSN;
950 insn_lload_1:
951 LOADL (1);
952 NEXT_INSN;
954 insn_lload_2:
955 LOADL (2);
956 NEXT_INSN;
958 insn_lload_3:
959 LOADL (3);
960 NEXT_INSN;
962 insn_fload_0:
963 LOADF (0);
964 NEXT_INSN;
966 insn_fload_1:
967 LOADF (1);
968 NEXT_INSN;
970 insn_fload_2:
971 LOADF (2);
972 NEXT_INSN;
974 insn_fload_3:
975 LOADF (3);
976 NEXT_INSN;
978 insn_dload_0:
979 LOADD (0);
980 NEXT_INSN;
982 insn_dload_1:
983 LOADD (1);
984 NEXT_INSN;
986 insn_dload_2:
987 LOADD (2);
988 NEXT_INSN;
990 insn_dload_3:
991 LOADD (3);
992 NEXT_INSN;
994 insn_aload_1:
995 LOADA(1);
996 NEXT_INSN;
998 insn_aload_2:
999 LOADA(2);
1000 NEXT_INSN;
1002 insn_aload_3:
1003 LOADA(3);
1004 NEXT_INSN;
1006 insn_iaload:
1007 SAVE_PC;
1009 jint index = POPI();
1010 jintArray arr = (jintArray) POPA();
1011 NULLCHECK (arr);
1012 if (index < 0 || index >= arr->length)
1014 _Jv_ThrowBadArrayIndex (index);
1016 PUSHI( elements(arr)[index] );
1018 NEXT_INSN;
1020 insn_laload:
1021 SAVE_PC;
1023 jint index = POPI();
1024 jlongArray arr = (jlongArray) POPA();
1025 NULLCHECK (arr);
1026 if (index < 0 || index >= arr->length)
1028 _Jv_ThrowBadArrayIndex (index);
1030 PUSHL( elements(arr)[index] );
1032 NEXT_INSN;
1034 insn_faload:
1035 SAVE_PC;
1037 jint index = POPI();
1038 jfloatArray arr = (jfloatArray) POPA();
1039 NULLCHECK (arr);
1040 if (index < 0 || index >= arr->length)
1042 _Jv_ThrowBadArrayIndex (index);
1044 PUSHF( elements(arr)[index] );
1046 NEXT_INSN;
1048 insn_daload:
1049 SAVE_PC;
1051 jint index = POPI();
1052 jdoubleArray arr = (jdoubleArray) POPA();
1053 NULLCHECK (arr);
1054 if (index < 0 || index >= arr->length)
1056 _Jv_ThrowBadArrayIndex (index);
1058 PUSHD( elements(arr)[index] );
1060 NEXT_INSN;
1062 insn_aaload:
1063 SAVE_PC;
1065 jint index = POPI();
1066 jobjectArray arr = (jobjectArray) POPA();
1067 NULLCHECK (arr);
1068 if (index < 0 || index >= arr->length)
1070 _Jv_ThrowBadArrayIndex (index);
1072 PUSHA( elements(arr)[index] );
1074 NEXT_INSN;
1076 insn_baload:
1077 SAVE_PC;
1079 jint index = POPI();
1080 jbyteArray arr = (jbyteArray) POPA();
1081 NULLCHECK (arr);
1082 if (index < 0 || index >= arr->length)
1084 _Jv_ThrowBadArrayIndex (index);
1086 PUSHI( elements(arr)[index] );
1088 NEXT_INSN;
1090 insn_caload:
1091 SAVE_PC;
1093 jint index = POPI();
1094 jcharArray arr = (jcharArray) POPA();
1095 NULLCHECK (arr);
1096 if (index < 0 || index >= arr->length)
1098 _Jv_ThrowBadArrayIndex (index);
1100 PUSHI( elements(arr)[index] );
1102 NEXT_INSN;
1104 insn_saload:
1105 SAVE_PC;
1107 jint index = POPI();
1108 jshortArray arr = (jshortArray) POPA();
1109 NULLCHECK (arr);
1110 if (index < 0 || index >= arr->length)
1112 _Jv_ThrowBadArrayIndex (index);
1114 PUSHI( elements(arr)[index] );
1116 NEXT_INSN;
1118 insn_istore:
1119 STOREI (get1u (pc++));
1120 NEXT_INSN;
1122 insn_lstore:
1123 STOREL (get1u (pc++));
1124 NEXT_INSN;
1126 insn_fstore:
1127 STOREF (get1u (pc++));
1128 NEXT_INSN;
1130 insn_dstore:
1131 STORED (get1u (pc++));
1132 NEXT_INSN;
1134 insn_astore:
1135 STOREI (get1u (pc++));
1136 NEXT_INSN;
1138 insn_istore_0:
1139 STOREI (0);
1140 NEXT_INSN;
1142 insn_istore_1:
1143 STOREI (1);
1144 NEXT_INSN;
1146 insn_istore_2:
1147 STOREI (2);
1148 NEXT_INSN;
1150 insn_istore_3:
1151 STOREI (3);
1152 NEXT_INSN;
1154 insn_lstore_0:
1155 STOREL (0);
1156 NEXT_INSN;
1158 insn_lstore_1:
1159 STOREL (1);
1160 NEXT_INSN;
1162 insn_lstore_2:
1163 STOREL (2);
1164 NEXT_INSN;
1166 insn_lstore_3:
1167 STOREL (3);
1168 NEXT_INSN;
1170 insn_fstore_0:
1171 STOREF (0);
1172 NEXT_INSN;
1174 insn_fstore_1:
1175 STOREF (1);
1176 NEXT_INSN;
1178 insn_fstore_2:
1179 STOREF (2);
1180 NEXT_INSN;
1182 insn_fstore_3:
1183 STOREF (3);
1184 NEXT_INSN;
1186 insn_dstore_0:
1187 STORED (0);
1188 NEXT_INSN;
1190 insn_dstore_1:
1191 STORED (1);
1192 NEXT_INSN;
1194 insn_dstore_2:
1195 STORED (2);
1196 NEXT_INSN;
1198 insn_dstore_3:
1199 STORED (3);
1200 NEXT_INSN;
1202 insn_astore_0:
1203 STOREA(0);
1204 NEXT_INSN;
1206 insn_astore_1:
1207 STOREA(1);
1208 NEXT_INSN;
1210 insn_astore_2:
1211 STOREA(2);
1212 NEXT_INSN;
1214 insn_astore_3:
1215 STOREA(3);
1216 NEXT_INSN;
1218 insn_iastore:
1219 SAVE_PC;
1221 jint value = POPI();
1222 jint index = POPI();
1223 jintArray arr = (jintArray) POPA();
1224 NULLCHECK (arr);
1225 if (index < 0 || index >= arr->length)
1227 _Jv_ThrowBadArrayIndex (index);
1229 elements(arr)[index] = value;
1231 NEXT_INSN;
1233 insn_lastore:
1234 SAVE_PC;
1236 jlong value = POPL();
1237 jint index = POPI();
1238 jlongArray arr = (jlongArray) POPA();
1239 NULLCHECK (arr);
1240 if (index < 0 || index >= arr->length)
1242 _Jv_ThrowBadArrayIndex (index);
1244 elements(arr)[index] = value;
1246 NEXT_INSN;
1248 insn_fastore:
1249 SAVE_PC;
1251 jfloat value = POPF();
1252 jint index = POPI();
1253 jfloatArray arr = (jfloatArray) POPA();
1254 NULLCHECK (arr);
1255 if (index < 0 || index >= arr->length)
1257 _Jv_ThrowBadArrayIndex (index);
1259 elements(arr)[index] = value;
1261 NEXT_INSN;
1263 insn_dastore:
1264 SAVE_PC;
1266 jdouble value = POPD();
1267 jint index = POPI();
1268 jdoubleArray arr = (jdoubleArray) POPA();
1269 NULLCHECK (arr);
1270 if (index < 0 || index >= arr->length)
1272 _Jv_ThrowBadArrayIndex (index);
1274 elements(arr)[index] = value;
1276 NEXT_INSN;
1278 insn_aastore:
1279 SAVE_PC;
1281 jobject value = POPA();
1282 jint index = POPI();
1283 jobjectArray arr = (jobjectArray) POPA();
1284 NULLCHECK (arr);
1285 if (index < 0 || index >= arr->length)
1287 _Jv_ThrowBadArrayIndex (index);
1289 _Jv_CheckArrayStore (arr, value);
1290 elements(arr)[index] = value;
1292 NEXT_INSN;
1294 insn_bastore:
1295 SAVE_PC;
1297 jbyte value = (jbyte) POPI();
1298 jint index = POPI();
1299 jbyteArray arr = (jbyteArray) POPA();
1300 NULLCHECK (arr);
1301 if (index < 0 || index >= arr->length)
1303 _Jv_ThrowBadArrayIndex (index);
1305 elements(arr)[index] = value;
1307 NEXT_INSN;
1309 insn_castore:
1310 SAVE_PC;
1312 jchar value = (jchar) POPI();
1313 jint index = POPI();
1314 jcharArray arr = (jcharArray) POPA();
1315 NULLCHECK (arr);
1316 if (index < 0 || index >= arr->length)
1318 _Jv_ThrowBadArrayIndex (index);
1320 elements(arr)[index] = value;
1322 NEXT_INSN;
1324 insn_sastore:
1325 SAVE_PC;
1327 jshort value = (jshort) POPI();
1328 jint index = POPI();
1329 jshortArray arr = (jshortArray) POPA();
1330 NULLCHECK (arr);
1331 if (index < 0 || index >= arr->length)
1333 _Jv_ThrowBadArrayIndex (index);
1335 elements(arr)[index] = value;
1337 NEXT_INSN;
1339 insn_pop:
1340 sp -= 1;
1341 NEXT_INSN;
1343 insn_pop2:
1344 sp -= 2;
1345 NEXT_INSN;
1347 insn_dup:
1348 sp[0] = sp[-1];
1349 sp += 1;
1350 NEXT_INSN;
1352 insn_dup_x1:
1353 dupx (sp, 1, 1); sp+=1;
1354 NEXT_INSN;
1356 insn_dup_x2:
1357 dupx (sp, 1, 2); sp+=1;
1358 NEXT_INSN;
1360 insn_dup2:
1361 sp[0] = sp[-2];
1362 sp[1] = sp[-1];
1363 sp += 2;
1364 NEXT_INSN;
1366 insn_dup2_x1:
1367 dupx (sp, 2, 1); sp+=2;
1368 NEXT_INSN;
1370 insn_dup2_x2:
1371 dupx (sp, 2, 2); sp+=2;
1372 NEXT_INSN;
1374 insn_swap:
1376 jobject tmp1 = POPA();
1377 jobject tmp2 = POPA();
1378 PUSHA (tmp1);
1379 PUSHA (tmp2);
1381 NEXT_INSN;
1383 insn_iadd:
1384 BINOPI(+);
1385 NEXT_INSN;
1387 insn_ladd:
1388 BINOPL(+);
1389 NEXT_INSN;
1391 insn_fadd:
1392 BINOPF(+);
1393 NEXT_INSN;
1395 insn_dadd:
1396 BINOPD(+);
1397 NEXT_INSN;
1399 insn_isub:
1400 BINOPI(-);
1401 NEXT_INSN;
1403 insn_lsub:
1404 BINOPL(-);
1405 NEXT_INSN;
1407 insn_fsub:
1408 BINOPF(-);
1409 NEXT_INSN;
1411 insn_dsub:
1412 BINOPD(-);
1413 NEXT_INSN;
1415 insn_imul:
1416 BINOPI(*);
1417 NEXT_INSN;
1419 insn_lmul:
1420 BINOPL(*);
1421 NEXT_INSN;
1423 insn_fmul:
1424 BINOPF(*);
1425 NEXT_INSN;
1427 insn_dmul:
1428 BINOPD(*);
1429 NEXT_INSN;
1431 insn_idiv:
1432 SAVE_PC;
1434 jint value2 = POPI();
1435 jint value1 = POPI();
1436 ZEROCHECK (value2);
1437 jint res = value1 / value2;
1438 PUSHI (res);
1440 NEXT_INSN;
1442 insn_ldiv:
1443 SAVE_PC;
1445 jlong value2 = POPL();
1446 jlong value1 = POPL();
1447 ZEROCHECK (value2);
1448 jlong res = value1 / value2;
1449 PUSHL (res);
1451 NEXT_INSN;
1453 insn_fdiv:
1454 SAVE_PC;
1456 jfloat value2 = POPF();
1457 jfloat value1 = POPF();
1458 ZEROCHECK (value2);
1459 jfloat res = value1 / value2;
1460 PUSHF (res);
1462 NEXT_INSN;
1464 insn_ddiv:
1465 SAVE_PC;
1467 jdouble value2 = POPD();
1468 jdouble value1 = POPD();
1469 ZEROCHECK (value2);
1470 jdouble res = value1 / value2;
1471 PUSHD (res);
1473 NEXT_INSN;
1475 insn_irem:
1476 SAVE_PC;
1478 jint value2 = POPI();
1479 jint value1 = POPI();
1480 ZEROCHECK (value2);
1481 jint res = value1 % value2;
1482 PUSHI (res);
1484 NEXT_INSN;
1486 insn_lrem:
1487 SAVE_PC;
1489 jlong value2 = POPL();
1490 jlong value1 = POPL();
1491 ZEROCHECK (value2);
1492 jlong res = value1 % value2;
1493 PUSHL (res);
1495 NEXT_INSN;
1497 insn_frem:
1498 SAVE_PC;
1500 jfloat value2 = POPF();
1501 jfloat value1 = POPF();
1502 ZEROCHECK (value2);
1503 jfloat res = __ieee754_fmod (value1, value2);
1504 PUSHF (res);
1506 NEXT_INSN;
1508 insn_drem:
1509 SAVE_PC;
1511 jdouble value2 = POPD();
1512 jdouble value1 = POPD();
1513 ZEROCHECK (value2);
1514 jdouble res = __ieee754_fmod (value1, value2);
1515 PUSHD (res);
1517 NEXT_INSN;
1519 insn_ineg:
1521 jint value = POPI();
1522 PUSHI (value * -1);
1524 NEXT_INSN;
1526 insn_lneg:
1528 jlong value = POPL();
1529 PUSHL (value * -1);
1531 NEXT_INSN;
1533 insn_fneg:
1535 jfloat value = POPF();
1536 PUSHF (value * -1);
1538 NEXT_INSN;
1540 insn_dneg:
1542 jdouble value = POPD();
1543 PUSHD (value * -1);
1545 NEXT_INSN;
1547 insn_ishl:
1549 jint shift = (POPI() & 0x1f);
1550 jint value = POPI();
1551 PUSHI (value << shift);
1553 NEXT_INSN;
1555 insn_lshl:
1557 jint shift = (POPI() & 0x3f);
1558 jlong value = POPL();
1559 PUSHL (value << shift);
1561 NEXT_INSN;
1563 insn_ishr:
1565 jint shift = (POPI() & 0x1f);
1566 jint value = POPI();
1567 PUSHI (value >> shift);
1569 NEXT_INSN;
1571 insn_lshr:
1573 jint shift = (POPI() & 0x3f);
1574 jlong value = POPL();
1575 PUSHL (value >> shift);
1577 NEXT_INSN;
1579 insn_iushr:
1581 jint shift = (POPI() & 0x1f);
1582 unsigned long value = POPI();
1583 PUSHI ((jint) (value >> shift));
1585 NEXT_INSN;
1587 insn_lushr:
1589 jint shift = (POPI() & 0x3f);
1590 UINT64 value = (UINT64) POPL();
1591 PUSHL ((value >> shift));
1593 NEXT_INSN;
1595 insn_iand:
1596 BINOPI (&);
1597 NEXT_INSN;
1599 insn_land:
1600 BINOPL (&);
1601 NEXT_INSN;
1603 insn_ior:
1604 BINOPI (|);
1605 NEXT_INSN;
1607 insn_lor:
1608 BINOPL (|);
1609 NEXT_INSN;
1611 insn_ixor:
1612 BINOPI (^);
1613 NEXT_INSN;
1615 insn_lxor:
1616 BINOPL (^);
1617 NEXT_INSN;
1619 insn_iinc:
1621 jint index = get1u (pc++);
1622 jint amount = get1s (pc++);
1623 locals[index].i += amount;
1625 NEXT_INSN;
1627 insn_i2l:
1628 {jlong value = POPI(); PUSHL (value);}
1629 NEXT_INSN;
1631 insn_i2f:
1632 {jfloat value = POPI(); PUSHF (value);}
1633 NEXT_INSN;
1635 insn_i2d:
1636 {jdouble value = POPI(); PUSHD (value);}
1637 NEXT_INSN;
1639 insn_l2i:
1640 {jint value = POPL(); PUSHI (value);}
1641 NEXT_INSN;
1643 insn_l2f:
1644 {jfloat value = POPL(); PUSHF (value);}
1645 NEXT_INSN;
1647 insn_l2d:
1648 {jdouble value = POPL(); PUSHD (value);}
1649 NEXT_INSN;
1651 insn_f2i:
1652 { jint value = (jint)POPF (); PUSHI(value); }
1653 NEXT_INSN;
1655 insn_f2l:
1656 { jlong value = (jlong)POPF (); PUSHL(value); }
1657 NEXT_INSN;
1659 insn_f2d:
1660 { jdouble value = POPF (); PUSHD(value); }
1661 NEXT_INSN;
1663 insn_d2i:
1664 { jint value = (jint)POPD (); PUSHI(value); }
1665 NEXT_INSN;
1667 insn_d2l:
1668 { jlong value = (jlong)POPD (); PUSHL(value); }
1669 NEXT_INSN;
1671 insn_d2f:
1672 { jfloat value = POPD (); PUSHF(value); }
1673 NEXT_INSN;
1675 insn_i2b:
1676 { jbyte value = POPI (); PUSHI(value); }
1677 NEXT_INSN;
1679 insn_i2c:
1680 { jchar value = POPI (); PUSHI(value); }
1681 NEXT_INSN;
1683 insn_i2s:
1684 { jshort value = POPI (); PUSHI(value); }
1685 NEXT_INSN;
1687 insn_lcmp:
1689 jlong value2 = POPL ();
1690 jlong value1 = POPL ();
1691 if (value1 > value2)
1692 { PUSHI (1); }
1693 else if (value1 == value2)
1694 { PUSHI (0); }
1695 else
1696 { PUSHI (-1); }
1698 NEXT_INSN;
1700 insn_fcmpl:
1701 insn_fcmpg:
1703 jfloat value2 = POPF ();
1704 jfloat value1 = POPF ();
1705 if (value1 > value2)
1706 PUSHI (1);
1707 else if (value1 == value2)
1708 PUSHI (0);
1709 else if (value1 < value2)
1710 PUSHI (-1);
1711 else if ((*(pc-1)) == op_fcmpg)
1712 PUSHI (1);
1713 else
1714 PUSHI (-1);
1716 NEXT_INSN;
1718 insn_dcmpl:
1719 insn_dcmpg:
1721 jdouble value2 = POPD ();
1722 jdouble value1 = POPD ();
1723 if (value1 > value2)
1724 PUSHI (1);
1725 else if (value1 == value2)
1726 PUSHI (0);
1727 else if (value1 < value2)
1728 PUSHI (-1);
1729 else if ((*(pc-1)) == op_dcmpg)
1730 PUSHI (1);
1731 else
1732 PUSHI (-1);
1734 NEXT_INSN;
1736 insn_ifeq:
1738 jint offset = get2s (pc);
1739 if (POPI() == 0)
1740 pc = pc-1+offset;
1741 else
1742 pc = pc+2;
1744 NEXT_INSN;
1746 insn_ifne:
1748 jint offset = get2s (pc);
1749 if (POPI() != 0)
1750 pc = pc-1+offset;
1751 else
1752 pc = pc+2;
1754 NEXT_INSN;
1756 insn_iflt:
1758 jint offset = get2s (pc);
1759 if (POPI() < 0)
1760 pc = pc-1+offset;
1761 else
1762 pc = pc+2;
1764 NEXT_INSN;
1766 insn_ifge:
1768 jint offset = get2s (pc);
1769 if (POPI() >= 0)
1770 pc = pc-1+offset;
1771 else
1772 pc = pc+2;
1774 NEXT_INSN;
1776 insn_ifgt:
1778 jint offset = get2s (pc);
1779 if (POPI() > 0)
1780 pc = pc-1+offset;
1781 else
1782 pc = pc+2;
1784 NEXT_INSN;
1786 insn_ifle:
1788 jint offset = get2s (pc);
1789 if (POPI() <= 0)
1790 pc = pc-1+offset;
1791 else
1792 pc = pc+2;
1794 NEXT_INSN;
1796 insn_if_icmpeq:
1798 jint offset = get2s (pc);
1799 jint value2 = POPI();
1800 jint value1 = POPI();
1801 if (value1 == value2)
1802 pc = pc-1+offset;
1803 else
1804 pc = pc+2;
1806 NEXT_INSN;
1808 insn_if_icmpne:
1810 jint offset = get2s (pc);
1811 jint value2 = POPI();
1812 jint value1 = POPI();
1813 if (value1 != value2)
1814 pc = pc-1+offset;
1815 else
1816 pc = pc+2;
1818 NEXT_INSN;
1820 insn_if_icmplt:
1822 jint offset = get2s (pc);
1823 jint value2 = POPI();
1824 jint value1 = POPI();
1825 if (value1 < value2)
1826 pc = pc-1+offset;
1827 else
1828 pc = pc+2;
1830 NEXT_INSN;
1832 insn_if_icmpge:
1834 jint offset = get2s (pc);
1835 jint value2 = POPI();
1836 jint value1 = POPI();
1837 if (value1 >= value2)
1838 pc = pc-1+offset;
1839 else
1840 pc = pc+2;
1842 NEXT_INSN;
1844 insn_if_icmpgt:
1846 jint offset = get2s (pc);
1847 jint value2 = POPI();
1848 jint value1 = POPI();
1849 if (value1 > value2)
1850 pc = pc-1+offset;
1851 else
1852 pc = pc+2;
1854 NEXT_INSN;
1856 insn_if_icmple:
1858 jint offset = get2s (pc);
1859 jint value2 = POPI();
1860 jint value1 = POPI();
1861 if (value1 <= value2)
1862 pc = pc-1+offset;
1863 else
1864 pc = pc+2;
1866 NEXT_INSN;
1868 insn_if_acmpeq:
1870 jint offset = get2s (pc);
1871 jobject value2 = POPA();
1872 jobject value1 = POPA();
1873 if (value1 == value2)
1874 pc = pc-1+offset;
1875 else
1876 pc = pc+2;
1878 NEXT_INSN;
1880 insn_if_acmpne:
1882 jint offset = get2s (pc);
1883 jobject value2 = POPA();
1884 jobject value1 = POPA();
1885 if (value1 != value2)
1886 pc = pc-1+offset;
1887 else
1888 pc = pc+2;
1890 NEXT_INSN;
1892 insn_goto:
1894 jint offset = get2s (pc);
1895 pc = pc-1+offset;
1897 NEXT_INSN;
1899 insn_jsr:
1901 unsigned char *base_pc = pc-1;
1902 jint offset = get2s (pc); pc += 2;
1903 PUSHA ((jobject)pc);
1904 pc = base_pc+offset;
1906 NEXT_INSN;
1908 insn_ret:
1910 jint index = get1u (pc);
1911 pc = (unsigned char*) PEEKA (index);
1913 NEXT_INSN;
1915 insn_tableswitch:
1917 unsigned char *base_pc = pc-1;
1918 int index = POPI();
1920 unsigned char* base = bytecode ();
1921 while ((pc-base) % 4 != 0)
1922 pc++;
1924 jint def = get4 (pc);
1925 jint low = get4 (pc+4);
1926 jint high = get4 (pc+8);
1928 if (index < low || index > high)
1929 pc = base_pc + def;
1930 else
1931 pc = base_pc + get4 (pc+4*(index-low+3));
1933 NEXT_INSN;
1935 insn_lookupswitch:
1937 unsigned char *base_pc = pc-1;
1938 int index = POPI();
1940 unsigned char* base = bytecode ();
1941 while ((pc-base) % 4 != 0)
1942 pc++;
1944 jint def = get4 (pc);
1945 jint npairs = get4 (pc+4);
1947 int max = npairs-1;
1948 int min = 0;
1950 // simple binary search...
1951 while (min < max)
1953 int half = (min+max)/2;
1954 int match = get4 (pc+ 4*(2 + 2*half));
1956 if (index == match)
1957 min = max = half;
1959 else if (index < match)
1960 max = half-1;
1962 else
1963 min = half+1;
1966 if (index == get4 (pc+ 4*(2 + 2*min)))
1967 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1968 else
1969 pc = base_pc + def;
1971 NEXT_INSN;
1973 /* on return, just save the sp and return to caller */
1974 insn_ireturn:
1975 insn_lreturn:
1976 insn_freturn:
1977 insn_dreturn:
1978 insn_areturn:
1979 insn_return:
1980 inv->sp = sp;
1981 return;
1983 insn_getstatic:
1984 SAVE_PC;
1986 unsigned char *base_pc = pc-1;
1987 jint fieldref_index = get2u (pc); pc += 2;
1988 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1989 _Jv_Field *field = pool_data[fieldref_index].field;
1991 if ((field->flags & Modifier::STATIC) == 0)
1992 throw_incompatible_class_change_error
1993 (JvNewStringLatin1 ("field no longer static"));
1995 jclass type = field->type;
1997 if (type->isPrimitive ())
1999 switch (type->size_in_bytes)
2001 case 1:
2002 *base_pc = op_getstatic_1;
2003 break;
2005 case 2:
2006 if (type == JvPrimClass (char))
2007 *base_pc = op_getstatic_2u;
2008 else
2009 *base_pc = op_getstatic_2s;
2010 break;
2012 case 4:
2013 *base_pc = op_getstatic_4;
2014 break;
2016 case 8:
2017 *base_pc = op_getstatic_8;
2018 break;
2021 else
2023 *base_pc = op_getstatic_a;
2026 pc = base_pc;
2028 NEXT_INSN;
2030 insn_getfield:
2031 SAVE_PC;
2033 unsigned char *base_pc = pc-1;
2034 jint fieldref_index = get2u (pc); pc += 2;
2035 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2036 _Jv_Field *field = pool_data[fieldref_index].field;
2038 if ((field->flags & Modifier::STATIC) != 0)
2039 throw_incompatible_class_change_error
2040 (JvNewStringLatin1 ("field is static"));
2042 jclass type = field->type;
2044 if (type->isPrimitive ())
2046 switch (type->size_in_bytes)
2048 case 1:
2049 *base_pc = op_getfield_1;
2050 break;
2052 case 2:
2053 if (type == JvPrimClass (char))
2054 *base_pc = op_getfield_2u;
2055 else
2056 *base_pc = op_getfield_2s;
2057 break;
2059 case 4:
2060 *base_pc = op_getfield_4;
2061 break;
2063 case 8:
2064 *base_pc = op_getfield_8;
2065 break;
2068 else
2070 *base_pc = op_getfield_a;
2073 if (field->u.boffset > 0xffff)
2074 JvThrow (new java::lang::VirtualMachineError);
2076 base_pc[1] = (field->u.boffset>>8) & 0xff;
2077 base_pc[2] = field->u.boffset & 0xff;
2079 pc = base_pc;
2081 NEXT_INSN;
2083 insn_putstatic:
2084 SAVE_PC;
2086 unsigned char* base_pc = pc-1;
2087 jint fieldref_index = get2u (pc); pc += 2;
2088 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2089 _Jv_Field *field = pool_data[fieldref_index].field;
2091 jclass type = field->type;
2093 // ResolvePoolEntry cannot check this
2094 if ((field->flags & Modifier::STATIC) == 0)
2095 throw_incompatible_class_change_error
2096 (JvNewStringLatin1 ("field no longer static"));
2098 /* if this is patented, then maybe we could install
2099 a function in the constant pool, to do the right thing */
2101 if (type->isPrimitive ())
2103 switch (type->size_in_bytes)
2105 case 1:
2106 *base_pc = op_putstatic_1;
2107 break;
2109 case 2:
2110 *base_pc = op_putstatic_2;
2111 break;
2113 case 4:
2114 *base_pc = op_putstatic_4;
2115 break;
2117 case 8:
2118 *base_pc = op_putstatic_8;
2119 break;
2122 else
2124 *base_pc = op_putstatic_a;
2127 // do the instruction again!
2128 pc = base_pc;
2130 NEXT_INSN;
2133 insn_putfield:
2134 SAVE_PC;
2136 unsigned char* base_pc = pc-1;
2137 jint fieldref_index = get2u (pc); pc += 2;
2138 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2139 _Jv_Field *field = pool_data[fieldref_index].field;
2141 jclass type = field->type;
2143 if ((field->flags & Modifier::STATIC) != 0)
2144 throw_incompatible_class_change_error
2145 (JvNewStringLatin1 ("field is static"));
2147 if (type->isPrimitive ())
2149 switch (type->size_in_bytes)
2151 case 1:
2152 *base_pc = op_putfield_1;
2153 break;
2155 case 2:
2156 *base_pc = op_putfield_2;
2157 break;
2159 case 4:
2160 *base_pc = op_putfield_4;
2161 break;
2163 case 8:
2164 *base_pc = op_putfield_8;
2165 break;
2168 else
2170 *base_pc = op_putfield_a;
2173 if (field->u.boffset > 0xffff)
2174 JvThrow (new java::lang::VirtualMachineError);
2176 base_pc[1] = (field->u.boffset>>8) & 0xff;
2177 base_pc[2] = field->u.boffset & 0xff;
2179 // do the instruction again!
2180 pc = base_pc;
2182 NEXT_INSN;
2185 insn_getfield_1:
2186 SAVE_PC;
2188 jobject obj = POPA();
2189 NULLCHECK(obj);
2190 jint field_offset = get2u (pc); pc += 2;
2191 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2193 NEXT_INSN;
2195 insn_getfield_2s:
2196 SAVE_PC;
2198 jobject obj = POPA();
2199 NULLCHECK(obj);
2200 jint field_offset = get2u (pc); pc += 2;
2201 PUSHI (*(jshort*) ((char*)obj + field_offset));
2203 NEXT_INSN;
2205 insn_getfield_2u:
2206 SAVE_PC;
2208 jobject obj = POPA();
2209 NULLCHECK(obj);
2210 jint field_offset = get2u (pc); pc += 2;
2211 PUSHI (*(jchar*) ((char*)obj + field_offset));
2213 NEXT_INSN;
2215 insn_getfield_8:
2216 SAVE_PC;
2218 jobject obj = POPA();
2219 NULLCHECK(obj);
2220 jint field_offset = get2u (pc); pc += 2;
2221 PUSHL(*(jlong*) ((char*)obj + field_offset));
2223 NEXT_INSN;
2225 insn_getstatic_1:
2227 jint fieldref_index = get2u (pc); pc += 2;
2228 _Jv_Field *field = pool_data[fieldref_index].field;
2229 PUSHI (*(jbyte*) (field->u.addr));
2231 NEXT_INSN;
2233 insn_getstatic_2s:
2235 jint fieldref_index = get2u (pc); pc += 2;
2236 _Jv_Field *field = pool_data[fieldref_index].field;
2237 PUSHI(*(jshort*) (field->u.addr));
2239 NEXT_INSN;
2241 insn_getstatic_2u:
2243 jint fieldref_index = get2u (pc); pc += 2;
2244 _Jv_Field *field = pool_data[fieldref_index].field;
2245 PUSHI(*(jchar*) (field->u.addr));
2247 NEXT_INSN;
2249 insn_getstatic_4:
2251 jint fieldref_index = get2u (pc); pc += 2;
2252 _Jv_Field *field = pool_data[fieldref_index].field;
2253 PUSHI(*(jint*) (field->u.addr));
2255 NEXT_INSN;
2257 insn_getstatic_8:
2259 jint fieldref_index = get2u (pc); pc += 2;
2260 _Jv_Field *field = pool_data[fieldref_index].field;
2261 PUSHL(*(jlong*) (field->u.addr));
2263 NEXT_INSN;
2265 insn_getstatic_a:
2267 jint fieldref_index = get2u (pc); pc += 2;
2268 _Jv_Field *field = pool_data[fieldref_index].field;
2269 PUSHA(*(jobject*) (field->u.addr));
2271 NEXT_INSN;
2273 insn_putfield_1:
2274 SAVE_PC;
2276 jint value = POPI();
2277 jobject obj = POPA();
2278 NULLCHECK(obj);
2279 jint field_offset = get2u (pc); pc += 2;
2280 *(jbyte*) ((char*)obj + field_offset) = value;
2282 NEXT_INSN;
2284 insn_putfield_2:
2285 SAVE_PC;
2287 jint value = POPI();
2288 jobject obj = POPA();
2289 NULLCHECK(obj);
2290 jint field_offset = get2u (pc); pc += 2;
2291 *(jchar*) ((char*)obj + field_offset) = value;
2293 NEXT_INSN;
2295 insn_putfield_4:
2296 SAVE_PC;
2298 jint value = POPI();
2299 jobject obj = POPA();
2300 NULLCHECK(obj);
2301 jint field_offset = get2u (pc); pc += 2;
2302 *(jint*) ((char*)obj + field_offset) = value;
2304 NEXT_INSN;
2306 insn_putfield_8:
2307 SAVE_PC;
2309 jlong value = POPL();
2310 jobject obj = POPA();
2311 NULLCHECK(obj);
2312 jint field_offset = get2u (pc); pc += 2;
2313 *(jlong*) ((char*)obj + field_offset) = value;
2315 NEXT_INSN;
2317 insn_putfield_a:
2318 SAVE_PC;
2320 jobject value = POPA();
2321 jobject obj = POPA();
2322 NULLCHECK(obj);
2323 jint field_offset = get2u (pc); pc += 2;
2324 *(jobject*) ((char*)obj + field_offset) = value;
2326 NEXT_INSN;
2328 insn_putstatic_1:
2330 jint value = POPI();
2331 jint fieldref_index = get2u (pc); pc += 2;
2332 _Jv_Field *field = pool_data[fieldref_index].field;
2333 *(jbyte*) (field->u.addr) = value;
2335 NEXT_INSN;
2337 insn_putstatic_2:
2339 jint value = POPI();
2340 jint fieldref_index = get2u (pc); pc += 2;
2341 _Jv_Field *field = pool_data[fieldref_index].field;
2342 *(jchar*) (field->u.addr) = value;
2344 NEXT_INSN;
2346 insn_putstatic_4:
2348 jint value = POPI();
2349 jint fieldref_index = get2u (pc); pc += 2;
2350 _Jv_Field *field = pool_data[fieldref_index].field;
2351 *(jint*) (field->u.addr) = value;
2353 NEXT_INSN;
2355 insn_putstatic_8:
2357 jlong value = POPL();
2358 jint fieldref_index = get2u (pc); pc += 2;
2359 _Jv_Field *field = pool_data[fieldref_index].field;
2360 *(jlong*) (field->u.addr) = value;
2362 NEXT_INSN;
2364 insn_putstatic_a:
2366 jobject value = POPA();
2367 jint fieldref_index = get2u (pc); pc += 2;
2368 _Jv_Field *field = pool_data[fieldref_index].field;
2369 *(jobject*) (field->u.addr) = value;
2371 NEXT_INSN;
2373 insn_invokespecial:
2374 SAVE_PC;
2376 int index = get2u (pc); pc += 2;
2378 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2380 sp -= rmeth->stack_item_count;
2382 NULLCHECK(sp[0]);
2384 fun = (void (*) (...))rmeth->method->ncode;
2386 goto perform_invoke;
2388 insn_invokestatic:
2389 SAVE_PC;
2391 int index = get2u (pc); pc += 2;
2393 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2395 sp -= rmeth->stack_item_count;
2397 _Jv_InitClass (rmeth->klass);
2398 fun = (void (*) (...))rmeth->method->ncode;
2400 goto perform_invoke;
2402 insn_invokeinterface:
2403 SAVE_PC;
2405 int index = get2u (pc); pc += 2;
2407 // invokeinterface has two unused bytes...
2408 pc += 2;
2410 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2412 sp -= rmeth->stack_item_count;
2413 NULLCHECK(sp[0]);
2415 jobject rcv = sp[0].o;
2417 fun = (void (*) (...))
2418 _Jv_LookupInterfaceMethod (rcv->getClass (),
2419 rmeth->method->name,
2420 rmeth->method->signature);
2422 goto perform_invoke;
2425 insn_new:
2426 SAVE_PC;
2428 int index = get2u (pc); pc += 2;
2429 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2430 _Jv_InitClass (klass);
2431 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2432 PUSHA (res);
2434 NEXT_INSN;
2436 insn_newarray:
2437 SAVE_PC;
2439 int atype = get1u (pc++);
2440 int size = POPI();
2441 jobject result = _Jv_NewArray (atype, size);
2442 PUSHA (result);
2444 NEXT_INSN;
2446 insn_anewarray:
2447 SAVE_PC;
2449 int index = get2u (pc); pc += 2;
2450 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2451 int size = POPI();
2452 _Jv_InitClass (klass);
2453 jobject result = _Jv_NewObjectArray (size, klass, 0);
2454 PUSHA (result);
2456 NEXT_INSN;
2458 insn_arraylength:
2459 SAVE_PC;
2461 __JArray *arr = (__JArray*)POPA();
2462 PUSHI (arr->length);
2464 NEXT_INSN;
2466 insn_athrow:
2467 SAVE_PC;
2469 jobject value = POPA();
2470 JvThrow (value);
2472 NEXT_INSN;
2474 insn_checkcast:
2475 SAVE_PC;
2477 jobject value = POPA();
2478 jint index = get2u (pc); pc += 2;
2479 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2481 if (value != NULL && ! to->isInstance (value))
2483 JvThrow (new java::lang::ClassCastException
2484 (to->getName()));
2487 PUSHA (value);
2489 NEXT_INSN;
2491 insn_instanceof:
2492 SAVE_PC;
2494 jobject value = POPA();
2495 jint index = get2u (pc); pc += 2;
2496 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2497 PUSHI (to->isInstance (value));
2499 NEXT_INSN;
2501 insn_monitorenter:
2502 SAVE_PC;
2504 jobject value = POPA();
2505 NULLCHECK(value);
2506 _Jv_MonitorEnter (value);
2508 NEXT_INSN;
2510 insn_monitorexit:
2511 SAVE_PC;
2513 jobject value = POPA();
2514 NULLCHECK(value);
2515 _Jv_MonitorExit (value);
2517 NEXT_INSN;
2519 insn_ifnull:
2521 unsigned char* base_pc = pc-1;
2522 jint offset = get2s (pc); pc += 2;
2523 jobject val = POPA();
2524 if (val == NULL)
2525 pc = base_pc+offset;
2527 NEXT_INSN;
2529 insn_ifnonnull:
2531 unsigned char* base_pc = pc-1;
2532 jint offset = get2s (pc); pc += 2;
2533 jobject val = POPA();
2534 if (val != NULL)
2535 pc = base_pc+offset;
2537 NEXT_INSN;
2539 insn_wide:
2540 SAVE_PC;
2542 jint the_mod_op = get1u (pc++);
2543 jint wide = get2u (pc); pc += 2;
2545 switch (the_mod_op)
2547 case op_istore:
2548 STOREI (wide);
2549 NEXT_INSN;
2551 case op_fstore:
2552 STOREF (wide);
2553 NEXT_INSN;
2555 case op_astore:
2556 STOREA (wide);
2557 NEXT_INSN;
2559 case op_lload:
2560 LOADL (wide);
2561 NEXT_INSN;
2563 case op_dload:
2564 LOADD (wide);
2565 NEXT_INSN;
2567 case op_iload:
2568 LOADI (wide);
2569 NEXT_INSN;
2571 case op_aload:
2572 LOADA (wide);
2573 NEXT_INSN;
2575 case op_lstore:
2576 STOREL (wide);
2577 NEXT_INSN;
2579 case op_dstore:
2580 STORED (wide);
2581 NEXT_INSN;
2583 case op_ret:
2584 pc = (unsigned char*) PEEKA (wide);
2585 NEXT_INSN;
2587 case op_iinc:
2589 jint amount = get2s (pc); pc += 2;
2590 jint value = PEEKI (wide);
2591 POKEI (wide, value+amount);
2593 NEXT_INSN;
2595 default:
2596 throw_internal_error ("illegal bytecode modified by wide");
2601 insn_multianewarray:
2602 SAVE_PC;
2604 int kind_index = get2u (pc); pc += 2;
2605 int dim = get1u (pc); pc += 1;
2607 jclass type
2608 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2609 _Jv_InitClass (type);
2610 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2612 for (int i = dim - 1; i >= 0; i--)
2614 sizes[i] = POPI ();
2617 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2619 PUSHA (res);
2621 NEXT_INSN;
2623 insn_goto_w:
2625 unsigned char* base_pc = pc-1;
2626 int offset = get4 (pc); pc += 4;
2627 pc = base_pc+offset;
2629 NEXT_INSN;
2631 insn_jsr_w:
2633 unsigned char* base_pc = pc-1;
2634 int offset = get4 (pc); pc += 4;
2635 PUSHA((jobject)pc);
2636 pc = base_pc+offset;
2638 NEXT_INSN;
2642 static void
2643 throw_internal_error (char *msg)
2645 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2648 static void
2649 throw_incompatible_class_change_error (jstring msg)
2651 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2654 #if !HANDLE_SEGV
2655 static java::lang::NullPointerException *null_pointer_exc;
2656 static void
2657 throw_null_pointer_exception ()
2659 if (null_pointer_exc == NULL)
2660 null_pointer_exc = new java::lang::NullPointerException;
2662 JvThrow (null_pointer_exc);
2664 #endif
2666 #if !HANDLE_FPE
2667 static java::lang::ArithmeticException *arithmetic_exc;
2668 static void
2669 throw_arithmetic_exception ()
2671 if (arithmetic_exc == NULL)
2672 arithmetic_exc = new java::lang::ArithmeticException
2673 (JvNewStringLatin1 ("/ by zero"));
2675 JvThrow (arithmetic_exc);
2677 #endif
2680 #endif // INTERPRETER