* testsuite/18_support/numeric_limits.cc (test_extrema): Fix typo.
[gcc.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
12
13 #include <config.h>
14
15 #pragma implementation "java-interp.h"
16
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/Long.h>
25 #include <java/lang/StringBuffer.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>
36
37 #ifdef INTERPRETER
38
39 #include <stdlib.h>
40
41 using namespace gcj;
42
43 static void throw_internal_error (char *msg)
44 __attribute__ ((__noreturn__));
45 static void throw_incompatible_class_change_error (jstring msg)
46 __attribute__ ((__noreturn__));
47 #ifndef HANDLE_SEGV
48 static void throw_null_pointer_exception ()
49 __attribute__ ((__noreturn__));
50 #endif
51
52 extern "C" double __ieee754_fmod (double,double);
53
54 static inline void dupx (_Jv_word *sp, int n, int x)
55 {
56 // first "slide" n+x elements n to the right
57 int top = n-1;
58 for (int i = 0; i < n+x; i++)
59 {
60 sp[(top-i)] = sp[(top-i)-n];
61 }
62
63 // next, copy the n top elements, n+x down
64 for (int i = 0; i < n; i++)
65 {
66 sp[top-(n+x)-i] = sp[top-i];
67 }
68
69 };
70
71 // Used to convert from floating types to integral types.
72 template<typename TO, typename FROM>
73 static inline TO
74 convert (FROM val, TO min, TO max)
75 {
76 TO ret;
77 if (val >= (FROM) max)
78 ret = max;
79 else if (val <= (FROM) min)
80 ret = min;
81 else if (val != val)
82 ret = 0;
83 else
84 ret = (TO) val;
85 return ret;
86 }
87
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #if SIZEOF_VOID_P == 8
92 # define PUSHL(V) (sp->l = (V), sp += 2)
93 # define PUSHD(V) (sp->d = (V), sp += 2)
94 #else
95 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
96 (sp++)->ia[0] = w2.ia[0]; \
97 (sp++)->ia[0] = w2.ia[1]; } while (0)
98 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
99 (sp++)->ia[0] = w2.ia[0]; \
100 (sp++)->ia[0] = w2.ia[1]; } while (0)
101 #endif
102
103 #define POPA() ((--sp)->o)
104 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
105 #define POPF() ((jfloat) (--sp)->f)
106 #if SIZEOF_VOID_P == 8
107 # define POPL() (sp -= 2, (jlong) sp->l)
108 # define POPD() (sp -= 2, (jdouble) sp->d)
109 #else
110 # define POPL() ({ _Jv_word2 w2; \
111 w2.ia[1] = (--sp)->ia[0]; \
112 w2.ia[0] = (--sp)->ia[0]; w2.l; })
113 # define POPD() ({ _Jv_word2 w2; \
114 w2.ia[1] = (--sp)->ia[0]; \
115 w2.ia[0] = (--sp)->ia[0]; w2.d; })
116 #endif
117
118 #define LOADA(I) (sp++)->o = locals[I].o
119 #define LOADI(I) (sp++)->i = locals[I].i
120 #define LOADF(I) (sp++)->f = locals[I].f
121 #if SIZEOF_VOID_P == 8
122 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
123 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
124 #else
125 # define LOADL(I) do { jint __idx = (I); \
126 (sp++)->ia[0] = locals[__idx].ia[0]; \
127 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
128 } while (0)
129 # define LOADD(I) LOADL(I)
130 #endif
131
132 #define STOREA(I) locals[I].o = (--sp)->o
133 #define STOREI(I) locals[I].i = (--sp)->i
134 #define STOREF(I) locals[I].f = (--sp)->f
135 #if SIZEOF_VOID_P == 8
136 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
137 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
138 #else
139 # define STOREL(I) do { jint __idx = (I); \
140 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
141 locals[__idx].ia[0] = (--sp)->ia[0]; \
142 } while (0)
143 # define STORED(I) STOREL(I)
144 #endif
145
146 #define PEEKI(I) (locals+(I))->i
147 #define PEEKA(I) (locals+(I))->o
148
149 #define POKEI(I,V) ((locals+(I))->i = (V))
150
151
152 #define BINOPI(OP) { \
153 jint value2 = POPI(); \
154 jint value1 = POPI(); \
155 PUSHI(value1 OP value2); \
156 }
157
158 #define BINOPF(OP) { \
159 jfloat value2 = POPF(); \
160 jfloat value1 = POPF(); \
161 PUSHF(value1 OP value2); \
162 }
163
164 #define BINOPL(OP) { \
165 jlong value2 = POPL(); \
166 jlong value1 = POPL(); \
167 PUSHL(value1 OP value2); \
168 }
169
170 #define BINOPD(OP) { \
171 jdouble value2 = POPD(); \
172 jdouble value1 = POPD(); \
173 PUSHD(value1 OP value2); \
174 }
175
176 static inline jint get1s(unsigned char* loc) {
177 return *(signed char*)loc;
178 }
179
180 static inline jint get1u(unsigned char* loc) {
181 return *loc;
182 }
183
184 static inline jint get2s(unsigned char* loc) {
185 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
186 }
187
188 static inline jint get2u(unsigned char* loc) {
189 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
190 }
191
192 static jint get4(unsigned char* loc) {
193 return (((jint)(loc[0])) << 24)
194 | (((jint)(loc[1])) << 16)
195 | (((jint)(loc[2])) << 8)
196 | (((jint)(loc[3])) << 0);
197 }
198
199
200 #ifdef HANDLE_SEGV
201 #define NULLCHECK(X)
202 #define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
203 #else
204 #define NULLCHECK(X) \
205 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
206 #define NULLARRAYCHECK(X) \
207 do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
208 #endif
209
210 #define ARRAYBOUNDSCHECK(array, index) \
211 do \
212 { \
213 if (((unsigned) index) >= (unsigned) (array->length)) \
214 _Jv_ThrowBadArrayIndex (index); \
215 } \
216 while (0)
217
218 // this method starts the actual running of the method. It is inlined
219 // in three different variants in the static methods run_normal,
220 // run_sync_object and run_sync_class (see below). Those static methods
221 // are installed directly in the stub for this method (by
222 // _Jv_InterpMethod::ncode, in resolve.cc).
223
224 inline jobject
225 _Jv_InterpMethod::run (ffi_cif* cif,
226 void *retp,
227 ffi_raw *args,
228 _Jv_InterpMethodInvocation *inv)
229 {
230 inv->running = this;
231 inv->pc = bytecode ();
232 inv->sp = inv->stack_base ();
233 _Jv_word *locals = inv->local_base ();
234
235 /* Go straight at it! the ffi raw format matches the internal
236 stack representation exactly. At least, that's the idea.
237 */
238 memcpy ((void*) locals, (void*) args, args_raw_size);
239
240 next_segment:
241
242 jobject ex = NULL;
243
244 try
245 {
246 continue1 (inv);
247 }
248 catch (java::lang::Throwable *ex2)
249 {
250 ex = ex2;
251 }
252
253 if (ex == 0) // no exception...
254 {
255 /* define sp locally, so the POP? macros will pick it up */
256 _Jv_word *sp = inv->sp;
257 int rtype = cif->rtype->type;
258
259 if (rtype == FFI_TYPE_POINTER)
260 {
261 jobject r = POPA();
262 *(jobject*) retp = r;
263 return 0;
264 }
265 else if (rtype == FFI_TYPE_SINT32)
266 {
267 jint r = POPI();
268 *(jint*)retp = r;
269 return 0;
270 }
271 else if (rtype == FFI_TYPE_VOID)
272 {
273 return 0;
274 }
275 else switch (rtype)
276 {
277 case FFI_TYPE_FLOAT:
278 {
279 jfloat r = POPF();
280 *(jfloat*)retp = r;
281 return 0;
282 }
283
284 case FFI_TYPE_DOUBLE:
285 {
286 jdouble r = POPD();
287 *(jdouble*)retp = r;
288 return 0;
289 }
290
291 case FFI_TYPE_UINT8:
292 case FFI_TYPE_UINT16:
293 case FFI_TYPE_UINT32:
294 case FFI_TYPE_SINT8:
295 case FFI_TYPE_SINT16:
296 {
297 jint r = POPI();
298 *(jint*)retp = r;
299 return 0;
300 }
301
302 case FFI_TYPE_SINT64:
303 {
304 jlong r = POPL();
305 *(jlong*)retp = r;
306 return 0;
307 }
308
309 default:
310 throw_internal_error ("unknown return type");
311 }
312 }
313
314 /** handle an exception */
315 if ( find_exception (ex, inv) )
316 goto next_segment;
317
318 return ex;
319 }
320
321 #define SAVE_PC inv->pc = pc
322
323 bool _Jv_InterpMethod::find_exception (jobject ex,
324 _Jv_InterpMethodInvocation *inv)
325 {
326 // We subtract one because the PC was incremented before it was
327 // saved.
328 int logical_pc = inv->pc - 1 - bytecode ();
329 _Jv_InterpException *exc = exceptions ();
330 jclass exc_class = ex->getClass ();
331
332 for (int i = 0; i < exc_count; i++)
333 {
334 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
335 {
336 jclass handler;
337
338 if (exc[i].handler_type != 0)
339 handler = (_Jv_ResolvePoolEntry (defining_class,
340 exc[i].handler_type)).clazz;
341 else
342 handler = NULL;
343
344 if (handler==NULL || handler->isAssignableFrom (exc_class))
345 {
346 inv->pc = bytecode () + exc[i].handler_pc;
347 inv->sp = inv->stack_base (); // reset stack
348 (inv->sp++)->o = ex; // push exception
349 return true;
350 }
351 }
352 }
353 return false;
354 }
355
356 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
357 void* ret,
358 ffi_raw * args,
359 void* __this)
360 {
361 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
362
363 // we do the alloca of the method invocation here, to allow the method
364 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
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));
369
370 jobject ex = _this->run (cif, ret, args, inv);
371 if (ex != 0) throw static_cast<jthrowable>(ex);
372 }
373
374 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
375 void* ret,
376 ffi_raw * args,
377 void* __this)
378 {
379 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
380 jobject rcv = (jobject)args[0].ptr;
381
382 int storage_size = _this->max_stack+_this->max_locals;
383 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
384 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
385 + storage_size * sizeof (_Jv_word));
386
387 _Jv_MonitorEnter (rcv);
388 jobject ex = _this->run (cif, ret, args, inv);
389 _Jv_MonitorExit (rcv);
390
391 if (ex != 0) throw static_cast<jthrowable>(ex);
392 }
393
394 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
395 void* ret,
396 ffi_raw * args,
397 void* __this)
398 {
399 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
400 jclass sync = _this->defining_class;
401
402 int storage_size = _this->max_stack+_this->max_locals;
403 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
404 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
405 + storage_size * sizeof (_Jv_word));
406
407 _Jv_MonitorEnter (sync);
408 jobject ex = _this->run (cif, ret, args, inv);
409 _Jv_MonitorExit (sync);
410
411 if (ex != 0) throw static_cast<jthrowable>(ex);
412 }
413
414 /*
415 This proceeds execution, as designated in "inv". If an exception
416 happens, then it is simply thrown, and handled in Java. Thus, the pc
417 needs to be stored in the inv->pc at all times, so we can figure
418 out which handler (if any) to invoke.
419
420 One design issue, which I have not completely considered, is if it
421 should be possible to have interpreted classes linked in! Seldom used
422 (or non-critical) classes could reasonably be interpreted.
423 */
424
425
426 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
427 {
428 using namespace java::lang::reflect;
429
430 _Jv_word *sp = inv->sp;
431 unsigned char *pc = inv->pc;
432 _Jv_word *locals = inv->local_base ();
433
434 _Jv_word *pool_data = defining_class->constants.data;
435
436 /* these two are used in the invokeXXX instructions */
437 void (*fun)();
438 _Jv_ResolvedMethod* rmeth;
439
440 #define INSN_LABEL(op) &&insn_##op
441 #define GOTO_INSN(op) goto *(insn_target[op])
442
443 static const void *const insn_target[] =
444 {
445 INSN_LABEL(nop),
446 INSN_LABEL(aconst_null),
447 INSN_LABEL(iconst_m1),
448 INSN_LABEL(iconst_0),
449 INSN_LABEL(iconst_1),
450 INSN_LABEL(iconst_2),
451 INSN_LABEL(iconst_3),
452 INSN_LABEL(iconst_4),
453 INSN_LABEL(iconst_5),
454 INSN_LABEL(lconst_0),
455 INSN_LABEL(lconst_1),
456 INSN_LABEL(fconst_0),
457 INSN_LABEL(fconst_1),
458 INSN_LABEL(fconst_2),
459 INSN_LABEL(dconst_0),
460 INSN_LABEL(dconst_1),
461 INSN_LABEL(bipush),
462 INSN_LABEL(sipush),
463 INSN_LABEL(ldc),
464 INSN_LABEL(ldc_w),
465 INSN_LABEL(ldc2_w),
466 INSN_LABEL(iload),
467 INSN_LABEL(lload),
468 INSN_LABEL(fload),
469 INSN_LABEL(dload),
470 INSN_LABEL(aload),
471 INSN_LABEL(iload_0),
472 INSN_LABEL(iload_1),
473 INSN_LABEL(iload_2),
474 INSN_LABEL(iload_3),
475 INSN_LABEL(lload_0),
476 INSN_LABEL(lload_1),
477 INSN_LABEL(lload_2),
478 INSN_LABEL(lload_3),
479 INSN_LABEL(fload_0),
480 INSN_LABEL(fload_1),
481 INSN_LABEL(fload_2),
482 INSN_LABEL(fload_3),
483 INSN_LABEL(dload_0),
484 INSN_LABEL(dload_1),
485 INSN_LABEL(dload_2),
486 INSN_LABEL(dload_3),
487 INSN_LABEL(aload_0),
488 INSN_LABEL(aload_1),
489 INSN_LABEL(aload_2),
490 INSN_LABEL(aload_3),
491 INSN_LABEL(iaload),
492 INSN_LABEL(laload),
493 INSN_LABEL(faload),
494 INSN_LABEL(daload),
495 INSN_LABEL(aaload),
496 INSN_LABEL(baload),
497 INSN_LABEL(caload),
498 INSN_LABEL(saload),
499 INSN_LABEL(istore),
500 INSN_LABEL(lstore),
501 INSN_LABEL(fstore),
502 INSN_LABEL(dstore),
503 INSN_LABEL(astore),
504 INSN_LABEL(istore_0),
505 INSN_LABEL(istore_1),
506 INSN_LABEL(istore_2),
507 INSN_LABEL(istore_3),
508 INSN_LABEL(lstore_0),
509 INSN_LABEL(lstore_1),
510 INSN_LABEL(lstore_2),
511 INSN_LABEL(lstore_3),
512 INSN_LABEL(fstore_0),
513 INSN_LABEL(fstore_1),
514 INSN_LABEL(fstore_2),
515 INSN_LABEL(fstore_3),
516 INSN_LABEL(dstore_0),
517 INSN_LABEL(dstore_1),
518 INSN_LABEL(dstore_2),
519 INSN_LABEL(dstore_3),
520 INSN_LABEL(astore_0),
521 INSN_LABEL(astore_1),
522 INSN_LABEL(astore_2),
523 INSN_LABEL(astore_3),
524 INSN_LABEL(iastore),
525 INSN_LABEL(lastore),
526 INSN_LABEL(fastore),
527 INSN_LABEL(dastore),
528 INSN_LABEL(aastore),
529 INSN_LABEL(bastore),
530 INSN_LABEL(castore),
531 INSN_LABEL(sastore),
532 INSN_LABEL(pop),
533 INSN_LABEL(pop2),
534 INSN_LABEL(dup),
535 INSN_LABEL(dup_x1),
536 INSN_LABEL(dup_x2),
537 INSN_LABEL(dup2),
538 INSN_LABEL(dup2_x1),
539 INSN_LABEL(dup2_x2),
540 INSN_LABEL(swap),
541 INSN_LABEL(iadd),
542 INSN_LABEL(ladd),
543 INSN_LABEL(fadd),
544 INSN_LABEL(dadd),
545 INSN_LABEL(isub),
546 INSN_LABEL(lsub),
547 INSN_LABEL(fsub),
548 INSN_LABEL(dsub),
549 INSN_LABEL(imul),
550 INSN_LABEL(lmul),
551 INSN_LABEL(fmul),
552 INSN_LABEL(dmul),
553 INSN_LABEL(idiv),
554 INSN_LABEL(ldiv),
555 INSN_LABEL(fdiv),
556 INSN_LABEL(ddiv),
557 INSN_LABEL(irem),
558 INSN_LABEL(lrem),
559 INSN_LABEL(frem),
560 INSN_LABEL(drem),
561 INSN_LABEL(ineg),
562 INSN_LABEL(lneg),
563 INSN_LABEL(fneg),
564 INSN_LABEL(dneg),
565 INSN_LABEL(ishl),
566 INSN_LABEL(lshl),
567 INSN_LABEL(ishr),
568 INSN_LABEL(lshr),
569 INSN_LABEL(iushr),
570 INSN_LABEL(lushr),
571 INSN_LABEL(iand),
572 INSN_LABEL(land),
573 INSN_LABEL(ior),
574 INSN_LABEL(lor),
575 INSN_LABEL(ixor),
576 INSN_LABEL(lxor),
577 INSN_LABEL(iinc),
578 INSN_LABEL(i2l),
579 INSN_LABEL(i2f),
580 INSN_LABEL(i2d),
581 INSN_LABEL(l2i),
582 INSN_LABEL(l2f),
583 INSN_LABEL(l2d),
584 INSN_LABEL(f2i),
585 INSN_LABEL(f2l),
586 INSN_LABEL(f2d),
587 INSN_LABEL(d2i),
588 INSN_LABEL(d2l),
589 INSN_LABEL(d2f),
590 INSN_LABEL(i2b),
591 INSN_LABEL(i2c),
592 INSN_LABEL(i2s),
593 INSN_LABEL(lcmp),
594 INSN_LABEL(fcmpl),
595 INSN_LABEL(fcmpg),
596 INSN_LABEL(dcmpl),
597 INSN_LABEL(dcmpg),
598 INSN_LABEL(ifeq),
599 INSN_LABEL(ifne),
600 INSN_LABEL(iflt),
601 INSN_LABEL(ifge),
602 INSN_LABEL(ifgt),
603 INSN_LABEL(ifle),
604 INSN_LABEL(if_icmpeq),
605 INSN_LABEL(if_icmpne),
606 INSN_LABEL(if_icmplt),
607 INSN_LABEL(if_icmpge),
608 INSN_LABEL(if_icmpgt),
609 INSN_LABEL(if_icmple),
610 INSN_LABEL(if_acmpeq),
611 INSN_LABEL(if_acmpne),
612 INSN_LABEL(goto),
613 INSN_LABEL(jsr),
614 INSN_LABEL(ret),
615 INSN_LABEL(tableswitch),
616 INSN_LABEL(lookupswitch),
617 INSN_LABEL(ireturn),
618 INSN_LABEL(lreturn),
619 INSN_LABEL(freturn),
620 INSN_LABEL(dreturn),
621 INSN_LABEL(areturn),
622 INSN_LABEL(return),
623 INSN_LABEL(getstatic),
624 INSN_LABEL(putstatic),
625 INSN_LABEL(getfield),
626 INSN_LABEL(putfield),
627 INSN_LABEL(invokevirtual),
628 INSN_LABEL(invokespecial),
629 INSN_LABEL(invokestatic),
630 INSN_LABEL(invokeinterface),
631 0, /* op_xxxunusedxxx1, */
632 INSN_LABEL(new),
633 INSN_LABEL(newarray),
634 INSN_LABEL(anewarray),
635 INSN_LABEL(arraylength),
636 INSN_LABEL(athrow),
637 INSN_LABEL(checkcast),
638 INSN_LABEL(instanceof),
639 INSN_LABEL(monitorenter),
640 INSN_LABEL(monitorexit),
641 INSN_LABEL(wide),
642 INSN_LABEL(multianewarray),
643 INSN_LABEL(ifnull),
644 INSN_LABEL(ifnonnull),
645 INSN_LABEL(goto_w),
646 INSN_LABEL(jsr_w),
647 };
648
649 /* If the macro INLINE_SWITCH is not defined, then the main loop
650 operates as one big (normal) switch statement. If it is defined,
651 then the case selection is performed `inline' in the end of the
652 code for each case. The latter saves a native branch instruction
653 for each java-instruction, but expands the code size somewhat.
654
655 NOTE: On i386 defining INLINE_SWITCH improves over all
656 performance approximately seven percent, but it may be different
657 for other machines. At some point, this may be made into a proper
658 configuration parameter. */
659
660 #define INLINE_SWITCH
661
662 #ifdef INLINE_SWITCH
663
664 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
665
666
667 NEXT_INSN;
668 #else
669
670 #define NEXT_INSN goto next_insn
671
672 next_insn:
673 GOTO_INSN (*pc++);
674
675 #endif
676
677 /* The first few instructions here are ordered according to their
678 frequency, in the hope that this will improve code locality a
679 little. */
680
681 insn_aload_0: // 0x2a
682 LOADA(0);
683 NEXT_INSN;
684
685 insn_iload: // 0x15
686 LOADI (get1u (pc++));
687 NEXT_INSN;
688
689 insn_iload_1: // 0x1b
690 LOADI (1);
691 NEXT_INSN;
692
693 insn_invokevirtual: // 0xb6
694 SAVE_PC;
695 {
696 int index = get2u (pc); pc += 2;
697
698 /* _Jv_ResolvePoolEntry returns immediately if the value already
699 * is resolved. If we want to clutter up the code here to gain
700 * a little performance, then we can check the corresponding bit
701 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
702 * don't think it is worth it. */
703
704 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
705
706 sp -= rmeth->stack_item_count;
707 // We don't use NULLCHECK here because we can't rely on that
708 // working if the method is final. So instead we do an
709 // explicit test.
710 if (! sp[0].o)
711 throw new java::lang::NullPointerException;
712
713 if (rmeth->vtable_index == -1)
714 {
715 // final methods do not appear in the vtable,
716 // if it does not appear in the superclass.
717 fun = (void (*)()) rmeth->method->ncode;
718 }
719 else
720 {
721 jobject rcv = sp[0].o;
722 _Jv_VTable *table = *(_Jv_VTable**)rcv;
723 fun = (void (*)()) table->get_method(rmeth->vtable_index);
724 }
725 }
726 goto perform_invoke;
727
728 perform_invoke:
729 {
730 /* here goes the magic again... */
731 ffi_cif *cif = &rmeth->cif;
732 ffi_raw *raw = (ffi_raw*) sp;
733
734 jdouble rvalue;
735
736 #if FFI_NATIVE_RAW_API
737 /* We assume that this is only implemented if it's correct */
738 /* to use it here. On a 64 bit machine, it never is. */
739 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
740 #else
741 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
742 #endif
743
744 int rtype = cif->rtype->type;
745
746 /* the likelyhood of object, int, or void return is very high,
747 * so those are checked before the switch */
748 if (rtype == FFI_TYPE_POINTER)
749 {
750 PUSHA (*(jobject*)&rvalue);
751 }
752 else if (rtype == FFI_TYPE_SINT32)
753 {
754 PUSHI (*(jint*)&rvalue);
755 }
756 else if (rtype == FFI_TYPE_VOID)
757 {
758 /* skip */
759 }
760 else switch (rtype)
761 {
762 case FFI_TYPE_SINT8:
763 {
764 jbyte value = (*(jint*)&rvalue) & 0xff;
765 PUSHI (value);
766 }
767 break;
768
769 case FFI_TYPE_SINT16:
770 {
771 jshort value = (*(jint*)&rvalue) & 0xffff;
772 PUSHI (value);
773 }
774 break;
775
776 case FFI_TYPE_UINT16:
777 {
778 jint value = (*(jint*)&rvalue) & 0xffff;
779 PUSHI (value);
780 }
781 break;
782
783 case FFI_TYPE_FLOAT:
784 PUSHF (*(jfloat*)&rvalue);
785 break;
786
787 case FFI_TYPE_DOUBLE:
788 PUSHD (rvalue);
789 break;
790
791 case FFI_TYPE_SINT64:
792 PUSHL (*(jlong*)&rvalue);
793 break;
794
795 default:
796 throw_internal_error ("unknown return type in invokeXXX");
797 }
798
799 }
800 NEXT_INSN;
801
802
803 insn_nop:
804 NEXT_INSN;
805
806 insn_aconst_null:
807 PUSHA (NULL);
808 NEXT_INSN;
809
810 insn_iconst_m1:
811 PUSHI (-1);
812 NEXT_INSN;
813
814 insn_iconst_0:
815 PUSHI (0);
816 NEXT_INSN;
817
818 insn_iconst_1:
819 PUSHI (1);
820 NEXT_INSN;
821
822 insn_iconst_2:
823 PUSHI (2);
824 NEXT_INSN;
825
826 insn_iconst_3:
827 PUSHI (3);
828 NEXT_INSN;
829
830 insn_iconst_4:
831 PUSHI (4);
832 NEXT_INSN;
833
834 insn_iconst_5:
835 PUSHI (5);
836 NEXT_INSN;
837
838 insn_lconst_0:
839 PUSHL (0);
840 NEXT_INSN;
841
842 insn_lconst_1:
843 PUSHL (1);
844 NEXT_INSN;
845
846 insn_fconst_0:
847 PUSHF (0);
848 NEXT_INSN;
849
850 insn_fconst_1:
851 PUSHF (1);
852 NEXT_INSN;
853
854 insn_fconst_2:
855 PUSHF (2);
856 NEXT_INSN;
857
858 insn_dconst_0:
859 PUSHD (0);
860 NEXT_INSN;
861
862 insn_dconst_1:
863 PUSHD (1);
864 NEXT_INSN;
865
866 insn_bipush:
867 PUSHI (get1s(pc++));
868 NEXT_INSN;
869
870 insn_sipush:
871 PUSHI (get2s(pc)); pc += 2;
872 NEXT_INSN;
873
874 insn_ldc:
875 {
876 int index = get1u (pc++);
877 PUSHA(pool_data[index].o);
878 }
879 NEXT_INSN;
880
881 insn_ldc_w:
882 {
883 int index = get2u (pc); pc += 2;
884 PUSHA(pool_data[index].o);
885 }
886 NEXT_INSN;
887
888 insn_ldc2_w:
889 {
890 int index = get2u (pc); pc += 2;
891 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
892 sp += 2;
893 }
894 NEXT_INSN;
895
896 insn_lload:
897 LOADL (get1u (pc++));
898 NEXT_INSN;
899
900 insn_fload:
901 LOADF (get1u (pc++));
902 NEXT_INSN;
903
904 insn_dload:
905 LOADD (get1u (pc++));
906 NEXT_INSN;
907
908 insn_aload:
909 LOADA (get1u (pc++));
910 NEXT_INSN;
911
912 insn_iload_0:
913 LOADI (0);
914 NEXT_INSN;
915
916 insn_iload_2:
917 LOADI (2);
918 NEXT_INSN;
919
920 insn_iload_3:
921 LOADI (3);
922 NEXT_INSN;
923
924 insn_lload_0:
925 LOADL (0);
926 NEXT_INSN;
927
928 insn_lload_1:
929 LOADL (1);
930 NEXT_INSN;
931
932 insn_lload_2:
933 LOADL (2);
934 NEXT_INSN;
935
936 insn_lload_3:
937 LOADL (3);
938 NEXT_INSN;
939
940 insn_fload_0:
941 LOADF (0);
942 NEXT_INSN;
943
944 insn_fload_1:
945 LOADF (1);
946 NEXT_INSN;
947
948 insn_fload_2:
949 LOADF (2);
950 NEXT_INSN;
951
952 insn_fload_3:
953 LOADF (3);
954 NEXT_INSN;
955
956 insn_dload_0:
957 LOADD (0);
958 NEXT_INSN;
959
960 insn_dload_1:
961 LOADD (1);
962 NEXT_INSN;
963
964 insn_dload_2:
965 LOADD (2);
966 NEXT_INSN;
967
968 insn_dload_3:
969 LOADD (3);
970 NEXT_INSN;
971
972 insn_aload_1:
973 LOADA(1);
974 NEXT_INSN;
975
976 insn_aload_2:
977 LOADA(2);
978 NEXT_INSN;
979
980 insn_aload_3:
981 LOADA(3);
982 NEXT_INSN;
983
984 insn_iaload:
985 {
986 jint index = POPI();
987 jintArray arr = (jintArray) POPA();
988 NULLARRAYCHECK (arr);
989 ARRAYBOUNDSCHECK (arr, index);
990 PUSHI( elements(arr)[index] );
991 }
992 NEXT_INSN;
993
994 insn_laload:
995 {
996 jint index = POPI();
997 jlongArray arr = (jlongArray) POPA();
998 NULLARRAYCHECK (arr);
999 ARRAYBOUNDSCHECK (arr, index);
1000 PUSHL( elements(arr)[index] );
1001 }
1002 NEXT_INSN;
1003
1004 insn_faload:
1005 {
1006 jint index = POPI();
1007 jfloatArray arr = (jfloatArray) POPA();
1008 NULLARRAYCHECK (arr);
1009 ARRAYBOUNDSCHECK (arr, index);
1010 PUSHF( elements(arr)[index] );
1011 }
1012 NEXT_INSN;
1013
1014 insn_daload:
1015 {
1016 jint index = POPI();
1017 jdoubleArray arr = (jdoubleArray) POPA();
1018 NULLARRAYCHECK (arr);
1019 ARRAYBOUNDSCHECK (arr, index);
1020 PUSHD( elements(arr)[index] );
1021 }
1022 NEXT_INSN;
1023
1024 insn_aaload:
1025 {
1026 jint index = POPI();
1027 jobjectArray arr = (jobjectArray) POPA();
1028 NULLARRAYCHECK (arr);
1029 ARRAYBOUNDSCHECK (arr, index);
1030 PUSHA( elements(arr)[index] );
1031 }
1032 NEXT_INSN;
1033
1034 insn_baload:
1035 {
1036 jint index = POPI();
1037 jbyteArray arr = (jbyteArray) POPA();
1038 NULLARRAYCHECK (arr);
1039 ARRAYBOUNDSCHECK (arr, index);
1040 PUSHI( elements(arr)[index] );
1041 }
1042 NEXT_INSN;
1043
1044 insn_caload:
1045 {
1046 jint index = POPI();
1047 jcharArray arr = (jcharArray) POPA();
1048 NULLARRAYCHECK (arr);
1049 ARRAYBOUNDSCHECK (arr, index);
1050 PUSHI( elements(arr)[index] );
1051 }
1052 NEXT_INSN;
1053
1054 insn_saload:
1055 {
1056 jint index = POPI();
1057 jshortArray arr = (jshortArray) POPA();
1058 NULLARRAYCHECK (arr);
1059 ARRAYBOUNDSCHECK (arr, index);
1060 PUSHI( elements(arr)[index] );
1061 }
1062 NEXT_INSN;
1063
1064 insn_istore:
1065 STOREI (get1u (pc++));
1066 NEXT_INSN;
1067
1068 insn_lstore:
1069 STOREL (get1u (pc++));
1070 NEXT_INSN;
1071
1072 insn_fstore:
1073 STOREF (get1u (pc++));
1074 NEXT_INSN;
1075
1076 insn_dstore:
1077 STORED (get1u (pc++));
1078 NEXT_INSN;
1079
1080 insn_astore:
1081 STOREA (get1u (pc++));
1082 NEXT_INSN;
1083
1084 insn_istore_0:
1085 STOREI (0);
1086 NEXT_INSN;
1087
1088 insn_istore_1:
1089 STOREI (1);
1090 NEXT_INSN;
1091
1092 insn_istore_2:
1093 STOREI (2);
1094 NEXT_INSN;
1095
1096 insn_istore_3:
1097 STOREI (3);
1098 NEXT_INSN;
1099
1100 insn_lstore_0:
1101 STOREL (0);
1102 NEXT_INSN;
1103
1104 insn_lstore_1:
1105 STOREL (1);
1106 NEXT_INSN;
1107
1108 insn_lstore_2:
1109 STOREL (2);
1110 NEXT_INSN;
1111
1112 insn_lstore_3:
1113 STOREL (3);
1114 NEXT_INSN;
1115
1116 insn_fstore_0:
1117 STOREF (0);
1118 NEXT_INSN;
1119
1120 insn_fstore_1:
1121 STOREF (1);
1122 NEXT_INSN;
1123
1124 insn_fstore_2:
1125 STOREF (2);
1126 NEXT_INSN;
1127
1128 insn_fstore_3:
1129 STOREF (3);
1130 NEXT_INSN;
1131
1132 insn_dstore_0:
1133 STORED (0);
1134 NEXT_INSN;
1135
1136 insn_dstore_1:
1137 STORED (1);
1138 NEXT_INSN;
1139
1140 insn_dstore_2:
1141 STORED (2);
1142 NEXT_INSN;
1143
1144 insn_dstore_3:
1145 STORED (3);
1146 NEXT_INSN;
1147
1148 insn_astore_0:
1149 STOREA(0);
1150 NEXT_INSN;
1151
1152 insn_astore_1:
1153 STOREA(1);
1154 NEXT_INSN;
1155
1156 insn_astore_2:
1157 STOREA(2);
1158 NEXT_INSN;
1159
1160 insn_astore_3:
1161 STOREA(3);
1162 NEXT_INSN;
1163
1164 insn_iastore:
1165 {
1166 jint value = POPI();
1167 jint index = POPI();
1168 jintArray arr = (jintArray) POPA();
1169 NULLARRAYCHECK (arr);
1170 ARRAYBOUNDSCHECK (arr, index);
1171 elements(arr)[index] = value;
1172 }
1173 NEXT_INSN;
1174
1175 insn_lastore:
1176 {
1177 jlong value = POPL();
1178 jint index = POPI();
1179 jlongArray arr = (jlongArray) POPA();
1180 NULLARRAYCHECK (arr);
1181 ARRAYBOUNDSCHECK (arr, index);
1182 elements(arr)[index] = value;
1183 }
1184 NEXT_INSN;
1185
1186 insn_fastore:
1187 {
1188 jfloat value = POPF();
1189 jint index = POPI();
1190 jfloatArray arr = (jfloatArray) POPA();
1191 NULLARRAYCHECK (arr);
1192 ARRAYBOUNDSCHECK (arr, index);
1193 elements(arr)[index] = value;
1194 }
1195 NEXT_INSN;
1196
1197 insn_dastore:
1198 {
1199 jdouble value = POPD();
1200 jint index = POPI();
1201 jdoubleArray arr = (jdoubleArray) POPA();
1202 NULLARRAYCHECK (arr);
1203 ARRAYBOUNDSCHECK (arr, index);
1204 elements(arr)[index] = value;
1205 }
1206 NEXT_INSN;
1207
1208 insn_aastore:
1209 {
1210 jobject value = POPA();
1211 jint index = POPI();
1212 jobjectArray arr = (jobjectArray) POPA();
1213 NULLARRAYCHECK (arr);
1214 ARRAYBOUNDSCHECK (arr, index);
1215 _Jv_CheckArrayStore (arr, value);
1216 elements(arr)[index] = value;
1217 }
1218 NEXT_INSN;
1219
1220 insn_bastore:
1221 {
1222 jbyte value = (jbyte) POPI();
1223 jint index = POPI();
1224 jbyteArray arr = (jbyteArray) POPA();
1225 NULLARRAYCHECK (arr);
1226 ARRAYBOUNDSCHECK (arr, index);
1227 elements(arr)[index] = value;
1228 }
1229 NEXT_INSN;
1230
1231 insn_castore:
1232 {
1233 jchar value = (jchar) POPI();
1234 jint index = POPI();
1235 jcharArray arr = (jcharArray) POPA();
1236 NULLARRAYCHECK (arr);
1237 ARRAYBOUNDSCHECK (arr, index);
1238 elements(arr)[index] = value;
1239 }
1240 NEXT_INSN;
1241
1242 insn_sastore:
1243 {
1244 jshort value = (jshort) POPI();
1245 jint index = POPI();
1246 jshortArray arr = (jshortArray) POPA();
1247 NULLARRAYCHECK (arr);
1248 ARRAYBOUNDSCHECK (arr, index);
1249 elements(arr)[index] = value;
1250 }
1251 NEXT_INSN;
1252
1253 insn_pop:
1254 sp -= 1;
1255 NEXT_INSN;
1256
1257 insn_pop2:
1258 sp -= 2;
1259 NEXT_INSN;
1260
1261 insn_dup:
1262 sp[0] = sp[-1];
1263 sp += 1;
1264 NEXT_INSN;
1265
1266 insn_dup_x1:
1267 dupx (sp, 1, 1); sp+=1;
1268 NEXT_INSN;
1269
1270 insn_dup_x2:
1271 dupx (sp, 1, 2); sp+=1;
1272 NEXT_INSN;
1273
1274 insn_dup2:
1275 sp[0] = sp[-2];
1276 sp[1] = sp[-1];
1277 sp += 2;
1278 NEXT_INSN;
1279
1280 insn_dup2_x1:
1281 dupx (sp, 2, 1); sp+=2;
1282 NEXT_INSN;
1283
1284 insn_dup2_x2:
1285 dupx (sp, 2, 2); sp+=2;
1286 NEXT_INSN;
1287
1288 insn_swap:
1289 {
1290 jobject tmp1 = POPA();
1291 jobject tmp2 = POPA();
1292 PUSHA (tmp1);
1293 PUSHA (tmp2);
1294 }
1295 NEXT_INSN;
1296
1297 insn_iadd:
1298 BINOPI(+);
1299 NEXT_INSN;
1300
1301 insn_ladd:
1302 BINOPL(+);
1303 NEXT_INSN;
1304
1305 insn_fadd:
1306 BINOPF(+);
1307 NEXT_INSN;
1308
1309 insn_dadd:
1310 BINOPD(+);
1311 NEXT_INSN;
1312
1313 insn_isub:
1314 BINOPI(-);
1315 NEXT_INSN;
1316
1317 insn_lsub:
1318 BINOPL(-);
1319 NEXT_INSN;
1320
1321 insn_fsub:
1322 BINOPF(-);
1323 NEXT_INSN;
1324
1325 insn_dsub:
1326 BINOPD(-);
1327 NEXT_INSN;
1328
1329 insn_imul:
1330 BINOPI(*);
1331 NEXT_INSN;
1332
1333 insn_lmul:
1334 BINOPL(*);
1335 NEXT_INSN;
1336
1337 insn_fmul:
1338 BINOPF(*);
1339 NEXT_INSN;
1340
1341 insn_dmul:
1342 BINOPD(*);
1343 NEXT_INSN;
1344
1345 insn_idiv:
1346 SAVE_PC;
1347 {
1348 jint value2 = POPI();
1349 jint value1 = POPI();
1350 jint res = _Jv_divI (value1, value2);
1351 PUSHI (res);
1352 }
1353 NEXT_INSN;
1354
1355 insn_ldiv:
1356 SAVE_PC;
1357 {
1358 jlong value2 = POPL();
1359 jlong value1 = POPL();
1360 jlong res = _Jv_divJ (value1, value2);
1361 PUSHL (res);
1362 }
1363 NEXT_INSN;
1364
1365 insn_fdiv:
1366 {
1367 jfloat value2 = POPF();
1368 jfloat value1 = POPF();
1369 jfloat res = value1 / value2;
1370 PUSHF (res);
1371 }
1372 NEXT_INSN;
1373
1374 insn_ddiv:
1375 {
1376 jdouble value2 = POPD();
1377 jdouble value1 = POPD();
1378 jdouble res = value1 / value2;
1379 PUSHD (res);
1380 }
1381 NEXT_INSN;
1382
1383 insn_irem:
1384 SAVE_PC;
1385 {
1386 jint value2 = POPI();
1387 jint value1 = POPI();
1388 jint res = _Jv_remI (value1, value2);
1389 PUSHI (res);
1390 }
1391 NEXT_INSN;
1392
1393 insn_lrem:
1394 SAVE_PC;
1395 {
1396 jlong value2 = POPL();
1397 jlong value1 = POPL();
1398 jlong res = _Jv_remJ (value1, value2);
1399 PUSHL (res);
1400 }
1401 NEXT_INSN;
1402
1403 insn_frem:
1404 {
1405 jfloat value2 = POPF();
1406 jfloat value1 = POPF();
1407 jfloat res = __ieee754_fmod (value1, value2);
1408 PUSHF (res);
1409 }
1410 NEXT_INSN;
1411
1412 insn_drem:
1413 {
1414 jdouble value2 = POPD();
1415 jdouble value1 = POPD();
1416 jdouble res = __ieee754_fmod (value1, value2);
1417 PUSHD (res);
1418 }
1419 NEXT_INSN;
1420
1421 insn_ineg:
1422 {
1423 jint value = POPI();
1424 PUSHI (value * -1);
1425 }
1426 NEXT_INSN;
1427
1428 insn_lneg:
1429 {
1430 jlong value = POPL();
1431 PUSHL (value * -1);
1432 }
1433 NEXT_INSN;
1434
1435 insn_fneg:
1436 {
1437 jfloat value = POPF();
1438 PUSHF (value * -1);
1439 }
1440 NEXT_INSN;
1441
1442 insn_dneg:
1443 {
1444 jdouble value = POPD();
1445 PUSHD (value * -1);
1446 }
1447 NEXT_INSN;
1448
1449 insn_ishl:
1450 {
1451 jint shift = (POPI() & 0x1f);
1452 jint value = POPI();
1453 PUSHI (value << shift);
1454 }
1455 NEXT_INSN;
1456
1457 insn_lshl:
1458 {
1459 jint shift = (POPI() & 0x3f);
1460 jlong value = POPL();
1461 PUSHL (value << shift);
1462 }
1463 NEXT_INSN;
1464
1465 insn_ishr:
1466 {
1467 jint shift = (POPI() & 0x1f);
1468 jint value = POPI();
1469 PUSHI (value >> shift);
1470 }
1471 NEXT_INSN;
1472
1473 insn_lshr:
1474 {
1475 jint shift = (POPI() & 0x3f);
1476 jlong value = POPL();
1477 PUSHL (value >> shift);
1478 }
1479 NEXT_INSN;
1480
1481 insn_iushr:
1482 {
1483 jint shift = (POPI() & 0x1f);
1484 unsigned long value = POPI();
1485 PUSHI ((jint) (value >> shift));
1486 }
1487 NEXT_INSN;
1488
1489 insn_lushr:
1490 {
1491 jint shift = (POPI() & 0x3f);
1492 UINT64 value = (UINT64) POPL();
1493 PUSHL ((value >> shift));
1494 }
1495 NEXT_INSN;
1496
1497 insn_iand:
1498 BINOPI (&);
1499 NEXT_INSN;
1500
1501 insn_land:
1502 BINOPL (&);
1503 NEXT_INSN;
1504
1505 insn_ior:
1506 BINOPI (|);
1507 NEXT_INSN;
1508
1509 insn_lor:
1510 BINOPL (|);
1511 NEXT_INSN;
1512
1513 insn_ixor:
1514 BINOPI (^);
1515 NEXT_INSN;
1516
1517 insn_lxor:
1518 BINOPL (^);
1519 NEXT_INSN;
1520
1521 insn_iinc:
1522 {
1523 jint index = get1u (pc++);
1524 jint amount = get1s (pc++);
1525 locals[index].i += amount;
1526 }
1527 NEXT_INSN;
1528
1529 insn_i2l:
1530 {jlong value = POPI(); PUSHL (value);}
1531 NEXT_INSN;
1532
1533 insn_i2f:
1534 {jfloat value = POPI(); PUSHF (value);}
1535 NEXT_INSN;
1536
1537 insn_i2d:
1538 {jdouble value = POPI(); PUSHD (value);}
1539 NEXT_INSN;
1540
1541 insn_l2i:
1542 {jint value = POPL(); PUSHI (value);}
1543 NEXT_INSN;
1544
1545 insn_l2f:
1546 {jfloat value = POPL(); PUSHF (value);}
1547 NEXT_INSN;
1548
1549 insn_l2d:
1550 {jdouble value = POPL(); PUSHD (value);}
1551 NEXT_INSN;
1552
1553 insn_f2i:
1554 {
1555 using namespace java::lang;
1556 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1557 PUSHI(value);
1558 }
1559 NEXT_INSN;
1560
1561 insn_f2l:
1562 {
1563 using namespace java::lang;
1564 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1565 PUSHL(value);
1566 }
1567 NEXT_INSN;
1568
1569 insn_f2d:
1570 { jdouble value = POPF (); PUSHD(value); }
1571 NEXT_INSN;
1572
1573 insn_d2i:
1574 {
1575 using namespace java::lang;
1576 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1577 PUSHI(value);
1578 }
1579 NEXT_INSN;
1580
1581 insn_d2l:
1582 {
1583 using namespace java::lang;
1584 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1585 PUSHL(value);
1586 }
1587 NEXT_INSN;
1588
1589 insn_d2f:
1590 { jfloat value = POPD (); PUSHF(value); }
1591 NEXT_INSN;
1592
1593 insn_i2b:
1594 { jbyte value = POPI (); PUSHI(value); }
1595 NEXT_INSN;
1596
1597 insn_i2c:
1598 { jchar value = POPI (); PUSHI(value); }
1599 NEXT_INSN;
1600
1601 insn_i2s:
1602 { jshort value = POPI (); PUSHI(value); }
1603 NEXT_INSN;
1604
1605 insn_lcmp:
1606 {
1607 jlong value2 = POPL ();
1608 jlong value1 = POPL ();
1609 if (value1 > value2)
1610 { PUSHI (1); }
1611 else if (value1 == value2)
1612 { PUSHI (0); }
1613 else
1614 { PUSHI (-1); }
1615 }
1616 NEXT_INSN;
1617
1618 insn_fcmpl:
1619 insn_fcmpg:
1620 {
1621 jfloat value2 = POPF ();
1622 jfloat value1 = POPF ();
1623 if (value1 > value2)
1624 PUSHI (1);
1625 else if (value1 == value2)
1626 PUSHI (0);
1627 else if (value1 < value2)
1628 PUSHI (-1);
1629 else if ((*(pc-1)) == op_fcmpg)
1630 PUSHI (1);
1631 else
1632 PUSHI (-1);
1633 }
1634 NEXT_INSN;
1635
1636 insn_dcmpl:
1637 insn_dcmpg:
1638 {
1639 jdouble value2 = POPD ();
1640 jdouble value1 = POPD ();
1641 if (value1 > value2)
1642 PUSHI (1);
1643 else if (value1 == value2)
1644 PUSHI (0);
1645 else if (value1 < value2)
1646 PUSHI (-1);
1647 else if ((*(pc-1)) == op_dcmpg)
1648 PUSHI (1);
1649 else
1650 PUSHI (-1);
1651 }
1652 NEXT_INSN;
1653
1654 insn_ifeq:
1655 {
1656 jint offset = get2s (pc);
1657 if (POPI() == 0)
1658 pc = pc-1+offset;
1659 else
1660 pc = pc+2;
1661 }
1662 NEXT_INSN;
1663
1664 insn_ifne:
1665 {
1666 jint offset = get2s (pc);
1667 if (POPI() != 0)
1668 pc = pc-1+offset;
1669 else
1670 pc = pc+2;
1671 }
1672 NEXT_INSN;
1673
1674 insn_iflt:
1675 {
1676 jint offset = get2s (pc);
1677 if (POPI() < 0)
1678 pc = pc-1+offset;
1679 else
1680 pc = pc+2;
1681 }
1682 NEXT_INSN;
1683
1684 insn_ifge:
1685 {
1686 jint offset = get2s (pc);
1687 if (POPI() >= 0)
1688 pc = pc-1+offset;
1689 else
1690 pc = pc+2;
1691 }
1692 NEXT_INSN;
1693
1694 insn_ifgt:
1695 {
1696 jint offset = get2s (pc);
1697 if (POPI() > 0)
1698 pc = pc-1+offset;
1699 else
1700 pc = pc+2;
1701 }
1702 NEXT_INSN;
1703
1704 insn_ifle:
1705 {
1706 jint offset = get2s (pc);
1707 if (POPI() <= 0)
1708 pc = pc-1+offset;
1709 else
1710 pc = pc+2;
1711 }
1712 NEXT_INSN;
1713
1714 insn_if_icmpeq:
1715 {
1716 jint offset = get2s (pc);
1717 jint value2 = POPI();
1718 jint value1 = POPI();
1719 if (value1 == value2)
1720 pc = pc-1+offset;
1721 else
1722 pc = pc+2;
1723 }
1724 NEXT_INSN;
1725
1726 insn_if_icmpne:
1727 {
1728 jint offset = get2s (pc);
1729 jint value2 = POPI();
1730 jint value1 = POPI();
1731 if (value1 != value2)
1732 pc = pc-1+offset;
1733 else
1734 pc = pc+2;
1735 }
1736 NEXT_INSN;
1737
1738 insn_if_icmplt:
1739 {
1740 jint offset = get2s (pc);
1741 jint value2 = POPI();
1742 jint value1 = POPI();
1743 if (value1 < value2)
1744 pc = pc-1+offset;
1745 else
1746 pc = pc+2;
1747 }
1748 NEXT_INSN;
1749
1750 insn_if_icmpge:
1751 {
1752 jint offset = get2s (pc);
1753 jint value2 = POPI();
1754 jint value1 = POPI();
1755 if (value1 >= value2)
1756 pc = pc-1+offset;
1757 else
1758 pc = pc+2;
1759 }
1760 NEXT_INSN;
1761
1762 insn_if_icmpgt:
1763 {
1764 jint offset = get2s (pc);
1765 jint value2 = POPI();
1766 jint value1 = POPI();
1767 if (value1 > value2)
1768 pc = pc-1+offset;
1769 else
1770 pc = pc+2;
1771 }
1772 NEXT_INSN;
1773
1774 insn_if_icmple:
1775 {
1776 jint offset = get2s (pc);
1777 jint value2 = POPI();
1778 jint value1 = POPI();
1779 if (value1 <= value2)
1780 pc = pc-1+offset;
1781 else
1782 pc = pc+2;
1783 }
1784 NEXT_INSN;
1785
1786 insn_if_acmpeq:
1787 {
1788 jint offset = get2s (pc);
1789 jobject value2 = POPA();
1790 jobject value1 = POPA();
1791 if (value1 == value2)
1792 pc = pc-1+offset;
1793 else
1794 pc = pc+2;
1795 }
1796 NEXT_INSN;
1797
1798 insn_if_acmpne:
1799 {
1800 jint offset = get2s (pc);
1801 jobject value2 = POPA();
1802 jobject value1 = POPA();
1803 if (value1 != value2)
1804 pc = pc-1+offset;
1805 else
1806 pc = pc+2;
1807 }
1808 NEXT_INSN;
1809
1810 insn_goto:
1811 {
1812 jint offset = get2s (pc);
1813 pc = pc-1+offset;
1814 }
1815 NEXT_INSN;
1816
1817 insn_jsr:
1818 {
1819 unsigned char *base_pc = pc-1;
1820 jint offset = get2s (pc); pc += 2;
1821 PUSHA ((jobject)pc);
1822 pc = base_pc+offset;
1823 }
1824 NEXT_INSN;
1825
1826 insn_ret:
1827 {
1828 jint index = get1u (pc);
1829 pc = (unsigned char*) PEEKA (index);
1830 }
1831 NEXT_INSN;
1832
1833 insn_tableswitch:
1834 {
1835 unsigned char *base_pc = pc-1;
1836 int index = POPI();
1837
1838 unsigned char* base = bytecode ();
1839 while ((pc-base) % 4 != 0)
1840 pc++;
1841
1842 jint def = get4 (pc);
1843 jint low = get4 (pc+4);
1844 jint high = get4 (pc+8);
1845
1846 if (index < low || index > high)
1847 pc = base_pc + def;
1848 else
1849 pc = base_pc + get4 (pc+4*(index-low+3));
1850 }
1851 NEXT_INSN;
1852
1853 insn_lookupswitch:
1854 {
1855 unsigned char *base_pc = pc-1;
1856 int index = POPI();
1857
1858 unsigned char* base = bytecode ();
1859 while ((pc-base) % 4 != 0)
1860 pc++;
1861
1862 jint def = get4 (pc);
1863 jint npairs = get4 (pc+4);
1864
1865 int max = npairs-1;
1866 int min = 0;
1867
1868 // simple binary search...
1869 while (min < max)
1870 {
1871 int half = (min+max)/2;
1872 int match = get4 (pc+ 4*(2 + 2*half));
1873
1874 if (index == match)
1875 min = max = half;
1876
1877 else if (index < match)
1878 max = half-1;
1879
1880 else
1881 min = half+1;
1882 }
1883
1884 if (index == get4 (pc+ 4*(2 + 2*min)))
1885 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1886 else
1887 pc = base_pc + def;
1888 }
1889 NEXT_INSN;
1890
1891 /* on return, just save the sp and return to caller */
1892 insn_ireturn:
1893 insn_lreturn:
1894 insn_freturn:
1895 insn_dreturn:
1896 insn_areturn:
1897 insn_return:
1898 inv->sp = sp;
1899 return;
1900
1901 insn_getstatic:
1902 SAVE_PC;
1903 {
1904 jint fieldref_index = get2u (pc); pc += 2;
1905 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1906 _Jv_Field *field = pool_data[fieldref_index].field;
1907
1908 if ((field->flags & Modifier::STATIC) == 0)
1909 throw_incompatible_class_change_error
1910 (JvNewStringLatin1 ("field no longer static"));
1911
1912 jclass type = field->type;
1913
1914 if (type->isPrimitive ())
1915 {
1916 switch (type->size_in_bytes)
1917 {
1918 case 1:
1919 PUSHI (*(jbyte*) (field->u.addr));
1920 break;
1921
1922 case 2:
1923 if (type == JvPrimClass (char))
1924 PUSHI(*(jchar*) (field->u.addr));
1925 else
1926 PUSHI(*(jshort*) (field->u.addr));
1927 break;
1928
1929 case 4:
1930 PUSHI(*(jint*) (field->u.addr));
1931 break;
1932
1933 case 8:
1934 PUSHL(*(jlong*) (field->u.addr));
1935 break;
1936 }
1937 }
1938 else
1939 {
1940 PUSHA(*(jobject*) (field->u.addr));
1941 }
1942 }
1943 NEXT_INSN;
1944
1945 insn_getfield:
1946 SAVE_PC;
1947 {
1948 jint fieldref_index = get2u (pc); pc += 2;
1949 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1950 _Jv_Field *field = pool_data[fieldref_index].field;
1951
1952 if ((field->flags & Modifier::STATIC) != 0)
1953 throw_incompatible_class_change_error
1954 (JvNewStringLatin1 ("field is static"));
1955
1956 jclass type = field->type;
1957 jint field_offset = field->u.boffset;
1958 if (field_offset > 0xffff)
1959 throw new java::lang::VirtualMachineError;
1960
1961 jobject obj = POPA();
1962 NULLCHECK(obj);
1963
1964 if (type->isPrimitive ())
1965 {
1966 switch (type->size_in_bytes)
1967 {
1968 case 1:
1969 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1970 break;
1971
1972 case 2:
1973 if (type == JvPrimClass (char))
1974 PUSHI (*(jchar*) ((char*)obj + field_offset));
1975 else
1976 PUSHI (*(jshort*) ((char*)obj + field_offset));
1977 break;
1978
1979 case 4:
1980 PUSHI (*(jint*) ((char*)obj + field_offset));
1981 break;
1982
1983 case 8:
1984 PUSHL(*(jlong*) ((char*)obj + field_offset));
1985 break;
1986 }
1987 }
1988 else
1989 {
1990 PUSHA(*(jobject*) ((char*)obj + field_offset));
1991 }
1992 }
1993 NEXT_INSN;
1994
1995 insn_putstatic:
1996 SAVE_PC;
1997 {
1998 jint fieldref_index = get2u (pc); pc += 2;
1999 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2000 _Jv_Field *field = pool_data[fieldref_index].field;
2001
2002 jclass type = field->type;
2003
2004 // ResolvePoolEntry cannot check this
2005 if ((field->flags & Modifier::STATIC) == 0)
2006 throw_incompatible_class_change_error
2007 (JvNewStringLatin1 ("field no longer static"));
2008
2009 if (type->isPrimitive ())
2010 {
2011 switch (type->size_in_bytes)
2012 {
2013 case 1:
2014 {
2015 jint value = POPI();
2016 *(jbyte*) (field->u.addr) = value;
2017 break;
2018 }
2019
2020 case 2:
2021 {
2022 jint value = POPI();
2023 *(jchar*) (field->u.addr) = value;
2024 break;
2025 }
2026
2027 case 4:
2028 {
2029 jint value = POPI();
2030 *(jint*) (field->u.addr) = value;
2031 break;
2032 }
2033
2034 case 8:
2035 {
2036 jlong value = POPL();
2037 *(jlong*) (field->u.addr) = value;
2038 break;
2039 }
2040 }
2041 }
2042 else
2043 {
2044 jobject value = POPA();
2045 *(jobject*) (field->u.addr) = value;
2046 }
2047 }
2048 NEXT_INSN;
2049
2050
2051 insn_putfield:
2052 SAVE_PC;
2053 {
2054 jint fieldref_index = get2u (pc); pc += 2;
2055 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2056 _Jv_Field *field = pool_data[fieldref_index].field;
2057
2058 jclass type = field->type;
2059
2060 if ((field->flags & Modifier::STATIC) != 0)
2061 throw_incompatible_class_change_error
2062 (JvNewStringLatin1 ("field is static"));
2063
2064 jint field_offset = field->u.boffset;
2065 if (field_offset > 0xffff)
2066 throw new java::lang::VirtualMachineError;
2067
2068 if (type->isPrimitive ())
2069 {
2070 switch (type->size_in_bytes)
2071 {
2072 case 1:
2073 {
2074 jint value = POPI();
2075 jobject obj = POPA();
2076 NULLCHECK(obj);
2077 *(jbyte*) ((char*)obj + field_offset) = value;
2078 break;
2079 }
2080
2081 case 2:
2082 {
2083 jint value = POPI();
2084 jobject obj = POPA();
2085 NULLCHECK(obj);
2086 *(jchar*) ((char*)obj + field_offset) = value;
2087 break;
2088 }
2089
2090 case 4:
2091 {
2092 jint value = POPI();
2093 jobject obj = POPA();
2094 NULLCHECK(obj);
2095 *(jint*) ((char*)obj + field_offset) = value;
2096 break;
2097 }
2098
2099 case 8:
2100 {
2101 jlong value = POPL();
2102 jobject obj = POPA();
2103 NULLCHECK(obj);
2104 *(jlong*) ((char*)obj + field_offset) = value;
2105 break;
2106 }
2107 }
2108 }
2109 else
2110 {
2111 jobject value = POPA();
2112 jobject obj = POPA();
2113 NULLCHECK(obj);
2114 *(jobject*) ((char*)obj + field_offset) = value;
2115 }
2116 }
2117 NEXT_INSN;
2118
2119 insn_invokespecial:
2120 SAVE_PC;
2121 {
2122 int index = get2u (pc); pc += 2;
2123
2124 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2125
2126 sp -= rmeth->stack_item_count;
2127
2128 NULLCHECK (sp[0].o);
2129
2130 fun = (void (*)()) rmeth->method->ncode;
2131 }
2132 goto perform_invoke;
2133
2134 insn_invokestatic:
2135 SAVE_PC;
2136 {
2137 int index = get2u (pc); pc += 2;
2138
2139 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2140
2141 sp -= rmeth->stack_item_count;
2142
2143 _Jv_InitClass (rmeth->klass);
2144 fun = (void (*)()) rmeth->method->ncode;
2145 }
2146 goto perform_invoke;
2147
2148 insn_invokeinterface:
2149 SAVE_PC;
2150 {
2151 int index = get2u (pc); pc += 2;
2152
2153 // invokeinterface has two unused bytes...
2154 pc += 2;
2155
2156 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2157
2158 sp -= rmeth->stack_item_count;
2159
2160 jobject rcv = sp[0].o;
2161
2162 NULLCHECK (rcv);
2163
2164 fun = (void (*)())
2165 _Jv_LookupInterfaceMethod (rcv->getClass (),
2166 rmeth->method->name,
2167 rmeth->method->signature);
2168 }
2169 goto perform_invoke;
2170
2171
2172 insn_new:
2173 SAVE_PC;
2174 {
2175 int index = get2u (pc); pc += 2;
2176 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2177 _Jv_InitClass (klass);
2178 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2179 PUSHA (res);
2180 }
2181 NEXT_INSN;
2182
2183 insn_newarray:
2184 SAVE_PC;
2185 {
2186 int atype = get1u (pc++);
2187 int size = POPI();
2188 jobject result = _Jv_NewArray (atype, size);
2189 PUSHA (result);
2190 }
2191 NEXT_INSN;
2192
2193 insn_anewarray:
2194 SAVE_PC;
2195 {
2196 int index = get2u (pc); pc += 2;
2197 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2198 int size = POPI();
2199 _Jv_InitClass (klass);
2200 jobject result = _Jv_NewObjectArray (size, klass, 0);
2201 PUSHA (result);
2202 }
2203 NEXT_INSN;
2204
2205 insn_arraylength:
2206 {
2207 __JArray *arr = (__JArray*)POPA();
2208 NULLARRAYCHECK (arr);
2209 PUSHI (arr->length);
2210 }
2211 NEXT_INSN;
2212
2213 insn_athrow:
2214 SAVE_PC;
2215 {
2216 jobject value = POPA();
2217 throw static_cast<jthrowable>(value);
2218 }
2219 NEXT_INSN;
2220
2221 insn_checkcast:
2222 SAVE_PC;
2223 {
2224 jobject value = POPA();
2225 jint index = get2u (pc); pc += 2;
2226 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2227
2228 if (value != NULL && ! to->isInstance (value))
2229 {
2230 throw new java::lang::ClassCastException (to->getName());
2231 }
2232
2233 PUSHA (value);
2234 }
2235 NEXT_INSN;
2236
2237 insn_instanceof:
2238 SAVE_PC;
2239 {
2240 jobject value = POPA();
2241 jint index = get2u (pc); pc += 2;
2242 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2243 PUSHI (to->isInstance (value));
2244 }
2245 NEXT_INSN;
2246
2247 insn_monitorenter:
2248 SAVE_PC;
2249 {
2250 jobject value = POPA();
2251 NULLCHECK(value);
2252 _Jv_MonitorEnter (value);
2253 }
2254 NEXT_INSN;
2255
2256 insn_monitorexit:
2257 SAVE_PC;
2258 {
2259 jobject value = POPA();
2260 NULLCHECK(value);
2261 _Jv_MonitorExit (value);
2262 }
2263 NEXT_INSN;
2264
2265 insn_ifnull:
2266 {
2267 unsigned char* base_pc = pc-1;
2268 jint offset = get2s (pc); pc += 2;
2269 jobject val = POPA();
2270 if (val == NULL)
2271 pc = base_pc+offset;
2272 }
2273 NEXT_INSN;
2274
2275 insn_ifnonnull:
2276 {
2277 unsigned char* base_pc = pc-1;
2278 jint offset = get2s (pc); pc += 2;
2279 jobject val = POPA();
2280 if (val != NULL)
2281 pc = base_pc+offset;
2282 }
2283 NEXT_INSN;
2284
2285 insn_wide:
2286 SAVE_PC;
2287 {
2288 jint the_mod_op = get1u (pc++);
2289 jint wide = get2u (pc); pc += 2;
2290
2291 switch (the_mod_op)
2292 {
2293 case op_istore:
2294 STOREI (wide);
2295 NEXT_INSN;
2296
2297 case op_fstore:
2298 STOREF (wide);
2299 NEXT_INSN;
2300
2301 case op_astore:
2302 STOREA (wide);
2303 NEXT_INSN;
2304
2305 case op_lload:
2306 LOADL (wide);
2307 NEXT_INSN;
2308
2309 case op_dload:
2310 LOADD (wide);
2311 NEXT_INSN;
2312
2313 case op_iload:
2314 LOADI (wide);
2315 NEXT_INSN;
2316
2317 case op_aload:
2318 LOADA (wide);
2319 NEXT_INSN;
2320
2321 case op_lstore:
2322 STOREL (wide);
2323 NEXT_INSN;
2324
2325 case op_dstore:
2326 STORED (wide);
2327 NEXT_INSN;
2328
2329 case op_ret:
2330 pc = (unsigned char*) PEEKA (wide);
2331 NEXT_INSN;
2332
2333 case op_iinc:
2334 {
2335 jint amount = get2s (pc); pc += 2;
2336 jint value = PEEKI (wide);
2337 POKEI (wide, value+amount);
2338 }
2339 NEXT_INSN;
2340
2341 default:
2342 throw_internal_error ("illegal bytecode modified by wide");
2343 }
2344
2345 }
2346
2347 insn_multianewarray:
2348 SAVE_PC;
2349 {
2350 int kind_index = get2u (pc); pc += 2;
2351 int dim = get1u (pc); pc += 1;
2352
2353 jclass type
2354 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2355 _Jv_InitClass (type);
2356 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2357
2358 for (int i = dim - 1; i >= 0; i--)
2359 {
2360 sizes[i] = POPI ();
2361 }
2362
2363 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2364
2365 PUSHA (res);
2366 }
2367 NEXT_INSN;
2368
2369 insn_goto_w:
2370 {
2371 unsigned char* base_pc = pc-1;
2372 int offset = get4 (pc); pc += 4;
2373 pc = base_pc+offset;
2374 }
2375 NEXT_INSN;
2376
2377 insn_jsr_w:
2378 {
2379 unsigned char* base_pc = pc-1;
2380 int offset = get4 (pc); pc += 4;
2381 PUSHA((jobject)pc);
2382 pc = base_pc+offset;
2383 }
2384 NEXT_INSN;
2385 }
2386
2387
2388 static void
2389 throw_internal_error (char *msg)
2390 {
2391 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
2392 }
2393
2394 static void
2395 throw_incompatible_class_change_error (jstring msg)
2396 {
2397 throw new java::lang::IncompatibleClassChangeError (msg);
2398 }
2399
2400 #ifndef HANDLE_SEGV
2401 static java::lang::NullPointerException *null_pointer_exc;
2402 static void
2403 throw_null_pointer_exception ()
2404 {
2405 if (null_pointer_exc == NULL)
2406 null_pointer_exc = new java::lang::NullPointerException;
2407
2408 throw null_pointer_exc;
2409 }
2410 #endif
2411
2412 #endif // INTERPRETER