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