Whitespace fixes
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blob6cfb58d39c89d41c93e03e76d01987170e14a2f6
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 <stdio.h>
24 #include <arpa/inet.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <math.h>
29 #include "jam.h"
30 #include "thread.h"
31 #include "lock.h"
32 #include "interp.h"
34 #include "interp-direct.h"
36 #ifdef JEM
37 #include <sys/syscall.h>
38 #include <unistd.h>
39 #include <sys/mman.h>
41 #include "arch/avr32_jem.h"
42 #include "interp_jem.h"
44 #define JEM_DEBUG
45 #ifdef JEM_DEBUG
46 #define jam_dprintf(arg...) jam_printf(arg)
47 #else
48 #define jam_dprintf(arg...) do {} while (0)
49 #endif
51 union jecr {
52 struct {
53 uint8_t dummy;
54 uint8_t opcode;
55 uint8_t op1;
56 uint8_t op2;
57 } s;
58 uint32_t i;
61 /* These static variables come from the time when there was only one function in
62 * this file. So, we are pretty sure they must be shared. An attempt to pack
63 * them all in struct and pass a pointer to it around ended up in a way too ugly
64 * and suboptimal code. FIXME: fix when going multithreaded. */
66 static MethodBlock *mb;
67 static uintptr_t *lvars_jem;
68 static uintptr_t *ostack;
69 static ConstantPool *cp;
70 static Object *this;
71 static MethodBlock *new_mb;
72 static uintptr_t *arg1;
73 static Frame *frame;
74 static uintptr_t *lvars;
75 static Class *new_class;
77 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
79 //check if it is an valid object ref (see alloc.c)
80 #define OBJECT_GRAIN 8
81 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
83 #define JEM_THROW_EXCEPTION(excep_name, message) \
84 ({ \
85 frame->last_pc = (CodePntr)jem->jpc; \
86 signalException(excep_name, message); \
87 jem_throwException(jem); \
90 #define JEM_NULL_POINTER_CHECK(ref) \
91 if(!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
93 /*********************************************
94 * JEM Trap Handlers **
95 * *******************************************/
96 static int trap_debug(struct jem_state *jem)
98 #ifdef JEM_DEBUG
99 union jecr jecr_u;
100 int i;
102 jecr_u.i = jem->jecr;
104 jam_printf("Trap 0x%08x: opcode 0x%x @ 0x%08x, operand 1 0x%x, operand 2 0x%x. Operands:\n",
105 jem->trap_pc, jecr_u.s.opcode, jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
107 for (i = 0; i < jem->josp; i++) {
108 uint32_t v;
109 if (ostack_read_u32(frame->ostack, ostack, i, &v) >= 0)
110 jam_printf("\tToS-%d: 0x%x\n", i, v);
112 #endif
113 return 1;
117 static int jem_throwException(struct jem_state *jem)
119 ExecEnv *ee = getExecEnv();
120 Object *excep = ee->exception;
121 ee->exception = NULL;
123 jem->jpc = (unsigned long)findCatchBlock(excep->class);
124 jam_dprintf("Found exception handler at 0x%08x\n", jem->jpc);
126 /* If we didn't find a handler, restore exception and
127 return to previous invocation */
129 if (!jem->jpc) {
130 ee->exception = excep;
131 /* Original code had a "return NULL" here, which means, end of
132 * executeJava */
133 return JEM_TRAP_HANDLER_FINISH;
136 /* If we're handling a stack overflow, reduce the stack
137 back past the red zone to enable handling of further
138 overflows */
140 if (ee->overflow) {
141 ee->overflow = FALSE;
142 ee->stack_end -= STACK_RED_ZONE_SIZE;
145 /* Setup intepreter to run the found catch block */
147 frame = ee->last_frame;
148 mb = frame->mb;
149 ostack = frame->ostack;
150 lvars = frame->lvars;
151 lvars_jem = frame->lvars_jem - 1;
152 this = JAM_OBJECT(*lvars_jem);
153 cp = &(CLASS_CB(mb->class)->constant_pool);
155 /* FIXME: don't know if this is correct, depends how we implement
156 * exceptions */
157 ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uint32_t)excep);
159 /* Dispatch to the first bytecode */
160 return 0;
163 static int opc_return(struct jem_state *jem)
165 ExecEnv *ee = getExecEnv();
166 /* Set interpreter state to previous frame */
168 if (frame->prev->mb == NULL) {
169 /* The previous frame is a dummy frame - this indicates
170 top of this Java invocation. */
171 return 1;
174 if (frame->lvars_jem != NULL)
175 sysFree(frame->lvars_jem - frame->mb->max_locals);
177 frame = frame->prev;
179 if (mb->access_flags & ACC_SYNCHRONIZED) {
180 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
181 objectUnlock(sync_ob);
184 mb = frame->mb;
185 ostack = lvars;
186 lvars = frame->lvars;
187 lvars_jem = frame->lvars_jem - 1;
188 this = JAM_OBJECT(*lvars_jem);
189 jem->jpc = (uint32_t)frame->last_pc;
190 cp = &(CLASS_CB(mb->class)->constant_pool);
191 jam_dprintf("[OPC_RETURN] lvars :%08x lvars_jem :%08x this %08x\n",lvars, lvars_jem, this);
193 /* Pop frame */
194 ee->last_frame = frame;
196 return 0;
199 static int invokeMethod(struct jem_state *jem)
201 ExecEnv *ee = getExecEnv();
202 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
203 Object *sync_ob = NULL;
204 int i;
206 jam_dprintf("[invokeMethod] with args count %d \n", new_mb->args_count);
207 jam_dprintf("[invokeMethod] new frame start %x\n", new_frame);
209 frame->last_pc = (CodePntr)jem->jpc;
210 ostack = (uintptr_t *)(new_frame + 1);
212 if (ostack_overflows(ostack, new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
213 if(ee->overflow++) {
214 /* Overflow when we're already throwing stack overflow.
215 Stack extension should be enough to throw exception,
216 so something's seriously gone wrong - abort the VM! */
217 jam_printf("Fatal stack overflow! Aborting VM.\n");
218 exitVM(1);
220 ee->stack_end += STACK_RED_ZONE_SIZE;
221 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
224 //TODO
225 new_frame->mb = new_mb;
226 new_frame->lvars = arg1;
227 //TODO: it seemed lvars is in java stack,but jos[8] should be part of java stack
228 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
229 // Here still not touch the java stack,allocate lvars_jem from native heap
231 new_frame->lvars_jem = sysMalloc(new_mb->max_locals * sizeof(uintptr_t));
232 new_frame->lvars_jem = new_frame->lvars_jem + new_mb->max_locals;
233 jam_dprintf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame->lvars_jem);
235 for (i = 0; i < new_mb->args_count; i++)
236 *(new_frame->lvars_jem - 1 - i) = *(arg1 + i);
238 new_frame->ostack = ostack;
239 new_frame->prev = frame;
241 ee->last_frame = new_frame;
243 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
244 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)JAM_OBJECT(*arg1);
245 objectLock(sync_ob);
248 if(new_mb->access_flags & ACC_NATIVE) {
249 //FIXME: the object references in JEM are direct pointer to instance variables.
250 // While JamVM requires object references as pointers to Object type.
251 jam_dprintf("[invokeMethod] invoke native method\n");
252 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
253 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
255 if(sync_ob)
256 objectUnlock(sync_ob);
258 ee->last_frame = frame;
260 if(exceptionOccured0(ee)){
261 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
262 return jem_throwException(jem);
263 //exitVM(1);
266 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
267 return 0;
268 } else {
269 frame = new_frame;
270 mb = new_mb;
271 lvars = frame->lvars;
272 lvars_jem = new_frame->lvars_jem - 1;
273 this = JAM_OBJECT(*lvars_jem);
274 jem->jpc = (unsigned long)mb->code & ~3;
275 cp = &(CLASS_CB(mb->class)->constant_pool);
277 jam_dprintf("[invokeMethod] invoke virtual method: frame %x mb %x "
278 "lvars %x jpc %x cp %x \n", frame, mb, lvars_jem, jem->jpc, cp);
280 jam_dprintf("[invokeMethod] finish virtual method invoke, return to loop\n");
282 return 0;
285 static int opc_invokesuper_quick(struct jem_state *jem)
287 Operand *operand = &jem->operand;
289 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
290 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[operand->i];
291 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d \n", new_mb->args_count);
293 // set up jem operand stack
294 arg1 = ostack_address(frame->ostack, mb->max_stack,
295 ostack - frame->ostack - new_mb->args_count);
296 JEM_NULL_POINTER_CHECK(*arg1);
297 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x \n", *arg1);
298 return invokeMethod(jem);
301 static int opc_invokenonvirtual_quick(struct jem_state *jem)
303 Operand *operand = &jem->operand;
305 new_mb = (MethodBlock*)operand->pntr;
306 jam_dprintf("[OPC_INVOKENONVIRTUAL_QUICK] new methodblock %s (%x) with %d args\n",
307 new_mb->name, new_mb, new_mb->args_count);
308 arg1 = ostack_address(frame->ostack, mb->max_stack,
309 ostack - frame->ostack - new_mb->args_count);
310 jam_dprintf("[OP_INVOKENONVIRTUAL_QUICK] arg1 %x \n", *arg1);
311 JEM_NULL_POINTER_CHECK(*arg1);
312 return invokeMethod(jem);
315 static int opc_invokevirtual_quick(struct jem_state *jem)
317 Object *obj;
318 arg1 = ostack_address(frame->ostack, mb->max_stack,
319 ostack - frame->ostack - INV_QUICK_ARGS(jem));
320 JEM_NULL_POINTER_CHECK(*arg1);
322 obj = JAM_OBJECT(*arg1);
323 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object 0x%08x (0x%08x)\n", obj, arg1);
324 new_class = obj->class;
325 new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(jem)];
326 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x on class %x\n",
327 new_mb, new_class);
328 return invokeMethod(jem);
331 static int opc_invokevirtual(struct jem_state *jem)
333 int idx;
334 ExecEnv *ee = getExecEnv();
336 idx = jem->jecr & 0xffff;
337 frame->last_pc = (CodePntr)jem->jpc;
338 new_mb = resolveMethod(mb->class, idx);
340 if(exceptionOccured0(ee))
341 return jem_throwException(jem);
343 jem->operand.uu.u1 = new_mb->args_count;
344 jem->operand.uu.u2 = new_mb->method_table_index;
346 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
347 new_mb,new_mb->args_count);
349 return opc_invokevirtual_quick(jem);
353 static int opc_invokespecial(struct jem_state *jem)
355 int idx;
356 Operand *operand = &jem->operand;
357 ExecEnv *ee = getExecEnv();
359 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
360 idx = jem->jecr & 0xffff;
362 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d \n", idx);
364 new_mb = resolveMethod(mb->class, idx);
366 if (exceptionOccured0(ee))
367 return jem_throwException(jem);
369 jam_dprintf("Resolved %s\n", new_mb->name);
371 /* Check if invoking a super method... */
372 if ((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
373 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
375 operand->i = new_mb->method_table_index;
376 return opc_invokesuper_quick(jem);
377 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
378 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
379 #endif
380 } else {
381 operand->pntr = new_mb;
382 return opc_invokenonvirtual_quick(jem);
385 return 0;
388 static int opc_invokestatic_quick(struct jem_state *jem)
390 new_mb = RESOLVED_METHOD(jem);
391 arg1 = ostack_address(frame->ostack, mb->max_stack,
392 ostack - frame->ostack - new_mb->args_count);
393 return invokeMethod(jem);
396 static int opc_invokestatic(struct jem_state *jem)
398 int idx, cache;
399 Operand *operand = &jem->operand;
400 ExecEnv *ee = getExecEnv();
402 idx = jem->jecr & 0xffff;
404 frame->last_pc = (CodePntr)jem->jpc;
405 new_mb = resolveMethod(mb->class, idx);
407 if(exceptionOccured0(ee))
408 return jem_throwException(jem);
410 operand->pntr = new_mb;
411 return opc_invokestatic_quick(jem);
414 static int opc_new_quick(struct jem_state *jem)
416 Operand *operand = &jem->operand;
417 Class *class = (Class*)CP_INFO(cp, operand->uui.u1);
418 Object *obj;
420 frame->last_pc = (CodePntr)jem->jpc;
421 if((obj = allocObject(class)) == NULL)
422 return jem_throwException(jem);
423 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack \n", obj);
424 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
425 (uint32_t)INST_DATA(obj));
428 static int opc_new(struct jem_state *jem)
430 Operand *operand = &jem->operand;
431 int idx = operand->uui.u1 = jem->jecr & 0xffff;
432 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
433 Class *class;
434 ExecEnv *ee = getExecEnv();
436 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
438 frame->last_pc = (CodePntr)jem->jpc;
439 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
440 if(exceptionOccured0(ee))
441 return jem_throwException(jem);
443 if(opcode == OPC_NEW) {
444 ClassBlock *cb = CLASS_CB(class);
445 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
446 signalException("java/lang/InstantiationError", cb->name);
447 return jem_throwException(jem);
451 return opc_new_quick(jem);
454 static int opc_anewarray_quick(struct jem_state *jem)
456 Class *class = RESOLVED_CLASS(jem);
457 char *name = CLASS_CB(class)->name;
458 int count;
459 Class *array_class;
460 char *ac_name;
461 Object *obj;
462 ExecEnv *ee = getExecEnv();
464 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, count);
465 frame->last_pc = (CodePntr)jem->jpc;
467 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name, count);
468 if(count < 0) {
469 signalException("java/lang/NegativeArraySizeException", NULL);
470 return jem_throwException(jem);
473 ac_name = sysMalloc(strlen(name) + 4);
475 if(name[0] == '[')
476 strcat(strcpy(ac_name, "["), name);
477 else
478 strcat(strcat(strcpy(ac_name, "[L"), name), ";");
480 array_class = findArrayClassFromClass(ac_name, mb->class);
481 free(ac_name);
483 if(exceptionOccured0(ee))
484 return jem_throwException(jem);
486 if((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
487 return jem_throwException(jem);
489 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
490 (uint32_t)ARRAY_DATA(obj));
493 static int opc_anewarray(struct jem_state *jem)
495 Operand *operand = &jem->operand;
496 int idx = operand->uui.u1 = jem->jecr & 0xffff;
497 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
498 Class *class;
499 ExecEnv *ee = getExecEnv();
501 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
503 frame->last_pc = (CodePntr)jem->jpc;
504 //resolve the array class
505 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
507 if(exceptionOccured0(ee))
508 return jem_throwException(jem);
510 return opc_anewarray_quick(jem);
513 static int opc_newarray(struct jem_state *jem)
515 int type = (jem->jecr >> 8) & 0xff;
516 int count;
517 Object *obj;
519 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, count);
520 frame->last_pc = (CodePntr)jem->jpc;
522 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type, count);
523 if((obj = allocTypeArray(type, count)) == NULL)
524 return jem_throwException(jem);
526 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
527 (uint32_t)ARRAY_DATA(obj));
530 static int opc_putfield_quick(struct jem_state *jem)
532 uint32_t arg;
533 uint32_t obj;
535 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, arg);
536 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
537 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg,
538 SINGLE_INDEX(jem), obj);
540 JEM_NULL_POINTER_CHECK(obj);
541 ((uint32_t*)obj)[SINGLE_INDEX(jem)] = arg;
543 return 0;
546 static int opc_putfield2_quick(struct jem_state *jem)
548 uint64_t arg;
549 uint32_t obj;
551 ostack_pop_u64(frame->ostack, mb->max_stack, ostack, arg);
552 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
554 JEM_NULL_POINTER_CHECK((uintptr_t*)obj);
555 *(uint64_t *)&(((uint32_t*)obj)[SINGLE_INDEX(jem)]) = arg;
556 jam_dprintf("[OPC_PUTFIELD2_QUICK] put 64 bit %08x to obj %08x\n", arg, obj);
558 return 0;
561 static int opc_putfield_quick_jem0(struct jem_state *jem)
563 uint32_t arg;
564 uintptr_t obj;
566 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, arg);
567 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
568 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x \n", arg);
570 JEM_NULL_POINTER_CHECK(obj);
572 if(arg && !IS_JAM_OBJECT(arg)){
573 arg = (uint32_t)JAM_OBJECT(arg);
576 ((uintptr_t*)obj)[SINGLE_INDEX(jem)] = arg;
577 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg,
578 SINGLE_INDEX(jem), obj);
580 return 0;
583 static int opc_putfield_quick_jem1(struct jem_state *jem)
585 uint32_t arg;
586 uintptr_t obj;
588 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, arg);
589 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
590 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %x \n", arg);
592 if(arg && !IS_JAM_OBJECT(arg)){
593 arg = (uint32_t)JAM_ARRAY(arg);
596 JEM_NULL_POINTER_CHECK(obj);
597 ((uintptr_t*)obj)[SINGLE_INDEX(jem)] = arg;
598 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %x to obj(%d) %x\n", arg,
599 SINGLE_INDEX(jem), obj);
601 return 0;
604 static int opc_putfield(struct jem_state *jem)
606 int idx = jem->jecr & 0xffff;
607 FieldBlock *fb;
608 ExecEnv *ee = getExecEnv();
610 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx);
612 frame->last_pc = (CodePntr)jem->jpc;
613 fb = resolveField(mb->class, idx);
614 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
616 if(exceptionOccured0(ee))
617 return jem_throwException(jem);
619 jem->operand.i = fb->offset;
620 switch (*fb->type) {
621 case 'J':
622 case 'D':
623 return opc_putfield2_quick(jem);
624 case 'L':
625 return opc_putfield_quick_jem0(jem);
626 case '[':
627 return opc_putfield_quick_jem1(jem);
628 default:
629 return opc_putfield_quick(jem);
633 static int opc_getfield2_quick(struct jem_state *jem)
635 uint32_t *obj;
636 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
637 JEM_NULL_POINTER_CHECK(obj);
638 jam_dprintf("[OPC_GETFIELD2_QUICK] get 64 bit field %08x from obj %08x\n",
639 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])), obj);
641 return ostack_push_u64(frame->ostack, mb->max_stack, ostack,
642 *(uint64_t*)(&(obj[SINGLE_INDEX(jem)])));
645 static int opc_getfield_quick(struct jem_state *jem)
647 uint32_t *obj;
648 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
649 JEM_NULL_POINTER_CHECK(obj);
651 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
652 obj[SINGLE_INDEX(jem)], obj);
653 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
654 obj[SINGLE_INDEX(jem)]);
657 static int opc_getfield_quick_jem0(struct jem_state *jem)
659 uint32_t *obj;
660 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
661 JEM_NULL_POINTER_CHECK(obj);
663 uint32_t value = obj[SINGLE_INDEX(jem)];
664 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj ref %x\n", value);
665 if(value){
666 Object *ref = (Object*)value;
667 if(IS_JAM_OBJECT(ref))
668 //jamvm objref
669 value = (uint32_t)INST_DATA(ref);
671 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value);
672 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, value);
676 static int opc_getfield_quick_jem1(struct jem_state *jem)
678 uint32_t *obj;
679 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
680 JEM_NULL_POINTER_CHECK(obj);
682 uint32_t value = obj[SINGLE_INDEX(jem)];
683 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value);
684 if(value){
685 Object *ref = (Object*)value;
686 if(IS_JAM_OBJECT(ref))
687 value = (uint32_t)ARRAY_DATA(ref);
689 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value);
690 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, value);
693 static int opc_getfield(struct jem_state *jem)
695 int idx = jem->jecr & 0xffff;
696 FieldBlock *fb;
697 ExecEnv *ee = getExecEnv();
699 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx);
701 frame->last_pc = (CodePntr)jem->jpc;
702 fb = resolveField(mb->class, idx);
703 jam_dprintf("[OPC_GETFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
705 if(exceptionOccured0(ee))
706 return jem_throwException(jem);
708 jem->operand.i = fb->offset;
709 switch (*fb->type) {
710 case 'J':
711 case 'D':
712 return opc_getfield2_quick(jem);
714 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
715 * in case of some JNI code will set field natively, we still handle it
716 * separately here.
718 case 'L':
719 return opc_getfield_quick_jem0(jem);
720 case '[':
721 return opc_getfield_quick_jem1(jem);
722 default:
723 return opc_getfield_quick(jem);
727 static int opc_ldc_w_quick_jem(struct jem_state *jem)
729 //CONSTANT_Class and CONSTANT_String are stored as object reference
730 Object *cp_info = (Object*)CP_INFO(cp, DOUBLE_INDEX(jem));
731 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack \n", cp_info);
732 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
733 (uint32_t)INST_DATA(cp_info));
736 static int opc_ldc_w_quick(struct jem_state *jem)
738 uint32_t cp_info = CP_INFO(cp, DOUBLE_INDEX(jem));
739 jam_dprintf("[OPC_LDC_W_QUICK] push constant %08x to stack\n", cp_info);
740 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, cp_info);
743 static int opc_ldc_quick(struct jem_state *jem)
745 uint32_t constant = RESOLVED_CONSTANT(jem);
746 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack \n", constant);
747 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)constant);
750 static int opc_ldc_common(struct jem_state *jem, int idx)
752 ExecEnv *ee = getExecEnv();
753 frame->last_pc = (CodePntr)jem->jpc;
755 jem->operand.u = resolveSingleConstant(mb->class, idx);
757 if(exceptionOccured0(ee))
758 return jem_throwException(jem);
760 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass) {
761 jem->operand.i = idx;
762 return opc_ldc_w_quick(jem);
763 }else if(CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
764 jem->operand.i = idx;
765 return opc_ldc_w_quick_jem(jem);
766 } else
767 return opc_ldc_quick(jem);
770 static int opc_ldc(struct jem_state *jem)
772 int idx;
773 ExecEnv *ee = getExecEnv();
775 idx = (jem->jecr & 0xff00) >> 8;
777 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx);
778 return opc_ldc_common(jem, idx);
781 static int opc_ldc_w(struct jem_state *jem)
783 int idx;
784 ExecEnv *ee = getExecEnv();
786 idx = (jem->jecr & 0xffff);
788 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx);
789 return opc_ldc_common(jem, idx);
792 static int opc_monitorenter(struct jem_state *jem)
794 Object *obj;
795 uintptr_t ptr;
796 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, ptr);
798 obj = JAM_OBJECT(ptr);
799 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj);
800 JEM_NULL_POINTER_CHECK(obj);
801 objectLock(obj);
802 return 0;
805 static int opc_monitorexit(struct jem_state *jem)
807 Object *obj;
808 uintptr_t ptr;
809 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, ptr);
811 obj = JAM_OBJECT(ptr);
812 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj);
813 JEM_NULL_POINTER_CHECK(obj);
814 objectUnlock(obj);
815 return 0;
818 static int opc_getstatic_quick(struct jem_state *jem)
820 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
821 RESOLVED_FIELD(jem)->static_value);
824 static int opc_getstatic2_quick(struct jem_state *jem)
826 return ostack_push_u64(frame->ostack, mb->max_stack, ostack,
827 RESOLVED_FIELD(jem)->static_value);
830 static int opc_getstatic_quick_jem0(struct jem_state *jem)
832 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
834 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value);
835 if(value) {
836 Object *ref = (Object*)value;
837 if(IS_JAM_OBJECT(ref))
838 //jamvm objref
839 value = (uintptr_t)INST_DATA(ref);
841 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value);
842 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, value);
845 static int opc_getstatic_quick_jem1(struct jem_state *jem)
847 uintptr_t value = RESOLVED_FIELD(jem)->static_value;
848 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value);
849 if(value) {
850 Object *ref = (Object*)value;
851 if(IS_JAM_OBJECT(ref))
852 //jamvm arrayref
853 value = (uintptr_t)ARRAY_DATA(ref);
855 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value);
856 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, value);
859 static int opc_getstatic(struct jem_state *jem)
861 int idx;
862 FieldBlock *fb;
863 Operand operand;
864 ExecEnv *ee = getExecEnv();
866 idx = (int)(jem->jecr & 0xffff);
867 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx,CLASS_CB(mb->class)->name);
869 frame->last_pc = (CodePntr)jem->jpc;
870 fb = resolveField(mb->class, idx);
872 if(exceptionOccured0(ee))
873 return jem_throwException(jem);
875 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb, *fb->type);
876 jem->operand.pntr = fb;
877 switch (*fb->type) {
878 case 'J':
879 case 'D':
880 return opc_getstatic2_quick(jem);
882 * see opc_getfield
884 case 'L':
885 return opc_getstatic_quick_jem0(jem);
886 case '[':
887 return opc_getstatic_quick_jem1(jem);
888 default:
889 return opc_getstatic_quick(jem);
893 static int opc_putstatic2_quick(struct jem_state *jem)
895 return ostack_pop_u64(frame->ostack, mb->max_stack, ostack,
896 *(u8*)&RESOLVED_FIELD(jem)->static_value);
899 static int opc_putstatic_quick(struct jem_state *jem)
901 return ostack_pop_u32(frame->ostack, mb->max_stack, ostack,
902 RESOLVED_FIELD(jem)->static_value);
905 static int opc_putstatic_quick_jem0(struct jem_state *jem)
907 uintptr_t value;
908 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, value);
910 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value);
911 if(value && !IS_JAM_OBJECT(value))
912 value = (uintptr_t)JAM_OBJECT(value);
913 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value);
914 RESOLVED_FIELD(jem)->static_value = value;
915 return 0;
918 static int opc_putstatic_quick_jem1(struct jem_state *jem)
920 uintptr_t value;
921 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, value);
923 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %x\n", value);
924 if(value && !IS_JAM_OBJECT(value))
925 value = (uintptr_t)JAM_ARRAY(value);
926 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %x\n", value);
927 RESOLVED_FIELD(jem)->static_value = value;
928 return 0;
931 static int opc_putstatic(struct jem_state *jem)
933 int idx;
934 FieldBlock *fb;
935 Operand operand;
936 ExecEnv *ee = getExecEnv();
938 idx = (int)(jem->jecr & 0xffff);
940 frame->last_pc = (CodePntr)jem->jpc;
941 fb = resolveField(mb->class, idx);
943 if(exceptionOccured0(ee))
944 return jem_throwException(jem);
946 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb, *fb->type);
947 jem->operand.pntr = fb;
948 switch (*fb->type) {
949 case 'J':
950 case 'D':
951 return opc_putstatic2_quick(jem);
952 case 'L':
953 return opc_putstatic_quick_jem0(jem);
954 case '[':
955 return opc_putstatic_quick_jem1(jem);
956 default:
957 return opc_putstatic_quick(jem);
961 static int opc_checkcast_quick(struct jem_state *jem)
963 Class *class = RESOLVED_CLASS(jem);
964 Object *obj;
965 uintptr_t *ptr;
967 ostack_read_u32(frame->ostack, ostack, 0, &ptr);
968 obj = JAM_OBJECT(ptr);
969 if(!IS_OBJECT(obj)) {
970 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
971 //should be array ref
972 obj = JAM_ARRAY(ptr);
974 ostack_read_u32(frame->ostack, ostack, 0, &obj);
976 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %s for obj(%s)\n", CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
977 if((obj != NULL) && !isInstanceOf(class, obj->class))
978 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
979 return 0;
982 static int opc_checkcast(struct jem_state *jem)
984 Operand *operand = &jem->operand;
985 int idx = operand->uui.u1 = jem->jecr & 0xffff;
986 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
987 Class *class;
988 ExecEnv *ee = getExecEnv();
990 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
992 frame->last_pc = (CodePntr)jem->jpc;
993 //resolve the cast class
994 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
996 if(exceptionOccured0(ee))
997 return jem_throwException(jem);
999 return opc_checkcast_quick(jem);
1002 static int do_javaExceptions(struct jem_state *jem)
1004 union jecr jecr_u;
1006 /* deliberate segfault */
1007 /* *(int *)0 = 0; */
1009 jecr_u.i = jem->jecr;
1010 /* This should not happen, because we don't use the "Java Handle" (H)
1011 * bit in the Status Register and we set JBCR to 0x80000000 - still
1012 * it does happen, but seems to be harmless so far. Just ignore. */
1013 if (jecr_u.s.opcode == OPC_AASTORE)
1014 return 0;
1016 return JEM_TRAP_HANDLER_SYSEX;
1019 static int opc_afireturn(struct jem_state *jem)
1021 uint32_t val;
1022 int ret;
1024 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, val);
1026 jam_dprintf("[OPC_AFIRETURN] return %08x\n", val);
1028 ret = opc_return(jem);
1029 if (!ret)
1030 ret = ostack_push_u32(frame->ostack, mb->max_stack, ostack, val);
1032 return ret;
1035 static int opc_fcmpl(struct jem_state *jem)
1037 float v1, v2;
1038 int res;
1039 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v2);
1040 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v1);
1041 if(v1 == v2)
1042 res = 0;
1043 else if(v1 < v2)
1044 res = -1;
1045 else if(v1 > v2)
1046 res = 1;
1047 else
1048 res = -1;
1049 jam_dprintf("[OPC_FCMPL] result %d\n", res);
1050 ostack_push_u32(frame->ostack, mb->max_stack, ostack, res);
1051 return 0;
1054 static int opc_i2f(struct jem_state *jem)
1056 int i;
1057 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, i);
1059 float f = (float)i;
1060 jam_dprintf("[OPC_I2F] convert to %f\n", f);
1061 ostack_push_f32(frame->ostack, mb->max_stack, ostack, f);
1062 return 0;
1065 static int opc_i2d(struct jem_state *jem)
1067 return JEM_TRAP_HANDLER_FINISH;
1070 static int opc_fmul(struct jem_state *jem)
1072 float v1, v2;
1073 float ret;
1074 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v2);
1075 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v1);
1076 ret = v1 * v2;
1077 jam_dprintf("[OPC_FMUL] result %f\n", ret);
1078 ostack_push_f32(frame->ostack, mb->max_stack, ostack, ret);
1079 return 0;
1082 static int opc_fadd(struct jem_state *jem)
1084 float v1, v2;
1085 float ret;
1086 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v2);
1087 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v1);
1088 ret = v1 + v2;
1089 jam_dprintf("[OPC_FADD] result %f\n", ret);
1090 ostack_push_f32(frame->ostack, mb->max_stack, ostack, ret);
1091 return 0;
1094 static int opc_fsub(struct jem_state *jem)
1096 float v1, v2;
1097 float ret;
1098 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v2);
1099 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, v1);
1100 ret = v1 - v2;
1101 jam_dprintf("[OPC_FSUB] result %f\n", ret);
1102 ostack_push_f32(frame->ostack, mb->max_stack, ostack, ret);
1103 return 0;
1106 static int opc_f2i(struct jem_state *jem)
1108 int res;
1109 float value;
1110 ostack_pop_f32(frame->ostack, mb->max_stack, ostack, value);
1111 jam_dprintf("[OPC_F2I] float value %f\n", value);
1112 if(value >= (float)INT_MAX)
1113 res = INT_MAX;
1114 else if(value <= (float)INT_MIN)
1115 res = INT_MIN;
1116 else if(value != value)
1117 res = 0;
1118 else
1119 res = (int)value;
1120 jam_dprintf("[OPC_F2I] int value %d\n", res);
1121 ostack_push_u32(frame->ostack, mb->max_stack, ostack, res);
1122 return 0;
1125 static int do_stackOverflow(struct jem_state *jem)
1127 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1128 trap_debug(jem);
1129 return 1;
1132 static int do_stackUnderflow(struct jem_state *jem)
1134 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1135 trap_debug(jem);
1136 return 1;
1139 static int do_stackOverflow1(struct jem_state *jem)
1141 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1142 trap_debug(jem);
1143 return 1;
1146 static int do_stackUnderflow1(struct jem_state *jem)
1148 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1149 trap_debug(jem);
1150 return 1;
1153 static handler_fn *trap_handler_f[256];
1155 static handler_fn *exception_handler_f[] = {
1156 [0] = do_javaExceptions,
1157 [1] = do_stackOverflow,
1158 [2] = do_stackUnderflow,
1159 [3] = do_stackOverflow1,
1160 [4] = do_stackUnderflow1,
1163 /******************************/
1164 uintptr_t *executeJava(void)
1166 #if 0
1168 * Using jamVm's direct threaded interpreting table to perform effective work
1170 #define L(opcode, level, label) &&opc##opcode##_##level##_##label
1172 #define D(opcode, level, label) &&rewrite_lock
1174 #define I(opcode, level, label) &&rewrite_lock
1176 #define DEF_HANDLER_TABLE(lvl,lbl) \
1177 HANDLER_TABLE_T *handlers_##lvl##_##lbl[] = { \
1178 L(0,lvl,lbl), L(1,lvl,lbl), L(2,lvl,lbl), L(3,lvl,lbl), L(4,lvl,lbl), \
1179 L(5,lvl,lbl), L(6,lvl,lbl), L(7,lvl,lbl), L(8,lvl,lbl), L(9,lvl,lbl), \
1180 L(10,lvl,lbl), L(11,lvl,lbl), L(12,lvl,lbl), L(13,lvl,lbl), L(14,lvl,lbl), \
1181 L(15,lvl,lbl), L(16,lvl,lbl), L(17,lvl,lbl), L(18,lvl,lbl), D(19,lvl,lbl), \
1182 L(20,lvl,lbl), L(21,lvl,lbl), L(22,lvl,lbl), L(23,lvl,lbl), L(24,lvl,lbl), \
1183 L(25,lvl,lbl), L(26,lvl,lbl), L(27,lvl,lbl), L(28,lvl,lbl), L(29,lvl,lbl), \
1184 L(30,lvl,lbl), L(31,lvl,lbl), L(32,lvl,lbl), L(33,lvl,lbl), L(34,lvl,lbl), \
1185 L(35,lvl,lbl), L(36,lvl,lbl), L(37,lvl,lbl), L(38,lvl,lbl), L(39,lvl,lbl), \
1186 L(40,lvl,lbl), L(41,lvl,lbl), D(42,lvl,lbl), L(43,lvl,lbl), L(44,lvl,lbl), \
1187 L(45,lvl,lbl), L(46,lvl,lbl), L(47,lvl,lbl), L(48,lvl,lbl), L(49,lvl,lbl), \
1188 L(50,lvl,lbl), L(51,lvl,lbl), L(52,lvl,lbl), L(53,lvl,lbl), L(54,lvl,lbl), \
1189 L(55,lvl,lbl), L(56,lvl,lbl), L(57,lvl,lbl), L(58,lvl,lbl), L(59,lvl,lbl), \
1190 L(60,lvl,lbl), L(61,lvl,lbl), L(62,lvl,lbl), L(63,lvl,lbl), L(64,lvl,lbl), \
1191 L(65,lvl,lbl), L(66,lvl,lbl), L(67,lvl,lbl), L(68,lvl,lbl), L(69,lvl,lbl), \
1192 L(70,lvl,lbl), L(71,lvl,lbl), L(72,lvl,lbl), L(73,lvl,lbl), L(74,lvl,lbl), \
1193 L(75,lvl,lbl), L(76,lvl,lbl), L(77,lvl,lbl), L(78,lvl,lbl), L(79,lvl,lbl), \
1194 L(80,lvl,lbl), L(81,lvl,lbl), L(82,lvl,lbl), L(83,lvl,lbl), L(84,lvl,lbl), \
1195 L(85,lvl,lbl), L(86,lvl,lbl), L(87,lvl,lbl), L(88,lvl,lbl), L(89,lvl,lbl), \
1196 L(90,lvl,lbl), L(91,lvl,lbl), L(92,lvl,lbl), L(93,lvl,lbl), L(94,lvl,lbl), \
1197 L(95,lvl,lbl), L(96,lvl,lbl), L(97,lvl,lbl), L(98,lvl,lbl), L(99,lvl,lbl), \
1198 L(100,lvl,lbl), L(101,lvl,lbl), L(102,lvl,lbl), L(103,lvl,lbl), L(104,lvl,lbl), \
1199 L(105,lvl,lbl), L(106,lvl,lbl), L(107,lvl,lbl), L(108,lvl,lbl), L(109,lvl,lbl), \
1200 L(110,lvl,lbl), L(111,lvl,lbl), L(112,lvl,lbl), L(113,lvl,lbl), L(114,lvl,lbl), \
1201 L(115,lvl,lbl), L(116,lvl,lbl), L(117,lvl,lbl), L(118,lvl,lbl), L(119,lvl,lbl), \
1202 L(120,lvl,lbl), L(121,lvl,lbl), L(122,lvl,lbl), L(123,lvl,lbl), L(124,lvl,lbl), \
1203 L(125,lvl,lbl), L(126,lvl,lbl), L(127,lvl,lbl), L(128,lvl,lbl), L(129,lvl,lbl), \
1204 L(130,lvl,lbl), L(131,lvl,lbl), L(132,lvl,lbl), L(133,lvl,lbl), L(134,lvl,lbl), \
1205 L(135,lvl,lbl), L(136,lvl,lbl), L(137,lvl,lbl), L(138,lvl,lbl), L(139,lvl,lbl), \
1206 L(140,lvl,lbl), L(141,lvl,lbl), L(142,lvl,lbl), L(143,lvl,lbl), L(144,lvl,lbl), \
1207 L(145,lvl,lbl), L(146,lvl,lbl), L(147,lvl,lbl), L(148,lvl,lbl), L(149,lvl,lbl), \
1208 L(150,lvl,lbl), L(151,lvl,lbl), L(152,lvl,lbl), L(153,lvl,lbl), L(154,lvl,lbl), \
1209 L(155,lvl,lbl), L(156,lvl,lbl), L(157,lvl,lbl), L(158,lvl,lbl), L(159,lvl,lbl), \
1210 L(160,lvl,lbl), L(161,lvl,lbl), L(162,lvl,lbl), L(163,lvl,lbl), L(164,lvl,lbl), \
1211 L(165,lvl,lbl), L(166,lvl,lbl), L(167,lvl,lbl), L(168,lvl,lbl), L(169,lvl,lbl), \
1212 L(170,lvl,lbl), L(171,lvl,lbl), L(172,lvl,lbl), L(173,lvl,lbl), L(174,lvl,lbl), \
1213 L(175,lvl,lbl), L(176,lvl,lbl), L(177,lvl,lbl), L(178,lvl,lbl), L(179,lvl,lbl), \
1214 L(180,lvl,lbl), L(181,lvl,lbl), L(182,lvl,lbl), L(183,lvl,lbl), L(184,lvl,lbl), \
1215 L(185,lvl,lbl), &&unused, L(187,lvl,lbl), L(188,lvl,lbl), L(189,lvl,lbl), \
1216 L(190,lvl,lbl), L(191,lvl,lbl), L(192,lvl,lbl), L(193,lvl,lbl), L(194,lvl,lbl), \
1217 L(195,lvl,lbl), D(196,lvl,lbl), L(197,lvl,lbl), L(198,lvl,lbl), L(199,lvl,lbl), \
1218 L(200,lvl,lbl), L(201,lvl,lbl), &&unused, L(203,lvl,lbl), L(204,lvl,lbl), \
1219 &&unused, L(206,lvl,lbl), L(207,lvl,lbl), L(208,lvl,lbl), L(209,lvl,lbl), \
1220 L(210,lvl,lbl), L(211,lvl,lbl), L(212,lvl,lbl), L(213,lvl,lbl), L(214,lvl,lbl), \
1221 L(215,lvl,lbl), L(216,lvl,lbl), &&unused, &&unused, &&unused, &&unused, \
1222 &&unused, &&unused, &&unused, &&unused, &&unused, D(226,lvl,lbl), \
1223 D(227,lvl,lbl), D(228,lvl,lbl), L(229,lvl,lbl), D(230,lvl,lbl), L(231,lvl,lbl), \
1224 L(232,lvl,lbl), L(233,lvl,lbl), &&unused, L(235,lvl,lbl), &&unused, \
1225 &&unused, L(238,lvl,lbl), L(239,lvl,lbl), &&unused, &&unused, &&unused, \
1226 L(243,lvl,lbl), L(244,lvl,lbl), L(245,lvl,lbl), I(246,lvl,lbl), &&unused, \
1227 &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, \
1228 &&unused}
1230 DEF_HANDLER_TABLE(0, ENTRY);
1231 #endif
1233 * load trap entries to JEM trap table set when initializing JamVM
1235 int i;
1237 // static const void **handlers[] = {handlers_0_ENTRY};
1239 ExecEnv *ee = getExecEnv();
1241 /* Initialize interpreter's static environment */
1242 frame = ee->last_frame;
1243 mb = frame->mb;
1244 lvars_jem = frame->lvars_jem - 1;
1246 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1247 * overflow we free a half of the stack (4 elements) to avoid an immediate
1248 * next overflow. When entering a trap, the Operand Stack is saved in a
1249 * temporary array in the reverse order:
1250 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1251 * jos[0] = r7 (?)
1252 * ...
1253 * jos[7 - N] = rN (ToS - N)
1254 * ...
1255 * jos[7] = r0 (ToS)
1256 * UPDATE (27.06.2008)
1257 * I think, actually, the manual is right in some way... If you access
1258 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1259 * with an ldm, you get this:
1260 * jos[0] = r7 (?)
1261 * ...
1262 * jos[7 - N] = rN (ToS)
1263 * ...
1264 * jos[7] = r0 (ToS - N)
1265 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1266 * set saved JOSP to 4.
1268 unsigned long jos[8];
1269 ostack = frame->ostack;
1270 cp = &(CLASS_CB(mb->class)->constant_pool);
1271 lvars = frame->lvars;
1272 this = JAM_OBJECT(*lvars_jem);
1273 /* End enterpreter's static environment */
1276 //fetch the original pc before prepare direct mb
1277 //TODO:
1278 /* I think, mb->code is indeed a copy of the original code[] array from the
1279 * class object. See class.c::defineClass():390 */
1280 struct jem_state jem;
1281 uint32_t jep;
1282 int done;
1284 jam_dprintf("[executeJava] ostack %08x this %08x locals %d lvars_jem %08x lvars %08x\n",
1285 ostack, *lvars, mb->max_locals, lvars_jem, lvars);
1286 jam_dprintf("[executeJava] execute method %s on class %s\n",
1287 mb->name, CLASS_CB(mb->class)->name);
1288 /* This is temporary. As we implement more handlers, we'll think of a better
1289 * way to link them. */
1290 trap_handler_f[OPC_INVOKESPECIAL] = opc_invokespecial;
1291 trap_handler_f[OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick;
1292 trap_handler_f[OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick;
1293 trap_handler_f[OPC_INVOKEVIRTUAL] = opc_invokevirtual;
1294 trap_handler_f[OPC_INVOKEVIRTUAL_QUICK] = opc_invokevirtual_quick;
1295 trap_handler_f[OPC_INVOKESTATIC] = opc_invokestatic;
1296 // trap_handler_f[OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick;
1297 trap_handler_f[OPC_NEW] = opc_new;
1298 trap_handler_f[OPC_NEW_QUICK] = opc_new_quick;
1299 trap_handler_f[OPC_RETURN] = opc_return;
1300 trap_handler_f[OPC_ARETURN] = opc_afireturn;
1301 trap_handler_f[OPC_IRETURN] = opc_afireturn;
1302 trap_handler_f[OPC_FRETURN] = opc_afireturn;
1303 trap_handler_f[OPC_PUTFIELD] = opc_putfield;
1304 // trap_handler_f[OPC_PUTFIELD_QUICK] = opc_putfield_quick;
1305 // trap_handler_f[OPC_PUTFIELD2_QUICK] = opc_putfield2_quick;
1306 // trap_handler_f[OPC_LDC_W_QUICK] = opc_ldc_w_quick;
1307 // trap_handler_f[OPC_LDC_QUICK] = opc_ldc_quick;
1308 trap_handler_f[OPC_LDC_W] = opc_ldc_w;
1309 trap_handler_f[OPC_LDC] = opc_ldc;
1310 trap_handler_f[OPC_MONITORENTER] = opc_monitorenter;
1311 trap_handler_f[OPC_MONITOREXIT] = opc_monitorexit;
1312 trap_handler_f[OPC_GETSTATIC] = opc_getstatic;
1313 // trap_handler_f[OPC_GETSTATIC_QUICK] = opc_getstatic_quick;
1314 // trap_handler_f[OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick;
1315 trap_handler_f[OPC_PUTSTATIC] = opc_putstatic;
1316 trap_handler_f[OPC_PUTSTATIC_QUICK] = opc_putstatic_quick;
1317 trap_handler_f[OPC_PUTSTATIC2_QUICK] = opc_putstatic2_quick;
1318 trap_handler_f[OPC_ANEWARRAY] = opc_anewarray;
1319 trap_handler_f[OPC_ANEWARRAY_QUICK] = opc_anewarray_quick;
1320 trap_handler_f[OPC_NEWARRAY] = opc_newarray;
1321 trap_handler_f[OPC_CHECKCAST] = opc_checkcast;
1322 trap_handler_f[OPC_CHECKCAST_QUICK] = opc_checkcast_quick;
1323 trap_handler_f[OPC_GETFIELD] = opc_getfield;
1324 // trap_handler_f[OPC_GETFIELD_QUICK] = opc_getfield_quick;
1325 // trap_handler_f[OPC_GETFIELD2_QUICK] = opc_getfield2_quick;
1326 trap_handler_f[OPC_FCMPL] = opc_fcmpl;
1327 trap_handler_f[OPC_I2F] = opc_i2f;
1328 // trap_handler_f[OPC_I2D] = opc_i2d;
1329 trap_handler_f[OPC_FMUL] = opc_fmul;
1330 // trap_handler_f[OPC_FADD] = opc_fadd;
1331 // trap_handler_f[OPC_FSUB] = opc_fsub;
1332 // trap_handler_f[OPC_F2I] = opc_f2i;
1334 #if 0
1335 /* Don't think we need it, at least, not in the direct.c form. There the code
1336 * is converted into an internal representation, which is useless for JEM */
1337 PREPARE_MB(mb);//see direct.c (prepare)
1338 #endif
1340 jem.jpc = (unsigned long)mb->code & ~3;
1341 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1342 *(char*)jem.jpc, *((char*)jem.jpc + 1));
1344 do {
1345 int opcode;
1347 jam_dprintf("About to enter JEM at 0x%08x, this = %p. Code:", jem.jpc, this);
1348 for (i = 0; i < 32 && jem.jpc + i < (unsigned long)(mb->code + mb->code_size); i++) {
1349 if (!(i & 0xf))
1350 jam_dprintf("\n0x%04x:", i);
1351 jam_dprintf(" 0x%02x", ((char*)jem.jpc)[i]);
1354 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", mb->max_locals);
1355 for (i = 0; i < min(8, mb->max_locals); i++)
1356 jam_dprintf("LVAR_%d: 0x%08x\n", i, *(lvars_jem - i));
1358 /* On entry we need last Java Operand Stack depth, set it not deeper
1359 * than half hardware stack */
1360 jem.josp = min(5, ostack_depth(frame->ostack, ostack));
1361 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1362 for (i = 0; i < jem.josp; i++)
1363 ostack_pop_u32(frame->ostack, mb->max_stack, ostack,
1364 jos[7 - jem.josp + 1 + i]);
1366 __asm__ __volatile__(
1367 "pushm r0-r7,r10-r11\n"
1368 " mov r8, %[cp]\n"
1369 " mov r9, %[lv0]\n"
1370 " mov lr, %[jpc]\n"
1371 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1372 " mov r11, %[ostack]\n"
1373 " pushm r11\n" /* Need ostack below */
1374 " ldm r11, r0-r7\n" /* Restore Java Operands */
1375 " cp.w r12, 0\n" /* Test josp == 0 */
1376 " breq 4f\n"
1377 "5: incjosp 1\n" /* ... for loop counter, */
1378 " sub r12, 1\n" /* because it can be */
1379 " brne 5b\n" /* one of r0-r7 */
1380 "4: popjc\n" /* Restore Local Variables */
1381 " sub r10, pc, . - trap\n" /* These 3 instructions */
1382 " retj\n" /* have to stay */
1383 "trap: pushjc\n" /* together */
1384 " mfsr r11, 0x58\n" /* JOSP */
1385 " lsl r11, 29\n" /* Clear r11[31:3] using */
1386 " lsr r11, 29\n" /* one register */
1387 " mov r8, r11\n"
1388 " breq 2f\n"
1389 "3: incjosp -1\n"
1390 " sub r11, 1\n"
1391 " brne 3b\n"
1392 "2: popm r11\n" /* ostack */
1393 " stm r11, r0-r7\n" /* Save Java Operands */
1394 " popm r0-r7,r10-r11\n"
1395 " mov %[tpc], r12\n"
1396 " mov %[jpc], lr\n" /* Resume address */
1397 " mfsr %[jecr], 0x54\n" /* JECR */
1398 " mov %[josp], r8\n" /* JOSP */
1399 : [jecr] "=r" (jem.jecr), [tpc] "=r" (jem.trap_pc),
1400 [josp] "+r" (jem.josp), [jpc] "+r" (jem.jpc)
1401 : [cp] "r" (cp->orgPointer), [lv0] "r" (lvars_jem),
1402 [ostack] "r" (jos)
1403 : "r8", "r9", "lr", "r12", "memory"
1406 * trap_pc now holds trap pc, describing which trap has been entered,
1407 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1408 * arguments at bits 7..0 and 15..8,
1409 * josp holds JOSP (JOSP & 7),
1410 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1411 * jpc points at the trapping opcode, in case of exceptions and stack
1412 * over- and underflows, and at the next opcode, in case of a trap
1415 for (i = 0; i < jem.josp; i++)
1416 ostack_push_u32(frame->ostack, mb->max_stack, ostack,
1417 jos[7 - i]);
1419 opcode = (jem.jecr >> 16) & 0xff;
1421 jep = jem.trap_pc & 0xfff;
1423 trap_debug(&jem);
1424 if (jep < 0x280)
1425 done = exception_handler_f[jep >> 7](&jem);
1426 else if (trap_handler_f[opcode])
1427 done = trap_handler_f[opcode](&jem);
1428 else {
1429 /* Unimplemented */
1430 jam_dprintf("Unimplemented Java Opcode 0x%02x\n", opcode);
1431 exitVM(1);
1433 } while (done != JEM_TRAP_HANDLER_FINISH);
1435 return ostack;
1437 rewrite_lock:
1438 // DISPATCH_FIRST;
1440 unused:
1441 jam_dprintf("Unknown Java Opcodes\n");
1442 exitVM(1);
1444 #if 0
1445 //our own trap handlers
1446 #define JEM_TRAP_MULTI_LEVEL_ENTRIES(level) \
1447 DEF_DISPATCHTRAP(level) \
1448 DEF_JAVAEX(level) \
1449 DEF_STACKOVERFLOW(level) \
1450 DEF_STACKUNDERFLOW(level) \
1451 DEF_STACKOVERFLOW1(level) \
1452 DEF_STACKUNDERFLOW1(level) \
1453 DEF_IAFRETURN(level) \
1454 DEF_RETURN(level) \
1455 DEF_LDRETURN(level) \
1456 DEF_IINC(level) \
1457 DEF_CHECKCASTQUICK(level) \
1458 DEF_INSTANCEOFQUICK(level) \
1459 DEF_GETSTATIC(level) \
1460 DEF_PUTSTATIC(level) \
1461 DEF_NEW(level)\
1462 DEF_INVOKESTATIC(level) \
1463 DEF_INVOKEINTERFACEQUICK(level) \
1464 DEF_INVOKEVIRTUALQUICK(level) \
1465 DEF_INVOKESTATICQUICK(level) \
1466 DEF_INVOKENONVIRTUALQUICK(level) \
1467 DEF_XNEWARRAY(level) \
1468 DEF_LONGINSTRPS(level) \
1469 DEF_FLOATINSTRPS(level) \
1470 DEF_DOUBLEINSTRPS(level) \
1471 DEF_OTHERINSTRPS(level)
1474 JEM_TRAP_MULTI_LEVEL_ENTRIES(0);
1475 #endif
1477 #if 0
1478 #define MULTI_LEVEL_OPCODES(level) \
1479 DEF_OPC(OPC_ICONST_M1, level, \
1480 PUSH_##level(-1, 1); \
1483 DEF_OPC_3(OPC_ACONST_NULL, \
1484 OPC_ICONST_0, \
1485 OPC_FCONST_0, level, \
1486 PUSH_##level(0, 1); \
1489 DEF_OPC(OPC_ICONST_1, level, \
1490 PUSH_##level(1, 1); \
1493 DEF_OPC(OPC_ICONST_2, level, \
1494 PUSH_##level(2, 1); \
1497 DEF_OPC(OPC_ICONST_3, level, \
1498 PUSH_##level(3, 1); \
1501 DEF_OPC(OPC_ICONST_4, level, \
1502 PUSH_##level(4, 1); \
1505 DEF_OPC(OPC_ICONST_5, level, \
1506 PUSH_##level(5, 1); \
1509 DEF_OPC(OPC_FCONST_1, level, \
1510 PUSH_##level(FLOAT_1_BITS, 1); \
1513 DEF_OPC(OPC_FCONST_2, level, \
1514 PUSH_##level(FLOAT_2_BITS, 1); \
1517 DEF_OPC(OPC_SIPUSH, level, \
1518 PUSH_##level(DOUBLE_SIGNED(pc), 3); \
1521 DEF_OPC(OPC_BIPUSH, level, \
1522 PUSH_##level(SINGLE_SIGNED(pc), 2); \
1525 DEF_OPC(OPC_LDC_QUICK, level, \
1526 PUSH_##level(RESOLVED_CONSTANT(pc), 2); \
1529 DEF_OPC(OPC_LDC_W_QUICK, level, \
1530 PUSH_##level(CP_INFO(cp, DOUBLE_INDEX(pc)), 3); \
1533 DEF_OPC_3(OPC_ILOAD, \
1534 OPC_FLOAD, \
1535 OPC_ALOAD, level, \
1536 PUSH_##level(lvars[SINGLE_INDEX(pc)], 2); \
1539 DEF_OPC(OPC_ALOAD_THIS, level, \
1540 ALOAD_THIS(level); \
1543 DEF_OPC_2(OPC_ILOAD_0, \
1544 OPC_FLOAD_0, level, \
1545 PUSH_##level(lvars[0], 1) \
1548 DEF_OPC_3(OPC_ILOAD_1, \
1549 OPC_FLOAD_1, \
1550 OPC_ALOAD_1, level, \
1551 PUSH_##level(lvars[1], 1); \
1554 DEF_OPC_3(OPC_ILOAD_2, \
1555 OPC_FLOAD_2, \
1556 OPC_ALOAD_2, level, \
1557 PUSH_##level(lvars[2], 1); \
1560 DEF_OPC_3(OPC_ILOAD_3, \
1561 OPC_FLOAD_3, \
1562 OPC_ALOAD_3, level, \
1563 PUSH_##level(lvars[3], 1); \
1566 DEF_OPC_3(OPC_ISTORE, \
1567 OPC_FSTORE, \
1568 OPC_ASTORE, level, \
1569 POP_##level(lvars[SINGLE_INDEX(pc)], 2); \
1572 DEF_OPC_3(OPC_ISTORE_0, \
1573 OPC_ASTORE_0, \
1574 OPC_FSTORE_0, level, \
1575 POP_##level(lvars[0], 1); \
1578 DEF_OPC_3(OPC_ISTORE_1, \
1579 OPC_ASTORE_1, \
1580 OPC_FSTORE_1, level, \
1581 POP_##level(lvars[1], 1); \
1584 DEF_OPC_3(OPC_ISTORE_2, \
1585 OPC_ASTORE_2, \
1586 OPC_FSTORE_2, level, \
1587 POP_##level(lvars[2], 1); \
1590 DEF_OPC_3(OPC_ISTORE_3, \
1591 OPC_ASTORE_3, \
1592 OPC_FSTORE_3, level, \
1593 POP_##level(lvars[3], 1); \
1596 DEF_OPC(OPC_IADD, level, \
1597 BINARY_OP_##level(+); \
1600 DEF_OPC(OPC_ISUB, level, \
1601 BINARY_OP_##level(-); \
1604 DEF_OPC(OPC_IMUL, level, \
1605 BINARY_OP_##level(*); \
1608 DEF_OPC(OPC_IDIV, level, \
1609 ZERO_DIVISOR_CHECK_##level; \
1610 BINARY_OP_##level(/); \
1613 DEF_OPC(OPC_IREM, level, \
1614 ZERO_DIVISOR_CHECK_##level; \
1615 BINARY_OP_##level(%); \
1618 DEF_OPC(OPC_IAND, level, \
1619 BINARY_OP_##level(&); \
1622 DEF_OPC(OPC_IOR, level, \
1623 BINARY_OP_##level(|); \
1626 DEF_OPC(OPC_IXOR, level, \
1627 BINARY_OP_##level(^); \
1630 DEF_OPC(OPC_INEG, level, \
1631 UNARY_MINUS_##level; \
1634 DEF_OPC(OPC_ISHL, level, \
1635 SHIFT_OP_##level(int, <<); \
1638 DEF_OPC(OPC_ISHR, level, \
1639 SHIFT_OP_##level(int, >>); \
1642 DEF_OPC(OPC_IUSHR, level, \
1643 SHIFT_OP_##level(unsigned int, >>); \
1646 DEF_OPC_2(OPC_IF_ACMPEQ, \
1647 OPC_IF_ICMPEQ, level, \
1648 IF_ICMP_##level(==); \
1651 DEF_OPC_2(OPC_IF_ACMPNE, \
1652 OPC_IF_ICMPNE, level, \
1653 IF_ICMP_##level(!=); \
1656 DEF_OPC(OPC_IF_ICMPLT, level, \
1657 IF_ICMP_##level(<); \
1660 DEF_OPC(OPC_IF_ICMPGE, level, \
1661 IF_ICMP_##level(>=); \
1664 DEF_OPC(OPC_IF_ICMPGT, level, \
1665 IF_ICMP_##level(>); \
1668 DEF_OPC(OPC_IF_ICMPLE, level, \
1669 IF_ICMP_##level(<=); \
1672 DEF_OPC_2(OPC_IFNE, \
1673 OPC_IFNONNULL, level, \
1674 IF_##level(!=); \
1677 DEF_OPC_2(OPC_IFEQ, \
1678 OPC_IFNULL, level, \
1679 IF_##level(==); \
1682 DEF_OPC(OPC_IFLT, level, \
1683 IF_##level(<); \
1686 DEF_OPC(OPC_IFGE, level, \
1687 IF_##level(>=); \
1690 DEF_OPC(OPC_IFGT, level, \
1691 IF_##level(>); \
1694 DEF_OPC(OPC_IFLE, level, \
1695 IF_##level(<=); \
1698 DEF_OPC(OPC_IINC, level, \
1699 lvars[IINC_LVAR_IDX(pc)] += IINC_DELTA(pc); \
1700 DISPATCH(level, 3); \
1703 DEF_OPC(OPC_POP, level, \
1704 POP1_##level; \
1707 DEF_OPC(OPC_POP2, level, \
1708 ostack -= 2 - level; \
1709 DISPATCH(0, 1); \
1712 DEF_OPC(OPC_DUP, level, \
1713 DUP_##level; \
1716 DEF_OPC_3(OPC_IRETURN, \
1717 OPC_ARETURN, \
1718 OPC_FRETURN, level, \
1719 RETURN_##level; \
1722 DEF_OPC(OPC_RETURN, level, \
1723 goto methodReturn; \
1726 DEF_OPC(OPC_GETSTATIC_QUICK, level, \
1727 PUSH_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1730 DEF_OPC(OPC_PUTSTATIC_QUICK, level, \
1731 POP_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1734 DEF_OPC(OPC_GETFIELD_THIS, level, \
1735 GETFIELD_THIS(level); \
1738 DEF_OPC(OPC_GETFIELD_QUICK, level, \
1739 GETFIELD_QUICK_##level; \
1742 #define ZERO_DIVISOR_CHECK_0 \
1743 ZERO_DIVISOR_CHECK((int)ostack[-1]);
1745 #define ZERO_DIVISOR_CHECK_1 \
1746 ZERO_DIVISOR_CHECK((int)cache.i.v1);
1748 #define ZERO_DIVISOR_CHECK_2 \
1749 ZERO_DIVISOR_CHECK((int)cache.i.v2);
1752 #define PUSH_0(value, ins_len) \
1753 *ostack++ = value; \
1754 DISPATCH(0, ins_len);
1757 #define PUSH_1(value, ins_len) \
1758 cache.i.v2 = value; \
1759 DISPATCH(2, ins_len);
1761 #define PUSH_2(value, ins_len) \
1762 *ostack++ = cache.i.v1; \
1763 cache.i.v1 = cache.i.v2; \
1764 cache.i.v2 = value; \
1765 DISPATCH(2, ins_len);
1767 #define POP_0(dest, ins_len) \
1768 dest = *--ostack; \
1769 DISPATCH(0, ins_len);
1771 #define POP_1(dest, ins_len) \
1772 dest = cache.i.v1; \
1773 DISPATCH(0, ins_len);
1775 #define POP_2(dest, ins_len) \
1776 dest = cache.i.v2; \
1777 DISPATCH(1, ins_len);
1779 #define POP1_0 \
1780 ostack--; \
1781 DISPATCH(0, 1);
1783 #define POP1_1 \
1784 DISPATCH(0, 1);
1786 #define POP1_2 \
1787 DISPATCH(1, 1);
1789 #define DUP_0 \
1790 PUSH_0(ostack[-1], 1);
1792 #define DUP_1 \
1793 PUSH_1(cache.i.v1, 1);
1795 #define DUP_2 \
1796 PUSH_2(cache.i.v2, 1);
1798 #define RETURN_0 \
1799 *lvars++ = *--ostack; \
1800 goto methodReturn;
1802 #define RETURN_1 \
1803 *lvars++ = cache.i.v1; \
1804 goto methodReturn;
1806 #define RETURN_2 \
1807 *lvars++ = cache.i.v2; \
1808 goto methodReturn;
1810 #define GETFIELD_QUICK_0 \
1812 Object *obj = (Object *)*--ostack; \
1813 NULL_POINTER_CHECK(obj); \
1814 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1817 #define GETFIELD_QUICK_1 \
1819 Object *obj = (Object *)cache.i.v1; \
1820 NULL_POINTER_CHECK(obj); \
1821 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1824 #define GETFIELD_QUICK_2 \
1826 Object *obj = (Object *)cache.i.v2; \
1827 NULL_POINTER_CHECK(obj); \
1828 PUSH_1(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1831 #define UNARY_MINUS_0 \
1833 int v = (int)*--ostack; \
1834 PUSH_0(-v, 1); \
1837 #define UNARY_MINUS_1 \
1838 PUSH_0(-(int)cache.i.v1, 1);
1840 #define UNARY_MINUS_2 \
1841 PUSH_1(-(int)cache.i.v2, 1);
1843 #define BINARY_OP_0(OP) \
1844 ostack -= 2; \
1845 PUSH_0((int)ostack[0] OP (int)ostack[1], 1);
1847 #define BINARY_OP_1(OP) \
1848 PUSH_0((int)*--ostack OP (int)cache.i.v1, 1);
1850 #define BINARY_OP_2(OP) \
1851 PUSH_0((int)cache.i.v1 OP (int)cache.i.v2, 1);
1853 #define SHIFT_OP_0(TYPE, OP) \
1854 ostack -= 2; \
1855 PUSH_0((TYPE)ostack[0] OP (ostack[1] & 0x1f), 1);
1857 #define SHIFT_OP_1(TYPE, OP) \
1858 PUSH_0((TYPE)*--ostack OP (cache.i.v1 & 0x1f), 1);
1860 #define SHIFT_OP_2(TYPE, OP) \
1861 PUSH_0((TYPE)cache.i.v1 OP (cache.i.v2 & 0x1f), 1);
1863 #define IF_ICMP_0(COND) \
1864 ostack -= 2; \
1865 BRANCH((int)ostack[0] COND (int)ostack[1]);
1867 #define IF_ICMP_1(COND) \
1868 BRANCH((int)*--ostack COND (int)cache.i.v1);
1870 #define IF_ICMP_2(COND) \
1871 BRANCH((int)cache.i.v1 COND (int)cache.i.v2);
1873 #define IF_0(COND) \
1874 BRANCH((int)*--ostack COND 0);
1876 #define IF_1(COND) \
1877 BRANCH((int)cache.i.v1 COND 0);
1879 #define IF_2(COND) \
1880 *ostack++ = cache.i.v1; \
1881 BRANCH((int)cache.i.v2 COND 0);
1883 #define ALOAD_THIS(level)
1885 #define GETFIELD_THIS(level) \
1886 PUSH_##level(INST_DATA(this)[pc->operand.i], 4);
1889 MULTI_LEVEL_OPCODES(0);
1892 DEF_OPC_210(OPC_NOP,
1893 DISPATCH(0, 1);
1897 #define PUSH_LONG(value, ins_len) \
1898 *(u8*)ostack = value; \
1899 ostack += 2; \
1900 DISPATCH(0, ins_len);
1902 DEF_OPC_210_2(
1903 OPC_LCONST_0,
1904 OPC_DCONST_0,
1905 PUSH_LONG(0, 1);
1908 DEF_OPC_210(OPC_DCONST_1,
1909 PUSH_LONG(DOUBLE_1_BITS, 1);
1912 DEF_OPC_210(OPC_LCONST_1,
1913 PUSH_LONG(1, 1);
1916 DEF_OPC_210(OPC_LDC2_W,
1917 PUSH_LONG(CP_LONG(cp, DOUBLE_INDEX(pc)), 3);
1920 DEF_OPC_210_2(
1921 OPC_LLOAD,
1922 OPC_DLOAD,
1923 PUSH_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1926 DEF_OPC_210_2(
1927 OPC_LLOAD_0,
1928 OPC_DLOAD_0,
1929 PUSH_LONG(*(u8*)(&lvars[0]), 1);
1932 DEF_OPC_210_2(
1933 OPC_LLOAD_1,
1934 OPC_DLOAD_1,
1935 PUSH_LONG(*(u8*)(&lvars[1]), 1);
1938 DEF_OPC_210_2(
1939 OPC_LLOAD_2,
1940 OPC_DLOAD_2,
1941 PUSH_LONG(*(u8*)(&lvars[2]), 1);
1944 DEF_OPC_210_2(
1945 OPC_LLOAD_3,
1946 OPC_DLOAD_3,
1947 PUSH_LONG(*(u8*)(&lvars[3]), 1);
1951 #define POP_LONG(dest, ins_len) \
1952 ostack -= 2; \
1953 dest = *(u8*)ostack; \
1954 DISPATCH(0, ins_len);
1957 DEF_OPC_012_2(
1958 OPC_LSTORE,
1959 OPC_DSTORE,
1960 POP_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1963 DEF_OPC_012_2(
1964 OPC_LSTORE_0,
1965 OPC_DSTORE_0,
1966 POP_LONG(*(u8*)(&lvars[0]), 1);
1969 DEF_OPC_012_2(
1970 OPC_LSTORE_1,
1971 OPC_DSTORE_1,
1972 POP_LONG(*(u8*)(&lvars[1]), 1);
1975 DEF_OPC_012_2(
1976 OPC_LSTORE_2,
1977 OPC_DSTORE_2,
1978 POP_LONG(*(u8*)(&lvars[2]), 1);
1981 DEF_OPC_012_2(
1982 OPC_LSTORE_3,
1983 OPC_DSTORE_3,
1984 POP_LONG(*(u8*)(&lvars[3]), 1);
1988 #define ARRAY_LOAD_IDX *--ostack
1989 #define ARRAY_LOAD_ARY *--ostack
1992 #define ARRAY_LOAD(TYPE) \
1994 int idx = ARRAY_LOAD_IDX; \
1995 Object *array = (Object *)ARRAY_LOAD_ARY; \
1997 NULL_POINTER_CHECK(array); \
1998 ARRAY_BOUNDS_CHECK(array, idx); \
1999 PUSH_0(((TYPE *)ARRAY_DATA(array))[idx], 1); \
2002 DEF_OPC_012_2(
2003 OPC_IALOAD,
2004 OPC_FALOAD,
2005 ARRAY_LOAD(int)
2008 DEF_OPC_012(OPC_AALOAD,
2009 ARRAY_LOAD(uintptr_t)
2012 DEF_OPC_012(OPC_BALOAD,
2013 ARRAY_LOAD(signed char)
2016 DEF_OPC_012(OPC_CALOAD,
2017 ARRAY_LOAD(unsigned short)
2020 DEF_OPC_012(OPC_SALOAD,
2021 ARRAY_LOAD(short)
2024 DEF_OPC_012(OPC_LALOAD, {
2025 int idx = ARRAY_LOAD_IDX;
2026 Object *array = (Object *)ARRAY_LOAD_ARY;
2028 NULL_POINTER_CHECK(array);
2029 ARRAY_BOUNDS_CHECK(array, idx);
2030 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
2033 DEF_OPC_012(OPC_DALOAD, {
2034 int idx = ARRAY_LOAD_IDX;
2035 Object *array = (Object *)ARRAY_LOAD_ARY;
2037 NULL_POINTER_CHECK(array);
2038 ARRAY_BOUNDS_CHECK(array, idx);
2039 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
2043 #define ARRAY_STORE_VAL *--ostack
2044 #define ARRAY_STORE_IDX *--ostack
2047 #define ARRAY_STORE(TYPE) \
2049 int val = ARRAY_STORE_VAL; \
2050 int idx = ARRAY_STORE_IDX; \
2051 Object *array = (Object *)*--ostack; \
2053 NULL_POINTER_CHECK(array); \
2054 ARRAY_BOUNDS_CHECK(array, idx); \
2055 ((TYPE *)ARRAY_DATA(array))[idx] = val; \
2056 DISPATCH(0, 1); \
2059 DEF_OPC_012_2(
2060 OPC_IASTORE,
2061 OPC_FASTORE,
2062 ARRAY_STORE(int)
2065 DEF_OPC_012(OPC_BASTORE,
2066 ARRAY_STORE(char);
2069 DEF_OPC_012_2(
2070 OPC_CASTORE,
2071 OPC_SASTORE,
2072 ARRAY_STORE(short);
2075 DEF_OPC_012(OPC_AASTORE, {
2076 Object *obj = (Object*)ARRAY_STORE_VAL;
2077 int idx = ARRAY_STORE_IDX;
2078 Object *array = (Object *)*--ostack;
2080 NULL_POINTER_CHECK(array);
2081 ARRAY_BOUNDS_CHECK(array, idx);
2083 if((obj != NULL) && !arrayStoreCheck(array->class, obj->class))
2084 THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
2086 ((Object**)ARRAY_DATA(array))[idx] = obj;
2087 DISPATCH(0, 1);
2091 DEF_OPC_012_2(
2092 OPC_LASTORE,
2093 OPC_DASTORE, {
2094 int idx = ostack[-3];
2095 Object *array = (Object *)ostack[-4];
2097 ostack -= 4;
2098 NULL_POINTER_CHECK(array);
2099 ARRAY_BOUNDS_CHECK(array, idx);
2101 ((u8 *)ARRAY_DATA(array))[idx] = *(u8*)&ostack[2];
2102 DISPATCH(0, 1);
2107 DEF_OPC_012(OPC_DUP_X1, {
2108 uintptr_t word1 = ostack[-1];
2109 uintptr_t word2 = ostack[-2];
2110 ostack[-2] = word1;
2111 ostack[-1] = word2;
2112 *ostack++ = word1;
2113 DISPATCH(0, 1);
2116 DEF_OPC_012(OPC_DUP_X2, {
2117 uintptr_t word1 = ostack[-1];
2118 uintptr_t word2 = ostack[-2];
2119 uintptr_t word3 = ostack[-3];
2120 ostack[-3] = word1;
2121 ostack[-2] = word3;
2122 ostack[-1] = word2;
2123 *ostack++ = word1;
2124 DISPATCH(0, 1);
2127 DEF_OPC_012(OPC_DUP2, {
2128 ostack[0] = ostack[-2];
2129 ostack[1] = ostack[-1];
2130 ostack += 2;
2131 DISPATCH(0, 1);
2134 DEF_OPC_012(OPC_DUP2_X1, {
2135 uintptr_t word1 = ostack[-1];
2136 uintptr_t word2 = ostack[-2];
2137 uintptr_t word3 = ostack[-3];
2138 ostack[-3] = word2;
2139 ostack[-2] = word1;
2140 ostack[-1] = word3;
2141 ostack[0] = word2;
2142 ostack[1] = word1;
2143 ostack += 2;
2144 DISPATCH(0, 1);
2147 DEF_OPC_012(OPC_DUP2_X2, {
2148 uintptr_t word1 = ostack[-1];
2149 uintptr_t word2 = ostack[-2];
2150 uintptr_t word3 = ostack[-3];
2151 uintptr_t word4 = ostack[-4];
2152 ostack[-4] = word2;
2153 ostack[-3] = word1;
2154 ostack[-2] = word4;
2155 ostack[-1] = word3;
2156 ostack[0] = word2;
2157 ostack[1] = word1;
2158 ostack += 2;
2159 DISPATCH(0, 1);
2162 DEF_OPC_012(OPC_SWAP, {
2163 uintptr_t word1 = ostack[-1];
2164 ostack[-1] = ostack[-2];
2165 ostack[-2] = word1;
2166 DISPATCH(0, 1)
2170 #define BINARY_OP_fp(TYPE, OP) \
2171 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] = \
2172 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] OP\
2173 *(TYPE *)&ostack[-sizeof(TYPE)/4]; \
2174 ostack -= sizeof(TYPE)/4; \
2175 DISPATCH(0, 1);
2177 DEF_OPC_210(OPC_FADD,
2178 BINARY_OP_fp(float, +);
2181 DEF_OPC_210(OPC_DADD,
2182 BINARY_OP_fp(double, +);
2185 DEF_OPC_210(OPC_FSUB,
2186 BINARY_OP_fp(float, -);
2189 DEF_OPC_210(OPC_DSUB,
2190 BINARY_OP_fp(double, -);
2193 DEF_OPC_210(OPC_FMUL,
2194 BINARY_OP_fp(float, *);
2197 DEF_OPC_210(OPC_DMUL,
2198 BINARY_OP_fp(double, *);
2201 DEF_OPC_210(OPC_FDIV,
2202 BINARY_OP_fp(float, /);
2205 DEF_OPC_210(OPC_DDIV,
2206 BINARY_OP_fp(double, /);
2210 #define BINARY_OP_long(OP) \
2211 BINARY_OP_fp(long long, OP)
2213 #define ZERO_DIVISOR_CHECK_long \
2214 ZERO_DIVISOR_CHECK(*(u8*)&ostack[-2]);
2217 DEF_OPC_012(OPC_LADD,
2218 BINARY_OP_long(+);
2221 DEF_OPC_012(OPC_LSUB,
2222 BINARY_OP_long(-);
2225 DEF_OPC_012(OPC_LMUL,
2226 BINARY_OP_long(*);
2229 DEF_OPC_012(OPC_LDIV,
2230 ZERO_DIVISOR_CHECK_long;
2231 BINARY_OP_long(/);
2234 DEF_OPC_012(OPC_LREM,
2235 ZERO_DIVISOR_CHECK_long;
2236 BINARY_OP_long(%);
2239 DEF_OPC_012(OPC_LAND,
2240 BINARY_OP_long(&);
2243 DEF_OPC_012(OPC_LOR,
2244 BINARY_OP_long(|);
2247 DEF_OPC_012(OPC_LXOR,
2248 BINARY_OP_long(^);
2252 #define SHIFT_OP_long(TYPE, OP) \
2254 int shift = *--ostack & 0x3f; \
2255 *(TYPE*)&ostack[-2] = \
2256 *(TYPE*)&ostack[-2] OP shift; \
2257 DISPATCH(0, 1); \
2261 DEF_OPC_012(OPC_LSHL,
2262 SHIFT_OP_long(long long, <<);
2265 DEF_OPC_012(OPC_LSHR,
2266 SHIFT_OP_long(long long, >>);
2269 DEF_OPC_012(OPC_LUSHR,
2270 SHIFT_OP_long(unsigned long long, >>);
2273 DEF_OPC_210(OPC_FREM, {
2274 float v2 = *(float *)&ostack[-1];
2275 float v1 = *(float *)&ostack[-2];
2277 *(float *)&ostack[-2] = fmod(v1, v2);
2278 ostack -= 1;
2279 DISPATCH(0, 1);
2282 DEF_OPC_210(OPC_DREM, {
2283 double v2 = *(double *)&ostack[-2];
2284 double v1 = *(double *)&ostack[-4];
2286 *(double *)&ostack[-4] = fmod(v1, v2);
2287 ostack -= 2;
2288 DISPATCH(0, 1);
2291 #define UNARY_MINUS(TYPE) \
2292 *(TYPE*)&ostack[-sizeof(TYPE)/4] = \
2293 -*(TYPE*)&ostack[-sizeof(TYPE)/4]; \
2294 DISPATCH(0, 1);
2296 DEF_OPC_210(OPC_LNEG,
2297 UNARY_MINUS(long long);
2300 DEF_OPC_210(OPC_FNEG,
2301 UNARY_MINUS(float);
2304 DEF_OPC_210(OPC_DNEG,
2305 UNARY_MINUS(double);
2308 DEF_OPC_210(OPC_I2L, {
2309 ostack -= 1;
2310 PUSH_LONG((int)*ostack, 1);
2313 DEF_OPC_012(OPC_L2I, {
2314 long long l;
2315 #ifdef USE_CACHE
2316 l = cache.l;
2317 #else
2318 ostack -= 2;
2319 l = *(long long*)ostack;
2320 #endif
2321 PUSH_0((int)l, 1);
2324 #define OPC_int2fp(DEST_TYPE) \
2325 ostack -= 1; \
2326 *(DEST_TYPE *)ostack = \
2327 (DEST_TYPE)(int)*ostack; \
2328 ostack += sizeof(DEST_TYPE)/4; \
2329 DISPATCH(0, 1);
2331 DEF_OPC_210(OPC_I2F,
2332 OPC_int2fp(float);
2335 DEF_OPC_210(OPC_I2D,
2336 OPC_int2fp(double);
2339 #define OPC_X2Y(SRC_TYPE, DEST_TYPE) \
2341 SRC_TYPE v; \
2342 ostack -= sizeof(SRC_TYPE)/4; \
2343 v = *(SRC_TYPE *)ostack; \
2344 *(DEST_TYPE *)ostack = (DEST_TYPE)v; \
2345 ostack += sizeof(DEST_TYPE)/4; \
2346 DISPATCH(0, 1); \
2349 DEF_OPC_210(OPC_L2F,
2350 OPC_X2Y(long long, float);
2353 DEF_OPC_210(OPC_L2D,
2354 OPC_X2Y(long long, double);
2357 DEF_OPC_210(OPC_F2D,
2358 OPC_X2Y(float, double);
2361 DEF_OPC_210(OPC_D2F,
2362 OPC_X2Y(double, float);
2365 #define OPC_fp2int(SRC_TYPE) \
2367 int res; \
2368 SRC_TYPE value; \
2369 ostack -= sizeof(SRC_TYPE)/4; \
2370 value = *(SRC_TYPE *)ostack; \
2372 if(value >= (SRC_TYPE)INT_MAX) \
2373 res = INT_MAX; \
2374 else if(value <= (SRC_TYPE)INT_MIN) \
2375 res = INT_MIN; \
2376 else if(value != value) \
2377 res = 0; \
2378 else \
2379 res = (int) value; \
2381 PUSH_0(res, 1); \
2384 DEF_OPC_210(OPC_F2I,
2385 OPC_fp2int(float);
2388 DEF_OPC_210(OPC_D2I,
2389 OPC_fp2int(double);
2392 #define OPC_fp2long(SRC_TYPE) \
2394 long long res; \
2395 SRC_TYPE value; \
2396 ostack -= sizeof(SRC_TYPE)/4; \
2397 value = *(SRC_TYPE *)ostack; \
2399 if(value >= (SRC_TYPE)LLONG_MAX) \
2400 res = LLONG_MAX; \
2401 else if(value <= (SRC_TYPE)LLONG_MIN) \
2402 res = LLONG_MIN; \
2403 else if(value != value) \
2404 res = 0; \
2405 else \
2406 res = (long long) value; \
2408 PUSH_LONG(res, 1); \
2411 DEF_OPC_210(OPC_F2L,
2412 OPC_fp2long(float);
2415 DEF_OPC_210(OPC_D2L,
2416 OPC_fp2long(double);
2419 DEF_OPC_210(OPC_I2B, {
2420 signed char v = *--ostack & 0xff;
2421 PUSH_0(v, 1);
2424 DEF_OPC_210(OPC_I2C, {
2425 int v = *--ostack & 0xffff;
2426 PUSH_0(v, 1);
2429 DEF_OPC_210(OPC_I2S, {
2430 signed short v = *--ostack & 0xffff;
2431 PUSH_0((int) v, 1);
2435 DEF_OPC_012(OPC_LCMP, {
2436 long long v2 = *(long long*)&ostack[-2];
2437 long long v1 = *(long long*)&ostack[-4];
2438 ostack[-4] = (v1 == v2) ? 0 : ((v1 < v2) ? -1 : 1);
2439 ostack -= 3;
2440 DISPATCH(0, 1);
2444 #define FCMP(TYPE, isNan) \
2445 ({ \
2446 int res; \
2447 TYPE v1, v2; \
2448 ostack -= sizeof(TYPE)/4; v2 = *(TYPE *)ostack; \
2449 ostack -= sizeof(TYPE)/4; v1 = *(TYPE *)ostack; \
2450 if(v1 == v2) \
2451 res = 0; \
2452 else if(v1 < v2) \
2453 res = -1; \
2454 else if(v1 > v2) \
2455 res = 1; \
2456 else \
2457 res = isNan; \
2458 PUSH_0(res, 1); \
2461 DEF_OPC_210(OPC_DCMPG,
2462 FCMP(double, 1);
2465 DEF_OPC_210(OPC_DCMPL,
2466 FCMP(double, -1);
2469 DEF_OPC_210(OPC_FCMPG,
2470 FCMP(float, 1);
2473 DEF_OPC_210(OPC_FCMPL,
2474 FCMP(float, -1);
2478 DEF_OPC_210_2(
2479 OPC_GOTO,
2480 OPC_GOTO_W,
2481 BRANCH(TRUE);
2484 DEF_OPC_210_2(
2485 OPC_JSR,
2486 OPC_JSR_W,
2487 *ostack++ = (uintptr_t)pc;
2488 BRANCH(TRUE);
2491 DEF_OPC_210(OPC_RET,
2492 pc = (CodePntr)lvars[SINGLE_INDEX(pc)];
2493 DISPATCH_RET(3);
2496 DEF_OPC_012_2(
2497 OPC_LRETURN,
2498 OPC_DRETURN,
2499 ostack -= 2;
2500 *(u8*)lvars = *(u8*)ostack;
2501 lvars += 2;
2502 goto methodReturn;
2505 DEF_OPC_210(OPC_ARRAYLENGTH, {
2506 Object *array = (Object *)*--ostack;
2508 NULL_POINTER_CHECK(array);
2509 PUSH_0(ARRAY_LEN(array), 1);
2512 DEF_OPC_210(OPC_ATHROW, {
2513 Object *obj = (Object *)ostack[-1];
2514 frame->last_pc = pc;
2515 NULL_POINTER_CHECK(obj);
2517 ee->exception = obj;
2518 goto throwException;
2521 DEF_OPC_210(OPC_NEWARRAY, {
2522 int type = ARRAY_TYPE(pc);
2523 int count = *--ostack;
2524 Object *obj;
2526 frame->last_pc = pc;
2527 if((obj = allocTypeArray(type, count)) == NULL)
2528 goto throwException;
2530 PUSH_0((uintptr_t)obj, 2);
2533 DEF_OPC_210(OPC_MONITORENTER, {
2534 Object *obj = (Object *)*--ostack;
2535 NULL_POINTER_CHECK(obj);
2536 objectLock(obj);
2537 DISPATCH(0, 1);
2540 DEF_OPC_210(OPC_MONITOREXIT, {
2541 Object *obj = (Object *)*--ostack;
2542 NULL_POINTER_CHECK(obj);
2543 objectUnlock(obj);
2544 DISPATCH(0, 1);
2547 DEF_OPC_RW(OPC_LDC, ({
2548 int idx, cache;
2549 Operand operand;
2551 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_LDC, idx, cache);
2553 frame->last_pc = pc;
2555 operand.u = resolveSingleConstant(mb->class, idx);
2557 if(exceptionOccured0(ee))
2558 goto throwException;
2560 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass ||
2561 CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
2562 operand.i = idx;
2563 OPCODE_REWRITE(OPC_LDC_W_QUICK, cache, operand);
2564 } else
2565 OPCODE_REWRITE(OPC_LDC_QUICK, cache, operand);
2567 REDISPATCH
2568 });)
2570 DEF_OPC_210(OPC_TABLESWITCH, {
2571 SwitchTable *table = (SwitchTable*)pc->operand.pntr;
2572 int index = *--ostack;
2574 if(index < table->low || index > table->high)
2575 pc = table->deflt;
2576 else
2577 pc = table->entries[index - table->low];
2579 DISPATCH_SWITCH
2582 DEF_OPC_210(OPC_LOOKUPSWITCH, {
2583 LookupTable *table = (LookupTable*)pc->operand.pntr;
2584 int key = *--ostack;
2585 int i;
2587 for(i = 0; (i < table->num_entries) && (key != table->entries[i].key); i++);
2589 pc = (i == table->num_entries ? table->deflt
2590 : table->entries[i].handler);
2591 DISPATCH_SWITCH
2594 DEF_OPC_RW(OPC_GETSTATIC, ({
2595 int idx, cache;
2596 FieldBlock *fb;
2597 Operand operand;
2599 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETSTATIC, idx, cache);
2601 frame->last_pc = pc;
2602 fb = resolveField(mb->class, idx);
2604 if(exceptionOccured0(ee))
2605 goto throwException;
2607 operand.pntr = fb;
2608 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2609 OPC_GETSTATIC2_QUICK : OPC_GETSTATIC_QUICK), cache, operand);
2611 REDISPATCH
2612 });)
2614 DEF_OPC_RW(OPC_PUTSTATIC, ({
2615 int idx, cache;
2616 FieldBlock *fb;
2617 Operand operand;
2619 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTSTATIC, idx, cache);
2621 frame->last_pc = pc;
2622 fb = resolveField(mb->class, idx);
2624 if(exceptionOccured0(ee))
2625 goto throwException;
2627 operand.pntr = fb;
2628 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2629 OPC_PUTSTATIC2_QUICK : OPC_PUTSTATIC_QUICK), cache, operand);
2631 REDISPATCH
2632 });)
2634 DEF_OPC_RW(OPC_GETFIELD, ({
2635 int idx, cache;
2636 FieldBlock *fb;
2637 Operand operand;
2639 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETFIELD, idx, cache);
2641 frame->last_pc = pc;
2642 fb = resolveField(mb->class, idx);
2644 if(exceptionOccured0(ee))
2645 goto throwException;
2647 operand.i = fb->offset;
2648 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2649 OPC_GETFIELD2_QUICK : OPC_GETFIELD_QUICK), cache, operand);
2651 REDISPATCH
2652 });)
2654 DEF_OPC_RW(OPC_PUTFIELD, ({
2655 int idx, cache;
2656 FieldBlock *fb;
2657 Operand operand;
2659 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTFIELD, idx, cache);
2661 frame->last_pc = pc;
2662 fb = resolveField(mb->class, idx);
2664 if(exceptionOccured0(ee))
2665 goto throwException;
2667 operand.i = fb->offset;
2668 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2669 OPC_PUTFIELD2_QUICK : OPC_PUTFIELD_QUICK), cache, operand);
2671 REDISPATCH
2672 });)
2674 DEF_OPC_RW(OPC_INVOKEVIRTUAL, ({
2675 int idx, cache;
2676 Operand operand;
2678 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEVIRTUAL, idx, cache);
2680 frame->last_pc = pc;
2681 new_mb = resolveMethod(mb->class, idx);
2683 if(exceptionOccured0(ee))
2684 goto throwException;
2686 operand.uu.u1 = new_mb->args_count;
2687 operand.uu.u2 = new_mb->method_table_index;
2688 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2689 REDISPATCH
2690 });)
2692 DEF_OPC_RW(OPC_INVOKESPECIAL, ({
2693 int idx, cache;
2694 Operand operand;
2696 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESPECIAL, idx, cache);
2698 frame->last_pc = pc;
2699 new_mb = resolveMethod(mb->class, idx);
2701 if(exceptionOccured0(ee))
2702 goto throwException;
2704 /* Check if invoking a super method... */
2705 if((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
2706 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
2708 operand.i = new_mb->method_table_index;
2709 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
2710 } else {
2711 operand.pntr = new_mb;
2712 OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand);
2715 REDISPATCH
2716 });)
2718 DEF_OPC_RW(OPC_INVOKESTATIC, ({
2719 int idx, cache;
2720 Operand operand;
2722 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESTATIC, idx, cache);
2724 frame->last_pc = pc;
2725 new_mb = resolveMethod(mb->class, idx);
2727 if(exceptionOccured0(ee))
2728 goto throwException;
2730 operand.pntr = new_mb;
2731 OPCODE_REWRITE(OPC_INVOKESTATIC_QUICK, cache, operand);
2732 REDISPATCH
2733 });)
2735 DEF_OPC_RW(OPC_INVOKEINTERFACE, ({
2736 int idx, cache;
2737 Operand operand;
2739 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEINTERFACE, idx, cache);
2741 frame->last_pc = pc;
2742 new_mb = resolveInterfaceMethod(mb->class, idx);
2744 if(exceptionOccured0(ee))
2745 goto throwException;
2747 if(CLASS_CB(new_mb->class)->access_flags & ACC_INTERFACE) {
2748 operand.uu.u1 = idx;
2749 operand.uu.u2 = 0;
2750 OPCODE_REWRITE(OPC_INVOKEINTERFACE_QUICK, cache, operand);
2751 } else {
2752 operand.uu.u1 = new_mb->args_count;
2753 operand.uu.u2 = new_mb->method_table_index;
2754 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2757 REDISPATCH
2758 });)
2760 DEF_OPC_RW(OPC_MULTIANEWARRAY, ({
2761 int idx = pc->operand.uui.u1;
2762 int cache = pc->operand.uui.i;
2764 frame->last_pc = pc;
2765 resolveClass(mb->class, idx, FALSE);
2767 if(exceptionOccured0(ee))
2768 goto throwException;
2770 OPCODE_REWRITE(OPC_MULTIANEWARRAY_QUICK, cache, pc->operand);
2771 REDISPATCH
2772 });)
2774 DEF_OPC_RW_4(OPC_NEW, OPC_ANEWARRAY, OPC_CHECKCAST, OPC_INSTANCEOF, ({
2775 int idx = pc->operand.uui.u1;
2776 int opcode = pc->operand.uui.u2;
2777 int cache = pc->operand.uui.i;
2778 Class *class;
2780 frame->last_pc = pc;
2781 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
2783 if(exceptionOccured0(ee))
2784 goto throwException;
2786 if(opcode == OPC_NEW) {
2787 ClassBlock *cb = CLASS_CB(class);
2788 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
2789 signalException("java/lang/InstantiationError", cb->name);
2790 goto throwException;
2794 OPCODE_REWRITE((opcode + OPC_NEW_QUICK-OPC_NEW), cache, pc->operand);
2795 REDISPATCH
2796 });)
2798 DEF_OPC_210(OPC_GETSTATIC2_QUICK, {
2799 FieldBlock *fb = RESOLVED_FIELD(pc);
2800 PUSH_LONG(*(u8*)&fb->static_value, 3);
2803 DEF_OPC_012(OPC_PUTSTATIC2_QUICK, {
2804 FieldBlock *fb = RESOLVED_FIELD(pc);
2805 POP_LONG(*(u8*)&fb->static_value, 3);
2808 DEF_OPC_210(OPC_GETFIELD2_QUICK, {
2809 Object *obj = (Object *)*--ostack;
2810 NULL_POINTER_CHECK(obj);
2812 PUSH_LONG(*(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])), 3);
2816 DEF_OPC_012(OPC_PUTFIELD2_QUICK, {
2817 Object *obj = (Object *)ostack[-3];
2819 ostack -= 3;
2820 NULL_POINTER_CHECK(obj);
2821 *(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])) = *(u8*)&ostack[1];
2822 DISPATCH(0, 3);
2825 DEF_OPC_012(OPC_PUTFIELD_QUICK, {
2826 Object *obj = (Object *)ostack[-2];
2828 ostack -= 2;
2829 NULL_POINTER_CHECK(obj);
2830 INST_DATA(obj)[SINGLE_INDEX(pc)] = ostack[1];
2831 DISPATCH(0, 3);
2835 DEF_OPC_210(OPC_INVOKESUPER_QUICK, {
2836 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)];
2837 arg1 = ostack - (new_mb->args_count);
2838 NULL_POINTER_CHECK(*arg1);
2839 goto invokeMethod;
2842 DEF_OPC_210(OPC_INVOKENONVIRTUAL_QUICK, {
2843 new_mb = RESOLVED_METHOD(pc);
2844 arg1 = ostack - (new_mb->args_count);
2845 NULL_POINTER_CHECK(*arg1);
2846 goto invokeMethod;
2849 DEF_OPC_210(OPC_INVOKESTATIC_QUICK, {
2850 new_mb = RESOLVED_METHOD(pc);
2851 arg1 = ostack - new_mb->args_count;
2852 goto invokeMethod;
2855 DEF_OPC_210(OPC_INVOKEINTERFACE_QUICK, {
2856 int mtbl_idx;
2857 ClassBlock *cb;
2858 int cache = INV_INTF_CACHE(pc);
2860 new_mb = (MethodBlock *)CP_INFO(cp, INV_INTF_IDX(pc));
2861 arg1 = ostack - new_mb->args_count;
2863 NULL_POINTER_CHECK(*arg1);
2865 cb = CLASS_CB(new_class = (*(Object **)arg1)->class);
2867 if((cache >= cb->imethod_table_size) ||
2868 (new_mb->class != cb->imethod_table[cache].interface)) {
2869 for(cache = 0; (cache < cb->imethod_table_size) &&
2870 (new_mb->class != cb->imethod_table[cache].interface); cache++);
2872 if(cache == cb->imethod_table_size)
2873 THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
2874 "unimplemented interface");
2876 INV_INTF_CACHE(pc) = cache;
2879 mtbl_idx = cb->imethod_table[cache].offsets[new_mb->method_table_index];
2880 new_mb = cb->method_table[mtbl_idx];
2882 goto invokeMethod;
2885 DEF_OPC_210(OPC_NEW_QUICK, {
2886 Class *class = RESOLVED_CLASS(pc);
2887 Object *obj;
2889 frame->last_pc = pc;
2890 if((obj = allocObject(class)) == NULL)
2891 goto throwException;
2893 PUSH_0((uintptr_t)obj, 3);
2896 DEF_OPC_210(OPC_ANEWARRAY_QUICK, {
2897 Class *class = RESOLVED_CLASS(pc);
2898 char *name = CLASS_CB(class)->name;
2899 int count = *--ostack;
2900 Class *array_class;
2901 char *ac_name;
2902 Object *obj;
2904 frame->last_pc = pc;
2906 if(count < 0) {
2907 signalException("java/lang/NegativeArraySizeException", NULL);
2908 goto throwException;
2911 ac_name = sysMalloc(strlen(name) + 4);
2913 if(name[0] == '[')
2914 strcat(strcpy(ac_name, "["), name);
2915 else
2916 strcat(strcat(strcpy(ac_name, "[L"), name), ";");
2918 array_class = findArrayClassFromClass(ac_name, mb->class);
2919 free(ac_name);
2921 if(exceptionOccured0(ee))
2922 goto throwException;
2924 if((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
2925 goto throwException;
2927 PUSH_0((uintptr_t)obj, 3);
2930 DEF_OPC_210(OPC_CHECKCAST_QUICK, {
2931 Class *class = RESOLVED_CLASS(pc);
2932 Object *obj = (Object*)ostack[-1];
2934 if((obj != NULL) && !isInstanceOf(class, obj->class))
2935 THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
2937 DISPATCH(0, 3);
2940 DEF_OPC_210(OPC_INSTANCEOF_QUICK, {
2941 Class *class = RESOLVED_CLASS(pc);
2942 Object *obj = (Object*)ostack[-1];
2944 if(obj != NULL)
2945 ostack[-1] = isInstanceOf(class, obj->class);
2947 DISPATCH(0, 3);
2950 DEF_OPC_210(OPC_MULTIANEWARRAY_QUICK, ({
2951 Class *class = RESOLVED_CLASS(pc);
2952 int i, dim = MULTI_ARRAY_DIM(pc);
2953 Object *obj;
2955 ostack -= dim;
2956 frame->last_pc = pc;
2958 for(i = 0; i < dim; i++)
2959 if((intptr_t)ostack[i] < 0) {
2960 signalException("java/lang/NegativeArraySizeException", NULL);
2961 goto throwException;
2964 if((obj = allocMultiArray(class, dim, (intptr_t *)ostack)) == NULL)
2965 goto throwException;
2967 PUSH_0((uintptr_t)obj, 4);
2968 });)
2970 /* Special bytecode which forms the body of an abstract method.
2971 If it is invoked it'll throw an abstract method exception. */
2973 DEF_OPC_210(OPC_ABSTRACT_METHOD_ERROR, {
2974 /* As the method has been invoked, a frame will exist for
2975 the abstract method itself. Pop this to get the correct
2976 exception stack trace. */
2977 ee->last_frame = frame->prev;
2979 /* Throw the exception */
2980 signalException("java/lang/AbstractMethodError", mb->name);
2981 goto throwException;
2986 DEF_OPC_210(OPC_INVOKEVIRTUAL_QUICK, {
2987 arg1 = ostack - INV_QUICK_ARGS(pc);
2988 NULL_POINTER_CHECK(*arg1);
2990 new_class = (*(Object **)arg1)->class;
2991 new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(pc)];
2993 goto invokeMethod;
2996 invokeMethod:
2998 #ifdef JEM
2999 #else
3000 /* Create new frame first. This is also created for natives
3001 so that they appear correctly in the stack trace */
3003 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
3004 Object *sync_ob = NULL;
3006 frame->last_pc = pc;
3007 ostack = (uintptr_t *)(new_frame+1);
3009 if((char*)(ostack + new_mb->max_stack) > ee->stack_end) {
3010 if(ee->overflow++) {
3011 /* Overflow when we're already throwing stack overflow.
3012 Stack extension should be enough to throw exception,
3013 so something's seriously gone wrong - abort the VM! */
3014 jam_printf("Fatal stack overflow! Aborting VM.\n");
3015 exitVM(1);
3017 ee->stack_end += STACK_RED_ZONE_SIZE;
3018 THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
3021 new_frame->mb = new_mb;
3022 new_frame->lvars = arg1;
3023 new_frame->ostack = ostack;
3024 new_frame->prev = frame;
3026 ee->last_frame = new_frame;
3028 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
3029 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1;
3030 objectLock(sync_ob);
3033 if(new_mb->access_flags & ACC_NATIVE) {
3034 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
3035 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
3037 if(sync_ob)
3038 objectUnlock(sync_ob);
3040 ee->last_frame = frame;
3042 if(exceptionOccured0(ee))
3043 goto throwException;
3044 DISPATCH(0, *pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
3045 } else {
3046 PREPARE_MB(new_mb);
3048 frame = new_frame;
3049 mb = new_mb;
3050 lvars = new_frame->lvars;
3051 this = (Object*)lvars[0];
3052 pc = (CodePntr)mb->code;
3053 cp = &(CLASS_CB(mb->class)->constant_pool);
3055 DISPATCH_FIRST
3056 #endif
3059 methodReturn:
3060 #ifdef JEM
3061 #else
3062 /* Set interpreter state to previous frame */
3064 frame = frame->prev;
3066 if(frame->mb == NULL) {
3067 /* The previous frame is a dummy frame - this indicates
3068 top of this Java invocation. */
3069 return ostack;
3072 if(mb->access_flags & ACC_SYNCHRONIZED) {
3073 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
3074 objectUnlock(sync_ob);
3077 mb = frame->mb;
3078 ostack = lvars;
3079 lvars = frame->lvars;
3080 this = (Object*)lvars[0];
3081 pc = frame->last_pc;
3082 cp = &(CLASS_CB(mb->class)->constant_pool);
3084 /* Pop frame */
3085 ee->last_frame = frame;
3087 DISPATCH_METHOD_RET(*pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
3088 #endif
3091 throwException:
3093 Object *excep = ee->exception;
3094 ee->exception = NULL;
3096 pc = findCatchBlock(excep->class);
3098 /* If we didn't find a handler, restore exception and
3099 return to previous invocation */
3101 if(pc == NULL) {
3102 ee->exception = excep;
3103 return NULL;
3106 /* If we're handling a stack overflow, reduce the stack
3107 back past the red zone to enable handling of further
3108 overflows */
3110 if(ee->overflow) {
3111 ee->overflow = FALSE;
3112 ee->stack_end -= STACK_RED_ZONE_SIZE;
3115 /* Setup intepreter to run the found catch block */
3117 frame = ee->last_frame;
3118 mb = frame->mb;
3119 ostack = frame->ostack;
3120 lvars = frame->lvars;
3121 this = (Object*)lvars[0];
3122 cp = &(CLASS_CB(mb->class)->constant_pool);
3124 *ostack++ = (uintptr_t)excep;
3126 /* Dispatch to the first bytecode */
3128 DISPATCH_FIRST
3130 #endif /* 0 */
3133 #ifndef executeJava
3134 void initialiseInterpreter(InitArgs *args) {
3135 initialiseDirect(args);
3137 #endif
3139 #endif //JEM