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.
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); \
38 *sp = va_arg(args, u4); \
42 #define VA_DOUBLE_JEM(args, sp, fp_jem) do { \
44 *(u8*)sp = va_arg(args, u8); \
45 *(u8*)fp_jem = *(u8*)sp; \
49 #define VA_SINGLE_JEM(args, sp, fp_jem) do { \
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)); \
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)); \
70 *(u4*)sp = va_arg(args, u4); \
71 *(u4*)fp_jem = *(u4*)sp; \
74 *sp = va_arg(args, u4); \
81 #define JA_DOUBLE(args, sp) *(u8*)sp = *args++; sp+=2
84 #define JA_DOUBLE_JEM(args, sp, fp_jem) do { \
87 *(u8*)fp_jem = *(u8*)sp; \
92 #define JA_SINGLE(args, sp) \
94 case 'L': case '[': case 'F': \
95 *sp = *(uintptr_t*)args; \
98 *sp = *(signed char*)args; \
101 *sp = *(unsigned short*)args; \
104 *sp = *(signed short*)args; \
107 *sp = *(signed int*)args; \
113 #define JA_SINGLE_JEM(args, sp, fp_jem) do { \
117 *sp = *(uintptr_t*)args; \
118 if (IS_JAM_OBJECT(*sp)) \
119 *fp_jem = (uint32_t)INST_DATA((Object*)(*sp));\
124 *sp = *(uintptr_t*)args; \
125 if (IS_JAM_ARRAY(*sp)) \
126 *fp_jem = (uint32_t)ARRAY_DATA((Object*)(*sp));\
131 *sp = *(uintptr_t*)args; \
136 *sp = *(signed char*)args; \
140 *sp = *(unsigned short*)args; \
144 *sp = *(signed short*)args; \
148 *sp = *(signed int*)args; \
157 void *executeMethodArgs(Object
*ob
, Class
*class, MethodBlock
*mb
, ...) {
162 ret
= executeMethodVaList(ob
, class, mb
, jargs
);
168 void *executeMethodVaList(Object
*ob
, Class
*class, MethodBlock
*mb
, va_list jargs
) {
169 char *sig
= mb
->type
;
171 ExecEnv
*ee
= getExecEnv();
174 uint32_t *sp_jem
= NULL
;
175 uint32_t *fp_jem
= NULL
;
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 */
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
;
193 if(IS_JAM_OBJECT(ob
))
194 *(--fp_jem
) = (uint32_t)INST_DATA(ob
);
196 *(--fp_jem
) = (uint32_t)ob
;
198 *sp
++ = (uintptr_t) ob
; /* push receiver first */
202 SCAN_SIG(sig
, VA_DOUBLE(jargs
, sp
), VA_SINGLE(jargs
, sp
));
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
))
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
);
219 if(mb
->access_flags
& ACC_SYNCHRONIZED
)
220 objectUnlock(ob
? ob
: (Object
*)mb
->class);
228 * Since ret might be returnAddressType, here convert back to JAM
229 * objrefs/arrayrefs from JEM refs
231 switch (*(strchr(mb
->type
, ')') + 1)) {
233 *(uint32_t*)ret
= (uint32_t)JAM_OBJECT(*(uint32_t*)ret
);
236 *(uint32_t*)ret
= (uint32_t)JAM_ARRAY(*(uint32_t*)ret
);
239 jam_printf("[executeMethodVaList] return 0x%x\n", *(uint32_t*)ret
);
244 void *executeMethodList(Object
*ob
, Class
*class, MethodBlock
*mb
, u8
*jargs
) {
245 char *sig
= mb
->type
;
247 ExecEnv
*ee
= getExecEnv();
251 uintptr_t *sp_jem
= NULL
;
252 uintptr_t *fp_jem
= NULL
;
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 */
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
);
269 if(IS_JAM_OBJECT(ob
))
270 *(--fp_jem
) = (uint32_t)INST_DATA(ob
);
272 *(--fp_jem
) = (uint32_t)ob
;
274 *sp
++ = (uintptr_t) ob
; /* push receiver first */
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
))
281 SCAN_SIG(sig
, JA_DOUBLE(jargs
, sp
), JA_SINGLE(jargs
, sp
));
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
);
291 if(mb
->access_flags
& ACC_SYNCHRONIZED
)
292 objectUnlock(ob
? ob
: (Object
*)mb
->class);
299 switch(*(strchr(mb
->type
,')')+1)){
301 *(uint32_t*)ret
= (uint32_t)JAM_OBJECT(*(uint32_t*)ret
);
304 *(uint32_t*)ret
= (uint32_t)JAM_ARRAY(*(uint32_t*)ret
);
307 jam_printf("[executeMethodList] return 0x%x\n", *(uint32_t*)ret
);