Whitespace fixes
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blob5adbaeed63efa30e1306304d74bcc701735d1f0a
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 /* These static variables come from the time when there was only one function in
52 * this file. So, we are pretty sure they must be shared. An attempt to pack
53 * them all in struct and pass a pointer to it around ended up in a way too ugly
54 * and suboptimal code. FIXME: fix when going multithreaded. */
56 static MethodBlock *mb;
57 static uintptr_t *lvars_jem;
58 static uintptr_t *ostack;
59 static ConstantPool *cp;
60 static Object *this;
61 static MethodBlock *new_mb;
62 static uintptr_t *arg1;
63 static Frame *frame;
64 static uintptr_t *lvars;
65 static Class *new_class;
67 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
69 #define JEM_THROW_EXCEPTION(excep_name, message) \
70 ({ \
71 frame->last_pc = (CodePntr)jem->jpc; \
72 signalException(excep_name, message); \
73 jem_throwException(jem); \
76 #define JEM_NULL_POINTER_CHECK(ref) \
77 if(!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
79 #define OSTACK_ASCENDING
81 #ifdef OSTACK_ASCENDING
83 #define ostack_overflows(base, size, top) ((base) + (size) >= (top))
85 #ifndef OSTACK_DEBUG
87 #define ostack_push_u32(base, size, top, data) ({ \
88 *(top)++ = (data); \
89 0; \
92 #define ostack_pop_u32(base, size, top, data) ({ \
93 (data) = (typeof(data))*--(top); \
94 0; \
97 #define ostack_push_u64(base, size, top, data) ({ \
98 *(uint64_t *)(top) = *(uint64_t *)&(data); \
99 (top) = (typeof(top))((uint64_t *)top + 1); \
100 0; \
103 #define ostack_pop_u64(base, size, top, data) ({ \
104 (top) = (typeof(top))((uint64_t *)(top) - 1); \
105 *(uint64_t *)&(data) = *(uint64_t *)(top); \
106 0; \
109 #define ostack_read_u32(base, top, offset, data) ({ \
110 *(data) = *(typeof(data))((top) - (offset) - 1);\
111 0; \
114 #define ostack_address(base, size, offset) ((base) + (offset))
116 #define ostack_depth(base, top) ((top) - (base))
118 #else
120 #define ostack_push_u32(base, size, top, data) ({ \
121 if ((size) <= (top) - (base)) \
122 -ENOMEM; \
123 else { \
124 *(top)++ = (data); \
125 0; \
129 #define ostack_pop_u32(base, size, top, data) ({ \
130 if ((top) <= (base)) \
131 -ENOMEM; \
132 else { \
133 (data) = *--(top); \
134 0; \
138 #define ostack_push_u64(base, size, top, data) ({ \
139 if ((size) <= (top) - (base)) \
140 -ENOMEM; \
141 else { \
142 *(uint64_t *)(top) = *(uint64_t *)&(data); \
143 (top) = (typeof(top))((uint64_t *)top + 1); \
144 0; \
148 #define ostack_pop_u64(base, size, top, data) ({ \
149 if ((top) <= (base)) \
150 -ENOMEM; \
151 else { \
152 (top) = (typeof(top))((uint64_t *)(top) - 1); \
153 *(uint64_t *)&(data) = *(uint64_t *)(top); \
154 0; \
158 #define ostack_read_u32(base, top, offset, data) ({ \
159 uint32_t _o = (offset), _t = (top); \
160 if (_o > _t - (base)) \
161 -ENOMEM; \
162 else { \
163 *(data) = *(_t - _o - 1); \
164 0; \
168 #define ostack_address(base, size, offset) ({ \
169 uint32_t _o = (offset); \
170 if (_o >= (size)) \
171 -ENOMEM; \
172 else \
173 (base) + _o; \
176 #define ostack_depth(base, top) ({ \
177 uint32_t _b = (base), _t = (top); \
178 if (_t < _b) \
179 -ENOMEM; \
180 else \
181 _t - _b; \
184 #endif
185 #endif
187 /*********************************************
188 * JEM Trap Handlers **
189 * *******************************************/
190 static int trap_debug(struct jem_state *jem)
192 #ifdef JEM_DEBUG
193 union {
194 struct {
195 uint8_t dummy;
196 uint8_t opcode;
197 uint8_t op1;
198 uint8_t op2;
199 } s;
200 uint32_t i;
201 } jecr_u;
202 int i;
204 jecr_u.i = jem->jecr;
206 jam_printf("Trap 0x%08x: opcode 0x%x @ 0x%08x, operand 1 0x%x, operand2 0x%x. Operands:\n",
207 jem->trap_pc, jecr_u.s.opcode, jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
209 for (i = 0; i < jem->josp; i++) {
210 uint32_t v;
211 if (ostack_read_u32(frame->ostack, ostack, i, &v) >= 0)
212 jam_printf("\tToS-%d: 0x%x\n", i, v);
214 #endif
215 return 1;
219 static int jem_throwException(struct jem_state *jem)
221 ExecEnv *ee = getExecEnv();
222 Object *excep = ee->exception;
223 ee->exception = NULL;
225 jem->jpc = (unsigned long)findCatchBlock(excep->class);
226 jam_printf("Found exception handler at 0x%08x\n", jem->jpc);
228 /* If we didn't find a handler, restore exception and
229 return to previous invocation */
231 if (!jem->jpc) {
232 ee->exception = excep;
233 /* Original code had a "return NULL" here, which means, end of
234 * executeJava */
235 return JEM_TRAP_HANDLER_FINISH;
238 /* If we're handling a stack overflow, reduce the stack
239 back past the red zone to enable handling of further
240 overflows */
242 if (ee->overflow) {
243 ee->overflow = FALSE;
244 ee->stack_end -= STACK_RED_ZONE_SIZE;
247 /* Setup intepreter to run the found catch block */
249 frame = ee->last_frame;
250 mb = frame->mb;
251 ostack = frame->ostack;
252 lvars = frame->lvars;
253 this = (Object*)lvars[0];
254 cp = &(CLASS_CB(mb->class)->constant_pool);
256 /* FIXME: don't know if this is correct, depends how we implement
257 * exceptions */
258 ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uint32_t)excep);
260 /* Dispatch to the first bytecode */
261 return 0;
264 static int opc_return(struct jem_state *jem)
266 ExecEnv *ee = getExecEnv();
267 /* Set interpreter state to previous frame */
269 if (frame->prev->mb == NULL) {
270 /* The previous frame is a dummy frame - this indicates
271 top of this Java invocation. */
272 return 1;
275 if (frame->lvars_jem != NULL)
276 sysFree(frame->lvars_jem - frame->mb->max_locals);
278 frame = frame->prev;
280 if (mb->access_flags & ACC_SYNCHRONIZED) {
281 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
282 objectUnlock(sync_ob);
285 mb = frame->mb;
286 ostack = lvars;
287 lvars = frame->lvars;
288 lvars_jem = frame->lvars_jem - 1;
289 this = (Object*)(*lvars_jem);
290 jem->jpc = (uint32_t)frame->last_pc;
291 cp = &(CLASS_CB(mb->class)->constant_pool);
293 /* Pop frame */
294 ee->last_frame = frame;
296 return 0;
299 static int invokeMethod(struct jem_state *jem)
301 ExecEnv *ee = getExecEnv();
302 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
303 Object *sync_ob = NULL;
304 int i;
306 jam_dprintf("[invokeMethod] with args count %d \n", new_mb->args_count);
307 jam_dprintf("[invokeMethod] new frame start %x\n", new_frame);
309 frame->last_pc = (CodePntr)jem->jpc;
310 ostack = (uintptr_t *)(new_frame + 1);
312 if (ostack_overflows(ostack, new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
313 if(ee->overflow++) {
314 /* Overflow when we're already throwing stack overflow.
315 Stack extension should be enough to throw exception,
316 so something's seriously gone wrong - abort the VM! */
317 jam_printf("Fatal stack overflow! Aborting VM.\n");
318 exitVM(1);
320 ee->stack_end += STACK_RED_ZONE_SIZE;
321 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
324 //TODO
325 new_frame->mb = new_mb;
326 new_frame->lvars = arg1;
327 //TODO: it seemed lvars is in java stack,but jos[8] should be part of java stack
328 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
329 // Here still not touch the java stack,allocate lvars_jem from native heap
331 new_frame->lvars_jem = sysMalloc(new_mb->max_locals * sizeof(uintptr_t));
332 new_frame->lvars_jem = new_frame->lvars_jem + new_mb->max_locals;
333 jam_dprintf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame->lvars_jem);
335 for (i = 0; i < new_mb->args_count; i++)
336 *(new_frame->lvars_jem - 1 - i) = *(arg1 + i);
338 new_frame->ostack = ostack;
339 new_frame->prev = frame;
341 ee->last_frame = new_frame;
343 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
344 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1;
345 objectLock(sync_ob);
348 if(new_mb->access_flags & ACC_NATIVE) {
349 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
350 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
352 if(sync_ob)
353 objectUnlock(sync_ob);
355 ee->last_frame = frame;
357 if(exceptionOccured0(ee)){
358 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
359 return jem_throwException(jem);
360 //exitVM(1);
363 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
364 return 0;
365 } else {
366 frame = new_frame;
367 mb = new_mb;
368 lvars = frame->lvars;
369 lvars_jem = new_frame->lvars_jem - 1;
370 this = (Object*)(*lvars_jem);
371 jem->jpc = (unsigned long)mb->code & ~3;
372 cp = &(CLASS_CB(mb->class)->constant_pool);
374 jam_dprintf("[invokeMethod] invoke virtual method: frame %x mb %x "
375 "lvars %x jpc %x cp %x \n", frame, mb, lvars_jem, jem->jpc, cp);
377 jam_dprintf("[invokeMethod] finish virtual method invoke, return to loop\n");
379 return 0;
382 static int opc_invokesuper_quick(struct jem_state *jem)
384 Operand *operand = &jem->operand;
386 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
387 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[operand->i];
388 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d \n", new_mb->args_count);
390 // set up jem operand stack
391 arg1 = ostack_address(frame->ostack, mb->max_stack,
392 ostack - frame->ostack - new_mb->args_count);
393 JEM_NULL_POINTER_CHECK(*arg1);
394 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x \n", *arg1);
395 return invokeMethod(jem);
398 static int opc_invokenonvirtual_quick(struct jem_state *jem)
400 Operand *operand = &jem->operand;
402 new_mb = (MethodBlock*)operand->pntr;
403 jam_dprintf("[OPC_INVOKENONVIRTUAL_QUICK] new methodblock %s (%x) with %d args\n",
404 new_mb->name, new_mb, new_mb->args_count);
405 arg1 = ostack_address(frame->ostack, mb->max_stack,
406 ostack - frame->ostack - new_mb->args_count);
407 jam_dprintf("[OP_INVOKENONVIRTUAL_QUICK] arg1 %x \n", *arg1);
408 JEM_NULL_POINTER_CHECK(*arg1);
409 return invokeMethod(jem);
412 static int opc_invokevirtual_quick(struct jem_state *jem)
414 arg1 = ostack_address(frame->ostack, mb->max_stack,
415 ostack - frame->ostack - INV_QUICK_ARGS(jem));
416 JEM_NULL_POINTER_CHECK(arg1);
418 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object 0x%08x\n", arg1);
419 new_class = (*(Object **)arg1)->class;
420 new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(jem)];
421 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x on class %x\n",
422 new_mb, new_class);
423 return invokeMethod(jem);
426 static int opc_invokevirtual(struct jem_state *jem)
428 int idx;
429 ExecEnv *ee = getExecEnv();
431 idx = jem->jecr & 0xffff;
432 frame->last_pc = (CodePntr)jem->jpc;
433 new_mb = resolveMethod(mb->class, idx);
435 if(exceptionOccured0(ee))
436 return jem_throwException(jem);
438 jem->operand.uu.u1 = new_mb->args_count;
439 jem->operand.uu.u2 = new_mb->method_table_index;
441 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
442 new_mb,new_mb->args_count);
444 return opc_invokevirtual_quick(jem);
448 static int opc_invokespecial(struct jem_state *jem)
450 int idx;
451 Operand *operand = &jem->operand;
452 ExecEnv *ee = getExecEnv();
454 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
455 idx = jem->jecr & 0xffff;
457 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d \n", idx);
459 new_mb = resolveMethod(mb->class, idx);
461 if (exceptionOccured0(ee))
462 return jem_throwException(jem);
464 jam_dprintf("Resolved %s\n", new_mb->name);
466 /* Check if invoking a super method... */
467 if ((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
468 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
470 operand->i = new_mb->method_table_index;
471 return opc_invokesuper_quick(jem);
472 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
473 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
474 #endif
475 } else {
476 operand->pntr = new_mb;
477 return opc_invokenonvirtual_quick(jem);
480 return 0;
483 static int opc_invokestatic_quick(struct jem_state *jem)
485 new_mb = RESOLVED_METHOD(jem);
486 arg1 = ostack_address(frame->ostack, mb->max_stack,
487 ostack - frame->ostack - new_mb->args_count);
488 return invokeMethod(jem);
491 static int opc_invokestatic(struct jem_state *jem)
493 int idx, cache;
494 Operand *operand = &jem->operand;
495 ExecEnv *ee = getExecEnv();
497 idx = jem->jecr & 0xffff;
499 frame->last_pc = (CodePntr)jem->jpc;
500 new_mb = resolveMethod(mb->class, idx);
502 if(exceptionOccured0(ee))
503 return jem_throwException(jem);
505 operand->pntr = new_mb;
506 return opc_invokestatic_quick(jem);
509 static int opc_new_quick(struct jem_state *jem)
511 Operand *operand = &jem->operand;
512 Class *class = (Class*)CP_INFO(cp, operand->uui.u1);
513 Object *obj;
515 frame->last_pc = (CodePntr)jem->jpc;
516 if((obj = allocObject(class)) == NULL)
517 return jem_throwException(jem);
518 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack \n", obj);
519 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)obj);
522 static int opc_new(struct jem_state *jem)
524 Operand *operand = &jem->operand;
525 int idx = operand->uui.u1 = jem->jecr & 0xffff;
526 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
527 Class *class;
528 ExecEnv *ee = getExecEnv();
530 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
532 frame->last_pc = (CodePntr)jem->jpc;
533 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
534 if(exceptionOccured0(ee))
535 return jem_throwException(jem);
537 if(opcode == OPC_NEW) {
538 ClassBlock *cb = CLASS_CB(class);
539 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
540 signalException("java/lang/InstantiationError", cb->name);
541 return jem_throwException(jem);
545 return opc_new_quick(jem);
548 static int opc_anewarray_quick(struct jem_state *jem)
550 Class *class = RESOLVED_CLASS(jem);
551 char *name = CLASS_CB(class)->name;
552 int count;
553 Class *array_class;
554 char *ac_name;
555 Object *obj;
556 ExecEnv *ee = getExecEnv();
558 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, count);
559 frame->last_pc = (CodePntr)jem->jpc;
561 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name, count);
562 if(count < 0) {
563 signalException("java/lang/NegativeArraySizeException", NULL);
564 return jem_throwException(jem);
567 ac_name = sysMalloc(strlen(name) + 4);
569 if(name[0] == '[')
570 strcat(strcpy(ac_name, "["), name);
571 else
572 strcat(strcat(strcpy(ac_name, "[L"), name), ";");
574 array_class = findArrayClassFromClass(ac_name, mb->class);
575 free(ac_name);
577 if(exceptionOccured0(ee))
578 return jem_throwException(jem);
580 if((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
581 return jem_throwException(jem);
583 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)obj);
586 static int opc_anewarray(struct jem_state *jem)
588 Operand *operand = &jem->operand;
589 int idx = operand->uui.u1 = jem->jecr & 0xffff;
590 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
591 Class *class;
592 ExecEnv *ee = getExecEnv();
594 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
596 frame->last_pc = (CodePntr)jem->jpc;
597 //resolve the array class
598 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
600 if(exceptionOccured0(ee))
601 return jem_throwException(jem);
603 return opc_anewarray_quick(jem);
606 static int opc_putfield_quick(struct jem_state *jem)
608 uint32_t arg;
609 Object *obj;
611 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, arg);
612 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
614 JEM_NULL_POINTER_CHECK(obj);
615 INST_DATA(obj)[SINGLE_INDEX(jem)] = arg;
617 return 0;
620 static int opc_putfield2_quick(struct jem_state *jem)
622 uint64_t arg;
623 Object *obj;
625 ostack_pop_u64(frame->ostack, mb->max_stack, ostack, arg);
626 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
628 JEM_NULL_POINTER_CHECK(obj);
629 *(uint64_t *)&(INST_DATA(obj)[SINGLE_INDEX(jem)]) = arg;
631 return 0;
634 static int opc_putfield(struct jem_state *jem)
636 int idx = jem->jecr & 0xffff;
637 FieldBlock *fb;
638 ExecEnv *ee = getExecEnv();
640 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx);
642 frame->last_pc = (CodePntr)jem->jpc;
643 fb = resolveField(mb->class, idx);
644 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
646 if(exceptionOccured0(ee))
647 return jem_throwException(jem);
649 jem->operand.i = fb->offset;
650 switch (*fb->type) {
651 case 'J':
652 case 'D':
653 return opc_putfield2_quick(jem);
654 default:
655 return opc_putfield_quick(jem);
659 static int opc_getfield2_quick(struct jem_state *jem)
661 Object *obj;
662 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
663 JEM_NULL_POINTER_CHECK(obj);
665 return ostack_push_u64(frame->ostack, mb->max_stack, ostack,
666 *(uint64_t*)(&(INST_DATA(obj)[SINGLE_INDEX(jem)])));
669 static int opc_getfield_quick(struct jem_state *jem)
671 Object *obj;
672 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
673 JEM_NULL_POINTER_CHECK(obj);
675 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
676 INST_DATA(obj)[SINGLE_INDEX(jem)]);
679 static int opc_getfield(struct jem_state *jem)
681 int idx = jem->jecr & 0xffff;
682 FieldBlock *fb;
683 ExecEnv *ee = getExecEnv();
685 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx);
687 frame->last_pc = (CodePntr)jem->jpc;
688 fb = resolveField(mb->class, idx);
689 jam_dprintf("[OPC_GETFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
691 if(exceptionOccured0(ee))
692 return jem_throwException(jem);
694 jem->operand.i = fb->offset;
695 switch (*fb->type) {
696 case 'J':
697 case 'D':
698 return opc_getfield2_quick(jem);
699 default:
700 return opc_getfield_quick(jem);
704 static int opc_ldc_w_quick(struct jem_state *jem)
706 uint32_t cp_info = CP_INFO(cp,DOUBLE_INDEX(jem));
707 jam_dprintf("[OPC_LDC_W_QUICK] push cp info %x to stack \n", cp_info);
708 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)cp_info);
711 static int opc_ldc_quick(struct jem_state *jem)
713 uint32_t constant = RESOLVED_CONSTANT(jem);
714 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack \n", constant);
715 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)constant);
718 static int opc_ldc(struct jem_state *jem)
720 int idx;
721 ExecEnv *ee = getExecEnv();
723 idx = (int)(jem->jecr & 0xffff);
725 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx);
726 frame->last_pc = (CodePntr)jem->jpc;
728 jem->operand.u = resolveSingleConstant(mb->class, idx);
730 if(exceptionOccured0(ee))
731 return jem_throwException(jem);
733 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass ||
734 CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
735 jem->operand.i = idx;
736 return opc_ldc_w_quick(jem);
737 } else
738 return opc_ldc_quick(jem);
741 static int opc_ldc_w(struct jem_state *jem)
743 //rewritten to opc_ldc
744 return opc_ldc(jem);
747 static int opc_monitorenter(struct jem_state *jem)
749 Object *obj;
750 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
752 JEM_NULL_POINTER_CHECK(obj);
753 objectLock(obj);
754 return 0;
757 static int opc_monitorexit(struct jem_state *jem)
759 Object *obj;
760 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
762 JEM_NULL_POINTER_CHECK(obj);
763 objectUnlock(obj);
764 return 0;
767 static int opc_getstatic_quick(struct jem_state *jem)
769 return ostack_push_u32(frame->ostack, mb->max_stack, ostack,
770 RESOLVED_FIELD(jem)->static_value);
773 static int opc_getstatic2_quick(struct jem_state *jem)
775 return ostack_push_u64(frame->ostack, mb->max_stack, ostack,
776 RESOLVED_FIELD(jem)->static_value);
779 static int opc_getstatic(struct jem_state *jem)
781 int idx;
782 FieldBlock *fb;
783 Operand operand;
784 ExecEnv *ee = getExecEnv();
786 idx = (int)(jem->jecr & 0xffff);
788 frame->last_pc = (CodePntr)jem->jpc;
789 fb = resolveField(mb->class, idx);
791 if(exceptionOccured0(ee))
792 return jem_throwException(jem);
794 jem->operand.pntr = fb;
795 switch (*fb->type) {
796 case 'J':
797 case 'D':
798 return opc_getstatic2_quick(jem);
799 default:
800 return opc_getstatic_quick(jem);
804 static int opc_putstatic2_quick(struct jem_state *jem)
806 return ostack_pop_u64(frame->ostack, mb->max_stack, ostack,
807 *(u8*)&RESOLVED_FIELD(jem)->static_value);
810 static int opc_putstatic_quick(struct jem_state *jem)
812 return ostack_pop_u32(frame->ostack, mb->max_stack, ostack,
813 RESOLVED_FIELD(jem)->static_value);
816 static int opc_putstatic(struct jem_state *jem)
818 int idx;
819 FieldBlock *fb;
820 Operand operand;
821 ExecEnv *ee = getExecEnv();
823 idx = (int)(jem->jecr & 0xffff);
825 frame->last_pc = (CodePntr)jem->jpc;
826 fb = resolveField(mb->class, idx);
828 if(exceptionOccured0(ee))
829 return jem_throwException(jem);
831 jem->operand.pntr = fb;
832 switch (*fb->type) {
833 case 'J':
834 case 'D':
835 return opc_putstatic2_quick(jem);
836 default:
837 return opc_putstatic_quick(jem);
841 static int opc_checkcast_quick(struct jem_state *jem)
843 Class *class = RESOLVED_CLASS(jem);
844 Object *obj;
845 ostack_read_u32(frame->ostack, ostack, 0, &obj);
847 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %s for obj(%s)\n", CLASS_CB(class)->name, CLASS_CB(obj->class)->name);
848 if((obj != NULL) && !isInstanceOf(class, obj->class))
849 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
850 return 0;
853 static int opc_checkcast(struct jem_state *jem)
855 Operand *operand = &jem->operand;
856 int idx = operand->uui.u1 = jem->jecr & 0xffff;
857 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
858 Class *class;
859 ExecEnv *ee = getExecEnv();
861 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
863 frame->last_pc = (CodePntr)jem->jpc;
864 //resolve the cast class
865 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
867 if(exceptionOccured0(ee))
868 return jem_throwException(jem);
870 return opc_checkcast_quick(jem);
873 static int do_javaExceptions(struct jem_state *jem)
875 return JEM_TRAP_HANDLER_SYSEX;
878 static int opc_afireturn(struct jem_state *jem)
880 uint32_t val;
881 int ret;
883 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, val);
885 ret = opc_return(jem);
886 if (!ret)
887 ret = ostack_push_u32(frame->ostack, mb->max_stack, ostack, val);
889 return ret;
892 static int do_stackOverflow(struct jem_state *jem)
894 return 1;
897 static int do_stackUnderflow(struct jem_state *jem)
899 return 1;
902 static int do_stackOverflow1(struct jem_state *jem)
904 return 1;
907 static int do_stackUnderflow1(struct jem_state *jem)
909 return 1;
912 static handler_fn *trap_handler_f[256];
914 static handler_fn *exception_handler_f[] = {
915 [0] = do_javaExceptions,
916 [1] = do_stackOverflow,
917 [2] = do_stackUnderflow,
918 [3] = do_stackOverflow1,
919 [4] = do_stackUnderflow1,
922 /******************************/
923 uintptr_t *executeJava(void)
925 #if 0
927 * Using jamVm's direct threaded interpreting table to perform effective work
929 #define L(opcode, level, label) &&opc##opcode##_##level##_##label
931 #define D(opcode, level, label) &&rewrite_lock
933 #define I(opcode, level, label) &&rewrite_lock
935 #define DEF_HANDLER_TABLE(lvl,lbl) \
936 HANDLER_TABLE_T *handlers_##lvl##_##lbl[] = { \
937 L(0,lvl,lbl), L(1,lvl,lbl), L(2,lvl,lbl), L(3,lvl,lbl), L(4,lvl,lbl), \
938 L(5,lvl,lbl), L(6,lvl,lbl), L(7,lvl,lbl), L(8,lvl,lbl), L(9,lvl,lbl), \
939 L(10,lvl,lbl), L(11,lvl,lbl), L(12,lvl,lbl), L(13,lvl,lbl), L(14,lvl,lbl), \
940 L(15,lvl,lbl), L(16,lvl,lbl), L(17,lvl,lbl), L(18,lvl,lbl), D(19,lvl,lbl), \
941 L(20,lvl,lbl), L(21,lvl,lbl), L(22,lvl,lbl), L(23,lvl,lbl), L(24,lvl,lbl), \
942 L(25,lvl,lbl), L(26,lvl,lbl), L(27,lvl,lbl), L(28,lvl,lbl), L(29,lvl,lbl), \
943 L(30,lvl,lbl), L(31,lvl,lbl), L(32,lvl,lbl), L(33,lvl,lbl), L(34,lvl,lbl), \
944 L(35,lvl,lbl), L(36,lvl,lbl), L(37,lvl,lbl), L(38,lvl,lbl), L(39,lvl,lbl), \
945 L(40,lvl,lbl), L(41,lvl,lbl), D(42,lvl,lbl), L(43,lvl,lbl), L(44,lvl,lbl), \
946 L(45,lvl,lbl), L(46,lvl,lbl), L(47,lvl,lbl), L(48,lvl,lbl), L(49,lvl,lbl), \
947 L(50,lvl,lbl), L(51,lvl,lbl), L(52,lvl,lbl), L(53,lvl,lbl), L(54,lvl,lbl), \
948 L(55,lvl,lbl), L(56,lvl,lbl), L(57,lvl,lbl), L(58,lvl,lbl), L(59,lvl,lbl), \
949 L(60,lvl,lbl), L(61,lvl,lbl), L(62,lvl,lbl), L(63,lvl,lbl), L(64,lvl,lbl), \
950 L(65,lvl,lbl), L(66,lvl,lbl), L(67,lvl,lbl), L(68,lvl,lbl), L(69,lvl,lbl), \
951 L(70,lvl,lbl), L(71,lvl,lbl), L(72,lvl,lbl), L(73,lvl,lbl), L(74,lvl,lbl), \
952 L(75,lvl,lbl), L(76,lvl,lbl), L(77,lvl,lbl), L(78,lvl,lbl), L(79,lvl,lbl), \
953 L(80,lvl,lbl), L(81,lvl,lbl), L(82,lvl,lbl), L(83,lvl,lbl), L(84,lvl,lbl), \
954 L(85,lvl,lbl), L(86,lvl,lbl), L(87,lvl,lbl), L(88,lvl,lbl), L(89,lvl,lbl), \
955 L(90,lvl,lbl), L(91,lvl,lbl), L(92,lvl,lbl), L(93,lvl,lbl), L(94,lvl,lbl), \
956 L(95,lvl,lbl), L(96,lvl,lbl), L(97,lvl,lbl), L(98,lvl,lbl), L(99,lvl,lbl), \
957 L(100,lvl,lbl), L(101,lvl,lbl), L(102,lvl,lbl), L(103,lvl,lbl), L(104,lvl,lbl), \
958 L(105,lvl,lbl), L(106,lvl,lbl), L(107,lvl,lbl), L(108,lvl,lbl), L(109,lvl,lbl), \
959 L(110,lvl,lbl), L(111,lvl,lbl), L(112,lvl,lbl), L(113,lvl,lbl), L(114,lvl,lbl), \
960 L(115,lvl,lbl), L(116,lvl,lbl), L(117,lvl,lbl), L(118,lvl,lbl), L(119,lvl,lbl), \
961 L(120,lvl,lbl), L(121,lvl,lbl), L(122,lvl,lbl), L(123,lvl,lbl), L(124,lvl,lbl), \
962 L(125,lvl,lbl), L(126,lvl,lbl), L(127,lvl,lbl), L(128,lvl,lbl), L(129,lvl,lbl), \
963 L(130,lvl,lbl), L(131,lvl,lbl), L(132,lvl,lbl), L(133,lvl,lbl), L(134,lvl,lbl), \
964 L(135,lvl,lbl), L(136,lvl,lbl), L(137,lvl,lbl), L(138,lvl,lbl), L(139,lvl,lbl), \
965 L(140,lvl,lbl), L(141,lvl,lbl), L(142,lvl,lbl), L(143,lvl,lbl), L(144,lvl,lbl), \
966 L(145,lvl,lbl), L(146,lvl,lbl), L(147,lvl,lbl), L(148,lvl,lbl), L(149,lvl,lbl), \
967 L(150,lvl,lbl), L(151,lvl,lbl), L(152,lvl,lbl), L(153,lvl,lbl), L(154,lvl,lbl), \
968 L(155,lvl,lbl), L(156,lvl,lbl), L(157,lvl,lbl), L(158,lvl,lbl), L(159,lvl,lbl), \
969 L(160,lvl,lbl), L(161,lvl,lbl), L(162,lvl,lbl), L(163,lvl,lbl), L(164,lvl,lbl), \
970 L(165,lvl,lbl), L(166,lvl,lbl), L(167,lvl,lbl), L(168,lvl,lbl), L(169,lvl,lbl), \
971 L(170,lvl,lbl), L(171,lvl,lbl), L(172,lvl,lbl), L(173,lvl,lbl), L(174,lvl,lbl), \
972 L(175,lvl,lbl), L(176,lvl,lbl), L(177,lvl,lbl), L(178,lvl,lbl), L(179,lvl,lbl), \
973 L(180,lvl,lbl), L(181,lvl,lbl), L(182,lvl,lbl), L(183,lvl,lbl), L(184,lvl,lbl), \
974 L(185,lvl,lbl), &&unused, L(187,lvl,lbl), L(188,lvl,lbl), L(189,lvl,lbl), \
975 L(190,lvl,lbl), L(191,lvl,lbl), L(192,lvl,lbl), L(193,lvl,lbl), L(194,lvl,lbl), \
976 L(195,lvl,lbl), D(196,lvl,lbl), L(197,lvl,lbl), L(198,lvl,lbl), L(199,lvl,lbl), \
977 L(200,lvl,lbl), L(201,lvl,lbl), &&unused, L(203,lvl,lbl), L(204,lvl,lbl), \
978 &&unused, L(206,lvl,lbl), L(207,lvl,lbl), L(208,lvl,lbl), L(209,lvl,lbl), \
979 L(210,lvl,lbl), L(211,lvl,lbl), L(212,lvl,lbl), L(213,lvl,lbl), L(214,lvl,lbl), \
980 L(215,lvl,lbl), L(216,lvl,lbl), &&unused, &&unused, &&unused, &&unused, \
981 &&unused, &&unused, &&unused, &&unused, &&unused, D(226,lvl,lbl), \
982 D(227,lvl,lbl), D(228,lvl,lbl), L(229,lvl,lbl), D(230,lvl,lbl), L(231,lvl,lbl), \
983 L(232,lvl,lbl), L(233,lvl,lbl), &&unused, L(235,lvl,lbl), &&unused, \
984 &&unused, L(238,lvl,lbl), L(239,lvl,lbl), &&unused, &&unused, &&unused, \
985 L(243,lvl,lbl), L(244,lvl,lbl), L(245,lvl,lbl), I(246,lvl,lbl), &&unused, \
986 &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, \
987 &&unused}
989 DEF_HANDLER_TABLE(0, ENTRY);
990 #endif
992 * load trap entries to JEM trap table set when initializing JamVM
994 int i;
996 // static const void **handlers[] = {handlers_0_ENTRY};
998 ExecEnv *ee = getExecEnv();
1000 /* Initialize interpreter's static environment */
1001 frame = ee->last_frame;
1002 mb = frame->mb;
1003 lvars_jem = frame->lvars_jem - 1;
1005 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1006 * overflow we free a half of the stack (4 elements) to avoid an immediate
1007 * next overflow. When entering a trap, the Operand Stack is saved in a
1008 * temporary array in the reverse order:
1009 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1010 * jos[0] = r7 (?)
1011 * ...
1012 * jos[7 - N] = rN (ToS - N)
1013 * ...
1014 * jos[7] = r0 (ToS)
1015 * UPDATE (27.06.2008)
1016 * I think, actually, the manual is right in some way... If you access
1017 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1018 * with an ldm, you get this:
1019 * jos[0] = r7 (?)
1020 * ...
1021 * jos[7 - N] = rN (ToS)
1022 * ...
1023 * jos[7] = r0 (ToS - N)
1024 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1025 * set saved JOSP to 4.
1027 unsigned long jos[8];
1028 ostack = frame->ostack;
1029 cp = &(CLASS_CB(mb->class)->constant_pool);
1030 lvars = frame->lvars;
1031 this = (Object*)lvars[0];
1032 /* End enterpreter's static environment */
1035 //fetch the original pc before prepare direct mb
1036 //TODO:
1037 /* I think, mb->code is indeed a copy of the original code[] array from the
1038 * class object. See class.c::defineClass():390 */
1039 struct jem_state jem;
1040 uint32_t jep;
1041 int done;
1043 /* This is temporary. As we implement more handlers, we'll think of a better
1044 * way to link them. */
1045 trap_handler_f[OPC_INVOKESPECIAL] = opc_invokespecial;
1046 trap_handler_f[OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick;
1047 trap_handler_f[OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick;
1048 trap_handler_f[OPC_INVOKEVIRTUAL] = opc_invokevirtual;
1049 trap_handler_f[OPC_INVOKEVIRTUAL_QUICK] = opc_invokevirtual_quick;
1050 trap_handler_f[OPC_INVOKESTATIC] = opc_invokestatic;
1051 trap_handler_f[OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick;
1052 trap_handler_f[OPC_NEW] = opc_new;
1053 trap_handler_f[OPC_NEW_QUICK] = opc_new_quick;
1054 trap_handler_f[OPC_RETURN] = opc_return;
1055 trap_handler_f[OPC_ARETURN] = opc_afireturn;
1056 trap_handler_f[OPC_IRETURN] = opc_afireturn;
1057 trap_handler_f[OPC_FRETURN] = opc_afireturn;
1058 trap_handler_f[OPC_PUTFIELD] = opc_putfield;
1059 trap_handler_f[OPC_PUTFIELD_QUICK] = opc_putfield_quick;
1060 trap_handler_f[OPC_PUTFIELD2_QUICK] = opc_putfield2_quick;
1061 trap_handler_f[OPC_LDC_W_QUICK] = opc_ldc_w_quick;
1062 trap_handler_f[OPC_LDC_QUICK] = opc_ldc_quick;
1063 trap_handler_f[OPC_LDC_W] = opc_ldc_w;
1064 trap_handler_f[OPC_LDC] = opc_ldc;
1065 trap_handler_f[OPC_MONITORENTER] = opc_monitorenter;
1066 trap_handler_f[OPC_MONITOREXIT] = opc_monitorexit;
1067 trap_handler_f[OPC_GETSTATIC] = opc_getstatic;
1068 trap_handler_f[OPC_GETSTATIC_QUICK] = opc_getstatic_quick;
1069 trap_handler_f[OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick;
1070 trap_handler_f[OPC_PUTSTATIC] = opc_putstatic;
1071 trap_handler_f[OPC_PUTSTATIC_QUICK] = opc_putstatic_quick;
1072 trap_handler_f[OPC_PUTSTATIC2_QUICK] = opc_putstatic2_quick;
1073 trap_handler_f[OPC_ANEWARRAY] = opc_anewarray;
1074 trap_handler_f[OPC_ANEWARRAY_QUICK] = opc_anewarray_quick;
1075 trap_handler_f[OPC_CHECKCAST] = opc_checkcast;
1076 trap_handler_f[OPC_CHECKCAST_QUICK] = opc_checkcast_quick;
1077 trap_handler_f[OPC_GETFIELD] = opc_getfield;
1078 trap_handler_f[OPC_GETFIELD_QUICK] = opc_getfield_quick;
1079 trap_handler_f[OPC_GETFIELD2_QUICK] = opc_getfield2_quick;
1082 #if 0
1083 /* Don't think we need it, at least, not in the direct.c form. There the code
1084 * is converted into an internal representation, which is useless for JEM */
1085 PREPARE_MB(mb);//see direct.c (prepare)
1086 #endif
1088 jem.jpc = (unsigned long)mb->code & ~3;
1090 do {
1091 int opcode;
1093 jam_dprintf("About to enter JEM at 0x%08x, this = %p. Code:", jem.jpc, this);
1094 for (i = 0; i < 32 && jem.jpc + i < (unsigned long)(mb->code + mb->code_size); i++) {
1095 if (!(i & 0xf))
1096 jam_dprintf("\n0x%04x:", i);
1097 jam_dprintf(" 0x%02x", ((char*)jem.jpc)[i]);
1100 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", mb->max_locals);
1101 for (i = 0; i < min(8, mb->max_locals); i++)
1102 jam_dprintf("LVAR_%d: 0x%08x\n", i, *(lvars - i));
1104 /* On entry we need last Java Operand Stack depth, set it not deeper
1105 * than half hardware stack */
1106 jem.josp = min(5, ostack_depth(frame->ostack, ostack));
1107 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1108 for (i = 0; i < jem.josp; i++)
1109 ostack_pop_u32(frame->ostack, mb->max_stack, ostack,
1110 jos[7 - jem.josp + 1 + i]);
1112 __asm__ __volatile__(
1113 "pushm r0-r7,r10-r11\n"
1114 " mov r8, %[cp]\n"
1115 " mov r9, %[lv0]\n"
1116 " mov lr, %[jpc]\n"
1117 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1118 " mov r11, %[ostack]\n"
1119 " pushm r11\n" /* Need ostack below */
1120 " ldm r11, r0-r7\n" /* Restore Java Operands */
1121 " cp.w r12, 0\n" /* Test josp == 0 */
1122 " breq 4f\n"
1123 "5: incjosp 1\n" /* ... for loop counter, */
1124 " sub r12, 1\n" /* because it can be */
1125 " brne 5b\n" /* one of r0-r7 */
1126 "4: popjc\n" /* Restore Local Variables */
1127 " sub r10, pc, . - trap\n" /* These 3 instructions */
1128 " retj\n" /* have to stay */
1129 "trap: pushjc\n" /* together */
1130 " mfsr r11, 0x58\n" /* JOSP */
1131 " lsl r11, 29\n" /* Clear r11[31:3] using */
1132 " lsr r11, 29\n" /* one register */
1133 " mov r8, r11\n"
1134 " breq 2f\n"
1135 "3: incjosp -1\n"
1136 " sub r11, 1\n"
1137 " brne 3b\n"
1138 "2: popm r11\n" /* ostack */
1139 " stm r11, r0-r7\n" /* Save Java Operands */
1140 " popm r0-r7,r10-r11\n"
1141 " mov %[tpc], r12\n"
1142 " mov %[jpc], lr\n" /* Resume address */
1143 " mfsr %[jecr], 0x54\n" /* JECR */
1144 " mov %[josp], r8\n" /* JOSP */
1145 : [jecr] "=r" (jem.jecr), [tpc] "=r" (jem.trap_pc),
1146 [josp] "+r" (jem.josp), [jpc] "+r" (jem.jpc)
1147 : [cp] "r" (cp->orgPointer), [lv0] "r" (lvars_jem),
1148 [ostack] "r" (jos)
1149 : "r8", "r9", "lr", "r12", "memory"
1152 * trap_pc now holds trap pc, describing which trap has been entered,
1153 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1154 * arguments at bits 7..0 and 15..8,
1155 * josp holds JOSP (JOSP & 7),
1156 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1157 * jpc points at the trapping opcode, in case of exceptions and stack
1158 * over- and underflows, and at the next opcode, in case of a trap
1161 for (i = 0; i < jem.josp; i++)
1162 ostack_push_u32(frame->ostack, mb->max_stack, ostack,
1163 jos[7 - i]);
1165 opcode = (jem.jecr >> 16) & 0xff;
1167 jep = jem.trap_pc & 0xfff;
1169 trap_debug(&jem);
1170 if (jep < 0x280)
1171 done = exception_handler_f[jep >> 7](&jem);
1172 else if (trap_handler_f[opcode])
1173 done = trap_handler_f[opcode](&jem);
1174 else {
1175 /* Unimplemented */
1176 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode);
1177 exitVM(1);
1179 } while (done != JEM_TRAP_HANDLER_FINISH);
1181 return ostack;
1183 rewrite_lock:
1184 // DISPATCH_FIRST;
1186 unused:
1187 jam_printf("Unknown Java Opcodes\n");
1188 exitVM(1);
1190 #if 0
1191 //our own trap handlers
1192 #define JEM_TRAP_MULTI_LEVEL_ENTRIES(level) \
1193 DEF_DISPATCHTRAP(level) \
1194 DEF_JAVAEX(level) \
1195 DEF_STACKOVERFLOW(level) \
1196 DEF_STACKUNDERFLOW(level) \
1197 DEF_STACKOVERFLOW1(level) \
1198 DEF_STACKUNDERFLOW1(level) \
1199 DEF_IAFRETURN(level) \
1200 DEF_RETURN(level) \
1201 DEF_LDRETURN(level) \
1202 DEF_IINC(level) \
1203 DEF_CHECKCASTQUICK(level) \
1204 DEF_INSTANCEOFQUICK(level) \
1205 DEF_GETSTATIC(level) \
1206 DEF_PUTSTATIC(level) \
1207 DEF_NEW(level)\
1208 DEF_INVOKESTATIC(level) \
1209 DEF_INVOKEINTERFACEQUICK(level) \
1210 DEF_INVOKEVIRTUALQUICK(level) \
1211 DEF_INVOKESTATICQUICK(level) \
1212 DEF_INVOKENONVIRTUALQUICK(level) \
1213 DEF_XNEWARRAY(level) \
1214 DEF_LONGINSTRPS(level) \
1215 DEF_FLOATINSTRPS(level) \
1216 DEF_DOUBLEINSTRPS(level) \
1217 DEF_OTHERINSTRPS(level)
1220 JEM_TRAP_MULTI_LEVEL_ENTRIES(0);
1221 #endif
1223 #if 0
1224 #define MULTI_LEVEL_OPCODES(level) \
1225 DEF_OPC(OPC_ICONST_M1, level, \
1226 PUSH_##level(-1, 1); \
1229 DEF_OPC_3(OPC_ACONST_NULL, \
1230 OPC_ICONST_0, \
1231 OPC_FCONST_0, level, \
1232 PUSH_##level(0, 1); \
1235 DEF_OPC(OPC_ICONST_1, level, \
1236 PUSH_##level(1, 1); \
1239 DEF_OPC(OPC_ICONST_2, level, \
1240 PUSH_##level(2, 1); \
1243 DEF_OPC(OPC_ICONST_3, level, \
1244 PUSH_##level(3, 1); \
1247 DEF_OPC(OPC_ICONST_4, level, \
1248 PUSH_##level(4, 1); \
1251 DEF_OPC(OPC_ICONST_5, level, \
1252 PUSH_##level(5, 1); \
1255 DEF_OPC(OPC_FCONST_1, level, \
1256 PUSH_##level(FLOAT_1_BITS, 1); \
1259 DEF_OPC(OPC_FCONST_2, level, \
1260 PUSH_##level(FLOAT_2_BITS, 1); \
1263 DEF_OPC(OPC_SIPUSH, level, \
1264 PUSH_##level(DOUBLE_SIGNED(pc), 3); \
1267 DEF_OPC(OPC_BIPUSH, level, \
1268 PUSH_##level(SINGLE_SIGNED(pc), 2); \
1271 DEF_OPC(OPC_LDC_QUICK, level, \
1272 PUSH_##level(RESOLVED_CONSTANT(pc), 2); \
1275 DEF_OPC(OPC_LDC_W_QUICK, level, \
1276 PUSH_##level(CP_INFO(cp, DOUBLE_INDEX(pc)), 3); \
1279 DEF_OPC_3(OPC_ILOAD, \
1280 OPC_FLOAD, \
1281 OPC_ALOAD, level, \
1282 PUSH_##level(lvars[SINGLE_INDEX(pc)], 2); \
1285 DEF_OPC(OPC_ALOAD_THIS, level, \
1286 ALOAD_THIS(level); \
1289 DEF_OPC_2(OPC_ILOAD_0, \
1290 OPC_FLOAD_0, level, \
1291 PUSH_##level(lvars[0], 1) \
1294 DEF_OPC_3(OPC_ILOAD_1, \
1295 OPC_FLOAD_1, \
1296 OPC_ALOAD_1, level, \
1297 PUSH_##level(lvars[1], 1); \
1300 DEF_OPC_3(OPC_ILOAD_2, \
1301 OPC_FLOAD_2, \
1302 OPC_ALOAD_2, level, \
1303 PUSH_##level(lvars[2], 1); \
1306 DEF_OPC_3(OPC_ILOAD_3, \
1307 OPC_FLOAD_3, \
1308 OPC_ALOAD_3, level, \
1309 PUSH_##level(lvars[3], 1); \
1312 DEF_OPC_3(OPC_ISTORE, \
1313 OPC_FSTORE, \
1314 OPC_ASTORE, level, \
1315 POP_##level(lvars[SINGLE_INDEX(pc)], 2); \
1318 DEF_OPC_3(OPC_ISTORE_0, \
1319 OPC_ASTORE_0, \
1320 OPC_FSTORE_0, level, \
1321 POP_##level(lvars[0], 1); \
1324 DEF_OPC_3(OPC_ISTORE_1, \
1325 OPC_ASTORE_1, \
1326 OPC_FSTORE_1, level, \
1327 POP_##level(lvars[1], 1); \
1330 DEF_OPC_3(OPC_ISTORE_2, \
1331 OPC_ASTORE_2, \
1332 OPC_FSTORE_2, level, \
1333 POP_##level(lvars[2], 1); \
1336 DEF_OPC_3(OPC_ISTORE_3, \
1337 OPC_ASTORE_3, \
1338 OPC_FSTORE_3, level, \
1339 POP_##level(lvars[3], 1); \
1342 DEF_OPC(OPC_IADD, level, \
1343 BINARY_OP_##level(+); \
1346 DEF_OPC(OPC_ISUB, level, \
1347 BINARY_OP_##level(-); \
1350 DEF_OPC(OPC_IMUL, level, \
1351 BINARY_OP_##level(*); \
1354 DEF_OPC(OPC_IDIV, level, \
1355 ZERO_DIVISOR_CHECK_##level; \
1356 BINARY_OP_##level(/); \
1359 DEF_OPC(OPC_IREM, level, \
1360 ZERO_DIVISOR_CHECK_##level; \
1361 BINARY_OP_##level(%); \
1364 DEF_OPC(OPC_IAND, level, \
1365 BINARY_OP_##level(&); \
1368 DEF_OPC(OPC_IOR, level, \
1369 BINARY_OP_##level(|); \
1372 DEF_OPC(OPC_IXOR, level, \
1373 BINARY_OP_##level(^); \
1376 DEF_OPC(OPC_INEG, level, \
1377 UNARY_MINUS_##level; \
1380 DEF_OPC(OPC_ISHL, level, \
1381 SHIFT_OP_##level(int, <<); \
1384 DEF_OPC(OPC_ISHR, level, \
1385 SHIFT_OP_##level(int, >>); \
1388 DEF_OPC(OPC_IUSHR, level, \
1389 SHIFT_OP_##level(unsigned int, >>); \
1392 DEF_OPC_2(OPC_IF_ACMPEQ, \
1393 OPC_IF_ICMPEQ, level, \
1394 IF_ICMP_##level(==); \
1397 DEF_OPC_2(OPC_IF_ACMPNE, \
1398 OPC_IF_ICMPNE, level, \
1399 IF_ICMP_##level(!=); \
1402 DEF_OPC(OPC_IF_ICMPLT, level, \
1403 IF_ICMP_##level(<); \
1406 DEF_OPC(OPC_IF_ICMPGE, level, \
1407 IF_ICMP_##level(>=); \
1410 DEF_OPC(OPC_IF_ICMPGT, level, \
1411 IF_ICMP_##level(>); \
1414 DEF_OPC(OPC_IF_ICMPLE, level, \
1415 IF_ICMP_##level(<=); \
1418 DEF_OPC_2(OPC_IFNE, \
1419 OPC_IFNONNULL, level, \
1420 IF_##level(!=); \
1423 DEF_OPC_2(OPC_IFEQ, \
1424 OPC_IFNULL, level, \
1425 IF_##level(==); \
1428 DEF_OPC(OPC_IFLT, level, \
1429 IF_##level(<); \
1432 DEF_OPC(OPC_IFGE, level, \
1433 IF_##level(>=); \
1436 DEF_OPC(OPC_IFGT, level, \
1437 IF_##level(>); \
1440 DEF_OPC(OPC_IFLE, level, \
1441 IF_##level(<=); \
1444 DEF_OPC(OPC_IINC, level, \
1445 lvars[IINC_LVAR_IDX(pc)] += IINC_DELTA(pc); \
1446 DISPATCH(level, 3); \
1449 DEF_OPC(OPC_POP, level, \
1450 POP1_##level; \
1453 DEF_OPC(OPC_POP2, level, \
1454 ostack -= 2 - level; \
1455 DISPATCH(0, 1); \
1458 DEF_OPC(OPC_DUP, level, \
1459 DUP_##level; \
1462 DEF_OPC_3(OPC_IRETURN, \
1463 OPC_ARETURN, \
1464 OPC_FRETURN, level, \
1465 RETURN_##level; \
1468 DEF_OPC(OPC_RETURN, level, \
1469 goto methodReturn; \
1472 DEF_OPC(OPC_GETSTATIC_QUICK, level, \
1473 PUSH_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1476 DEF_OPC(OPC_PUTSTATIC_QUICK, level, \
1477 POP_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1480 DEF_OPC(OPC_GETFIELD_THIS, level, \
1481 GETFIELD_THIS(level); \
1484 DEF_OPC(OPC_GETFIELD_QUICK, level, \
1485 GETFIELD_QUICK_##level; \
1488 #define ZERO_DIVISOR_CHECK_0 \
1489 ZERO_DIVISOR_CHECK((int)ostack[-1]);
1491 #define ZERO_DIVISOR_CHECK_1 \
1492 ZERO_DIVISOR_CHECK((int)cache.i.v1);
1494 #define ZERO_DIVISOR_CHECK_2 \
1495 ZERO_DIVISOR_CHECK((int)cache.i.v2);
1498 #define PUSH_0(value, ins_len) \
1499 *ostack++ = value; \
1500 DISPATCH(0, ins_len);
1503 #define PUSH_1(value, ins_len) \
1504 cache.i.v2 = value; \
1505 DISPATCH(2, ins_len);
1507 #define PUSH_2(value, ins_len) \
1508 *ostack++ = cache.i.v1; \
1509 cache.i.v1 = cache.i.v2; \
1510 cache.i.v2 = value; \
1511 DISPATCH(2, ins_len);
1513 #define POP_0(dest, ins_len) \
1514 dest = *--ostack; \
1515 DISPATCH(0, ins_len);
1517 #define POP_1(dest, ins_len) \
1518 dest = cache.i.v1; \
1519 DISPATCH(0, ins_len);
1521 #define POP_2(dest, ins_len) \
1522 dest = cache.i.v2; \
1523 DISPATCH(1, ins_len);
1525 #define POP1_0 \
1526 ostack--; \
1527 DISPATCH(0, 1);
1529 #define POP1_1 \
1530 DISPATCH(0, 1);
1532 #define POP1_2 \
1533 DISPATCH(1, 1);
1535 #define DUP_0 \
1536 PUSH_0(ostack[-1], 1);
1538 #define DUP_1 \
1539 PUSH_1(cache.i.v1, 1);
1541 #define DUP_2 \
1542 PUSH_2(cache.i.v2, 1);
1544 #define RETURN_0 \
1545 *lvars++ = *--ostack; \
1546 goto methodReturn;
1548 #define RETURN_1 \
1549 *lvars++ = cache.i.v1; \
1550 goto methodReturn;
1552 #define RETURN_2 \
1553 *lvars++ = cache.i.v2; \
1554 goto methodReturn;
1556 #define GETFIELD_QUICK_0 \
1558 Object *obj = (Object *)*--ostack; \
1559 NULL_POINTER_CHECK(obj); \
1560 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1563 #define GETFIELD_QUICK_1 \
1565 Object *obj = (Object *)cache.i.v1; \
1566 NULL_POINTER_CHECK(obj); \
1567 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1570 #define GETFIELD_QUICK_2 \
1572 Object *obj = (Object *)cache.i.v2; \
1573 NULL_POINTER_CHECK(obj); \
1574 PUSH_1(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1577 #define UNARY_MINUS_0 \
1579 int v = (int)*--ostack; \
1580 PUSH_0(-v, 1); \
1583 #define UNARY_MINUS_1 \
1584 PUSH_0(-(int)cache.i.v1, 1);
1586 #define UNARY_MINUS_2 \
1587 PUSH_1(-(int)cache.i.v2, 1);
1589 #define BINARY_OP_0(OP) \
1590 ostack -= 2; \
1591 PUSH_0((int)ostack[0] OP (int)ostack[1], 1);
1593 #define BINARY_OP_1(OP) \
1594 PUSH_0((int)*--ostack OP (int)cache.i.v1, 1);
1596 #define BINARY_OP_2(OP) \
1597 PUSH_0((int)cache.i.v1 OP (int)cache.i.v2, 1);
1599 #define SHIFT_OP_0(TYPE, OP) \
1600 ostack -= 2; \
1601 PUSH_0((TYPE)ostack[0] OP (ostack[1] & 0x1f), 1);
1603 #define SHIFT_OP_1(TYPE, OP) \
1604 PUSH_0((TYPE)*--ostack OP (cache.i.v1 & 0x1f), 1);
1606 #define SHIFT_OP_2(TYPE, OP) \
1607 PUSH_0((TYPE)cache.i.v1 OP (cache.i.v2 & 0x1f), 1);
1609 #define IF_ICMP_0(COND) \
1610 ostack -= 2; \
1611 BRANCH((int)ostack[0] COND (int)ostack[1]);
1613 #define IF_ICMP_1(COND) \
1614 BRANCH((int)*--ostack COND (int)cache.i.v1);
1616 #define IF_ICMP_2(COND) \
1617 BRANCH((int)cache.i.v1 COND (int)cache.i.v2);
1619 #define IF_0(COND) \
1620 BRANCH((int)*--ostack COND 0);
1622 #define IF_1(COND) \
1623 BRANCH((int)cache.i.v1 COND 0);
1625 #define IF_2(COND) \
1626 *ostack++ = cache.i.v1; \
1627 BRANCH((int)cache.i.v2 COND 0);
1629 #define ALOAD_THIS(level)
1631 #define GETFIELD_THIS(level) \
1632 PUSH_##level(INST_DATA(this)[pc->operand.i], 4);
1635 MULTI_LEVEL_OPCODES(0);
1638 DEF_OPC_210(OPC_NOP,
1639 DISPATCH(0, 1);
1643 #define PUSH_LONG(value, ins_len) \
1644 *(u8*)ostack = value; \
1645 ostack += 2; \
1646 DISPATCH(0, ins_len);
1648 DEF_OPC_210_2(
1649 OPC_LCONST_0,
1650 OPC_DCONST_0,
1651 PUSH_LONG(0, 1);
1654 DEF_OPC_210(OPC_DCONST_1,
1655 PUSH_LONG(DOUBLE_1_BITS, 1);
1658 DEF_OPC_210(OPC_LCONST_1,
1659 PUSH_LONG(1, 1);
1662 DEF_OPC_210(OPC_LDC2_W,
1663 PUSH_LONG(CP_LONG(cp, DOUBLE_INDEX(pc)), 3);
1666 DEF_OPC_210_2(
1667 OPC_LLOAD,
1668 OPC_DLOAD,
1669 PUSH_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1672 DEF_OPC_210_2(
1673 OPC_LLOAD_0,
1674 OPC_DLOAD_0,
1675 PUSH_LONG(*(u8*)(&lvars[0]), 1);
1678 DEF_OPC_210_2(
1679 OPC_LLOAD_1,
1680 OPC_DLOAD_1,
1681 PUSH_LONG(*(u8*)(&lvars[1]), 1);
1684 DEF_OPC_210_2(
1685 OPC_LLOAD_2,
1686 OPC_DLOAD_2,
1687 PUSH_LONG(*(u8*)(&lvars[2]), 1);
1690 DEF_OPC_210_2(
1691 OPC_LLOAD_3,
1692 OPC_DLOAD_3,
1693 PUSH_LONG(*(u8*)(&lvars[3]), 1);
1697 #define POP_LONG(dest, ins_len) \
1698 ostack -= 2; \
1699 dest = *(u8*)ostack; \
1700 DISPATCH(0, ins_len);
1703 DEF_OPC_012_2(
1704 OPC_LSTORE,
1705 OPC_DSTORE,
1706 POP_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1709 DEF_OPC_012_2(
1710 OPC_LSTORE_0,
1711 OPC_DSTORE_0,
1712 POP_LONG(*(u8*)(&lvars[0]), 1);
1715 DEF_OPC_012_2(
1716 OPC_LSTORE_1,
1717 OPC_DSTORE_1,
1718 POP_LONG(*(u8*)(&lvars[1]), 1);
1721 DEF_OPC_012_2(
1722 OPC_LSTORE_2,
1723 OPC_DSTORE_2,
1724 POP_LONG(*(u8*)(&lvars[2]), 1);
1727 DEF_OPC_012_2(
1728 OPC_LSTORE_3,
1729 OPC_DSTORE_3,
1730 POP_LONG(*(u8*)(&lvars[3]), 1);
1734 #define ARRAY_LOAD_IDX *--ostack
1735 #define ARRAY_LOAD_ARY *--ostack
1738 #define ARRAY_LOAD(TYPE) \
1740 int idx = ARRAY_LOAD_IDX; \
1741 Object *array = (Object *)ARRAY_LOAD_ARY; \
1743 NULL_POINTER_CHECK(array); \
1744 ARRAY_BOUNDS_CHECK(array, idx); \
1745 PUSH_0(((TYPE *)ARRAY_DATA(array))[idx], 1); \
1748 DEF_OPC_012_2(
1749 OPC_IALOAD,
1750 OPC_FALOAD,
1751 ARRAY_LOAD(int)
1754 DEF_OPC_012(OPC_AALOAD,
1755 ARRAY_LOAD(uintptr_t)
1758 DEF_OPC_012(OPC_BALOAD,
1759 ARRAY_LOAD(signed char)
1762 DEF_OPC_012(OPC_CALOAD,
1763 ARRAY_LOAD(unsigned short)
1766 DEF_OPC_012(OPC_SALOAD,
1767 ARRAY_LOAD(short)
1770 DEF_OPC_012(OPC_LALOAD, {
1771 int idx = ARRAY_LOAD_IDX;
1772 Object *array = (Object *)ARRAY_LOAD_ARY;
1774 NULL_POINTER_CHECK(array);
1775 ARRAY_BOUNDS_CHECK(array, idx);
1776 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
1779 DEF_OPC_012(OPC_DALOAD, {
1780 int idx = ARRAY_LOAD_IDX;
1781 Object *array = (Object *)ARRAY_LOAD_ARY;
1783 NULL_POINTER_CHECK(array);
1784 ARRAY_BOUNDS_CHECK(array, idx);
1785 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
1789 #define ARRAY_STORE_VAL *--ostack
1790 #define ARRAY_STORE_IDX *--ostack
1793 #define ARRAY_STORE(TYPE) \
1795 int val = ARRAY_STORE_VAL; \
1796 int idx = ARRAY_STORE_IDX; \
1797 Object *array = (Object *)*--ostack; \
1799 NULL_POINTER_CHECK(array); \
1800 ARRAY_BOUNDS_CHECK(array, idx); \
1801 ((TYPE *)ARRAY_DATA(array))[idx] = val; \
1802 DISPATCH(0, 1); \
1805 DEF_OPC_012_2(
1806 OPC_IASTORE,
1807 OPC_FASTORE,
1808 ARRAY_STORE(int)
1811 DEF_OPC_012(OPC_BASTORE,
1812 ARRAY_STORE(char);
1815 DEF_OPC_012_2(
1816 OPC_CASTORE,
1817 OPC_SASTORE,
1818 ARRAY_STORE(short);
1821 DEF_OPC_012(OPC_AASTORE, {
1822 Object *obj = (Object*)ARRAY_STORE_VAL;
1823 int idx = ARRAY_STORE_IDX;
1824 Object *array = (Object *)*--ostack;
1826 NULL_POINTER_CHECK(array);
1827 ARRAY_BOUNDS_CHECK(array, idx);
1829 if((obj != NULL) && !arrayStoreCheck(array->class, obj->class))
1830 THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
1832 ((Object**)ARRAY_DATA(array))[idx] = obj;
1833 DISPATCH(0, 1);
1837 DEF_OPC_012_2(
1838 OPC_LASTORE,
1839 OPC_DASTORE, {
1840 int idx = ostack[-3];
1841 Object *array = (Object *)ostack[-4];
1843 ostack -= 4;
1844 NULL_POINTER_CHECK(array);
1845 ARRAY_BOUNDS_CHECK(array, idx);
1847 ((u8 *)ARRAY_DATA(array))[idx] = *(u8*)&ostack[2];
1848 DISPATCH(0, 1);
1853 DEF_OPC_012(OPC_DUP_X1, {
1854 uintptr_t word1 = ostack[-1];
1855 uintptr_t word2 = ostack[-2];
1856 ostack[-2] = word1;
1857 ostack[-1] = word2;
1858 *ostack++ = word1;
1859 DISPATCH(0, 1);
1862 DEF_OPC_012(OPC_DUP_X2, {
1863 uintptr_t word1 = ostack[-1];
1864 uintptr_t word2 = ostack[-2];
1865 uintptr_t word3 = ostack[-3];
1866 ostack[-3] = word1;
1867 ostack[-2] = word3;
1868 ostack[-1] = word2;
1869 *ostack++ = word1;
1870 DISPATCH(0, 1);
1873 DEF_OPC_012(OPC_DUP2, {
1874 ostack[0] = ostack[-2];
1875 ostack[1] = ostack[-1];
1876 ostack += 2;
1877 DISPATCH(0, 1);
1880 DEF_OPC_012(OPC_DUP2_X1, {
1881 uintptr_t word1 = ostack[-1];
1882 uintptr_t word2 = ostack[-2];
1883 uintptr_t word3 = ostack[-3];
1884 ostack[-3] = word2;
1885 ostack[-2] = word1;
1886 ostack[-1] = word3;
1887 ostack[0] = word2;
1888 ostack[1] = word1;
1889 ostack += 2;
1890 DISPATCH(0, 1);
1893 DEF_OPC_012(OPC_DUP2_X2, {
1894 uintptr_t word1 = ostack[-1];
1895 uintptr_t word2 = ostack[-2];
1896 uintptr_t word3 = ostack[-3];
1897 uintptr_t word4 = ostack[-4];
1898 ostack[-4] = word2;
1899 ostack[-3] = word1;
1900 ostack[-2] = word4;
1901 ostack[-1] = word3;
1902 ostack[0] = word2;
1903 ostack[1] = word1;
1904 ostack += 2;
1905 DISPATCH(0, 1);
1908 DEF_OPC_012(OPC_SWAP, {
1909 uintptr_t word1 = ostack[-1];
1910 ostack[-1] = ostack[-2];
1911 ostack[-2] = word1;
1912 DISPATCH(0, 1)
1916 #define BINARY_OP_fp(TYPE, OP) \
1917 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] = \
1918 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] OP\
1919 *(TYPE *)&ostack[-sizeof(TYPE)/4]; \
1920 ostack -= sizeof(TYPE)/4; \
1921 DISPATCH(0, 1);
1923 DEF_OPC_210(OPC_FADD,
1924 BINARY_OP_fp(float, +);
1927 DEF_OPC_210(OPC_DADD,
1928 BINARY_OP_fp(double, +);
1931 DEF_OPC_210(OPC_FSUB,
1932 BINARY_OP_fp(float, -);
1935 DEF_OPC_210(OPC_DSUB,
1936 BINARY_OP_fp(double, -);
1939 DEF_OPC_210(OPC_FMUL,
1940 BINARY_OP_fp(float, *);
1943 DEF_OPC_210(OPC_DMUL,
1944 BINARY_OP_fp(double, *);
1947 DEF_OPC_210(OPC_FDIV,
1948 BINARY_OP_fp(float, /);
1951 DEF_OPC_210(OPC_DDIV,
1952 BINARY_OP_fp(double, /);
1956 #define BINARY_OP_long(OP) \
1957 BINARY_OP_fp(long long, OP)
1959 #define ZERO_DIVISOR_CHECK_long \
1960 ZERO_DIVISOR_CHECK(*(u8*)&ostack[-2]);
1963 DEF_OPC_012(OPC_LADD,
1964 BINARY_OP_long(+);
1967 DEF_OPC_012(OPC_LSUB,
1968 BINARY_OP_long(-);
1971 DEF_OPC_012(OPC_LMUL,
1972 BINARY_OP_long(*);
1975 DEF_OPC_012(OPC_LDIV,
1976 ZERO_DIVISOR_CHECK_long;
1977 BINARY_OP_long(/);
1980 DEF_OPC_012(OPC_LREM,
1981 ZERO_DIVISOR_CHECK_long;
1982 BINARY_OP_long(%);
1985 DEF_OPC_012(OPC_LAND,
1986 BINARY_OP_long(&);
1989 DEF_OPC_012(OPC_LOR,
1990 BINARY_OP_long(|);
1993 DEF_OPC_012(OPC_LXOR,
1994 BINARY_OP_long(^);
1998 #define SHIFT_OP_long(TYPE, OP) \
2000 int shift = *--ostack & 0x3f; \
2001 *(TYPE*)&ostack[-2] = \
2002 *(TYPE*)&ostack[-2] OP shift; \
2003 DISPATCH(0, 1); \
2007 DEF_OPC_012(OPC_LSHL,
2008 SHIFT_OP_long(long long, <<);
2011 DEF_OPC_012(OPC_LSHR,
2012 SHIFT_OP_long(long long, >>);
2015 DEF_OPC_012(OPC_LUSHR,
2016 SHIFT_OP_long(unsigned long long, >>);
2019 DEF_OPC_210(OPC_FREM, {
2020 float v2 = *(float *)&ostack[-1];
2021 float v1 = *(float *)&ostack[-2];
2023 *(float *)&ostack[-2] = fmod(v1, v2);
2024 ostack -= 1;
2025 DISPATCH(0, 1);
2028 DEF_OPC_210(OPC_DREM, {
2029 double v2 = *(double *)&ostack[-2];
2030 double v1 = *(double *)&ostack[-4];
2032 *(double *)&ostack[-4] = fmod(v1, v2);
2033 ostack -= 2;
2034 DISPATCH(0, 1);
2037 #define UNARY_MINUS(TYPE) \
2038 *(TYPE*)&ostack[-sizeof(TYPE)/4] = \
2039 -*(TYPE*)&ostack[-sizeof(TYPE)/4]; \
2040 DISPATCH(0, 1);
2042 DEF_OPC_210(OPC_LNEG,
2043 UNARY_MINUS(long long);
2046 DEF_OPC_210(OPC_FNEG,
2047 UNARY_MINUS(float);
2050 DEF_OPC_210(OPC_DNEG,
2051 UNARY_MINUS(double);
2054 DEF_OPC_210(OPC_I2L, {
2055 ostack -= 1;
2056 PUSH_LONG((int)*ostack, 1);
2059 DEF_OPC_012(OPC_L2I, {
2060 long long l;
2061 #ifdef USE_CACHE
2062 l = cache.l;
2063 #else
2064 ostack -= 2;
2065 l = *(long long*)ostack;
2066 #endif
2067 PUSH_0((int)l, 1);
2070 #define OPC_int2fp(DEST_TYPE) \
2071 ostack -= 1; \
2072 *(DEST_TYPE *)ostack = \
2073 (DEST_TYPE)(int)*ostack; \
2074 ostack += sizeof(DEST_TYPE)/4; \
2075 DISPATCH(0, 1);
2077 DEF_OPC_210(OPC_I2F,
2078 OPC_int2fp(float);
2081 DEF_OPC_210(OPC_I2D,
2082 OPC_int2fp(double);
2085 #define OPC_X2Y(SRC_TYPE, DEST_TYPE) \
2087 SRC_TYPE v; \
2088 ostack -= sizeof(SRC_TYPE)/4; \
2089 v = *(SRC_TYPE *)ostack; \
2090 *(DEST_TYPE *)ostack = (DEST_TYPE)v; \
2091 ostack += sizeof(DEST_TYPE)/4; \
2092 DISPATCH(0, 1); \
2095 DEF_OPC_210(OPC_L2F,
2096 OPC_X2Y(long long, float);
2099 DEF_OPC_210(OPC_L2D,
2100 OPC_X2Y(long long, double);
2103 DEF_OPC_210(OPC_F2D,
2104 OPC_X2Y(float, double);
2107 DEF_OPC_210(OPC_D2F,
2108 OPC_X2Y(double, float);
2111 #define OPC_fp2int(SRC_TYPE) \
2113 int res; \
2114 SRC_TYPE value; \
2115 ostack -= sizeof(SRC_TYPE)/4; \
2116 value = *(SRC_TYPE *)ostack; \
2118 if(value >= (SRC_TYPE)INT_MAX) \
2119 res = INT_MAX; \
2120 else if(value <= (SRC_TYPE)INT_MIN) \
2121 res = INT_MIN; \
2122 else if(value != value) \
2123 res = 0; \
2124 else \
2125 res = (int) value; \
2127 PUSH_0(res, 1); \
2130 DEF_OPC_210(OPC_F2I,
2131 OPC_fp2int(float);
2134 DEF_OPC_210(OPC_D2I,
2135 OPC_fp2int(double);
2138 #define OPC_fp2long(SRC_TYPE) \
2140 long long res; \
2141 SRC_TYPE value; \
2142 ostack -= sizeof(SRC_TYPE)/4; \
2143 value = *(SRC_TYPE *)ostack; \
2145 if(value >= (SRC_TYPE)LLONG_MAX) \
2146 res = LLONG_MAX; \
2147 else if(value <= (SRC_TYPE)LLONG_MIN) \
2148 res = LLONG_MIN; \
2149 else if(value != value) \
2150 res = 0; \
2151 else \
2152 res = (long long) value; \
2154 PUSH_LONG(res, 1); \
2157 DEF_OPC_210(OPC_F2L,
2158 OPC_fp2long(float);
2161 DEF_OPC_210(OPC_D2L,
2162 OPC_fp2long(double);
2165 DEF_OPC_210(OPC_I2B, {
2166 signed char v = *--ostack & 0xff;
2167 PUSH_0(v, 1);
2170 DEF_OPC_210(OPC_I2C, {
2171 int v = *--ostack & 0xffff;
2172 PUSH_0(v, 1);
2175 DEF_OPC_210(OPC_I2S, {
2176 signed short v = *--ostack & 0xffff;
2177 PUSH_0((int) v, 1);
2181 DEF_OPC_012(OPC_LCMP, {
2182 long long v2 = *(long long*)&ostack[-2];
2183 long long v1 = *(long long*)&ostack[-4];
2184 ostack[-4] = (v1 == v2) ? 0 : ((v1 < v2) ? -1 : 1);
2185 ostack -= 3;
2186 DISPATCH(0, 1);
2190 #define FCMP(TYPE, isNan) \
2191 ({ \
2192 int res; \
2193 TYPE v1, v2; \
2194 ostack -= sizeof(TYPE)/4; v2 = *(TYPE *)ostack; \
2195 ostack -= sizeof(TYPE)/4; v1 = *(TYPE *)ostack; \
2196 if(v1 == v2) \
2197 res = 0; \
2198 else if(v1 < v2) \
2199 res = -1; \
2200 else if(v1 > v2) \
2201 res = 1; \
2202 else \
2203 res = isNan; \
2204 PUSH_0(res, 1); \
2207 DEF_OPC_210(OPC_DCMPG,
2208 FCMP(double, 1);
2211 DEF_OPC_210(OPC_DCMPL,
2212 FCMP(double, -1);
2215 DEF_OPC_210(OPC_FCMPG,
2216 FCMP(float, 1);
2219 DEF_OPC_210(OPC_FCMPL,
2220 FCMP(float, -1);
2224 DEF_OPC_210_2(
2225 OPC_GOTO,
2226 OPC_GOTO_W,
2227 BRANCH(TRUE);
2230 DEF_OPC_210_2(
2231 OPC_JSR,
2232 OPC_JSR_W,
2233 *ostack++ = (uintptr_t)pc;
2234 BRANCH(TRUE);
2237 DEF_OPC_210(OPC_RET,
2238 pc = (CodePntr)lvars[SINGLE_INDEX(pc)];
2239 DISPATCH_RET(3);
2242 DEF_OPC_012_2(
2243 OPC_LRETURN,
2244 OPC_DRETURN,
2245 ostack -= 2;
2246 *(u8*)lvars = *(u8*)ostack;
2247 lvars += 2;
2248 goto methodReturn;
2251 DEF_OPC_210(OPC_ARRAYLENGTH, {
2252 Object *array = (Object *)*--ostack;
2254 NULL_POINTER_CHECK(array);
2255 PUSH_0(ARRAY_LEN(array), 1);
2258 DEF_OPC_210(OPC_ATHROW, {
2259 Object *obj = (Object *)ostack[-1];
2260 frame->last_pc = pc;
2261 NULL_POINTER_CHECK(obj);
2263 ee->exception = obj;
2264 goto throwException;
2267 DEF_OPC_210(OPC_NEWARRAY, {
2268 int type = ARRAY_TYPE(pc);
2269 int count = *--ostack;
2270 Object *obj;
2272 frame->last_pc = pc;
2273 if((obj = allocTypeArray(type, count)) == NULL)
2274 goto throwException;
2276 PUSH_0((uintptr_t)obj, 2);
2279 DEF_OPC_210(OPC_MONITORENTER, {
2280 Object *obj = (Object *)*--ostack;
2281 NULL_POINTER_CHECK(obj);
2282 objectLock(obj);
2283 DISPATCH(0, 1);
2286 DEF_OPC_210(OPC_MONITOREXIT, {
2287 Object *obj = (Object *)*--ostack;
2288 NULL_POINTER_CHECK(obj);
2289 objectUnlock(obj);
2290 DISPATCH(0, 1);
2293 DEF_OPC_RW(OPC_LDC, ({
2294 int idx, cache;
2295 Operand operand;
2297 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_LDC, idx, cache);
2299 frame->last_pc = pc;
2301 operand.u = resolveSingleConstant(mb->class, idx);
2303 if(exceptionOccured0(ee))
2304 goto throwException;
2306 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass ||
2307 CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
2308 operand.i = idx;
2309 OPCODE_REWRITE(OPC_LDC_W_QUICK, cache, operand);
2310 } else
2311 OPCODE_REWRITE(OPC_LDC_QUICK, cache, operand);
2313 REDISPATCH
2314 });)
2316 DEF_OPC_210(OPC_TABLESWITCH, {
2317 SwitchTable *table = (SwitchTable*)pc->operand.pntr;
2318 int index = *--ostack;
2320 if(index < table->low || index > table->high)
2321 pc = table->deflt;
2322 else
2323 pc = table->entries[index - table->low];
2325 DISPATCH_SWITCH
2328 DEF_OPC_210(OPC_LOOKUPSWITCH, {
2329 LookupTable *table = (LookupTable*)pc->operand.pntr;
2330 int key = *--ostack;
2331 int i;
2333 for(i = 0; (i < table->num_entries) && (key != table->entries[i].key); i++);
2335 pc = (i == table->num_entries ? table->deflt
2336 : table->entries[i].handler);
2337 DISPATCH_SWITCH
2340 DEF_OPC_RW(OPC_GETSTATIC, ({
2341 int idx, cache;
2342 FieldBlock *fb;
2343 Operand operand;
2345 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETSTATIC, idx, cache);
2347 frame->last_pc = pc;
2348 fb = resolveField(mb->class, idx);
2350 if(exceptionOccured0(ee))
2351 goto throwException;
2353 operand.pntr = fb;
2354 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2355 OPC_GETSTATIC2_QUICK : OPC_GETSTATIC_QUICK), cache, operand);
2357 REDISPATCH
2358 });)
2360 DEF_OPC_RW(OPC_PUTSTATIC, ({
2361 int idx, cache;
2362 FieldBlock *fb;
2363 Operand operand;
2365 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTSTATIC, idx, cache);
2367 frame->last_pc = pc;
2368 fb = resolveField(mb->class, idx);
2370 if(exceptionOccured0(ee))
2371 goto throwException;
2373 operand.pntr = fb;
2374 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2375 OPC_PUTSTATIC2_QUICK : OPC_PUTSTATIC_QUICK), cache, operand);
2377 REDISPATCH
2378 });)
2380 DEF_OPC_RW(OPC_GETFIELD, ({
2381 int idx, cache;
2382 FieldBlock *fb;
2383 Operand operand;
2385 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETFIELD, idx, cache);
2387 frame->last_pc = pc;
2388 fb = resolveField(mb->class, idx);
2390 if(exceptionOccured0(ee))
2391 goto throwException;
2393 operand.i = fb->offset;
2394 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2395 OPC_GETFIELD2_QUICK : OPC_GETFIELD_QUICK), cache, operand);
2397 REDISPATCH
2398 });)
2400 DEF_OPC_RW(OPC_PUTFIELD, ({
2401 int idx, cache;
2402 FieldBlock *fb;
2403 Operand operand;
2405 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTFIELD, idx, cache);
2407 frame->last_pc = pc;
2408 fb = resolveField(mb->class, idx);
2410 if(exceptionOccured0(ee))
2411 goto throwException;
2413 operand.i = fb->offset;
2414 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2415 OPC_PUTFIELD2_QUICK : OPC_PUTFIELD_QUICK), cache, operand);
2417 REDISPATCH
2418 });)
2420 DEF_OPC_RW(OPC_INVOKEVIRTUAL, ({
2421 int idx, cache;
2422 Operand operand;
2424 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEVIRTUAL, idx, cache);
2426 frame->last_pc = pc;
2427 new_mb = resolveMethod(mb->class, idx);
2429 if(exceptionOccured0(ee))
2430 goto throwException;
2432 operand.uu.u1 = new_mb->args_count;
2433 operand.uu.u2 = new_mb->method_table_index;
2434 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2435 REDISPATCH
2436 });)
2438 DEF_OPC_RW(OPC_INVOKESPECIAL, ({
2439 int idx, cache;
2440 Operand operand;
2442 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESPECIAL, idx, cache);
2444 frame->last_pc = pc;
2445 new_mb = resolveMethod(mb->class, idx);
2447 if(exceptionOccured0(ee))
2448 goto throwException;
2450 /* Check if invoking a super method... */
2451 if((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
2452 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
2454 operand.i = new_mb->method_table_index;
2455 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
2456 } else {
2457 operand.pntr = new_mb;
2458 OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand);
2461 REDISPATCH
2462 });)
2464 DEF_OPC_RW(OPC_INVOKESTATIC, ({
2465 int idx, cache;
2466 Operand operand;
2468 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESTATIC, idx, cache);
2470 frame->last_pc = pc;
2471 new_mb = resolveMethod(mb->class, idx);
2473 if(exceptionOccured0(ee))
2474 goto throwException;
2476 operand.pntr = new_mb;
2477 OPCODE_REWRITE(OPC_INVOKESTATIC_QUICK, cache, operand);
2478 REDISPATCH
2479 });)
2481 DEF_OPC_RW(OPC_INVOKEINTERFACE, ({
2482 int idx, cache;
2483 Operand operand;
2485 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEINTERFACE, idx, cache);
2487 frame->last_pc = pc;
2488 new_mb = resolveInterfaceMethod(mb->class, idx);
2490 if(exceptionOccured0(ee))
2491 goto throwException;
2493 if(CLASS_CB(new_mb->class)->access_flags & ACC_INTERFACE) {
2494 operand.uu.u1 = idx;
2495 operand.uu.u2 = 0;
2496 OPCODE_REWRITE(OPC_INVOKEINTERFACE_QUICK, cache, operand);
2497 } else {
2498 operand.uu.u1 = new_mb->args_count;
2499 operand.uu.u2 = new_mb->method_table_index;
2500 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2503 REDISPATCH
2504 });)
2506 DEF_OPC_RW(OPC_MULTIANEWARRAY, ({
2507 int idx = pc->operand.uui.u1;
2508 int cache = pc->operand.uui.i;
2510 frame->last_pc = pc;
2511 resolveClass(mb->class, idx, FALSE);
2513 if(exceptionOccured0(ee))
2514 goto throwException;
2516 OPCODE_REWRITE(OPC_MULTIANEWARRAY_QUICK, cache, pc->operand);
2517 REDISPATCH
2518 });)
2520 DEF_OPC_RW_4(OPC_NEW, OPC_ANEWARRAY, OPC_CHECKCAST, OPC_INSTANCEOF, ({
2521 int idx = pc->operand.uui.u1;
2522 int opcode = pc->operand.uui.u2;
2523 int cache = pc->operand.uui.i;
2524 Class *class;
2526 frame->last_pc = pc;
2527 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
2529 if(exceptionOccured0(ee))
2530 goto throwException;
2532 if(opcode == OPC_NEW) {
2533 ClassBlock *cb = CLASS_CB(class);
2534 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
2535 signalException("java/lang/InstantiationError", cb->name);
2536 goto throwException;
2540 OPCODE_REWRITE((opcode + OPC_NEW_QUICK-OPC_NEW), cache, pc->operand);
2541 REDISPATCH
2542 });)
2544 DEF_OPC_210(OPC_GETSTATIC2_QUICK, {
2545 FieldBlock *fb = RESOLVED_FIELD(pc);
2546 PUSH_LONG(*(u8*)&fb->static_value, 3);
2549 DEF_OPC_012(OPC_PUTSTATIC2_QUICK, {
2550 FieldBlock *fb = RESOLVED_FIELD(pc);
2551 POP_LONG(*(u8*)&fb->static_value, 3);
2554 DEF_OPC_210(OPC_GETFIELD2_QUICK, {
2555 Object *obj = (Object *)*--ostack;
2556 NULL_POINTER_CHECK(obj);
2558 PUSH_LONG(*(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])), 3);
2562 DEF_OPC_012(OPC_PUTFIELD2_QUICK, {
2563 Object *obj = (Object *)ostack[-3];
2565 ostack -= 3;
2566 NULL_POINTER_CHECK(obj);
2567 *(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])) = *(u8*)&ostack[1];
2568 DISPATCH(0, 3);
2571 DEF_OPC_012(OPC_PUTFIELD_QUICK, {
2572 Object *obj = (Object *)ostack[-2];
2574 ostack -= 2;
2575 NULL_POINTER_CHECK(obj);
2576 INST_DATA(obj)[SINGLE_INDEX(pc)] = ostack[1];
2577 DISPATCH(0, 3);
2581 DEF_OPC_210(OPC_INVOKESUPER_QUICK, {
2582 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)];
2583 arg1 = ostack - (new_mb->args_count);
2584 NULL_POINTER_CHECK(*arg1);
2585 goto invokeMethod;
2588 DEF_OPC_210(OPC_INVOKENONVIRTUAL_QUICK, {
2589 new_mb = RESOLVED_METHOD(pc);
2590 arg1 = ostack - (new_mb->args_count);
2591 NULL_POINTER_CHECK(*arg1);
2592 goto invokeMethod;
2595 DEF_OPC_210(OPC_INVOKESTATIC_QUICK, {
2596 new_mb = RESOLVED_METHOD(pc);
2597 arg1 = ostack - new_mb->args_count;
2598 goto invokeMethod;
2601 DEF_OPC_210(OPC_INVOKEINTERFACE_QUICK, {
2602 int mtbl_idx;
2603 ClassBlock *cb;
2604 int cache = INV_INTF_CACHE(pc);
2606 new_mb = (MethodBlock *)CP_INFO(cp, INV_INTF_IDX(pc));
2607 arg1 = ostack - new_mb->args_count;
2609 NULL_POINTER_CHECK(*arg1);
2611 cb = CLASS_CB(new_class = (*(Object **)arg1)->class);
2613 if((cache >= cb->imethod_table_size) ||
2614 (new_mb->class != cb->imethod_table[cache].interface)) {
2615 for(cache = 0; (cache < cb->imethod_table_size) &&
2616 (new_mb->class != cb->imethod_table[cache].interface); cache++);
2618 if(cache == cb->imethod_table_size)
2619 THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
2620 "unimplemented interface");
2622 INV_INTF_CACHE(pc) = cache;
2625 mtbl_idx = cb->imethod_table[cache].offsets[new_mb->method_table_index];
2626 new_mb = cb->method_table[mtbl_idx];
2628 goto invokeMethod;
2631 DEF_OPC_210(OPC_NEW_QUICK, {
2632 Class *class = RESOLVED_CLASS(pc);
2633 Object *obj;
2635 frame->last_pc = pc;
2636 if((obj = allocObject(class)) == NULL)
2637 goto throwException;
2639 PUSH_0((uintptr_t)obj, 3);
2642 DEF_OPC_210(OPC_ANEWARRAY_QUICK, {
2643 Class *class = RESOLVED_CLASS(pc);
2644 char *name = CLASS_CB(class)->name;
2645 int count = *--ostack;
2646 Class *array_class;
2647 char *ac_name;
2648 Object *obj;
2650 frame->last_pc = pc;
2652 if(count < 0) {
2653 signalException("java/lang/NegativeArraySizeException", NULL);
2654 goto throwException;
2657 ac_name = sysMalloc(strlen(name) + 4);
2659 if(name[0] == '[')
2660 strcat(strcpy(ac_name, "["), name);
2661 else
2662 strcat(strcat(strcpy(ac_name, "[L"), name), ";");
2664 array_class = findArrayClassFromClass(ac_name, mb->class);
2665 free(ac_name);
2667 if(exceptionOccured0(ee))
2668 goto throwException;
2670 if((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
2671 goto throwException;
2673 PUSH_0((uintptr_t)obj, 3);
2676 DEF_OPC_210(OPC_CHECKCAST_QUICK, {
2677 Class *class = RESOLVED_CLASS(pc);
2678 Object *obj = (Object*)ostack[-1];
2680 if((obj != NULL) && !isInstanceOf(class, obj->class))
2681 THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
2683 DISPATCH(0, 3);
2686 DEF_OPC_210(OPC_INSTANCEOF_QUICK, {
2687 Class *class = RESOLVED_CLASS(pc);
2688 Object *obj = (Object*)ostack[-1];
2690 if(obj != NULL)
2691 ostack[-1] = isInstanceOf(class, obj->class);
2693 DISPATCH(0, 3);
2696 DEF_OPC_210(OPC_MULTIANEWARRAY_QUICK, ({
2697 Class *class = RESOLVED_CLASS(pc);
2698 int i, dim = MULTI_ARRAY_DIM(pc);
2699 Object *obj;
2701 ostack -= dim;
2702 frame->last_pc = pc;
2704 for(i = 0; i < dim; i++)
2705 if((intptr_t)ostack[i] < 0) {
2706 signalException("java/lang/NegativeArraySizeException", NULL);
2707 goto throwException;
2710 if((obj = allocMultiArray(class, dim, (intptr_t *)ostack)) == NULL)
2711 goto throwException;
2713 PUSH_0((uintptr_t)obj, 4);
2714 });)
2716 /* Special bytecode which forms the body of an abstract method.
2717 If it is invoked it'll throw an abstract method exception. */
2719 DEF_OPC_210(OPC_ABSTRACT_METHOD_ERROR, {
2720 /* As the method has been invoked, a frame will exist for
2721 the abstract method itself. Pop this to get the correct
2722 exception stack trace. */
2723 ee->last_frame = frame->prev;
2725 /* Throw the exception */
2726 signalException("java/lang/AbstractMethodError", mb->name);
2727 goto throwException;
2732 DEF_OPC_210(OPC_INVOKEVIRTUAL_QUICK, {
2733 arg1 = ostack - INV_QUICK_ARGS(pc);
2734 NULL_POINTER_CHECK(*arg1);
2736 new_class = (*(Object **)arg1)->class;
2737 new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(pc)];
2739 goto invokeMethod;
2742 invokeMethod:
2744 #ifdef JEM
2745 #else
2746 /* Create new frame first. This is also created for natives
2747 so that they appear correctly in the stack trace */
2749 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
2750 Object *sync_ob = NULL;
2752 frame->last_pc = pc;
2753 ostack = (uintptr_t *)(new_frame+1);
2755 if((char*)(ostack + new_mb->max_stack) > ee->stack_end) {
2756 if(ee->overflow++) {
2757 /* Overflow when we're already throwing stack overflow.
2758 Stack extension should be enough to throw exception,
2759 so something's seriously gone wrong - abort the VM! */
2760 jam_printf("Fatal stack overflow! Aborting VM.\n");
2761 exitVM(1);
2763 ee->stack_end += STACK_RED_ZONE_SIZE;
2764 THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
2767 new_frame->mb = new_mb;
2768 new_frame->lvars = arg1;
2769 new_frame->ostack = ostack;
2770 new_frame->prev = frame;
2772 ee->last_frame = new_frame;
2774 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
2775 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1;
2776 objectLock(sync_ob);
2779 if(new_mb->access_flags & ACC_NATIVE) {
2780 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
2781 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
2783 if(sync_ob)
2784 objectUnlock(sync_ob);
2786 ee->last_frame = frame;
2788 if(exceptionOccured0(ee))
2789 goto throwException;
2790 DISPATCH(0, *pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
2791 } else {
2792 PREPARE_MB(new_mb);
2794 frame = new_frame;
2795 mb = new_mb;
2796 lvars = new_frame->lvars;
2797 this = (Object*)lvars[0];
2798 pc = (CodePntr)mb->code;
2799 cp = &(CLASS_CB(mb->class)->constant_pool);
2801 DISPATCH_FIRST
2802 #endif
2805 methodReturn:
2806 #ifdef JEM
2807 #else
2808 /* Set interpreter state to previous frame */
2810 frame = frame->prev;
2812 if(frame->mb == NULL) {
2813 /* The previous frame is a dummy frame - this indicates
2814 top of this Java invocation. */
2815 return ostack;
2818 if(mb->access_flags & ACC_SYNCHRONIZED) {
2819 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
2820 objectUnlock(sync_ob);
2823 mb = frame->mb;
2824 ostack = lvars;
2825 lvars = frame->lvars;
2826 this = (Object*)lvars[0];
2827 pc = frame->last_pc;
2828 cp = &(CLASS_CB(mb->class)->constant_pool);
2830 /* Pop frame */
2831 ee->last_frame = frame;
2833 DISPATCH_METHOD_RET(*pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
2834 #endif
2837 throwException:
2839 Object *excep = ee->exception;
2840 ee->exception = NULL;
2842 pc = findCatchBlock(excep->class);
2844 /* If we didn't find a handler, restore exception and
2845 return to previous invocation */
2847 if(pc == NULL) {
2848 ee->exception = excep;
2849 return NULL;
2852 /* If we're handling a stack overflow, reduce the stack
2853 back past the red zone to enable handling of further
2854 overflows */
2856 if(ee->overflow) {
2857 ee->overflow = FALSE;
2858 ee->stack_end -= STACK_RED_ZONE_SIZE;
2861 /* Setup intepreter to run the found catch block */
2863 frame = ee->last_frame;
2864 mb = frame->mb;
2865 ostack = frame->ostack;
2866 lvars = frame->lvars;
2867 this = (Object*)lvars[0];
2868 cp = &(CLASS_CB(mb->class)->constant_pool);
2870 *ostack++ = (uintptr_t)excep;
2872 /* Dispatch to the first bytecode */
2874 DISPATCH_FIRST
2876 #endif
2879 #ifndef executeJava
2880 void initialiseInterpreter(InitArgs *args) {
2881 initialiseDirect(args);
2883 #endif
2885 #endif //JEM