Fix LDC, LDC_W, and INSTANCEOF opcodes, more debugging
[jamvm-avr32-jem.git] / src / execute.c
blob345cbc90becc8bc12c3b94f099ea3bd60a26bcfe
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 #include <stdio.h>
23 #include <string.h>
24 #include "jam.h"
25 #include "sig.h"
26 #include "frame.h"
27 #include "lock.h"
28 #include "arch/avr32_jem.h"
30 #define VA_DOUBLE(args, sp) *(u8*)sp = va_arg(args, u8); sp+=2
32 #define VA_SINGLE(args, sp) \
33 if(*sig == 'L' || *sig == '[') \
34 *sp = va_arg(args, uintptr_t); \
35 else if(*sig == 'F') \
36 *(u4*)sp = va_arg(args, u4); \
37 else \
38 *sp = va_arg(args, u4); \
39 sp++
41 #ifdef JEM
42 #define VA_DOUBLE_JEM(args, sp, fp_jem) do { \
43 fp_jem -= 2; \
44 *(u8*)sp = va_arg(args, u8); \
45 *(u8*)fp_jem = *(u8*)sp; \
46 } while (0)
48 #define VA_SINGLE_JEM(args, sp, fp_jem) do { \
49 fp_jem--; \
50 switch (*sig) { \
51 case 'L': \
52 *sp = va_arg(args, uintptr_t); \
53 if (*sp && (!JAM_ON_STACK || IS_JAM_OBJECT(*sp))) \
54 /* If this is an object, we have to calculate a */ \
55 /* pointer to its data for JEM */ \
56 *fp_jem = (uint32_t)INST_DATA((Object*)(*sp)); \
57 else \
58 *fp_jem = *sp; \
59 break; \
60 case '[': \
61 *sp = va_arg(args, uintptr_t); \
62 if (*sp && (!JAM_ON_STACK || IS_JAM_ARRAY(*sp))) \
63 /* Array - similar to object above */ \
64 *fp_jem = (uint32_t)ARRAY_DATA((Object*)(*sp)); \
65 else \
66 *fp_jem = *sp; \
67 break; \
68 case 'F': \
69 default: \
70 *(uint32_t*)sp = va_arg(args, uint32_t); \
71 *(uint32_t*)fp_jem = *(uint32_t*)sp; \
72 break; \
73 } \
74 } while (0)
75 #endif
77 #define JA_DOUBLE(args, sp) *(u8*)sp = *args++; sp+=2
79 #ifdef JEM
80 #define JA_DOUBLE_JEM(args, sp, fp_jem) do { \
81 fp_jem -= 2; \
82 *(u8*)sp = *args++; \
83 *(u8*)fp_jem = *(u8*)sp; \
84 sp += 2; \
85 } while (0)
86 #endif
88 #define JA_SINGLE(args, sp) \
89 switch(*sig) { \
90 case 'L': case '[': case 'F': \
91 *sp = *(uintptr_t*)args; \
92 break; \
93 case 'B': case 'Z': \
94 *sp = *(signed char*)args; \
95 break; \
96 case 'C': \
97 *sp = *(unsigned short*)args; \
98 break; \
99 case 'S': \
100 *sp = *(signed short*)args; \
101 break; \
102 case 'I': \
103 *sp = *(signed int*)args; \
104 break; \
106 sp++; args++
108 #ifdef JEM
109 #define JA_SINGLE_JEM(args, sp, fp_jem) do { \
110 fp_jem--; \
111 switch (*sig) { \
112 case 'L': \
113 *sp = *(uintptr_t*)args; \
114 if (*sp && (!JAM_ON_STACK || IS_JAM_OBJECT(*sp))) \
115 *fp_jem = (uint32_t)INST_DATA((Object*)(*sp)); \
116 else \
117 *fp_jem = *sp; \
118 break; \
119 case '[': \
120 *sp = *(uintptr_t*)args; \
121 if (*sp && (!JAM_ON_STACK || IS_JAM_ARRAY(*sp))) \
122 *fp_jem = (uint32_t)ARRAY_DATA((Object*)(*sp)); \
123 else \
124 *fp_jem = *sp; \
125 break; \
126 case 'F': \
127 *sp = *(uintptr_t*)args; \
128 *fp_jem = *sp; \
129 break; \
130 case 'B': \
131 case 'Z': \
132 *sp = *(signed char*)args; \
133 *fp_jem = *sp; \
134 break; \
135 case 'C': \
136 *sp = *(unsigned short*)args; \
137 *fp_jem = *sp; \
138 break; \
139 case 'S': \
140 *sp = *(signed short*)args; \
141 *fp_jem = *sp; \
142 break; \
143 case 'I': \
144 *sp = *(signed int*)args; \
145 *fp_jem = *sp; \
146 break; \
148 sp++; \
149 args++; \
150 } while (0)
151 #endif
153 void *executeMethodArgs(Object *ob, Class *class, MethodBlock *mb, ...) {
154 va_list jargs;
155 void *ret;
157 va_start(jargs, mb);
158 ret = executeMethodVaList(ob, class, mb, jargs);
159 va_end(jargs);
161 return ret;
164 void *executeMethodVaList(Object *ob, Class *class, MethodBlock *mb, va_list jargs)
166 char *sig = mb->type;
167 ExecEnv *ee = getExecEnv();
168 uintptr_t *sp;
169 uintptr_t tmp[2];
170 #ifdef JEM
171 uint32_t *fp_jem = NULL;
172 #endif
173 void *ret;
175 ret = CREATE_TOP_FRAME(ee, class, mb, &sp);
176 if (!ret)
177 return ret;
179 /* copy args onto stack */
180 /* Do not touch the original stack frame,just allocate lvars_jem from the
181 * native heap and free it after finishing method execution */
182 #ifdef JEM
183 jam_dprintf("[%s] execute method (locals %d, args %d) %s type %s signature %s on obj %x\n",
184 __func__, mb->max_locals, mb->args_count, mb->name, sig, mb->signature, ob);
185 if(mb->max_locals > 0)
186 fp_jem = ee->last_frame->lvars_jem;
187 #endif
189 if (ob) {
190 #ifndef JEM
191 *sp++ = (uintptr_t) ob; /* push receiver first */
192 #else
193 if(!JAM_ON_STACK || IS_JAM_OBJECT(ob))
194 *(--fp_jem) = (uint32_t)INST_DATA(ob);
195 else
196 *(--fp_jem) = (uint32_t)ob;
197 #endif
200 #ifndef JEM
201 SCAN_SIG(sig, VA_DOUBLE(jargs, sp), VA_SINGLE(jargs, sp));
202 #else
203 sp = tmp;
204 SCAN_SIG(sig, VA_DOUBLE_JEM(jargs, sp, fp_jem), VA_SINGLE_JEM(jargs, sp, fp_jem));
206 if (JAM_ON_STACK && ob && !IS_JAM_OBJECT(ob))
207 ob = JAM_OBJECT((uintptr_t *)ob);
208 #endif
210 if(mb->access_flags & ACC_SYNCHRONIZED)
211 objectLock(ob ? ob : (Object*)mb->class);
213 if(mb->access_flags & ACC_NATIVE) {
214 jam_dprintf("[%s] execute native method\n", __func__);
215 (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))mb->native_invoker)(class, mb, ret);
216 } else
217 executeJava();
219 if(mb->access_flags & ACC_SYNCHRONIZED)
220 objectUnlock(ob ? ob : (Object*)mb->class);
222 POP_TOP_FRAME(ee);
223 #ifdef JEM
226 * Since ret might be returnAddressType, here convert back to JAM
227 * objrefs/arrayrefs from JEM refs
229 if (*(uint32_t *)ret)
230 switch (*(strchr(mb->type, ')') + 1)) {
231 case 'L':
232 *(uint32_t*)ret = (uint32_t)JAM_OBJECT((uintptr_t *)*(uint32_t *)ret);
233 break;
234 case '[':
235 *(uint32_t*)ret = (uint32_t)JAM_ARRAY((uintptr_t *)*(uint32_t *)ret);
236 break;
238 jam_dprintf("[%s] %s: return 0x%x @ %p\n", __func__, mb->type, *(uint32_t *)ret, ret);
239 #endif
240 return ret;
243 void *executeMethodList(Object *ob, Class *class, MethodBlock *mb, u8 *jargs) {
244 char *sig = mb->type;
246 ExecEnv *ee = getExecEnv();
247 uintptr_t *sp;
248 void *ret;
249 #ifdef JEM
250 uintptr_t *fp_jem;
251 #endif
253 ret = CREATE_TOP_FRAME(ee, class, mb, &sp);
254 if (!ret)
255 return ret;
257 /* copy args onto stack */
258 /* Do not touch the original stack frame,just allocate lvars_jem from the
259 * native heap and free it after finishing method execution */
260 #ifdef JEM
261 jam_dprintf("[executeMethodList] execute method (args %d) %s\n", mb->max_locals, mb->name);
262 fp_jem = ee->last_frame->lvars_jem;
263 #endif
265 if(ob){
266 #ifdef JEM
267 if(!JAM_ON_STACK || IS_JAM_OBJECT(ob))
268 *(--fp_jem) = (uint32_t)INST_DATA(ob);
269 else
270 *(--fp_jem) = (uint32_t)ob;
271 #endif
272 *sp++ = (uintptr_t) ob; /* push receiver first */
274 #ifdef JEM
275 SCAN_SIG(sig, JA_DOUBLE_JEM(jargs, sp, fp_jem), JA_SINGLE_JEM(jargs, sp, fp_jem));
276 if (JAM_ON_STACK && ob && !IS_JAM_OBJECT(ob))
277 ob = JAM_OBJECT((uintptr_t *)ob);
278 #else
279 SCAN_SIG(sig, JA_DOUBLE(jargs, sp), JA_SINGLE(jargs, sp));
280 #endif
281 if(mb->access_flags & ACC_SYNCHRONIZED)
282 objectLock(ob ? ob : (Object*)mb->class);
284 if(mb->access_flags & ACC_NATIVE)
285 (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))mb->native_invoker)(class, mb, ret);
286 else
287 executeJava();
289 if(mb->access_flags & ACC_SYNCHRONIZED)
290 objectUnlock(ob ? ob : (Object*)mb->class);
292 POP_TOP_FRAME(ee);
294 #ifdef JEM
295 switch(*(strchr(mb->type,')')+1)){
296 case 'L':
297 *(uint32_t *)ret = (uint32_t)JAM_OBJECT((uintptr_t *)*(uint32_t *)ret);
298 break;
299 case '[':
300 *(uint32_t *)ret = (uint32_t)JAM_ARRAY((uintptr_t *)*(uint32_t *)ret);
301 break;
303 jam_dprintf("[%s] return 0x%x\n", __func__, *(uint32_t *)ret);
304 #endif
306 return ret;