dd9926d90038f06fa78deff8b3d1e6560f9fe1a8
[cacao.git] / src / vm / jit / powerpc64 / asmpart.S
1 /* src/vm/jit/powerpc64/asmpart.S - Java-C interface functions for PowerPC64
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 #define __ASSEMBLY__
31
32 #include "md-abi.h"
33 #include "md-asm.h"
34
35 #include "vm/jit/abi-asm.h"
36 #include "vm/jit/methodheader.h"
37
38
39 /* export functions ***********************************************************/
40
41         .globl asm_vm_call_method_exception_handler
42         .globl asm_vm_call_method_end
43
44         .globl asm_handle_nat_exception
45         .globl asm_handle_exception
46
47         .globl asm_abstractmethoderror
48
49         .globl asm_cacheflush
50
51
52 /* asm_vm_call_method **********************************************************
53 *                                                                              *
54 *   This function calls a Java-method (which possibly needs compilation)       *
55 *   with up to 4 address parameters.                                           *
56 *                                                                              *
57 *   This functions calls the JIT-compiler which eventually translates the      *
58 *   method into machine code.                                                  *
59 *                                                                              *
60 *   C-prototype:                                                               *
61 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
62 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
63 *                                                                              *
64 *******************************************************************************/
65         /* this is the method header see src/vm/jit/methodheader.h */
66
67         .align  3
68
69         .quad   0                           /* catch type all                     */
70         .quad   0                           /* handler pc                         */
71         .quad   0                           /* end pc                             */
72         .quad   0                           /* start pc                           */
73         .long   1                           /* extable size                       */
74         .long   0                           /* ALIGNMENT PADDING                  */
75         .quad   0                           /* line number table  start           */
76         .quad   0                           /* line number table  size            */
77         .long   0                           /* fltsave                            */
78         .long   0                           /* intsave                            */
79         .long   0                           /* isleaf                             */
80         .long   0                           /* frame size                         */
81         .quad   0                           /* codeinfo pointer                   */
82
83 #ifdef ENABLE_LIBJVM
84         
85         .globl asm_vm_call_method
86         .globl asm_vm_call_method_int
87         .globl asm_vm_call_method_long
88         .globl asm_vm_call_method_float
89         .globl asm_vm_call_method_double
90         .section ".opd","aw"
91         .align 3
92
93         asm_vm_call_method:
94         asm_vm_call_method_int:
95         asm_vm_call_method_long:
96         asm_vm_call_method_float:
97         asm_vm_call_method_double:
98                 .quad   .asm_vm_call_method,.TOC.@tocbase,0
99                 .previous
100                 .size asm_vm_call_method, 24
101                 .type .asm_vm_call_method,@function
102                 .globl .asm_vm_call_method
103 #else
104         asm_vm_call_method:
105         .globl asm_vm_call_method
106         asm_vm_call_method_int:
107         .globl asm_vm_call_method_int
108         asm_vm_call_method_long:
109         .globl asm_vm_call_method_long
110         asm_vm_call_method_float:
111         .globl asm_vm_call_method_float
112         asm_vm_call_method_double:
113         .globl asm_vm_call_method_double
114 #endif
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         mflr    r0
122         std     r0,LA_LR_OFFSET(sp)
123         stdu    sp,-40*8(sp)
124         
125         std     s0,8*8(sp)                /* save used callee saved registers     */
126         std     a0,9*8(sp)                /* save method pointer for compiler     */
127
128         std     pv,11*8(sp)               /* save PV register                     */
129
130         std     itmp3,12*8(sp)            /* registers r14-r31 are callee saved   */
131         stfd    ftmp1,13*8(sp)            /* registers f14-f31 are callee saved   */
132         stfd    ftmp2,14*8(sp)
133
134
135         SAVE_TEMPORARY_REGISTERS(15)     
136         mr      s0, r1                  /* save stack pointer */
137
138         /* a1 contains a pointer to a unit64_t structure filled with all INT_ARG_REG,
139         followed by ADR_ARG_CNT and FLT_ARG_CNT, afterwards what else needs to be copied onto
140         the stack 
141         a2 contains the number of additional stack slots to be copied
142         */
143
144 L_register_copy:
145         mr      t1, a1
146         mr      t2, a2
147
148         ld      a0 ,  0*8(t1)
149         ld      a1 ,  1*8(t1)
150         ld      a2 ,  2*8(t1)
151         ld      a3 ,  3*8(t1)
152         ld      a4 ,  4*8(t1)
153         ld      a5 ,  5*8(t1)
154         ld      a6 ,  6*8(t1)
155         ld      a7 ,  7*8(t1)
156
157         lfd     fa0 , 8*8(t1)
158         lfd     fa1 , 9*8(t1)
159         lfd     fa2 ,10*8(t1)
160         lfd     fa3 ,11*8(t1)
161         lfd     fa4 ,12*8(t1)
162         lfd     fa5 ,13*8(t1)
163         lfd     fa6 ,14*8(t1)
164         lfd     fa7 ,15*8(t1)
165         lfd     fa8 ,16*8(t1)
166         lfd     fa9 ,17*8(t1)
167         lfd     fa10,18*8(t1)
168         lfd     fa11,19*8(t1)
169         lfd     fa12,20*8(t1)
170
171         mr.     t2,t2
172         beq L_stack_copy_done
173
174 L_stack_copy:
175         addi    t1,t1,20*8              /* before first possible stack slot arg */
176         mr      t3,t2                   /* argument counter */
177         sldi    t2,t2,8                 /* calculate size of stack */
178         sub     sp,sp,t2                /* increase the stack */
179         mr      t2,sp                   /* t2 points to bottom of stack now */
180
181 L_stack_copy_loop:
182         addi    t1,t1,8                 /* next possible stack slot to copy */
183         mr.     t3,t3                   /* more stack slots to copy ? */
184         beq     L_stack_copy_done
185         ld      itmp3, 0(t1)
186         std     itmp3, 0(t2)
187         addi    t2,t2,8
188         addi    t3,t3,-1
189         b L_stack_copy_loop
190
191 L_stack_copy_done:
192         mr      itmp1, s0               /* fake invokevirtual invocation */
193         addi    itmp1, itmp1, 9*8       /* address of methods pv */
194         ld      pv,0*8(itmp1)
195         mtctr   pv
196         bctrl
197 1:
198         mflr    itmp1
199         addi    pv,itmp1,(.asm_vm_call_method - 1b)@l
200
201 L_asm_vm_call_method_return:
202         mr      sp,s0                     /* restore the function's sp            */
203
204         ld      s0,8*8(sp)                /* restore used callee saved registers  */
205
206         ld      pv,11*8(sp)               /* save PV register                     */
207
208         ld      itmp3,12*8(sp)
209         lfd     ftmp1,13*8(sp)            /* registers f14-f31 are callee saved   */
210         lfd     ftmp2,14*8(sp)
211
212         RESTORE_TEMPORARY_REGISTERS(15) 
213
214         ld     r0,40*8+LA_LR_OFFSET(r1)
215         mtlr   r0
216         addi   r1,r1,40*8
217         blr
218
219 asm_vm_call_method_exception_handler:
220         mr      r3,itmp1
221         bl      builtin_throw_exception
222         b       L_asm_vm_call_method_return
223
224 asm_vm_call_method_end:
225         nop
226
227
228 /********************* function asm_handle_exception ***************************
229 *                                                                              *
230 *   This function handles an exception. It does not use the usual calling      *
231 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
232 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
233 *   the local exception table for a handler. If no one is found, it unwinds    *
234 *   stacks and continues searching the callers.                                *
235 *                                                                              *
236 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
237 *                                                                              *
238 *******************************************************************************/
239                 
240 asm_handle_nat_exception:
241 L_asm_handle_nat_exception:             /* required for PIC code              */
242 L_asm_handle_exception_stack_loop:
243         mflr    r0
244         addi    sp,sp,-(LA_SIZE+PA_SIZE+((4+6)*8))  /* allocate stack (+4 for darwin)     */
245         std     xptr,LA_SIZE+PA_SIZE+(4+0)*8(sp)    /* save exception pointer             */
246         std     xpc,LA_SIZE+PA_SIZE+(4+1)*8(sp)     /* save exception pc                  */
247         std     r0,LA_SIZE+PA_SIZE+(4+3)*8(sp)      /* save return address                */
248         li      itmp3,0
249         std     itmp3,LA_SIZE+PA_SIZE+(4+4)*8(sp)   /* save maybe-leaf flag (cleared)     */
250
251         mr      a0,r0                       /* pass return address                */
252         bl      md_codegen_get_pv_from_pc   /* get PV from RA                     */
253         std     v0,LA_SIZE+PA_SIZE+(4+2)*8(sp)      /* save data segment pointer          */
254
255         ld      a0,LA_SIZE+PA_SIZE+(4+0)*8(sp)      /* pass xptr                          */
256         ld      a1,LA_SIZE+PA_SIZE+(4+1)*8(sp)      /* pass xpc                           */
257         ld      a2,LA_SIZE+PA_SIZE+(4+2)*8(sp)      /* pass PV (v0 == a0)                 */
258         addi    a3,sp,LA_SIZE+PA_SIZE+((4+6)*8)     /* pass Java SP                       */
259
260         b       L_asm_handle_exception_continue
261
262
263 asm_handle_exception:
264 L_asm_handle_exception:                 /* required for PIC code              */
265         addi    sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
266
267         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
268         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
269
270         addi    sp,sp,-(LA_SIZE+PA_SIZE+(4+6)*8)        /* allocate stack                     */
271         std     xptr,LA_SIZE+PA_SIZE+(4+0)*8(sp)        /* save exception pointer             */
272         std     pv,LA_SIZE+PA_SIZE+(4+2)*8(sp)          /* save data segment pointer          */
273         mflr    r0                                      /* save return address                */
274         std     r0,LA_SIZE+PA_SIZE+(4+3)*8(sp)          
275         li      t0, 1
276         std     t0, LA_SIZE+PA_SIZE+(4+4)*8(sp)         /* maybe-leaf flag */
277         
278         mr      a0,xptr                     /* pass exception pointer             */
279         mr      a1,xpc                      /* pass exception pc                  */
280         mr      a2,pv                       /* pass data segment pointer          */
281         addi    a3,sp,LA_SIZE+PA_SIZE+(ARG_CNT+TMP_CNT)*8+(4+6)*8
282
283
284 L_asm_handle_exception_continue:
285         bl      exceptions_handle_exception
286
287         mr.     v0,v0
288         beq     L_asm_handle_exception_not_catched
289
290         mr      xpc,v0                              /* move handlerpc into xpc            */
291         ld      xptr,LA_SIZE+PA_SIZE+(4+0)*8(sp)    /* restore exception pointer          */
292         ld      pv,LA_SIZE+PA_SIZE+(4+2)*8(sp)      /* restore data segment pointer       */
293         ld      r0,LA_SIZE+PA_SIZE+(4+3)*8(sp)      /* restore return address             */
294         mtlr    r0
295         ld      t0,LA_SIZE+PA_SIZE+(4+4)*8(sp)      /* get maybe-leaf flag                */
296         addi    sp,sp,LA_SIZE+PA_SIZE+(4+6)*8       /* free stack frame                   */
297
298         mr.     t0,t0
299         beq     L_asm_handle_exception_no_leaf
300
301         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
302         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
303
304         addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
305
306 L_asm_handle_exception_no_leaf:
307         mtctr   xpc                         /* jump to the handler                */
308         bctr
309
310 L_asm_handle_exception_not_catched:
311         ld      xptr,LA_SIZE+PA_SIZE+(4+0)*8(sp)        /* restore exception pointer          */
312         ld      pv,LA_SIZE+PA_SIZE+(4+2)*8(sp)          /* restore data segment pointer       */
313         ld      r0,LA_SIZE+PA_SIZE+(4+3)*8(sp)          /* restore return address             */
314         mtlr    r0
315         ld      t0,LA_SIZE+PA_SIZE+(4+4)*8(sp)          /* get maybe-leaf flag                */
316         addi    sp,sp,LA_SIZE+PA_SIZE+(4+6)*8           /* free stack frame                   */
317
318         mr.     t0,t0
319         beq     L_asm_handle_exception_no_leaf_stack
320
321         addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
322         li      t0,0                        /* clear the maybe-leaf flag          */
323
324 L_asm_handle_exception_no_leaf_stack:
325         lwz     t1,FrameSize(pv)            /* get frame size                     */
326         add     t1,sp,t1                    /* pointer to save area               */
327
328         lwz     t2,IsLeaf(pv)               /* is leaf procedure                  */
329         mr.     t2,t2
330         bne     L_asm_handle_exception_no_ra_restore
331
332         ld      r0,LA_LR_OFFSET(t1)         /* restore ra                         */
333         mtlr    r0
334
335 L_asm_handle_exception_no_ra_restore:
336         mflr    xpc                         /* the new xpc is ra                  */
337         mr      t4,xpc                      /* save RA */
338         lwz     t2,IntSave(pv)              /* t1 = saved int register count      */
339         bl      ex_int1
340 ex_int1:
341         mflr    t3                          /* t3 = current pc                    */
342         addi    t3,t3,(ex_int2-ex_int1)@l
343         slwi    t2,t2,2                     /* t2 = register count * 4            */
344         subf    t3,t2,t3                    /* t3 = IntSave - t2                  */
345         mtctr   t3
346         bctr
347
348         ld      s0,-9*8(t1)
349         ld      s1,-8*8(t1)
350         ld      s2,-7*8(t1)
351         ld      s3,-6*8(t1)
352         ld      s4,-5*8(t1)
353         ld      s5,-4*8(t1)
354         ld      s6,-3*8(t1)
355         ld      s7,-2*8(t1)
356         ld      s8,-1*8(t1)
357
358 ex_int2:
359         subf    t1,t2,t1                    /* t1 = t1 - register count * 4       */
360         lwz     t2,FltSave(pv)
361         bl      ex_flt1
362 ex_flt1:
363         mflr    t3
364         addi    t3,t3,(ex_flt2-ex_flt1)@l
365         slwi    t2,t2,2                     /* t2 = register count * 4            */
366         subf    t3,t2,t3                    /* t3 = FltSave - t2                  */
367         mtctr   t3
368         bctr
369
370         lfd     fs0,-10*8(t1)
371         lfd     fs1,-9*8(t1)
372         lfd     fs2,-8*8(t1)
373         lfd     fs3,-7*8(t1)
374         lfd     fs4,-6*8(t1)
375         lfd     fs5,-5*8(t1)
376         lfd     fs6,-4*8(t1)
377         lfd     fs7,-3*8(t1)
378         lfd     fs8,-2*8(t1)
379         lfd     fs9,-1*8(t1)
380
381 ex_flt2:
382         mtlr    t4                                   /* restore RA */
383         lwz     t1,FrameSize(pv)                     
384         add     sp,sp,t1                             /* unwind stack */
385         b       L_asm_handle_exception_stack_loop
386
387
388 /* asm_abstractmethoderror *****************************************************
389
390    Creates and throws an AbstractMethodError.
391
392 *******************************************************************************/
393
394 asm_abstractmethoderror:
395         mflr    r0
396         std     r0,LA_LR_OFFSET(sp)
397         stdu    sp,-LA_SIZE_ALIGNED(sp)     /* preserve linkage area              */
398         addi    a0,sp,LA_SIZE_ALIGNED       /* pass java sp                       */
399         mr      a1,r0                       /* pass exception address             */
400         bl      exceptions_asm_new_abstractmethoderror
401         ld      r0,LA_SIZE_ALIGNED+LA_LR_OFFSET(sp)
402         mtlr    r0                          /* restore return address             */
403         addi    sp,sp,LA_SIZE_ALIGNED
404
405         mr      xptr,v0                     /* get exception pointer              */
406         mr      xpc,r0                      /* we can't use r0 directly in addi   */
407         addi    xpc,xpc,-4                  /* exception address is ra - 4        */
408         b       L_asm_handle_nat_exception
409
410
411 /* asm_cacheflush **************************************************************
412         assumes 128 byte cache line size.
413         All registers used may be trashed for fun and profit.
414 *******************************************************************************/
415
416         .section ".opd","aw"
417         .align 3
418 asm_cacheflush:
419                 .quad   .asm_cacheflush,.TOC.@tocbase,0
420                 .previous
421                 .size asm_cacheflush, 24
422                 .type .asm_cacheflush,@function
423                 .globl .asm_cacheflush 
424 .asm_cacheflush:
425         /* construct the AND mask */
426         li      r6,   0xffffffffffff8000
427         ori     r6,r6,0x000000000000ff80
428
429         add     r4,r3,r4
430         and.    r3,r3,r6
431         addi    r4,r4,127
432         and.    r4,r4,r6
433         mr      r5,r3
434 1:
435         cmpld   r3,r4
436         bge     0f
437         dcbst   0,r3
438         addi    r3,r3,128
439         b       1b
440 0:
441         sync
442 1:
443         cmpld   r5,r4
444         bge     0f
445         icbi    0,r5
446         addi    r5,r5,128
447         b       1b
448 0:
449         sync
450         isync
451         blr
452
453
454 /* disable exec-stacks ********************************************************/
455
456 #if defined(__linux__) && defined(__ELF__)
457         .section .note.GNU-stack,"",%progbits
458 #endif
459
460
461 /*
462  * These are local overrides for various environment variables in Emacs.
463  * Please do not remove this and leave it at the end of the file, where
464  * Emacs will automagically detect them.
465  * ---------------------------------------------------------------------
466  * Local variables:
467  * mode: asm
468  * indent-tabs-mode: t
469  * c-basic-offset: 4
470  * tab-width: 4
471  * End:
472  * vim:noexpandtab:sw=4:ts=4:
473  */