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 4357 2006-01-22 23:33:38Z 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 .globl asm_calljavafunction_int
58 .globl asm_calljavafunction2
59 .globl asm_calljavafunction2int
60 .globl asm_calljavafunction2long
61 .globl asm_calljavafunction2float
62 .globl asm_calljavafunction2double
64 .globl asm_call_jit_compiler
65 .globl asm_handle_exception
66 .globl asm_handle_nat_exception
68 .globl asm_wrapper_patcher
70 .globl asm_builtin_f2i
71 .globl asm_builtin_f2l
72 .globl asm_builtin_d2i
73 .globl asm_builtin_d2l
75 .globl asm_perform_threadswitch
76 .globl asm_initialize_thread_stack
77 .globl asm_switchstackandcall
78 .globl asm_criticalsections
79 .globl asm_getclassvalues_atomic
82 /********************* function asm_calljavafunction ***************************
84 * This function calls a Java-method (which possibly needs compilation) *
85 * with up to 4 address parameters. *
87 * This functions calls the JIT-compiler which eventually translates the *
88 * method into machine code. *
91 * javaobject_header *asm_calljavamethod (methodinfo *m, *
92 * void *arg1, void *arg2, void *arg3, void *arg4); *
94 *******************************************************************************/
98 .quad 0 /* catch type all */
99 .quad calljava_xhandler /* handler pc */
100 .quad calljava_xhandler /* end pc */
101 .quad asm_calljavafunction /* start pc */
102 .long 1 /* extable size */
104 .quad 0 /* line number table start */
105 .quad 0 /* line number table size */
107 .long 0 /* fltsave */
108 .long 0 /* intsave */
111 .long 8 /* frame size */
112 .quad 0 /* method pointer (pointer to name) */
114 asm_calljavafunction:
115 asm_calljavafunction_int:
116 sub $(3*8),sp /* keep stack 16-byte aligned */
118 mov %rbx,1*8(sp) /* %rbx is not a callee saved in CACAO*/
119 mov a0,itmp1 /* move function pointer to itmp1 */
120 /* compilerstub uses this */
122 mov a1,a0 /* pass remaining parameters */
127 lea asm_call_jit_compiler,itmp3
128 call *itmp3 /* call JIT compiler */
130 L_asm_calljavafunction_return:
132 mov 1*8(sp),%rbx /* %rbx is not a callee saved in CACAO*/
133 add $(3*8),sp /* free stack space */
137 mov xptr,a0 /* pass exception pointer */
138 call builtin_throw_exception
139 xor v0,v0 /* return NULL */
140 jmp L_asm_calljavafunction_return
143 /********************* function asm_calljavafunction ***************************
145 * This function calls a Java-method (which possibly needs compilation) *
146 * with up to 4 address parameters. *
148 * This functions calls the JIT-compiler which eventually translates the *
149 * method into machine code. *
152 * javaobject_header *asm_calljavamethod (methodinfo *m, *
153 * void *arg1, void *arg2, void *arg3, void *arg4); *
155 *******************************************************************************/
159 .quad 0 /* catch type all */
160 .quad calljava_xhandler2 /* handler pc */
161 .quad calljava_xhandler2 /* end pc */
162 .quad asm_calljavafunction2 /* start pc */
163 .long 1 /* extable size */
165 .quad 0 /* line number table start */
166 .quad 0 /* line number table size */
168 .long 0 /* fltsave */
169 .long 0 /* intsave */
172 .long 24 /* frame size */
173 .quad 0 /* method pointer (pointer to name) */
175 asm_calljavafunction2:
176 asm_calljavafunction2int:
177 asm_calljavafunction2long:
178 asm_calljavafunction2float:
179 asm_calljavafunction2double:
180 sub $(7*8),sp /* keep stack 16-byte aligned */
181 mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/
188 mov a0,itmp1 /* move method pointer for compiler */
189 xor %rbp,%rbp /* set argument stack frame to zero */
191 test a1,a1 /* maybe we have no args... */
194 mov a1,itmp3 /* arg count */
195 mov a3,itmp2 /* pointer to arg block */
197 mov itmp2,%r14 /* save argument block pointer */
198 mov itmp3,%r15 /* save argument count */
200 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
201 add $1,itmp3 /* initialize argument count */
202 xor %r12,%r12 /* initialize integer argument counter*/
203 xor %r13,%r13 /* initialize float argument counter */
206 add $sizejniblock,itmp2 /* goto next argument block */
207 dec itmp3 /* argument count - 1 */
208 jz L_register_copy_done
209 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
210 jnz L_register_handle_float /* yes, handle it */
212 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
213 je L_register_copy /* register? yes, next loop */
215 lea jumptable_integer,%rbp
216 mov 0(%rbp,%r12,8),%rbx
217 inc %r12 /* integer argument counter + 1 */
220 L_register_handle_float:
221 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
222 je L_register_copy /* register? yes, next loop */
224 lea jumptable_float,%rbp
225 mov 0(%rbp,%r13,8),%rbx
226 inc %r13 /* float argument counter + 1 */
229 L_register_copy_done:
230 mov %r15,%rbp /* calculate remaining arguments */
231 sub %r12,%rbp /* - integer arguments in registers */
232 sub %r13,%rbp /* - float arguments in registers */
233 jle L_copy_done /* are all assigned to registers? */
235 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
236 shl $3,%rbp /* calculate stack size */
237 sub %rbp,sp /* stack frame for arguments */
238 mov sp,%rbx /* use %rbx as temp sp */
240 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
241 add $1,%r15 /* initialize argument count */
244 add $sizejniblock,%r14 /* goto next argument block */
245 dec %r15 /* are there any arguments left? */
246 jz L_copy_done /* no test needed after dec */
248 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
249 jnz L_stack_handle_float
250 dec %r12 /* arguments assigned to registers */
251 jge L_stack_copy_loop
254 L_stack_handle_float:
255 dec %r13 /* arguments assigned to registers */
256 jge L_stack_copy_loop
259 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
261 add $8,%rbx /* increase sp to next argument */
262 jmp L_stack_copy_loop
265 lea asm_call_jit_compiler,itmp3 /* %rax still contains method pointer */
266 call *itmp3 /* call JIT compiler */
268 add bp,sp /* remove argument stack frame if any */
270 L_asm_calljavafunction2_return:
271 mov 0*8(sp),%rbx /* restore callee saved registers */
277 add $(7*8),sp /* free stack space */
281 mov xptr,a0 /* pass exception pointer */
282 call builtin_throw_exception
283 xor v0,v0 /* return NULL */
284 jmp L_asm_calljavafunction2_return
296 mov offjniitem(itmp2),a0
299 mov offjniitem(itmp2),a1
302 mov offjniitem(itmp2),a2
305 mov offjniitem(itmp2),a3
308 mov offjniitem(itmp2),a4
311 mov offjniitem(itmp2),a5
326 movq offjniitem(itmp2),fa0
329 movq offjniitem(itmp2),fa1
332 movq offjniitem(itmp2),fa2
335 movq offjniitem(itmp2),fa3
338 movq offjniitem(itmp2),fa4
341 movq offjniitem(itmp2),fa5
344 movq offjniitem(itmp2),fa6
347 movq offjniitem(itmp2),fa7
351 /****************** function asm_call_jit_compiler *****************************
353 * invokes the compiler for untranslated JavaVM methods. *
355 * Register R0 contains a pointer to the method info structure (prepared *
356 * by createcompilerstub). Using the return address in R26 and the *
357 * offset in the LDA instruction or using the value in methodptr R28 the *
358 * patching address for storing the method address can be computed: *
360 * method address was either loaded using *
362 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
363 * i386_call_reg(REG_ITMP2) *
367 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
368 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
369 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
370 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
371 * i386_call_reg(REG_ITMP1) *
373 * in the static case the method pointer can be computed using the *
374 * return address and the lda function following the jmp instruction *
376 *******************************************************************************/
378 asm_call_jit_compiler:
379 /* keep stack 16-byte aligned */
380 sub $((3+ARG_CNT)*8+sizestackframeinfo),sp
382 mov t0,0*8(sp) /* save register */
384 mov (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address */
385 mov -1(itmp3),%bl /* get function code */
386 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
387 jne L_not_static_special
389 sub $11,itmp3 /* calculate address of immediate */
390 jmp L_call_jit_compile
392 L_not_static_special:
393 cmp $0xd0,%bl /* called with `call *REG_ITMP1' */
394 jne L_not_virtual_interface
396 sub $7,itmp3 /* calculate address of offset */
397 mov (itmp3),itmp3l /* get offset (32-bit) */
398 add itmp2,itmp3 /* add base address to get method addr*/
399 jmp L_call_jit_compile
401 L_not_virtual_interface: /* a call from asm_calljavamethod */
405 mov 0*8(sp),t0 /* restore register */
406 mov itmp3,0*8(sp) /* save address for method pointer */
407 mov itmp1,1*8(sp) /* save method pointer */
409 SAVE_ARGUMENT_REGISTERS(3)
411 mov sp,a0 /* create stackframe info */
412 add $((3+ARG_CNT)*8),a0 /* pass sfi */
413 xor a1,a1 /* if pv is NULL, use findmethod */
414 mov sp,a2 /* pass java sp */
415 add $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
416 /* pass ra to java function */
417 mov ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
418 mov a3,a4 /* xpc is equal to ra */
419 call stacktrace_create_extern_stackframeinfo
421 mov 1*8(sp),a0 /* pass method pointer */
423 mov v0,1*8(sp) /* save return value */
425 mov sp,a0 /* remove stackframe info */
426 add $((3+ARG_CNT)*8),a0 /* pass sfi */
427 call stacktrace_remove_stackframeinfo
429 mov 0*8(sp),itmp3 /* restore address for method pointer */
430 mov 1*8(sp),v0 /* restore return value */
432 RESTORE_ARGUMENT_REGISTERS(3)
434 add $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame */
436 test v0,v0 /* check for exception */
437 je L_asm_call_jit_compiler_exception
439 test itmp3,itmp3 /* is address == 0 (asm_calljavamethod*/
442 mov v0,(itmp3) /* and now save the new pointer */
445 jmp *v0 /* ...and now call the new method */
447 L_asm_call_jit_compiler_exception:
448 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
449 call builtin_asm_get_exceptionptrptr
450 mov v0,itmp2 /* v0 == xptr */
452 lea _no_threads_exceptionptr,itmp2
454 mov (itmp2),xptr /* get the exception pointer */
455 movl $0,(itmp2) /* clear exception pointer */
457 pop xpc /* delete return address */
458 sub $5,xpc /* faulting address is ra - 5 */
459 jmp asm_handle_exception
462 /* asm_handle_exception ********************************************************
464 * This function handles an exception. It does not use the usual calling *
465 * conventions. The exception pointer is passed in REG_ITMP1 and the *
466 * pc from the exception raising position is passed in REG_ITMP2. It searches *
467 * the local exception table for a handler. If no one is found, it unwinds *
468 * stacks and continues searching the callers. *
470 *******************************************************************************/
472 asm_handle_nat_exception:
473 add $8,sp /* clear return address of native stub*/
475 asm_handle_exception:
476 sub $((ARG_CNT+TMP_CNT)*8),sp /* create maybe-leaf stackframe */
478 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
479 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
481 mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */
482 mov $1,t0 /* set maybe-leaf flag */
484 L_asm_handle_exception_stack_loop:
486 mov xptr,0*8(sp) /* save exception pointer */
487 mov xpc,1*8(sp) /* save exception pc */
488 add sp,a3 /* calculate Java sp into a3... */
490 mov a3,3*8(sp) /* ...and save it */
491 mov t0,4*8(sp) /* save maybe-leaf flag */
493 mov xpc,a0 /* exception pc */
494 call codegen_findmethod
495 mov v0,2*8(sp) /* save data segment pointer */
497 mov 0*8(sp),a0 /* pass exception pointer */
498 mov 1*8(sp),a1 /* pass exception pc */
499 mov v0,a2 /* pass data segment pointer */
500 mov 3*8(sp),a3 /* pass Java stack pointer */
501 call exceptions_handle_exception
504 jz L_asm_handle_exception_not_catched
506 mov v0,xpc /* move handlerpc into xpc */
507 mov 0*8(sp),xptr /* restore exception pointer */
508 mov 4*8(sp),t0 /* get maybe-leaf flag */
509 add $(6*8),sp /* free stack frame */
511 test t0,t0 /* test for maybe-leaf flag */
512 jz L_asm_handle_exception_no_leaf
514 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
515 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
517 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
519 L_asm_handle_exception_no_leaf:
520 jmp *xpc /* jump to the handler */
522 L_asm_handle_exception_not_catched:
523 mov 0*8(sp),xptr /* restore exception pointer */
524 mov 2*8(sp),itmp3 /* restore data segment pointer */
525 mov 4*8(sp),t0 /* get maybe-leaf flag */
529 jz L_asm_handle_exception_no_leaf_stack
531 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
532 xor t0,t0 /* clear the isleaf flags */
534 L_asm_handle_exception_no_leaf_stack:
535 mov FrameSize(itmp3),itmp2l /* get frame size */
536 add sp,itmp2 /* pointer to save area */
538 mov IntSave(itmp3),a0l /* a0l = saved int register count */
561 shl $3,a0l /* multiply by 8 bytes */
566 mov FltSave(itmp3),a0l /* a0l = saved flt register count */
579 movq -5*8(itmp2),%xmm11
581 movq -4*8(itmp2),%xmm12
583 movq -3*8(itmp2),%xmm13
585 movq -2*8(itmp2),%xmm14
587 movq -1*8(itmp2),%xmm15
591 mov FrameSize(itmp3),itmp2l /* get frame size */
592 add itmp2,sp /* unwind stack */
594 /* exception pointer is still set */
595 pop xpc /* the new xpc is return address */
596 sub $3,xpc /* subtract 3 bytes for call */
598 xor a3,a3 /* prepare a3 for handle_exception */
600 jmp L_asm_handle_exception_stack_loop
603 /* asm_wrapper_patcher *********************************************************
609 32 pointer to virtual java_objectheader
610 24 machine code (which is patched back later)
611 16 unresolved class/method/field reference
612 8 data segment displacement from load instructions
613 0 pointer to patcher function
616 *******************************************************************************/
619 push bp /* save base pointer */
620 mov sp,bp /* move actual sp to bp */
621 sub $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
622 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
623 /* leaf functions) */
625 SAVE_ARGUMENT_REGISTERS(3)
626 SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
628 mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
629 mov itmp2,1*8(sp) /* can be used by some instructions */
631 mov sp,a0 /* create stackframe info */
632 add $((3+ARG_CNT+TMP_CNT)*8),a0
633 xor a1,a1 /* if pv is NULL, use findmethod */
634 mov bp,a2 /* pass java sp */
636 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
637 mov a3,a4 /* xpc is equal to ra */
638 call stacktrace_create_extern_stackframeinfo
640 mov bp,a0 /* pass stack pointer */
641 add $((1+1)*8),a0 /* skip function pointer */
642 mov 1*8(bp),itmp3 /* get function pointer */
643 call *itmp3 /* call the patcher function */
644 mov v0,2*8(sp) /* save return value */
646 mov sp,a0 /* remove stackframe info */
647 add $((3+ARG_CNT+TMP_CNT)*8),a0
648 call stacktrace_remove_stackframeinfo
650 RESTORE_ARGUMENT_REGISTERS(3)
651 RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
653 mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
654 mov 1*8(sp),itmp2 /* can be used by some instructions */
655 mov 2*8(sp),itmp3 /* restore return value */
657 mov bp,sp /* restore original sp */
658 pop bp /* restore bp */
659 add $(5*8),sp /* remove patcher stackframe, keep ra */
661 test itmp3,itmp3 /* exception thrown? */
662 jz L_asm_wrapper_patcher_exception
663 ret /* call new patched code */
665 L_asm_wrapper_patcher_exception:
666 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
667 call builtin_asm_get_exceptionptrptr
668 mov v0,itmp2 /* v0 == xptr */
670 lea _no_threads_exceptionptr,itmp2
672 mov (itmp2),xptr /* get the exception pointer */
673 movl $0,(itmp2) /* clear exception pointer */
675 pop xpc /* get and remove return address */
676 jmp asm_handle_exception
679 /* asm_builtin_x2x *************************************************************
681 * Wrapper functions for float to int corner cases *
683 *******************************************************************************/
688 SAVE_ARGUMENT_REGISTERS(0)
693 RESTORE_ARGUMENT_REGISTERS(0)
702 SAVE_ARGUMENT_REGISTERS(0)
707 RESTORE_ARGUMENT_REGISTERS(0)
716 SAVE_ARGUMENT_REGISTERS(0)
721 RESTORE_ARGUMENT_REGISTERS(0)
730 SAVE_ARGUMENT_REGISTERS(0)
735 RESTORE_ARGUMENT_REGISTERS(0)
741 /******************* function asm_initialize_thread_stack **********************
743 * initialized a thread stack *
744 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
746 *******************************************************************************/
748 asm_initialize_thread_stack:
759 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
760 mov %rsi,%rax /* return restorepoint in %rax */
764 /******************* function asm_perform_threadswitch *************************
766 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
768 * performs a threadswitch *
770 *******************************************************************************/
772 asm_perform_threadswitch:
773 sub $(7*8),%rsp /* allocate stack frame */
782 mov 7*8(%rsp),%rax /* save current return address */
785 mov %rsp,(%rdi) /* first argument **from */
786 mov %rsp,(%rdx) /* third argument **stackTop */
788 mov (%rsi),%rsp /* load new stack pointer */
797 mov 6*8(%rsp),%rax /* restore return address */
798 add $(7*8),%rsp /* free stack frame */
803 /********************* function asm_switchstackandcall *************************
805 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
808 * Switches to a new stack, calls a function and switches back. *
809 * a0 (%rdi) new stack pointer *
810 * a1 (%rsi) function pointer *
811 * a2 (%rdx) pointer to variable where stack top should be stored *
812 * a3 (%rcx) pointer to user data, is passed to the function *
814 *******************************************************************************/
816 asm_switchstackandcall:
817 sub $(1*8),%rsp /* keep stack 16-byte aligned */
818 sub $16,%rdi /* allocate new stack */
820 mov 8(%rsp),%rax /* save return address on new stack */
822 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
823 mov %rsp,(%rdx) /* save old stack pointer to variable */
825 mov %rdi,%rsp /* switch to new stack */
827 mov %rcx,%rdi /* pass pointer */
828 call *%rsi /* and call function */
830 mov (%rsp),%r10 /* load return address */
831 mov 8(%rsp),%rsp /* switch to old stack */
832 add $(1*8),%rsp /* free stack space */
833 mov %r10,(%rsp) /* write return adress */
837 asm_getclassvalues_atomic:
840 movl offbaseval(a0),itmp1l
841 movl offdiffval(a0),itmp2l
842 movl offbaseval(a1),itmp3l
844 movl itmp1l,offcast_super_baseval(a2)
845 movl itmp2l,offcast_super_diffval(a2)
846 movl itmp3l,offcast_sub_baseval(a2)
851 asm_criticalsections:
852 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
861 * These are local overrides for various environment variables in Emacs.
862 * Please do not remove this and leave it at the end of the file, where
863 * Emacs will automagically detect them.
864 * ---------------------------------------------------------------------
867 * indent-tabs-mode: t