* src/vm/jit/i386/asmpart.S (asm_replacement_in, asm_replacement_out): Removed
[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 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 */
26
27
28 #include "config.h"
29
30 #include "vm/jit/x86_64/arch.h"
31 #include "vm/jit/x86_64/md-abi.h"
32 #include "vm/jit/x86_64/md-asm.h"
33
34 #include "vm/jit/abi-asm.h"
35 #include "vm/jit/methodheader.h"
36
37
38         .text
39
40
41 /* export functions ***********************************************************/
42
43         .globl asm_vm_call_method
44         .globl asm_vm_call_method_int
45         .globl asm_vm_call_method_long
46         .globl asm_vm_call_method_float
47         .globl asm_vm_call_method_double
48         .globl asm_vm_call_method_exception_handler
49         .globl asm_vm_call_method_end
50
51         .globl asm_call_jit_compiler
52
53         .globl asm_handle_exception
54         .globl asm_handle_nat_exception
55
56         .globl asm_abstractmethoderror
57
58         .globl asm_builtin_f2i
59         .globl asm_builtin_f2l
60         .globl asm_builtin_d2i
61         .globl asm_builtin_d2l
62
63         .globl asm_compare_and_swap
64         .globl asm_memory_barrier
65
66
67 /********************* function asm_calljavafunction ***************************
68 *                                                                              *
69 *   This function calls a Java-method (which possibly needs compilation)       *
70 *   with up to 4 address parameters.                                           *
71 *                                                                              *
72 *   This functions calls the JIT-compiler which eventually translates the      *
73 *   method into machine code.                                                  *
74 *                                                                              *
75 *   C-prototype:                                                               *
76 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
77 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
78 *                                                                              *
79 *******************************************************************************/
80
81         .align  8
82
83         .quad   0                           /* catch type all                     */
84         .quad   0                           /* handler pc                         */
85         .quad   0                           /* end pc                             */
86         .quad   0                           /* start pc                           */
87         .long   1                           /* extable size                       */
88         .long   0                           /* ALIGNMENT PADDING                  */
89         .quad   0                           /* line number table  start           */
90         .quad   0                           /* line number table  size            */
91         .long   0                           /* ALIGNMENT PADDING                  */
92         .long   0                           /* fltsave                            */
93         .long   0                           /* intsave                            */
94         .long   0                           /* isleaf                             */
95         .long   0                           /* IsSync                             */
96         .long   0                           /* frame size                         */
97         .quad   0                           /* codeinfo pointer                   */
98
99 asm_vm_call_method:
100 asm_vm_call_method_int:
101 asm_vm_call_method_long:
102 asm_vm_call_method_float:
103 asm_vm_call_method_double:
104         sub     $(7*8),sp                   /* keep stack 16-byte aligned         */
105         mov     %rbx,0*8(sp)                /* %rbx is not a callee saved in cacao*/
106         mov     s0,1*8(sp)
107         mov     s1,2*8(sp)
108         mov     s2,3*8(sp)
109         mov     s3,4*8(sp)
110         mov     s4,5*8(sp)
111
112         mov     a0,6*8(sp)                  /* store method PV                    */
113
114         mov     sp,s0                       /* save stack pointer                 */
115
116         mov     a1,t0                       /* address of data structure          */
117         mov     a2,itmp1                    /* number of stack arguments          */
118
119         mov     0*8(t0),a0
120         mov     1*8(t0),a1
121         mov     2*8(t0),a2
122         mov     3*8(t0),a3
123         mov     4*8(t0),a4
124         mov     5*8(t0),a5
125
126         movq    6*8(t0),fa0
127         movq    7*8(t0),fa1
128         movq    8*8(t0),fa2
129         movq    9*8(t0),fa3
130         movq    10*8(t0),fa4
131         movq    11*8(t0),fa5
132         movq    12*8(t0),fa6
133         movq    13*8(t0),fa7
134
135         cmp     $0,itmp1l
136         je      L_asm_vm_call_method_stack_copy_done
137
138         mov     itmp1,itmp2
139         add     $1,itmp2                    /* keep stack 16-byte aligned         */
140         and     $0xfffffffffffffffe,itmp2
141         shl     $3,itmp2                    /* calculate stack size               */
142         sub     itmp2,sp                    /* create stack frame                 */
143         mov     sp,itmp2                    /* temporary stack pointer            */
144
145 L_asm_vm_call_method_stack_copy_loop:
146         mov     14*8(t0),itmp3              /* load argument                      */
147         mov     itmp3,0(itmp2)              /* store argument on stack            */
148
149         sub     $1,itmp1l                   /* subtract 1 argument                */
150         add     $8,t0                       /* set address of next argument       */
151         add     $8,itmp2                    /* increase SP                        */
152
153         cmp     $0,itmp1l
154         jg      L_asm_vm_call_method_stack_copy_loop
155
156 L_asm_vm_call_method_stack_copy_done:
157         lea     (6*8-256)(s0),mptr          /* We subtract 256 to force the next  */
158                                             /* move instruction to have a 32-bit  */
159                                             /* offset.                            */
160
161         mov     (0*8+256)(mptr),itmp3       /* load PV                            */
162         call    *itmp3
163
164         mov     s0,sp                       /* restore SP                         */
165
166 L_asm_vm_call_method_return:
167         mov     0*8(sp),%rbx                /* restore callee saved registers     */
168         mov     1*8(sp),s0
169         mov     2*8(sp),s1
170         mov     3*8(sp),s2
171         mov     4*8(sp),s3
172         mov     5*8(sp),s4
173         add     $(7*8),sp                   /* free stack space                   */
174         ret
175                 
176 asm_vm_call_method_exception_handler:
177         mov     xptr,a0                     /* pass exception pointer             */
178         call    builtin_throw_exception@PLT
179         jmp     L_asm_vm_call_method_return
180
181 asm_vm_call_method_end:
182         nop
183
184
185 /****************** function asm_call_jit_compiler *****************************
186 *                                                                              *
187 *   invokes the compiler for untranslated JavaVM methods.                      *
188 *                                                                              *
189 *   Register R0 contains a pointer to the method info structure (prepared      *
190 *   by createcompilerstub). Using the return address in R26 and the            *
191 *   offset in the LDA instruction or using the value in methodptr R28 the      *
192 *   patching address for storing the method address can be computed:           *
193 *                                                                              *
194 *   method address was either loaded using                                     *
195 *                                                                              *
196 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
197 *   i386_call_reg(REG_ITMP2)                                                   *
198 *                                                                              *
199 *   or                                                                         *
200 *                                                                              *
201 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
202 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
203 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
204 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
205 *   i386_call_reg(REG_ITMP1)                                                   *
206 *                                                                              *
207 *   in the static case the method pointer can be computed using the            *
208 *   return address and the lda function following the jmp instruction          *
209 *                                                                              *
210 *******************************************************************************/
211
212 asm_call_jit_compiler:
213 L_asm_call_jit_compiler:                /* required for PIC code              */
214         sub     $(ARG_CNT+1)*8,sp           /* +1: keep stack 16-byte aligned     */
215
216         SAVE_ARGUMENT_REGISTERS(0)
217
218         mov     itmp1,a0                    /* pass methodinfo pointer            */
219         mov     mptr,a1                     /* pass method pointer                */
220         mov     sp,a2                       /* pass java sp                       */
221         add     $(1+ARG_CNT+1)*8,a2
222         mov     (ARG_CNT+1)*8(sp),a3        /* pass ra to java function           */
223         call    jit_asm_compile@PLT
224
225         RESTORE_ARGUMENT_REGISTERS(0)
226
227         add     $(ARG_CNT+1)*8,sp           /* remove stack frame                 */
228
229         test    v0,v0                       /* check for exception                */
230         je      L_asm_call_jit_compiler_exception
231
232         jmp     *v0                         /* ...and now call the new method     */
233
234 L_asm_call_jit_compiler_exception:
235         call    exceptions_get_and_clear_exception@PLT
236         pop     xpc                         /* delete return address              */
237         sub     $3,xpc                      /* faulting address is ra - 3         */
238         jmp     L_asm_handle_exception
239
240
241 /* asm_handle_exception ********************************************************
242 *                                                                              *
243 *   This function handles an exception. It does not use the usual calling      *
244 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
245 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
246 *   the local exception table for a handler. If no one is found, it unwinds    *
247 *   stacks and continues searching the callers.                                *
248 *                                                                              *
249 *******************************************************************************/
250
251 asm_handle_nat_exception:
252         add     $8,sp                       /* clear return address of native stub*/
253                 
254 asm_handle_exception:
255 L_asm_handle_exception:                 /* required for PIC code              */
256         sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
257
258         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
259         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
260
261         mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
262         mov     $1,t0                       /* set maybe-leaf flag                */
263
264 L_asm_handle_exception_stack_loop:
265         sub     $(6*8),sp
266         mov     xptr,0*8(sp)                /* save exception pointer             */
267         mov     xpc,1*8(sp)                 /* save exception pc                  */
268         add     sp,a3                       /* calculate Java sp into a3...       */
269         add     $(6*8),a3
270         mov     a3,3*8(sp)                  /* ...and save it                     */
271         mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
272
273         mov     xpc,a0                      /* exception pc                       */
274         call    codegen_get_pv_from_pc@PLT
275         mov     v0,2*8(sp)                  /* save data segment pointer          */
276         
277         mov     0*8(sp),a0                  /* pass exception pointer             */
278         mov     1*8(sp),a1                  /* pass exception pc                  */
279         mov     v0,a2                       /* pass data segment pointer          */
280         mov     3*8(sp),a3                  /* pass Java stack pointer            */
281         call    exceptions_handle_exception@PLT
282
283         test    v0,v0
284         jz      L_asm_handle_exception_not_catched
285
286         mov     v0,xpc                      /* move handlerpc into xpc            */
287         mov     0*8(sp),xptr                /* restore exception pointer          */
288         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
289         add     $(6*8),sp                   /* free stack frame                   */
290
291         test    t0,t0                       /* test for maybe-leaf flag           */
292         jz      L_asm_handle_exception_no_leaf
293
294         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
295         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
296
297         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
298
299 L_asm_handle_exception_no_leaf:
300         jmp     *xpc                        /* jump to the handler                */
301
302 L_asm_handle_exception_not_catched:
303         mov     0*8(sp),xptr                /* restore exception pointer          */
304         mov     2*8(sp),itmp3               /* restore data segment pointer       */
305         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
306         add     $(6*8),sp
307
308         test    t0,t0
309         jz      L_asm_handle_exception_no_leaf_stack
310
311         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
312         xor     t0,t0                       /* clear the isleaf flags             */
313
314 L_asm_handle_exception_no_leaf_stack:
315         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
316         add     sp,itmp2                    /* pointer to save area               */
317         
318         mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
319         test    a0l,a0l
320         je      noint
321         
322         cmp     $1,a0l
323         je      int1
324         cmp     $2,a0l
325         je      int2
326         cmp     $3,a0l
327         je      int3
328         cmp     $4,a0l
329         je      int4
330         
331         mov     -5*8(itmp2),s0
332 int4:   
333         mov     -4*8(itmp2),s1
334 int3:   
335         mov     -3*8(itmp2),s2
336 int2:   
337         mov     -2*8(itmp2),s3
338 int1:   
339         mov     -1*8(itmp2),s4
340
341         shl     $3,a0l                      /* multiply by 8 bytes                */
342         sub     a0,itmp2
343                 
344 noint:
345 #if 0
346         mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
347         test    a0l,a0l
348         je      noflt
349         
350         cmpl    $1,a0l
351         je      flt1
352         cmpl    $2,a0l
353         je      flt2
354         cmpl    $3,a0l
355         je      flt3
356         cmpl    $4,a0l
357         je      flt4
358
359         movq    -5*8(itmp2),%xmm11
360 flt4:   
361         movq    -4*8(itmp2),%xmm12
362 flt3:   
363         movq    -3*8(itmp2),%xmm13
364 flt2:   
365         movq    -2*8(itmp2),%xmm14
366 flt1:   
367         movq    -1*8(itmp2),%xmm15
368                 
369 noflt:
370 #endif
371         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
372         add     itmp2,sp                    /* unwind stack                       */
373
374                                             /* exception pointer is still set     */
375         pop     xpc                         /* the new xpc is return address      */
376         sub     $3,xpc                      /* subtract 3 bytes for call          */
377
378         xor     a3,a3                       /* prepare a3 for handle_exception    */
379         
380         jmp             L_asm_handle_exception_stack_loop
381
382
383 /* asm_abstractmethoderror *****************************************************
384
385    Creates and throws an AbstractMethodError.
386
387 *******************************************************************************/
388
389 asm_abstractmethoderror:
390         mov     sp,a0                       /* pass java sp                       */
391         add     $1*8,a0
392         mov     0*8(sp),a1                  /* pass exception address             */
393         sub     $3,a1
394         call    exceptions_asm_new_abstractmethoderror@PLT
395                                             /* exception pointer is return value  */
396         pop     xpc                         /* get exception address              */
397         sub     $3,xpc                      /* exception address is ra - 3        */
398         jmp     L_asm_handle_exception
399
400
401 /* asm_builtin_x2x *************************************************************
402 *                                                                              *
403 *   Wrapper functions for float to int corner cases                            *
404 *                                                                              *
405 *******************************************************************************/
406
407 asm_builtin_f2i:
408         sub     $(ARG_CNT*8),sp
409         
410         SAVE_ARGUMENT_REGISTERS(0)
411         
412         movq    ftmp1,fa0
413         call    builtin_f2i@PLT
414         
415         RESTORE_ARGUMENT_REGISTERS(0)
416         
417         add     $(ARG_CNT*8),sp
418         ret
419
420
421 asm_builtin_f2l:
422         sub     $(ARG_CNT*8),sp
423         
424         SAVE_ARGUMENT_REGISTERS(0)
425         
426         movq    ftmp1,fa0
427         call    builtin_f2l@PLT
428         
429         RESTORE_ARGUMENT_REGISTERS(0)
430         
431         add     $(ARG_CNT*8),sp
432         ret
433
434
435 asm_builtin_d2i:
436         sub     $(ARG_CNT*8),sp
437         
438         SAVE_ARGUMENT_REGISTERS(0)
439         
440         movq    ftmp1,fa0
441         call    builtin_d2i@PLT
442         
443         RESTORE_ARGUMENT_REGISTERS(0)
444         
445         add     $(ARG_CNT*8),sp
446         ret
447
448
449 asm_builtin_d2l:
450         sub     $(ARG_CNT*8),sp
451         
452         SAVE_ARGUMENT_REGISTERS(0)
453         
454         movq    ftmp1,fa0
455         call    builtin_d2l@PLT
456         
457         RESTORE_ARGUMENT_REGISTERS(0)
458         
459         add     $(ARG_CNT*8),sp
460         ret
461
462
463 /* asm_compare_and_swap ********************************************************
464
465    Does an atomic compare and swap.  Required for the lock
466    implementation.
467
468 *******************************************************************************/
469
470 asm_compare_and_swap:
471         mov     a1,v0                       /* v0 is %rax                         */
472         lock cmpxchg a2,(a0)
473         ret
474
475
476 /* asm_memory_barrier **********************************************************
477
478    A memory barrier for the Java Memory Model.
479
480 *******************************************************************************/
481
482 asm_memory_barrier:
483         mfence
484         ret
485
486
487 /* disable exec-stacks ********************************************************/
488
489 #if defined(__linux__) && defined(__ELF__)
490         .section .note.GNU-stack,"",%progbits
491 #endif
492
493
494 /*
495  * These are local overrides for various environment variables in Emacs.
496  * Please do not remove this and leave it at the end of the file, where
497  * Emacs will automagically detect them.
498  * ---------------------------------------------------------------------
499  * Local variables:
500  * mode: asm
501  * indent-tabs-mode: t
502  * c-basic-offset: 4
503  * tab-width: 4
504  * End:
505  * vim:noexpandtab:sw=4:ts=4:
506  */