* configure.ac [ENABLE_STATICVM] (AC_CHECK_LIB(dl)): Only perform the
[cacao.git] / src / vm / jit / arm / asmpart.S
1 /* src/vm/jit/arm/asmpart.S - Java-C interface functions for ARM
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Michael Starzinger
28
29    Changes: Christian Thalinger
30
31    $Id: asmpart.S 6541 2006-08-22 14:48:01Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include "vm/jit/arm/offsets.h"
39 #include "vm/jit/arm/md-asm.h"
40
41 #include "vm/jit/methodheader.h"
42
43
44         .file "asmpart.S"
45         .text
46         .align 2
47
48
49 /* export functions ***********************************************************/
50
51         .globl asm_vm_call_method
52         .globl asm_vm_call_method_int
53         .globl asm_vm_call_method_long
54         .globl asm_vm_call_method_float
55         .globl asm_vm_call_method_double
56         .globl asm_vm_call_method_exception_handler
57
58         .globl asm_call_jit_compiler
59
60         .globl asm_handle_exception
61         .globl asm_handle_nat_exception
62
63         .globl asm_abstractmethoderror
64
65         .globl asm_patcher_wrapper
66
67         .globl asm_cacheflush
68
69         .globl asm_getclassvalues_atomic
70         .globl asm_criticalsections
71
72
73 #if !defined(ENABLE_THREADS)
74 asm_exceptionptr:
75         .word _no_threads_exceptionptr
76 #endif
77
78 asm_jitcompilerptr:
79         .word asm_call_jit_compiler
80
81 asm_criticalsections:
82 #if defined(ENABLE_THREADS)
83         .word _crit_begin
84         .word _crit_end
85         .word _crit_restart
86 #endif
87         .word 0
88
89
90 /* asm_vm_call_method **********************************************************
91
92    This function calls a Java-method (which possibly needs compilation)
93    with up to 4 address parameters.
94
95    This functions calls the JIT-compiler which eventually translates the
96    method into machine code.
97
98 *******************************************************************************/
99
100         .align  2
101
102         .word   0                           /* catch type all                     */
103         .word   0                           /* handler pc                         */
104         .word   0                           /* end pc                             */
105         .word   0                           /* start pc                           */
106         .word   1                           /* extable size                       */
107         .word   0                           /* line number table start            */
108         .word   0                           /* line number table size             */
109         .word   0                           /* FltSave                            */
110         .word   0                           /* IntSave                            */
111         .word   0                           /* IsLeaf                             */
112         .word   0                           /* IsSync                             */
113         .word   0                           /* FrameSize                          */
114         .word   0                           /* CodeinfoPointer                    */
115
116 asm_vm_call_method:
117 asm_vm_call_method_int:
118 asm_vm_call_method_long:
119 /* asm_vm_call_method_float:
120 asm_vm_call_method_double: */
121         SAVE_SCRATCH_REGISTERS            /* save our personal scratch regs   */
122         stmfd sp!, {v1}                   /* V1 is used to recompute SP ...   */
123         mov   v1, #0                      /* ... when using stack arguments   */
124         ldr   ip, asm_jitcompilerptr
125         str   ip, [sp, #-4]!              /* store fake address               */
126         mov   mptr, sp                    /* set method pointer               */
127
128         mov   itmp1, a1                   /* pass methodinfo* via ITMP1       */
129
130         cmp   a2, #0                      /* do we have arguments?            */
131         ble   asm_calljava_copyfinish     /* no -> do not care :-)            */
132
133         /* REMEMBER: stack space for arguments is reserved here! */
134         /* TODO: we possibly reserve to much here */
135         mov   v1, a2, lsl #3              /* how much stack do we alloc?      */
136         sub   sp, sp, v1                  /* allocate stack for arguments!    */
137
138         mov   itmp3, #0                   /* stack position                   */
139 asm_calljava_copyloop:                /* reorder stack arguments!         */
140 #if defined(__ARMEL__)
141         ldr   ip, [a3,#offvmargdata]      /* get LOW word of argument         */
142         str   ip, [sp, itmp3]
143         add   itmp3, itmp3, #4
144         ldr   ip, [a3,#offvmargtype]      /* is it a 2_WORD_TYPE?             */
145         tst   ip, #1
146         ldrne ip, [a3,#offvmargdata + 4]  /* yes -> get HIGH word of argument */
147         strne ip, [sp, itmp3]
148         addne itmp3, itmp3, #4
149 #else /* defined(__ARMEB__) */
150         ldr   ip, [a3,#offvmargtype + 4]  /* get our item type (it is u8)    */
151         teq   ip, #2                      /* is it a TYPE_FLOAT?              */
152         ldreq ip, [a3,#offvmargdata]      /* yes -> get LOW word of float     */
153         streq ip, [sp, itmp3]
154         addeq itmp3, itmp3, #4
155         beq   asm_calljava_copydone
156         tst   ip, #1                      /* is it a 2_WORD_TYPE?             */
157         ldrne ip, [a3,#offvmargdata]      /* yes -> get HIGH word of argument */
158         strne ip, [sp, itmp3]
159         addne itmp3, itmp3, #4
160         ldr   ip, [a3,#offvmargdata + 4]  /* get LOW word of argument         */
161         str   ip, [sp, itmp3]
162         add   itmp3, itmp3, #4
163 asm_calljava_copydone:
164 #endif
165         add   a3, a3, #sizevmarg          /* next argument block              */
166         subs  a2, a2, #1
167         bgt   asm_calljava_copyloop
168
169         /* REMEMBER: first four args are passed in regs, take them out again  */
170         ldmfd sp, {a1, a2, a3, a4}        /* load first four args to register */
171         cmp   v1, #16                     /* do we have four arguments?       */
172         addlt sp, sp, v1
173         movlt v1, #0
174         addge sp, sp, #16
175         subge v1, v1, #16
176
177 asm_calljava_copyfinish:
178         /* REMEMBER: do the method call just like in java! */
179         ldr   ip, [mptr]                  /* fake virtual function call       */
180         mov   lr, pc 
181         mov   pc, ip 
182 fake2:
183         sub   ip, pc, #(fake2 - asm_vm_call_method)+8
184
185         add   sp, sp, v1                  /* free stack arguments!            */
186         add   sp, sp, #4                  /* free fake address                */
187         ldmfd sp!, {v1}
188         RESTORE_SCRATCH_REGS_AND_RETURN   /* return to caller, restore regs   */
189
190 asm_vm_call_method_exception_handler:
191         mov   a1, xptr                    /* exception pointer is arg1        */
192         bl    builtin_throw_exception     /* throw the exception              */
193         mov   res1, #0                    /* return NULL                      */
194         mov   res2, #0                    /* return NULL                      */
195         add   sp, sp, v1                  /* free stack arguments!            */
196         add   sp, sp, #4                  /* free fake address                */
197         ldmfd sp!, {v1}
198         RESTORE_SCRATCH_REGS_AND_RETURN   /* return to caller, restore regs   */
199
200 asm_vm_call_method_float:
201         mov a1,#0x51
202         b asm_debug
203 asm_vm_call_method_double:
204         mov a1,#0x52
205         b asm_debug
206
207
208 /****************** function asm_call_jit_compiler *****************************
209 *                                                                              *
210 *   Invokes the compiler for untranslated JavaVM methods.                      *
211 *   What this method does:                                                     *
212 *    - save args and LR                                                        *
213 *    - fire up jit_compile (pass methodinfo pointer)                           *
214 *    - try to find out where to write back the new method pointer              *
215 *    - restore args and LR                                                     *
216 *    - check for exceptions                                                    *
217 *    - eventually write back new method pointer                                *
218 *    - call jit code (wich will then return to caller)                         *
219 *                                                                              *
220 *   These methods can call us: codegen_compilerstub & asm_calljavafunction     *
221 *   ATTENTION: use REG_ITMP1 to pass methodinfo pointer to me!                 *
222 *                                                                              *
223 *******************************************************************************/
224
225 #define MYSTACKSIZE (5*4)
226
227 asm_call_jit_compiler:
228         SAVE_ARGUMENT_REGISTERS             /* save our argument registers & LR   */
229
230         mov   a1, itmp1                     /* pass methodinfo pointer            */
231         mov   a2, mptr                      /* pass method pointer                */
232         add   a3, sp, #MYSTACKSIZE          /* pass Java sp                       */
233         mov   a4, lr                        /* pass Java RA (correct for leafs)   */
234         bl    jit_asm_compile
235         mov   itmp1, res1                   /* save pointer to new jit-code       */
236
237         tst   itmp1,itmp1                   /* check for exeption                 */
238         beq   L_asm_call_jit_compiler_exception
239
240         RESTORE_ARGUMENT_REGISTERS          /* load our argument registers & LR   */
241
242         mov   ip, itmp1
243         mov   pc, ip                        /* call jit-code                      */
244
245 L_asm_call_jit_compiler_exception:
246         bl    exceptions_get_and_clear_exception
247         mov   xptr, res1                    /* get exception                      */
248
249         RESTORE_ARGUMENT_REGISTERS          /* load LR                            */
250
251         sub   xpc, lr, #4                   /* xpc = instruction that called us   */
252         b     asm_handle_nat_exception
253
254
255 /********************* function asm_handle_exception ***************************
256 *                                                                              *
257 *   This function handles an exception. It does not use the usual calling      *
258 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
259 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
260 *   the local exception table for a handler. If no one is found, it unwinds    *
261 *   stacks and continues searching the callers.                                *
262 *                                                                              *
263 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
264 *                                                                              *
265 *******************************************************************************/
266
267 asm_handle_nat_exception:
268         /*TODO:maybe make a macro out of it!!!*/
269         SAVE_ARGUMENT_REGISTERS  
270         mov   a1, lr
271         bl    md_codegen_get_pv_from_pc
272         mov   ip, res1
273         RESTORE_ARGUMENT_REGISTERS  
274         /* fall through */
275
276 asm_handle_exception:
277         stmfd sp!, {r0 - r3}               /* save possible used registers    */
278         mov   itmp3, #1                    /* set maybe-leaf flag             */
279         mov   a4, #(4*4)                   /* prepare a4 for handle_exception */
280
281 asm_handle_exception_loop:
282         stmfd sp!, {ip,lr}                 /* call exception helper here!     */
283         mov   a1, xptr                     /* pass exception pointer          */
284         mov   a2, xpc                      /* pass exception pointer          */
285         mov   a3, ip                       /* pass data segment pointer       */
286         add   a4, sp, a4                   /* calculate Java sp into a4...    */
287         add   a4, a4, #(2*4)
288         bl    exceptions_handle_exception
289         ldmfd sp!, {ip,lr}
290
291         tst   a1, a1
292         beq   asm_handle_exception_not_catched
293
294         mov   xpc, a1                      /* move handlerpc into xpc         */
295         tst   itmp3,itmp3                  /* if this is a lead method ...    */
296         ldmnefd sp!, {r0 - r3}             /* restore argument registers      */
297
298         mov   pc, xpc                      /* jump to handler                 */
299
300 asm_handle_exception_not_catched:
301         tst   itmp3,itmp3                  /* if this is a lead method ...    */
302         addne sp, sp, #(4*4)               /* remove maybe-leaf stackframe    */
303         movne itmp3, #0                    /* remove maybe-leaf flag          */
304
305         ldr   a3, [ip, #FrameSize]         /* t2 = frame size                 */
306         add   a1, sp, a3                   /* t0 = pointer to save area       */
307         ldr   a2, [ip, #IsLeaf]            /* t1 = is leaf procedure          */
308         tst   a2, a2                       /* if is leaf ...                  */
309         ldreq lr, [a1, #-4]!               /* ... restore RA                  */
310         mov   xpc, lr                      /* the new xpc is RA               */
311
312         ldr   a2, [ip, #IntSave]           /* t1 = saved int register count   */
313         rsb   a2, a2, #5                   /* t1 = count of unsaved registers */
314         sub   a2, a2, #1
315         add   pc, pc, a2, lsl #2           /* do not load unsaved registers   */
316         ldr   v1, [a1, #-20]               /* ... but restore the other ones  */
317         ldr   v2, [a1, #-16]
318         ldr   v3, [a1, #-12]
319         ldr   v4, [a1, #- 8]
320         ldr   v5, [a1, #- 4]
321
322         add   sp, sp, a3                   /* unwind stack (using t2)         */
323         mov   a4, #0                       /* prepare a4 for handle_exception */
324
325         /*TODO:maybe make a macro out of it!!!*/
326         SAVE_ARGUMENT_REGISTERS  
327         mov   a1, lr
328         bl    md_codegen_get_pv_from_pc
329         mov   ip, res1
330         RESTORE_ARGUMENT_REGISTERS  
331
332         b     asm_handle_exception_loop
333
334
335 /* asm_patcher_wrapper *********************************************************
336 *                                                                              *
337 *   TODO: document me                                                          *
338 *                                                                              *
339 *   Stack layout when calling patcher function:                                *
340 *    24   saved REG_ITMP3, should be restored                ( -4)             *
341 *    20   data segment displacement from load instructions   ( -8)             *
342 *    16   return address into JIT code (patch position)      (-12)             *
343 *    12   pointer to virtual java_objectheader                                 *
344 *     8   machine code (which is patched back later)                           *
345 *   [ 8   result of patcher function (indicates exception)  ]                  *
346 *     4   unresolved class/method/field reference                              *
347 *   [ 0   patcher function pointer to call                  ]                  *
348 *     0   saved IP of caller (caller needs it!)                                *
349 *                                                                              *
350 *******************************************************************************/
351
352 #define PATCHSTACKSIZE 7*4
353
354 asm_patcher_wrapper:
355         mov   itmp3, sp                     /* preserve original SP in ITMP3      */
356
357         SAVE_ARGUMENT_REGISTERS_IP          /* save our argument registers & LR   */
358         SAVE_FLOAT_REGISTERS                /* save our float registers here      */
359
360         mov   a1, itmp3                     /* pass SP of patcher stub            */
361         mov   a2, ip                        /* pass PV                            */
362         mov   a3, lr                        /* pass RA (correct for leafs)        */
363         bl    patcher_wrapper
364         mov   itmp3, res1                   /* save return value                  */
365
366         RESTORE_FLOAT_REGISTERS             /* restore our float registers here   */
367         RESTORE_ARGUMENT_REGISTERS_IP       /* load our argument registers & LR   */
368
369         tst   itmp3, itmp3                  /* check for an exception             */
370         bne   L_asm_patcher_wrapper_exception
371
372         add   sp, sp, #PATCHSTACKSIZE       /* remove patcher stack frame         */
373
374         ldr   itmp3, [sp, #-4]              /* restore ITMP3 for calling method   */
375         ldr   pc, [sp, #-12]                /* jump to new patched code           */
376
377 L_asm_patcher_wrapper_exception:
378         mov   xptr, itmp3                   /* get exception                      */
379         ldr   xpc, [sp, #16]                /* RA is xpc                          */
380
381         add   sp, sp, #PATCHSTACKSIZE       /* remove patcher stack frame         */
382
383         b     asm_handle_exception
384
385
386 /* asm_abstractmethoderror *****************************************************
387
388    Creates and throws an AbstractMethodError.
389
390 *******************************************************************************/
391
392 asm_abstractmethoderror:
393         stmfd sp!, {lr}                     /* save return address                */
394         add   a1, sp, #(1*4)                /* pass java sp                       */
395         mov   a2, lr                        /* pass exception address             */
396         bl    exceptions_asm_new_abstractmethoderror
397         ldmfd sp!, {lr}                     /* restore return address             */
398
399         mov   xptr, res1                    /* get exception pointer              */
400         sub   xpc, lr, #4                   /* exception address is ra - 4        */
401         b     asm_handle_nat_exception
402
403                 
404 /********************* function asm_cacheflush *********************************
405 *                                                                              *
406 *   TODO: document me                                                          *
407 *                                                                              *
408 *   void asm_cacheflush(void *p, s4 size);                                     *
409 *                                                                              *
410 *******************************************************************************/
411
412 #if 1
413 .equ sys_cacheflush, 0x9f0002
414 asm_cacheflush:
415         add   a2, a1, a2
416         mov   a3, #0
417         #if 1
418           /* TODO: repeair this! */
419           /* cacheflush is messed up beyond all repair! */
420           mov a1, #0x0
421           mov a2, #0xff000000
422         #endif
423         swi   #sys_cacheflush
424         mov   pc, lr
425 #else
426 .equ IMBa, 0xf00000
427 .equ IMBb, 0xf00001
428 asm_cacheflush:
429         /* clean and invalidate the entire cache!!! */
430         swi   #IMBa
431         mov   pc, lr
432 #endif
433
434
435 /********************* function asm_getclassvalues_atomic *********************/
436
437 asm_getclassvalues_atomic:
438         stmfd sp!, {r4, r5, r6}
439 _crit_restart:
440 _crit_begin:
441         ldr   r4,[a1,#offbaseval]
442         ldr   r5,[a1,#offdiffval]
443         ldr   r6,[a2,#offbaseval]
444 _crit_end:
445         str   r4,[a3,#offcast_super_baseval]
446         str   r5,[a3,#offcast_super_diffval]
447         str   r6,[a3,#offcast_sub_baseval]
448         ldmfd sp!, {r4, r5, r6}
449         mov   pc, lr
450
451
452 /* Disable exec-stacks, required for Gentoo ***********************************/
453
454 #if defined(__GCC__) && defined(__ELF__)
455         .section .note.GNU-stack,"",@progbits
456 #endif
457
458
459 /*
460  * These are local overrides for various environment variables in Emacs.
461  * Please do not remove this and leave it at the end of the file, where
462  * Emacs will automagically detect them.
463  * ---------------------------------------------------------------------
464  * Local variables:
465  * mode: asm
466  * indent-tabs-mode: t
467  * c-basic-offset: 4
468  * tab-width: 4
469  * End:
470  * vim:noexpandtab:sw=4:ts=4:
471  */