Some formatting unifications.
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blob0b74e3e91968494c1043bf9f6e7d22619232b90c
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 #ifdef JEM
38 #include <sys/syscall.h>
39 #include <unistd.h>
40 #include <sys/mman.h>
42 #include "arch/avr32_jem.h"
43 #include "interp_jem.h"
45 union jecr {
46 struct {
47 uint8_t dummy;
48 uint8_t opcode;
49 uint8_t op1;
50 uint8_t op2;
51 } s;
52 uint32_t i;
55 /**
56 * Interpreter execution context
58 struct intrp_ctx {
59 /* JEM state */
60 struct jem_state jem;
62 /* the interpreter execution context */
63 Frame *frame;
64 MethodBlock *mb;
65 MethodBlock *new_mb;
66 ConstantPool *cp;
67 Object *this;
68 uintptr_t *lvars_jem;
69 uintptr_t *ostack;
70 uintptr_t *arg1;
71 ExecEnv *ee;
74 typedef int handler_fn(struct intrp_ctx *ctx);
76 static void jem_opcode_rewrite(uint32_t new_opcode, char *pc, int argc, ...)
78 int i;
79 va_list vargs;
81 va_start(vargs, argc);
82 pc[0] = new_opcode;
83 for (i = 1; i <= argc; i++)
84 pc[i] = (char)va_arg(vargs, int);
85 va_end(vargs);
88 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
90 //check if it is an valid object ref (see alloc.c)
91 #define OBJECT_GRAIN 8
92 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
94 #define JEM_THROW_EXCEPTION(excep_name, message) \
95 ({ \
96 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
97 signalException(excep_name, message); \
98 jem_throwException(ctx); \
101 #define JEM_NULL_POINTER_CHECK(ref) \
102 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
104 /*********************************************
105 * JEM Trap Handlers **
106 * *******************************************/
107 static int trap_debug(struct intrp_ctx *ctx)
109 #ifdef JEM_DEBUG
110 struct jem_state *jem = &ctx->jem;
111 union jecr jecr_u;
112 int i;
113 static unsigned long count;
115 jecr_u.i = jem->jecr;
117 jam_printf("[%lu]: Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
118 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
119 count++, jem->trap_pc, ctx->ostack, jecr_u.s.opcode,
120 jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
122 for (i = 0; i < jem->josp; i++) {
123 uint32_t v;
124 if (ostack_read_u32(ctx->frame->ostack, ctx->ostack, i, &v) >= 0)
125 jam_printf("\tToS-%d: 0x%x\n", i, v);
127 #endif
128 return 1;
132 static int jem_throwException(struct intrp_ctx *ctx)
134 struct jem_state *jem = &ctx->jem;
135 ExecEnv *ee = ctx->ee;
136 Object *excep = ee->exception;
137 ee->exception = NULL;
139 jem->jpc = (unsigned long)findCatchBlock(excep->class);
140 jam_dprintf("Found exception handler at 0x%08x\n", jem->jpc);
142 /* If we didn't find a handler, restore exception and
143 return to previous invocation */
145 if (!jem->jpc) {
146 ee->exception = excep;
147 /* Original code had a "return NULL" here, which means, end of
148 * executeJava */
149 return JEM_TRAP_HANDLER_FINISH;
152 /* If we're handling a stack overflow, reduce the stack
153 back past the red zone to enable handling of further
154 overflows */
156 if (ee->overflow) {
157 ee->overflow = FALSE;
158 ee->stack_end -= STACK_RED_ZONE_SIZE;
161 /* Setup intepreter to run the found catch block */
163 ctx->frame = ee->last_frame;
164 ctx->mb = ctx->frame->mb;
165 ctx->ostack = ctx->frame->ostack;
166 ctx->lvars_jem = ctx->frame->lvars_jem ? ctx->frame->lvars_jem - 1 : NULL;
167 if (ctx->lvars_jem) {
168 uintptr_t *aobj = (uintptr_t *)*ctx->lvars_jem;
169 ctx->this = JAM_OBJECT(aobj);
170 } else
171 ctx->this = NULL;
172 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
174 /* FIXME: don't know if this is correct, depends how we implement
175 * exceptions */
176 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uint32_t)excep);
178 /* Dispatch to the first bytecode */
179 return 0;
182 static int opc_return(struct intrp_ctx *ctx)
184 ExecEnv *ee = ctx->ee;
186 /* Set interpreter state to previous frame */
187 if (ctx->frame->prev->mb == NULL) {
188 /* The previous frame is a dummy frame - this indicates
189 * top of this Java invocation. */
190 return 1;
193 ctx->frame = ctx->frame->prev;
195 if (ctx->mb->access_flags & ACC_SYNCHRONIZED) {
196 Object *sync_ob = ctx->mb->access_flags & ACC_STATIC ? (Object*)ctx->mb->class : ctx->this;
197 objectUnlock(sync_ob);
200 ctx->ostack = ctx->lvars_jem - ctx->mb->max_locals + 1 - ctx->mb->args_count;
201 ctx->mb = ctx->frame->mb;
202 ctx->lvars_jem = ctx->frame->lvars_jem ? ctx->frame->lvars_jem - 1 : 0;
203 if (ctx->lvars_jem) {
204 uintptr_t *aobj = (uintptr_t *)*ctx->lvars_jem;
205 ctx->this = JAM_OBJECT(aobj);
206 } else
207 ctx->this = NULL;
208 ctx->jem.jpc = (uint32_t)ctx->frame->last_pc;
209 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
210 jam_dprintf("[OPC_RETURN] ostack : %08x, lvars_jem :%08x this %08x\n",
211 ctx->ostack, ctx->lvars_jem, ctx->this);
213 /* Pop frame */
214 ee->last_frame = ctx->frame;
216 return 0;
219 static int invokeMethod(struct intrp_ctx *ctx)
221 ExecEnv *ee = ctx->ee;
222 /* Seems like the original jamvm reused top of caller's stack for callee's
223 * local variables for passing of method arguments. Our stack and
224 * local variables grow in opposite directions now, so, this is impossible.
225 * ctx->ostack points at the beginning of the free space above ostack.
227 Frame *new_frame = (Frame *)(ctx->ostack + ctx->new_mb->max_locals);
228 Object *sync_ob = NULL;
229 int i;
230 uintptr_t *aobj;
232 jam_dprintf("[invokeMethod] with args count %d\n", ctx->new_mb->args_count);
233 jam_dprintf("[invokeMethod] new frame start %x\n", new_frame);
235 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
236 ctx->ostack = (uintptr_t *)(new_frame + 1);
238 if (ostack_overflows(ctx->ostack, ctx->new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
239 if (ee->overflow++) {
240 /* Overflow when we're already throwing stack overflow.
241 Stack extension should be enough to throw exception,
242 so something's seriously gone wrong - abort the VM! */
243 jam_printf("Fatal stack overflow! Aborting VM.\n");
244 exitVM(1);
246 ee->stack_end += STACK_RED_ZONE_SIZE;
247 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
250 //TODO
251 new_frame->mb = ctx->new_mb;
252 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
253 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
254 // Here still not touch the java stack, allocate lvars_jem from native heap
256 new_frame->lvars_jem = (uintptr_t *)new_frame;
258 if (ctx->new_mb->max_locals > 0) {
260 for (i = 0; i < ctx->new_mb->args_count; i++) {
261 *(new_frame->lvars_jem - 1 - i) = *(ctx->arg1 + i);
262 jam_dprintf("arg[%d] = 0x%x@%p\n", i, *(ctx->arg1 + i), ctx->arg1 + i);
265 jam_dprintf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame->lvars_jem);
267 new_frame->ostack = ctx->ostack;
268 new_frame->prev = ctx->frame;
270 ee->last_frame = new_frame;
272 if (ctx->new_mb->access_flags & ACC_SYNCHRONIZED) {
273 aobj = (uintptr_t *)*ctx->arg1;
274 sync_ob = ctx->new_mb->access_flags & ACC_STATIC ?
275 (Object*)ctx->new_mb->class : JAM_OBJECT(aobj);
276 objectLock(sync_ob);
279 if (ctx->new_mb->access_flags & ACC_NATIVE) {
280 //FIXME: the object references in JEM are direct pointer to instance variables.
281 // While JamVM requires object references as pointers to Object type.
282 jam_dprintf("[invokeMethod] invoke native method\n");
283 ctx->ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
284 ctx->new_mb->native_invoker)(ctx->new_mb->class, ctx->new_mb, ctx->arg1);
286 if (sync_ob)
287 objectUnlock(sync_ob);
289 ee->last_frame = ctx->frame;
291 if (exceptionOccured0(ee)) {
292 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
293 return jem_throwException(ctx);
296 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
297 } else {
298 ctx->frame = new_frame;
299 ctx->mb = ctx->new_mb;
300 ctx->lvars_jem = new_frame->lvars_jem ? new_frame->lvars_jem - 1 : NULL;
302 if (ctx->lvars_jem) {
303 aobj = (uintptr_t *)*ctx->lvars_jem;
304 ctx->this = JAM_OBJECT(aobj);
305 } else
306 ctx->this = NULL;
308 ctx->jem.jpc = (unsigned long)ctx->mb->code & ~3;
309 ctx->cp = &(CLASS_CB(ctx->mb->class)->constant_pool);
311 jam_dprintf("[invokeMethod] invoke virtual method: frame %x mb %x "
312 "lvars %x jpc %x cp %x\n", ctx->frame, ctx->mb,
313 ctx->lvars_jem, ctx->jem.jpc, ctx->cp);
314 jam_dprintf("[invokeMethod] finish virtual method invoke, return to loop\n");
317 return 0;
320 static int opc_invokesuper_quick(struct intrp_ctx *ctx)
322 struct jem_state *jem = &ctx->jem;
323 Operand *operand = &jem->operand;
325 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
326 ctx->new_mb = CLASS_CB(CLASS_CB(ctx->mb->class)->super)->method_table[operand->i];
327 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx->new_mb->args_count);
329 // set up jem operand stack
330 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
331 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
332 JEM_NULL_POINTER_CHECK(*ctx->arg1);
333 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx->arg1);
334 return invokeMethod(ctx);
337 static int opc_invokenonvirtual_quick(struct intrp_ctx *ctx)
339 struct jem_state *jem = &ctx->jem;
340 Operand *operand = &jem->operand;
342 ctx->new_mb = (MethodBlock*)operand->pntr;
343 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
344 __func__, ctx->new_mb->name, ctx->new_mb, ctx->new_mb->args_count);
345 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
346 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
348 jam_dprintf("[%s] ctx->arg1 %x\n", __func__, *ctx->arg1);
349 JEM_NULL_POINTER_CHECK(*ctx->arg1);
350 return invokeMethod(ctx);
353 static int opc_invokevirtual_quick(struct intrp_ctx *ctx)
355 struct jem_state *jem = &ctx->jem;
356 Object *obj;
357 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
358 ctx->ostack - ctx->frame->ostack - INV_QUICK_ARGS(jem));
359 JEM_NULL_POINTER_CHECK(*ctx->arg1);
360 Class *new_class;
362 //in case of "AALOAD" loads JAM obj from reference array
363 obj = (Object *)*ctx->arg1;
364 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj))
365 obj = JAM_OBJECT((uintptr_t *)obj);
367 //we should ensure ostack constains no JAM object
368 *ctx->arg1 = (uintptr_t)INST_DATA(obj);
370 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object 0x%08x (0x%08x)\n", obj, ctx->arg1);
371 new_class = obj->class;
372 ctx->new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(jem)];
373 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x on class %x\n",
374 ctx->new_mb, new_class);
375 return invokeMethod(ctx);
378 static int opc_invokevirtual(struct intrp_ctx *ctx)
380 int idx;
381 ExecEnv *ee = ctx->ee;
382 struct jem_state *jem = &ctx->jem;
384 idx = jem->jecr & 0xffff;
385 ctx->frame->last_pc = (CodePntr)jem->jpc;
386 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
388 if (exceptionOccured0(ee))
389 return jem_throwException(ctx);
391 jem->operand.uu.u1 = ctx->new_mb->args_count;
392 jem->operand.uu.u2 = ctx->new_mb->method_table_index;
394 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
395 ctx->new_mb,ctx->new_mb->args_count);
397 return opc_invokevirtual_quick(ctx);
400 static int opc_invokespecial(struct intrp_ctx *ctx)
402 int idx;
403 struct jem_state *jem = &ctx->jem;
404 Operand *operand = &jem->operand;
405 ExecEnv *ee = ctx->ee;
407 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
408 idx = jem->jecr & 0xffff;
410 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx);
412 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
414 if (exceptionOccured0(ee))
415 return jem_throwException(ctx);
417 jam_dprintf("Resolved %s\n", ctx->new_mb->name);
419 /* Check if invoking a super method... */
420 if ((CLASS_CB(ctx->mb->class)->access_flags & ACC_SUPER) &&
421 ((ctx->new_mb->access_flags & ACC_PRIVATE) == 0) && (ctx->new_mb->name[0] != '<')) {
423 operand->i = ctx->new_mb->method_table_index;
424 return opc_invokesuper_quick(ctx);
425 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
426 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
427 #endif
428 } else {
429 operand->pntr = ctx->new_mb;
430 return opc_invokenonvirtual_quick(ctx);
433 return 0;
436 static int opc_invokestatic_quick(struct intrp_ctx *ctx)
438 struct jem_state *jem = &ctx->jem;
440 ctx->new_mb = RESOLVED_METHOD(jem);
441 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
442 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
443 return invokeMethod(ctx);
446 static int opc_invokestatic(struct intrp_ctx *ctx)
448 int idx, cache;
449 struct jem_state *jem = &ctx->jem;
450 Operand *operand = &jem->operand;
451 ExecEnv *ee = ctx->ee;
453 idx = jem->jecr & 0xffff;
455 ctx->frame->last_pc = (CodePntr)jem->jpc;
456 ctx->new_mb = resolveMethod(ctx->mb->class, idx);
458 if (exceptionOccured0(ee))
459 return jem_throwException(ctx);
461 operand->pntr = ctx->new_mb;
462 return opc_invokestatic_quick(ctx);
465 static int opc_new_quick(struct intrp_ctx *ctx)
467 struct jem_state *jem = &ctx->jem;
468 Operand *operand = &jem->operand;
469 Class *class = (Class*)CP_INFO(ctx->cp, operand->uui.u1);
470 Object *obj;
472 ctx->frame->last_pc = (CodePntr)jem->jpc;
473 if ((obj = allocObject(class)) == NULL)
474 return jem_throwException(ctx);
475 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj);
476 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
477 (uint32_t)INST_DATA(obj));
480 static int opc_new(struct intrp_ctx *ctx)
482 struct jem_state *jem = &ctx->jem;
483 Operand *operand = &jem->operand;
484 int idx = operand->uui.u1 = jem->jecr & 0xffff;
485 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
486 Class *class;
487 ExecEnv *ee = ctx->ee;
489 jam_dprintf("[OPC_NEW] opcode: %x\n", opcode);
491 ctx->frame->last_pc = (CodePntr)jem->jpc;
492 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
493 if (exceptionOccured0(ee))
494 return jem_throwException(ctx);
496 if (opcode == OPC_NEW) {
497 ClassBlock *cb = CLASS_CB(class);
498 if (cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
499 signalException("java/lang/InstantiationError", cb->name);
500 return jem_throwException(ctx);
502 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
503 jem_opcode_rewrite(0xDD, (char*)jem->jpc - 3, 0);
506 return opc_new_quick(ctx);
509 static int opc_anewarray_quick(struct intrp_ctx *ctx)
511 struct jem_state *jem = &ctx->jem;
512 ConstantPool *cp = ctx->cp;
513 Class *class = RESOLVED_CLASS(jem);
514 char *name = CLASS_CB(class)->name;
515 int count;
516 Class *array_class;
517 char *ac_name;
518 Object *obj;
519 ExecEnv *ee = ctx->ee;
521 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
522 ctx->frame->last_pc = (CodePntr)jem->jpc;
524 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name, count);
525 if (count < 0) {
526 signalException("java/lang/NegativeArraySizeException", NULL);
527 return jem_throwException(ctx);
530 ac_name = sysMalloc(strlen(name) + 4);
532 if (name[0] == '[')
533 sprintf(ac_name, "[%s", name);
534 else
535 sprintf(ac_name, "[L%s;", name);
537 array_class = findArrayClassFromClass(ac_name, ctx->mb->class);
538 free(ac_name);
540 if (exceptionOccured0(ee))
541 return jem_throwException(ctx);
543 if ((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
544 return jem_throwException(ctx);
546 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
547 (uint32_t)ARRAY_DATA(obj));
550 static int opc_anewarray(struct intrp_ctx *ctx)
552 struct jem_state *jem = &ctx->jem;
553 Operand *operand = &jem->operand;
554 int idx = operand->uui.u1 = jem->jecr & 0xffff;
555 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
556 Class *class;
557 ExecEnv *ee = ctx->ee;
559 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
561 ctx->frame->last_pc = (CodePntr)jem->jpc;
562 //resolve the array class
563 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
565 if (exceptionOccured0(ee))
566 return jem_throwException(ctx);
568 return opc_anewarray_quick(ctx);
571 static int opc_multianewarray_quick(struct intrp_ctx *ctx)
573 struct jem_state *jem = &ctx->jem;
574 ConstantPool *cp = ctx->cp;
575 Class *class = RESOLVED_CLASS(jem);
576 int i, dim = MULTI_ARRAY_DIM(jem);
577 int count;
578 Object *obj;
579 ExecEnv *ee = ctx->ee;
581 ctx->frame->last_pc = (CodePntr)jem->jpc;
583 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim, CLASS_CB(class)->name);
584 for (i = 0; i < dim; i++) {
585 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
586 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count, i);
587 if (count < 0) {
588 signalException("java/lang/NegativeArraySizeException", NULL);
589 return jem_throwException(ctx);
593 /* counts are still stored in ostack even after we did pop them out */
594 if ((obj = allocMultiArray(class, dim, (intptr_t *)ctx->ostack)) == NULL)
595 return jem_throwException(ctx);
597 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
598 (uint32_t)ARRAY_DATA(obj));
601 static int opc_multianewarray(struct intrp_ctx *ctx)
603 struct jem_state *jem = &ctx->jem;
604 Operand *operand = &jem->operand;
605 int idx = operand->uui.u1 = jem->jecr & 0xffff;
607 Class *class;
608 ExecEnv *ee = ctx->ee;
610 /* dimensions */
611 operand->uui.u2 = *(unsigned char*)jem->jpc;
612 jem->jpc++; /* skip dims */
614 ctx->frame->last_pc = (CodePntr)jem->jpc;
615 /* resolve the array class */
616 class = resolveClass(ctx->mb->class, idx, FALSE);
618 if (exceptionOccured0(ee))
619 return jem_throwException(ctx);
621 return opc_multianewarray_quick(ctx);
624 static int opc_newarray(struct intrp_ctx *ctx)
626 struct jem_state *jem = &ctx->jem;
627 int type = (jem->jecr >> 8) & 0xff;
628 int count;
629 Object *obj;
631 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, count);
632 ctx->frame->last_pc = (CodePntr)jem->jpc;
634 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type, count);
635 if ((obj = allocTypeArray(type, count)) == NULL)
636 return jem_throwException(ctx);
638 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
639 (uint32_t)ARRAY_DATA(obj));
642 static int opc_putfield_quick(struct intrp_ctx *ctx)
644 uint32_t arg;
645 uint32_t obj;
646 struct jem_state *jem = &ctx->jem;
648 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
649 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
650 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg,
651 SINGLE_INDEX(jem), obj);
653 JEM_NULL_POINTER_CHECK(obj);
655 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
656 obj = (uint32_t)INST_DATA((Object *)obj);
658 ((uint32_t*)obj)[SINGLE_INDEX(jem)] = arg;
660 return 0;
663 static int opc_putfield2_quick(struct intrp_ctx *ctx)
665 uint64_t arg;
666 uint32_t obj;
667 struct jem_state *jem = &ctx->jem;
669 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
670 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
672 JEM_NULL_POINTER_CHECK((uintptr_t*)obj);
674 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
675 obj = (uint32_t)INST_DATA((Object *)obj);
677 *(uint64_t *)&(((uint32_t*)obj)[SINGLE_INDEX(jem)]) = arg;
678 jam_dprintf("[OPC_PUTFIELD2_QUICK] put 64 bit %08x to obj %08x\n", arg, obj);
680 return 0;
683 static int opc_putfield_quick_jem0(struct intrp_ctx *ctx)
685 uint32_t arg;
686 uintptr_t *aobj;
687 struct jem_state *jem = &ctx->jem;
689 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
690 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
691 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg);
693 JEM_NULL_POINTER_CHECK(aobj);
695 if (JAM_ON_STACK && arg && !IS_JAM_OBJECT(arg))
696 arg = (uint32_t)JAM_OBJECT((uintptr_t *)arg);
698 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
699 aobj = INST_DATA((Object *)aobj);
701 aobj[SINGLE_INDEX(jem)] = arg;
702 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg,
703 SINGLE_INDEX(jem), aobj);
705 return 0;
708 static int opc_putfield_quick_jem1(struct intrp_ctx *ctx)
710 uintptr_t *aobj, *arg;
711 struct jem_state *jem = &ctx->jem;
713 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, arg);
714 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
715 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg);
717 if (JAM_ON_STACK && arg && !IS_JAM_ARRAY(arg))
718 arg = (uintptr_t *)JAM_ARRAY(arg);
720 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
721 aobj = INST_DATA((Object *)aobj);
723 JEM_NULL_POINTER_CHECK(aobj);
724 aobj[SINGLE_INDEX(jem)] = (uintptr_t)arg;
725 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg,
726 SINGLE_INDEX(jem), aobj);
728 return 0;
731 static int opc_putfield(struct intrp_ctx *ctx)
733 struct jem_state *jem = &ctx->jem;
734 int idx = jem->jecr & 0xffff;
735 FieldBlock *fb;
736 ExecEnv *ee = ctx->ee;
738 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx);
740 ctx->frame->last_pc = (CodePntr)jem->jpc;
741 fb = resolveField(ctx->mb->class, idx);
742 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
744 if (exceptionOccured0(ee))
745 return jem_throwException(ctx);
747 jem->operand.i = fb->offset;
748 switch (*fb->type) {
749 case 'J':
750 case 'D':
751 /* rewrite opc_putfield to opc_putfield2_quick */
752 jem_opcode_rewrite(0xD1, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
753 return opc_putfield2_quick(ctx);
754 case 'L':
755 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
756 return opc_putfield_quick_jem0(ctx);
757 case '[':
758 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
759 return opc_putfield_quick_jem1(ctx);
760 default:
761 jem_opcode_rewrite(0xCF, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
762 return opc_putfield_quick(ctx);
766 static int opc_getfield2_quick(struct intrp_ctx *ctx)
768 uint32_t *obj;
769 struct jem_state *jem = &ctx->jem;
770 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
771 JEM_NULL_POINTER_CHECK(obj);
773 if (JAM_ON_STACK && IS_JAM_OBJECT(obj))
774 obj = (uint32_t*)INST_DATA((Object*)obj);
776 jam_dprintf("[OPC_GETFIELD2_QUICK] get 64 bit field %08x from obj %08x\n",
777 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])), obj);
779 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
780 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])));
783 static int opc_getfield_quick(struct intrp_ctx *ctx)
785 uintptr_t *aobj;
786 struct jem_state *jem = &ctx->jem;
788 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
789 JEM_NULL_POINTER_CHECK(aobj);
791 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
792 aobj = (uint32_t*)INST_DATA((Object*)aobj);
794 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
795 aobj[SINGLE_INDEX(jem)], aobj);
796 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
797 aobj[SINGLE_INDEX(jem)]);
800 static int opc_getfield_quick_jem0(struct intrp_ctx *ctx)
802 uint32_t *aobj;
803 struct jem_state *jem = &ctx->jem;
804 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
805 JEM_NULL_POINTER_CHECK(aobj);
807 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
808 aobj = (uint32_t*)INST_DATA((Object*)aobj);
810 uint32_t value = aobj[SINGLE_INDEX(jem)];
811 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj ref %x\n", value);
812 if (value) {
813 Object *ref = (Object*)value;
814 if (JAM_ON_STACK && IS_JAM_OBJECT(ref))
815 //jamvm objref
816 value = (uint32_t)INST_DATA(ref);
818 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value);
819 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
823 static int opc_getfield_quick_jem1(struct intrp_ctx *ctx)
825 uint32_t *aobj;
826 struct jem_state *jem = &ctx->jem;
828 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
829 JEM_NULL_POINTER_CHECK(aobj);
831 //"aaload" would put jamvm obj ref onto the ostack
832 if (JAM_ON_STACK && IS_JAM_OBJECT(aobj))
833 aobj = (uint32_t*)INST_DATA((Object*)aobj);
835 uint32_t value = aobj[SINGLE_INDEX(jem)];
836 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value);
837 if (value) {
838 Object *ref = (Object*)value;
839 if (JAM_ON_STACK && IS_JAM_ARRAY(ref))
840 value = (uint32_t)ARRAY_DATA(ref);
842 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value);
843 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
846 static int opc_getfield(struct intrp_ctx *ctx)
848 struct jem_state *jem = &ctx->jem;
849 int idx = jem->jecr & 0xffff;
850 FieldBlock *fb;
851 ExecEnv *ee = ctx->ee;
853 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx);
855 ctx->frame->last_pc = (CodePntr)jem->jpc;
856 fb = resolveField(ctx->mb->class, idx);
857 jam_dprintf("[OPC_GETFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
859 if (exceptionOccured0(ee))
860 return jem_throwException(ctx);
862 jem->operand.i = fb->offset;
863 switch (*fb->type) {
864 case 'J':
865 case 'D':
866 jem_opcode_rewrite(0xD0, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
867 return opc_getfield2_quick(ctx);
869 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
870 * in case of some JNI code will set field natively, we still handle it
871 * separately here.
873 case 'L':
874 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
875 return opc_getfield_quick_jem0(ctx);
876 case '[':
877 jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, fb->offset >> 8, fb->offset);
878 return opc_getfield_quick_jem1(ctx);
879 default:
880 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
881 return opc_getfield_quick(ctx);
885 static int opc_ldc_w_quick_jem(struct intrp_ctx *ctx)
887 struct jem_state *jem = &ctx->jem;
888 //CONSTANT_Class and CONSTANT_String are stored as object reference
889 Object *cp_info = (Object*)CP_INFO(ctx->cp, DOUBLE_INDEX(jem));
890 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info);
891 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
892 (uint32_t)INST_DATA(cp_info));
895 static int opc_ldc_w_quick(struct intrp_ctx *ctx)
897 struct jem_state *jem = &ctx->jem;
898 uint32_t cp_info = CP_INFO(ctx->cp, DOUBLE_INDEX(jem));
899 jam_dprintf("[OPC_LDC_W_QUICK] push constant %08x to stack\n", cp_info);
900 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, cp_info);
903 static int opc_ldc_quick(struct intrp_ctx *ctx)
905 struct jem_state *jem = &ctx->jem;
906 uint32_t constant = RESOLVED_CONSTANT(jem);
907 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant);
908 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, (uintptr_t)constant);
911 static int opc_ldc_common(struct intrp_ctx *ctx, int idx)
913 struct jem_state *jem = &ctx->jem;
914 ExecEnv *ee = ctx->ee;
915 ctx->frame->last_pc = (CodePntr)jem->jpc;
917 jem->operand.u = resolveSingleConstant(ctx->mb->class, idx);
919 if (exceptionOccured0(ee))
920 return jem_throwException(ctx);
922 if (CP_TYPE(ctx->cp, idx) == CONSTANT_ResolvedClass) {
923 jem->operand.i = idx;
924 jem_opcode_rewrite(0xCC, (char*)jem->jpc - 3, 0);
925 return opc_ldc_w_quick(ctx);
926 } else if (CP_TYPE(ctx->cp, idx) == CONSTANT_ResolvedString) {
927 jem->operand.i = idx;
928 return opc_ldc_w_quick_jem(ctx);
929 } else {
930 jem_opcode_rewrite(0xCB, (char*)jem->jpc - 2, 0);
931 return opc_ldc_quick(ctx);
935 static int opc_ldc(struct intrp_ctx *ctx)
937 int idx;
938 ExecEnv *ee = ctx->ee;
939 struct jem_state *jem = &ctx->jem;
941 idx = (jem->jecr & 0xff00) >> 8;
943 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx);
944 return opc_ldc_common(ctx, idx);
947 static int opc_ldc_w(struct intrp_ctx *ctx)
949 int idx;
950 ExecEnv *ee = ctx->ee;
951 struct jem_state *jem = &ctx->jem;
953 idx = (jem->jecr & 0xffff);
955 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx);
956 return opc_ldc_common(ctx, idx);
959 static int opc_monitorenter(struct intrp_ctx *ctx)
961 Object *obj;
962 uintptr_t *ptr;
963 struct jem_state *jem = &ctx->jem;
964 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
966 obj = JAM_OBJECT(ptr);
967 if (!IS_OBJECT(obj))
968 /* is an array ref */
969 obj = JAM_ARRAY(ptr);
970 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj);
971 JEM_NULL_POINTER_CHECK(obj);
972 objectLock(obj);
973 return 0;
976 static int opc_monitorexit(struct intrp_ctx *ctx)
978 Object *obj;
979 uintptr_t *ptr;
980 struct jem_state *jem = &ctx->jem;
981 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
983 obj = JAM_OBJECT(ptr);
984 if (!IS_OBJECT(obj))
985 /* is an array ref */
986 obj = JAM_ARRAY(ptr);
987 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj);
988 JEM_NULL_POINTER_CHECK(obj);
989 objectUnlock(obj);
990 return 0;
993 static int opc_getstatic_quick(struct intrp_ctx *ctx)
995 struct jem_state *jem = &ctx->jem;
996 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
997 RESOLVED_FIELD(jem)->static_value);
1000 static int opc_getstatic2_quick(struct intrp_ctx *ctx)
1002 struct jem_state *jem = &ctx->jem;
1003 return ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1004 RESOLVED_FIELD(jem)->static_value);
1007 static int opc_getstatic_quick_jem0(struct intrp_ctx *ctx)
1009 struct jem_state *jem = &ctx->jem;
1010 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1012 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value);
1013 if (value) {
1014 Object *ref = (Object *)value;
1015 if (!JAM_ON_STACK || IS_JAM_OBJECT(ref))
1016 //jamvm objref
1017 value = (uintptr_t)INST_DATA(ref);
1019 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value);
1020 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1023 static int opc_getstatic_quick_jem1(struct intrp_ctx *ctx)
1025 struct jem_state *jem = &ctx->jem;
1026 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
1027 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value);
1028 if (value) {
1029 Object *ref = (Object*)value;
1030 if (!JAM_ON_STACK || IS_JAM_ARRAY(ref))
1031 //jamvm arrayref
1032 value = (uintptr_t)ARRAY_DATA(ref);
1034 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value);
1035 return ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1038 static int opc_getstatic(struct intrp_ctx *ctx)
1040 int idx;
1041 FieldBlock *fb;
1042 Operand operand;
1043 ExecEnv *ee = ctx->ee;
1044 struct jem_state *jem = &ctx->jem;
1046 idx = (int)(jem->jecr & 0xffff);
1047 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx,CLASS_CB(ctx->mb->class)->name);
1049 ctx->frame->last_pc = (CodePntr)jem->jpc;
1050 fb = resolveField(ctx->mb->class, idx);
1052 if (exceptionOccured0(ee))
1053 return jem_throwException(ctx);
1055 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb, *fb->type);
1056 jem->operand.pntr = fb;
1057 switch (*fb->type) {
1058 case 'J':
1059 case 'D':
1060 return opc_getstatic2_quick(ctx);
1062 * see opc_getfield
1064 case 'L':
1065 return opc_getstatic_quick_jem0(ctx);
1066 case '[':
1067 return opc_getstatic_quick_jem1(ctx);
1068 default:
1069 return opc_getstatic_quick(ctx);
1073 static int opc_putstatic2_quick(struct intrp_ctx *ctx)
1075 struct jem_state *jem = &ctx->jem;
1076 return ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1077 *(u8*)&RESOLVED_FIELD(jem)->static_value);
1080 static int opc_putstatic_quick(struct intrp_ctx *ctx)
1082 struct jem_state *jem = &ctx->jem;
1083 return ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,
1084 RESOLVED_FIELD(jem)->static_value);
1087 static int opc_putstatic_quick_jem0(struct intrp_ctx *ctx)
1089 uintptr_t value;
1090 struct jem_state *jem = &ctx->jem;
1091 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1093 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value);
1094 if (value && (!JAM_ON_STACK || !IS_JAM_OBJECT(value)))
1095 value = (uintptr_t)JAM_OBJECT((uintptr_t *)value);
1096 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value);
1097 RESOLVED_FIELD(jem)->static_value = value;
1098 return 0;
1101 static int opc_putstatic_quick_jem1(struct intrp_ctx *ctx)
1103 uintptr_t *value;
1104 struct jem_state *jem = &ctx->jem;
1105 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1107 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value);
1108 if (value && (!JAM_ON_STACK || !IS_JAM_ARRAY(value)))
1109 value = (uintptr_t*)JAM_ARRAY(value);
1110 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value);
1111 RESOLVED_FIELD(jem)->static_value = (uintptr_t)value;
1112 return 0;
1115 static int opc_putstatic(struct intrp_ctx *ctx)
1117 int idx;
1118 FieldBlock *fb;
1119 Operand operand;
1120 ExecEnv *ee = ctx->ee;
1121 struct jem_state *jem = &ctx->jem;
1123 idx = (int)(jem->jecr & 0xffff);
1125 ctx->frame->last_pc = (CodePntr)jem->jpc;
1126 fb = resolveField(ctx->mb->class, idx);
1128 if (exceptionOccured0(ee))
1129 return jem_throwException(ctx);
1131 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb, *fb->type);
1132 jem->operand.pntr = fb;
1133 switch (*fb->type) {
1134 case 'J':
1135 case 'D':
1136 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1137 return opc_putstatic2_quick(ctx);
1138 case 'L':
1139 return opc_putstatic_quick_jem0(ctx);
1140 case '[':
1141 return opc_putstatic_quick_jem1(ctx);
1142 default:
1143 return opc_putstatic_quick(ctx);
1147 static int opc_checkcast_quick(struct intrp_ctx *ctx)
1149 struct jem_state *jem = &ctx->jem;
1150 ConstantPool *cp = ctx->cp;
1151 Class *class = RESOLVED_CLASS(jem);
1152 Object *obj;
1153 uintptr_t *ptr;
1155 ostack_read_u32(ctx->frame->ostack, ctx->ostack, 0, &ptr);
1156 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr, CLASS_CB(class)->name);
1157 if (ptr != NULL) {
1158 #warning Does not look right!
1159 if (!JAM_ON_STACK || !IS_JAM_OBJECT(ptr) || !IS_JAM_ARRAY(ptr)) {
1160 obj = JAM_OBJECT(ptr);
1161 if (!IS_OBJECT(obj)) {
1162 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1163 //should be array ref
1164 obj = JAM_ARRAY(ptr);
1166 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj);
1167 } else {
1168 obj = (Object*)ptr;
1170 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %s for obj(%s)\n", CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
1171 if ((obj != NULL) && !isInstanceOf(class, obj->class))
1172 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
1175 return 0;
1178 static int opc_checkcast(struct intrp_ctx *ctx)
1180 struct jem_state *jem = &ctx->jem;
1181 Operand *operand = &jem->operand;
1182 int idx = operand->uui.u1 = jem->jecr & 0xffff;
1183 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
1184 Class *class;
1185 ExecEnv *ee = ctx->ee;
1187 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
1189 ctx->frame->last_pc = (CodePntr)jem->jpc;
1190 //resolve the cast class
1191 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
1193 if (exceptionOccured0(ee))
1194 return jem_throwException(ctx);
1196 return opc_checkcast_quick(ctx);
1199 static int opc_invokeinterface_quick(struct intrp_ctx *ctx)
1201 int mtbl_idx;
1202 ClassBlock *cb;
1203 Object *objref;
1204 int cache = ctx->jem.operand.uu.u2;
1206 ctx->new_mb = (MethodBlock *)CP_INFO(ctx->cp, ctx->jem.operand.uu.u1);
1207 ctx->arg1 = ostack_address(ctx->frame->ostack, ctx->mb->max_stack,
1208 ctx->ostack - ctx->frame->ostack - ctx->new_mb->args_count);
1210 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1211 ctx->new_mb, ctx->new_mb->name, ctx->new_mb->args_count, ctx->arg1);
1213 objref = (Object *)*ctx->arg1;
1214 #warning Does not look right!
1215 if (!JAM_ON_STACK || !IS_JAM_OBJECT(objref) || !IS_JAM_ARRAY(objref)) {
1216 objref = JAM_OBJECT((uintptr_t *)objref);
1217 if (!IS_OBJECT(objref))
1218 objref = JAM_ARRAY((uintptr_t *)*ctx->arg1);
1219 } else {
1220 //turn type in the stack to JEM type ref
1221 *ctx->arg1 = (uintptr_t)INST_DATA(objref);
1223 JEM_NULL_POINTER_CHECK(objref);
1225 cb = CLASS_CB(objref->class);
1227 if ((cache >= cb->imethod_table_size) ||
1228 (ctx->new_mb->class != cb->imethod_table[cache].interface)) {
1229 for (cache = 0; (cache < cb->imethod_table_size) &&
1230 (ctx->new_mb->class != cb->imethod_table[cache].interface); cache++);
1232 if (cache == cb->imethod_table_size)
1233 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1234 "unimplemented interface");
1237 mtbl_idx = cb->imethod_table[cache].offsets[ctx->new_mb->method_table_index];
1238 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx);
1239 ctx->new_mb = cb->method_table[mtbl_idx];
1240 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx);
1241 return invokeMethod(ctx);
1244 static int opc_invokeinterface(struct intrp_ctx *ctx)
1246 struct jem_state *jem = &ctx->jem;
1247 Operand *operand = &jem->operand;
1248 ExecEnv *ee = ctx->ee;
1250 int idx = operand->uu.u1 = jem->jecr & 0xffff;
1251 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1252 * For JEM, two index bytes has been processed before trap,
1253 * so offset jpc 4 operands for next opcode
1254 *FIXME: ? not know why JEM does not handle this */
1255 ctx->frame->last_pc = (CodePntr)(jem->jpc += 2);
1256 ctx-> new_mb = resolveInterfaceMethod(ctx->mb->class, idx);
1258 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx);
1259 if (exceptionOccured0(ee))
1260 return jem_throwException(ctx);
1262 if (CLASS_CB(ctx->new_mb->class)->access_flags & ACC_INTERFACE) {
1263 operand->uu.u2 = 0;
1264 return opc_invokeinterface_quick(ctx);
1265 } else {
1266 operand->uu.u1 = ctx->new_mb->args_count;
1267 operand->uu.u2 = ctx->new_mb->method_table_index;
1268 return opc_invokevirtual_quick(ctx);
1272 static int opc_instanceof_quick(struct intrp_ctx *ctx)
1274 struct jem_state *jem = &ctx->jem;
1275 ConstantPool *cp = ctx->cp;
1276 Class *class = RESOLVED_CLASS(jem);
1277 Object *obj;
1278 uintptr_t *ptr;
1280 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ptr);
1281 if (ptr != NULL) {
1282 obj = JAM_OBJECT(ptr);
1283 if (!IS_OBJECT(obj)) {
1284 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1285 //should be array ref
1286 obj = JAM_ARRAY(ptr);
1289 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n", CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
1290 if (obj != NULL)
1291 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack,isInstanceOf(class, obj->class));
1293 return 0;
1296 static int opc_instanceof(struct intrp_ctx *ctx)
1298 struct jem_state *jem = &ctx->jem;
1299 Operand *operand = &jem->operand;
1300 int idx = operand->uui.u1 = jem->jecr & 0xffff;
1301 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
1302 Class *class;
1303 ExecEnv *ee = ctx->ee;
1305 jam_dprintf("[OPC_INSTANCEOF] opcode : %x\n", opcode);
1307 ctx->frame->last_pc = (CodePntr)jem->jpc;
1308 //resolve the cast class
1309 class = resolveClass(ctx->mb->class, idx, opcode == OPC_NEW);
1311 if (exceptionOccured0(ee))
1312 return jem_throwException(ctx);
1314 return opc_instanceof_quick(ctx);
1317 static int opc_aastore(struct intrp_ctx *ctx)
1319 Object *obj;
1320 uintptr_t *aobj;
1321 int idx ;
1322 Object *array;
1324 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, aobj);
1325 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, idx);
1326 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, array);
1328 jam_dprintf("[OPC_AASTORE] obj %x, idx %x, array %x\n", aobj, idx, array);
1330 /* aobj does point to an object, but we do not know if that's an array or
1331 * not, and we need to know that for the arrayStoreCheck() check below */
1332 #warning Does not look right!
1333 if (aobj && (!JAM_ON_STACK || !IS_JAM_OBJECT(aobj) || !IS_JAM_ARRAY(aobj))) {
1334 if (!IS_OBJECT(JAM_OBJECT(aobj))) {
1335 //in case of storing an array to another array
1336 obj = JAM_ARRAY(aobj);
1337 } else {
1338 obj = JAM_OBJECT(aobj);
1340 } else
1341 obj = (Object *)aobj;
1342 array = JAM_ARRAY((uintptr_t *)array);
1344 jam_dprintf("[OPC_AASTORE] store obj ref %x to array %x in index %d\n", obj, array, idx);
1345 JEM_NULL_POINTER_CHECK(array);
1347 if (idx >= ARRAY_LEN(array)) {
1348 char buff[MAX_INT_DIGITS];
1349 snprintf(buff, MAX_INT_DIGITS, "%d", idx);
1350 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff);
1353 if ((obj != NULL) && !arrayStoreCheck(array->class, obj->class))
1354 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
1356 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1357 // the array to get the non jamvm refs to use, which then causes segfault.
1358 #if JAM_ON_STACK
1359 ((Object**)ARRAY_DATA(array))[idx] = obj;
1360 #else
1361 ((uintptr_t**)ARRAY_DATA(array))[idx] = aobj;
1362 #endif
1363 return 0;
1366 static int do_javaExceptions(struct intrp_ctx *ctx)
1368 union jecr jecr_u;
1369 struct jem_state *jem = &ctx->jem;
1371 /* deliberate segfault */
1372 /* *(int *)0 = 0; */
1374 jecr_u.i = jem->jecr;
1375 /* This should not happen, because we don't use the "Java Handle" (H)
1376 * bit in the Status Register and we set JBCR to 0x80000000 - still
1377 * it does happen, but seems to be harmless so far. Just ignore. */
1378 if (jecr_u.s.opcode == OPC_AASTORE)
1379 return opc_aastore(ctx);
1381 return 1;
1384 static int opc_afireturn(struct intrp_ctx *ctx)
1386 uint32_t val;
1387 int ret;
1388 struct jem_state *jem = &ctx->jem;
1390 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1392 jam_dprintf("[OPC_AFIRETURN] return %08x @ %p\n", val, ctx->lvars_jem);
1394 ret = opc_return(ctx);
1395 if (!ret)
1396 ret = ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1397 else
1398 *ctx->lvars_jem = val;
1400 return ret;
1403 static int opc_ldreturn(struct intrp_ctx *ctx)
1405 uint64_t val;
1406 int ret;
1408 struct jem_state *jem = &ctx->jem;
1409 ostack_pop_u64(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, val);
1411 jam_dprintf("[OPC_LDRETURN] return %lld\n", val);
1413 ret = opc_return(ctx);
1415 if (!ret)
1416 ret = ostack_push_u64(ctx->frame->ostack, ctx->mb->max_stack,
1417 ctx->ostack, val);
1418 else
1419 *(uint64_t*)ctx->lvars_jem = val;
1421 return ret;
1424 static int opc_fcmpg(struct intrp_ctx *ctx)
1426 float v1, v2;
1427 int res;
1428 struct jem_state *jem = &ctx->jem;
1429 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1430 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1431 if (v1 == v2)
1432 res = 0;
1433 else if (v1 < v2)
1434 res = -1;
1435 else if (v1 > v2)
1436 res = 1;
1437 else
1438 res = 1; /* isNaN */
1439 jam_dprintf("[OPC_FCMPG] result %d\n", res);
1440 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1441 return 0;
1444 static int opc_fcmpl(struct intrp_ctx *ctx)
1446 float v1, v2;
1447 int res;
1448 struct jem_state *jem = &ctx->jem;
1449 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1450 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1451 if (v1 == v2)
1452 res = 0;
1453 else if (v1 < v2)
1454 res = -1;
1455 else if (v1 > v2)
1456 res = 1;
1457 else
1458 res = -1;
1459 jam_dprintf("[OPC_FCMPL] result %d\n", res);
1460 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1461 return 0;
1464 static int opc_i2f(struct intrp_ctx *ctx)
1466 int i;
1467 struct jem_state *jem = &ctx->jem;
1468 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, i);
1470 float f = (float)i;
1471 jam_dprintf("[OPC_I2F] convert to %f\n", f);
1472 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, f);
1473 return 0;
1476 static int opc_i2d(struct intrp_ctx *ctx)
1478 return JEM_TRAP_HANDLER_FINISH;
1481 static int opc_fmul(struct intrp_ctx *ctx)
1483 float v1, v2;
1484 float ret;
1485 struct jem_state *jem = &ctx->jem;
1486 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1487 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1488 ret = v1 * v2;
1489 jam_dprintf("[OPC_FMUL] result %f\n", ret);
1490 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1491 return 0;
1494 static int opc_fadd(struct intrp_ctx *ctx)
1496 float v1, v2;
1497 float ret;
1498 struct jem_state *jem = &ctx->jem;
1499 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1500 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1501 ret = v1 + v2;
1502 jam_dprintf("[OPC_FADD] result %f\n", ret);
1503 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1504 return 0;
1507 static int opc_fsub(struct intrp_ctx *ctx)
1509 float v1, v2;
1510 float ret;
1511 struct jem_state *jem = &ctx->jem;
1512 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v2);
1513 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, v1);
1514 ret = v1 - v2;
1515 jam_dprintf("[OPC_FSUB] result %f\n", ret);
1516 ostack_push_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, ret);
1517 return 0;
1520 static int opc_f2i(struct intrp_ctx *ctx)
1522 int res;
1523 float value;
1524 struct jem_state *jem = &ctx->jem;
1525 ostack_pop_f32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, value);
1526 jam_dprintf("[OPC_F2I] float value %f\n", value);
1527 if (value >= (float)INT_MAX)
1528 res = INT_MAX;
1529 else if (value <= (float)INT_MIN)
1530 res = INT_MIN;
1531 else if (value != value)
1532 res = 0;
1533 else
1534 res = (int)value;
1535 jam_dprintf("[OPC_F2I] int value %d\n", res);
1536 ostack_push_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, res);
1537 return 0;
1540 static int opc_iinc(struct intrp_ctx *ctx)
1542 union jecr jecr_u;
1543 jecr_u.i = ctx->jem.jecr;
1544 int index = (int)jecr_u.s.op1;
1545 int con = (int)jecr_u.s.op2;
1546 uintptr_t *ptr = ctx->lvars_jem;
1548 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1549 con, ptr[-index], index, ctx->mb->max_locals);
1550 ptr[-index] = ptr[-index] + con;
1552 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr[-index]);
1553 return 0;
1556 static int opc_athrow(struct intrp_ctx *ctx)
1558 Object *obj;
1559 ostack_pop_u32(ctx->frame->ostack, ctx->mb->max_stack, ctx->ostack, obj);
1560 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc;
1561 ExecEnv *ee = ctx->ee;
1563 JEM_NULL_POINTER_CHECK(obj);
1565 if (!JAM_ON_STACK || !IS_JAM_OBJECT(obj))
1566 obj = JAM_OBJECT((uintptr_t *)obj);
1568 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj->class)->name);
1569 ee->exception = obj;
1570 return jem_throwException(ctx);
1573 static int do_stackOverflow(struct intrp_ctx *ctx)
1575 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1576 trap_debug(ctx);
1577 return 0;
1580 static int do_stackUnderflow(struct intrp_ctx *ctx)
1582 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1583 trap_debug(ctx);
1584 return 1;
1587 static int do_stackOverflow1(struct intrp_ctx *ctx)
1589 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1590 trap_debug(ctx);
1591 return 1;
1594 static int do_stackUnderflow1(struct intrp_ctx *ctx)
1596 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1597 trap_debug(ctx);
1598 return 1;
1601 static handler_fn *trap_handler_f[256] = {
1602 [OPC_INVOKEINTERFACE] = opc_invokeinterface,
1603 [OPC_INVOKESPECIAL] = opc_invokespecial,
1604 [OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick,
1605 [OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick,
1606 [OPC_INVOKEVIRTUAL] = opc_invokevirtual,
1607 [OPC_INVOKEVIRTUAL_QUICK] = opc_invokevirtual_quick,
1608 [OPC_INVOKESTATIC] = opc_invokestatic,
1609 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1610 [OPC_NEW] = opc_new,
1611 [0xDD] = opc_new, /* JEM: NEW_QUICK */
1612 [OPC_RETURN] = opc_return,
1613 [OPC_ARETURN] = opc_afireturn,
1614 [OPC_IRETURN] = opc_afireturn,
1615 [OPC_FRETURN] = opc_afireturn,
1616 [OPC_PUTFIELD] = opc_putfield,
1617 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1618 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1619 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1620 // [OPC_LDC_QUICK] = opc_ldc_quick,
1621 [OPC_LDC_W] = opc_ldc_w,
1622 [OPC_LDC] = opc_ldc,
1623 [OPC_MONITORENTER] = opc_monitorenter,
1624 [OPC_MONITOREXIT] = opc_monitorexit,
1625 [OPC_GETSTATIC] = opc_getstatic,
1626 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1627 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1628 [OPC_PUTSTATIC] = opc_putstatic,
1629 [OPC_PUTSTATIC_QUICK] = opc_putstatic_quick,
1630 [OPC_PUTSTATIC2_QUICK] = opc_putstatic2_quick,
1631 [OPC_ANEWARRAY] = opc_anewarray,
1632 [OPC_ANEWARRAY_QUICK] = opc_anewarray_quick,
1633 [OPC_MULTIANEWARRAY] = opc_multianewarray,
1634 [OPC_NEWARRAY] = opc_newarray,
1635 [OPC_CHECKCAST] = opc_checkcast,
1636 [OPC_CHECKCAST_QUICK] = opc_checkcast_quick,
1637 [OPC_GETFIELD] = opc_getfield,
1638 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1639 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1640 [OPC_FCMPL] = opc_fcmpl,
1641 [OPC_FCMPG] = opc_fcmpg,
1642 [OPC_I2F] = opc_i2f,
1643 [OPC_I2D] = opc_i2d,
1644 [OPC_FMUL] = opc_fmul,
1645 // [OPC_FADD] = opc_fadd,
1646 // [OPC_FSUB] = opc_fsub,
1647 [OPC_F2I] = opc_f2i,
1648 [OPC_IINC] = opc_iinc,
1649 [OPC_INSTANCEOF] = opc_instanceof,
1650 [OPC_ATHROW] = opc_athrow,
1651 [OPC_LRETURN] = opc_ldreturn,
1654 static handler_fn *exception_handler_f[] = {
1655 [0] = do_javaExceptions,
1656 [1] = do_stackOverflow,
1657 [2] = do_stackUnderflow,
1658 [3] = do_stackOverflow1,
1659 [4] = do_stackUnderflow1,
1662 struct jem_profile {
1663 unsigned long time;
1664 unsigned int n;
1667 static struct jem_profile prof[256];
1669 /******************************/
1670 uintptr_t *executeJava(void)
1673 * load trap entries to JEM trap table set when initializing JamVM
1675 int i;
1676 uint32_t jep;
1677 int done;
1678 #ifdef JEM_PROFILE
1679 static struct timeval tv1, tv2;
1680 #endif
1681 ExecEnv *ee = getExecEnv();
1683 /* Initialize interpreter's static environment */
1684 struct intrp_ctx ctx;
1685 struct jem_state *jem = &ctx.jem;
1687 ctx.ee = ee;
1688 ctx.frame = ee->last_frame;
1689 ctx.mb = ctx.frame->mb;
1691 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1692 * overflow we free a half of the stack (4 elements) to avoid an immediate
1693 * next overflow. When entering a trap, the Operand Stack is saved in a
1694 * temporary array in the reverse order:
1695 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1696 * jos[0] = r7 (?)
1697 * ...
1698 * jos[7 - N] = rN (ToS - N)
1699 * ...
1700 * jos[7] = r0 (ToS)
1701 * UPDATE (27.06.2008)
1702 * I think, actually, the manual is right in some way... If you access
1703 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1704 * with an ldm, you get this:
1705 * jos[0] = r7 (?)
1706 * ...
1707 * jos[7 - N] = rN (ToS)
1708 * ...
1709 * jos[7] = r0 (ToS - N)
1710 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1711 * set saved JOSP to 4.
1713 unsigned long jos[8];
1715 ctx.ostack = ctx.frame->ostack;
1716 ctx.cp = &(CLASS_CB(ctx.mb->class)->constant_pool);
1717 /* End enterpreter's static environment */
1719 //fetch the original pc before prepare direct mb
1720 //TODO:
1721 /* I think, mb->code is indeed a copy of the original code[] array from the
1722 * class object. See class.c::defineClass():390 */
1724 if (ctx.frame->lvars_jem) {
1725 uintptr_t *ptr;
1726 ctx.lvars_jem = ctx.frame->lvars_jem - 1;
1727 ptr = (uintptr_t *)*ctx.lvars_jem;
1728 ctx.this = JAM_OBJECT(ptr);
1729 } else {
1730 /* FIXME: do not know how to set it when there're none local var */
1731 ctx.lvars_jem = NULL;
1732 ctx.this = NULL;
1735 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1736 ctx.ostack, ctx.mb->max_locals, ctx.lvars_jem);
1737 jam_dprintf("[executeJava] execute method %s on class %s\n",
1738 ctx.mb->name, CLASS_CB(ctx.mb->class)->name);
1740 #if 0
1741 /* Don't think we need it, at least, not in the direct.c form. There the code
1742 * is converted into an internal representation, which is useless for JEM */
1743 PREPARE_MB(ctx.mb);//see direct.c (prepare)
1744 #endif
1746 jem->jpc = (unsigned long)ctx.mb->code & ~3;
1747 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1748 *(char*)jem->jpc, *((char*)jem->jpc + 1));
1750 do {
1751 static int opcode;
1753 #ifdef JEM_DEBUG
1754 jam_dprintf("About to enter JEM at 0x%08x, this = %p. Code:", jem->jpc, ctx.this);
1755 for (i = 0; i < 32 && jem->jpc + i < (unsigned long)(ctx.mb->code + ctx.mb->code_size); i++) {
1756 if (!(i & 0xf))
1757 jam_dprintf("\n0x%04x:", i);
1758 jam_dprintf(" 0x%02x", ((char*)jem->jpc)[i]);
1761 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx.mb->max_locals);
1762 for (i = 0; i < min(8, ctx.mb->max_locals); i++)
1763 jam_dprintf("LVAR_%d: 0x%08x\n", i, *(ctx.lvars_jem - i), ctx.lvars_jem - i);
1764 #endif
1766 /* On entry we need last Java Operand Stack depth, set it not deeper
1767 * than half hardware stack */
1768 jem->josp = min(5, ostack_depth(ctx.frame->ostack, ctx.ostack));
1769 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem->josp,
1770 ctx.frame->ostack, ctx.ostack);
1771 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1772 for (i = 0; i < jem->josp; i++)
1773 ostack_pop_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
1774 jos[7 - jem->josp + 1 + i]);
1776 #ifdef JEM_PROFILE
1777 if (tv1.tv_sec) {
1778 gettimeofday(&tv2, NULL);
1779 prof[opcode].time += (tv2.tv_sec - tv1.tv_sec) * 1000000 +
1780 tv2.tv_usec - tv1.tv_usec;
1781 prof[opcode].n++;
1783 #endif
1785 __asm__ __volatile__(
1786 ".globl debug_jem_enter\n"
1787 "debug_jem_enter:\n"
1788 " pushm r0-r7,r10-r11\n"
1789 " mov r8, %[cp]\n"
1790 " mov r9, %[lv0]\n"
1791 " mov lr, %[jpc]\n"
1792 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1793 " mov r11, %[ostack]\n"
1794 " pushm r11\n" /* Need ostack below */
1795 " ldm r11, r0-r7\n" /* Restore Java Operands */
1796 " cp.w r12, 0\n" /* Test josp == 0 */
1797 " breq 4f\n"
1798 "5: incjosp 1\n" /* ... for loop counter, */
1799 " sub r12, 1\n" /* because it can be */
1800 " brne 5b\n" /* one of r0-r7 */
1801 "4: popjc\n" /* Restore Local Variables */
1802 " sub r10, pc, . - trap\n" /* These 3 instructions */
1803 " retj\n" /* have to stay */
1804 "trap: pushjc\n" /* together */
1805 " mfsr r11, 0x58\n" /* JOSP */
1806 " lsl r11, 28\n" /* Clear r11[31:3] using */
1807 " lsr r11, 28\n" /* one register */
1808 " mov r8, r11\n"
1809 " breq 2f\n"
1810 "3: incjosp -1\n"
1811 " sub r11, 1\n"
1812 " brne 3b\n"
1813 "2: popm r11\n" /* ostack */
1814 " stm r11, r0-r7\n" /* Save Java Operands */
1815 " popm r0-r7,r10-r11\n"
1816 " mov %[tpc], r12\n"
1817 " mov %[jpc], lr\n" /* Resume address */
1818 " mfsr %[jecr], 0x54\n" /* JECR */
1819 " mov %[josp], r8\n" /* JOSP */
1820 " .globl debug_jem_exit\n"
1821 "debug_jem_exit:\n"
1822 : [jecr] "=r" (jem->jecr), [tpc] "=r" (jem->trap_pc),
1823 [josp] "+r" (jem->josp), [jpc] "+r" (jem->jpc)
1824 : [cp] "r" (ctx.cp->info), [lv0] "r" (ctx.lvars_jem),
1825 [ostack] "r" (jos)
1826 : "r8", "r9", "lr", "r12", "memory"
1829 * trap_pc now holds trap pc, describing which trap has been entered,
1830 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1831 * arguments at bits 7..0 and 15..8,
1832 * josp holds JOSP (JOSP & 0xf),
1833 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1834 * jpc points at the trapping opcode, in case of exceptions and stack
1835 * over- and underflows, and at the next opcode, in case of a trap
1838 #ifdef JEM_PROFILE
1839 gettimeofday(&tv1, NULL);
1840 #endif
1842 for (i = 0; i < jem->josp; i++)
1843 ostack_push_u32(ctx.frame->ostack, ctx.mb->max_stack, ctx.ostack,
1844 jos[7 - i]);
1846 opcode = (jem->jecr >> 16) & 0xff;
1848 jep = jem->trap_pc & 0xfff;
1850 trap_debug(&ctx);
1851 if (jep < 0x280)
1852 done = exception_handler_f[jep >> 7](&ctx);
1853 else if (trap_handler_f[opcode])
1854 done = trap_handler_f[opcode](&ctx);
1855 else {
1856 /* Unimplemented */
1857 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode);
1858 exitVM(1);
1861 #ifdef JEM_DEBUG
1862 usleep(100);
1863 #endif
1864 } while (done != JEM_TRAP_HANDLER_FINISH);
1866 return ctx.ostack;
1868 // DISPATCH_FIRST;
1870 jam_dprintf("Unknown Java Opcodes\n");
1871 exitVM(1);
1874 #ifndef executeJava
1875 void initialiseInterpreter(InitArgs *args) {
1876 initialiseDirect(args);
1878 #endif
1880 void dump_profile(void)
1882 #ifdef JEM_PROFILE
1883 int i;
1885 for (i = 0; i < 256; i++)
1886 if (prof[i].n)
1887 jam_printf("0x%x:\t%u times,\t%lu usec\n", i, prof[i].n, prof[i].time);
1888 #endif
1891 #endif //JEM