White-space fixes
[jamvm-avr32-jem.git] / src / interp / engine / interp_jem.c
blob092ae51840fc2141f2a0c780ba486f470ce175c2
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 /* These static variables come from the time when there was only one function in
45 * this file. So, we are pretty sure they must be shared. An attempt to pack
46 * them all in struct and pass a pointer to it around ended up in a way too ugly
47 * and suboptimal code. FIXME: fix when going multithreaded. */
49 static MethodBlock *mb;
50 static uintptr_t *lvars_jem;
51 static uintptr_t *ostack;
52 static ConstantPool *cp;
53 static Object *this;
54 static MethodBlock *new_mb;
55 static uintptr_t *arg1;
56 static Frame *frame;
57 static uintptr_t *lvars;
59 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
61 #define JEM_THROW_EXCEPTION(excep_name, message) \
62 ({ \
63 frame->last_pc = (CodePntr)jem->jpc; \
64 signalException(excep_name, message); \
65 jem_throwException(jem); \
68 #define JEM_NULL_POINTER_CHECK(ref) \
69 if(!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
71 #define OSTACK_ASCENDING
73 #ifdef OSTACK_ASCENDING
75 #define ostack_overflows(base, size, top) ((base) + (size) >= (top))
77 #ifndef OSTACK_DEBUG
79 #define ostack_push_u32(base, size, top, data) ({ \
80 *(top)++ = (data); \
81 0; \
84 #define ostack_pop_u32(base, size, top, data) ({ \
85 (data) = (typeof(data))*--(top); \
86 0; \
89 #define ostack_pop_u64(base, size, top, data) ({ \
90 (top) = (typeof(top))((uint64_t *)top - 1); \
91 (data) = *(uint64_t *)top; \
92 0; \
95 #define ostack_read_u32(base, top, offset, data) ({ \
96 *(data) = *((top) - (offset) - 1); \
97 0; \
100 #define ostack_address(base, size, offset) ((base) + (offset))
102 #define ostack_depth(base, top) ((top) - (base))
104 #else
106 #define ostack_push_u32(base, size, top, data) ({ \
107 if ((size) <= (top) - (base)) \
108 -ENOMEM; \
109 else { \
110 *(top)++ = (data); \
111 0; \
115 #define ostack_pop_u32(base, size, top, data) ({ \
116 if ((top) <= (base)) \
117 -ENOMEM; \
118 else { \
119 (data) = *--(top); \
120 0; \
124 #define ostack_pop_u64(base, size, top, data) ({ \
125 if ((top) <= (base)) \
126 -ENOMEM; \
127 else { \
128 (data) = *--((uint64_t *)top); \
129 0; \
133 #define ostack_read_u32(base, top, offset, data) ({ \
134 uint32_t _o = (offset), _t = (top); \
135 if (_o > _t - (base)) \
136 -ENOMEM; \
137 else { \
138 *data = *(_t - _o - 1); \
139 0; \
143 #define ostack_address(base, size, offset) ({ \
144 uint32_t _o = (offset); \
145 if (_o >= (size)) \
146 -ENOMEM; \
147 else \
148 (base) + _o; \
151 #define ostack_depth(base, top) ({ \
152 uint32_t _b = (base), _t = (top); \
153 if (_t < _b) \
154 -ENOMEM; \
155 else \
156 _t - _b; \
159 #endif
160 #endif
162 /*********************************************
163 * JEM Trap Handlers **
164 * *******************************************/
165 static int trap_debug(struct jem_state *jem)
167 union {
168 struct {
169 uint8_t dummy;
170 uint8_t opcode;
171 uint8_t op1;
172 uint8_t op2;
173 } s;
174 uint32_t i;
175 } jecr_u;
176 int i;
178 jecr_u.i = jem->jecr;
180 printf("Trap 0x%08x: opcode 0x%x @ 0x%08x, operand 1 0x%x, operand2 0x%x. Operands:\n",
181 jem->trap_pc, jecr_u.s.opcode, jem->jpc, jecr_u.s.op1, jecr_u.s.op2);
183 for (i = 0; i < jem->josp; i++) {
184 uint32_t v;
185 if (ostack_read_u32(frame->ostack, ostack, i, &v) >= 0)
186 printf("\tToS-%d: 0x%x\n", i, v);
189 return 1;
193 static int jem_throwException(struct jem_state *jem)
195 ExecEnv *ee = getExecEnv();
196 Object *excep = ee->exception;
197 ee->exception = NULL;
199 jem->jpc = (unsigned long)findCatchBlock(excep->class);
200 jam_printf("Found exception handler at 0x%08x\n", jem->jpc);
202 /* If we didn't find a handler, restore exception and
203 return to previous invocation */
205 if (!jem->jpc) {
206 ee->exception = excep;
207 /* Original code had a "return NULL" here, which means, end of
208 * executeJava */
209 return JEM_TRAP_HANDLER_FINISH;
212 /* If we're handling a stack overflow, reduce the stack
213 back past the red zone to enable handling of further
214 overflows */
216 if (ee->overflow) {
217 ee->overflow = FALSE;
218 ee->stack_end -= STACK_RED_ZONE_SIZE;
221 /* Setup intepreter to run the found catch block */
223 frame = ee->last_frame;
224 mb = frame->mb;
225 ostack = frame->ostack;
226 lvars = frame->lvars;
227 this = (Object*)lvars[0];
228 cp = &(CLASS_CB(mb->class)->constant_pool);
230 /* FIXME: don't know if this is correct, depends how we implement
231 * exceptions */
232 ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uint32_t)excep);
234 /* Dispatch to the first bytecode */
235 return 0;
238 static int opc_return(struct jem_state *jem)
240 ExecEnv *ee = getExecEnv();
241 /* Set interpreter state to previous frame */
243 if (frame->prev->mb == NULL) {
244 /* The previous frame is a dummy frame - this indicates
245 top of this Java invocation. */
246 return 1;
249 if (frame->lvars_jem != NULL)
250 sysFree(frame->lvars_jem - frame->mb->max_locals);
252 frame = frame->prev;
254 if (mb->access_flags & ACC_SYNCHRONIZED) {
255 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
256 objectUnlock(sync_ob);
259 mb = frame->mb;
260 ostack = lvars;
261 lvars = frame->lvars;
262 lvars_jem = frame->lvars_jem - 1;
263 this = (Object*)(*lvars_jem);
264 jem->jpc = (uint32_t)frame->last_pc;
265 cp = &(CLASS_CB(mb->class)->constant_pool);
267 /* Pop frame */
268 ee->last_frame = frame;
270 return 0;
273 static int invokeMethod(struct jem_state *jem)
275 ExecEnv *ee = getExecEnv();
276 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
277 Object *sync_ob = NULL;
278 int i;
280 jam_printf("[invokeMethod] with args count %d \n", new_mb->args_count);
281 jam_printf("[invokeMethod] new frame start %x\n", new_frame);
283 frame->last_pc = (CodePntr)jem->jpc;
284 ostack = (uintptr_t *)(new_frame + 1);
286 if (ostack_overflows(ostack, new_mb->max_stack, (uintptr_t *)ee->stack_end)) {
287 if(ee->overflow++) {
288 /* Overflow when we're already throwing stack overflow.
289 Stack extension should be enough to throw exception,
290 so something's seriously gone wrong - abort the VM! */
291 jam_printf("Fatal stack overflow! Aborting VM.\n");
292 exitVM(1);
294 ee->stack_end += STACK_RED_ZONE_SIZE;
295 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
298 //TODO
299 new_frame->mb = new_mb;
300 new_frame->lvars = arg1;
301 //TODO: it seemed lvars is in java stack,but jos[8] should be part of java stack
302 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
303 // Here still not touch the java stack,allocate lvars_jem from native heap
305 new_frame->lvars_jem = sysMalloc(new_mb->max_locals * sizeof(uintptr_t));
306 new_frame->lvars_jem = new_frame->lvars_jem + new_mb->max_locals;
307 jam_printf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame->lvars_jem);
309 for (i = 0; i < new_mb->args_count; i++)
310 *(new_frame->lvars_jem - 1 - i) = *(arg1 + i);
312 new_frame->ostack = ostack;
313 new_frame->prev = frame;
315 ee->last_frame = new_frame;
317 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
318 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1;
319 objectLock(sync_ob);
322 if(new_mb->access_flags & ACC_NATIVE) {
323 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
324 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
326 if(sync_ob)
327 objectUnlock(sync_ob);
329 ee->last_frame = frame;
331 if(exceptionOccured0(ee)){
332 jam_printf("[invokeMethod] exceptio occured, goto throwException\n");
333 return jem_throwException(jem);
334 //exitVM(1);
337 jam_printf("[invokeMethod] finish native method invoke, return to loop\n");
338 return 0;
339 } else {
340 frame = new_frame;
341 mb = new_mb;
342 lvars = frame->lvars;
343 lvars_jem = new_frame->lvars_jem - 1;
344 this = (Object*)(*lvars_jem);
345 jem->jpc = (unsigned long)mb->code & ~3;
346 cp = &(CLASS_CB(mb->class)->constant_pool);
348 jam_printf("[invokeMethod] invoke virtual method: frame %x mb %x "
349 "lvars %x jpc %x cp %x \n", frame, mb, lvars_jem, jem->jpc, cp);
351 jam_printf("[invokeMethod] finish virtual method invoke, return to loop\n");
353 return 0;
356 static int opc_invokesuper_quick(struct jem_state *jem)
358 Operand *operand = &jem->operand;
360 jam_printf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand->i);
361 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[operand->i];
362 jam_printf("[OPC_INVOKESUPER_QUICK] method args count %d \n", new_mb->args_count);
364 // set up jem operand stack
365 arg1 = ostack_address(frame->ostack, mb->max_stack,
366 ostack - frame->ostack - new_mb->args_count);
367 JEM_NULL_POINTER_CHECK(*arg1);
368 jam_printf("[OP_INVOKESUPER_QUICK] arg1 %x \n", *arg1);
369 return invokeMethod(jem);
372 static int opc_invokenonvirtual_quick(struct jem_state *jem)
374 Operand *operand = &jem->operand;
376 new_mb = (MethodBlock*)operand->pntr;
377 jam_printf("[OPC_INVOKENONVIRTUAL_QUICK] new methodblock %s (%x) with %d args\n",
378 new_mb->name, new_mb, new_mb->args_count);
379 arg1 = ostack_address(frame->ostack, mb->max_stack,
380 ostack - frame->ostack - new_mb->args_count);
381 jam_printf("[OP_INVOKENONVIRTUAL_QUICK] arg1 %x \n", *arg1);
382 JEM_NULL_POINTER_CHECK(*arg1);
383 return invokeMethod(jem);
386 static int opc_invokespecial(struct jem_state *jem)
388 int idx, cache;
389 Operand *operand = &jem->operand;
390 ExecEnv *ee = getExecEnv();
392 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
393 idx = jem->jecr & 0xffff;
395 jam_printf("[OPC_INVOKESPECIAL] constant pool index %d \n", idx);
397 new_mb = resolveMethod(mb->class, idx);
399 if (exceptionOccured0(ee))
400 return jem_throwException(jem);
402 jam_printf("Resolved %s\n", new_mb->name);
404 /* Check if invoking a super method... */
405 if ((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
406 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
408 operand->i = new_mb->method_table_index;
409 return opc_invokesuper_quick(jem);
410 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
411 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
412 #endif
413 } else {
414 operand->pntr = new_mb;
415 return opc_invokenonvirtual_quick(jem);
416 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
417 OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand);
418 #endif
421 return 0;
424 static int opc_new_quick(struct jem_state *jem)
426 Operand *operand = &jem->operand;
427 Class *class = (Class*)CP_INFO(cp, operand->uui.u1);
428 Object *obj;
430 frame->last_pc = (CodePntr)jem->jpc;
431 if((obj = allocObject(class)) == NULL)
432 return jem_throwException(jem);
433 jam_printf("[OPC_NEW_QUICK] push obj ref %x to stack \n", obj);
434 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)obj);
437 static int opc_new(struct jem_state *jem)
439 Operand *operand = &jem->operand;
440 int idx = operand->uui.u1 = jem->jecr & 0xffff;
441 int opcode = operand->uui.u2 = (jem->jecr >> 16) & 0xff;
442 int cache = operand->uui.i = 0;
443 Class *class;
444 ExecEnv *ee = getExecEnv();
446 jam_printf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode);
448 frame->last_pc = (CodePntr)jem->jpc;
449 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
450 if(exceptionOccured0(ee))
451 return jem_throwException(jem);
453 if(opcode == OPC_NEW) {
454 ClassBlock *cb = CLASS_CB(class);
455 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
456 signalException("java/lang/InstantiationError", cb->name);
457 return jem_throwException(jem);
461 return opc_new_quick(jem);
464 static int opc_putfield_quick(struct jem_state *jem)
466 uint32_t arg;
467 Object *obj;
469 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, arg);
470 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
472 JEM_NULL_POINTER_CHECK(obj);
473 INST_DATA(obj)[SINGLE_INDEX(jem)] = arg;
475 return 0;
478 static int opc_putfield2_quick(struct jem_state *jem)
480 uint64_t arg;
481 Object *obj;
483 ostack_pop_u64(frame->ostack, mb->max_stack, ostack, arg);
484 ostack_pop_u32(frame->ostack, mb->max_stack, ostack, obj);
486 JEM_NULL_POINTER_CHECK(obj);
487 *(uint64_t *)&(INST_DATA(obj)[SINGLE_INDEX(jem)]) = arg;
489 return 0;
492 static int opc_putfield(struct jem_state *jem)
494 int idx = jem->jecr & 0xffff;
495 FieldBlock *fb;
496 ExecEnv *ee = getExecEnv();
498 jam_printf("[OPC_PUTFIELD] constant pool index %d\n", idx);
500 frame->last_pc = (CodePntr)jem->jpc;
501 fb = resolveField(mb->class, idx);
502 jam_printf("[OPC_PUTFIELD] resolve field 0x%08x, type %c\n", fb, *fb->type);
504 if(exceptionOccured0(ee))
505 return jem_throwException(jem);
507 jem->operand.i = fb->offset;
508 switch (*fb->type) {
509 case 'J':
510 case 'D':
511 return opc_putfield2_quick(jem);
512 default:
513 return opc_putfield_quick(jem);
517 static int opc_ldc_w_quick(struct jem_state *jem)
519 uint32_t cp_info = CP_INFO(cp,DOUBLE_INDEX(jem));
520 jam_printf("[OPC_LDC_W_QUICK] push cp info %x to stack \n", cp_info);
521 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)cp_info);
524 static int opc_ldc_quick(struct jem_state *jem)
526 uint32_t constant = RESOLVED_CONSTANT(jem);
527 jam_printf("[OPC_LDC_QUICK] push constant %x to stack \n", constant);
528 return ostack_push_u32(frame->ostack, mb->max_stack, ostack, (uintptr_t)constant);
531 static int opc_ldc(struct jem_state *jem)
533 int idx;
534 ExecEnv *ee = getExecEnv();
536 idx = (int)(jem->jecr & 0xffff);
538 jam_printf("[OPC_LDC] constant pool index %d\n", idx);
539 frame->last_pc = (CodePntr)jem->jpc;
541 jem->operand.u = resolveSingleConstant(mb->class, idx);
543 if(exceptionOccured0(ee))
544 return jem_throwException(jem);
546 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass ||
547 CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
548 jem->operand.i = idx;
549 return opc_ldc_w_quick(jem);
550 } else
551 return opc_ldc_quick(jem);
554 static int opc_ldc_w(struct jem_state *jem)
556 //rewritten to opc_ldc
557 return opc_ldc(jem);
560 static int do_javaExceptions(struct jem_state *jem)
562 return JEM_TRAP_HANDLER_SYSEX;
565 static int do_stackOverflow(struct jem_state *jem)
567 return 1;
570 static int do_stackUnderflow(struct jem_state *jem)
572 return 1;
575 static int do_stackOverflow1(struct jem_state *jem)
577 return 1;
580 static int do_stackUnderflow1(struct jem_state *jem)
582 return 1;
585 static handler_fn *trap_handler_f[256];
587 static handler_fn *exception_handler_f[] = {
588 [0] = do_javaExceptions,
589 [1] = do_stackOverflow,
590 [2] = do_stackUnderflow,
591 [3] = do_stackOverflow1,
592 [4] = do_stackUnderflow1,
595 /******************************/
596 uintptr_t *executeJava(void)
598 #if 0
600 * Using jamVm's direct threaded interpreting table to perform effective work
602 #define L(opcode, level, label) &&opc##opcode##_##level##_##label
604 #define D(opcode, level, label) &&rewrite_lock
606 #define I(opcode, level, label) &&rewrite_lock
608 #define DEF_HANDLER_TABLE(lvl,lbl) \
609 HANDLER_TABLE_T *handlers_##lvl##_##lbl[] = { \
610 L(0,lvl,lbl), L(1,lvl,lbl), L(2,lvl,lbl), L(3,lvl,lbl), L(4,lvl,lbl), \
611 L(5,lvl,lbl), L(6,lvl,lbl), L(7,lvl,lbl), L(8,lvl,lbl), L(9,lvl,lbl), \
612 L(10,lvl,lbl), L(11,lvl,lbl), L(12,lvl,lbl), L(13,lvl,lbl), L(14,lvl,lbl), \
613 L(15,lvl,lbl), L(16,lvl,lbl), L(17,lvl,lbl), L(18,lvl,lbl), D(19,lvl,lbl), \
614 L(20,lvl,lbl), L(21,lvl,lbl), L(22,lvl,lbl), L(23,lvl,lbl), L(24,lvl,lbl), \
615 L(25,lvl,lbl), L(26,lvl,lbl), L(27,lvl,lbl), L(28,lvl,lbl), L(29,lvl,lbl), \
616 L(30,lvl,lbl), L(31,lvl,lbl), L(32,lvl,lbl), L(33,lvl,lbl), L(34,lvl,lbl), \
617 L(35,lvl,lbl), L(36,lvl,lbl), L(37,lvl,lbl), L(38,lvl,lbl), L(39,lvl,lbl), \
618 L(40,lvl,lbl), L(41,lvl,lbl), D(42,lvl,lbl), L(43,lvl,lbl), L(44,lvl,lbl), \
619 L(45,lvl,lbl), L(46,lvl,lbl), L(47,lvl,lbl), L(48,lvl,lbl), L(49,lvl,lbl), \
620 L(50,lvl,lbl), L(51,lvl,lbl), L(52,lvl,lbl), L(53,lvl,lbl), L(54,lvl,lbl), \
621 L(55,lvl,lbl), L(56,lvl,lbl), L(57,lvl,lbl), L(58,lvl,lbl), L(59,lvl,lbl), \
622 L(60,lvl,lbl), L(61,lvl,lbl), L(62,lvl,lbl), L(63,lvl,lbl), L(64,lvl,lbl), \
623 L(65,lvl,lbl), L(66,lvl,lbl), L(67,lvl,lbl), L(68,lvl,lbl), L(69,lvl,lbl), \
624 L(70,lvl,lbl), L(71,lvl,lbl), L(72,lvl,lbl), L(73,lvl,lbl), L(74,lvl,lbl), \
625 L(75,lvl,lbl), L(76,lvl,lbl), L(77,lvl,lbl), L(78,lvl,lbl), L(79,lvl,lbl), \
626 L(80,lvl,lbl), L(81,lvl,lbl), L(82,lvl,lbl), L(83,lvl,lbl), L(84,lvl,lbl), \
627 L(85,lvl,lbl), L(86,lvl,lbl), L(87,lvl,lbl), L(88,lvl,lbl), L(89,lvl,lbl), \
628 L(90,lvl,lbl), L(91,lvl,lbl), L(92,lvl,lbl), L(93,lvl,lbl), L(94,lvl,lbl), \
629 L(95,lvl,lbl), L(96,lvl,lbl), L(97,lvl,lbl), L(98,lvl,lbl), L(99,lvl,lbl), \
630 L(100,lvl,lbl), L(101,lvl,lbl), L(102,lvl,lbl), L(103,lvl,lbl), L(104,lvl,lbl), \
631 L(105,lvl,lbl), L(106,lvl,lbl), L(107,lvl,lbl), L(108,lvl,lbl), L(109,lvl,lbl), \
632 L(110,lvl,lbl), L(111,lvl,lbl), L(112,lvl,lbl), L(113,lvl,lbl), L(114,lvl,lbl), \
633 L(115,lvl,lbl), L(116,lvl,lbl), L(117,lvl,lbl), L(118,lvl,lbl), L(119,lvl,lbl), \
634 L(120,lvl,lbl), L(121,lvl,lbl), L(122,lvl,lbl), L(123,lvl,lbl), L(124,lvl,lbl), \
635 L(125,lvl,lbl), L(126,lvl,lbl), L(127,lvl,lbl), L(128,lvl,lbl), L(129,lvl,lbl), \
636 L(130,lvl,lbl), L(131,lvl,lbl), L(132,lvl,lbl), L(133,lvl,lbl), L(134,lvl,lbl), \
637 L(135,lvl,lbl), L(136,lvl,lbl), L(137,lvl,lbl), L(138,lvl,lbl), L(139,lvl,lbl), \
638 L(140,lvl,lbl), L(141,lvl,lbl), L(142,lvl,lbl), L(143,lvl,lbl), L(144,lvl,lbl), \
639 L(145,lvl,lbl), L(146,lvl,lbl), L(147,lvl,lbl), L(148,lvl,lbl), L(149,lvl,lbl), \
640 L(150,lvl,lbl), L(151,lvl,lbl), L(152,lvl,lbl), L(153,lvl,lbl), L(154,lvl,lbl), \
641 L(155,lvl,lbl), L(156,lvl,lbl), L(157,lvl,lbl), L(158,lvl,lbl), L(159,lvl,lbl), \
642 L(160,lvl,lbl), L(161,lvl,lbl), L(162,lvl,lbl), L(163,lvl,lbl), L(164,lvl,lbl), \
643 L(165,lvl,lbl), L(166,lvl,lbl), L(167,lvl,lbl), L(168,lvl,lbl), L(169,lvl,lbl), \
644 L(170,lvl,lbl), L(171,lvl,lbl), L(172,lvl,lbl), L(173,lvl,lbl), L(174,lvl,lbl), \
645 L(175,lvl,lbl), L(176,lvl,lbl), L(177,lvl,lbl), L(178,lvl,lbl), L(179,lvl,lbl), \
646 L(180,lvl,lbl), L(181,lvl,lbl), L(182,lvl,lbl), L(183,lvl,lbl), L(184,lvl,lbl), \
647 L(185,lvl,lbl), &&unused, L(187,lvl,lbl), L(188,lvl,lbl), L(189,lvl,lbl), \
648 L(190,lvl,lbl), L(191,lvl,lbl), L(192,lvl,lbl), L(193,lvl,lbl), L(194,lvl,lbl), \
649 L(195,lvl,lbl), D(196,lvl,lbl), L(197,lvl,lbl), L(198,lvl,lbl), L(199,lvl,lbl), \
650 L(200,lvl,lbl), L(201,lvl,lbl), &&unused, L(203,lvl,lbl), L(204,lvl,lbl), \
651 &&unused, L(206,lvl,lbl), L(207,lvl,lbl), L(208,lvl,lbl), L(209,lvl,lbl), \
652 L(210,lvl,lbl), L(211,lvl,lbl), L(212,lvl,lbl), L(213,lvl,lbl), L(214,lvl,lbl), \
653 L(215,lvl,lbl), L(216,lvl,lbl), &&unused, &&unused, &&unused, &&unused, \
654 &&unused, &&unused, &&unused, &&unused, &&unused, D(226,lvl,lbl), \
655 D(227,lvl,lbl), D(228,lvl,lbl), L(229,lvl,lbl), D(230,lvl,lbl), L(231,lvl,lbl), \
656 L(232,lvl,lbl), L(233,lvl,lbl), &&unused, L(235,lvl,lbl), &&unused, \
657 &&unused, L(238,lvl,lbl), L(239,lvl,lbl), &&unused, &&unused, &&unused, \
658 L(243,lvl,lbl), L(244,lvl,lbl), L(245,lvl,lbl), I(246,lvl,lbl), &&unused, \
659 &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, &&unused, \
660 &&unused}
662 DEF_HANDLER_TABLE(0, ENTRY);
663 #endif
665 * load trap entries to JEM trap table set when initializing JamVM
667 int i;
669 // static const void **handlers[] = {handlers_0_ENTRY};
671 ExecEnv *ee = getExecEnv();
673 /* Initialize interpreter's static environment */
674 frame = ee->last_frame;
675 mb = frame->mb;
676 lvars_jem = frame->lvars_jem - 1;
678 * We use ostack to save overflowing Java Operand Stack elements. On a stack
679 * overflow we free a half of the stack (4 elements) to avoid an immediate
680 * next overflow. When entering a trap, the Operand Stack is saved in a
681 * temporary array in the reverse order:
682 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
683 * jos[0] = r7 (?)
684 * ...
685 * jos[7 - N] = rN (ToS - N)
686 * ...
687 * jos[7] = r0 (ToS)
688 * UPDATE (27.06.2008)
689 * I think, actually, the manual is right in some way... If you access
690 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
691 * with an ldm, you get this:
692 * jos[0] = r7 (?)
693 * ...
694 * jos[7 - N] = rN (ToS)
695 * ...
696 * jos[7] = r0 (ToS - N)
697 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
698 * set saved JOSP to 4.
700 unsigned long jos[8];
701 ostack = frame->ostack;
702 cp = &(CLASS_CB(mb->class)->constant_pool);
703 lvars = frame->lvars;
704 this = (Object*)lvars[0];
705 /* End enterpreter's static environment */
707 Class *new_class;
709 //fetch the original pc before prepare direct mb
710 //TODO:
711 /* I think, mb->code is indeed a copy of the original code[] array from the
712 * class object. See class.c::defineClass():390 */
713 struct jem_state jem;
714 uint32_t jep;
715 int done;
717 /* This is temporary. As we implement more handlers, we'll think of a better
718 * way to link them. */
719 trap_handler_f[OPC_INVOKESPECIAL] = opc_invokespecial;
720 trap_handler_f[OPC_INVOKESUPER_QUICK] = opc_invokesuper_quick;
721 trap_handler_f[OPC_INVOKENONVIRTUAL_QUICK] = opc_invokenonvirtual_quick;
722 trap_handler_f[OPC_NEW] = opc_new;
723 trap_handler_f[OPC_NEW_QUICK] = opc_new_quick;
724 trap_handler_f[OPC_RETURN] = opc_return;
725 trap_handler_f[OPC_PUTFIELD] = opc_putfield;
726 trap_handler_f[OPC_PUTFIELD_QUICK] = opc_putfield_quick;
727 trap_handler_f[OPC_PUTFIELD2_QUICK] = opc_putfield2_quick;
728 trap_handler_f[OPC_LDC_W_QUICK] = opc_ldc_w_quick;
729 trap_handler_f[OPC_LDC_QUICK] = opc_ldc_quick;
730 trap_handler_f[OPC_LDC_W] = opc_ldc_w;
731 trap_handler_f[OPC_LDC] = opc_ldc;
733 #if 0
734 /* Don't think we need it, at least, not in the direct.c form. There the code
735 * is converted into an internal representation, which is useless for JEM */
736 PREPARE_MB(mb);//see direct.c (prepare)
737 #endif
739 jem.jpc = (unsigned long)mb->code & ~3;
741 do {
742 int opcode;
744 jam_printf("About to enter JEM at 0x%08x, this = %p. Code:", jem.jpc, this);
745 for (i = 0; i < 32 && jem.jpc + i < (unsigned long)(mb->code + mb->code_size); i++) {
746 if (!(i & 0xf))
747 jam_printf("\n0x%04x:", i);
748 jam_printf(" 0x%02x", ((char*)jem.jpc)[i]);
751 jam_printf("\nUp to 8 first Local Variables out of %d:\n", mb->max_locals);
752 for (i = 0; i < min(8, mb->max_locals); i++)
753 jam_printf("LVAR_%d: 0x%08x\n", i, *(lvars - i));
755 /* On entry we need last Java Operand Stack depth, set it not deeper
756 * than half hardware stack */
757 jem.josp = min(4, ostack_depth(frame->ostack, ostack));
758 /* As long as we are in asm, top jem.josp stack elements belong JEM */
759 for (i = 0; i < jem.josp; i++)
760 ostack_pop_u32(frame->ostack, mb->max_stack, ostack,
761 jos[7 - jem.josp + 1 + i]);
763 __asm__ __volatile__(
764 "pushm r0-r7,r10-r11\n"
765 " mov r8, %[cp]\n"
766 " mov r9, %[lv0]\n"
767 " mov lr, %[jpc]\n"
768 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
769 " mov r11, %[ostack]\n"
770 " pushm r11\n" /* Need ostack below */
771 " ldm r11, r0-r7\n" /* Restore Java Operands */
772 " cp.w r12, 0\n" /* Test josp == 0 */
773 " breq 4f\n"
774 "5: incjosp 1\n" /* ... for loop counter, */
775 " sub r12, 1\n" /* because it can be */
776 " brne 5b\n" /* one of r0-r7 */
777 "4: popjc\n" /* Restore Local Variables */
778 " sub r10, pc, . - trap\n" /* These 3 instructions */
779 " retj\n" /* have to stay */
780 "trap: pushjc\n" /* together */
781 " mfsr r11, 0x58\n" /* JOSP */
782 " lsl r11, 29\n" /* Clear r11[31:3] using */
783 " lsr r11, 29\n" /* one register */
784 " mov r8, r11\n"
785 " breq 2f\n"
786 "3: incjosp -1\n"
787 " sub r11, 1\n"
788 " brne 3b\n"
789 "2: popm r11\n" /* ostack */
790 " stm r11, r0-r7\n" /* Save Java Operands */
791 " popm r0-r7,r10-r11\n"
792 " mov %[tpc], r12\n"
793 " mov %[jpc], lr\n" /* Resume address */
794 " mfsr %[jecr], 0x54\n" /* JECR */
795 " mov %[josp], r8\n" /* JOSP */
796 : [jecr] "=r" (jem.jecr), [tpc] "=r" (jem.trap_pc),
797 [josp] "+r" (jem.josp), [jpc] "+r" (jem.jpc)
798 : [cp] "r" (cp->orgPointer), [lv0] "r" (lvars_jem),
799 [ostack] "r" (jos)
800 : "r8", "r9", "lr", "r12", "memory"
803 * trap_pc now holds trap pc, describing which trap has been entered,
804 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
805 * arguments at bits 7..0 and 15..8,
806 * josp holds JOSP (JOSP & 7),
807 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
808 * jpc points at the trapping opcode, in case of exceptions and stack
809 * over- and underflows, and at the next opcode, in case of a trap
812 for (i = 0; i < jem.josp; i++)
813 ostack_push_u32(frame->ostack, mb->max_stack, ostack,
814 jos[7 - i]);
816 opcode = (jem.jecr >> 16) & 0xff;
818 jep = jem.trap_pc & 0xfff;
820 trap_debug(&jem);
821 if (jep < 0x280)
822 done = exception_handler_f[jep >> 7](&jem);
823 else if (trap_handler_f[opcode])
824 done = trap_handler_f[opcode](&jem);
825 else {
826 /* Unimplemented */
827 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode);
828 exitVM(1);
830 } while (done != JEM_TRAP_HANDLER_FINISH);
832 return ostack;
834 rewrite_lock:
835 // DISPATCH_FIRST;
837 unused:
838 jam_printf("Unknown Java Opcodes\n");
839 exitVM(1);
841 #if 0
842 //our own trap handlers
843 #define JEM_TRAP_MULTI_LEVEL_ENTRIES(level) \
844 DEF_DISPATCHTRAP(level) \
845 DEF_JAVAEX(level) \
846 DEF_STACKOVERFLOW(level) \
847 DEF_STACKUNDERFLOW(level) \
848 DEF_STACKOVERFLOW1(level) \
849 DEF_STACKUNDERFLOW1(level) \
850 DEF_IAFRETURN(level) \
851 DEF_RETURN(level) \
852 DEF_LDRETURN(level) \
853 DEF_IINC(level) \
854 DEF_CHECKCASTQUICK(level) \
855 DEF_INSTANCEOFQUICK(level) \
856 DEF_GETSTATIC(level) \
857 DEF_PUTSTATIC(level) \
858 DEF_NEW(level)\
859 DEF_INVOKESTATIC(level) \
860 DEF_INVOKEINTERFACEQUICK(level) \
861 DEF_INVOKEVIRTUALQUICK(level) \
862 DEF_INVOKESTATICQUICK(level) \
863 DEF_INVOKENONVIRTUALQUICK(level) \
864 DEF_XNEWARRAY(level) \
865 DEF_LONGINSTRPS(level) \
866 DEF_FLOATINSTRPS(level) \
867 DEF_DOUBLEINSTRPS(level) \
868 DEF_OTHERINSTRPS(level)
871 JEM_TRAP_MULTI_LEVEL_ENTRIES(0);
872 #endif
874 #if 0
875 #define MULTI_LEVEL_OPCODES(level) \
876 DEF_OPC(OPC_ICONST_M1, level, \
877 PUSH_##level(-1, 1); \
880 DEF_OPC_3(OPC_ACONST_NULL, \
881 OPC_ICONST_0, \
882 OPC_FCONST_0, level, \
883 PUSH_##level(0, 1); \
886 DEF_OPC(OPC_ICONST_1, level, \
887 PUSH_##level(1, 1); \
890 DEF_OPC(OPC_ICONST_2, level, \
891 PUSH_##level(2, 1); \
894 DEF_OPC(OPC_ICONST_3, level, \
895 PUSH_##level(3, 1); \
898 DEF_OPC(OPC_ICONST_4, level, \
899 PUSH_##level(4, 1); \
902 DEF_OPC(OPC_ICONST_5, level, \
903 PUSH_##level(5, 1); \
906 DEF_OPC(OPC_FCONST_1, level, \
907 PUSH_##level(FLOAT_1_BITS, 1); \
910 DEF_OPC(OPC_FCONST_2, level, \
911 PUSH_##level(FLOAT_2_BITS, 1); \
914 DEF_OPC(OPC_SIPUSH, level, \
915 PUSH_##level(DOUBLE_SIGNED(pc), 3); \
918 DEF_OPC(OPC_BIPUSH, level, \
919 PUSH_##level(SINGLE_SIGNED(pc), 2); \
922 DEF_OPC(OPC_LDC_QUICK, level, \
923 PUSH_##level(RESOLVED_CONSTANT(pc), 2); \
926 DEF_OPC(OPC_LDC_W_QUICK, level, \
927 PUSH_##level(CP_INFO(cp, DOUBLE_INDEX(pc)), 3); \
930 DEF_OPC_3(OPC_ILOAD, \
931 OPC_FLOAD, \
932 OPC_ALOAD, level, \
933 PUSH_##level(lvars[SINGLE_INDEX(pc)], 2); \
936 DEF_OPC(OPC_ALOAD_THIS, level, \
937 ALOAD_THIS(level); \
940 DEF_OPC_2(OPC_ILOAD_0, \
941 OPC_FLOAD_0, level, \
942 PUSH_##level(lvars[0], 1) \
945 DEF_OPC_3(OPC_ILOAD_1, \
946 OPC_FLOAD_1, \
947 OPC_ALOAD_1, level, \
948 PUSH_##level(lvars[1], 1); \
951 DEF_OPC_3(OPC_ILOAD_2, \
952 OPC_FLOAD_2, \
953 OPC_ALOAD_2, level, \
954 PUSH_##level(lvars[2], 1); \
957 DEF_OPC_3(OPC_ILOAD_3, \
958 OPC_FLOAD_3, \
959 OPC_ALOAD_3, level, \
960 PUSH_##level(lvars[3], 1); \
963 DEF_OPC_3(OPC_ISTORE, \
964 OPC_FSTORE, \
965 OPC_ASTORE, level, \
966 POP_##level(lvars[SINGLE_INDEX(pc)], 2); \
969 DEF_OPC_3(OPC_ISTORE_0, \
970 OPC_ASTORE_0, \
971 OPC_FSTORE_0, level, \
972 POP_##level(lvars[0], 1); \
975 DEF_OPC_3(OPC_ISTORE_1, \
976 OPC_ASTORE_1, \
977 OPC_FSTORE_1, level, \
978 POP_##level(lvars[1], 1); \
981 DEF_OPC_3(OPC_ISTORE_2, \
982 OPC_ASTORE_2, \
983 OPC_FSTORE_2, level, \
984 POP_##level(lvars[2], 1); \
987 DEF_OPC_3(OPC_ISTORE_3, \
988 OPC_ASTORE_3, \
989 OPC_FSTORE_3, level, \
990 POP_##level(lvars[3], 1); \
993 DEF_OPC(OPC_IADD, level, \
994 BINARY_OP_##level(+); \
997 DEF_OPC(OPC_ISUB, level, \
998 BINARY_OP_##level(-); \
1001 DEF_OPC(OPC_IMUL, level, \
1002 BINARY_OP_##level(*); \
1005 DEF_OPC(OPC_IDIV, level, \
1006 ZERO_DIVISOR_CHECK_##level; \
1007 BINARY_OP_##level(/); \
1010 DEF_OPC(OPC_IREM, level, \
1011 ZERO_DIVISOR_CHECK_##level; \
1012 BINARY_OP_##level(%); \
1015 DEF_OPC(OPC_IAND, level, \
1016 BINARY_OP_##level(&); \
1019 DEF_OPC(OPC_IOR, level, \
1020 BINARY_OP_##level(|); \
1023 DEF_OPC(OPC_IXOR, level, \
1024 BINARY_OP_##level(^); \
1027 DEF_OPC(OPC_INEG, level, \
1028 UNARY_MINUS_##level; \
1031 DEF_OPC(OPC_ISHL, level, \
1032 SHIFT_OP_##level(int, <<); \
1035 DEF_OPC(OPC_ISHR, level, \
1036 SHIFT_OP_##level(int, >>); \
1039 DEF_OPC(OPC_IUSHR, level, \
1040 SHIFT_OP_##level(unsigned int, >>); \
1043 DEF_OPC_2(OPC_IF_ACMPEQ, \
1044 OPC_IF_ICMPEQ, level, \
1045 IF_ICMP_##level(==); \
1048 DEF_OPC_2(OPC_IF_ACMPNE, \
1049 OPC_IF_ICMPNE, level, \
1050 IF_ICMP_##level(!=); \
1053 DEF_OPC(OPC_IF_ICMPLT, level, \
1054 IF_ICMP_##level(<); \
1057 DEF_OPC(OPC_IF_ICMPGE, level, \
1058 IF_ICMP_##level(>=); \
1061 DEF_OPC(OPC_IF_ICMPGT, level, \
1062 IF_ICMP_##level(>); \
1065 DEF_OPC(OPC_IF_ICMPLE, level, \
1066 IF_ICMP_##level(<=); \
1069 DEF_OPC_2(OPC_IFNE, \
1070 OPC_IFNONNULL, level, \
1071 IF_##level(!=); \
1074 DEF_OPC_2(OPC_IFEQ, \
1075 OPC_IFNULL, level, \
1076 IF_##level(==); \
1079 DEF_OPC(OPC_IFLT, level, \
1080 IF_##level(<); \
1083 DEF_OPC(OPC_IFGE, level, \
1084 IF_##level(>=); \
1087 DEF_OPC(OPC_IFGT, level, \
1088 IF_##level(>); \
1091 DEF_OPC(OPC_IFLE, level, \
1092 IF_##level(<=); \
1095 DEF_OPC(OPC_IINC, level, \
1096 lvars[IINC_LVAR_IDX(pc)] += IINC_DELTA(pc); \
1097 DISPATCH(level, 3); \
1100 DEF_OPC(OPC_POP, level, \
1101 POP1_##level; \
1104 DEF_OPC(OPC_POP2, level, \
1105 ostack -= 2 - level; \
1106 DISPATCH(0, 1); \
1109 DEF_OPC(OPC_DUP, level, \
1110 DUP_##level; \
1113 DEF_OPC_3(OPC_IRETURN, \
1114 OPC_ARETURN, \
1115 OPC_FRETURN, level, \
1116 RETURN_##level; \
1119 DEF_OPC(OPC_RETURN, level, \
1120 goto methodReturn; \
1123 DEF_OPC(OPC_GETSTATIC_QUICK, level, \
1124 PUSH_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1127 DEF_OPC(OPC_PUTSTATIC_QUICK, level, \
1128 POP_##level(RESOLVED_FIELD(pc)->static_value, 3); \
1131 DEF_OPC(OPC_GETFIELD_THIS, level, \
1132 GETFIELD_THIS(level); \
1135 DEF_OPC(OPC_GETFIELD_QUICK, level, \
1136 GETFIELD_QUICK_##level; \
1139 #define ZERO_DIVISOR_CHECK_0 \
1140 ZERO_DIVISOR_CHECK((int)ostack[-1]);
1142 #define ZERO_DIVISOR_CHECK_1 \
1143 ZERO_DIVISOR_CHECK((int)cache.i.v1);
1145 #define ZERO_DIVISOR_CHECK_2 \
1146 ZERO_DIVISOR_CHECK((int)cache.i.v2);
1149 #define PUSH_0(value, ins_len) \
1150 *ostack++ = value; \
1151 DISPATCH(0, ins_len);
1154 #define PUSH_1(value, ins_len) \
1155 cache.i.v2 = value; \
1156 DISPATCH(2, ins_len);
1158 #define PUSH_2(value, ins_len) \
1159 *ostack++ = cache.i.v1; \
1160 cache.i.v1 = cache.i.v2; \
1161 cache.i.v2 = value; \
1162 DISPATCH(2, ins_len);
1164 #define POP_0(dest, ins_len) \
1165 dest = *--ostack; \
1166 DISPATCH(0, ins_len);
1168 #define POP_1(dest, ins_len) \
1169 dest = cache.i.v1; \
1170 DISPATCH(0, ins_len);
1172 #define POP_2(dest, ins_len) \
1173 dest = cache.i.v2; \
1174 DISPATCH(1, ins_len);
1176 #define POP1_0 \
1177 ostack--; \
1178 DISPATCH(0, 1);
1180 #define POP1_1 \
1181 DISPATCH(0, 1);
1183 #define POP1_2 \
1184 DISPATCH(1, 1);
1186 #define DUP_0 \
1187 PUSH_0(ostack[-1], 1);
1189 #define DUP_1 \
1190 PUSH_1(cache.i.v1, 1);
1192 #define DUP_2 \
1193 PUSH_2(cache.i.v2, 1);
1195 #define RETURN_0 \
1196 *lvars++ = *--ostack; \
1197 goto methodReturn;
1199 #define RETURN_1 \
1200 *lvars++ = cache.i.v1; \
1201 goto methodReturn;
1203 #define RETURN_2 \
1204 *lvars++ = cache.i.v2; \
1205 goto methodReturn;
1207 #define GETFIELD_QUICK_0 \
1209 Object *obj = (Object *)*--ostack; \
1210 NULL_POINTER_CHECK(obj); \
1211 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1214 #define GETFIELD_QUICK_1 \
1216 Object *obj = (Object *)cache.i.v1; \
1217 NULL_POINTER_CHECK(obj); \
1218 PUSH_0(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1221 #define GETFIELD_QUICK_2 \
1223 Object *obj = (Object *)cache.i.v2; \
1224 NULL_POINTER_CHECK(obj); \
1225 PUSH_1(INST_DATA(obj)[SINGLE_INDEX(pc)], 3); \
1228 #define UNARY_MINUS_0 \
1230 int v = (int)*--ostack; \
1231 PUSH_0(-v, 1); \
1234 #define UNARY_MINUS_1 \
1235 PUSH_0(-(int)cache.i.v1, 1);
1237 #define UNARY_MINUS_2 \
1238 PUSH_1(-(int)cache.i.v2, 1);
1240 #define BINARY_OP_0(OP) \
1241 ostack -= 2; \
1242 PUSH_0((int)ostack[0] OP (int)ostack[1], 1);
1244 #define BINARY_OP_1(OP) \
1245 PUSH_0((int)*--ostack OP (int)cache.i.v1, 1);
1247 #define BINARY_OP_2(OP) \
1248 PUSH_0((int)cache.i.v1 OP (int)cache.i.v2, 1);
1250 #define SHIFT_OP_0(TYPE, OP) \
1251 ostack -= 2; \
1252 PUSH_0((TYPE)ostack[0] OP (ostack[1] & 0x1f), 1);
1254 #define SHIFT_OP_1(TYPE, OP) \
1255 PUSH_0((TYPE)*--ostack OP (cache.i.v1 & 0x1f), 1);
1257 #define SHIFT_OP_2(TYPE, OP) \
1258 PUSH_0((TYPE)cache.i.v1 OP (cache.i.v2 & 0x1f), 1);
1260 #define IF_ICMP_0(COND) \
1261 ostack -= 2; \
1262 BRANCH((int)ostack[0] COND (int)ostack[1]);
1264 #define IF_ICMP_1(COND) \
1265 BRANCH((int)*--ostack COND (int)cache.i.v1);
1267 #define IF_ICMP_2(COND) \
1268 BRANCH((int)cache.i.v1 COND (int)cache.i.v2);
1270 #define IF_0(COND) \
1271 BRANCH((int)*--ostack COND 0);
1273 #define IF_1(COND) \
1274 BRANCH((int)cache.i.v1 COND 0);
1276 #define IF_2(COND) \
1277 *ostack++ = cache.i.v1; \
1278 BRANCH((int)cache.i.v2 COND 0);
1280 #define ALOAD_THIS(level)
1282 #define GETFIELD_THIS(level) \
1283 PUSH_##level(INST_DATA(this)[pc->operand.i], 4);
1286 MULTI_LEVEL_OPCODES(0);
1289 DEF_OPC_210(OPC_NOP,
1290 DISPATCH(0, 1);
1294 #define PUSH_LONG(value, ins_len) \
1295 *(u8*)ostack = value; \
1296 ostack += 2; \
1297 DISPATCH(0, ins_len);
1299 DEF_OPC_210_2(
1300 OPC_LCONST_0,
1301 OPC_DCONST_0,
1302 PUSH_LONG(0, 1);
1305 DEF_OPC_210(OPC_DCONST_1,
1306 PUSH_LONG(DOUBLE_1_BITS, 1);
1309 DEF_OPC_210(OPC_LCONST_1,
1310 PUSH_LONG(1, 1);
1313 DEF_OPC_210(OPC_LDC2_W,
1314 PUSH_LONG(CP_LONG(cp, DOUBLE_INDEX(pc)), 3);
1317 DEF_OPC_210_2(
1318 OPC_LLOAD,
1319 OPC_DLOAD,
1320 PUSH_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1323 DEF_OPC_210_2(
1324 OPC_LLOAD_0,
1325 OPC_DLOAD_0,
1326 PUSH_LONG(*(u8*)(&lvars[0]), 1);
1329 DEF_OPC_210_2(
1330 OPC_LLOAD_1,
1331 OPC_DLOAD_1,
1332 PUSH_LONG(*(u8*)(&lvars[1]), 1);
1335 DEF_OPC_210_2(
1336 OPC_LLOAD_2,
1337 OPC_DLOAD_2,
1338 PUSH_LONG(*(u8*)(&lvars[2]), 1);
1341 DEF_OPC_210_2(
1342 OPC_LLOAD_3,
1343 OPC_DLOAD_3,
1344 PUSH_LONG(*(u8*)(&lvars[3]), 1);
1348 #define POP_LONG(dest, ins_len) \
1349 ostack -= 2; \
1350 dest = *(u8*)ostack; \
1351 DISPATCH(0, ins_len);
1354 DEF_OPC_012_2(
1355 OPC_LSTORE,
1356 OPC_DSTORE,
1357 POP_LONG(*(u8*)(&lvars[SINGLE_INDEX(pc)]), 2);
1360 DEF_OPC_012_2(
1361 OPC_LSTORE_0,
1362 OPC_DSTORE_0,
1363 POP_LONG(*(u8*)(&lvars[0]), 1);
1366 DEF_OPC_012_2(
1367 OPC_LSTORE_1,
1368 OPC_DSTORE_1,
1369 POP_LONG(*(u8*)(&lvars[1]), 1);
1372 DEF_OPC_012_2(
1373 OPC_LSTORE_2,
1374 OPC_DSTORE_2,
1375 POP_LONG(*(u8*)(&lvars[2]), 1);
1378 DEF_OPC_012_2(
1379 OPC_LSTORE_3,
1380 OPC_DSTORE_3,
1381 POP_LONG(*(u8*)(&lvars[3]), 1);
1385 #define ARRAY_LOAD_IDX *--ostack
1386 #define ARRAY_LOAD_ARY *--ostack
1389 #define ARRAY_LOAD(TYPE) \
1391 int idx = ARRAY_LOAD_IDX; \
1392 Object *array = (Object *)ARRAY_LOAD_ARY; \
1394 NULL_POINTER_CHECK(array); \
1395 ARRAY_BOUNDS_CHECK(array, idx); \
1396 PUSH_0(((TYPE *)ARRAY_DATA(array))[idx], 1); \
1399 DEF_OPC_012_2(
1400 OPC_IALOAD,
1401 OPC_FALOAD,
1402 ARRAY_LOAD(int)
1405 DEF_OPC_012(OPC_AALOAD,
1406 ARRAY_LOAD(uintptr_t)
1409 DEF_OPC_012(OPC_BALOAD,
1410 ARRAY_LOAD(signed char)
1413 DEF_OPC_012(OPC_CALOAD,
1414 ARRAY_LOAD(unsigned short)
1417 DEF_OPC_012(OPC_SALOAD,
1418 ARRAY_LOAD(short)
1421 DEF_OPC_012(OPC_LALOAD, {
1422 int idx = ARRAY_LOAD_IDX;
1423 Object *array = (Object *)ARRAY_LOAD_ARY;
1425 NULL_POINTER_CHECK(array);
1426 ARRAY_BOUNDS_CHECK(array, idx);
1427 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
1430 DEF_OPC_012(OPC_DALOAD, {
1431 int idx = ARRAY_LOAD_IDX;
1432 Object *array = (Object *)ARRAY_LOAD_ARY;
1434 NULL_POINTER_CHECK(array);
1435 ARRAY_BOUNDS_CHECK(array, idx);
1436 PUSH_LONG(((u8 *)ARRAY_DATA(array))[idx], 1);
1440 #define ARRAY_STORE_VAL *--ostack
1441 #define ARRAY_STORE_IDX *--ostack
1444 #define ARRAY_STORE(TYPE) \
1446 int val = ARRAY_STORE_VAL; \
1447 int idx = ARRAY_STORE_IDX; \
1448 Object *array = (Object *)*--ostack; \
1450 NULL_POINTER_CHECK(array); \
1451 ARRAY_BOUNDS_CHECK(array, idx); \
1452 ((TYPE *)ARRAY_DATA(array))[idx] = val; \
1453 DISPATCH(0, 1); \
1456 DEF_OPC_012_2(
1457 OPC_IASTORE,
1458 OPC_FASTORE,
1459 ARRAY_STORE(int)
1462 DEF_OPC_012(OPC_BASTORE,
1463 ARRAY_STORE(char);
1466 DEF_OPC_012_2(
1467 OPC_CASTORE,
1468 OPC_SASTORE,
1469 ARRAY_STORE(short);
1472 DEF_OPC_012(OPC_AASTORE, {
1473 Object *obj = (Object*)ARRAY_STORE_VAL;
1474 int idx = ARRAY_STORE_IDX;
1475 Object *array = (Object *)*--ostack;
1477 NULL_POINTER_CHECK(array);
1478 ARRAY_BOUNDS_CHECK(array, idx);
1480 if((obj != NULL) && !arrayStoreCheck(array->class, obj->class))
1481 THROW_EXCEPTION("java/lang/ArrayStoreException", NULL);
1483 ((Object**)ARRAY_DATA(array))[idx] = obj;
1484 DISPATCH(0, 1);
1488 DEF_OPC_012_2(
1489 OPC_LASTORE,
1490 OPC_DASTORE, {
1491 int idx = ostack[-3];
1492 Object *array = (Object *)ostack[-4];
1494 ostack -= 4;
1495 NULL_POINTER_CHECK(array);
1496 ARRAY_BOUNDS_CHECK(array, idx);
1498 ((u8 *)ARRAY_DATA(array))[idx] = *(u8*)&ostack[2];
1499 DISPATCH(0, 1);
1504 DEF_OPC_012(OPC_DUP_X1, {
1505 uintptr_t word1 = ostack[-1];
1506 uintptr_t word2 = ostack[-2];
1507 ostack[-2] = word1;
1508 ostack[-1] = word2;
1509 *ostack++ = word1;
1510 DISPATCH(0, 1);
1513 DEF_OPC_012(OPC_DUP_X2, {
1514 uintptr_t word1 = ostack[-1];
1515 uintptr_t word2 = ostack[-2];
1516 uintptr_t word3 = ostack[-3];
1517 ostack[-3] = word1;
1518 ostack[-2] = word3;
1519 ostack[-1] = word2;
1520 *ostack++ = word1;
1521 DISPATCH(0, 1);
1524 DEF_OPC_012(OPC_DUP2, {
1525 ostack[0] = ostack[-2];
1526 ostack[1] = ostack[-1];
1527 ostack += 2;
1528 DISPATCH(0, 1);
1531 DEF_OPC_012(OPC_DUP2_X1, {
1532 uintptr_t word1 = ostack[-1];
1533 uintptr_t word2 = ostack[-2];
1534 uintptr_t word3 = ostack[-3];
1535 ostack[-3] = word2;
1536 ostack[-2] = word1;
1537 ostack[-1] = word3;
1538 ostack[0] = word2;
1539 ostack[1] = word1;
1540 ostack += 2;
1541 DISPATCH(0, 1);
1544 DEF_OPC_012(OPC_DUP2_X2, {
1545 uintptr_t word1 = ostack[-1];
1546 uintptr_t word2 = ostack[-2];
1547 uintptr_t word3 = ostack[-3];
1548 uintptr_t word4 = ostack[-4];
1549 ostack[-4] = word2;
1550 ostack[-3] = word1;
1551 ostack[-2] = word4;
1552 ostack[-1] = word3;
1553 ostack[0] = word2;
1554 ostack[1] = word1;
1555 ostack += 2;
1556 DISPATCH(0, 1);
1559 DEF_OPC_012(OPC_SWAP, {
1560 uintptr_t word1 = ostack[-1];
1561 ostack[-1] = ostack[-2];
1562 ostack[-2] = word1;
1563 DISPATCH(0, 1)
1567 #define BINARY_OP_fp(TYPE, OP) \
1568 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] = \
1569 *(TYPE *)&ostack[-sizeof(TYPE)/4 * 2] OP\
1570 *(TYPE *)&ostack[-sizeof(TYPE)/4]; \
1571 ostack -= sizeof(TYPE)/4; \
1572 DISPATCH(0, 1);
1574 DEF_OPC_210(OPC_FADD,
1575 BINARY_OP_fp(float, +);
1578 DEF_OPC_210(OPC_DADD,
1579 BINARY_OP_fp(double, +);
1582 DEF_OPC_210(OPC_FSUB,
1583 BINARY_OP_fp(float, -);
1586 DEF_OPC_210(OPC_DSUB,
1587 BINARY_OP_fp(double, -);
1590 DEF_OPC_210(OPC_FMUL,
1591 BINARY_OP_fp(float, *);
1594 DEF_OPC_210(OPC_DMUL,
1595 BINARY_OP_fp(double, *);
1598 DEF_OPC_210(OPC_FDIV,
1599 BINARY_OP_fp(float, /);
1602 DEF_OPC_210(OPC_DDIV,
1603 BINARY_OP_fp(double, /);
1607 #define BINARY_OP_long(OP) \
1608 BINARY_OP_fp(long long, OP)
1610 #define ZERO_DIVISOR_CHECK_long \
1611 ZERO_DIVISOR_CHECK(*(u8*)&ostack[-2]);
1614 DEF_OPC_012(OPC_LADD,
1615 BINARY_OP_long(+);
1618 DEF_OPC_012(OPC_LSUB,
1619 BINARY_OP_long(-);
1622 DEF_OPC_012(OPC_LMUL,
1623 BINARY_OP_long(*);
1626 DEF_OPC_012(OPC_LDIV,
1627 ZERO_DIVISOR_CHECK_long;
1628 BINARY_OP_long(/);
1631 DEF_OPC_012(OPC_LREM,
1632 ZERO_DIVISOR_CHECK_long;
1633 BINARY_OP_long(%);
1636 DEF_OPC_012(OPC_LAND,
1637 BINARY_OP_long(&);
1640 DEF_OPC_012(OPC_LOR,
1641 BINARY_OP_long(|);
1644 DEF_OPC_012(OPC_LXOR,
1645 BINARY_OP_long(^);
1649 #define SHIFT_OP_long(TYPE, OP) \
1651 int shift = *--ostack & 0x3f; \
1652 *(TYPE*)&ostack[-2] = \
1653 *(TYPE*)&ostack[-2] OP shift; \
1654 DISPATCH(0, 1); \
1658 DEF_OPC_012(OPC_LSHL,
1659 SHIFT_OP_long(long long, <<);
1662 DEF_OPC_012(OPC_LSHR,
1663 SHIFT_OP_long(long long, >>);
1666 DEF_OPC_012(OPC_LUSHR,
1667 SHIFT_OP_long(unsigned long long, >>);
1670 DEF_OPC_210(OPC_FREM, {
1671 float v2 = *(float *)&ostack[-1];
1672 float v1 = *(float *)&ostack[-2];
1674 *(float *)&ostack[-2] = fmod(v1, v2);
1675 ostack -= 1;
1676 DISPATCH(0, 1);
1679 DEF_OPC_210(OPC_DREM, {
1680 double v2 = *(double *)&ostack[-2];
1681 double v1 = *(double *)&ostack[-4];
1683 *(double *)&ostack[-4] = fmod(v1, v2);
1684 ostack -= 2;
1685 DISPATCH(0, 1);
1688 #define UNARY_MINUS(TYPE) \
1689 *(TYPE*)&ostack[-sizeof(TYPE)/4] = \
1690 -*(TYPE*)&ostack[-sizeof(TYPE)/4]; \
1691 DISPATCH(0, 1);
1693 DEF_OPC_210(OPC_LNEG,
1694 UNARY_MINUS(long long);
1697 DEF_OPC_210(OPC_FNEG,
1698 UNARY_MINUS(float);
1701 DEF_OPC_210(OPC_DNEG,
1702 UNARY_MINUS(double);
1705 DEF_OPC_210(OPC_I2L, {
1706 ostack -= 1;
1707 PUSH_LONG((int)*ostack, 1);
1710 DEF_OPC_012(OPC_L2I, {
1711 long long l;
1712 #ifdef USE_CACHE
1713 l = cache.l;
1714 #else
1715 ostack -= 2;
1716 l = *(long long*)ostack;
1717 #endif
1718 PUSH_0((int)l, 1);
1721 #define OPC_int2fp(DEST_TYPE) \
1722 ostack -= 1; \
1723 *(DEST_TYPE *)ostack = \
1724 (DEST_TYPE)(int)*ostack; \
1725 ostack += sizeof(DEST_TYPE)/4; \
1726 DISPATCH(0, 1);
1728 DEF_OPC_210(OPC_I2F,
1729 OPC_int2fp(float);
1732 DEF_OPC_210(OPC_I2D,
1733 OPC_int2fp(double);
1736 #define OPC_X2Y(SRC_TYPE, DEST_TYPE) \
1738 SRC_TYPE v; \
1739 ostack -= sizeof(SRC_TYPE)/4; \
1740 v = *(SRC_TYPE *)ostack; \
1741 *(DEST_TYPE *)ostack = (DEST_TYPE)v; \
1742 ostack += sizeof(DEST_TYPE)/4; \
1743 DISPATCH(0, 1); \
1746 DEF_OPC_210(OPC_L2F,
1747 OPC_X2Y(long long, float);
1750 DEF_OPC_210(OPC_L2D,
1751 OPC_X2Y(long long, double);
1754 DEF_OPC_210(OPC_F2D,
1755 OPC_X2Y(float, double);
1758 DEF_OPC_210(OPC_D2F,
1759 OPC_X2Y(double, float);
1762 #define OPC_fp2int(SRC_TYPE) \
1764 int res; \
1765 SRC_TYPE value; \
1766 ostack -= sizeof(SRC_TYPE)/4; \
1767 value = *(SRC_TYPE *)ostack; \
1769 if(value >= (SRC_TYPE)INT_MAX) \
1770 res = INT_MAX; \
1771 else if(value <= (SRC_TYPE)INT_MIN) \
1772 res = INT_MIN; \
1773 else if(value != value) \
1774 res = 0; \
1775 else \
1776 res = (int) value; \
1778 PUSH_0(res, 1); \
1781 DEF_OPC_210(OPC_F2I,
1782 OPC_fp2int(float);
1785 DEF_OPC_210(OPC_D2I,
1786 OPC_fp2int(double);
1789 #define OPC_fp2long(SRC_TYPE) \
1791 long long res; \
1792 SRC_TYPE value; \
1793 ostack -= sizeof(SRC_TYPE)/4; \
1794 value = *(SRC_TYPE *)ostack; \
1796 if(value >= (SRC_TYPE)LLONG_MAX) \
1797 res = LLONG_MAX; \
1798 else if(value <= (SRC_TYPE)LLONG_MIN) \
1799 res = LLONG_MIN; \
1800 else if(value != value) \
1801 res = 0; \
1802 else \
1803 res = (long long) value; \
1805 PUSH_LONG(res, 1); \
1808 DEF_OPC_210(OPC_F2L,
1809 OPC_fp2long(float);
1812 DEF_OPC_210(OPC_D2L,
1813 OPC_fp2long(double);
1816 DEF_OPC_210(OPC_I2B, {
1817 signed char v = *--ostack & 0xff;
1818 PUSH_0(v, 1);
1821 DEF_OPC_210(OPC_I2C, {
1822 int v = *--ostack & 0xffff;
1823 PUSH_0(v, 1);
1826 DEF_OPC_210(OPC_I2S, {
1827 signed short v = *--ostack & 0xffff;
1828 PUSH_0((int) v, 1);
1832 DEF_OPC_012(OPC_LCMP, {
1833 long long v2 = *(long long*)&ostack[-2];
1834 long long v1 = *(long long*)&ostack[-4];
1835 ostack[-4] = (v1 == v2) ? 0 : ((v1 < v2) ? -1 : 1);
1836 ostack -= 3;
1837 DISPATCH(0, 1);
1841 #define FCMP(TYPE, isNan) \
1842 ({ \
1843 int res; \
1844 TYPE v1, v2; \
1845 ostack -= sizeof(TYPE)/4; v2 = *(TYPE *)ostack; \
1846 ostack -= sizeof(TYPE)/4; v1 = *(TYPE *)ostack; \
1847 if(v1 == v2) \
1848 res = 0; \
1849 else if(v1 < v2) \
1850 res = -1; \
1851 else if(v1 > v2) \
1852 res = 1; \
1853 else \
1854 res = isNan; \
1855 PUSH_0(res, 1); \
1858 DEF_OPC_210(OPC_DCMPG,
1859 FCMP(double, 1);
1862 DEF_OPC_210(OPC_DCMPL,
1863 FCMP(double, -1);
1866 DEF_OPC_210(OPC_FCMPG,
1867 FCMP(float, 1);
1870 DEF_OPC_210(OPC_FCMPL,
1871 FCMP(float, -1);
1875 DEF_OPC_210_2(
1876 OPC_GOTO,
1877 OPC_GOTO_W,
1878 BRANCH(TRUE);
1881 DEF_OPC_210_2(
1882 OPC_JSR,
1883 OPC_JSR_W,
1884 *ostack++ = (uintptr_t)pc;
1885 BRANCH(TRUE);
1888 DEF_OPC_210(OPC_RET,
1889 pc = (CodePntr)lvars[SINGLE_INDEX(pc)];
1890 DISPATCH_RET(3);
1893 DEF_OPC_012_2(
1894 OPC_LRETURN,
1895 OPC_DRETURN,
1896 ostack -= 2;
1897 *(u8*)lvars = *(u8*)ostack;
1898 lvars += 2;
1899 goto methodReturn;
1902 DEF_OPC_210(OPC_ARRAYLENGTH, {
1903 Object *array = (Object *)*--ostack;
1905 NULL_POINTER_CHECK(array);
1906 PUSH_0(ARRAY_LEN(array), 1);
1909 DEF_OPC_210(OPC_ATHROW, {
1910 Object *obj = (Object *)ostack[-1];
1911 frame->last_pc = pc;
1912 NULL_POINTER_CHECK(obj);
1914 ee->exception = obj;
1915 goto throwException;
1918 DEF_OPC_210(OPC_NEWARRAY, {
1919 int type = ARRAY_TYPE(pc);
1920 int count = *--ostack;
1921 Object *obj;
1923 frame->last_pc = pc;
1924 if((obj = allocTypeArray(type, count)) == NULL)
1925 goto throwException;
1927 PUSH_0((uintptr_t)obj, 2);
1930 DEF_OPC_210(OPC_MONITORENTER, {
1931 Object *obj = (Object *)*--ostack;
1932 NULL_POINTER_CHECK(obj);
1933 objectLock(obj);
1934 DISPATCH(0, 1);
1937 DEF_OPC_210(OPC_MONITOREXIT, {
1938 Object *obj = (Object *)*--ostack;
1939 NULL_POINTER_CHECK(obj);
1940 objectUnlock(obj);
1941 DISPATCH(0, 1);
1944 DEF_OPC_RW(OPC_LDC, ({
1945 int idx, cache;
1946 Operand operand;
1948 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_LDC, idx, cache);
1950 frame->last_pc = pc;
1952 operand.u = resolveSingleConstant(mb->class, idx);
1954 if(exceptionOccured0(ee))
1955 goto throwException;
1957 if(CP_TYPE(cp, idx) == CONSTANT_ResolvedClass ||
1958 CP_TYPE(cp, idx) == CONSTANT_ResolvedString) {
1959 operand.i = idx;
1960 OPCODE_REWRITE(OPC_LDC_W_QUICK, cache, operand);
1961 } else
1962 OPCODE_REWRITE(OPC_LDC_QUICK, cache, operand);
1964 REDISPATCH
1965 });)
1967 DEF_OPC_210(OPC_TABLESWITCH, {
1968 SwitchTable *table = (SwitchTable*)pc->operand.pntr;
1969 int index = *--ostack;
1971 if(index < table->low || index > table->high)
1972 pc = table->deflt;
1973 else
1974 pc = table->entries[index - table->low];
1976 DISPATCH_SWITCH
1979 DEF_OPC_210(OPC_LOOKUPSWITCH, {
1980 LookupTable *table = (LookupTable*)pc->operand.pntr;
1981 int key = *--ostack;
1982 int i;
1984 for(i = 0; (i < table->num_entries) && (key != table->entries[i].key); i++);
1986 pc = (i == table->num_entries ? table->deflt
1987 : table->entries[i].handler);
1988 DISPATCH_SWITCH
1991 DEF_OPC_RW(OPC_GETSTATIC, ({
1992 int idx, cache;
1993 FieldBlock *fb;
1994 Operand operand;
1996 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETSTATIC, idx, cache);
1998 frame->last_pc = pc;
1999 fb = resolveField(mb->class, idx);
2001 if(exceptionOccured0(ee))
2002 goto throwException;
2004 operand.pntr = fb;
2005 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2006 OPC_GETSTATIC2_QUICK : OPC_GETSTATIC_QUICK), cache, operand);
2008 REDISPATCH
2009 });)
2011 DEF_OPC_RW(OPC_PUTSTATIC, ({
2012 int idx, cache;
2013 FieldBlock *fb;
2014 Operand operand;
2016 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTSTATIC, idx, cache);
2018 frame->last_pc = pc;
2019 fb = resolveField(mb->class, idx);
2021 if(exceptionOccured0(ee))
2022 goto throwException;
2024 operand.pntr = fb;
2025 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2026 OPC_PUTSTATIC2_QUICK : OPC_PUTSTATIC_QUICK), cache, operand);
2028 REDISPATCH
2029 });)
2031 DEF_OPC_RW(OPC_GETFIELD, ({
2032 int idx, cache;
2033 FieldBlock *fb;
2034 Operand operand;
2036 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETFIELD, idx, cache);
2038 frame->last_pc = pc;
2039 fb = resolveField(mb->class, idx);
2041 if(exceptionOccured0(ee))
2042 goto throwException;
2044 operand.i = fb->offset;
2045 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2046 OPC_GETFIELD2_QUICK : OPC_GETFIELD_QUICK), cache, operand);
2048 REDISPATCH
2049 });)
2051 DEF_OPC_RW(OPC_PUTFIELD, ({
2052 int idx, cache;
2053 FieldBlock *fb;
2054 Operand operand;
2056 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_PUTFIELD, idx, cache);
2058 frame->last_pc = pc;
2059 fb = resolveField(mb->class, idx);
2061 if(exceptionOccured0(ee))
2062 goto throwException;
2064 operand.i = fb->offset;
2065 OPCODE_REWRITE(((*fb->type == 'J') || (*fb->type == 'D') ?
2066 OPC_PUTFIELD2_QUICK : OPC_PUTFIELD_QUICK), cache, operand);
2068 REDISPATCH
2069 });)
2071 DEF_OPC_RW(OPC_INVOKEVIRTUAL, ({
2072 int idx, cache;
2073 Operand operand;
2075 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEVIRTUAL, idx, cache);
2077 frame->last_pc = pc;
2078 new_mb = resolveMethod(mb->class, idx);
2080 if(exceptionOccured0(ee))
2081 goto throwException;
2083 operand.uu.u1 = new_mb->args_count;
2084 operand.uu.u2 = new_mb->method_table_index;
2085 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2086 REDISPATCH
2087 });)
2089 DEF_OPC_RW(OPC_INVOKESPECIAL, ({
2090 int idx, cache;
2091 Operand operand;
2093 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESPECIAL, idx, cache);
2095 frame->last_pc = pc;
2096 new_mb = resolveMethod(mb->class, idx);
2098 if(exceptionOccured0(ee))
2099 goto throwException;
2101 /* Check if invoking a super method... */
2102 if((CLASS_CB(mb->class)->access_flags & ACC_SUPER) &&
2103 ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) {
2105 operand.i = new_mb->method_table_index;
2106 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand);
2107 } else {
2108 operand.pntr = new_mb;
2109 OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand);
2112 REDISPATCH
2113 });)
2115 DEF_OPC_RW(OPC_INVOKESTATIC, ({
2116 int idx, cache;
2117 Operand operand;
2119 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKESTATIC, idx, cache);
2121 frame->last_pc = pc;
2122 new_mb = resolveMethod(mb->class, idx);
2124 if(exceptionOccured0(ee))
2125 goto throwException;
2127 operand.pntr = new_mb;
2128 OPCODE_REWRITE(OPC_INVOKESTATIC_QUICK, cache, operand);
2129 REDISPATCH
2130 });)
2132 DEF_OPC_RW(OPC_INVOKEINTERFACE, ({
2133 int idx, cache;
2134 Operand operand;
2136 WITH_OPCODE_CHANGE_CP_DINDEX(OPC_INVOKEINTERFACE, idx, cache);
2138 frame->last_pc = pc;
2139 new_mb = resolveInterfaceMethod(mb->class, idx);
2141 if(exceptionOccured0(ee))
2142 goto throwException;
2144 if(CLASS_CB(new_mb->class)->access_flags & ACC_INTERFACE) {
2145 operand.uu.u1 = idx;
2146 operand.uu.u2 = 0;
2147 OPCODE_REWRITE(OPC_INVOKEINTERFACE_QUICK, cache, operand);
2148 } else {
2149 operand.uu.u1 = new_mb->args_count;
2150 operand.uu.u2 = new_mb->method_table_index;
2151 OPCODE_REWRITE(OPC_INVOKEVIRTUAL_QUICK, cache, operand);
2154 REDISPATCH
2155 });)
2157 DEF_OPC_RW(OPC_MULTIANEWARRAY, ({
2158 int idx = pc->operand.uui.u1;
2159 int cache = pc->operand.uui.i;
2161 frame->last_pc = pc;
2162 resolveClass(mb->class, idx, FALSE);
2164 if(exceptionOccured0(ee))
2165 goto throwException;
2167 OPCODE_REWRITE(OPC_MULTIANEWARRAY_QUICK, cache, pc->operand);
2168 REDISPATCH
2169 });)
2171 DEF_OPC_RW_4(OPC_NEW, OPC_ANEWARRAY, OPC_CHECKCAST, OPC_INSTANCEOF, ({
2172 int idx = pc->operand.uui.u1;
2173 int opcode = pc->operand.uui.u2;
2174 int cache = pc->operand.uui.i;
2175 Class *class;
2177 frame->last_pc = pc;
2178 class = resolveClass(mb->class, idx, opcode == OPC_NEW);
2180 if(exceptionOccured0(ee))
2181 goto throwException;
2183 if(opcode == OPC_NEW) {
2184 ClassBlock *cb = CLASS_CB(class);
2185 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
2186 signalException("java/lang/InstantiationError", cb->name);
2187 goto throwException;
2191 OPCODE_REWRITE((opcode + OPC_NEW_QUICK-OPC_NEW), cache, pc->operand);
2192 REDISPATCH
2193 });)
2195 DEF_OPC_210(OPC_GETSTATIC2_QUICK, {
2196 FieldBlock *fb = RESOLVED_FIELD(pc);
2197 PUSH_LONG(*(u8*)&fb->static_value, 3);
2200 DEF_OPC_012(OPC_PUTSTATIC2_QUICK, {
2201 FieldBlock *fb = RESOLVED_FIELD(pc);
2202 POP_LONG(*(u8*)&fb->static_value, 3);
2205 DEF_OPC_210(OPC_GETFIELD2_QUICK, {
2206 Object *obj = (Object *)*--ostack;
2207 NULL_POINTER_CHECK(obj);
2209 PUSH_LONG(*(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])), 3);
2213 DEF_OPC_012(OPC_PUTFIELD2_QUICK, {
2214 Object *obj = (Object *)ostack[-3];
2216 ostack -= 3;
2217 NULL_POINTER_CHECK(obj);
2218 *(u8*)(&(INST_DATA(obj)[SINGLE_INDEX(pc)])) = *(u8*)&ostack[1];
2219 DISPATCH(0, 3);
2222 DEF_OPC_012(OPC_PUTFIELD_QUICK, {
2223 Object *obj = (Object *)ostack[-2];
2225 ostack -= 2;
2226 NULL_POINTER_CHECK(obj);
2227 INST_DATA(obj)[SINGLE_INDEX(pc)] = ostack[1];
2228 DISPATCH(0, 3);
2232 DEF_OPC_210(OPC_INVOKESUPER_QUICK, {
2233 new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)];
2234 arg1 = ostack - (new_mb->args_count);
2235 NULL_POINTER_CHECK(*arg1);
2236 goto invokeMethod;
2239 DEF_OPC_210(OPC_INVOKENONVIRTUAL_QUICK, {
2240 new_mb = RESOLVED_METHOD(pc);
2241 arg1 = ostack - (new_mb->args_count);
2242 NULL_POINTER_CHECK(*arg1);
2243 goto invokeMethod;
2246 DEF_OPC_210(OPC_INVOKESTATIC_QUICK, {
2247 new_mb = RESOLVED_METHOD(pc);
2248 arg1 = ostack - new_mb->args_count;
2249 goto invokeMethod;
2252 DEF_OPC_210(OPC_INVOKEINTERFACE_QUICK, {
2253 int mtbl_idx;
2254 ClassBlock *cb;
2255 int cache = INV_INTF_CACHE(pc);
2257 new_mb = (MethodBlock *)CP_INFO(cp, INV_INTF_IDX(pc));
2258 arg1 = ostack - new_mb->args_count;
2260 NULL_POINTER_CHECK(*arg1);
2262 cb = CLASS_CB(new_class = (*(Object **)arg1)->class);
2264 if((cache >= cb->imethod_table_size) ||
2265 (new_mb->class != cb->imethod_table[cache].interface)) {
2266 for(cache = 0; (cache < cb->imethod_table_size) &&
2267 (new_mb->class != cb->imethod_table[cache].interface); cache++);
2269 if(cache == cb->imethod_table_size)
2270 THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
2271 "unimplemented interface");
2273 INV_INTF_CACHE(pc) = cache;
2276 mtbl_idx = cb->imethod_table[cache].offsets[new_mb->method_table_index];
2277 new_mb = cb->method_table[mtbl_idx];
2279 goto invokeMethod;
2282 DEF_OPC_210(OPC_NEW_QUICK, {
2283 Class *class = RESOLVED_CLASS(pc);
2284 Object *obj;
2286 frame->last_pc = pc;
2287 if((obj = allocObject(class)) == NULL)
2288 goto throwException;
2290 PUSH_0((uintptr_t)obj, 3);
2293 DEF_OPC_210(OPC_ANEWARRAY_QUICK, {
2294 Class *class = RESOLVED_CLASS(pc);
2295 char *name = CLASS_CB(class)->name;
2296 int count = *--ostack;
2297 Class *array_class;
2298 char *ac_name;
2299 Object *obj;
2301 frame->last_pc = pc;
2303 if(count < 0) {
2304 signalException("java/lang/NegativeArraySizeException", NULL);
2305 goto throwException;
2308 ac_name = sysMalloc(strlen(name) + 4);
2310 if(name[0] == '[')
2311 strcat(strcpy(ac_name, "["), name);
2312 else
2313 strcat(strcat(strcpy(ac_name, "[L"), name), ";");
2315 array_class = findArrayClassFromClass(ac_name, mb->class);
2316 free(ac_name);
2318 if(exceptionOccured0(ee))
2319 goto throwException;
2321 if((obj = allocArray(array_class, count, sizeof(Object*))) == NULL)
2322 goto throwException;
2324 PUSH_0((uintptr_t)obj, 3);
2327 DEF_OPC_210(OPC_CHECKCAST_QUICK, {
2328 Class *class = RESOLVED_CLASS(pc);
2329 Object *obj = (Object*)ostack[-1];
2331 if((obj != NULL) && !isInstanceOf(class, obj->class))
2332 THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj->class)->name);
2334 DISPATCH(0, 3);
2337 DEF_OPC_210(OPC_INSTANCEOF_QUICK, {
2338 Class *class = RESOLVED_CLASS(pc);
2339 Object *obj = (Object*)ostack[-1];
2341 if(obj != NULL)
2342 ostack[-1] = isInstanceOf(class, obj->class);
2344 DISPATCH(0, 3);
2347 DEF_OPC_210(OPC_MULTIANEWARRAY_QUICK, ({
2348 Class *class = RESOLVED_CLASS(pc);
2349 int i, dim = MULTI_ARRAY_DIM(pc);
2350 Object *obj;
2352 ostack -= dim;
2353 frame->last_pc = pc;
2355 for(i = 0; i < dim; i++)
2356 if((intptr_t)ostack[i] < 0) {
2357 signalException("java/lang/NegativeArraySizeException", NULL);
2358 goto throwException;
2361 if((obj = allocMultiArray(class, dim, (intptr_t *)ostack)) == NULL)
2362 goto throwException;
2364 PUSH_0((uintptr_t)obj, 4);
2365 });)
2367 /* Special bytecode which forms the body of an abstract method.
2368 If it is invoked it'll throw an abstract method exception. */
2370 DEF_OPC_210(OPC_ABSTRACT_METHOD_ERROR, {
2371 /* As the method has been invoked, a frame will exist for
2372 the abstract method itself. Pop this to get the correct
2373 exception stack trace. */
2374 ee->last_frame = frame->prev;
2376 /* Throw the exception */
2377 signalException("java/lang/AbstractMethodError", mb->name);
2378 goto throwException;
2383 DEF_OPC_210(OPC_INVOKEVIRTUAL_QUICK, {
2384 arg1 = ostack - INV_QUICK_ARGS(pc);
2385 NULL_POINTER_CHECK(*arg1);
2387 new_class = (*(Object **)arg1)->class;
2388 new_mb = CLASS_CB(new_class)->method_table[INV_QUICK_IDX(pc)];
2390 goto invokeMethod;
2393 invokeMethod:
2395 #ifdef JEM
2396 #else
2397 /* Create new frame first. This is also created for natives
2398 so that they appear correctly in the stack trace */
2400 Frame *new_frame = (Frame *)(arg1 + new_mb->max_locals);
2401 Object *sync_ob = NULL;
2403 frame->last_pc = pc;
2404 ostack = (uintptr_t *)(new_frame+1);
2406 if((char*)(ostack + new_mb->max_stack) > ee->stack_end) {
2407 if(ee->overflow++) {
2408 /* Overflow when we're already throwing stack overflow.
2409 Stack extension should be enough to throw exception,
2410 so something's seriously gone wrong - abort the VM! */
2411 jam_printf("Fatal stack overflow! Aborting VM.\n");
2412 exitVM(1);
2414 ee->stack_end += STACK_RED_ZONE_SIZE;
2415 THROW_EXCEPTION("java/lang/StackOverflowError", NULL);
2418 new_frame->mb = new_mb;
2419 new_frame->lvars = arg1;
2420 new_frame->ostack = ostack;
2421 new_frame->prev = frame;
2423 ee->last_frame = new_frame;
2425 if(new_mb->access_flags & ACC_SYNCHRONIZED) {
2426 sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1;
2427 objectLock(sync_ob);
2430 if(new_mb->access_flags & ACC_NATIVE) {
2431 ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))
2432 new_mb->native_invoker)(new_mb->class, new_mb, arg1);
2434 if(sync_ob)
2435 objectUnlock(sync_ob);
2437 ee->last_frame = frame;
2439 if(exceptionOccured0(ee))
2440 goto throwException;
2441 DISPATCH(0, *pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
2442 } else {
2443 PREPARE_MB(new_mb);
2445 frame = new_frame;
2446 mb = new_mb;
2447 lvars = new_frame->lvars;
2448 this = (Object*)lvars[0];
2449 pc = (CodePntr)mb->code;
2450 cp = &(CLASS_CB(mb->class)->constant_pool);
2452 DISPATCH_FIRST
2453 #endif
2456 methodReturn:
2457 #ifdef JEM
2458 #else
2459 /* Set interpreter state to previous frame */
2461 frame = frame->prev;
2463 if(frame->mb == NULL) {
2464 /* The previous frame is a dummy frame - this indicates
2465 top of this Java invocation. */
2466 return ostack;
2469 if(mb->access_flags & ACC_SYNCHRONIZED) {
2470 Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this;
2471 objectUnlock(sync_ob);
2474 mb = frame->mb;
2475 ostack = lvars;
2476 lvars = frame->lvars;
2477 this = (Object*)lvars[0];
2478 pc = frame->last_pc;
2479 cp = &(CLASS_CB(mb->class)->constant_pool);
2481 /* Pop frame */
2482 ee->last_frame = frame;
2484 DISPATCH_METHOD_RET(*pc == OPC_INVOKEINTERFACE_QUICK ? 5 : 3);
2485 #endif
2488 throwException:
2490 Object *excep = ee->exception;
2491 ee->exception = NULL;
2493 pc = findCatchBlock(excep->class);
2495 /* If we didn't find a handler, restore exception and
2496 return to previous invocation */
2498 if(pc == NULL) {
2499 ee->exception = excep;
2500 return NULL;
2503 /* If we're handling a stack overflow, reduce the stack
2504 back past the red zone to enable handling of further
2505 overflows */
2507 if(ee->overflow) {
2508 ee->overflow = FALSE;
2509 ee->stack_end -= STACK_RED_ZONE_SIZE;
2512 /* Setup intepreter to run the found catch block */
2514 frame = ee->last_frame;
2515 mb = frame->mb;
2516 ostack = frame->ostack;
2517 lvars = frame->lvars;
2518 this = (Object*)lvars[0];
2519 cp = &(CLASS_CB(mb->class)->constant_pool);
2521 *ostack++ = (uintptr_t)excep;
2523 /* Dispatch to the first bytecode */
2525 DISPATCH_FIRST
2527 #endif
2530 #ifndef executeJava
2531 void initialiseInterpreter(InitArgs *args) {
2532 initialiseDirect(args);
2534 #endif
2536 #endif //JEM