Fix ostack manipulation for floating numbers, fix IS_JAM_ARRAY
[jamvm-avr32-jem.git] / src / execute.c
blob4530c890b20616d3d95cd389c67f456707366992
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 sp += 2; \
47 } while (0)
49 #define VA_SINGLE_JEM(args, sp, fp_jem) do { \
50 fp_jem--; \
51 switch (*sig) { \
52 case 'L': \
53 *sp = va_arg(args, uintptr_t); \
54 if (IS_JAM_OBJECT(*sp)) \
55 /* If this is an object, we have to calculate a */ \
56 /* pointer to its data for JEM */ \
57 *fp_jem = (uint32_t)INST_DATA((Object*)(*sp)); \
58 else \
59 *fp_jem = *sp; \
60 break; \
61 case '[': \
62 *sp = va_arg(args, uintptr_t); \
63 if(IS_JAM_ARRAY(*sp)) \
64 /* Array - similar to object above */ \
65 *fp_jem = (uint32_t)ARRAY_DATA((Object*)(*sp)); \
66 else \
67 *fp_jem = *sp; \
68 break; \
69 case 'F': \
70 *(u4*)sp = va_arg(args, u4); \
71 *(u4*)fp_jem = *(u4*)sp; \
72 break; \
73 default: \
74 *sp = va_arg(args, u4); \
75 *fp_jem = *sp; \
76 } \
77 sp++; \
78 } while (0)
79 #endif
81 #define JA_DOUBLE(args, sp) *(u8*)sp = *args++; sp+=2
83 #ifdef JEM
84 #define JA_DOUBLE_JEM(args, sp, fp_jem) do { \
85 fp_jem -= 2; \
86 *(u8*)sp = *args++; \
87 *(u8*)fp_jem = *(u8*)sp; \
88 sp += 2; \
89 } while (0)
90 #endif
92 #define JA_SINGLE(args, sp) \
93 switch(*sig) { \
94 case 'L': case '[': case 'F': \
95 *sp = *(uintptr_t*)args; \
96 break; \
97 case 'B': case 'Z': \
98 *sp = *(signed char*)args; \
99 break; \
100 case 'C': \
101 *sp = *(unsigned short*)args; \
102 break; \
103 case 'S': \
104 *sp = *(signed short*)args; \
105 break; \
106 case 'I': \
107 *sp = *(signed int*)args; \
108 break; \
110 sp++; args++
112 #ifdef JEM
113 #define JA_SINGLE_JEM(args, sp, fp_jem) do { \
114 fp_jem--; \
115 switch (*sig) { \
116 case 'L': \
117 *sp = *(uintptr_t*)args; \
118 if (IS_JAM_OBJECT(*sp)) \
119 *fp_jem = (uint32_t)INST_DATA((Object*)(*sp));\
120 else \
121 *fp_jem = *sp; \
122 break; \
123 case '[': \
124 *sp = *(uintptr_t*)args; \
125 if (IS_JAM_ARRAY(*sp)) \
126 *fp_jem = (uint32_t)ARRAY_DATA((Object*)(*sp));\
127 else \
128 *fp_jem = *sp; \
129 break; \
130 case 'F': \
131 *sp = *(uintptr_t*)args; \
132 *fp_jem = *sp; \
133 break; \
134 case 'B': \
135 case 'Z': \
136 *sp = *(signed char*)args; \
137 *fp_jem = *sp; \
138 break; \
139 case 'C': \
140 *sp = *(unsigned short*)args; \
141 *fp_jem = *sp; \
142 break; \
143 case 'S': \
144 *sp = *(signed short*)args; \
145 *fp_jem = *sp; \
146 break; \
147 case 'I': \
148 *sp = *(signed int*)args; \
149 *fp_jem = *sp; \
150 break; \
152 sp++; \
153 args++; \
154 } while (0)
155 #endif
157 void *executeMethodArgs(Object *ob, Class *class, MethodBlock *mb, ...) {
158 va_list jargs;
159 void *ret;
161 va_start(jargs, mb);
162 ret = executeMethodVaList(ob, class, mb, jargs);
163 va_end(jargs);
165 return ret;
168 void *executeMethodVaList(Object *ob, Class *class, MethodBlock *mb, va_list jargs) {
169 char *sig = mb->type;
171 ExecEnv *ee = getExecEnv();
172 uintptr_t *sp;
173 #ifdef JEM
174 uint32_t *sp_jem = NULL;
175 uint32_t *fp_jem = NULL;
176 #endif
177 void *ret;
179 CREATE_TOP_FRAME(ee, class, mb, sp, ret);
181 /* copy args onto stack */
182 /* Do not touch the original stack frame,just allocate lvars_jem from the
183 * native heap and free it after finishing method execution */
184 #ifdef JEM
185 jam_printf("[executeMethodVAList] execute method (args %d) %s on obj %x\n", mb->max_locals, mb->name, ob);
186 if(mb->max_locals > 0)
187 sp_jem = sysMalloc(mb->max_locals * sizeof(uint32_t));
188 ee->last_frame->lvars_jem = fp_jem = sp_jem + mb->max_locals;
189 #endif
191 if (ob) {
192 #ifdef JEM
193 if(IS_JAM_OBJECT(ob))
194 *(--fp_jem) = (uint32_t)INST_DATA(ob);
195 else
196 *(--fp_jem) = (uint32_t)ob;
197 #endif
198 *sp++ = (uintptr_t) ob; /* push receiver first */
201 #ifndef JEM
202 SCAN_SIG(sig, VA_DOUBLE(jargs, sp), VA_SINGLE(jargs, sp));
203 #else
204 SCAN_SIG(sig, VA_DOUBLE_JEM(jargs, sp, fp_jem), VA_SINGLE_JEM(jargs, sp, fp_jem));
206 if (ob && !IS_JAM_OBJECT(ob))
207 ob = JAM_OBJECT(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_printf("[executeMethodVAList] execute native method\n");
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
224 if(sp_jem)
225 sysFree(sp_jem);
228 * Since ret might be returnAddressType, here convert back to JAM
229 * objrefs/arrayrefs from JEM refs
231 switch (*(strchr(mb->type, ')') + 1)) {
232 case 'L':
233 *(uint32_t*)ret = (uint32_t)JAM_OBJECT(*(uint32_t*)ret);
234 break;
235 case '[':
236 *(uint32_t*)ret = (uint32_t)JAM_ARRAY(*(uint32_t*)ret);
237 break;
239 jam_printf("[executeMethodVaList] return 0x%x\n", *(uint32_t*)ret);
240 #endif
241 return ret;
244 void *executeMethodList(Object *ob, Class *class, MethodBlock *mb, u8 *jargs) {
245 char *sig = mb->type;
247 ExecEnv *ee = getExecEnv();
248 uintptr_t *sp;
249 void *ret;
250 #ifdef JEM
251 uintptr_t *sp_jem = NULL;
252 uintptr_t *fp_jem = NULL;
253 #endif
255 CREATE_TOP_FRAME(ee, class, mb, sp, 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_printf("[executeMethodList] execute method (args %d) %s\n", mb->max_locals, mb->name);
262 if(mb->max_locals > 0)
263 sp_jem = sysMalloc(mb->max_locals * sizeof(uintptr_t));
264 ee->last_frame->lvars_jem = (fp_jem = sp_jem + mb->max_locals);
265 #endif
267 if(ob){
268 #ifdef JEM
269 if(IS_JAM_OBJECT(ob))
270 *(--fp_jem) = (uint32_t)INST_DATA(ob);
271 else
272 *(--fp_jem) = (uint32_t)ob;
273 #endif
274 *sp++ = (uintptr_t) ob; /* push receiver first */
276 #ifdef JEM
277 SCAN_SIG(sig, JA_DOUBLE_JEM(jargs, sp, fp_jem), JA_SINGLE_JEM(jargs, sp, fp_jem));
278 if (ob && !IS_JAM_OBJECT(ob))
279 ob = JAM_OBJECT(ob);
280 #else
281 SCAN_SIG(sig, JA_DOUBLE(jargs, sp), JA_SINGLE(jargs, sp));
282 #endif
283 if(mb->access_flags & ACC_SYNCHRONIZED)
284 objectLock(ob ? ob : (Object*)mb->class);
286 if(mb->access_flags & ACC_NATIVE)
287 (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*))mb->native_invoker)(class, mb, ret);
288 else
289 executeJava();
291 if(mb->access_flags & ACC_SYNCHRONIZED)
292 objectUnlock(ob ? ob : (Object*)mb->class);
294 POP_TOP_FRAME(ee);
296 #ifdef JEM
297 if(sp_jem)
298 sysFree(sp_jem);
299 switch(*(strchr(mb->type,')')+1)){
300 case 'L':
301 *(uint32_t*)ret = (uint32_t)JAM_OBJECT(*(uint32_t*)ret);
302 break;
303 case '[':
304 *(uint32_t*)ret = (uint32_t)JAM_ARRAY(*(uint32_t*)ret);
305 break;
307 jam_printf("[executeMethodList] return 0x%x\n", *(uint32_t*)ret);
308 #endif
310 return ret;