Flush instruction caches only after inserting code.
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blob0ebbee45ace6e287e0aed25dc1b3ae34c807facc
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/cachectl.h>
46 #include "arch/avr32_jem.h"
47 #include "interp_jem.h"
49 union jecr {
50 struct {
51 uint8_t dummy;
52 uint8_t opcode;
53 uint8_t op1;
54 uint8_t op2;
55 } s;
56 uint32_t i;
59 /**
60 * Interpreter execution context
62 struct intrp_ctx {
63 /* JEM state */
64 struct jem_state jem;
66 /* the interpreter execution context */
67 Frame *frame;
68 MethodBlock *mb;
69 MethodBlock *new_mb;
70 ConstantPool *cp;
71 Object *this;
72 uintptr_t *lvars_jem;
73 uintptr_t *ostack;
74 uintptr_t *arg1;
75 ExecEnv *ee;
78 #define GET_THIS(ctx) do { \
79 if (!((ctx)->mb->access_flags & ACC_STATIC) && (ctx)->mb->max_locals && \
80 *(ctx)->lvars_jem) { \
81 uintptr_t *__p = (uintptr_t *)*(ctx)->lvars_jem; \
82 (ctx)->this = JAM_OBJECT(__p); \
83 } else \
84 (ctx)->this = NULL; \
85 jam_dprintf("[%s] %smethod with %d vars, assigning %p\n", __func__, \
86 (ctx)->mb->access_flags & ACC_STATIC ? "static " : "", \
87 (ctx)->mb->max_locals, (ctx)->this); \
88 } while (0)
90 typedef int handler_fn(struct intrp_ctx *ctx);
92 static void jem_opcode_rewrite(uint32_t new_opcode, char *pc, int argc, ...)
94 int i;
95 va_list vargs;
97 va_start(vargs, argc);
98 pc[0] = new_opcode;
99 for (i = 1; i <= argc; i++)
100 pc[i] = (char)va_arg(vargs, int);
101 va_end(vargs);
102 syscall(__NR_cacheflush, CACHE_IFLUSH, (int)pc & ~31, 32);
105 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
107 //check if it is an valid object ref (see alloc.c)
108 #define OBJECT_GRAIN 8
109 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
111 #define JEM_THROW_EXCEPTION(excep_name, message) \
112 ({ \
113 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
114 signalException(excep_name, message); \
115 jem_throwException(ctx); \
118 #define JEM_NULL_POINTER_CHECK(ref) \
119 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
121 /*********************************************
122 * JEM Trap Handlers **
123 * *******************************************/
124 static int trap_debug(struct intrp_ctx *ctx)
126 #ifdef JEM_DEBUG
127 struct jem_state *jem = &ctx->jem;
128 union jecr jecr_u;
129 int i;
130 static unsigned long count;
132 jecr_u.i = jem->jecr;
134 jam_printf("[%lu] (%u): Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
135 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
136 count++, pthread_self(), jem->trap_pc, ctx->ostack, jecr_u.s.opcode,
137 jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
139 for (i = 0; i < jem->josp; i++) {
140 uint32_t v;
141 if (ostack_read_u32(ctx->frame->ostack, ctx->ostack, i, &v) >= 0)
142 jam_printf("\tToS-%d: 0x%x\n", i, v);
144 #endif
145 return 1;
149 static int jem_throwException(struct intrp_ctx *ctx)
151 struct jem_state *jem = &ctx->jem;
152 ExecEnv *ee = ctx->ee;
153 Object *excep = ee->exception;
154 ee->exception = NULL;
156 jem->jpc = (unsigned long)findCatchBlock(excep->class);
157 jam_dprintf("Found exception handler at 0x%08x\n", jem->jpc);
159 /* If we didn't find a handler, restore exception and
160 return to previous invocation */
162 if (!jem->jpc) {
163 ee->exception = excep;
164 /* Original code had a "return NULL" here, which means, end of
165 * executeJava */
166 return JEM_TRAP_HANDLER_FINISH;
169 /* If we're handling a stack overflow, reduce the stack
170 back past the red zone to enable handling of further
171 overflows */
173 if (ee->overflow) {
174 ee->overflow = FALSE;
175 ee->stack_end -= STACK_RED_ZONE_SIZE;
178 /* Setup intepreter to run the found catch block */
180 ctx->frame = ee->last_frame;
181 ctx->mb = ctx->frame->mb;
182 ctx->ostack = ctx->frame->ostack;
183 ctx->lvars_jem = ctx->frame->lvars_jem - 1;
185 GET_THIS(ctx);
187 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
189 /* FIXME: don't know if this is correct, depends how we implement
190 * exceptions */
191 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uint32_t)excep);
193 /* Dispatch to the first bytecode */
194 return 0;
197 static int opc_return(struct intrp_ctx *ctx)
199 ExecEnv *ee = ctx->ee;
201 /* Set interpreter state to previous frame */
202 if (ctx->frame->prev->mb == NULL) {
203 /* The previous frame is a dummy frame - this indicates
204 * top of this Java invocation. */
205 return JEM_TRAP_HANDLER_FINISH;
208 ctx->frame = ctx->frame->prev;
210 jam_dprintf("[%s] return to frame %p mb %p\n", __func__, ctx->frame, ctx->frame->mb);
212 if (ctx->mb->access_flags & ACC_SYNCHRONIZED) {
213 Object *sync_ob = ctx->mb->access_flags & ACC_STATIC ? (Object*)ctx->mb->class : ctx->this;
214 jam_dprintf("[%s] %smethod unlock obj %p\n", __func__,
215 ctx->mb->access_flags & ACC_STATIC ? "static " : "", sync_ob);
216 objectUnlock(sync_ob);
219 ctx->ostack = ctx->lvars_jem - ctx->mb->max_locals + 1 - ctx->mb->args_count;
220 ctx->mb = ctx->frame->mb;
221 ctx->lvars_jem = ctx->frame->lvars_jem - 1;
223 GET_THIS(ctx);
225 ctx->jem.jpc = (uint32_t)ctx->frame->last_pc;
226 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
227 jam_dprintf("[OPC_RETURN] ostack: %p, lvars_jem: %p this: %p class %p\n",
228 ctx->ostack, ctx->lvars_jem, ctx->this,
229 ctx->this ? ctx->this->class : NULL);
231 /* Pop frame */
232 ee->last_frame = ctx->frame;
234 return 0;
237 static int invokeMethod(struct intrp_ctx *ctx)
239 ExecEnv *ee = ctx->ee;
240 /* Seems like the original jamvm reused top of caller's stack for callee's
241 * local variables for passing of method arguments. Our stack and
242 * local variables grow in opposite directions now, so, this is impossible.
243 * ctx->ostack points at the beginning of the free space above ostack.
245 Frame *new_frame = (Frame *)(ctx->ostack + ctx->new_mb->max_locals);
246 Object *sync_ob = NULL;
247 int i;
248 uintptr_t *aobj;
250 jam_dprintf("[invokeMethod] with args count %d, frame %p\n",
251 ctx->new_mb->args_count, new_frame);
253 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
254 ctx->ostack = (uintptr_t *)(new_frame + 1);
256 if (ostack_overflows(ctx->ostack, ctx->new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
257 if (ee->overflow++) {
258 /* Overflow when we're already throwing stack overflow.
259 Stack extension should be enough to throw exception,
260 so something's seriously gone wrong - abort the VM! */
261 jam_printf("Fatal stack overflow! Aborting VM.\n");
262 exitVM(1);
264 ee->stack_end += STACK_RED_ZONE_SIZE;
265 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
268 //TODO
269 new_frame->mb = ctx->new_mb;
270 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
271 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
272 // Here still not touch the java stack, allocate lvars_jem from native heap
274 new_frame->lvars_jem = (uintptr_t *)new_frame;
276 if (ctx->new_mb->max_locals > 0) {
277 for (i = 0; i < ctx->new_mb->args_count; i++) {
278 *(new_frame->lvars_jem - 1 - i) = *(ctx->arg1 + i);
279 jam_dprintf("arg[%d] = 0x%x@%p\n", i, *(ctx->arg1 + i), ctx->arg1 + i);
283 jam_dprintf("[invokeMethod] %s::%s() lvars_jem %p\n",
284 CLASS_CB(ctx->new_mb->class)->name, ctx->new_mb->name, new_frame->lvars_jem);
286 new_frame->ostack = ctx->ostack;
287 new_frame->prev = ctx->frame;
289 ee->last_frame = new_frame;
291 if (ctx->new_mb->access_flags & ACC_SYNCHRONIZED) {
292 aobj = (uintptr_t *)*ctx->arg1;
293 sync_ob = ctx->new_mb->access_flags & ACC_STATIC ?
294 (Object*)ctx->new_mb->class : JAM_OBJECT(aobj);
295 objectLock(sync_ob);
298 if (ctx->new_mb->access_flags & ACC_NATIVE) {
299 //FIXME: the object references in JEM are direct pointer to instance variables.
300 // While JamVM requires object references as pointers to Object type.
301 jam_dprintf("[invokeMethod] invoke native method using %p invoker\n",
302 ctx->new_mb->native_invoker);
303 ctx->ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
304 ctx->new_mb->native_invoker)(ctx->new_mb->class, ctx->new_mb, ctx->arg1);
306 if (sync_ob)
307 objectUnlock(sync_ob);
309 ee->last_frame = ctx->frame;
311 if (exceptionOccured0(ee)) {
312 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
313 return jem_throwException(ctx);
316 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
317 } else {
318 ctx->frame = new_frame;
319 ctx->mb = ctx->new_mb;
320 ctx->lvars_jem = new_frame->lvars_jem - 1;
322 GET_THIS(ctx);
324 ctx->jem.jpc = (unsigned long)ctx->mb->code & ~3;
325 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
327 jam_dprintf("[invokeMethod] invoke virtual method: mb %x "
328 "lvars %x jpc %x cp %x\n", ctx->mb,
329 ctx->lvars_jem, ctx->jem.jpc, ctx->cp);
332 return 0;
335 static int opc_invokesuper_quick(struct intrp_ctx *ctx)
337 struct jem_state *jem = &ctx->jem;
338 Operand *operand = &jem->operand;
340 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
341 ctx->new_mb = CLASS_CB(CLASS_CB(ctx->mb->class)->super)->method_table[operand->i];
342 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx->new_mb->args_count);
344 // set up jem operand stack
345 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
346 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
347 JEM_NULL_POINTER_CHECK(*ctx->arg1);
348 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx->arg1);
349 return invokeMethod(ctx);
352 static int opc_invokenonvirtual_quick(struct intrp_ctx *ctx)
354 struct jem_state *jem = &ctx->jem;
355 Operand *operand = &jem->operand;
357 ctx->new_mb = (MethodBlock*)operand->pntr;
358 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
359 __func__, ctx->new_mb->name, ctx->new_mb, ctx->new_mb->args_count);
360 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
361 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
363 jam_dprintf("[%s] ctx->arg1 %x\n", __func__, *ctx->arg1);
364 JEM_NULL_POINTER_CHECK(*ctx->arg1);
365 return invokeMethod(ctx);
368 static int opc_invokevirtual_quick(struct intrp_ctx *ctx)
370 struct jem_state *jem = &ctx->jem;
371 Object *obj;
372 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
373 ctx->ostack - ctx->frame->ostack - INV_QUICK_ARGS(jem));
374 JEM_NULL_POINTER_CHECK(*ctx->arg1);
375 Class *new_class;
377 //in case of "AALOAD" loads JAM obj from reference array
378 obj = (Object *)*ctx->arg1;
379 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj)) {
380 obj = JAM_OBJECT((uintptr_t *)obj);
381 //we should ensure ostack contains no JAM object
382 *ctx->arg1 = (uintptr_t)INST_DATA(obj);
385 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object %p from %p class %p\n",
386 obj, ctx->arg1, obj->class);
387 new_class = obj->class;
388 ctx->new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(jem)];
389 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x\n",
390 ctx->new_mb);
391 return invokeMethod(ctx);
394 static int opc_invokevirtual(struct intrp_ctx *ctx)
396 int idx;
397 ExecEnv *ee = ctx->ee;
398 struct jem_state *jem = &ctx->jem;
400 idx = jem->jecr & 0xffff;
401 ctx->frame->last_pc = (CodePntr)jem->jpc;
402 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
404 if (exceptionOccured0(ee))
405 return jem_throwException(ctx);
407 jem->operand.uu.u1 = ctx->new_mb->args_count;
408 jem->operand.uu.u2 = ctx->new_mb->method_table_index;
410 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
411 ctx->new_mb, ctx->new_mb->args_count);
413 return opc_invokevirtual_quick(ctx);
416 static int opc_invokespecial(struct intrp_ctx *ctx)
418 int idx;
419 struct jem_state *jem = &ctx->jem;
420 Operand *operand = &jem->operand;
421 ExecEnv *ee = ctx->ee;
423 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
424 idx = jem->jecr & 0xffff;
426 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx);
428 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
430 if (exceptionOccured0(ee))
431 return jem_throwException(ctx);
433 jam_dprintf("Resolved %s\n", ctx->new_mb->name);
435 /* Check if invoking a super method... */
436 if ((CLASS_CB(ctx->mb->class)->access_flags & ACC_SUPER) &&
437 ((ctx->new_mb->access_flags & ACC_PRIVATE) == 0) && (ctx->new_mb->name[0] != '<')) {
439 operand->i = ctx->new_mb->method_table_index;
440 return opc_invokesuper_quick(ctx);
441 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
442 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
443 #endif
444 } else {
445 operand->pntr = ctx->new_mb;
446 return opc_invokenonvirtual_quick(ctx);
449 return 0;
452 static int opc_invokestatic_quick(struct intrp_ctx *ctx)
454 struct jem_state *jem = &ctx->jem;
456 ctx->new_mb = RESOLVED_METHOD(jem);
457 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
458 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
459 return invokeMethod(ctx);
462 static int opc_invokestatic(struct intrp_ctx *ctx)
464 int idx, cache;
465 struct jem_state *jem = &ctx->jem;
466 Operand *operand = &jem->operand;
467 ExecEnv *ee = ctx->ee;
469 idx = jem->jecr & 0xffff;
471 ctx->frame->last_pc = (CodePntr)jem->jpc;
472 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
474 if (exceptionOccured0(ee))
475 return jem_throwException(ctx);
477 operand->pntr = ctx->new_mb;
478 return opc_invokestatic_quick(ctx);
481 static int opc_new_quick(struct intrp_ctx *ctx)
483 struct jem_state *jem = &ctx->jem;
484 Operand *operand = &jem->operand;
485 Class *class = (Class*)CP_INFO(ctx->cp, operand->uui.u1);
486 Object *obj;
488 ctx->frame->last_pc = (CodePntr)jem->jpc;
489 if ((obj = allocObject(class)) == NULL)
490 return jem_throwException(ctx);
491 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj);
492 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
493 (uint32_t)INST_DATA(obj));
496 static int opc_new(struct intrp_ctx *ctx)
498 struct jem_state *jem = &ctx->jem;
499 Operand *operand = &jem->operand;
500 int idx = jem->jecr & 0xffff;
501 int opcode = (jem->jecr >> 16) & 0xff;
502 Class *class;
503 ExecEnv *ee = ctx->ee;
505 operand->uui.u1 = idx;
506 operand->uui.u2 = opcode;
508 jam_dprintf("[OPC_NEW] opcode: 0x%x, index: 0x%x\n", opcode, idx);
510 ctx->frame->last_pc = (CodePntr)jem->jpc;
511 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
512 if (exceptionOccured0(ee))
513 return jem_throwException(ctx);
515 if (opcode == OPC_NEW) {
516 ClassBlock *cb = CLASS_CB(class);
517 if (cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
518 signalException("java/lang/InstantiationError", cb->name);
519 return jem_throwException(ctx);
521 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
522 jem_opcode_rewrite(0xDD, (char*)jem->jpc - 3, 0);
525 return opc_new_quick(ctx);
528 static int opc_anewarray_quick(struct intrp_ctx *ctx)
530 struct jem_state *jem = &ctx->jem;
531 ConstantPool *cp = ctx->cp;
532 Class *class = RESOLVED_CLASS(jem);
533 char *name = CLASS_CB(class)->name;
534 int count;
535 Class *array_class;
536 char *ac_name;
537 Object *obj;
538 ExecEnv *ee = ctx->ee;
540 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
541 ctx->frame->last_pc = (CodePntr)jem->jpc;
543 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name, count);
544 if (count < 0) {
545 signalException("java/lang/NegativeArraySizeException", NULL);
546 return jem_throwException(ctx);
549 ac_name = sysMalloc(strlen(name) + 4);
551 if (name[0] == '[')
552 sprintf(ac_name, "[%s", name);
553 else
554 sprintf(ac_name, "[L%s;", name);
556 array_class = findArrayClassFromClass(ac_name, ctx->mb->class);
557 free(ac_name);
559 if (exceptionOccured0(ee))
560 return jem_throwException(ctx);
562 if ((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
563 return jem_throwException(ctx);
565 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
566 (uint32_t)ARRAY_DATA(obj));
569 static int opc_anewarray(struct intrp_ctx *ctx)
571 struct jem_state *jem = &ctx->jem;
572 Operand *operand = &jem->operand;
573 int idx = jem->jecr & 0xffff;
574 int opcode = (jem->jecr >> 16) & 0xff;
575 Class *class;
576 ExecEnv *ee = ctx->ee;
578 operand->uui.u1 = idx;
579 operand->uui.u2 = opcode;
581 jam_dprintf("[OPC_ANEWARRAY] index: 0x%x\n", idx);
583 ctx->frame->last_pc = (CodePntr)jem->jpc;
584 //resolve the array class
585 class = resolveClass(ctx->mb->class, idx, FALSE);
587 if (exceptionOccured0(ee))
588 return jem_throwException(ctx);
590 return opc_anewarray_quick(ctx);
593 static int opc_multianewarray_quick(struct intrp_ctx *ctx)
595 struct jem_state *jem = &ctx->jem;
596 ConstantPool *cp = ctx->cp;
597 Class *class = RESOLVED_CLASS(jem);
598 int i, dim = MULTI_ARRAY_DIM(jem);
599 int count;
600 Object *obj;
601 ExecEnv *ee = ctx->ee;
603 ctx->frame->last_pc = (CodePntr)jem->jpc;
605 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim, CLASS_CB(class)->name);
606 for (i = 0; i < dim; i++) {
607 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
608 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count, i);
609 if (count < 0) {
610 signalException("java/lang/NegativeArraySizeException", NULL);
611 return jem_throwException(ctx);
615 /* counts are still stored in ostack even after we did pop them out */
616 if ((obj = allocMultiArray(class, dim, (intptr_t *)ctx->ostack)) == NULL)
617 return jem_throwException(ctx);
619 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
620 (uint32_t)ARRAY_DATA(obj));
623 static int opc_multianewarray(struct intrp_ctx *ctx)
625 struct jem_state *jem = &ctx->jem;
626 Operand *operand = &jem->operand;
627 int idx = operand->uui.u1 = jem->jecr & 0xffff;
629 Class *class;
630 ExecEnv *ee = ctx->ee;
632 /* dimensions */
633 operand->uui.u2 = *(unsigned char*)jem->jpc;
634 jem->jpc++; /* skip dims */
636 ctx->frame->last_pc = (CodePntr)jem->jpc;
637 /* resolve the array class */
638 class = resolveClass(ctx->mb->class, idx, FALSE);
640 if (exceptionOccured0(ee))
641 return jem_throwException(ctx);
643 return opc_multianewarray_quick(ctx);
646 static int opc_newarray(struct intrp_ctx *ctx)
648 struct jem_state *jem = &ctx->jem;
649 int type = (jem->jecr >> 8) & 0xff;
650 int count;
651 Object *obj;
653 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
654 ctx->frame->last_pc = (CodePntr)jem->jpc;
656 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type, count);
657 if ((obj = allocTypeArray(type, count)) == NULL)
658 return jem_throwException(ctx);
660 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
661 (uint32_t)ARRAY_DATA(obj));
664 static int opc_putfield_quick(struct intrp_ctx *ctx)
666 uint32_t arg;
667 uint32_t obj;
668 struct jem_state *jem = &ctx->jem;
670 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
671 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
672 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg,
673 SINGLE_INDEX(jem), obj);
675 JEM_NULL_POINTER_CHECK(obj);
677 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
678 obj = (uint32_t)INST_DATA((Object *)obj);
680 ((uint32_t*)obj)[SINGLE_INDEX(jem)] = arg;
682 return 0;
685 static int opc_putfield2_quick(struct intrp_ctx *ctx)
687 uint64_t arg;
688 uint32_t obj;
689 struct jem_state *jem = &ctx->jem;
691 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
692 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
694 JEM_NULL_POINTER_CHECK((uintptr_t*)obj);
696 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
697 obj = (uint32_t)INST_DATA((Object *)obj);
699 *(uint64_t *)&(((uint32_t*)obj)[SINGLE_INDEX(jem)]) = arg;
700 jam_dprintf("[OPC_PUTFIELD2_QUICK] put 64 bit %08x to obj %08x\n", arg, obj);
702 return 0;
705 static int opc_putfield_quick_jem0(struct intrp_ctx *ctx)
707 uint32_t arg;
708 uintptr_t *aobj;
709 struct jem_state *jem = &ctx->jem;
711 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
712 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
713 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg);
715 JEM_NULL_POINTER_CHECK(aobj);
717 if (JAM_ON_STACK && arg && !IS_JAM_OBJECT(arg))
718 arg = (uint32_t)JAM_OBJECT((uintptr_t *)arg);
720 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
721 aobj = INST_DATA((Object *)aobj);
723 aobj[SINGLE_INDEX(jem)] = arg;
724 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg,
725 SINGLE_INDEX(jem), aobj);
727 return 0;
730 static int opc_putfield_quick_jem1(struct intrp_ctx *ctx)
732 uintptr_t *aobj, *arg;
733 struct jem_state *jem = &ctx->jem;
735 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
736 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
737 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg);
739 if (JAM_ON_STACK && arg && !IS_JAM_ARRAY(arg))
740 arg = (uintptr_t *)JAM_ARRAY(arg);
742 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
743 aobj = INST_DATA((Object *)aobj);
745 JEM_NULL_POINTER_CHECK(aobj);
746 aobj[SINGLE_INDEX(jem)] = (uintptr_t)arg;
747 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg,
748 SINGLE_INDEX(jem), aobj);
750 return 0;
753 static int opc_putfield(struct intrp_ctx *ctx)
755 struct jem_state *jem = &ctx->jem;
756 int idx = jem->jecr & 0xffff;
757 FieldBlock *fb;
758 ExecEnv *ee = ctx->ee;
760 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx);
762 ctx->frame->last_pc = (CodePntr)jem->jpc;
763 fb = resolveField(ctx->mb->class, idx);
764 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c, name %s\n", fb, *fb->type, fb->name);
766 if (exceptionOccured0(ee))
767 return jem_throwException(ctx);
769 jem->operand.i = fb->offset;
770 switch (*fb->type) {
771 case 'J':
772 case 'D':
773 /* rewrite opc_putfield to opc_putfield2_quick */
774 jem_opcode_rewrite(0xD1, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
775 return opc_putfield2_quick(ctx);
776 case 'L':
777 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
778 return opc_putfield_quick_jem0(ctx);
779 case '[':
780 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
781 return opc_putfield_quick_jem1(ctx);
782 default:
783 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
784 return opc_putfield_quick(ctx);
788 static int opc_getfield2_quick(struct intrp_ctx *ctx)
790 uint32_t *obj;
791 struct jem_state *jem = &ctx->jem;
792 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
793 JEM_NULL_POINTER_CHECK(obj);
795 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
796 obj = (uint32_t*)INST_DATA((Object*)obj);
798 jam_dprintf("[OPC_GETFIELD2_QUICK] get 64 bit field %08x from obj %08x\n",
799 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])), obj);
801 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
802 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])));
805 static int opc_getfield_quick(struct intrp_ctx *ctx)
807 uintptr_t *aobj;
808 struct jem_state *jem = &ctx->jem;
810 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
811 JEM_NULL_POINTER_CHECK(aobj);
813 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
814 aobj = (uint32_t*)INST_DATA((Object*)aobj);
816 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
817 aobj[SINGLE_INDEX(jem)], aobj);
818 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
819 aobj[SINGLE_INDEX(jem)]);
822 static int opc_getfield_quick_jem0(struct intrp_ctx *ctx)
824 uint32_t *aobj;
825 struct jem_state *jem = &ctx->jem;
827 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
828 JEM_NULL_POINTER_CHECK(aobj);
830 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
831 aobj = (uint32_t*)INST_DATA((Object*)aobj);
833 uint32_t value = aobj[SINGLE_INDEX(jem)];
834 if (value) {
835 Object *ref = (Object*)value;
836 if (JAM_ON_STACK && IS_JAM_OBJECT(ref))
837 //jamvm objref
838 value = (uint32_t)INST_DATA(ref);
839 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj %p ref %x, class %p : %p\n",
840 aobj, value, JAM_OBJECT((void *)value)->class, ref->class);
842 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value);
843 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
846 static int opc_getfield_quick_jem1(struct intrp_ctx *ctx)
848 uint32_t *aobj;
849 struct jem_state *jem = &ctx->jem;
851 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
852 JEM_NULL_POINTER_CHECK(aobj);
854 //"aaload" would put jamvm obj ref onto the ostack
855 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
856 aobj = (uint32_t*)INST_DATA((Object*)aobj);
858 uint32_t value = aobj[SINGLE_INDEX(jem)];
859 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value);
860 if (value) {
861 Object *ref = (Object*)value;
862 if (JAM_ON_STACK && IS_JAM_ARRAY(ref))
863 value = (uint32_t)ARRAY_DATA(ref);
865 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value);
866 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
869 static int opc_getfield(struct intrp_ctx *ctx)
871 struct jem_state *jem = &ctx->jem;
872 int idx = jem->jecr & 0xffff;
873 FieldBlock *fb;
874 ExecEnv *ee = ctx->ee;
876 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx);
878 ctx->frame->last_pc = (CodePntr)jem->jpc;
879 fb = resolveField(ctx->mb->class, idx);
881 if (exceptionOccured0(ee))
882 return jem_throwException(ctx);
884 jem->operand.i = fb->offset;
886 jam_dprintf("[OPC_GETFIELD] resolve field %s @ %p, type %c, offset %i, class %p\n",
887 fb->name, fb, *fb->type, jem->operand.i, fb->class);
889 switch (*fb->type) {
890 case 'J':
891 case 'D':
892 jem_opcode_rewrite(0xD0, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
893 return opc_getfield2_quick(ctx);
895 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
896 * in case of some JNI code will set field natively, we still handle it
897 * separately here.
899 case 'L':
900 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
901 return opc_getfield_quick_jem0(ctx);
902 case '[':
903 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
904 return opc_getfield_quick_jem1(ctx);
905 default:
906 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
907 return opc_getfield_quick(ctx);
911 static int opc_ldc_w_quick_jem(struct intrp_ctx *ctx)
913 struct jem_state *jem = &ctx->jem;
914 //CONSTANT_Class and CONSTANT_String are stored as object reference
915 Object *cp_info = (Object*)CP_INFO(ctx->cp, DOUBLE_INDEX(jem));
916 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info);
917 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
918 (uint32_t)INST_DATA(cp_info));
921 static int opc_ldc_w_quick(struct intrp_ctx *ctx)
923 struct jem_state *jem = &ctx->jem;
924 uint32_t cp_info = CP_INFO(ctx->cp, DOUBLE_INDEX(jem));
925 jam_dprintf("[OPC_LDC_W_QUICK] push constant %08x to stack\n", cp_info);
926 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, cp_info);
929 static int opc_ldc_quick(struct intrp_ctx *ctx)
931 struct jem_state *jem = &ctx->jem;
932 uint32_t constant = RESOLVED_CONSTANT(jem);
933 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant);
934 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uintptr_t)constant);
937 static int opc_ldc_common(struct intrp_ctx *ctx, int idx)
939 struct jem_state *jem = &ctx->jem;
940 ExecEnv *ee = ctx->ee;
941 ctx->frame->last_pc = (CodePntr)jem->jpc;
943 jem->operand.u = resolveSingleConstant(ctx->mb->class, idx);
945 if (exceptionOccured0(ee))
946 return jem_throwException(ctx);
948 if (CP_TYPE(ctx->cp, idx) == CONSTANT_ResolvedClass) {
949 jem->operand.i = idx;
950 jem_opcode_rewrite(0xCC, (char*)jem->jpc - 3, 0);
951 return opc_ldc_w_quick(ctx);
952 } else if (CP_TYPE(ctx->cp, idx) == CONSTANT_ResolvedString) {
953 jem->operand.i = idx;
954 return opc_ldc_w_quick_jem(ctx);
955 } else {
956 jem_opcode_rewrite(0xCB, (char*)jem->jpc - 2, 0);
957 return opc_ldc_quick(ctx);
961 static int opc_ldc(struct intrp_ctx *ctx)
963 int idx;
964 ExecEnv *ee = ctx->ee;
965 struct jem_state *jem = &ctx->jem;
967 idx = (jem->jecr & 0xff00) >> 8;
969 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx);
970 return opc_ldc_common(ctx, idx);
973 static int opc_ldc_w(struct intrp_ctx *ctx)
975 int idx;
976 ExecEnv *ee = ctx->ee;
977 struct jem_state *jem = &ctx->jem;
979 idx = (jem->jecr & 0xffff);
981 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx);
982 return opc_ldc_common(ctx, idx);
985 static int opc_monitorenter(struct intrp_ctx *ctx)
987 Object *obj;
988 uintptr_t *ptr;
989 struct jem_state *jem = &ctx->jem;
990 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
992 obj = JAM_OBJECT(ptr);
993 if (!IS_OBJECT(obj))
994 /* is an array ref */
995 obj = JAM_ARRAY(ptr);
996 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj);
997 JEM_NULL_POINTER_CHECK(obj);
998 objectLock(obj);
999 return 0;
1002 static int opc_monitorexit(struct intrp_ctx *ctx)
1004 Object *obj;
1005 uintptr_t *ptr;
1006 struct jem_state *jem = &ctx->jem;
1007 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1009 obj = JAM_OBJECT(ptr);
1010 if (!IS_OBJECT(obj))
1011 /* is an array ref */
1012 obj = JAM_ARRAY(ptr);
1013 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj);
1014 JEM_NULL_POINTER_CHECK(obj);
1015 objectUnlock(obj);
1016 return 0;
1019 static int opc_getstatic_quick(struct intrp_ctx *ctx)
1021 struct jem_state *jem = &ctx->jem;
1022 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1023 RESOLVED_FIELD(jem)->static_value);
1026 static int opc_getstatic2_quick(struct intrp_ctx *ctx)
1028 struct jem_state *jem = &ctx->jem;
1029 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1030 RESOLVED_FIELD(jem)->static_value);
1033 static int opc_getstatic_quick_jem0(struct intrp_ctx *ctx)
1035 struct jem_state *jem = &ctx->jem;
1036 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1038 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value);
1039 if (value) {
1040 Object *ref = (Object *)value;
1041 if (!JAM_ON_STACK || IS_JAM_OBJECT(ref))
1042 //jamvm objref
1043 value = (uintptr_t)INST_DATA(ref);
1045 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value);
1046 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1049 static int opc_getstatic_quick_jem1(struct intrp_ctx *ctx)
1051 struct jem_state *jem = &ctx->jem;
1052 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1053 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value);
1054 if (value) {
1055 Object *ref = (Object*)value;
1056 if (!JAM_ON_STACK || IS_JAM_ARRAY(ref))
1057 //jamvm arrayref
1058 value = (uintptr_t)ARRAY_DATA(ref);
1060 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value);
1061 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1064 static int opc_getstatic(struct intrp_ctx *ctx)
1066 int idx;
1067 FieldBlock *fb;
1068 Operand operand;
1069 ExecEnv *ee = ctx->ee;
1070 struct jem_state *jem = &ctx->jem;
1072 idx = (int)(jem->jecr & 0xffff);
1073 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx,CLASS_CB(ctx->mb->class)->name);
1075 ctx->frame->last_pc = (CodePntr)jem->jpc;
1076 fb = resolveField(ctx->mb->class, idx);
1078 if (exceptionOccured0(ee))
1079 return jem_throwException(ctx);
1081 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb, *fb->type);
1082 jem->operand.pntr = fb;
1083 switch (*fb->type) {
1084 case 'J':
1085 case 'D':
1086 return opc_getstatic2_quick(ctx);
1088 * see opc_getfield
1090 case 'L':
1091 return opc_getstatic_quick_jem0(ctx);
1092 case '[':
1093 return opc_getstatic_quick_jem1(ctx);
1094 default:
1095 return opc_getstatic_quick(ctx);
1099 static int opc_putstatic2_quick(struct intrp_ctx *ctx)
1101 struct jem_state *jem = &ctx->jem;
1102 return ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1103 *(u8*)&RESOLVED_FIELD(jem)->static_value);
1106 static int opc_putstatic_quick(struct intrp_ctx *ctx)
1108 struct jem_state *jem = &ctx->jem;
1109 return ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1110 RESOLVED_FIELD(jem)->static_value);
1113 static int opc_putstatic_quick_jem0(struct intrp_ctx *ctx)
1115 uintptr_t value;
1116 struct jem_state *jem = &ctx->jem;
1117 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1119 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value);
1120 if (value && (!JAM_ON_STACK || !IS_JAM_OBJECT(value)))
1121 value = (uintptr_t)JAM_OBJECT((uintptr_t *)value);
1122 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value);
1123 RESOLVED_FIELD(jem)->static_value = value;
1124 return 0;
1127 static int opc_putstatic_quick_jem1(struct intrp_ctx *ctx)
1129 uintptr_t *value;
1130 struct jem_state *jem = &ctx->jem;
1131 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1133 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value);
1134 if (value && (!JAM_ON_STACK || !IS_JAM_ARRAY(value)))
1135 value = (uintptr_t*)JAM_ARRAY(value);
1136 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value);
1137 RESOLVED_FIELD(jem)->static_value = (uintptr_t)value;
1138 return 0;
1141 static int opc_putstatic(struct intrp_ctx *ctx)
1143 int idx;
1144 FieldBlock *fb;
1145 Operand operand;
1146 ExecEnv *ee = ctx->ee;
1147 struct jem_state *jem = &ctx->jem;
1149 idx = (int)(jem->jecr & 0xffff);
1151 ctx->frame->last_pc = (CodePntr)jem->jpc;
1152 fb = resolveField(ctx->mb->class, idx);
1154 if (exceptionOccured0(ee))
1155 return jem_throwException(ctx);
1157 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb, *fb->type);
1158 jem->operand.pntr = fb;
1159 switch (*fb->type) {
1160 case 'J':
1161 case 'D':
1162 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1163 return opc_putstatic2_quick(ctx);
1164 case 'L':
1165 return opc_putstatic_quick_jem0(ctx);
1166 case '[':
1167 return opc_putstatic_quick_jem1(ctx);
1168 default:
1169 return opc_putstatic_quick(ctx);
1173 static int opc_checkcast_quick(struct intrp_ctx *ctx)
1175 struct jem_state *jem = &ctx->jem;
1176 ConstantPool *cp = ctx->cp;
1177 Class *class = RESOLVED_CLASS(jem);
1178 Object *obj;
1179 uintptr_t *ptr;
1181 ostack_read_u32(ctx->frame->ostack, ctx->ostack, 0, &ptr);
1182 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr, CLASS_CB(class)->name);
1183 if (ptr != NULL) {
1184 #warning Does not look right!
1185 if (!JAM_ON_STACK || !IS_JAM_OBJECT(ptr) || !IS_JAM_ARRAY(ptr)) {
1186 obj = JAM_OBJECT(ptr);
1187 if (!IS_OBJECT(obj)) {
1188 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1189 //should be array ref
1190 obj = JAM_ARRAY(ptr);
1192 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj);
1193 } else {
1194 obj = (Object*)ptr;
1196 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %p (%s) for obj %p (%s)\n",
1197 class, CLASS_CB(class)->name, obj->class, CLASS_CB(obj->class)->name);
1198 if (!isInstanceOf(class, obj->class))
1199 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
1202 return 0;
1205 static int opc_checkcast(struct intrp_ctx *ctx)
1207 struct jem_state *jem = &ctx->jem;
1208 Operand *operand = &jem->operand;
1209 int idx = jem->jecr & 0xffff;
1210 int opcode = (jem->jecr >> 16) & 0xff;
1211 Class *class;
1212 ExecEnv *ee = ctx->ee;
1214 operand->uui.u1 = idx;
1215 operand->uui.u2 = opcode;
1217 jam_dprintf("[OPC_CHECKCAST] index: 0x%x\n", idx);
1219 ctx->frame->last_pc = (CodePntr)jem->jpc;
1220 //resolve the cast class
1221 class = resolveClass(ctx->mb->class, idx, FALSE);
1223 if (exceptionOccured0(ee))
1224 return jem_throwException(ctx);
1226 return opc_checkcast_quick(ctx);
1229 static int opc_invokeinterface_quick(struct intrp_ctx *ctx)
1231 int mtbl_idx;
1232 ClassBlock *cb;
1233 Object *objref;
1234 int cache = ctx->jem.operand.uu.u2;
1236 ctx->new_mb = (MethodBlock *)CP_INFO(ctx->cp, ctx->jem.operand.uu.u1);
1237 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
1238 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
1240 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1241 ctx->new_mb, ctx->new_mb->name, ctx->new_mb->args_count, ctx->arg1);
1243 objref = (Object *)*ctx->arg1;
1244 #warning Does not look right!
1245 if (!JAM_ON_STACK || !IS_JAM_OBJECT(objref) || !IS_JAM_ARRAY(objref)) {
1246 objref = JAM_OBJECT((uintptr_t *)objref);
1247 if (!IS_OBJECT(objref))
1248 objref = JAM_ARRAY((uintptr_t *)*ctx->arg1);
1249 } else {
1250 //turn type in the stack to JEM type ref
1251 *ctx->arg1 = (uintptr_t)INST_DATA(objref);
1253 JEM_NULL_POINTER_CHECK(objref);
1255 cb = CLASS_CB(objref->class);
1257 if ((cache >= cb->imethod_table_size) ||
1258 (ctx->new_mb->class != cb->imethod_table[cache].interface)) {
1259 for (cache = 0; (cache < cb->imethod_table_size) &&
1260 (ctx->new_mb->class != cb->imethod_table[cache].interface); cache++);
1262 if (cache == cb->imethod_table_size)
1263 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1264 "unimplemented interface");
1267 mtbl_idx = cb->imethod_table[cache].offsets[ctx->new_mb->method_table_index];
1268 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx);
1269 ctx->new_mb = cb->method_table[mtbl_idx];
1270 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx);
1271 return invokeMethod(ctx);
1274 static int opc_invokeinterface(struct intrp_ctx *ctx)
1276 struct jem_state *jem = &ctx->jem;
1277 Operand *operand = &jem->operand;
1278 ExecEnv *ee = ctx->ee;
1280 int idx = operand->uu.u1 = jem->jecr & 0xffff;
1281 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1282 * For JEM, two index bytes has been processed before trap,
1283 * so offset jpc 4 operands for next opcode
1284 *FIXME: ? not know why JEM does not handle this */
1285 ctx->frame->last_pc = (CodePntr)(jem->jpc += 2);
1286 ctx-> new_mb = resolveInterfaceMethod(ctx->mb->class, idx);
1288 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx);
1289 if (exceptionOccured0(ee))
1290 return jem_throwException(ctx);
1292 if (CLASS_CB(ctx->new_mb->class)->access_flags & ACC_INTERFACE) {
1293 operand->uu.u2 = 0;
1294 return opc_invokeinterface_quick(ctx);
1295 } else {
1296 operand->uu.u1 = ctx->new_mb->args_count;
1297 operand->uu.u2 = ctx->new_mb->method_table_index;
1298 return opc_invokevirtual_quick(ctx);
1302 static int opc_instanceof_quick(struct intrp_ctx *ctx)
1304 struct jem_state *jem = &ctx->jem;
1305 ConstantPool *cp = ctx->cp;
1306 Class *class = RESOLVED_CLASS(jem);
1307 Object *obj;
1308 uintptr_t *ptr;
1310 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1311 if (ptr != NULL) {
1312 obj = JAM_OBJECT(ptr);
1313 if (!IS_OBJECT(obj)) {
1314 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1315 //should be array ref
1316 obj = JAM_ARRAY(ptr);
1319 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n",
1320 CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
1321 if (obj != NULL)
1322 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1323 (uint32_t)isInstanceOf(class, obj->class));
1325 return 0;
1328 static int opc_instanceof(struct intrp_ctx *ctx)
1330 struct jem_state *jem = &ctx->jem;
1331 Operand *operand = &jem->operand;
1332 int idx = jem->jecr & 0xffff;
1333 int opcode = (jem->jecr >> 16) & 0xff;
1334 Class *class;
1335 ExecEnv *ee = ctx->ee;
1337 operand->uui.u1 = idx;
1338 operand->uui.u2 = opcode;
1340 jam_dprintf("[OPC_INSTANCEOF] index: 0x%x\n", idx);
1342 ctx->frame->last_pc = (CodePntr)jem->jpc;
1343 //resolve the cast class
1344 class = resolveClass(ctx->mb->class, idx, FALSE);
1346 if (exceptionOccured0(ee))
1347 return jem_throwException(ctx);
1349 return opc_instanceof_quick(ctx);
1352 static int opc_aastore(struct intrp_ctx *ctx)
1354 Object *obj;
1355 uintptr_t *aobj;
1356 int idx ;
1357 Object *array;
1359 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
1360 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, idx);
1361 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, array);
1363 jam_dprintf("[OPC_AASTORE] obj %x, idx %x, array %x\n", aobj, idx, array);
1365 /* aobj does point to an object, but we do not know if that's an array or
1366 * not, and we need to know that for the arrayStoreCheck() check below */
1367 #warning Does not look right!
1368 if (aobj && (!JAM_ON_STACK || !IS_JAM_OBJECT(aobj) || !IS_JAM_ARRAY(aobj))) {
1369 if (!IS_OBJECT(JAM_OBJECT(aobj))) {
1370 //in case of storing an array to another array
1371 obj = JAM_ARRAY(aobj);
1372 } else {
1373 obj = JAM_OBJECT(aobj);
1375 } else
1376 obj = (Object *)aobj;
1377 array = JAM_ARRAY((uintptr_t *)array);
1379 jam_dprintf("[OPC_AASTORE] store obj ref %x to array %x in index %d\n", obj, array, idx);
1380 JEM_NULL_POINTER_CHECK(array);
1382 if (idx >= ARRAY_LEN(array)) {
1383 char buff[MAX_INT_DIGITS];
1384 snprintf(buff, MAX_INT_DIGITS, "%d", idx);
1385 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff);
1388 if ((obj != NULL) && !arrayStoreCheck(array->class, obj->class))
1389 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
1391 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1392 // the array to get the non jamvm refs to use, which then causes segfault.
1393 #if JAM_ON_STACK
1394 ((Object**)ARRAY_DATA(array))[idx] = obj;
1395 #else
1396 ((uintptr_t**)ARRAY_DATA(array))[idx] = aobj;
1397 #endif
1398 return 0;
1401 static int do_javaExceptions(struct intrp_ctx *ctx)
1403 union jecr jecr_u;
1404 struct jem_state *jem = &ctx->jem;
1406 /* deliberate segfault */
1407 /* *(int *)0 = 0; */
1409 jecr_u.i = jem->jecr;
1410 /* This should not happen, because we don't use the "Java Handle" (H)
1411 * bit in the Status Register and we set JBCR to 0x80000000 - still
1412 * it does happen, but seems to be harmless so far. Just ignore. */
1413 if (jecr_u.s.opcode == OPC_AASTORE)
1414 return opc_aastore(ctx);
1416 return 1;
1419 static int opc_afireturn(struct intrp_ctx *ctx)
1421 uint32_t val;
1422 int ret;
1423 struct jem_state *jem = &ctx->jem;
1425 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1427 jam_dprintf("[OPC_AFIRETURN] return 0x%08x @ %p, this %p\n",
1428 val, ctx->lvars_jem, ctx->this);
1430 ret = opc_return(ctx);
1431 if (!ret)
1432 ret = ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1433 else
1434 /* Function returning a value must have local variables */
1435 *ctx->lvars_jem = val;
1437 return ret;
1440 static int opc_ldreturn(struct intrp_ctx *ctx)
1442 uint64_t val;
1443 int ret;
1445 struct jem_state *jem = &ctx->jem;
1446 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1448 jam_dprintf("[OPC_LDRETURN] return %lld\n", val);
1450 ret = opc_return(ctx);
1452 if (!ret)
1453 ret = ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack,
1454 ctx->ostack, val);
1455 else
1456 /* Function returning a value must have local variables */
1457 *(uint64_t*)ctx->lvars_jem = val;
1459 return ret;
1462 static int opc_fcmpg(struct intrp_ctx *ctx)
1464 float v1, v2;
1465 int res;
1466 struct jem_state *jem = &ctx->jem;
1467 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1468 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1469 if (v1 == v2)
1470 res = 0;
1471 else if (v1 < v2)
1472 res = -1;
1473 else if (v1 > v2)
1474 res = 1;
1475 else
1476 res = 1; /* isNaN */
1477 jam_dprintf("[OPC_FCMPG] result %d\n", res);
1478 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1479 return 0;
1482 static int opc_fcmpl(struct intrp_ctx *ctx)
1484 float v1, v2;
1485 int res;
1486 struct jem_state *jem = &ctx->jem;
1487 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1488 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1489 if (v1 == v2)
1490 res = 0;
1491 else if (v1 < v2)
1492 res = -1;
1493 else if (v1 > v2)
1494 res = 1;
1495 else
1496 res = -1;
1497 jam_dprintf("[OPC_FCMPL] result %d\n", res);
1498 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1499 return 0;
1502 static int opc_i2f(struct intrp_ctx *ctx)
1504 int i;
1505 struct jem_state *jem = &ctx->jem;
1506 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, i);
1508 float f = (float)i;
1509 jam_dprintf("[OPC_I2F] convert to %f\n", f);
1510 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, f);
1511 return 0;
1514 static int opc_i2d(struct intrp_ctx *ctx)
1516 return JEM_TRAP_HANDLER_FINISH;
1519 static int opc_fmul(struct intrp_ctx *ctx)
1521 float v1, v2;
1522 float ret;
1523 struct jem_state *jem = &ctx->jem;
1524 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1525 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1526 ret = v1 * v2;
1527 jam_dprintf("[OPC_FMUL] result %f\n", ret);
1528 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1529 return 0;
1532 static int opc_fadd(struct intrp_ctx *ctx)
1534 float v1, v2;
1535 float ret;
1536 struct jem_state *jem = &ctx->jem;
1537 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1538 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1539 ret = v1 + v2;
1540 jam_dprintf("[OPC_FADD] result %f\n", ret);
1541 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1542 return 0;
1545 static int opc_fsub(struct intrp_ctx *ctx)
1547 float v1, v2;
1548 float ret;
1549 struct jem_state *jem = &ctx->jem;
1550 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1551 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1552 ret = v1 - v2;
1553 jam_dprintf("[OPC_FSUB] result %f\n", ret);
1554 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1555 return 0;
1558 static int opc_f2i(struct intrp_ctx *ctx)
1560 int res;
1561 float value;
1562 struct jem_state *jem = &ctx->jem;
1563 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1564 jam_dprintf("[OPC_F2I] float value %f\n", value);
1565 if (value >= (float)INT_MAX)
1566 res = INT_MAX;
1567 else if (value <= (float)INT_MIN)
1568 res = INT_MIN;
1569 else if (value != value)
1570 res = 0;
1571 else
1572 res = (int)value;
1573 jam_dprintf("[OPC_F2I] int value %d\n", res);
1574 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1575 return 0;
1578 static int opc_iinc(struct intrp_ctx *ctx)
1580 union jecr jecr_u;
1581 jecr_u.i = ctx->jem.jecr;
1582 int index = (int)jecr_u.s.op1;
1583 int con = (int)jecr_u.s.op2;
1584 uintptr_t *ptr = ctx->lvars_jem;
1586 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1587 con, ptr[-index], index, ctx->mb->max_locals);
1588 ptr[-index] = ptr[-index] + con;
1590 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr[-index]);
1591 return 0;
1594 static int opc_athrow(struct intrp_ctx *ctx)
1596 Object *obj;
1597 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
1598 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
1599 ExecEnv *ee = ctx->ee;
1601 JEM_NULL_POINTER_CHECK(obj);
1603 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj))
1604 obj = JAM_OBJECT((uintptr_t *)obj);
1606 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj->class)->name);
1607 ee->exception = obj;
1608 return jem_throwException(ctx);
1611 static int do_stackOverflow(struct intrp_ctx *ctx)
1613 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1614 return 0;
1617 static int do_stackUnderflow(struct intrp_ctx *ctx)
1619 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1620 return 1;
1623 static int do_stackOverflow1(struct intrp_ctx *ctx)
1625 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1626 return 1;
1629 static int do_stackUnderflow1(struct intrp_ctx *ctx)
1631 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1632 return 1;
1635 static handler_fn *trap_handler_f[256] = {
1636 [OPC_INVOKEINTERFACE] = opc_invokeinterface,
1637 [OPC_INVOKESPECIAL] = opc_invokespecial,
1638 [OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick,
1639 [OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick,
1640 [OPC_INVOKEVIRTUAL] = opc_invokevirtual,
1641 [OPC_INVOKEVIRTUAL_QUICK] = opc_invokevirtual_quick,
1642 [OPC_INVOKESTATIC] = opc_invokestatic,
1643 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1644 [OPC_NEW] = opc_new,
1645 [0xDD] = opc_new, /* JEM: NEW_QUICK */
1646 [OPC_RETURN] = opc_return,
1647 [OPC_ARETURN] = opc_afireturn,
1648 [OPC_IRETURN] = opc_afireturn,
1649 [OPC_FRETURN] = opc_afireturn,
1650 [OPC_PUTFIELD] = opc_putfield,
1651 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1652 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1653 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1654 // [OPC_LDC_QUICK] = opc_ldc_quick,
1655 [OPC_LDC_W] = opc_ldc_w,
1656 [OPC_LDC] = opc_ldc,
1657 [OPC_MONITORENTER] = opc_monitorenter,
1658 [OPC_MONITOREXIT] = opc_monitorexit,
1659 [OPC_GETSTATIC] = opc_getstatic,
1660 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1661 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1662 [OPC_PUTSTATIC] = opc_putstatic,
1663 [OPC_PUTSTATIC_QUICK] = opc_putstatic_quick,
1664 [OPC_PUTSTATIC2_QUICK] = opc_putstatic2_quick,
1665 [OPC_ANEWARRAY] = opc_anewarray,
1666 [OPC_ANEWARRAY_QUICK] = opc_anewarray_quick,
1667 [OPC_MULTIANEWARRAY] = opc_multianewarray,
1668 [OPC_NEWARRAY] = opc_newarray,
1669 [OPC_CHECKCAST] = opc_checkcast,
1670 [OPC_CHECKCAST_QUICK] = opc_checkcast_quick,
1671 [OPC_GETFIELD] = opc_getfield,
1672 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1673 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1674 [OPC_FCMPL] = opc_fcmpl,
1675 [OPC_FCMPG] = opc_fcmpg,
1676 [OPC_I2F] = opc_i2f,
1677 [OPC_I2D] = opc_i2d,
1678 [OPC_FMUL] = opc_fmul,
1679 // [OPC_FADD] = opc_fadd,
1680 // [OPC_FSUB] = opc_fsub,
1681 [OPC_F2I] = opc_f2i,
1682 [OPC_IINC] = opc_iinc,
1683 [OPC_INSTANCEOF] = opc_instanceof,
1684 [OPC_ATHROW] = opc_athrow,
1685 [OPC_LRETURN] = opc_ldreturn,
1688 static handler_fn *exception_handler_f[] = {
1689 [0] = do_javaExceptions,
1690 [1] = do_stackOverflow,
1691 [2] = do_stackUnderflow,
1692 [3] = do_stackOverflow1,
1693 [4] = do_stackUnderflow1,
1696 struct jem_profile {
1697 unsigned long time;
1698 unsigned int n;
1701 static struct jem_profile prof[256];
1703 /******************************/
1704 uintptr_t *executeJava(void)
1707 * load trap entries to JEM trap table set when initializing JamVM
1709 int i;
1710 uint32_t jep;
1711 int done;
1712 #ifdef JEM_PROFILE
1713 static struct timeval tv1, tv2;
1714 #endif
1715 ExecEnv *ee = getExecEnv();
1717 /* Initialize interpreter's static environment */
1718 struct intrp_ctx ctx;
1719 struct jem_state *jem = &ctx.jem;
1721 ctx.ee = ee;
1722 ctx.frame = ee->last_frame;
1723 ctx.mb = ctx.frame->mb;
1725 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1726 * overflow we free a half of the stack (4 elements) to avoid an immediate
1727 * next overflow. When entering a trap, the Operand Stack is saved in a
1728 * temporary array in the reverse order:
1729 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1730 * jos[0] = r7 (?)
1731 * ...
1732 * jos[7 - N] = rN (ToS - N)
1733 * ...
1734 * jos[7] = r0 (ToS)
1735 * UPDATE (27.06.2008)
1736 * I think, actually, the manual is right in some way... If you access
1737 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1738 * with an ldm, you get this:
1739 * jos[0] = r7 (?)
1740 * ...
1741 * jos[7 - N] = rN (ToS)
1742 * ...
1743 * jos[7] = r0 (ToS - N)
1744 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1745 * set saved JOSP to 4.
1747 unsigned long jos[8];
1749 ctx.ostack = ctx.frame->ostack;
1750 ctx.cp = &(CLASS_CB(ctx.mb->class)->constant_pool);
1751 /* End enterpreter's static environment */
1753 //fetch the original pc before prepare direct mb
1754 //TODO:
1755 /* I think, mb->code is indeed a copy of the original code[] array from the
1756 * class object. See class.c::defineClass():390 */
1758 if (ctx.frame->lvars_jem) {
1759 ctx.lvars_jem = ctx.frame->lvars_jem - 1;
1761 GET_THIS(&ctx);
1762 } else {
1763 jam_printf("BUG: lvars_jem == NULL!!!");
1764 exitVM(1);
1767 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1768 ctx.ostack, ctx.mb->max_locals, ctx.lvars_jem);
1769 jam_dprintf("[executeJava] execute method %s on class %s\n",
1770 ctx.mb->name, CLASS_CB(ctx.mb->class)->name);
1772 #if 0
1773 /* Don't think we need it, at least, not in the direct.c form. There the code
1774 * is converted into an internal representation, which is useless for JEM */
1775 PREPARE_MB(ctx.mb);//see direct.c (prepare)
1776 #endif
1778 jem->jpc = (unsigned long)ctx.mb->code & ~3;
1779 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1780 *(char*)jem->jpc, *((char*)jem->jpc + 1));
1782 do {
1783 #ifdef JEM_PROFILE
1784 /* This is not thread-safe. Have to use TLS. */
1785 static
1786 #endif
1787 int opcode;
1789 #ifdef JEM_DEBUG
1790 jam_dprintf("About to enter JEM at 0x%08x, this = %p, class = %p. Code:",
1791 jem->jpc, ctx.this, ctx.this ? ctx.this->class : NULL);
1792 for (i = 0; i < 32 && jem->jpc + i < (unsigned long)(ctx.mb->code + ctx.mb->code_size); i++) {
1793 if (!(i & 0xf))
1794 jam_dprintf("\n0x%04x:", i);
1795 jam_dprintf(" 0x%02x", ((char*)jem->jpc)[i]);
1798 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx.mb->max_locals);
1799 for (i = 0; i < min(8, ctx.mb->max_locals); i++)
1800 jam_dprintf("LVAR_%d: 0x%08x\n", i, *(ctx.lvars_jem - i), ctx.lvars_jem - i);
1801 #endif
1803 /* On entry we need last Java Operand Stack depth, set it not deeper
1804 * than half hardware stack */
1805 jem->josp = min(5, ostack_depth(ctx.frame->ostack, ctx.ostack));
1806 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem->josp,
1807 ctx.frame->ostack, ctx.ostack);
1808 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1809 for (i = 0; i < jem->josp; i++)
1810 ostack_pop_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
1811 jos[7 - jem->josp + 1 + i]);
1813 #ifdef JEM_PROFILE
1814 if (tv1.tv_sec) {
1815 gettimeofday(&tv2, NULL);
1816 prof[opcode].time += (tv2.tv_sec - tv1.tv_sec) * 1000000 +
1817 tv2.tv_usec - tv1.tv_usec;
1818 prof[opcode].n++;
1820 #endif
1822 __asm__ __volatile__(
1823 ".globl debug_jem_enter\n"
1824 "debug_jem_enter:\n"
1825 " pushm r0-r7,r10-r11\n"
1826 " mov r8, %[cp]\n"
1827 " mov r9, %[lv0]\n"
1828 " mov lr, %[jpc]\n"
1829 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1830 " mov r11, %[ostack]\n"
1831 " pushm r11\n" /* Need ostack below */
1832 " ldm r11, r0-r7\n" /* Restore Java Operands */
1833 " cp.w r12, 0\n" /* Test josp == 0 */
1834 " breq 4f\n"
1835 "5: incjosp 1\n" /* ... for loop counter, */
1836 " sub r12, 1\n" /* because it can be */
1837 " brne 5b\n" /* one of r0-r7 */
1838 "4: popjc\n" /* Restore Local Variables */
1839 " sub r10, pc, . - trap\n" /* These 3 instructions */
1840 " retj\n" /* have to stay */
1841 "trap: pushjc\n" /* together */
1842 " mfsr r11, 0x58\n" /* JOSP */
1843 " lsl r11, 28\n" /* Clear r11[31:3] using */
1844 " lsr r11, 28\n" /* one register */
1845 " mov r8, r11\n"
1846 " breq 2f\n"
1847 "3: incjosp -1\n"
1848 " sub r11, 1\n"
1849 " brne 3b\n"
1850 "2: popm r11\n" /* ostack */
1851 " stm r11, r0-r7\n" /* Save Java Operands */
1852 " popm r0-r7,r10-r11\n"
1853 " mov %[tpc], r12\n"
1854 " mov %[jpc], lr\n" /* Resume address */
1855 " mfsr %[jecr], 0x54\n" /* JECR */
1856 " mov %[josp], r8\n" /* JOSP */
1857 " .globl debug_jem_exit\n"
1858 "debug_jem_exit:\n"
1859 : [jecr] "=r" (jem->jecr), [tpc] "=r" (jem->trap_pc),
1860 [josp] "+r" (jem->josp), [jpc] "+r" (jem->jpc)
1861 : [cp] "r" (ctx.cp->info), [lv0] "r" (ctx.lvars_jem),
1862 [ostack] "r" (jos)
1863 : "r8", "r9", "lr", "r12", "memory"
1866 * trap_pc now holds trap pc, describing which trap has been entered,
1867 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1868 * arguments at bits 7..0 and 15..8,
1869 * josp holds JOSP (JOSP & 0xf),
1870 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1871 * jpc points at the trapping opcode, in case of exceptions and stack
1872 * over- and underflows, and at the next opcode, in case of a trap
1875 #ifdef JEM_PROFILE
1876 gettimeofday(&tv1, NULL);
1877 #endif
1879 for (i = 0; i < jem->josp; i++)
1880 ostack_push_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
1881 jos[7 - i]);
1883 opcode = (jem->jecr >> 16) & 0xff;
1885 jep = jem->trap_pc & 0xfff;
1887 trap_debug(&ctx);
1888 if (jep < 0x280)
1889 done = exception_handler_f[jep >> 7](&ctx);
1890 else if (trap_handler_f[opcode])
1891 done = trap_handler_f[opcode](&ctx);
1892 else {
1893 /* Unimplemented */
1894 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode);
1895 exitVM(1);
1898 #ifdef JEM_DEBUG
1899 usleep(100);
1900 #endif
1901 } while (done != JEM_TRAP_HANDLER_FINISH);
1903 return ctx.ostack;
1905 // DISPATCH_FIRST;
1907 jam_dprintf("Unknown Java Opcodes\n");
1908 exitVM(1);
1911 #ifndef executeJava
1912 void initialiseInterpreter(InitArgs *args) {
1913 initialiseDirect(args);
1915 #endif
1917 void dump_profile(void)
1919 #ifdef JEM_PROFILE
1920 int i;
1922 for (i = 0; i < 256; i++)
1923 if (prof[i].n)
1924 jam_printf("0x%x:\t%u times,\t%lu usec\n", i, prof[i].n, prof[i].time);
1925 #endif