Merged revisions 8123-8136 via svnmerge from
[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, 2007 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    $Id: asmpart.S 8127 2007-06-21 11:55:56Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include "vm/jit/arm/offsets.h"
33 #include "vm/jit/arm/md-asm.h"
34
35 #include "vm/jit/methodheader.h"
36
37
38         .file "asmpart.S"
39         .text
40         .align 2
41
42
43 /* export functions ***********************************************************/
44
45         .globl asm_vm_call_method
46         .globl asm_vm_call_method_int
47         .globl asm_vm_call_method_long
48         .globl asm_vm_call_method_float
49         .globl asm_vm_call_method_double
50         .globl asm_vm_call_method_exception_handler
51         .globl asm_vm_call_method_end
52
53         .globl asm_call_jit_compiler
54
55         .globl asm_handle_exception
56         .globl asm_handle_nat_exception
57
58         .globl asm_abstractmethoderror
59
60         .globl asm_patcher_wrapper
61
62         .globl asm_cacheflush
63
64         .globl asm_getclassvalues_atomic
65         .globl asm_criticalsections
66
67
68 #if !defined(ENABLE_THREADS)
69 asm_exceptionptr:
70         .word _no_threads_exceptionptr
71 #endif
72
73 asm_criticalsections:
74 #if defined(ENABLE_THREADS)
75         .word _crit_begin
76         .word _crit_end
77         .word _crit_restart
78 #endif
79         .word 0
80
81
82 /* asm_vm_call_method **********************************************************
83
84    This function calls a Java-method (which possibly needs compilation)
85    with up to 4 address parameters.
86
87    This functions calls the JIT-compiler which eventually translates the
88    method into machine code.
89
90 *******************************************************************************/
91
92         .align  2
93
94         .word   0                           /* catch type all                     */
95         .word   0                           /* handler pc                         */
96         .word   0                           /* end pc                             */
97         .word   0                           /* start pc                           */
98         .word   1                           /* extable size                       */
99         .word   0                           /* line number table start            */
100         .word   0                           /* line number table size             */
101         .word   0                           /* FltSave                            */
102         .word   0                           /* IntSave                            */
103         .word   0                           /* IsLeaf                             */
104         .word   0                           /* IsSync                             */
105         .word   0                           /* FrameSize                          */
106         .word   0                           /* CodeinfoPointer                    */
107
108 asm_vm_call_method:
109 asm_vm_call_method_int:
110 asm_vm_call_method_long:
111 /* asm_vm_call_method_float:
112 asm_vm_call_method_double: */
113         SAVE_SCRATCH_REGISTERS            /* save our personal scratch regs   */
114         stmfd sp!, {v1}                   /* V1 is used to remember SP        */
115         str   a0, [sp, #-4]!              /* store methods entrypoint         */
116
117         mov   v1, sp                      /* remember SP                      */
118
119         mov   itmp1, a1                   /* address of data structure        */
120         mov   itmp3, a2                   /* stack argument count             */
121
122         ldr   a0, [itmp1], #8             /* load argument registers          */
123         ldr   a1, [itmp1], #8
124         ldr   a2, [itmp1], #8
125         ldr   a3, [itmp1], #8
126
127         cmp   itmp3, #0                   /* do we have stack arguments?      */
128         ble   asm_calljava_copyfinish     /* no -> do not care :-)            */
129
130         mov   itmp2, #0
131         sub   sp, sp, itmp3, lsl #3       /* create stackframe for arguments  */
132 asm_calljava_copyloop:                /* reorder stack arguments!         */
133         ldr   ip, [itmp1], #4             /* load argument                    */
134         str   ip, [sp, itmp2]             /* store argument on stack          */
135         add   itmp2, itmp2, #4            /* next stackslot                   */
136         ldr   ip, [itmp1], #4             /* load argument                    */
137         str   ip, [sp, itmp2]             /* store argument on stack          */
138         add   itmp2, itmp2, #4            /* next stackslot                   */
139         subs  itmp3, itmp3, #1            /* next argument                    */
140         bgt   asm_calljava_copyloop
141
142 asm_calljava_copyfinish:
143         mov   mptr, v1                    /* set method pointer               */
144
145         /* REMEMBER: do the method call just like in java! */
146         ldr   ip, [mptr]                  /* fake virtual function call       */
147         mov   lr, pc
148         mov   pc, ip
149 fake:
150         sub   ip, pc, #(fake - asm_vm_call_method)+8
151
152         mov   sp, v1                      /* restore SP                       */
153         add   sp, sp, #4                  /* free fake address                */
154         ldmfd sp!, {v1}
155         RESTORE_SCRATCH_REGS_AND_RETURN   /* return to caller, restore regs   */
156
157 asm_vm_call_method_exception_handler:
158         mov   a0, xptr                    /* exception pointer is arg1        */
159         bl    builtin_throw_exception     /* throw the exception              */
160         mov   res1, #0                    /* return NULL                      */
161         mov   res2, #0                    /* return NULL                      */
162         mov   sp, v1                      /* restore SP                       */
163         add   sp, sp, #4                  /* free fake address                */
164         ldmfd sp!, {v1}
165         RESTORE_SCRATCH_REGS_AND_RETURN   /* return to caller, restore regs   */
166
167 asm_vm_call_method_float:
168         mov a0,#0x51
169         b asm_debug
170 asm_vm_call_method_double:
171         mov a0,#0x52
172         b asm_debug
173
174 asm_vm_call_method_end:
175
176
177 /****************** function asm_call_jit_compiler *****************************
178 *                                                                              *
179 *   Invokes the compiler for untranslated JavaVM methods.                      *
180 *   What this method does:                                                     *
181 *    - save args and LR                                                        *
182 *    - fire up jit_compile (pass methodinfo pointer)                           *
183 *    - try to find out where to write back the new method pointer              *
184 *    - restore args and LR                                                     *
185 *    - check for exceptions                                                    *
186 *    - eventually write back new method pointer                                *
187 *    - call jit code (wich will then return to caller)                         *
188 *                                                                              *
189 *   These methods can call us: codegen_compilerstub & asm_calljavafunction     *
190 *   ATTENTION: use REG_ITMP1 to pass methodinfo pointer to me!                 *
191 *                                                                              *
192 *******************************************************************************/
193
194 #define MYSTACKSIZE (6*4)
195
196 asm_call_jit_compiler:
197         SAVE_ARGUMENT_REGISTERS             /* save our argument registers & LR   */
198         sub   sp, sp, #4                    /* keep stack 8-byte aligned          */
199
200         mov   a0, itmp1                     /* pass methodinfo pointer            */
201         mov   a1, mptr                      /* pass method pointer                */
202         add   a2, sp, #MYSTACKSIZE          /* pass Java sp                       */
203         mov   a3, lr                        /* pass Java RA (correct for leafs)   */
204         bl    jit_asm_compile
205         mov   itmp1, res1                   /* save pointer to new jit-code       */
206
207         tst   itmp1,itmp1                   /* check for exeption                 */
208         beq   L_asm_call_jit_compiler_exception
209
210         add   sp, sp, #4                    /* keep stack 8-byte aligned          */
211         RESTORE_ARGUMENT_REGISTERS          /* load our argument registers & LR   */
212
213         mov   ip, itmp1
214         mov   pc, ip                        /* call jit-code                      */
215
216 L_asm_call_jit_compiler_exception:
217         bl    exceptions_get_and_clear_exception
218         mov   xptr, res1                    /* get exception                      */
219
220         add   sp, sp, #4                    /* keep stack 8-byte aligned          */
221         RESTORE_ARGUMENT_REGISTERS          /* load LR                            */
222
223         sub   xpc, lr, #4                   /* xpc = instruction that called us   */
224         b     asm_handle_nat_exception
225
226
227 /********************* function asm_handle_exception ***************************
228 *                                                                              *
229 *   This function handles an exception. It does not use the usual calling      *
230 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
231 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
232 *   the local exception table for a handler. If no one is found, it unwinds    *
233 *   stacks and continues searching the callers.                                *
234 *                                                                              *
235 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
236 *                                                                              *
237 *******************************************************************************/
238
239 asm_handle_nat_exception:
240         /*TODO:maybe make a macro out of it!!!*/
241         SAVE_ARGUMENT_REGISTERS  
242         mov   a0, lr
243         bl    md_codegen_get_pv_from_pc
244         mov   ip, res1
245         RESTORE_ARGUMENT_REGISTERS  
246         /* fall through */
247
248 asm_handle_exception:
249         stmfd sp!, {r0 - r3}               /* save possible used registers    */
250         mov   itmp3, #1                    /* set maybe-leaf flag             */
251         mov   a3, #(4*4)                   /* prepare a3 for handle_exception */
252
253 asm_handle_exception_loop:
254         stmfd sp!, {ip,lr}                 /* call exception helper here!     */
255         mov   a0, xptr                     /* pass exception pointer          */
256         mov   a1, xpc                      /* pass exception pointer          */
257         mov   a2, ip                       /* pass data segment pointer       */
258         add   a3, sp, a3                   /* calculate Java sp into a3...    */
259         add   a3, a3, #(2*4)
260         bl    exceptions_handle_exception
261         ldmfd sp!, {ip,lr}
262
263         tst   a0, a0
264         beq   asm_handle_exception_not_catched
265
266         mov   xpc, a0                      /* move handlerpc into xpc         */
267         tst   itmp3,itmp3                  /* if this is a lead method ...    */
268         ldmnefd sp!, {r0 - r3}             /* restore argument registers      */
269
270         mov   pc, xpc                      /* jump to handler                 */
271
272 asm_handle_exception_not_catched:
273         tst   itmp3,itmp3                  /* if this is a lead method ...    */
274         addne sp, sp, #(4*4)               /* remove maybe-leaf stackframe    */
275         movne itmp3, #0                    /* remove maybe-leaf flag          */
276
277         ldr   a2, [ip, #FrameSize]         /* t2 = frame size                 */
278         add   a0, sp, a2                   /* t0 = pointer to save area       */
279         ldr   a1, [ip, #IsLeaf]            /* t1 = is leaf procedure          */
280         tst   a1, a1                       /* if is leaf ...                  */
281         ldreq lr, [a0, #-4]!               /* ... restore RA                  */
282         mov   xpc, lr                      /* the new xpc is RA               */
283
284         ldr   a1, [ip, #IntSave]           /* t1 = saved int register count   */
285         rsb   a1, a1, #5                   /* t1 = count of unsaved registers */
286         sub   a1, a1, #1
287         add   pc, pc, a1, lsl #2           /* do not load unsaved registers   */
288         ldr   v1, [a0, #-20]               /* ... but restore the other ones  */
289         ldr   v2, [a0, #-16]
290         ldr   v3, [a0, #-12]
291         ldr   v4, [a0, #- 8]
292         ldr   v5, [a0, #- 4]
293
294         add   sp, sp, a2                   /* unwind stack (using t2)         */
295         mov   a3, #0                       /* prepare a3 for handle_exception */
296
297         /*TODO:maybe make a macro out of it!!!*/
298         SAVE_ARGUMENT_REGISTERS  
299         mov   a0, lr
300         bl    md_codegen_get_pv_from_pc
301         mov   ip, res1
302         RESTORE_ARGUMENT_REGISTERS  
303
304         b     asm_handle_exception_loop
305
306
307 /* asm_patcher_wrapper *********************************************************
308 *                                                                              *
309 *   TODO: document me                                                          *
310 *                                                                              *
311 *   Stack layout when calling patcher function:                                *
312 *    28   empty because stack needs to be aligned                              *
313 *    24   saved REG_ITMP3, should be restored                ( -8)             *
314 *    20   data segment displacement from load instructions   (-12)             *
315 *    16   return address into JIT code (patch position)      (-16)             *
316 *    12   pointer to virtual java_objectheader                                 *
317 *     8   machine code (which is patched back later)                           *
318 *   [ 8   result of patcher function (indicates exception)  ]                  *
319 *     4   unresolved class/method/field reference                              *
320 *   [ 0   patcher function pointer to call                  ]                  *
321 *     0   saved IP of caller (caller needs it!)                                *
322 *                                                                              *
323 *******************************************************************************/
324
325 #define PATCHSTACKSIZE 8*4
326
327 asm_patcher_wrapper:
328         mov   itmp3, sp                     /* preserve original SP in ITMP3      */
329
330         SAVE_ARGUMENT_REGISTERS_IP          /* save our argument registers & LR   */
331         SAVE_FLOAT_REGISTERS                /* save our float registers here      */
332
333         mov   a0, itmp3                     /* pass SP of patcher stub            */
334         mov   a1, ip                        /* pass PV                            */
335         mov   a2, lr                        /* pass RA (correct for leafs)        */
336         bl    patcher_wrapper
337         mov   itmp3, res1                   /* save return value                  */
338
339         RESTORE_FLOAT_REGISTERS             /* restore our float registers here   */
340         RESTORE_ARGUMENT_REGISTERS_IP       /* load our argument registers & LR   */
341
342         add   sp, sp, #PATCHSTACKSIZE       /* remove patcher stack frame         */
343
344         tst   itmp3, itmp3                  /* check for an exception             */
345         bne   L_asm_patcher_wrapper_exception
346
347         ldr   itmp3, [sp, #-8]              /* restore ITMP3 for calling method   */
348         ldr   pc, [sp, #-16]                /* jump to new patched code           */
349
350 L_asm_patcher_wrapper_exception:
351         mov   xptr, itmp3                   /* get exception                      */
352         ldr   xpc, [sp, #-16]               /* RA is xpc                          */
353
354         /* Note: A normal branch instruction could modify the PV here,            */
355         /*       so we use this construct instead.                                */
356         ldr   pc, [pc, #-4]
357         .word asm_handle_exception
358
359
360 /* asm_abstractmethoderror *****************************************************
361
362    Creates and throws an AbstractMethodError.
363
364 *******************************************************************************/
365
366 asm_abstractmethoderror:
367         stmfd sp!, {lr}                     /* save return address                */
368         add   a0, sp, #(1*4)                /* pass java sp                       */
369         mov   a1, lr                        /* pass exception address             */
370         bl    exceptions_asm_new_abstractmethoderror
371         ldmfd sp!, {lr}                     /* restore return address             */
372
373         mov   xptr, res1                    /* get exception pointer              */
374         sub   xpc, lr, #4                   /* exception address is ra - 4        */
375         b     asm_handle_nat_exception
376
377                 
378 /********************* function asm_cacheflush *********************************
379 *                                                                              *
380 *   TODO: document me                                                          *
381 *                                                                              *
382 *   void asm_cacheflush(void *p, s4 size);                                     *
383 *                                                                              *
384 *******************************************************************************/
385
386 #if 1
387 .equ sys_cacheflush, 0x9f0002
388 asm_cacheflush:
389         add   a1, a0, a1
390         mov   a2, #0
391
392 #if 0
393         /* TWISTI: required on iyonix, maybe a linux-2.4 bug */
394         /* TODO: repeair this! */
395         /* cacheflush is messed up beyond all repair! */
396         mov a0, #0x0
397         mov a1, #0xff000000
398 #endif
399
400         swi   #sys_cacheflush
401         mov   pc, lr
402 #endif
403
404
405 /********************* function asm_getclassvalues_atomic *********************/
406
407 asm_getclassvalues_atomic:
408         stmfd sp!, {r4, r5, r6}
409 _crit_restart:
410 _crit_begin:
411         ldr   r4,[a0,#offbaseval]
412         ldr   r5,[a0,#offdiffval]
413         ldr   r6,[a1,#offbaseval]
414 _crit_end:
415         str   r4,[a2,#offcast_super_baseval]
416         str   r5,[a2,#offcast_super_diffval]
417         str   r6,[a2,#offcast_sub_baseval]
418         ldmfd sp!, {r4, r5, r6}
419         mov   pc, lr
420
421
422 /* disable exec-stacks ********************************************************/
423
424 #if defined(__linux__) && defined(__ELF__)
425         .section .note.GNU-stack,"",%progbits
426 #endif
427
428
429 /*
430  * These are local overrides for various environment variables in Emacs.
431  * Please do not remove this and leave it at the end of the file, where
432  * Emacs will automagically detect them.
433  * ---------------------------------------------------------------------
434  * Local variables:
435  * mode: asm
436  * indent-tabs-mode: t
437  * c-basic-offset: 4
438  * tab-width: 4
439  * End:
440  * vim:noexpandtab:sw=4:ts=4:
441  */