5807491ecbac01e65242b9c65be0c10615d4faaa
[cacao.git] / src / vm / jit / x86_64 / asmpart.S
1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include "vm/jit/x86_64/arch.h"
29 #include "vm/jit/x86_64/md-abi.h"
30 #include "vm/jit/x86_64/md-asm.h"
31
32 #include "vm/jit/abi-asm.h"
33 #include "vm/jit/methodheader.h"
34
35
36         .text
37
38
39 /* export functions ***********************************************************/
40
41         .globl asm_vm_call_method
42         .globl asm_vm_call_method_int
43         .globl asm_vm_call_method_long
44         .globl asm_vm_call_method_float
45         .globl asm_vm_call_method_double
46         .globl asm_vm_call_method_exception_handler
47         .globl asm_vm_call_method_end
48
49         .globl asm_handle_exception
50         .globl asm_handle_nat_exception
51
52         .globl asm_abstractmethoderror
53
54         .globl asm_builtin_f2i
55         .globl asm_builtin_f2l
56         .globl asm_builtin_d2i
57         .globl asm_builtin_d2l
58
59         .globl asm_get_cycle_count
60
61
62 /********************* function asm_calljavafunction ***************************
63 *                                                                              *
64 *   This function calls a Java-method (which possibly needs compilation)       *
65 *   with up to 4 address parameters.                                           *
66 *                                                                              *
67 *   This functions calls the JIT-compiler which eventually translates the      *
68 *   method into machine code.                                                  *
69 *                                                                              *
70 *   C-prototype:                                                               *
71 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
72 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
73 *                                                                              *
74 *******************************************************************************/
75
76         .align  8
77
78         .long   0                           /* fltsave                            */
79         .long   0                           /* intsave                            */
80         .long   0                           /* isleaf                             */
81         .long   0                           /* frame size                         */
82         .quad   0                           /* codeinfo pointer                   */
83
84 asm_vm_call_method:
85 asm_vm_call_method_int:
86 asm_vm_call_method_long:
87 asm_vm_call_method_float:
88 asm_vm_call_method_double:
89         sub     $(7*8),sp                   /* keep stack 16-byte aligned         */
90         mov     %rbx,0*8(sp)                /* %rbx is not a callee saved in cacao*/
91         mov     s0,1*8(sp)
92         mov     s1,2*8(sp)
93         mov     s2,3*8(sp)
94         mov     s3,4*8(sp)
95         mov     s4,5*8(sp)
96
97         mov     a0,6*8(sp)                  /* store method PV                    */
98
99         mov     sp,s0                       /* save stack pointer                 */
100
101         mov     a1,t0                       /* address of data structure          */
102         mov     a2,itmp1                    /* number of stack arguments          */
103
104         mov     0*8(t0),a0
105         mov     1*8(t0),a1
106         mov     2*8(t0),a2
107         mov     3*8(t0),a3
108         mov     4*8(t0),a4
109         mov     5*8(t0),a5
110
111         movq    6*8(t0),fa0
112         movq    7*8(t0),fa1
113         movq    8*8(t0),fa2
114         movq    9*8(t0),fa3
115         movq    10*8(t0),fa4
116         movq    11*8(t0),fa5
117         movq    12*8(t0),fa6
118         movq    13*8(t0),fa7
119
120         cmp     $0,itmp1l
121         je      L_asm_vm_call_method_stack_copy_done
122
123         mov     itmp1,itmp2
124         add     $1,itmp2                    /* keep stack 16-byte aligned         */
125         and     $0xfffffffffffffffe,itmp2
126         shl     $3,itmp2                    /* calculate stack size               */
127         sub     itmp2,sp                    /* create stack frame                 */
128         mov     sp,itmp2                    /* temporary stack pointer            */
129
130 L_asm_vm_call_method_stack_copy_loop:
131         mov     14*8(t0),itmp3              /* load argument                      */
132         mov     itmp3,0(itmp2)              /* store argument on stack            */
133
134         sub     $1,itmp1l                   /* subtract 1 argument                */
135         add     $8,t0                       /* set address of next argument       */
136         add     $8,itmp2                    /* increase SP                        */
137
138         cmp     $0,itmp1l
139         jg      L_asm_vm_call_method_stack_copy_loop
140
141 L_asm_vm_call_method_stack_copy_done:
142         lea     (6*8-256)(s0),mptr          /* We subtract 256 to force the next  */
143                                             /* move instruction to have a 32-bit  */
144                                             /* offset.                            */
145
146         mov     (0*8+256)(mptr),itmp3       /* load PV                            */
147         call    *itmp3
148
149 L_asm_vm_call_method_return:
150         mov     s0,sp                       /* restore SP                         */
151
152         mov     0*8(sp),%rbx                /* restore callee saved registers     */
153         mov     1*8(sp),s0
154         mov     2*8(sp),s1
155         mov     3*8(sp),s2
156         mov     4*8(sp),s3
157         mov     5*8(sp),s4
158         add     $(7*8),sp                   /* free stack space                   */
159         ret
160                 
161 asm_vm_call_method_exception_handler:
162         mov     xptr,a0                     /* pass exception pointer             */
163         call    builtin_throw_exception@PLT
164         jmp     L_asm_vm_call_method_return
165
166 asm_vm_call_method_end:
167         nop
168
169
170 /* asm_handle_exception ********************************************************
171 *                                                                              *
172 *   This function handles an exception. It does not use the usual calling      *
173 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
174 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
175 *   the local exception table for a handler. If no one is found, it unwinds    *
176 *   stacks and continues searching the callers.                                *
177 *                                                                              *
178 *******************************************************************************/
179
180 asm_handle_nat_exception:
181         add     $8,sp                       /* clear return address of native stub*/
182                 
183 asm_handle_exception:
184 L_asm_handle_exception:                 /* required for PIC code              */
185         sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
186
187         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
188         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
189
190         mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
191         mov     $1,t0                       /* set maybe-leaf flag                */
192
193 L_asm_handle_exception_stack_loop:
194         sub     $(6*8),sp
195         mov     xptr,0*8(sp)                /* save exception pointer             */
196         mov     xpc,1*8(sp)                 /* save exception pc                  */
197         add     sp,a3                       /* calculate Java sp into a3...       */
198         add     $(6*8),a3
199         mov     a3,3*8(sp)                  /* ...and save it                     */
200         mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
201
202         mov     xpc,a0                      /* exception pc                       */
203         call    methodtree_find@PLT
204         mov     v0,2*8(sp)                  /* save data segment pointer          */
205         
206         mov     0*8(sp),a0                  /* pass exception pointer             */
207         mov     1*8(sp),a1                  /* pass exception pc                  */
208         mov     v0,a2                       /* pass data segment pointer          */
209         mov     3*8(sp),a3                  /* pass Java stack pointer            */
210         call    exceptions_handle_exception@PLT
211
212         test    v0,v0
213         jz      L_asm_handle_exception_not_catched
214
215         mov     v0,xpc                      /* move handlerpc into xpc            */
216         mov     0*8(sp),xptr                /* restore exception pointer          */
217         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
218         add     $(6*8),sp                   /* free stack frame                   */
219
220         test    t0,t0                       /* test for maybe-leaf flag           */
221         jz      L_asm_handle_exception_no_leaf
222
223         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
224         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
225
226         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
227
228 L_asm_handle_exception_no_leaf:
229         jmp     *xpc                        /* jump to the handler                */
230
231 L_asm_handle_exception_not_catched:
232         mov     0*8(sp),xptr                /* restore exception pointer          */
233         mov     2*8(sp),itmp3               /* restore data segment pointer       */
234         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
235         add     $(6*8),sp
236
237         test    t0,t0
238         jz      L_asm_handle_exception_no_leaf_stack
239
240         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
241         xor     t0,t0                       /* clear the isleaf flags             */
242
243 L_asm_handle_exception_no_leaf_stack:
244         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
245         add     sp,itmp2                    /* pointer to save area               */
246         
247         mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
248         test    a0l,a0l
249         je      noint
250         
251         cmp     $1,a0l
252         je      int1
253         cmp     $2,a0l
254         je      int2
255         cmp     $3,a0l
256         je      int3
257         cmp     $4,a0l
258         je      int4
259         
260         mov     -5*8(itmp2),s0
261 int4:   
262         mov     -4*8(itmp2),s1
263 int3:   
264         mov     -3*8(itmp2),s2
265 int2:   
266         mov     -2*8(itmp2),s3
267 int1:   
268         mov     -1*8(itmp2),s4
269
270         shl     $3,a0l                      /* multiply by 8 bytes                */
271         sub     a0,itmp2
272                 
273 noint:
274 #if 0
275         mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
276         test    a0l,a0l
277         je      noflt
278         
279         cmpl    $1,a0l
280         je      flt1
281         cmpl    $2,a0l
282         je      flt2
283         cmpl    $3,a0l
284         je      flt3
285         cmpl    $4,a0l
286         je      flt4
287
288         movq    -5*8(itmp2),%xmm11
289 flt4:   
290         movq    -4*8(itmp2),%xmm12
291 flt3:   
292         movq    -3*8(itmp2),%xmm13
293 flt2:   
294         movq    -2*8(itmp2),%xmm14
295 flt1:   
296         movq    -1*8(itmp2),%xmm15
297                 
298 noflt:
299 #endif
300         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
301         add     itmp2,sp                    /* unwind stack                       */
302
303                                             /* exception pointer is still set     */
304         pop     xpc                         /* the new xpc is return address      */
305         sub     $3,xpc                      /* subtract 3 bytes for call          */
306
307         xor     a3,a3                       /* prepare a3 for handle_exception    */
308         
309         jmp             L_asm_handle_exception_stack_loop
310
311
312 /* asm_abstractmethoderror *****************************************************
313
314    Creates and throws an AbstractMethodError.
315
316 *******************************************************************************/
317
318 asm_abstractmethoderror:
319         mov     sp,a0                       /* pass java sp                       */
320         add     $1*8,a0
321         mov     0*8(sp),a1                  /* pass exception address             */
322         sub     $3,a1
323         call    exceptions_asm_new_abstractmethoderror@PLT
324                                             /* exception pointer is return value  */
325         pop     xpc                         /* get exception address              */
326         sub     $3,xpc                      /* exception address is ra - 3        */
327         jmp     L_asm_handle_exception
328
329
330 /* asm_builtin_x2x *************************************************************
331 *                                                                              *
332 *   Wrapper functions for float to int corner cases                            *
333 *                                                                              *
334 *******************************************************************************/
335
336 asm_builtin_f2i:
337         sub     $(ARG_CNT*8),sp
338         
339         SAVE_ARGUMENT_REGISTERS(0)
340         
341         movq    ftmp1,fa0
342         call    builtin_f2i@PLT
343         
344         RESTORE_ARGUMENT_REGISTERS(0)
345         
346         add     $(ARG_CNT*8),sp
347         ret
348
349
350 asm_builtin_f2l:
351         sub     $(ARG_CNT*8),sp
352         
353         SAVE_ARGUMENT_REGISTERS(0)
354         
355         movq    ftmp1,fa0
356         call    builtin_f2l@PLT
357         
358         RESTORE_ARGUMENT_REGISTERS(0)
359         
360         add     $(ARG_CNT*8),sp
361         ret
362
363
364 asm_builtin_d2i:
365         sub     $(ARG_CNT*8),sp
366         
367         SAVE_ARGUMENT_REGISTERS(0)
368         
369         movq    ftmp1,fa0
370         call    builtin_d2i@PLT
371         
372         RESTORE_ARGUMENT_REGISTERS(0)
373         
374         add     $(ARG_CNT*8),sp
375         ret
376
377
378 asm_builtin_d2l:
379         sub     $(ARG_CNT*8),sp
380         
381         SAVE_ARGUMENT_REGISTERS(0)
382         
383         movq    ftmp1,fa0
384         call    builtin_d2l@PLT
385         
386         RESTORE_ARGUMENT_REGISTERS(0)
387         
388         add     $(ARG_CNT*8),sp
389         ret
390
391
392 /* asm_get_cycle_count *********************************************************
393
394    Get the current time-stamp counter from the CPU.
395
396 *******************************************************************************/
397
398 asm_get_cycle_count:
399         rdtsc
400         shl $0x20, %rdx
401         mov %eax, %eax
402         or %rdx, %rax
403         ret
404
405
406 /* disable exec-stacks ********************************************************/
407
408 #if defined(__linux__) && defined(__ELF__)
409         .section .note.GNU-stack,"",%progbits
410 #endif
411
412
413 /*
414  * These are local overrides for various environment variables in Emacs.
415  * Please do not remove this and leave it at the end of the file, where
416  * Emacs will automagically detect them.
417  * ---------------------------------------------------------------------
418  * Local variables:
419  * mode: asm
420  * indent-tabs-mode: t
421  * c-basic-offset: 4
422  * tab-width: 4
423  * End:
424  * vim:noexpandtab:sw=4:ts=4:
425  */