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 4559 2006-03-05 23:24:50Z 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_vm_call_method
56 .globl asm_vm_call_method_int
57 .globl asm_vm_call_method_long
58 .globl asm_vm_call_method_float
59 .globl asm_vm_call_method_double
61 .globl asm_call_jit_compiler
62 .globl asm_handle_exception
63 .globl asm_handle_nat_exception
65 .globl asm_wrapper_patcher
67 .globl asm_builtin_f2i
68 .globl asm_builtin_f2l
69 .globl asm_builtin_d2i
70 .globl asm_builtin_d2l
72 .globl asm_perform_threadswitch
73 .globl asm_initialize_thread_stack
74 .globl asm_switchstackandcall
75 .globl asm_criticalsections
76 .globl asm_getclassvalues_atomic
79 /********************* function asm_calljavafunction ***************************
81 * This function calls a Java-method (which possibly needs compilation) *
82 * with up to 4 address parameters. *
84 * This functions calls the JIT-compiler which eventually translates the *
85 * method into machine code. *
88 * javaobject_header *asm_calljavamethod (methodinfo *m, *
89 * void *arg1, void *arg2, void *arg3, void *arg4); *
91 *******************************************************************************/
95 .quad 0 /* catch type all */
96 .quad calljava_xhandler2 /* handler pc */
97 .quad calljava_xhandler2 /* end pc */
98 .quad L_asm_vm_call_method /* start pc */
99 .long 1 /* extable size */
101 .quad 0 /* line number table start */
102 .quad 0 /* line number table size */
104 .long 0 /* fltsave */
105 .long 0 /* intsave */
108 .long 24 /* frame size */
109 .quad 0 /* method pointer (pointer to name) */
112 asm_vm_call_method_int:
113 asm_vm_call_method_long:
114 asm_vm_call_method_float:
115 asm_vm_call_method_double:
116 L_asm_vm_call_method: /* required for PIC code */
117 sub $(7*8),sp /* keep stack 16-byte aligned */
118 mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/
125 mov a0,itmp1 /* move method pointer for compiler */
126 xor %rbp,%rbp /* set argument stack frame to zero */
128 test a1,a1 /* maybe we have no args... */
131 mov a1,itmp3 /* arg count */
132 mov a2,itmp2 /* pointer to arg block */
134 mov itmp2,%r14 /* save argument block pointer */
135 mov itmp3,%r15 /* save argument count */
137 sub $sizevmarg,itmp2 /* initialize pointer (smaller code) */
138 add $1,itmp3 /* initialize argument count */
139 xor %r12,%r12 /* initialize integer argument counter*/
140 xor %r13,%r13 /* initialize float argument counter */
143 add $sizevmarg,itmp2 /* goto next argument block */
144 dec itmp3 /* argument count - 1 */
145 jz L_register_copy_done
146 andb $0x02,offvmargtype(itmp2) /* is this a float/double type? */
147 jnz L_register_handle_float /* yes, handle it */
149 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
150 je L_register_copy /* register? yes, next loop */
152 lea jumptable_integer(%rip),%rbp
153 mov 0(%rbp,%r12,8),%rbx
154 inc %r12 /* integer argument counter + 1 */
157 L_register_handle_float:
158 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
159 je L_register_copy /* register? yes, next loop */
161 lea jumptable_float(%rip),%rbp
162 mov 0(%rbp,%r13,8),%rbx
163 inc %r13 /* float argument counter + 1 */
166 L_register_copy_done:
167 mov %r15,%rbp /* calculate remaining arguments */
168 sub %r12,%rbp /* - integer arguments in registers */
169 sub %r13,%rbp /* - float arguments in registers */
170 jle L_copy_done /* are all assigned to registers? */
172 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
173 shl $3,%rbp /* calculate stack size */
174 sub %rbp,sp /* stack frame for arguments */
175 mov sp,%rbx /* use %rbx as temp sp */
177 sub $sizevmarg,%r14 /* initialize pointer (smaller code) */
178 add $1,%r15 /* initialize argument count */
181 add $sizevmarg,%r14 /* goto next argument block */
182 dec %r15 /* are there any arguments left? */
183 jz L_copy_done /* no test needed after dec */
185 andb $0x02,offvmargtype(%r14) /* is this a float/double type? */
186 jnz L_stack_handle_float
187 dec %r12 /* arguments assigned to registers */
188 jge L_stack_copy_loop
191 L_stack_handle_float:
192 dec %r13 /* arguments assigned to registers */
193 jge L_stack_copy_loop
196 mov offvmargdata(%r14),itmp3 /* copy s8 argument onto stack */
198 add $8,%rbx /* increase sp to next argument */
199 jmp L_stack_copy_loop
202 /* itmp1 still contains method pointer*/
203 lea L_asm_call_jit_compiler(%rip),itmp3
204 call *itmp3 /* call JIT compiler */
206 add bp,sp /* remove argument stack frame if any */
208 L_asm_vm_call_method_return:
209 mov 0*8(sp),%rbx /* restore callee saved registers */
215 add $(7*8),sp /* free stack space */
219 mov xptr,a0 /* pass exception pointer */
220 call builtin_throw_exception@PLT
221 xor v0,v0 /* return NULL */
222 jmp L_asm_vm_call_method_return
234 mov offvmargdata(itmp2),a0
237 mov offvmargdata(itmp2),a1
240 mov offvmargdata(itmp2),a2
243 mov offvmargdata(itmp2),a3
246 mov offvmargdata(itmp2),a4
249 mov offvmargdata(itmp2),a5
264 movq offvmargdata(itmp2),fa0
267 movq offvmargdata(itmp2),fa1
270 movq offvmargdata(itmp2),fa2
273 movq offvmargdata(itmp2),fa3
276 movq offvmargdata(itmp2),fa4
279 movq offvmargdata(itmp2),fa5
282 movq offvmargdata(itmp2),fa6
285 movq offvmargdata(itmp2),fa7
289 /****************** function asm_call_jit_compiler *****************************
291 * invokes the compiler for untranslated JavaVM methods. *
293 * Register R0 contains a pointer to the method info structure (prepared *
294 * by createcompilerstub). Using the return address in R26 and the *
295 * offset in the LDA instruction or using the value in methodptr R28 the *
296 * patching address for storing the method address can be computed: *
298 * method address was either loaded using *
300 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
301 * i386_call_reg(REG_ITMP2) *
305 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
306 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
307 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
308 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
309 * i386_call_reg(REG_ITMP1) *
311 * in the static case the method pointer can be computed using the *
312 * return address and the lda function following the jmp instruction *
314 *******************************************************************************/
316 asm_call_jit_compiler:
317 L_asm_call_jit_compiler: /* required for PIC code */
318 /* keep stack 16-byte aligned */
319 sub $((3+ARG_CNT)*8+sizestackframeinfo),sp
321 mov t0,0*8(sp) /* save register */
323 mov (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address */
324 mov -1(itmp3),%bl /* get function code */
325 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
326 jne L_not_static_special
328 sub $11,itmp3 /* calculate address of immediate */
329 jmp L_call_jit_compile
331 L_not_static_special:
332 cmp $0xd0,%bl /* called with `call *REG_ITMP1' */
333 jne L_not_virtual_interface
335 sub $7,itmp3 /* calculate address of offset */
336 mov (itmp3),itmp3l /* get offset (32-bit) */
337 add itmp2,itmp3 /* add base address to get method addr*/
338 jmp L_call_jit_compile
340 L_not_virtual_interface: /* a call from asm_calljavamethod */
344 mov 0*8(sp),t0 /* restore register */
345 mov itmp3,0*8(sp) /* save address for method pointer */
346 mov itmp1,1*8(sp) /* save method pointer */
348 SAVE_ARGUMENT_REGISTERS(3)
350 mov sp,a0 /* create stackframe info */
351 add $((3+ARG_CNT)*8),a0 /* pass sfi */
352 xor a1,a1 /* if pv is NULL, use findmethod */
353 mov sp,a2 /* pass java sp */
354 add $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
355 /* pass ra to java function */
356 mov ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
357 mov a3,a4 /* xpc is equal to ra */
358 call stacktrace_create_extern_stackframeinfo@PLT
360 mov 1*8(sp),a0 /* pass method pointer */
362 mov v0,1*8(sp) /* save return value */
364 mov sp,a0 /* remove stackframe info */
365 add $((3+ARG_CNT)*8),a0 /* pass sfi */
366 call stacktrace_remove_stackframeinfo@PLT
368 mov 0*8(sp),itmp3 /* restore address for method pointer */
369 mov 1*8(sp),v0 /* restore return value */
371 RESTORE_ARGUMENT_REGISTERS(3)
373 add $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame */
375 test v0,v0 /* check for exception */
376 je L_asm_call_jit_compiler_exception
378 test itmp3,itmp3 /* is address == 0 (asm_calljavamethod*/
381 mov v0,(itmp3) /* and now save the new pointer */
384 jmp *v0 /* ...and now call the new method */
386 L_asm_call_jit_compiler_exception:
387 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
388 call builtin_asm_get_exceptionptrptr@PLT
389 mov v0,itmp2 /* v0 == xptr */
391 lea _no_threads_exceptionptr(%rip),itmp2
393 mov (itmp2),xptr /* get the exception pointer */
394 movl $0,(itmp2) /* clear exception pointer */
396 pop xpc /* delete return address */
397 sub $5,xpc /* faulting address is ra - 5 */
398 jmp L_asm_handle_exception
401 /* asm_handle_exception ********************************************************
403 * This function handles an exception. It does not use the usual calling *
404 * conventions. The exception pointer is passed in REG_ITMP1 and the *
405 * pc from the exception raising position is passed in REG_ITMP2. It searches *
406 * the local exception table for a handler. If no one is found, it unwinds *
407 * stacks and continues searching the callers. *
409 *******************************************************************************/
411 asm_handle_nat_exception:
412 add $8,sp /* clear return address of native stub*/
414 asm_handle_exception:
415 L_asm_handle_exception: /* required for PIC code */
416 sub $((ARG_CNT+TMP_CNT)*8),sp /* create maybe-leaf stackframe */
418 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
419 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
421 mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */
422 mov $1,t0 /* set maybe-leaf flag */
424 L_asm_handle_exception_stack_loop:
426 mov xptr,0*8(sp) /* save exception pointer */
427 mov xpc,1*8(sp) /* save exception pc */
428 add sp,a3 /* calculate Java sp into a3... */
430 mov a3,3*8(sp) /* ...and save it */
431 mov t0,4*8(sp) /* save maybe-leaf flag */
433 mov xpc,a0 /* exception pc */
434 call codegen_findmethod@PLT
435 mov v0,2*8(sp) /* save data segment pointer */
437 mov 0*8(sp),a0 /* pass exception pointer */
438 mov 1*8(sp),a1 /* pass exception pc */
439 mov v0,a2 /* pass data segment pointer */
440 mov 3*8(sp),a3 /* pass Java stack pointer */
441 call exceptions_handle_exception@PLT
444 jz L_asm_handle_exception_not_catched
446 mov v0,xpc /* move handlerpc into xpc */
447 mov 0*8(sp),xptr /* restore exception pointer */
448 mov 4*8(sp),t0 /* get maybe-leaf flag */
449 add $(6*8),sp /* free stack frame */
451 test t0,t0 /* test for maybe-leaf flag */
452 jz L_asm_handle_exception_no_leaf
454 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
455 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
457 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
459 L_asm_handle_exception_no_leaf:
460 jmp *xpc /* jump to the handler */
462 L_asm_handle_exception_not_catched:
463 mov 0*8(sp),xptr /* restore exception pointer */
464 mov 2*8(sp),itmp3 /* restore data segment pointer */
465 mov 4*8(sp),t0 /* get maybe-leaf flag */
469 jz L_asm_handle_exception_no_leaf_stack
471 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
472 xor t0,t0 /* clear the isleaf flags */
474 L_asm_handle_exception_no_leaf_stack:
475 mov FrameSize(itmp3),itmp2l /* get frame size */
476 add sp,itmp2 /* pointer to save area */
478 mov IntSave(itmp3),a0l /* a0l = saved int register count */
501 shl $3,a0l /* multiply by 8 bytes */
506 mov FltSave(itmp3),a0l /* a0l = saved flt register count */
519 movq -5*8(itmp2),%xmm11
521 movq -4*8(itmp2),%xmm12
523 movq -3*8(itmp2),%xmm13
525 movq -2*8(itmp2),%xmm14
527 movq -1*8(itmp2),%xmm15
531 mov FrameSize(itmp3),itmp2l /* get frame size */
532 add itmp2,sp /* unwind stack */
534 /* exception pointer is still set */
535 pop xpc /* the new xpc is return address */
536 sub $3,xpc /* subtract 3 bytes for call */
538 xor a3,a3 /* prepare a3 for handle_exception */
540 jmp L_asm_handle_exception_stack_loop
543 /* asm_wrapper_patcher *********************************************************
549 32 pointer to virtual java_objectheader
550 24 machine code (which is patched back later)
551 16 unresolved class/method/field reference
552 8 data segment displacement from load instructions
553 0 pointer to patcher function
556 *******************************************************************************/
559 push bp /* save base pointer */
560 mov sp,bp /* move actual sp to bp */
561 sub $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
562 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
563 /* leaf functions) */
565 SAVE_ARGUMENT_REGISTERS(3)
566 SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
568 mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
569 mov itmp2,1*8(sp) /* can be used by some instructions */
571 mov sp,a0 /* create stackframe info */
572 add $((3+ARG_CNT+TMP_CNT)*8),a0
573 xor a1,a1 /* if pv is NULL, use findmethod */
574 mov bp,a2 /* pass java sp */
576 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
577 mov a3,a4 /* xpc is equal to ra */
578 call stacktrace_create_extern_stackframeinfo@PLT
580 mov bp,a0 /* pass stack pointer */
581 add $((1+1)*8),a0 /* skip function pointer */
582 mov 1*8(bp),itmp3 /* get function pointer */
583 call *itmp3 /* call the patcher function */
584 mov v0,2*8(sp) /* save return value */
586 mov sp,a0 /* remove stackframe info */
587 add $((3+ARG_CNT+TMP_CNT)*8),a0
588 call stacktrace_remove_stackframeinfo@PLT
590 RESTORE_ARGUMENT_REGISTERS(3)
591 RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
593 mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
594 mov 1*8(sp),itmp2 /* can be used by some instructions */
595 mov 2*8(sp),itmp3 /* restore return value */
597 mov bp,sp /* restore original sp */
598 pop bp /* restore bp */
599 add $(5*8),sp /* remove patcher stackframe, keep ra */
601 test itmp3,itmp3 /* exception thrown? */
602 jz L_asm_wrapper_patcher_exception
603 ret /* call new patched code */
605 L_asm_wrapper_patcher_exception:
606 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
607 call builtin_asm_get_exceptionptrptr@PLT
608 mov v0,itmp2 /* v0 == xptr */
610 mov _no_threads_exceptionptr,itmp2
612 mov (itmp2),xptr /* get the exception pointer */
613 movl $0,(itmp2) /* clear exception pointer */
615 pop xpc /* get and remove return address */
616 jmp L_asm_handle_exception
619 /* asm_builtin_x2x *************************************************************
621 * Wrapper functions for float to int corner cases *
623 *******************************************************************************/
628 SAVE_ARGUMENT_REGISTERS(0)
633 RESTORE_ARGUMENT_REGISTERS(0)
642 SAVE_ARGUMENT_REGISTERS(0)
647 RESTORE_ARGUMENT_REGISTERS(0)
656 SAVE_ARGUMENT_REGISTERS(0)
661 RESTORE_ARGUMENT_REGISTERS(0)
670 SAVE_ARGUMENT_REGISTERS(0)
675 RESTORE_ARGUMENT_REGISTERS(0)
681 /******************* function asm_initialize_thread_stack **********************
683 * initialized a thread stack *
684 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
686 *******************************************************************************/
688 asm_initialize_thread_stack:
699 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
700 mov %rsi,%rax /* return restorepoint in %rax */
704 /******************* function asm_perform_threadswitch *************************
706 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
708 * performs a threadswitch *
710 *******************************************************************************/
712 asm_perform_threadswitch:
713 sub $(7*8),%rsp /* allocate stack frame */
722 mov 7*8(%rsp),%rax /* save current return address */
725 mov %rsp,(%rdi) /* first argument **from */
726 mov %rsp,(%rdx) /* third argument **stackTop */
728 mov (%rsi),%rsp /* load new stack pointer */
737 mov 6*8(%rsp),%rax /* restore return address */
738 add $(7*8),%rsp /* free stack frame */
743 /********************* function asm_switchstackandcall *************************
745 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
748 * Switches to a new stack, calls a function and switches back. *
749 * a0 (%rdi) new stack pointer *
750 * a1 (%rsi) function pointer *
751 * a2 (%rdx) pointer to variable where stack top should be stored *
752 * a3 (%rcx) pointer to user data, is passed to the function *
754 *******************************************************************************/
756 asm_switchstackandcall:
757 sub $(1*8),%rsp /* keep stack 16-byte aligned */
758 sub $16,%rdi /* allocate new stack */
760 mov 8(%rsp),%rax /* save return address on new stack */
762 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
763 mov %rsp,(%rdx) /* save old stack pointer to variable */
765 mov %rdi,%rsp /* switch to new stack */
767 mov %rcx,%rdi /* pass pointer */
768 call *%rsi /* and call function */
770 mov (%rsp),%r10 /* load return address */
771 mov 8(%rsp),%rsp /* switch to old stack */
772 add $(1*8),%rsp /* free stack space */
773 mov %r10,(%rsp) /* write return adress */
777 asm_getclassvalues_atomic:
780 movl offbaseval(a0),itmp1l
781 movl offdiffval(a0),itmp2l
782 movl offbaseval(a1),itmp3l
784 movl itmp1l,offcast_super_baseval(a2)
785 movl itmp2l,offcast_super_diffval(a2)
786 movl itmp3l,offcast_sub_baseval(a2)
791 asm_criticalsections:
792 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
800 /* Disable exec-stacks, required for Gentoo ***********************************/
802 #if defined(__GCC__) && defined(__ELF__)
803 .section .note.GNU-stack,"",@progbits
808 * These are local overrides for various environment variables in Emacs.
809 * Please do not remove this and leave it at the end of the file, where
810 * Emacs will automagically detect them.
811 * ---------------------------------------------------------------------
814 * indent-tabs-mode: t