Fix Java long (64 bit) operations, add missing ones, fix compiler warnings
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blobe9b7c0e3b8957640ffa71eb7585f1f621e06fefa
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #define _GNU_SOURCE
23 #include <arpa/inet.h>
24 #include <math.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "jam.h"
31 #include "thread.h"
32 #include "lock.h"
33 #include "interp.h"
35 #include "interp-direct.h"
37 #include <sys/syscall.h>
38 #include <unistd.h>
39 #include <sys/mman.h>
41 #include <sys/types.h>
42 #include <linux/unistd.h>
44 #include <asm/byteorder.h>
45 #include <asm/cachectl.h>
47 #include "arch/avr32_jem.h"
48 #include "interp_jem.h"
50 union jecr {
51 struct {
52 uint8_t dummy;
53 uint8_t opcode;
54 uint8_t op1;
55 uint8_t op2;
56 } s;
57 uint32_t i;
60 /**
61 * Interpreter execution context
63 struct intrp_ctx {
64 /* JEM state */
65 struct jem_state jem;
67 /* the interpreter execution context */
68 Frame *frame;
69 MethodBlock *mb;
70 MethodBlock *new_mb;
71 ConstantPool *cp;
72 Object *this;
73 uintptr_t *lvars_jem;
74 uintptr_t *ostack;
75 uintptr_t *arg1;
76 ExecEnv *ee;
79 #define GET_THIS(ctx) do { \
80 if (!((ctx)->mb->access_flags & ACC_STATIC) && (ctx)->mb->max_locals && \
81 *(ctx)->lvars_jem) { \
82 uintptr_t *__p = (uintptr_t *)*(ctx)->lvars_jem; \
83 (ctx)->this = JAM_OBJECT(__p); \
84 } else \
85 (ctx)->this = NULL; \
86 jam_dprintf("[%s] %smethod with %d vars, assigning %p\n", __func__, \
87 (ctx)->mb->access_flags & ACC_STATIC ? "static " : "", \
88 (ctx)->mb->max_locals, (ctx)->this); \
89 } while (0)
91 typedef int handler_fn(struct intrp_ctx *ctx);
93 static void jem_opcode_rewrite(uint32_t new_opcode, char *pc, int argc, ...)
95 int i;
96 va_list vargs;
98 va_start(vargs, argc);
99 pc[0] = new_opcode;
100 for (i = 1; i <= argc; i++)
101 pc[i] = (char)va_arg(vargs, int);
102 va_end(vargs);
103 syscall(__NR_cacheflush, CACHE_IFLUSH, (int)pc & ~31, 32);
106 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
108 //check if it is an valid object ref (see alloc.c)
109 #define OBJECT_GRAIN 8
110 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
112 #define JEM_THROW_EXCEPTION(excep_name, message) \
113 ({ \
114 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
115 signalException(excep_name, message); \
116 jem_throwException(ctx); \
119 #define JEM_NULL_POINTER_CHECK(ref) \
120 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
122 /*********************************************
123 * JEM Trap Handlers **
124 * *******************************************/
125 static int trap_debug(struct intrp_ctx *ctx)
127 #ifdef JEM_DEBUG
128 struct jem_state *jem = &ctx->jem;
129 union jecr jecr_u;
130 int i;
131 static unsigned long count;
133 jecr_u.i = jem->jecr;
135 jam_printf("[%lu] (%u): Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
136 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
137 count++, pthread_self(), jem->trap_pc, ctx->ostack, jecr_u.s.opcode,
138 jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
140 for (i = 0; i < jem->josp; i++) {
141 uint32_t v;
142 if (ostack_read_u32(ctx->frame->ostack, ctx->ostack, i, &v) >= 0)
143 jam_printf("\tToS-%d: 0x%x\n", i, v);
145 #endif
146 return 1;
150 static int jem_throwException(struct intrp_ctx *ctx)
152 struct jem_state *jem = &ctx->jem;
153 ExecEnv *ee = ctx->ee;
154 Object *excep = ee->exception;
155 ee->exception = NULL;
157 jem->jpc = (unsigned long)findCatchBlock(excep->class);
158 jam_dprintf("Found exception handler at 0x%08x\n", jem->jpc);
160 /* If we didn't find a handler, restore exception and
161 return to previous invocation */
163 if (!jem->jpc) {
164 ee->exception = excep;
165 /* Original code had a "return NULL" here, which means, end of
166 * executeJava */
167 return JEM_TRAP_HANDLER_FINISH;
170 /* If we're handling a stack overflow, reduce the stack
171 back past the red zone to enable handling of further
172 overflows */
174 if (ee->overflow) {
175 ee->overflow = FALSE;
176 ee->stack_end -= STACK_RED_ZONE_SIZE;
179 /* Setup intepreter to run the found catch block */
181 ctx->frame = ee->last_frame;
182 ctx->mb = ctx->frame->mb;
183 ctx->ostack = ctx->frame->ostack;
184 ctx->lvars_jem = ctx->frame->lvars_jem - 1;
186 GET_THIS(ctx);
188 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
190 /* FIXME: don't know if this is correct, depends how we implement
191 * exceptions */
192 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uint32_t)excep);
194 /* Dispatch to the first bytecode */
195 return 0;
198 static int opc_return(struct intrp_ctx *ctx)
200 ExecEnv *ee = ctx->ee;
202 /* Set interpreter state to previous frame */
203 if (ctx->frame->prev->mb == NULL) {
204 /* The previous frame is a dummy frame - this indicates
205 * top of this Java invocation. */
206 return JEM_TRAP_HANDLER_FINISH;
209 ctx->frame = ctx->frame->prev;
211 jam_dprintf("[%s] return to frame %p mb %p\n", __func__, ctx->frame, ctx->frame->mb);
213 if (ctx->mb->access_flags & ACC_SYNCHRONIZED) {
214 Object *sync_ob = ctx->mb->access_flags & ACC_STATIC ? (Object*)ctx->mb->class : ctx->this;
215 jam_dprintf("[%s] %smethod unlock obj %p\n", __func__,
216 ctx->mb->access_flags & ACC_STATIC ? "static " : "", sync_ob);
217 objectUnlock(sync_ob);
220 ctx->ostack = ctx->lvars_jem - ctx->mb->max_locals + 1 - ctx->mb->args_count;
221 ctx->mb = ctx->frame->mb;
222 ctx->lvars_jem = ctx->frame->lvars_jem - 1;
224 GET_THIS(ctx);
226 ctx->jem.jpc = (uint32_t)ctx->frame->last_pc;
227 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
228 jam_dprintf("[OPC_RETURN] ostack: %p, lvars_jem: %p this: %p class %p\n",
229 ctx->ostack, ctx->lvars_jem, ctx->this,
230 ctx->this ? ctx->this->class : NULL);
232 /* Pop frame */
233 ee->last_frame = ctx->frame;
235 return 0;
238 static int invokeMethod(struct intrp_ctx *ctx)
240 ExecEnv *ee = ctx->ee;
241 /* Seems like the original jamvm reused top of caller's stack for callee's
242 * local variables for passing of method arguments. Our stack and
243 * local variables grow in opposite directions now, so, this is impossible.
244 * ctx->ostack points at the beginning of the free space above ostack.
246 Frame *new_frame = (Frame *)(ctx->ostack + ctx->new_mb->max_locals);
247 Object *sync_ob = NULL;
248 int i;
249 uintptr_t *aobj;
251 jam_dprintf("[invokeMethod] with args count %d, frame %p, return to 0x%08x\n",
252 ctx->new_mb->args_count, new_frame, ctx->jem.jpc);
254 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
255 ctx->ostack = (uintptr_t *)(new_frame + 1);
257 if (ostack_overflows(ctx->ostack, ctx->new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
258 if (ee->overflow++) {
259 /* Overflow when we're already throwing stack overflow.
260 Stack extension should be enough to throw exception,
261 so something's seriously gone wrong - abort the VM! */
262 jam_printf("Fatal stack overflow! Aborting VM.\n");
263 exitVM(1);
265 ee->stack_end += STACK_RED_ZONE_SIZE;
266 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
269 //TODO
270 new_frame->mb = ctx->new_mb;
271 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
272 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
273 // Here still not touch the java stack, allocate lvars_jem from native heap
275 new_frame->lvars_jem = (uintptr_t *)new_frame;
277 for (i = 0; i < ctx->new_mb->max_locals; i++) {
278 if (i < ctx->new_mb->args_count) {
279 *(new_frame->lvars_jem - 1 - i) = *(ctx->arg1 + i);
280 jam_dprintf("arg[%d] = 0x%x@%p\n", i, *(ctx->arg1 + i), ctx->arg1 + i);
282 #ifdef JEM_DEBUG
283 else
284 *(new_frame->lvars_jem - 1 - i) = 0xdeadbeef;
285 #endif
288 jam_dprintf("[invokeMethod] %s::%s() lvars_jem %p\n",
289 CLASS_CB(ctx->new_mb->class)->name, ctx->new_mb->name, new_frame->lvars_jem);
291 new_frame->ostack = ctx->ostack;
292 new_frame->prev = ctx->frame;
294 ee->last_frame = new_frame;
296 if (ctx->new_mb->access_flags & ACC_SYNCHRONIZED) {
297 aobj = (uintptr_t *)*ctx->arg1;
298 sync_ob = ctx->new_mb->access_flags & ACC_STATIC ?
299 (Object*)ctx->new_mb->class : JAM_OBJECT(aobj);
300 objectLock(sync_ob);
303 if (ctx->new_mb->access_flags & ACC_NATIVE) {
304 //FIXME: the object references in JEM are direct pointer to instance variables.
305 // While JamVM requires object references as pointers to Object type.
306 jam_dprintf("[invokeMethod] invoke native method using %p invoker\n",
307 ctx->new_mb->native_invoker);
308 ctx->ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
309 ctx->new_mb->native_invoker)(ctx->new_mb->class, ctx->new_mb, ctx->arg1);
311 if (sync_ob)
312 objectUnlock(sync_ob);
314 ee->last_frame = ctx->frame;
316 if (exceptionOccured0(ee)) {
317 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
318 return jem_throwException(ctx);
321 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
322 } else {
323 ctx->frame = new_frame;
324 ctx->mb = ctx->new_mb;
325 ctx->lvars_jem = new_frame->lvars_jem - 1;
327 GET_THIS(ctx);
329 ctx->jem.jpc = (unsigned long)ctx->mb->code & ~3;
330 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
332 jam_dprintf("[invokeMethod] invoke virtual method: mb %x "
333 "lvars %x jpc %x cp %x\n", ctx->mb,
334 ctx->lvars_jem, ctx->jem.jpc, ctx->cp);
337 return 0;
340 static int opc_invokesuper_quick(struct intrp_ctx *ctx)
342 struct jem_state *jem = &ctx->jem;
343 Operand *operand = &jem->operand;
345 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
346 ctx->new_mb = CLASS_CB(CLASS_CB(ctx->mb->class)->super)->method_table[operand->i];
347 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx->new_mb->args_count);
349 // set up jem operand stack
350 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
351 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
352 JEM_NULL_POINTER_CHECK(*ctx->arg1);
353 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx->arg1);
354 return invokeMethod(ctx);
357 static int opc_invokenonvirtual_quick(struct intrp_ctx *ctx)
359 struct jem_state *jem = &ctx->jem;
360 Operand *operand = &jem->operand;
362 ctx->new_mb = (MethodBlock*)operand->pntr;
363 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
364 __func__, ctx->new_mb->name, ctx->new_mb, ctx->new_mb->args_count);
365 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
366 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
368 jam_dprintf("[%s] ctx->arg1 %x\n", __func__, *ctx->arg1);
369 JEM_NULL_POINTER_CHECK(*ctx->arg1);
370 return invokeMethod(ctx);
373 static int opc_invokevirtual_quick(struct intrp_ctx *ctx)
375 struct jem_state *jem = &ctx->jem;
376 Object *obj;
377 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
378 ctx->ostack - ctx->frame->ostack - INV_QUICK_ARGS(jem));
379 JEM_NULL_POINTER_CHECK(*ctx->arg1);
380 Class *new_class;
382 //in case of "AALOAD" loads JAM obj from reference array
383 obj = (Object *)*ctx->arg1;
384 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj)) {
385 obj = JAM_OBJECT((uintptr_t *)obj);
386 //we should ensure ostack contains no JAM object
387 *ctx->arg1 = (uintptr_t)INST_DATA(obj);
390 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object %p from %p class %p\n",
391 obj, ctx->arg1, obj->class);
392 new_class = obj->class;
393 ctx->new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(jem)];
394 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x\n",
395 ctx->new_mb);
396 return invokeMethod(ctx);
399 static int opc_invokevirtual(struct intrp_ctx *ctx)
401 int idx;
402 ExecEnv *ee = ctx->ee;
403 struct jem_state *jem = &ctx->jem;
405 idx = jem->jecr & 0xffff;
406 ctx->frame->last_pc = (CodePntr)jem->jpc;
407 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
409 if (exceptionOccured0(ee))
410 return jem_throwException(ctx);
412 jem->operand.uu.u1 = ctx->new_mb->args_count;
413 jem->operand.uu.u2 = ctx->new_mb->method_table_index;
415 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
416 ctx->new_mb, ctx->new_mb->args_count);
418 return opc_invokevirtual_quick(ctx);
421 static int opc_invokespecial(struct intrp_ctx *ctx)
423 int idx;
424 struct jem_state *jem = &ctx->jem;
425 Operand *operand = &jem->operand;
426 ExecEnv *ee = ctx->ee;
428 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
429 idx = jem->jecr & 0xffff;
431 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx);
433 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
435 if (exceptionOccured0(ee))
436 return jem_throwException(ctx);
438 jam_dprintf("Resolved %s\n", ctx->new_mb->name);
440 /* Check if invoking a super method... */
441 if ((CLASS_CB(ctx->mb->class)->access_flags & ACC_SUPER) &&
442 ((ctx->new_mb->access_flags & ACC_PRIVATE) == 0) && (ctx->new_mb->name[0] != '<')) {
444 operand->i = ctx->new_mb->method_table_index;
445 return opc_invokesuper_quick(ctx);
446 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
447 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
448 #endif
449 } else {
450 operand->pntr = ctx->new_mb;
451 return opc_invokenonvirtual_quick(ctx);
454 return 0;
457 static int opc_invokestatic_quick(struct intrp_ctx *ctx)
459 struct jem_state *jem = &ctx->jem;
461 ctx->new_mb = RESOLVED_METHOD(jem);
462 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
463 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
464 return invokeMethod(ctx);
467 static int opc_invokestatic(struct intrp_ctx *ctx)
469 int idx;
470 struct jem_state *jem = &ctx->jem;
471 Operand *operand = &jem->operand;
472 ExecEnv *ee = ctx->ee;
474 idx = jem->jecr & 0xffff;
476 ctx->frame->last_pc = (CodePntr)jem->jpc;
477 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
479 if (exceptionOccured0(ee))
480 return jem_throwException(ctx);
482 operand->pntr = ctx->new_mb;
483 return opc_invokestatic_quick(ctx);
486 static int opc_new_quick(struct intrp_ctx *ctx)
488 struct jem_state *jem = &ctx->jem;
489 Operand *operand = &jem->operand;
490 Class *class = (Class*)CP_INFO(ctx->cp, operand->uui.u1);
491 Object *obj;
493 ctx->frame->last_pc = (CodePntr)jem->jpc;
494 if ((obj = allocObject(class)) == NULL)
495 return jem_throwException(ctx);
496 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj);
497 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
498 (uint32_t)INST_DATA(obj));
501 static int opc_new(struct intrp_ctx *ctx)
503 struct jem_state *jem = &ctx->jem;
504 Operand *operand = &jem->operand;
505 int idx = jem->jecr & 0xffff;
506 int opcode = (jem->jecr >> 16) & 0xff;
507 Class *class;
508 ExecEnv *ee = ctx->ee;
510 operand->uui.u1 = idx;
511 operand->uui.u2 = opcode;
513 jam_dprintf("[OPC_NEW] opcode: 0x%x, index: 0x%x\n", opcode, idx);
515 ctx->frame->last_pc = (CodePntr)jem->jpc;
516 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
517 if (exceptionOccured0(ee))
518 return jem_throwException(ctx);
520 if (opcode == OPC_NEW) {
521 ClassBlock *cb = CLASS_CB(class);
522 if (cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
523 signalException("java/lang/InstantiationError", cb->name);
524 return jem_throwException(ctx);
526 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
527 jem_opcode_rewrite(0xDD, (char*)jem->jpc - 3, 0);
530 return opc_new_quick(ctx);
533 static int opc_anewarray_quick(struct intrp_ctx *ctx)
535 struct jem_state *jem = &ctx->jem;
536 ConstantPool *cp = ctx->cp;
537 Class *class = RESOLVED_CLASS(jem);
538 char *name = CLASS_CB(class)->name;
539 int count;
540 Class *array_class;
541 char *ac_name;
542 Object *obj;
543 ExecEnv *ee = ctx->ee;
545 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
546 ctx->frame->last_pc = (CodePntr)jem->jpc;
548 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name, count);
549 if (count < 0) {
550 signalException("java/lang/NegativeArraySizeException", NULL);
551 return jem_throwException(ctx);
554 ac_name = sysMalloc(strlen(name) + 4);
556 if (name[0] == '[')
557 sprintf(ac_name, "[%s", name);
558 else
559 sprintf(ac_name, "[L%s;", name);
561 array_class = findArrayClassFromClass(ac_name, ctx->mb->class);
562 free(ac_name);
564 if (exceptionOccured0(ee))
565 return jem_throwException(ctx);
567 if ((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
568 return jem_throwException(ctx);
570 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
571 (uint32_t)ARRAY_DATA(obj));
574 static int opc_anewarray(struct intrp_ctx *ctx)
576 struct jem_state *jem = &ctx->jem;
577 Operand *operand = &jem->operand;
578 int idx = jem->jecr & 0xffff;
579 int opcode = (jem->jecr >> 16) & 0xff;
580 Class *class;
581 ExecEnv *ee = ctx->ee;
583 operand->uui.u1 = idx;
584 operand->uui.u2 = opcode;
586 jam_dprintf("[OPC_ANEWARRAY] index: 0x%x\n", idx);
588 ctx->frame->last_pc = (CodePntr)jem->jpc;
589 //resolve the array class
590 class = resolveClass(ctx->mb->class, idx, FALSE);
592 if (exceptionOccured0(ee))
593 return jem_throwException(ctx);
595 return opc_anewarray_quick(ctx);
598 static int opc_multianewarray_quick(struct intrp_ctx *ctx)
600 struct jem_state *jem = &ctx->jem;
601 ConstantPool *cp = ctx->cp;
602 Class *class = RESOLVED_CLASS(jem);
603 int i, dim = MULTI_ARRAY_DIM(jem);
604 int count;
605 Object *obj;
607 ctx->frame->last_pc = (CodePntr)jem->jpc;
609 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim, CLASS_CB(class)->name);
610 for (i = 0; i < dim; i++) {
611 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
612 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count, i);
613 if (count < 0) {
614 signalException("java/lang/NegativeArraySizeException", NULL);
615 return jem_throwException(ctx);
619 /* counts are still stored in ostack even after we did pop them out */
620 if ((obj = allocMultiArray(class, dim, (intptr_t *)ctx->ostack)) == NULL)
621 return jem_throwException(ctx);
623 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
624 (uint32_t)ARRAY_DATA(obj));
627 static int opc_multianewarray(struct intrp_ctx *ctx)
629 struct jem_state *jem = &ctx->jem;
630 Operand *operand = &jem->operand;
631 int idx = operand->uui.u1 = jem->jecr & 0xffff;
633 Class *class;
634 ExecEnv *ee = ctx->ee;
636 /* dimensions */
637 operand->uui.u2 = *(unsigned char*)jem->jpc;
638 jem->jpc++; /* skip dims */
640 ctx->frame->last_pc = (CodePntr)jem->jpc;
641 /* resolve the array class */
642 class = resolveClass(ctx->mb->class, idx, FALSE);
644 if (exceptionOccured0(ee))
645 return jem_throwException(ctx);
647 return opc_multianewarray_quick(ctx);
650 static int opc_newarray(struct intrp_ctx *ctx)
652 struct jem_state *jem = &ctx->jem;
653 int type = (jem->jecr >> 8) & 0xff;
654 int count;
655 Object *obj;
657 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
658 ctx->frame->last_pc = (CodePntr)jem->jpc;
660 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type, count);
661 if ((obj = allocTypeArray(type, count)) == NULL)
662 return jem_throwException(ctx);
664 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
665 (uint32_t)ARRAY_DATA(obj));
668 static int opc_putfield_quick(struct intrp_ctx *ctx)
670 uint32_t arg;
671 uint32_t obj;
672 struct jem_state *jem = &ctx->jem;
674 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
675 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
676 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg,
677 SINGLE_INDEX(jem), obj);
679 JEM_NULL_POINTER_CHECK(obj);
681 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
682 obj = (uint32_t)INST_DATA((Object *)obj);
684 ((uint32_t*)obj)[SINGLE_INDEX(jem)] = arg;
686 return 0;
689 union ull_2ui {
690 long long ll;
691 unsigned int i[2];
694 static int opc_putfield2_quick(struct intrp_ctx *ctx)
696 uint32_t obj;
697 struct jem_state *jem = &ctx->jem;
698 union ull_2ui v;
700 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
701 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
703 JEM_NULL_POINTER_CHECK((uintptr_t*)obj);
705 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
706 obj = (uint32_t)INST_DATA((Object *)obj);
708 *(uint64_t *)&(((uint32_t*)obj)[SINGLE_INDEX(jem)]) = v.ll;
709 jam_dprintf("[%s] put 64 bit field 0x%llx to obj %08x\n", __func__, v.ll, obj);
711 return 0;
714 static int opc_putfield_quick_jem0(struct intrp_ctx *ctx)
716 uint32_t arg;
717 uintptr_t *aobj;
718 struct jem_state *jem = &ctx->jem;
720 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
721 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
722 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg);
724 JEM_NULL_POINTER_CHECK(aobj);
726 if (JAM_ON_STACK && arg && !IS_JAM_OBJECT(arg))
727 arg = (uint32_t)JAM_OBJECT((uintptr_t *)arg);
729 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
730 aobj = INST_DATA((Object *)aobj);
732 aobj[SINGLE_INDEX(jem)] = arg;
733 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg,
734 SINGLE_INDEX(jem), aobj);
736 return 0;
739 static int opc_putfield_quick_jem1(struct intrp_ctx *ctx)
741 uintptr_t *aobj, *arg;
742 struct jem_state *jem = &ctx->jem;
744 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
745 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
746 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg);
748 if (JAM_ON_STACK && arg && !IS_JAM_ARRAY(arg))
749 arg = (uintptr_t *)JAM_ARRAY(arg);
751 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
752 aobj = INST_DATA((Object *)aobj);
754 JEM_NULL_POINTER_CHECK(aobj);
755 aobj[SINGLE_INDEX(jem)] = (uintptr_t)arg;
756 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg,
757 SINGLE_INDEX(jem), aobj);
759 return 0;
762 static int opc_putfield(struct intrp_ctx *ctx)
764 struct jem_state *jem = &ctx->jem;
765 int idx = jem->jecr & 0xffff;
766 FieldBlock *fb;
767 ExecEnv *ee = ctx->ee;
769 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx);
771 ctx->frame->last_pc = (CodePntr)jem->jpc;
772 fb = resolveField(ctx->mb->class, idx);
773 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c, name %s\n", fb, *fb->type, fb->name);
775 if (exceptionOccured0(ee))
776 return jem_throwException(ctx);
778 jem->operand.i = fb->offset;
779 switch (*fb->type) {
780 case 'J':
781 case 'D':
782 /* rewrite opc_putfield to opc_putfield2_quick */
783 jem_opcode_rewrite(0xD1, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
784 return opc_putfield2_quick(ctx);
785 case 'L':
786 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
787 return opc_putfield_quick_jem0(ctx);
788 case '[':
789 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
790 return opc_putfield_quick_jem1(ctx);
791 default:
792 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
793 return opc_putfield_quick(ctx);
797 static int opc_getfield2_quick(struct intrp_ctx *ctx)
799 uint32_t *obj;
800 struct jem_state *jem = &ctx->jem;
801 union ull_2ui v;
803 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
805 JEM_NULL_POINTER_CHECK(obj);
807 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
808 obj = (uint32_t*)INST_DATA((Object*)obj);
810 v.ll = *(uint64_t*)(&(obj[SINGLE_INDEX(jem)]));
811 jam_dprintf("[%s] get 64 bit field 0x%llx from obj %08x\n", __func__, v.ll, obj);
813 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
816 static int opc_getfield_quick(struct intrp_ctx *ctx)
818 uintptr_t *aobj;
819 struct jem_state *jem = &ctx->jem;
821 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
822 JEM_NULL_POINTER_CHECK(aobj);
824 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
825 aobj = (uint32_t*)INST_DATA((Object*)aobj);
827 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
828 aobj[SINGLE_INDEX(jem)], aobj);
829 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
830 aobj[SINGLE_INDEX(jem)]);
833 static int opc_getfield_quick_jem0(struct intrp_ctx *ctx)
835 uint32_t *aobj;
836 struct jem_state *jem = &ctx->jem;
838 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
839 JEM_NULL_POINTER_CHECK(aobj);
841 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
842 aobj = (uint32_t*)INST_DATA((Object*)aobj);
844 uint32_t value = aobj[SINGLE_INDEX(jem)];
845 if (value) {
846 Object *ref = (Object*)value;
847 if (JAM_ON_STACK && IS_JAM_OBJECT(ref))
848 //jamvm objref
849 value = (uint32_t)INST_DATA(ref);
850 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj %p ref %x, class %p : %p\n",
851 aobj, value, JAM_OBJECT((void *)value)->class, ref->class);
853 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value);
854 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
857 static int opc_getfield_quick_jem1(struct intrp_ctx *ctx)
859 uint32_t *aobj;
860 struct jem_state *jem = &ctx->jem;
862 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
863 JEM_NULL_POINTER_CHECK(aobj);
865 //"aaload" would put jamvm obj ref onto the ostack
866 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
867 aobj = (uint32_t*)INST_DATA((Object*)aobj);
869 uint32_t value = aobj[SINGLE_INDEX(jem)];
870 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value);
871 if (value) {
872 Object *ref = (Object*)value;
873 if (JAM_ON_STACK && IS_JAM_ARRAY(ref))
874 value = (uint32_t)ARRAY_DATA(ref);
876 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value);
877 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
880 static int opc_getfield(struct intrp_ctx *ctx)
882 struct jem_state *jem = &ctx->jem;
883 int idx = jem->jecr & 0xffff;
884 FieldBlock *fb;
885 ExecEnv *ee = ctx->ee;
887 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx);
889 ctx->frame->last_pc = (CodePntr)jem->jpc;
890 fb = resolveField(ctx->mb->class, idx);
892 if (exceptionOccured0(ee))
893 return jem_throwException(ctx);
895 jem->operand.i = fb->offset;
897 jam_dprintf("[OPC_GETFIELD] resolve field %s @ %p, type %c, offset %i, class %p\n",
898 fb->name, fb, *fb->type, jem->operand.i, fb->class);
900 switch (*fb->type) {
901 case 'J':
902 case 'D':
903 jem_opcode_rewrite(0xD0, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
904 return opc_getfield2_quick(ctx);
906 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
907 * in case of some JNI code will set field natively, we still handle it
908 * separately here.
910 case 'L':
911 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
912 return opc_getfield_quick_jem0(ctx);
913 case '[':
914 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
915 return opc_getfield_quick_jem1(ctx);
916 default:
917 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
918 return opc_getfield_quick(ctx);
922 static int opc_ldc2_w(struct intrp_ctx *ctx)
924 int idx;
925 union ull_2ui v;
926 struct jem_state *jem = &ctx->jem;
928 idx = (jem->jecr & 0xffff);
929 jam_dprintf("[OPC_LDC2_W] constant pool index %d\n", idx);
930 jem->operand.i = idx;
932 //read long long from constant pool
933 v.ll = (uint64_t)CP_LONG(ctx->cp, DOUBLE_INDEX(jem));
934 jam_dprintf("[OPC_LDC2_W] push constant 0x%llx to stack\n", v.ll);
936 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
939 static int opc_ldc_w_quick_jem(struct intrp_ctx *ctx)
941 struct jem_state *jem = &ctx->jem;
942 //CONSTANT_Class and CONSTANT_String are stored as object reference
943 Object *cp_info = (Object*)CP_INFO(ctx->cp, DOUBLE_INDEX(jem));
944 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info);
945 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
946 (uint32_t)INST_DATA(cp_info));
949 static int opc_ldc_quick(struct intrp_ctx *ctx)
951 struct jem_state *jem = &ctx->jem;
952 uint32_t constant = RESOLVED_CONSTANT(jem);
953 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant);
954 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uintptr_t)constant);
957 static int opc_ldc_common(struct intrp_ctx *ctx, int idx)
959 struct jem_state *jem = &ctx->jem;
960 ExecEnv *ee = ctx->ee;
961 ctx->frame->last_pc = (CodePntr)jem->jpc;
963 jem->operand.u = resolveSingleConstant(ctx->mb->class, idx);
965 if (exceptionOccured0(ee))
966 return jem_throwException(ctx);
968 switch (CP_TYPE(ctx->cp, idx)) {
969 case CONSTANT_ResolvedClass:
970 case CONSTANT_ResolvedString:
971 jem->operand.i = idx;
972 return opc_ldc_w_quick_jem(ctx);
973 default:
974 jem_opcode_rewrite(0xCB, (char*)jem->jpc - 2, 0);
975 return opc_ldc_quick(ctx);
979 static int opc_ldc(struct intrp_ctx *ctx)
981 int idx;
982 struct jem_state *jem = &ctx->jem;
984 idx = (jem->jecr & 0xff00) >> 8;
986 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx);
987 return opc_ldc_common(ctx, idx);
990 static int opc_ldc_w(struct intrp_ctx *ctx)
992 int idx;
993 struct jem_state *jem = &ctx->jem;
995 idx = (jem->jecr & 0xffff);
997 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx);
998 return opc_ldc_common(ctx, idx);
1001 static int opc_monitorenter(struct intrp_ctx *ctx)
1003 Object *obj;
1004 uintptr_t *ptr;
1005 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1007 obj = JAM_OBJECT(ptr);
1008 if (!IS_OBJECT(obj))
1009 /* is an array ref */
1010 obj = JAM_ARRAY(ptr);
1011 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj);
1012 JEM_NULL_POINTER_CHECK(obj);
1013 objectLock(obj);
1014 return 0;
1017 static int opc_monitorexit(struct intrp_ctx *ctx)
1019 Object *obj;
1020 uintptr_t *ptr;
1021 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1023 obj = JAM_OBJECT(ptr);
1024 if (!IS_OBJECT(obj))
1025 /* is an array ref */
1026 obj = JAM_ARRAY(ptr);
1027 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj);
1028 JEM_NULL_POINTER_CHECK(obj);
1029 objectUnlock(obj);
1030 return 0;
1033 static int opc_getstatic_quick(struct intrp_ctx *ctx)
1035 struct jem_state *jem = &ctx->jem;
1036 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1037 RESOLVED_FIELD(jem)->static_value);
1040 static int opc_getstatic2_quick(struct intrp_ctx *ctx)
1042 struct jem_state *jem = &ctx->jem;
1043 union ull_2ui v;
1045 v.ll = RESOLVED_FIELD(jem)->static_value;
1047 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
1050 static int opc_getstatic_quick_jem0(struct intrp_ctx *ctx)
1052 struct jem_state *jem = &ctx->jem;
1053 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1055 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value);
1056 if (value) {
1057 Object *ref = (Object *)value;
1058 if (!JAM_ON_STACK || IS_JAM_OBJECT(ref))
1059 //jamvm objref
1060 value = (uintptr_t)INST_DATA(ref);
1062 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value);
1063 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1066 static int opc_getstatic_quick_jem1(struct intrp_ctx *ctx)
1068 struct jem_state *jem = &ctx->jem;
1069 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1070 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value);
1071 if (value) {
1072 Object *ref = (Object*)value;
1073 if (!JAM_ON_STACK || IS_JAM_ARRAY(ref))
1074 //jamvm arrayref
1075 value = (uintptr_t)ARRAY_DATA(ref);
1077 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value);
1078 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1081 static int opc_getstatic(struct intrp_ctx *ctx)
1083 int idx;
1084 FieldBlock *fb;
1085 ExecEnv *ee = ctx->ee;
1086 struct jem_state *jem = &ctx->jem;
1088 idx = (int)(jem->jecr & 0xffff);
1089 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx,CLASS_CB(ctx->mb->class)->name);
1091 ctx->frame->last_pc = (CodePntr)jem->jpc;
1092 fb = resolveField(ctx->mb->class, idx);
1094 if (exceptionOccured0(ee))
1095 return jem_throwException(ctx);
1097 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb, *fb->type);
1098 jem->operand.pntr = fb;
1099 switch (*fb->type) {
1100 case 'J':
1101 case 'D':
1102 return opc_getstatic2_quick(ctx);
1104 * see opc_getfield
1106 case 'L':
1107 return opc_getstatic_quick_jem0(ctx);
1108 case '[':
1109 return opc_getstatic_quick_jem1(ctx);
1110 default:
1111 return opc_getstatic_quick(ctx);
1115 static int opc_putstatic2_quick(struct intrp_ctx *ctx)
1117 struct jem_state *jem = &ctx->jem;
1118 return ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1119 &RESOLVED_FIELD(jem)->static_value);
1122 static int opc_putstatic_quick(struct intrp_ctx *ctx)
1124 struct jem_state *jem = &ctx->jem;
1125 return ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1126 RESOLVED_FIELD(jem)->static_value);
1129 static int opc_putstatic_quick_jem0(struct intrp_ctx *ctx)
1131 uintptr_t value;
1132 struct jem_state *jem = &ctx->jem;
1133 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1135 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value);
1136 if (value && (!JAM_ON_STACK || !IS_JAM_OBJECT(value)))
1137 value = (uintptr_t)JAM_OBJECT((uintptr_t *)value);
1138 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value);
1139 RESOLVED_FIELD(jem)->static_value = value;
1140 return 0;
1143 static int opc_putstatic_quick_jem1(struct intrp_ctx *ctx)
1145 uintptr_t *value;
1146 struct jem_state *jem = &ctx->jem;
1147 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1149 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value);
1150 if (value && (!JAM_ON_STACK || !IS_JAM_ARRAY(value)))
1151 value = (uintptr_t*)JAM_ARRAY(value);
1152 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value);
1153 RESOLVED_FIELD(jem)->static_value = (uintptr_t)value;
1154 return 0;
1157 static int opc_putstatic(struct intrp_ctx *ctx)
1159 int idx;
1160 FieldBlock *fb;
1161 ExecEnv *ee = ctx->ee;
1162 struct jem_state *jem = &ctx->jem;
1164 idx = (int)(jem->jecr & 0xffff);
1166 ctx->frame->last_pc = (CodePntr)jem->jpc;
1167 fb = resolveField(ctx->mb->class, idx);
1169 if (exceptionOccured0(ee))
1170 return jem_throwException(ctx);
1172 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb, *fb->type);
1173 jem->operand.pntr = fb;
1174 switch (*fb->type) {
1175 case 'J':
1176 case 'D':
1177 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1178 return opc_putstatic2_quick(ctx);
1179 case 'L':
1180 return opc_putstatic_quick_jem0(ctx);
1181 case '[':
1182 return opc_putstatic_quick_jem1(ctx);
1183 default:
1184 return opc_putstatic_quick(ctx);
1188 static int opc_checkcast_quick(struct intrp_ctx *ctx)
1190 struct jem_state *jem = &ctx->jem;
1191 ConstantPool *cp = ctx->cp;
1192 Class *class = RESOLVED_CLASS(jem);
1193 Object *obj;
1194 uintptr_t *ptr;
1196 ostack_read_u32(ctx->frame->ostack, ctx->ostack, 0, &ptr);
1197 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr, CLASS_CB(class)->name);
1198 if (ptr != NULL) {
1199 #warning Does not look right!
1200 if (!JAM_ON_STACK || !IS_JAM_OBJECT(ptr) || !IS_JAM_ARRAY(ptr)) {
1201 obj = JAM_OBJECT(ptr);
1202 if (!IS_OBJECT(obj)) {
1203 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1204 //should be array ref
1205 obj = JAM_ARRAY(ptr);
1207 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj);
1208 } else {
1209 obj = (Object*)ptr;
1211 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %p (%s) for obj %p (%s)\n",
1212 class, CLASS_CB(class)->name, obj->class, CLASS_CB(obj->class)->name);
1213 if (!isInstanceOf(class, obj->class))
1214 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
1217 return 0;
1220 static int opc_checkcast(struct intrp_ctx *ctx)
1222 struct jem_state *jem = &ctx->jem;
1223 Operand *operand = &jem->operand;
1224 int idx = jem->jecr & 0xffff;
1225 int opcode = (jem->jecr >> 16) & 0xff;
1226 Class *class;
1227 ExecEnv *ee = ctx->ee;
1229 operand->uui.u1 = idx;
1230 operand->uui.u2 = opcode;
1232 jam_dprintf("[OPC_CHECKCAST] index: 0x%x\n", idx);
1234 ctx->frame->last_pc = (CodePntr)jem->jpc;
1235 //resolve the cast class
1236 class = resolveClass(ctx->mb->class, idx, FALSE);
1238 if (exceptionOccured0(ee))
1239 return jem_throwException(ctx);
1241 return opc_checkcast_quick(ctx);
1244 static int opc_invokeinterface_quick(struct intrp_ctx *ctx)
1246 int mtbl_idx;
1247 ClassBlock *cb;
1248 Object *objref;
1249 int cache = ctx->jem.operand.uu.u2;
1251 ctx->new_mb = (MethodBlock *)CP_INFO(ctx->cp, ctx->jem.operand.uu.u1);
1252 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
1253 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
1255 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1256 ctx->new_mb, ctx->new_mb->name, ctx->new_mb->args_count, ctx->arg1);
1258 objref = (Object *)*ctx->arg1;
1259 #warning Does not look right!
1260 if (!JAM_ON_STACK || !IS_JAM_OBJECT(objref) || !IS_JAM_ARRAY(objref)) {
1261 objref = JAM_OBJECT((uintptr_t *)objref);
1262 if (!IS_OBJECT(objref))
1263 objref = JAM_ARRAY((uintptr_t *)*ctx->arg1);
1264 } else {
1265 //turn type in the stack to JEM type ref
1266 *ctx->arg1 = (uintptr_t)INST_DATA(objref);
1268 JEM_NULL_POINTER_CHECK(objref);
1270 cb = CLASS_CB(objref->class);
1272 if ((cache >= cb->imethod_table_size) ||
1273 (ctx->new_mb->class != cb->imethod_table[cache].interface)) {
1274 for (cache = 0; (cache < cb->imethod_table_size) &&
1275 (ctx->new_mb->class != cb->imethod_table[cache].interface); cache++);
1277 if (cache == cb->imethod_table_size)
1278 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1279 "unimplemented interface");
1282 mtbl_idx = cb->imethod_table[cache].offsets[ctx->new_mb->method_table_index];
1283 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx);
1284 ctx->new_mb = cb->method_table[mtbl_idx];
1285 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx);
1286 return invokeMethod(ctx);
1289 static int opc_invokeinterface(struct intrp_ctx *ctx)
1291 struct jem_state *jem = &ctx->jem;
1292 Operand *operand = &jem->operand;
1293 ExecEnv *ee = ctx->ee;
1295 int idx = operand->uu.u1 = jem->jecr & 0xffff;
1296 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1297 * For JEM, two index bytes has been processed before trap,
1298 * so offset jpc 4 operands for next opcode
1299 *FIXME: ? not know why JEM does not handle this */
1300 ctx->frame->last_pc = (CodePntr)(jem->jpc += 2);
1301 ctx-> new_mb = resolveInterfaceMethod(ctx->mb->class, idx);
1303 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx);
1304 if (exceptionOccured0(ee))
1305 return jem_throwException(ctx);
1307 if (CLASS_CB(ctx->new_mb->class)->access_flags & ACC_INTERFACE) {
1308 operand->uu.u2 = 0;
1309 return opc_invokeinterface_quick(ctx);
1310 } else {
1311 operand->uu.u1 = ctx->new_mb->args_count;
1312 operand->uu.u2 = ctx->new_mb->method_table_index;
1313 return opc_invokevirtual_quick(ctx);
1317 static int opc_instanceof_quick(struct intrp_ctx *ctx)
1319 struct jem_state *jem = &ctx->jem;
1320 ConstantPool *cp = ctx->cp;
1321 Class *class = RESOLVED_CLASS(jem);
1322 Object *obj;
1323 uintptr_t *ptr;
1325 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1326 if (ptr != NULL) {
1327 obj = JAM_OBJECT(ptr);
1328 if (!IS_OBJECT(obj)) {
1329 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1330 //should be array ref
1331 obj = JAM_ARRAY(ptr);
1334 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n",
1335 CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
1337 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1338 ptr ? (uint32_t)isInstanceOf(class, obj->class) : 0);
1339 return 0;
1342 static int opc_instanceof(struct intrp_ctx *ctx)
1344 struct jem_state *jem = &ctx->jem;
1345 Operand *operand = &jem->operand;
1346 int idx = jem->jecr & 0xffff;
1347 int opcode = (jem->jecr >> 16) & 0xff;
1348 Class *class;
1349 ExecEnv *ee = ctx->ee;
1351 operand->uui.u1 = idx;
1352 operand->uui.u2 = opcode;
1354 jam_dprintf("[OPC_INSTANCEOF] index: 0x%x\n", idx);
1356 ctx->frame->last_pc = (CodePntr)jem->jpc;
1357 //resolve the cast class
1358 class = resolveClass(ctx->mb->class, idx, FALSE);
1360 if (exceptionOccured0(ee))
1361 return jem_throwException(ctx);
1363 return opc_instanceof_quick(ctx);
1366 static int opc_aastore(struct intrp_ctx *ctx)
1368 Object *obj;
1369 uintptr_t *aobj;
1370 int idx ;
1371 Object *array;
1373 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
1374 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, idx);
1375 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, array);
1377 jam_dprintf("[OPC_AASTORE] obj %p, index %d, array %p\n", aobj, idx, array);
1379 /* aobj does point to an object, but we do not know if that's an array or
1380 * not, and we need to know that for the arrayStoreCheck() check below */
1381 #warning Does not look right!
1382 if (aobj && (!JAM_ON_STACK || !IS_JAM_OBJECT(aobj) || !IS_JAM_ARRAY(aobj))) {
1383 if (!IS_OBJECT(JAM_OBJECT(aobj))) {
1384 //in case of storing an array to another array
1385 obj = JAM_ARRAY(aobj);
1386 } else {
1387 obj = JAM_OBJECT(aobj);
1389 } else
1390 obj = (Object *)aobj;
1391 array = JAM_ARRAY((uintptr_t *)array);
1393 jam_dprintf("[OPC_AASTORE] store obj ref %p of %p to array %p[%d/%d] of %p\n",
1394 obj, obj ? obj->class : obj, array, idx, array->instance[0], array->class);
1395 JEM_NULL_POINTER_CHECK(array);
1397 if (idx >= ARRAY_LEN(array)) {
1398 char buff[MAX_INT_DIGITS];
1399 snprintf(buff, MAX_INT_DIGITS, "%d", idx);
1400 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff);
1403 if (obj != NULL && !arrayStoreCheck(array->class, obj->class))
1404 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
1406 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1407 // the array to get the non jamvm refs to use, which then causes segfault.
1408 #if JAM_ON_STACK
1409 ((Object**)ARRAY_DATA(array))[idx] = obj;
1410 #else
1411 ((uintptr_t**)ARRAY_DATA(array))[idx] = aobj;
1412 #endif
1413 return 0;
1416 static int do_javaExceptions(struct intrp_ctx *ctx)
1418 union jecr jecr_u;
1419 struct jem_state *jem = &ctx->jem;
1421 /* deliberate segfault */
1422 /* *(int *)0 = 0; */
1424 jecr_u.i = jem->jecr;
1425 /* This should not happen, because we don't use the "Java Handle" (H)
1426 * bit in the Status Register and we set JBCR to 0x80000000 - still
1427 * it does happen, but seems to be harmless so far. Just ignore. */
1428 if (jecr_u.s.opcode == OPC_AASTORE)
1429 return opc_aastore(ctx);
1431 return 1;
1434 static int opc_afireturn(struct intrp_ctx *ctx)
1436 uint32_t val;
1437 int ret;
1439 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1441 jam_dprintf("[OPC_AFIRETURN] return 0x%08x @ %p, this %p\n",
1442 val, ctx->lvars_jem, ctx->this);
1444 ret = opc_return(ctx);
1445 if (!ret)
1446 ret = ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1447 else
1448 /* Function returning a value must have local variables */
1449 *ctx->lvars_jem = val;
1451 return ret;
1454 static int opc_ldreturn(struct intrp_ctx *ctx)
1456 int ret;
1457 union ull_2ui v;
1459 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
1460 jam_dprintf("[OPC_LDRETURN] return 0x%llx\n", v.ll);
1462 ret = opc_return(ctx);
1464 if (!ret)
1465 ret = ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack,
1466 ctx->ostack, v.i);
1467 else
1468 /* Function returning a value must have local variables */
1469 *(uint64_t*)ctx->lvars_jem = v.ll;
1471 return ret;
1474 static int opc_fcmpg(struct intrp_ctx *ctx)
1476 float v1, v2;
1477 int res;
1479 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1480 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1482 if (v1 == v2)
1483 res = 0;
1484 else if (v1 < v2)
1485 res = -1;
1486 else if (v1 > v2)
1487 res = 1;
1488 else
1489 res = 1; /* isNaN */
1491 jam_dprintf("[OPC_FCMPG] result %d\n", res);
1493 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1496 static int opc_fcmpl(struct intrp_ctx *ctx)
1498 float v1, v2;
1499 int res;
1501 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1502 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1504 if (v1 == v2)
1505 res = 0;
1506 else if (v1 < v2)
1507 res = -1;
1508 else if (v1 > v2)
1509 res = 1;
1510 else
1511 res = -1;
1513 jam_dprintf("[OPC_FCMPL] result %d\n", res);
1514 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1517 static int opc_lcmp(struct intrp_ctx *ctx)
1519 union ull_2ui v1, v2;
1520 int res;
1522 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2.i);
1523 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1525 if (v1.ll == v2.ll)
1526 res = 0;
1527 else if (v1.ll - v2.ll > 0LL)
1528 res = 1;
1529 else
1530 res = -1;
1532 jam_dprintf("[%s] (0x%llx,0x%llx) result %d\n", __func__, v1.ll, v2.ll, res);
1533 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1536 static int opc_i2f(struct intrp_ctx *ctx)
1538 int i;
1539 float f;
1541 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, i);
1542 f = (float)i;
1544 jam_dprintf("[OPC_I2F] convert to %f\n", f);
1546 return ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, f);
1549 static int opc_i2d(struct intrp_ctx *ctx)
1551 return JEM_TRAP_HANDLER_FINISH;
1554 static int opc_ldiv(struct intrp_ctx *ctx)
1556 union ull_2ui v1, v2, res;
1558 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2.i);
1559 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1561 res.ll = v1.ll / v2.ll;
1563 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__, v1.ll, v2.ll, res.ll);
1565 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1568 static int opc_lrem(struct intrp_ctx *ctx)
1570 union ull_2ui v1, v2, res;
1572 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2.i);
1573 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1575 res.ll = v1.ll % v2.ll;
1577 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__, v1.ll, v2.ll, res.ll);
1579 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1582 static int opc_lmul(struct intrp_ctx *ctx)
1584 union ull_2ui v1, v2, res;
1586 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2.i);
1587 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1589 res.ll = v1.ll * v2.ll;
1591 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__, v1.ll, v2.ll, res.ll);
1593 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1596 static int opc_lushr(struct intrp_ctx *ctx)
1598 union ull_2ui res, v1;
1599 unsigned long v2;
1601 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1602 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1604 res.ll = v1.ll >> (v2 & 0x3f);
1606 jam_dprintf("[%s] (0x%llx,%u) result 0x%llx\n", __func__, v1.ll, v2, res.ll);
1608 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1611 static int opc_lshr(struct intrp_ctx *ctx)
1613 union ull_2ui v1, res;
1614 unsigned long v2;
1616 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1617 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1.i);
1619 res.ll = (long long)v1.ll / (1LL << (v2 & 0x3f));
1621 jam_dprintf("[%s] (0x%llx,%u) result 0x%llx\n", __func__, v1.ll, v2, res.ll);
1623 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1626 static int opc_lneg(struct intrp_ctx *ctx)
1628 union ull_2ui v, res;
1630 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v.i);
1632 res.ll = -v.ll;
1634 jam_dprintf("[%s] (0x%llx) result 0x%llx\n", __func__, v.ll, res.ll);
1636 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res.i);
1639 static int opc_fmul(struct intrp_ctx *ctx)
1641 float v1, v2;
1642 float ret;
1644 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1645 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1647 ret = v1 * v2;
1649 jam_dprintf("[OPC_FMUL] result %f\n", ret);
1651 return ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1654 static int opc_fadd(struct intrp_ctx *ctx)
1656 float v1, v2;
1657 float ret;
1659 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1660 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1662 ret = v1 + v2;
1664 jam_dprintf("[OPC_FADD] result %f\n", ret);
1666 return ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1669 static int opc_fsub(struct intrp_ctx *ctx)
1671 float v1, v2;
1672 float ret;
1674 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1675 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1677 ret = v1 - v2;
1679 jam_dprintf("[OPC_FSUB] result %f\n", ret);
1681 return ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1684 static int opc_f2i(struct intrp_ctx *ctx)
1686 int res;
1687 float value;
1689 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1691 jam_dprintf("[OPC_F2I] float value %f\n", value);
1692 if (value >= (float)INT_MAX)
1693 res = INT_MAX;
1694 else if (value <= (float)INT_MIN)
1695 res = INT_MIN;
1696 else if (value != value)
1697 res = 0;
1698 else
1699 res = (int)value;
1701 jam_dprintf("[OPC_F2I] int value %d\n", res);
1703 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1706 static int opc_iinc(struct intrp_ctx *ctx)
1708 union jecr jecr_u;
1709 jecr_u.i = ctx->jem.jecr;
1710 int index = (int)jecr_u.s.op1;
1711 int con = (int)jecr_u.s.op2;
1712 uintptr_t *ptr = ctx->lvars_jem;
1714 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1715 con, ptr[-index], index, ctx->mb->max_locals);
1716 ptr[-index] = ptr[-index] + con;
1718 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr[-index]);
1719 return 0;
1722 static int opc_tableswitch(struct intrp_ctx *ctx)
1724 /* On entry JPC points to "default" */
1725 int32_t dflt, high, low, *dflt_p;
1726 int32_t idx;
1727 uint32_t target;
1728 uint8_t *tswitch;
1730 tswitch = (uint8_t *)(ctx->jem.jpc - 3);
1731 dflt_p = (int32_t *)(ctx->jem.jpc & ~3);
1733 dflt = __be32_to_cpu(*dflt_p);
1734 low = __be32_to_cpu(*(dflt_p + 1));
1735 high = __be32_to_cpu(*(dflt_p + 2));
1737 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, idx);
1739 if (idx < low || idx > high)
1740 target = dflt;
1741 else
1742 target = __be32_to_cpu(*(dflt_p + 3 + idx - low));
1744 #ifdef JEM_DEBUG
1745 for (i = 0; i <= high - low; i++) {
1746 int32_t *addr = dflt_p + 3 + i;
1748 if (!(i & 15))
1749 jam_dprintf("%p:", addr);
1750 jam_dprintf(" 0x%x", *addr);
1751 if ((i & 15) == 15 || i == high - low)
1752 jam_dprintf("\n", addr);
1754 #endif
1756 jam_dprintf("[%s] trap @%p, jpc 0x%x, default 0x%x @ %p, low %d, high %d, idx %d, target 0x%x\n",
1757 __func__, tswitch, ctx->jem.jpc, dflt, dflt_p, low, high, idx, target);
1759 ctx->jem.jpc = (uint32_t)(tswitch + target);
1761 return 0;
1764 static int opc_athrow(struct intrp_ctx *ctx)
1766 Object *obj;
1767 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
1768 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
1769 ExecEnv *ee = ctx->ee;
1771 JEM_NULL_POINTER_CHECK(obj);
1773 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj))
1774 obj = JAM_OBJECT((uintptr_t *)obj);
1776 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj->class)->name);
1777 ee->exception = obj;
1778 return jem_throwException(ctx);
1781 static int do_stackOverflow(struct intrp_ctx *ctx)
1783 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1784 return 0;
1787 static int do_stackUnderflow(struct intrp_ctx *ctx)
1789 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1790 return 1;
1793 static int do_stackOverflow1(struct intrp_ctx *ctx)
1795 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1796 return 1;
1799 static int do_stackUnderflow1(struct intrp_ctx *ctx)
1801 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1802 return 1;
1805 static handler_fn *trap_handler_f[256] = {
1806 [OPC_INVOKEINTERFACE] = opc_invokeinterface,
1807 [OPC_INVOKESPECIAL] = opc_invokespecial,
1808 [OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick,
1809 [OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick,
1810 [OPC_INVOKEVIRTUAL] = opc_invokevirtual,
1811 [OPC_INVOKEVIRTUAL_QUICK] = opc_invokevirtual_quick,
1812 [OPC_INVOKESTATIC] = opc_invokestatic,
1813 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1814 [OPC_NEW] = opc_new,
1815 [0xDD] = opc_new, /* JEM: NEW_QUICK */
1816 [OPC_RETURN] = opc_return,
1817 [OPC_ARETURN] = opc_afireturn,
1818 [OPC_IRETURN] = opc_afireturn,
1819 [OPC_FRETURN] = opc_afireturn,
1820 [OPC_PUTFIELD] = opc_putfield,
1821 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1822 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1823 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1824 // [OPC_LDC_QUICK] = opc_ldc_quick,
1825 [OPC_LDC_W] = opc_ldc_w,
1826 [OPC_LDC] = opc_ldc,
1827 [OPC_LDC2_W] = opc_ldc2_w,
1828 [OPC_MONITORENTER] = opc_monitorenter,
1829 [OPC_MONITOREXIT] = opc_monitorexit,
1830 [OPC_GETSTATIC] = opc_getstatic,
1831 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1832 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1833 [OPC_PUTSTATIC] = opc_putstatic,
1834 [OPC_PUTSTATIC_QUICK] = opc_putstatic_quick,
1835 [OPC_PUTSTATIC2_QUICK] = opc_putstatic2_quick,
1836 [OPC_ANEWARRAY] = opc_anewarray,
1837 [OPC_ANEWARRAY_QUICK] = opc_anewarray_quick,
1838 [OPC_MULTIANEWARRAY] = opc_multianewarray,
1839 [OPC_NEWARRAY] = opc_newarray,
1840 [OPC_CHECKCAST] = opc_checkcast,
1841 [OPC_CHECKCAST_QUICK] = opc_checkcast_quick,
1842 [OPC_GETFIELD] = opc_getfield,
1843 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1844 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1845 [OPC_LSHR] = opc_lshr,
1846 [OPC_LUSHR] = opc_lushr,
1847 [OPC_LCMP] = opc_lcmp,
1848 [OPC_LNEG] = opc_lneg,
1849 [OPC_LDIV] = opc_ldiv,
1850 [OPC_LREM] = opc_lrem,
1851 [OPC_LMUL] = opc_lmul,
1852 [OPC_FCMPL] = opc_fcmpl,
1853 [OPC_FCMPG] = opc_fcmpg,
1854 [OPC_I2F] = opc_i2f,
1855 [OPC_I2D] = opc_i2d,
1856 [OPC_FMUL] = opc_fmul,
1857 [OPC_FADD] = opc_fadd,
1858 [OPC_FSUB] = opc_fsub,
1859 [OPC_F2I] = opc_f2i,
1860 [OPC_IINC] = opc_iinc,
1861 [OPC_INSTANCEOF] = opc_instanceof,
1862 [OPC_ATHROW] = opc_athrow,
1863 [OPC_LRETURN] = opc_ldreturn,
1864 [OPC_TABLESWITCH] = opc_tableswitch,
1867 static handler_fn *exception_handler_f[] = {
1868 [0] = do_javaExceptions,
1869 [1] = do_stackOverflow,
1870 [2] = do_stackUnderflow,
1871 [3] = do_stackOverflow1,
1872 [4] = do_stackUnderflow1,
1875 struct jem_profile {
1876 unsigned long time;
1877 unsigned int n;
1880 #ifdef JEM_PROFILE
1881 static struct jem_profile prof[256];
1882 #endif
1884 /******************************/
1885 uintptr_t *executeJava(void)
1888 * load trap entries to JEM trap table set when initializing JamVM
1890 int i;
1891 uint32_t jep;
1892 int done = 0;
1893 #ifdef JEM_PROFILE
1894 static struct timeval tv1, tv2;
1895 #endif
1896 ExecEnv *ee = getExecEnv();
1898 /* Initialize interpreter's static environment */
1899 struct intrp_ctx ctx;
1900 struct jem_state *jem = &ctx.jem;
1902 ctx.ee = ee;
1903 ctx.frame = ee->last_frame;
1904 ctx.mb = ctx.frame->mb;
1906 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1907 * overflow we free a half of the stack (4 elements) to avoid an immediate
1908 * next overflow. When entering a trap, the Operand Stack is saved in a
1909 * temporary array in the reverse order:
1910 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1911 * jos[0] = r7 (?)
1912 * ...
1913 * jos[7 - N] = rN (ToS - N)
1914 * ...
1915 * jos[7] = r0 (ToS)
1916 * UPDATE (27.06.2008)
1917 * I think, actually, the manual is right in some way... If you access
1918 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1919 * with an ldm, you get this:
1920 * jos[0] = r7 (?)
1921 * ...
1922 * jos[7 - N] = rN (ToS)
1923 * ...
1924 * jos[7] = r0 (ToS - N)
1925 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1926 * set saved JOSP to 4.
1928 unsigned long jos[8];
1930 ctx.ostack = ctx.frame->ostack;
1931 ctx.cp = &(CLASS_CB(ctx.mb->class)->constant_pool);
1932 /* End enterpreter's static environment */
1934 //fetch the original pc before prepare direct mb
1935 //TODO:
1936 /* I think, mb->code is indeed a copy of the original code[] array from the
1937 * class object. See class.c::defineClass():390 */
1939 if (ctx.frame->lvars_jem) {
1940 ctx.lvars_jem = ctx.frame->lvars_jem - 1;
1942 GET_THIS(&ctx);
1943 } else {
1944 jam_printf("BUG: lvars_jem == NULL!!!");
1945 exitVM(1);
1948 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1949 ctx.ostack, ctx.mb->max_locals, ctx.lvars_jem);
1950 jam_dprintf("[executeJava] execute method %s on class %s\n",
1951 ctx.mb->name, CLASS_CB(ctx.mb->class)->name);
1953 #if 0
1954 /* Don't think we need it, at least, not in the direct.c form. There the code
1955 * is converted into an internal representation, which is useless for JEM */
1956 PREPARE_MB(ctx.mb);//see direct.c (prepare)
1957 #endif
1959 jem->jpc = (unsigned long)ctx.mb->code & ~3;
1960 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1961 *(char*)jem->jpc, *((char*)jem->jpc + 1));
1963 do {
1964 #ifdef JEM_PROFILE
1965 /* This is not thread-safe. Have to use TLS. */
1966 static
1967 #endif
1968 int opcode;
1970 #ifdef JEM_DEBUG
1971 jam_dprintf("About to enter JEM at 0x%08x, this = %p, class = %p. Code:",
1972 jem->jpc, ctx.this, ctx.this ? ctx.this->class : NULL);
1973 for (i = 0; i < 32 && jem->jpc + i < (unsigned long)(ctx.mb->code + ctx.mb->code_size); i++) {
1974 if (!(i & 0xf))
1975 jam_dprintf("\n0x%04x:", i);
1976 jam_dprintf(" 0x%02x", ((char*)jem->jpc)[i]);
1979 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx.mb->max_locals);
1980 for (i = 0; i < min(8, ctx.mb->max_locals); i++)
1981 jam_dprintf("LVAR_%d: 0x%08x\n", i, *(ctx.lvars_jem - i), ctx.lvars_jem - i);
1982 #endif
1984 /* On entry we need last Java Operand Stack depth, set it not deeper
1985 * than half hardware stack */
1986 jem->josp = min(5, ostack_depth(ctx.frame->ostack, ctx.ostack));
1987 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem->josp,
1988 ctx.frame->ostack, ctx.ostack);
1989 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1990 for (i = 0; i < jem->josp; i++)
1991 ostack_pop_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
1992 jos[7 - jem->josp + 1 + i]);
1994 #ifdef JEM_PROFILE
1995 if (tv1.tv_sec) {
1996 gettimeofday(&tv2, NULL);
1997 prof[opcode].time += (tv2.tv_sec - tv1.tv_sec) * 1000000 +
1998 tv2.tv_usec - tv1.tv_usec;
1999 prof[opcode].n++;
2001 #endif
2003 __asm__ __volatile__(
2004 ".globl debug_jem_enter\n"
2005 "debug_jem_enter:\n"
2006 " pushm r0-r7,r10-r11\n"
2007 " mov r8, %[cp]\n"
2008 " mov r9, %[lv0]\n"
2009 " mov lr, %[jpc]\n"
2010 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
2011 " mov r11, %[ostack]\n"
2012 " pushm r11\n" /* Need ostack below */
2013 " ldm r11, r0-r7\n" /* Restore Java Operands */
2014 " cp.w r12, 0\n" /* Test josp == 0 */
2015 " breq 4f\n"
2016 "5: incjosp 1\n" /* ... for loop counter, */
2017 " sub r12, 1\n" /* because it can be */
2018 " brne 5b\n" /* one of r0-r7 */
2019 "4: popjc\n" /* Restore Local Variables */
2020 " sub r10, pc, . - trap\n" /* These 3 instructions */
2021 " retj\n" /* have to stay */
2022 "trap: pushjc\n" /* together */
2023 " mfsr r11, 0x58\n" /* JOSP */
2024 " lsl r11, 28\n" /* Clear r11[31:3] using */
2025 " lsr r11, 28\n" /* one register */
2026 " mov r8, r11\n"
2027 " breq 2f\n"
2028 "3: incjosp -1\n"
2029 " sub r11, 1\n"
2030 " brne 3b\n"
2031 "2: popm r11\n" /* ostack */
2032 " stm r11, r0-r7\n" /* Save Java Operands */
2033 " popm r0-r7,r10-r11\n"
2034 " mov %[tpc], r12\n"
2035 " mov %[jpc], lr\n" /* Resume address */
2036 " mfsr %[jecr], 0x54\n" /* JECR */
2037 " mov %[josp], r8\n" /* JOSP */
2038 " .globl debug_jem_exit\n"
2039 "debug_jem_exit:\n"
2040 : [jecr] "=r" (jem->jecr), [tpc] "=r" (jem->trap_pc),
2041 [josp] "+r" (jem->josp), [jpc] "+r" (jem->jpc)
2042 : [cp] "r" (ctx.cp->info), [lv0] "r" (ctx.lvars_jem),
2043 [ostack] "r" (jos)
2044 : "r8", "r9", "lr", "r12", "sp", "memory", "cc"
2047 * trap_pc now holds trap pc, describing which trap has been entered,
2048 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
2049 * arguments at bits 7..0 and 15..8,
2050 * josp holds JOSP (JOSP & 0xf),
2051 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
2052 * jpc points at the trapping opcode, in case of exceptions and stack
2053 * over- and underflows, and at the next opcode, in case of a trap
2056 #ifdef JEM_PROFILE
2057 gettimeofday(&tv1, NULL);
2058 #endif
2060 for (i = 0; i < jem->josp; i++)
2061 ostack_push_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
2062 jos[7 - i]);
2064 opcode = (jem->jecr >> 16) & 0xff;
2066 jep = jem->trap_pc & 0xfff;
2068 trap_debug(&ctx);
2069 if (jep < 0x280)
2070 done = exception_handler_f[jep >> 7](&ctx);
2071 else if (trap_handler_f[opcode])
2072 done = trap_handler_f[opcode](&ctx);
2073 else {
2074 /* Unimplemented */
2075 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode);
2076 exitVM(1);
2079 #ifdef JEM_DEBUG
2080 usleep(100);
2081 #endif
2082 } while (done != JEM_TRAP_HANDLER_FINISH);
2084 return ctx.ostack;
2086 // DISPATCH_FIRST;
2088 jam_dprintf("Unknown Java Opcodes\n");
2089 exitVM(1);
2092 #ifndef executeJava
2093 void initialiseInterpreter(InitArgs *args) {
2094 initialiseDirect(args);
2096 #endif
2098 void dump_profile(void)
2100 #ifdef JEM_PROFILE
2101 int i;
2103 for (i = 0; i < 256; i++)
2104 if (prof[i].n)
2105 jam_printf("0x%x:\t%u times,\t%lu usec\n", i, prof[i].n, prof[i].time);
2106 #endif