Merged with tip.
[cacao.git] / src / vm / jit / powerpc / asmpart.S
1 /* src/vm/jit/powerpc/asmpart.S - Java-C interface functions for PowerPC
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.text;  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 */
26
27
28 #include "config.h"
29
30 #include "md-abi.h"
31 #include "md-asm.h"
32
33 #include "vm/jit/abi-asm.h"
34 #include "vm/jit/methodheader.h"
35
36
37         .text
38
39         .align 2
40
41
42 /* export functions ***********************************************************/
43
44         .globl asm_vm_call_method
45         .globl asm_vm_call_method_int
46         .globl asm_vm_call_method_long
47         .globl asm_vm_call_method_float
48         .globl asm_vm_call_method_double
49
50         .globl asm_vm_call_method_exception_handler
51         .globl asm_vm_call_method_end
52
53         .globl asm_handle_nat_exception
54         .globl asm_handle_exception
55
56         .globl asm_abstractmethoderror
57
58         .globl asm_cacheflush
59
60
61 /* asm_vm_call_method **********************************************************
62 *                                                                              *
63 *   This function calls a Java-method (which possibly needs compilation)       *
64 *   with up to 4 address parameters.                                           *
65 *                                                                              *
66 *   This functions calls the JIT-compiler which eventually translates the      *
67 *   method into machine code.                                                  *
68 *                                                                              *
69 *   C-prototype:                                                               *
70 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
71 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
72 *                                                                              *
73 *******************************************************************************/
74
75         .align 2
76
77         .long   0                         /* fltsave                              */
78         .long   0                         /* intsave                              */
79         .long   0                         /* IsLeaf                               */
80         .long   0                         /* frame size                           */
81         .long   0                         /* codeinfo pointer                     */
82
83 asm_vm_call_method:
84 asm_vm_call_method_int:
85 asm_vm_call_method_long:
86 asm_vm_call_method_float:
87 asm_vm_call_method_double:
88         mflr    r0
89         stw     r0,LA_LR_OFFSET(sp)
90         stwu    sp,-40*4(sp)              /* keep stack 16-byte aligned           */
91
92         stw     s0,8*4(sp)                /* save used callee saved registers     */
93
94 #if defined(__DARWIN__)
95         stw     itmp1,10*4(sp)            /* register r11 is callee saved         */
96 #endif
97         stw     pv,11*4(sp)               /* save PV register                     */
98
99         stw     itmp3,12*4(sp)            /* registers r14-r31 are callee saved   */
100         stfd    ftmp1,14*4(sp)            /* registers f14-f31 are callee saved   */
101         stfd    ftmp2,16*4(sp)
102
103 #if defined(__DARWIN__)
104         stw     t1,18*4(sp)
105         stw     t2,19*4(sp)
106         stw     t3,20*4(sp)
107         stw     t4,21*4(sp)
108         stw     t5,22*4(sp)
109         stw     t6,23*4(sp)
110         stw     t7,24*4(sp)
111
112         stfd    ft0,26*4(sp)
113         stfd    ft1,28*4(sp)
114         stfd    ft2,30*4(sp)
115         stfd    ft3,32*4(sp)
116         stfd    ft4,34*4(sp)
117         stfd    ft5,36*4(sp)
118 #else
119         SAVE_TEMPORARY_REGISTERS(18)        /* the offset has to be even          */
120 #endif
121
122         mr      pv,a0                       /* move PV into PV register           */
123         mtctr   pv                          /* move PV into branch register       */
124
125         mr      t0,a1                       /* address of data structure          */
126         mr      t1,a2                       /* stack argument count               */
127
128         mr      s0,sp                       /* save SP                            */
129
130         lwz     a0,0*8+4(t0)                /* we are on big-endian               */
131         lwz     a1,1*8+4(t0)
132         lwz     a2,2*8+4(t0)
133         lwz     a3,3*8+4(t0)
134         lwz     a4,4*8+4(t0)
135         lwz     a5,5*8+4(t0)
136         lwz     a6,6*8+4(t0)
137         lwz     a7,7*8+4(t0)
138
139         lfd     fa0,8*8(t0)
140         lfd     fa1,9*8(t0)
141         lfd     fa2,10*8(t0)
142         lfd     fa3,11*8(t0)
143         lfd     fa4,12*8(t0)
144         lfd     fa5,13*8(t0)
145         lfd     fa6,14*8(t0)
146         lfd     fa7,15*8(t0)
147
148 #if defined(__DARWIN__)
149         lfd     fa8,16*8(t0)
150         lfd     fa9,17*8(t0)
151         lfd     fa10,18*8(t0)
152         lfd     fa11,19*8(t0)
153         lfd     fa12,20*8(t0)
154 #endif
155
156         mr.     t1,t1
157         beq     L_asm_vm_call_method_stack_copy_done
158
159         slwi    t2,t1,3                     /* calculate stackframe size (* 8)    */
160
161         sub     sp,sp,t2                    /* create stackframe                  */
162         mr      t2,sp                       /* temporary stack pointer            */
163
164 L_asm_vm_call_method_stack_copy_loop:
165 #if defined(__DARWIN__)
166         lwz     t3,21*8+0(t0)               /* load argument                      */
167         lwz     t4,21*8+4(t0)
168 #else
169         lwz     t3,16*8+0(t0)               /* load argument                      */
170         lwz     t4,16*8+4(t0)
171 #endif
172         stw     t3,0(t2)                    /* store argument on stack            */
173         stw     t4,4(t2)
174
175         addi    t0,t0,8                     /* load address of next argument      */
176         addi    t2,t2,8                     /* increase stack pointer             */
177         addi    t1,t1,-1                    /* subtract 1 argument                */
178         mr.     t1,t1
179         bgt     L_asm_vm_call_method_stack_copy_loop
180
181 L_asm_vm_call_method_stack_copy_done:
182         bctrl
183 1:
184         mflr    itmp1
185 #if defined(__DARWIN__)
186         addi    pv,itmp1,lo16(asm_vm_call_method - 1b)
187 #else
188         addi    pv,itmp1,(asm_vm_call_method - 1b)@l
189 #endif
190
191 L_asm_vm_call_method_return:
192         mr      sp,s0                       /* restore the SP                     */
193
194         lwz     s0,8*4(sp)                  /* restore used callee saved registers*/
195
196 #if defined(__DARWIN__)
197         lwz     itmp1,10*4(sp)              /* register r11 is callee saved       */
198 #endif
199         lwz     pv,11*4(sp)                 /* save PV register                   */
200
201         lwz     itmp3,12*4(sp)
202         lfd     ftmp1,14*4(sp)              /* registers f14-f31 are callee saved */
203         lfd     ftmp2,16*4(sp)
204
205 #if defined(__DARWIN__)
206         lwz     t1,18*4(sp)
207         lwz     t2,19*4(sp)
208         lwz     t3,20*4(sp)
209         lwz     t4,21*4(sp)
210         lwz     t5,22*4(sp)
211         lwz     t6,23*4(sp)
212         lwz     t7,24*4(sp)
213
214         lfd     ft0,26*4(sp)
215         lfd     ft1,28*4(sp)
216         lfd     ft2,30*4(sp)
217         lfd     ft3,32*4(sp)
218         lfd     ft4,34*4(sp)
219         lfd     ft5,36*4(sp)
220 #else
221         RESTORE_TEMPORARY_REGISTERS(18)   /* the offset has to be even            */
222 #endif
223
224         lwz     r0,40*4+LA_LR_OFFSET(sp)
225         mtlr    r0
226         addi    sp,sp,40*4
227         blr
228
229 asm_vm_call_method_exception_handler:
230         mr      a0,itmp1
231         bl      builtin_throw_exception
232         b       L_asm_vm_call_method_return
233
234 asm_vm_call_method_end:
235         nop
236
237
238 /********************* function asm_handle_exception ***************************
239 *                                                                              *
240 *   This function handles an exception. It does not use the usual calling      *
241 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
242 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
243 *   the local exception table for a handler. If no one is found, it unwinds    *
244 *   stacks and continues searching the callers.                                *
245 *                                                                              *
246 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
247 *                                                                              *
248 *******************************************************************************/
249                 
250 asm_handle_nat_exception:
251 L_asm_handle_nat_exception:             /* required for PIC code              */
252 L_asm_handle_exception_stack_loop:
253         mflr    r0
254         addi    sp,sp,-(LA_SIZE+((4+6)*4))  /* allocate stack (+4 for darwin)     */
255         stw     xptr,LA_SIZE+(4+0)*4(sp)    /* save exception pointer             */
256         stw     xpc,LA_SIZE+(4+1)*4(sp)     /* save exception pc                  */
257         stw     r0,LA_SIZE+(4+3)*4(sp)      /* save return address                */
258         li      itmp3,0
259         stw     itmp3,LA_SIZE+(4+4)*4(sp)   /* save maybe-leaf flag (cleared)     */
260
261         mr      a0,r0                       /* pass return address                */
262         bl      md_asm_codegen_get_pv_from_pc /* get PV from RA                   */
263         stw     v0,LA_SIZE+(4+2)*4(sp)      /* save data segment pointer          */
264
265         lwz     a0,LA_SIZE+(4+0)*4(sp)      /* pass xptr                          */
266         lwz     a1,LA_SIZE+(4+1)*4(sp)      /* pass xpc                           */
267         lwz     a2,LA_SIZE+(4+2)*4(sp)      /* pass PV (v0 == a0)                 */
268         addi    a3,sp,LA_SIZE+((4+6)*4)     /* pass Java SP                       */
269
270         b       L_asm_handle_exception_continue
271
272 asm_handle_exception:
273 L_asm_handle_exception:                 /* required for PIC code              */
274         addi    sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
275
276 #if defined(__DARWIN__)
277 #else
278         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
279         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
280 #endif
281
282         addi    sp,sp,-(LA_SIZE+(4+6)*4)    /* allocate stack                     */
283         stw     xptr,LA_SIZE+(4+0)*4(sp)    /* save xptr                          */
284         stw     pv,LA_SIZE+(4+2)*4(sp)      /* save PV                            */
285         mflr    r0                          /* save RA                            */
286         stw     r0,LA_SIZE+(4+3)*4(sp)
287         li      t0,1                        /* set maybe-leaf flag                */
288         stw     t0,LA_SIZE+(4+4)*4(sp)      /* save maybe-leaf flag               */
289
290         mr      a0,xptr                     /* pass exception pointer             */
291         mr      a1,xpc                      /* pass exception pc                  */
292         mr      a2,pv                       /* pass data segment pointer          */
293         addi    a3,sp,LA_SIZE+(ARG_CNT+TMP_CNT)*8+(4+6)*4
294
295 L_asm_handle_exception_continue:
296         bl      exceptions_handle_exception
297
298         mr.     v0,v0
299         beq     L_asm_handle_exception_not_catched
300
301         mr      xpc,v0                      /* move handlerpc into xpc            */
302         lwz     xptr,LA_SIZE+(4+0)*4(sp)    /* restore xptr                       */
303         lwz     pv,LA_SIZE+(4+2)*4(sp)      /* restore PV                         */
304         lwz     r0,LA_SIZE+(4+3)*4(sp)      /* restore RA                         */
305         mtlr    r0
306         lwz     t0,LA_SIZE+(4+4)*4(sp)      /* get maybe-leaf flag                */
307         addi    sp,sp,LA_SIZE+(4+6)*4       /* free stack frame                   */
308
309         mr.     t0,t0
310         beq     L_asm_handle_exception_no_leaf
311
312 #if defined(__DARWIN__)
313 #else
314         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
315         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
316 #endif
317
318         addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
319
320 L_asm_handle_exception_no_leaf:
321         mtctr   xpc                         /* jump to the handler                */
322         bctr
323
324 L_asm_handle_exception_not_catched:
325         lwz     xptr,LA_SIZE+(4+0)*4(sp)    /* restore xptr                       */
326         lwz     pv,LA_SIZE+(4+2)*4(sp)      /* restore PV                         */
327         lwz     r0,LA_SIZE+(4+3)*4(sp)      /* restore RA                         */
328         mtlr    r0
329         lwz     t0,LA_SIZE+(4+4)*4(sp)      /* get maybe-leaf flag                */
330         addi    sp,sp,LA_SIZE+(4+6)*4       /* free stack frame                   */
331
332         mr.     t0,t0
333         beq     L_asm_handle_exception_no_leaf_stack
334
335         addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
336         li      t0,0                        /* clear the maybe-leaf flag          */
337
338 L_asm_handle_exception_no_leaf_stack:
339         lwz     t1,FrameSize(pv)            /* get frame size                     */
340         add     t1,sp,t1                    /* pointer to save area               */
341
342         lwz     t2,IsLeaf(pv)               /* is leaf procedure                  */
343         mr.     t2,t2
344         bne     L_asm_handle_exception_no_ra_restore
345
346         lwz     r0,LA_LR_OFFSET(t1)         /* restore ra                         */
347         mtlr    r0
348
349 L_asm_handle_exception_no_ra_restore:
350         mflr    xpc                         /* the new xpc is ra                  */
351         mr      t4,xpc                      /* save RA                            */
352         lwz     t2,IntSave(pv)              /* t2 = saved int register count      */
353         bl      ex_int1
354 ex_int1:
355         mflr    t3                          /* t3 = current pc                    */
356 #if defined(__DARWIN__)
357         addi    t3,t3,lo16(ex_int2-ex_int1)
358 #else
359         addi    t3,t3,(ex_int2-ex_int1)@l
360 #endif
361         slwi    t2,t2,2                     /* t2 = register count * 4            */
362         subf    t3,t2,t3                    /* t3 = IntSave - t2                  */
363         mtctr   t3
364         bctr
365
366         lwz     s0,-10*8(t1)
367         lwz     s1,-9*8(t1)
368         lwz     s2,-8*8(t1)
369         lwz     s3,-7*8(t1)
370         lwz     s4,-6*8(t1)
371         lwz     s5,-5*8(t1)
372         lwz     s6,-4*8(t1)
373         lwz     s7,-3*8(t1)
374         lwz     s8,-2*8(t1)
375         lwz     s9,-1*8(t1)
376
377 ex_int2:
378         subf    t1,t2,t1                    /* t1 = t1 - register count * 4       */
379
380         lwz     t2,FltSave(pv)
381         bl      ex_flt1
382 ex_flt1:
383         mflr    t3
384 #if defined(__DARWIN__)
385         addi    t3,t3,lo16(ex_flt2-ex_flt1)
386 #else
387         addi    t3,t3,(ex_flt2-ex_flt1)@l
388 #endif
389         slwi    t2,t2,2                     /* t2 = register count * 4            */
390         subf    t3,t2,t3                    /* t3 = FltSave - t2                  */
391         mtctr   t3
392         bctr
393
394         lfd     fs0,-10*8(t1)
395         lfd     fs1,-9*8(t1)
396         lfd     fs2,-8*8(t1)
397         lfd     fs3,-7*8(t1)
398         lfd     fs4,-6*8(t1)
399         lfd     fs5,-5*8(t1)
400         lfd     fs6,-4*8(t1)
401         lfd     fs7,-3*8(t1)
402         lfd     fs8,-2*8(t1)
403         lfd     fs9,-1*8(t1)
404
405 ex_flt2:
406         mtlr    t4                          /* restore RA                         */
407         lwz     t1,FrameSize(pv)            /* get frame size                     */
408         add     sp,sp,t1                    /* unwind stack                       */
409         b       L_asm_handle_exception_stack_loop
410
411
412 /* asm_abstractmethoderror *****************************************************
413
414    Creates and throws an AbstractMethodError.
415
416 *******************************************************************************/
417
418 asm_abstractmethoderror:
419         mflr    r0
420         stw     r0,LA_LR_OFFSET(sp)
421         stwu    sp,-LA_SIZE_ALIGNED(sp)     /* preserve linkage area              */
422         addi    a0,sp,LA_SIZE_ALIGNED       /* pass java sp                       */
423         mr      a1,r0                       /* pass exception address             */
424         bl      exceptions_asm_new_abstractmethoderror
425         lwz     r0,LA_SIZE_ALIGNED+LA_LR_OFFSET(sp)
426         mtlr    r0                          /* restore return address             */
427         addi    sp,sp,LA_SIZE_ALIGNED
428
429         mr      xptr,v0                     /* get exception pointer              */
430         mr      xpc,r0                      /* we can't use r0 directly in addi   */
431         addi    xpc,xpc,-4                  /* exception address is ra - 4        */
432         b       L_asm_handle_nat_exception
433
434
435 /*********************************************************************/
436
437 asm_cacheflush:
438         add     a1,a0,a1
439         rlwinm  a0,a0,0,0,26
440         addi    a1,a1,31
441         rlwinm  a1,a1,0,0,26
442         mr      a2,a0
443 1:
444         cmplw   a0,a1
445         bge     0f
446         dcbst   0,a0
447         addi    a0,a0,32
448         b       1b
449 0:
450         sync
451 1:
452         cmplw   a2,a1
453         bge     0f
454         icbi    0,a2
455         addi    a2,a2,32
456         b       1b
457 0:
458         sync
459         isync
460         blr
461
462
463 #if defined(__DARWIN__)
464
465 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
466         .align 2
467 L_builtin_throw_exception$stub:
468         .indirect_symbol _builtin_throw_exception
469         mflr r0
470         bcl 20,31,L00$_builtin_throw_exception
471 L00$_builtin_throw_exception:
472         mflr r11
473         addis r11,r11,ha16(L_builtin_throw_exception$lazy_ptr - L00$_builtin_throw_exception)
474         mtlr r0
475         lwzu r12,lo16(L_builtin_throw_exception$lazy_ptr - L00$_builtin_throw_exception)(r11)
476         mtctr r12
477         bctr
478 .data
479 .lazy_symbol_pointer
480 L_builtin_throw_exception$lazy_ptr:
481         .indirect_symbol _builtin_throw_exception
482         .long dyld_stub_binding_helper
483
484
485 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
486         .align 2
487 L_md_asm_codegen_get_pv_from_pc$stub:
488         .indirect_symbol _md_asm_codegen_get_pv_from_pc
489         mflr r0
490         bcl 20,31,L00$_md_asm_codegen_get_pv_from_pc
491 L00$_md_asm_codegen_get_pv_from_pc:
492         mflr r11
493         addis r11,r11,ha16(L_md_asm_codegen_get_pv_from_pc$lazy_ptr - L00$_md_asm_codegen_get_pv_from_pc)
494         mtlr r0
495         lwzu r12,lo16(L_md_asm_codegen_get_pv_from_pc$lazy_ptr - L00$_md_asm_codegen_get_pv_from_pc)(r11)
496         mtctr r12
497         bctr
498 .data
499 .lazy_symbol_pointer
500 L_md_asm_codegen_get_pv_from_pc$lazy_ptr:
501         .indirect_symbol _md_asm_codegen_get_pv_from_pc
502         .long dyld_stub_binding_helper
503
504
505 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
506         .align 2
507 L_exceptions_handle_exception$stub:
508         .indirect_symbol _exceptions_handle_exception
509         mflr r0
510         bcl 20,31,L00$_exceptions_handle_exception
511 L00$_exceptions_handle_exception:
512         mflr r11
513         addis r11,r11,ha16(L_exceptions_handle_exception$lazy_ptr - L00$_exceptions_handle_exception)
514         mtlr r0
515         lwzu r12,lo16(L_exceptions_handle_exception$lazy_ptr - L00$_exceptions_handle_exception)(r11)
516         mtctr r12
517         bctr
518 .data
519 .lazy_symbol_pointer
520 L_exceptions_handle_exception$lazy_ptr:
521         .indirect_symbol _exceptions_handle_exception
522         .long dyld_stub_binding_helper
523
524
525 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
526         .align 2
527 L_exceptions_asm_new_abstractmethoderror$stub:
528         .indirect_symbol _exceptions_asm_new_abstractmethoderror
529         mflr r0
530         bcl 20,31,L00$_exceptions_asm_new_abstractmethoderror
531 L00$_exceptions_asm_new_abstractmethoderror:
532         mflr r11
533         addis r11,r11,ha16(L_exceptions_asm_new_abstractmethoderror$lazy_ptr - L00$_exceptions_asm_new_abstractmethoderror)
534         mtlr r0
535         lwzu r12,lo16(L_exceptions_asm_new_abstractmethoderror$lazy_ptr - L00$_exceptions_asm_new_abstractmethoderror)(r11)
536         mtctr r12
537         bctr
538 .data
539 .lazy_symbol_pointer
540 L_exceptions_asm_new_abstractmethoderror$lazy_ptr:
541         .indirect_symbol _exceptions_asm_new_abstractmethoderror
542         .long dyld_stub_binding_helper
543
544 #endif /* defined(__DARWIN__) */
545
546
547 /* disable exec-stacks ********************************************************/
548
549 #if defined(__linux__) && defined(__ELF__)
550         .section .note.GNU-stack,"",%progbits
551 #endif
552
553
554 /*
555  * These are local overrides for various environment variables in Emacs.
556  * Please do not remove this and leave it at the end of the file, where
557  * Emacs will automagically detect them.
558  * ---------------------------------------------------------------------
559  * Local variables:
560  * mode: asm
561  * indent-tabs-mode: t
562  * c-basic-offset: 4
563  * tab-width: 4
564  * End:
565  * vim:noexpandtab:sw=4:ts=4:
566  */