1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
3 Copyright (C) 1996-2005, 2006 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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
33 $Id: asmpart.S 4530 2006-02-21 09:11:53Z twisti $
43 #include "vm/jit/abi.h"
44 #include "vm/jit/x86_64/arch.h"
45 #include "vm/jit/x86_64/offsets.h"
47 #include "vm/jit/methodheader.h"
53 /* exported functions and variables *******************************************/
55 .globl asm_calljavafunction
56 .type asm_calljavafunction, @function
58 .globl asm_calljavafunction_int
60 .globl asm_calljavafunction2
61 .globl asm_calljavafunction2int
62 .globl asm_calljavafunction2long
63 .globl asm_calljavafunction2float
64 .globl asm_calljavafunction2double
66 .globl asm_call_jit_compiler
67 .globl asm_handle_exception
68 .globl asm_handle_nat_exception
70 .globl asm_wrapper_patcher
72 .globl asm_builtin_f2i
73 .globl asm_builtin_f2l
74 .globl asm_builtin_d2i
75 .globl asm_builtin_d2l
77 .globl asm_perform_threadswitch
78 .globl asm_initialize_thread_stack
79 .globl asm_switchstackandcall
80 .globl asm_criticalsections
81 .globl asm_getclassvalues_atomic
84 /********************* function asm_calljavafunction ***************************
86 * This function calls a Java-method (which possibly needs compilation) *
87 * with up to 4 address parameters. *
89 * This functions calls the JIT-compiler which eventually translates the *
90 * method into machine code. *
93 * javaobject_header *asm_calljavamethod (methodinfo *m, *
94 * void *arg1, void *arg2, void *arg3, void *arg4); *
96 *******************************************************************************/
100 .quad 0 /* catch type all */
101 .quad calljava_xhandler /* handler pc */
102 .quad calljava_xhandler /* end pc */
103 .quad L_asm_calljavafunction /* start pc */
104 .long 1 /* extable size */
106 .quad 0 /* line number table start */
107 .quad 0 /* line number table size */
109 .long 0 /* fltsave */
110 .long 0 /* intsave */
113 .long 8 /* frame size */
114 .quad 0 /* method pointer (pointer to name) */
116 asm_calljavafunction:
117 asm_calljavafunction_int:
118 L_asm_calljavafunction: /* required for PIC code */
119 sub $(3*8),sp /* keep stack 16-byte aligned */
121 mov %rbx,1*8(sp) /* %rbx is not a callee saved in CACAO*/
122 mov a0,itmp1 /* move function pointer to itmp1 */
123 /* compilerstub uses this */
125 mov a1,a0 /* pass remaining parameters */
130 lea L_asm_call_jit_compiler(%rip),itmp3
131 call *itmp3 /* call JIT compiler */
133 L_asm_calljavafunction_return:
135 mov 1*8(sp),%rbx /* %rbx is not a callee saved in CACAO*/
136 add $(3*8),sp /* free stack space */
140 mov xptr,a0 /* pass exception pointer */
141 call builtin_throw_exception@PLT
142 xor v0,v0 /* return NULL */
143 jmp L_asm_calljavafunction_return
146 /********************* function asm_calljavafunction ***************************
148 * This function calls a Java-method (which possibly needs compilation) *
149 * with up to 4 address parameters. *
151 * This functions calls the JIT-compiler which eventually translates the *
152 * method into machine code. *
155 * javaobject_header *asm_calljavamethod (methodinfo *m, *
156 * void *arg1, void *arg2, void *arg3, void *arg4); *
158 *******************************************************************************/
162 .quad 0 /* catch type all */
163 .quad calljava_xhandler2 /* handler pc */
164 .quad calljava_xhandler2 /* end pc */
165 .quad L_asm_calljavafunction2 /* start pc */
166 .long 1 /* extable size */
168 .quad 0 /* line number table start */
169 .quad 0 /* line number table size */
171 .long 0 /* fltsave */
172 .long 0 /* intsave */
175 .long 24 /* frame size */
176 .quad 0 /* method pointer (pointer to name) */
178 asm_calljavafunction2:
179 asm_calljavafunction2int:
180 asm_calljavafunction2long:
181 asm_calljavafunction2float:
182 asm_calljavafunction2double:
183 L_asm_calljavafunction2: /* required for PIC code */
184 sub $(7*8),sp /* keep stack 16-byte aligned */
185 mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/
192 mov a0,itmp1 /* move method pointer for compiler */
193 xor %rbp,%rbp /* set argument stack frame to zero */
195 test a1,a1 /* maybe we have no args... */
198 mov a1,itmp3 /* arg count */
199 mov a3,itmp2 /* pointer to arg block */
201 mov itmp2,%r14 /* save argument block pointer */
202 mov itmp3,%r15 /* save argument count */
204 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
205 add $1,itmp3 /* initialize argument count */
206 xor %r12,%r12 /* initialize integer argument counter*/
207 xor %r13,%r13 /* initialize float argument counter */
210 add $sizejniblock,itmp2 /* goto next argument block */
211 dec itmp3 /* argument count - 1 */
212 jz L_register_copy_done
213 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
214 jnz L_register_handle_float /* yes, handle it */
216 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
217 je L_register_copy /* register? yes, next loop */
219 lea jumptable_integer(%rip),%rbp
220 mov 0(%rbp,%r12,8),%rbx
221 inc %r12 /* integer argument counter + 1 */
224 L_register_handle_float:
225 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
226 je L_register_copy /* register? yes, next loop */
228 lea jumptable_float(%rip),%rbp
229 mov 0(%rbp,%r13,8),%rbx
230 inc %r13 /* float argument counter + 1 */
233 L_register_copy_done:
234 mov %r15,%rbp /* calculate remaining arguments */
235 sub %r12,%rbp /* - integer arguments in registers */
236 sub %r13,%rbp /* - float arguments in registers */
237 jle L_copy_done /* are all assigned to registers? */
239 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
240 shl $3,%rbp /* calculate stack size */
241 sub %rbp,sp /* stack frame for arguments */
242 mov sp,%rbx /* use %rbx as temp sp */
244 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
245 add $1,%r15 /* initialize argument count */
248 add $sizejniblock,%r14 /* goto next argument block */
249 dec %r15 /* are there any arguments left? */
250 jz L_copy_done /* no test needed after dec */
252 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
253 jnz L_stack_handle_float
254 dec %r12 /* arguments assigned to registers */
255 jge L_stack_copy_loop
258 L_stack_handle_float:
259 dec %r13 /* arguments assigned to registers */
260 jge L_stack_copy_loop
263 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
265 add $8,%rbx /* increase sp to next argument */
266 jmp L_stack_copy_loop
269 /* itmp1 still contains method pointer*/
270 lea L_asm_call_jit_compiler(%rip),itmp3
271 call *itmp3 /* call JIT compiler */
273 add bp,sp /* remove argument stack frame if any */
275 L_asm_calljavafunction2_return:
276 mov 0*8(sp),%rbx /* restore callee saved registers */
282 add $(7*8),sp /* free stack space */
286 mov xptr,a0 /* pass exception pointer */
287 call builtin_throw_exception@PLT
288 xor v0,v0 /* return NULL */
289 jmp L_asm_calljavafunction2_return
301 mov offjniitem(itmp2),a0
304 mov offjniitem(itmp2),a1
307 mov offjniitem(itmp2),a2
310 mov offjniitem(itmp2),a3
313 mov offjniitem(itmp2),a4
316 mov offjniitem(itmp2),a5
331 movq offjniitem(itmp2),fa0
334 movq offjniitem(itmp2),fa1
337 movq offjniitem(itmp2),fa2
340 movq offjniitem(itmp2),fa3
343 movq offjniitem(itmp2),fa4
346 movq offjniitem(itmp2),fa5
349 movq offjniitem(itmp2),fa6
352 movq offjniitem(itmp2),fa7
356 /****************** function asm_call_jit_compiler *****************************
358 * invokes the compiler for untranslated JavaVM methods. *
360 * Register R0 contains a pointer to the method info structure (prepared *
361 * by createcompilerstub). Using the return address in R26 and the *
362 * offset in the LDA instruction or using the value in methodptr R28 the *
363 * patching address for storing the method address can be computed: *
365 * method address was either loaded using *
367 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
368 * i386_call_reg(REG_ITMP2) *
372 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
373 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
374 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
375 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
376 * i386_call_reg(REG_ITMP1) *
378 * in the static case the method pointer can be computed using the *
379 * return address and the lda function following the jmp instruction *
381 *******************************************************************************/
383 asm_call_jit_compiler:
384 L_asm_call_jit_compiler: /* required for PIC code */
385 /* keep stack 16-byte aligned */
386 sub $((3+ARG_CNT)*8+sizestackframeinfo),sp
388 mov t0,0*8(sp) /* save register */
390 mov (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address */
391 mov -1(itmp3),%bl /* get function code */
392 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
393 jne L_not_static_special
395 sub $11,itmp3 /* calculate address of immediate */
396 jmp L_call_jit_compile
398 L_not_static_special:
399 cmp $0xd0,%bl /* called with `call *REG_ITMP1' */
400 jne L_not_virtual_interface
402 sub $7,itmp3 /* calculate address of offset */
403 mov (itmp3),itmp3l /* get offset (32-bit) */
404 add itmp2,itmp3 /* add base address to get method addr*/
405 jmp L_call_jit_compile
407 L_not_virtual_interface: /* a call from asm_calljavamethod */
411 mov 0*8(sp),t0 /* restore register */
412 mov itmp3,0*8(sp) /* save address for method pointer */
413 mov itmp1,1*8(sp) /* save method pointer */
415 SAVE_ARGUMENT_REGISTERS(3)
417 mov sp,a0 /* create stackframe info */
418 add $((3+ARG_CNT)*8),a0 /* pass sfi */
419 xor a1,a1 /* if pv is NULL, use findmethod */
420 mov sp,a2 /* pass java sp */
421 add $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
422 /* pass ra to java function */
423 mov ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
424 mov a3,a4 /* xpc is equal to ra */
425 call stacktrace_create_extern_stackframeinfo@PLT
427 mov 1*8(sp),a0 /* pass method pointer */
429 mov v0,1*8(sp) /* save return value */
431 mov sp,a0 /* remove stackframe info */
432 add $((3+ARG_CNT)*8),a0 /* pass sfi */
433 call stacktrace_remove_stackframeinfo@PLT
435 mov 0*8(sp),itmp3 /* restore address for method pointer */
436 mov 1*8(sp),v0 /* restore return value */
438 RESTORE_ARGUMENT_REGISTERS(3)
440 add $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame */
442 test v0,v0 /* check for exception */
443 je L_asm_call_jit_compiler_exception
445 test itmp3,itmp3 /* is address == 0 (asm_calljavamethod*/
448 mov v0,(itmp3) /* and now save the new pointer */
451 jmp *v0 /* ...and now call the new method */
453 L_asm_call_jit_compiler_exception:
454 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
455 call builtin_asm_get_exceptionptrptr@PLT
456 mov v0,itmp2 /* v0 == xptr */
458 lea _no_threads_exceptionptr,itmp2
460 mov (itmp2),xptr /* get the exception pointer */
461 movl $0,(itmp2) /* clear exception pointer */
463 pop xpc /* delete return address */
464 sub $5,xpc /* faulting address is ra - 5 */
465 jmp L_asm_handle_exception
468 /* asm_handle_exception ********************************************************
470 * This function handles an exception. It does not use the usual calling *
471 * conventions. The exception pointer is passed in REG_ITMP1 and the *
472 * pc from the exception raising position is passed in REG_ITMP2. It searches *
473 * the local exception table for a handler. If no one is found, it unwinds *
474 * stacks and continues searching the callers. *
476 *******************************************************************************/
478 asm_handle_nat_exception:
479 add $8,sp /* clear return address of native stub*/
481 asm_handle_exception:
482 L_asm_handle_exception: /* required for PIC code */
483 sub $((ARG_CNT+TMP_CNT)*8),sp /* create maybe-leaf stackframe */
485 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
486 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
488 mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */
489 mov $1,t0 /* set maybe-leaf flag */
491 L_asm_handle_exception_stack_loop:
493 mov xptr,0*8(sp) /* save exception pointer */
494 mov xpc,1*8(sp) /* save exception pc */
495 add sp,a3 /* calculate Java sp into a3... */
497 mov a3,3*8(sp) /* ...and save it */
498 mov t0,4*8(sp) /* save maybe-leaf flag */
500 mov xpc,a0 /* exception pc */
501 call codegen_findmethod@PLT
502 mov v0,2*8(sp) /* save data segment pointer */
504 mov 0*8(sp),a0 /* pass exception pointer */
505 mov 1*8(sp),a1 /* pass exception pc */
506 mov v0,a2 /* pass data segment pointer */
507 mov 3*8(sp),a3 /* pass Java stack pointer */
508 call exceptions_handle_exception@PLT
511 jz L_asm_handle_exception_not_catched
513 mov v0,xpc /* move handlerpc into xpc */
514 mov 0*8(sp),xptr /* restore exception pointer */
515 mov 4*8(sp),t0 /* get maybe-leaf flag */
516 add $(6*8),sp /* free stack frame */
518 test t0,t0 /* test for maybe-leaf flag */
519 jz L_asm_handle_exception_no_leaf
521 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
522 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
524 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
526 L_asm_handle_exception_no_leaf:
527 jmp *xpc /* jump to the handler */
529 L_asm_handle_exception_not_catched:
530 mov 0*8(sp),xptr /* restore exception pointer */
531 mov 2*8(sp),itmp3 /* restore data segment pointer */
532 mov 4*8(sp),t0 /* get maybe-leaf flag */
536 jz L_asm_handle_exception_no_leaf_stack
538 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
539 xor t0,t0 /* clear the isleaf flags */
541 L_asm_handle_exception_no_leaf_stack:
542 mov FrameSize(itmp3),itmp2l /* get frame size */
543 add sp,itmp2 /* pointer to save area */
545 mov IntSave(itmp3),a0l /* a0l = saved int register count */
568 shl $3,a0l /* multiply by 8 bytes */
573 mov FltSave(itmp3),a0l /* a0l = saved flt register count */
586 movq -5*8(itmp2),%xmm11
588 movq -4*8(itmp2),%xmm12
590 movq -3*8(itmp2),%xmm13
592 movq -2*8(itmp2),%xmm14
594 movq -1*8(itmp2),%xmm15
598 mov FrameSize(itmp3),itmp2l /* get frame size */
599 add itmp2,sp /* unwind stack */
601 /* exception pointer is still set */
602 pop xpc /* the new xpc is return address */
603 sub $3,xpc /* subtract 3 bytes for call */
605 xor a3,a3 /* prepare a3 for handle_exception */
607 jmp L_asm_handle_exception_stack_loop
610 /* asm_wrapper_patcher *********************************************************
616 32 pointer to virtual java_objectheader
617 24 machine code (which is patched back later)
618 16 unresolved class/method/field reference
619 8 data segment displacement from load instructions
620 0 pointer to patcher function
623 *******************************************************************************/
626 push bp /* save base pointer */
627 mov sp,bp /* move actual sp to bp */
628 sub $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
629 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
630 /* leaf functions) */
632 SAVE_ARGUMENT_REGISTERS(3)
633 SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
635 mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
636 mov itmp2,1*8(sp) /* can be used by some instructions */
638 mov sp,a0 /* create stackframe info */
639 add $((3+ARG_CNT+TMP_CNT)*8),a0
640 xor a1,a1 /* if pv is NULL, use findmethod */
641 mov bp,a2 /* pass java sp */
643 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
644 mov a3,a4 /* xpc is equal to ra */
645 call stacktrace_create_extern_stackframeinfo@PLT
647 mov bp,a0 /* pass stack pointer */
648 add $((1+1)*8),a0 /* skip function pointer */
649 mov 1*8(bp),itmp3 /* get function pointer */
650 call *itmp3 /* call the patcher function */
651 mov v0,2*8(sp) /* save return value */
653 mov sp,a0 /* remove stackframe info */
654 add $((3+ARG_CNT+TMP_CNT)*8),a0
655 call stacktrace_remove_stackframeinfo@PLT
657 RESTORE_ARGUMENT_REGISTERS(3)
658 RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
660 mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
661 mov 1*8(sp),itmp2 /* can be used by some instructions */
662 mov 2*8(sp),itmp3 /* restore return value */
664 mov bp,sp /* restore original sp */
665 pop bp /* restore bp */
666 add $(5*8),sp /* remove patcher stackframe, keep ra */
668 test itmp3,itmp3 /* exception thrown? */
669 jz L_asm_wrapper_patcher_exception
670 ret /* call new patched code */
672 L_asm_wrapper_patcher_exception:
673 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
674 call builtin_asm_get_exceptionptrptr@PLT
675 mov v0,itmp2 /* v0 == xptr */
677 lea _no_threads_exceptionptr,itmp2
679 mov (itmp2),xptr /* get the exception pointer */
680 movl $0,(itmp2) /* clear exception pointer */
682 pop xpc /* get and remove return address */
683 jmp L_asm_handle_exception
686 /* asm_builtin_x2x *************************************************************
688 * Wrapper functions for float to int corner cases *
690 *******************************************************************************/
695 SAVE_ARGUMENT_REGISTERS(0)
700 RESTORE_ARGUMENT_REGISTERS(0)
709 SAVE_ARGUMENT_REGISTERS(0)
714 RESTORE_ARGUMENT_REGISTERS(0)
723 SAVE_ARGUMENT_REGISTERS(0)
728 RESTORE_ARGUMENT_REGISTERS(0)
737 SAVE_ARGUMENT_REGISTERS(0)
742 RESTORE_ARGUMENT_REGISTERS(0)
748 /******************* function asm_initialize_thread_stack **********************
750 * initialized a thread stack *
751 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
753 *******************************************************************************/
755 asm_initialize_thread_stack:
766 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
767 mov %rsi,%rax /* return restorepoint in %rax */
771 /******************* function asm_perform_threadswitch *************************
773 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
775 * performs a threadswitch *
777 *******************************************************************************/
779 asm_perform_threadswitch:
780 sub $(7*8),%rsp /* allocate stack frame */
789 mov 7*8(%rsp),%rax /* save current return address */
792 mov %rsp,(%rdi) /* first argument **from */
793 mov %rsp,(%rdx) /* third argument **stackTop */
795 mov (%rsi),%rsp /* load new stack pointer */
804 mov 6*8(%rsp),%rax /* restore return address */
805 add $(7*8),%rsp /* free stack frame */
810 /********************* function asm_switchstackandcall *************************
812 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
815 * Switches to a new stack, calls a function and switches back. *
816 * a0 (%rdi) new stack pointer *
817 * a1 (%rsi) function pointer *
818 * a2 (%rdx) pointer to variable where stack top should be stored *
819 * a3 (%rcx) pointer to user data, is passed to the function *
821 *******************************************************************************/
823 asm_switchstackandcall:
824 sub $(1*8),%rsp /* keep stack 16-byte aligned */
825 sub $16,%rdi /* allocate new stack */
827 mov 8(%rsp),%rax /* save return address on new stack */
829 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
830 mov %rsp,(%rdx) /* save old stack pointer to variable */
832 mov %rdi,%rsp /* switch to new stack */
834 mov %rcx,%rdi /* pass pointer */
835 call *%rsi /* and call function */
837 mov (%rsp),%r10 /* load return address */
838 mov 8(%rsp),%rsp /* switch to old stack */
839 add $(1*8),%rsp /* free stack space */
840 mov %r10,(%rsp) /* write return adress */
844 asm_getclassvalues_atomic:
847 movl offbaseval(a0),itmp1l
848 movl offdiffval(a0),itmp2l
849 movl offbaseval(a1),itmp3l
851 movl itmp1l,offcast_super_baseval(a2)
852 movl itmp2l,offcast_super_diffval(a2)
853 movl itmp3l,offcast_sub_baseval(a2)
858 asm_criticalsections:
859 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
867 /* Disable exec-stacks, required for Gentoo ***********************************/
869 #if defined(__GCC__) && defined(__ELF__)
870 .section .note.GNU-stack,"",@progbits
875 * These are local overrides for various environment variables in Emacs.
876 * Please do not remove this and leave it at the end of the file, where
877 * Emacs will automagically detect them.
878 * ---------------------------------------------------------------------
881 * indent-tabs-mode: t