1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
31 $Id: asmpart.S 2991 2005-07-11 21:25:31Z twisti $
41 #include "vm/jit/x86_64/arch.h"
42 #include "vm/jit/x86_64/asmoffsets.h"
43 #include "vm/jit/x86_64/offsets.h"
49 /********************* exported functions and variables ***********************/
51 .globl asm_calljavafunction
52 .globl asm_calljavafunction_int
54 .globl asm_calljavafunction2
55 .globl asm_calljavafunction2int
56 .globl asm_calljavafunction2long
57 .globl asm_calljavafunction2float
58 .globl asm_calljavafunction2double
60 .globl asm_call_jit_compiler
61 .globl asm_handle_exception
62 .globl asm_handle_nat_exception
64 .globl asm_wrapper_patcher
66 .globl asm_builtin_arraycheckcast
68 .globl asm_builtin_f2i
69 .globl asm_builtin_f2l
70 .globl asm_builtin_d2i
71 .globl asm_builtin_d2l
73 .globl asm_perform_threadswitch
74 .globl asm_initialize_thread_stack
75 .globl asm_switchstackandcall
76 .globl asm_criticalsections
77 .globl asm_getclassvalues_atomic
80 /********************* function asm_calljavafunction ***************************
82 * This function calls a Java-method (which possibly needs compilation) *
83 * with up to 4 address parameters. *
85 * This functions calls the JIT-compiler which eventually translates the *
86 * method into machine code. *
89 * javaobject_header *asm_calljavamethod (methodinfo *m, *
90 * void *arg1, void *arg2, void *arg3, void *arg4); *
92 *******************************************************************************/
97 .quad 0 /* catch type all */
98 .quad calljava_xhandler /* handler pc */
99 .quad calljava_xhandler /* end pc */
100 .quad asm_calljavafunction /* start pc */
101 .long 1 /* extable size */
103 .quad 0 /* line number table start */
104 .quad 0 /* line number table size */
106 .long 0 /* fltsave */
107 .long 0 /* intsave */
110 .long 8 /* frame size */
111 .quad 0 /* method pointer (pointer to name) */
113 asm_calljavafunction:
114 asm_calljavafunction_int:
115 sub $(3*8),%rsp /* keep stack 16-byte aligned */
117 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
118 mov %rdi,%rax /* move function pointer to %rax */
119 /* compilerstub uses this */
121 mov %rsi,%rdi /* pass remaining parameters */
126 lea asm_call_jit_compiler,%r11
127 call *%r11 /* call JIT compiler */
131 add $(3*8),%rsp /* free stack space */
135 mov %rax,%rdi /* pass exception pointer */
136 call builtin_throw_exception
140 xor %rax,%rax /* return NULL */
144 /********************* function asm_calljavafunction ***************************
146 * This function calls a Java-method (which possibly needs compilation) *
147 * with up to 4 address parameters. *
149 * This functions calls the JIT-compiler which eventually translates the *
150 * method into machine code. *
153 * javaobject_header *asm_calljavamethod (methodinfo *m, *
154 * void *arg1, void *arg2, void *arg3, void *arg4); *
156 *******************************************************************************/
161 .quad 0 /* catch type all */
162 .quad calljava_xhandler2 /* handler pc */
163 .quad calljava_xhandler2 /* end pc */
164 .quad asm_calljavafunction2 /* start pc */
165 .long 1 /* extable size */
167 .quad 0 /* line number table start */
168 .quad 0 /* line number table size */
170 .long 0 /* fltsave */
171 .long 0 /* intsave */
174 .long 24 /* frame size */
175 .quad 0 /* method pointer (pointer to name) */
177 asm_calljavafunction2:
178 asm_calljavafunction2int:
179 asm_calljavafunction2long:
180 asm_calljavafunction2float:
181 asm_calljavafunction2double:
182 sub $(7*8),%rsp /* keep stack 16-byte aligned */
183 mov %rbx,0*8(%rsp) /* %rbx is not a callee saved in cacao */
190 mov %rdi,%rax /* move method pointer for compiler */
191 xor %rbp,%rbp /* set argument stack frame to zero */
193 test %rsi,%rsi /* maybe we have no args... */
196 mov %rsi,itmp3 /* arg count */
197 mov %rcx,itmp2 /* pointer to arg block */
199 mov itmp2,%r14 /* save argument block pointer */
200 mov itmp3,%r15 /* save argument count */
202 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
203 add $1,itmp3 /* initialize argument count */
204 xor %r12,%r12 /* initialize integer argument counter */
205 xor %r13,%r13 /* initialize float argument counter */
208 add $sizejniblock,itmp2 /* goto next argument block */
209 dec itmp3 /* argument count - 1 */
210 jz L_register_copy_done
211 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
212 jnz L_register_handle_float /* yes, handle it */
214 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
215 je L_register_copy /* register? yes, next loop */
217 lea jumptable_integer,%rbp
218 mov 0(%rbp,%r12,8),%rbx
219 inc %r12 /* integer argument counter + 1 */
222 L_register_handle_float:
223 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
224 je L_register_copy /* register? yes, next loop */
226 lea jumptable_float,%rbp
227 mov 0(%rbp,%r13,8),%rbx
228 inc %r13 /* float argument counter + 1 */
231 L_register_copy_done:
232 mov %r15,%rbp /* calculate remaining arguments */
233 sub %r12,%rbp /* - integer arguments in registers */
234 sub %r13,%rbp /* - float arguments in registers */
235 jle L_copy_done /* are all assigned to registers? */
237 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
238 shl $3,%rbp /* calculate stack size */
239 sub %rbp,%rsp /* stack frame for arguments */
240 mov %rsp,%rbx /* use %rbx as temp sp */
242 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
243 add $1,%r15 /* initialize argument count */
246 add $sizejniblock,%r14 /* goto next argument block */
247 dec %r15 /* are there any arguments left? */
248 jz L_copy_done /* no test needed after dec */
250 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
251 jnz L_stack_handle_float
252 dec %r12 /* arguments assigned to registers */
253 jge L_stack_copy_loop
256 L_stack_handle_float:
257 dec %r13 /* arguments assigned to registers */
258 jge L_stack_copy_loop
261 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
263 add $8,%rbx /* increase sp to next argument */
264 jmp L_stack_copy_loop
267 lea asm_call_jit_compiler,%r11/* %rax still contains method pointer */
268 call *%r11 /* call JIT compiler */
270 add %rbp,%rsp /* remove argument stack frame if any */
272 mov 5*8(%rsp),%r15 /* restore callee saved registers */
278 add $(7*8),%rsp /* free stack space */
282 mov %rax,%rdi /* pass exception pointer */
283 call builtin_throw_exception
285 mov 5*8(%rsp),%r15 /* restore callee saved registers */
291 add $(7*8),%rsp /* free stack space */
292 xor %rax,%rax /* return NULL */
305 mov offjniitem(itmp2),a0
308 mov offjniitem(itmp2),a1
311 mov offjniitem(itmp2),a2
314 mov offjniitem(itmp2),a3
317 mov offjniitem(itmp2),a4
320 mov offjniitem(itmp2),a5
335 movq offjniitem(itmp2),fa0
338 movq offjniitem(itmp2),fa1
341 movq offjniitem(itmp2),fa2
344 movq offjniitem(itmp2),fa3
347 movq offjniitem(itmp2),fa4
350 movq offjniitem(itmp2),fa5
353 movq offjniitem(itmp2),fa6
356 movq offjniitem(itmp2),fa7
360 /****************** function asm_call_jit_compiler *****************************
362 * invokes the compiler for untranslated JavaVM methods. *
364 * Register R0 contains a pointer to the method info structure (prepared *
365 * by createcompilerstub). Using the return address in R26 and the *
366 * offset in the LDA instruction or using the value in methodptr R28 the *
367 * patching address for storing the method address can be computed: *
369 * method address was either loaded using *
371 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
372 * i386_call_reg(REG_ITMP2) *
376 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
377 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
378 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
379 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
380 * i386_call_reg(REG_ITMP1) *
382 * in the static case the method pointer can be computed using the *
383 * return address and the lda function following the jmp instruction *
385 *******************************************************************************/
387 asm_call_jit_compiler:
388 sub $8,%rsp /* keep stack 16-byte aligned */
390 mov %rbx,(%rsp) /* save register */
392 mov 8(%rsp),%r11 /* get return address */
393 mov -1(%r11),%bl /* get function code */
394 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%r10)? */
395 jne L_not_static_special
397 sub $11,%r11 /* calculate address of immediate */
398 jmp L_call_jit_compile
400 L_not_static_special:
401 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
402 jne L_not_virtual_interface
404 sub $7,%r11 /* calculate address of offset */
405 mov (%r11),%r11d /* get offset (32-bit) */
406 add %r10,%r11 /* add base address to get method address */
407 jmp L_call_jit_compile
409 L_not_virtual_interface: /* a call from asm_calljavamethod */
413 mov (%rsp),%rbx /* restore register */
415 sub $(24*8),%rsp /* 8 + 6*8 + 8*8 + 8*8 */
417 mov %r11,0*8(%rsp) /* save address for method pointer */
419 SAVE_ARGUMENT_REGISTERS(1)
421 mov %rax,%rdi /* pass method pointer */
424 mov 0*8(%rsp),%r11 /* restore address for method pointer */
426 RESTORE_ARGUMENT_REGISTERS(1)
429 add $8,%rsp /* keep stack 16-byte aligned */
431 test %rax,%rax /* check for exception */
432 je L_asm_call_jit_compiler_exception
434 test %r11,%r11 /* is address == 0 (asm_calljavamethod) */
437 mov %rax,(%r11) /* and now save the new pointer */
440 jmp *%rax /* ...and now call the new method */
442 L_asm_call_jit_compiler_exception:
443 xor a0,a0 /* we don't have pv handy */
444 mov sp,a1 /* pass java sp */
446 mov 0*8(sp),a2 /* pass ra to parent Java function */
447 mov a2,a3 /* xpc is the same as ra */
448 call stacktrace_extern_fillInStackTrace
450 pop xpc /* delete return address */
451 sub $5,xpc /* faulting address is ra - 5 */
452 jmp asm_handle_exception
455 /********************* function asm_handle_exception ***************************
457 * This function handles an exception. It does not use the usual calling *
458 * conventions. The exception pointer is passed in REG_ITMP1 and the *
459 * pc from the exception raising position is passed in REG_ITMP2. It searches *
460 * the local exception table for a handler. If no one is found, it unwinds *
461 * stacks and continues searching the callers. *
463 * void asm_handle_exception (exceptionptr, exceptionpc); *
465 *******************************************************************************/
467 asm_handle_nat_exception:
468 add $8,%rsp /* clear return address of native stub*/
470 asm_handle_exception:
472 mov xptr,0*8(%rsp) /* save exception pointer */
473 mov xpc,1*8(%rsp) /* save exception pc */
475 mov xpc,%rdi /* exception pc */
476 call codegen_findmethod
478 mov %rax,2*8(%rsp) /* save data segment pointer */
480 mov 0*8(%rsp),%rax /* restore exception pointer */
481 mov 1*8(%rsp),%r10 /* restore exception pc */
484 mov %rax,%rdi /* exception pointer */
485 mov MethodPointer(itmp3),%rsi /* method pointer */
486 mov xpc,%rdx /* exception pc */
488 mov $1,%r8 /* set noindent flag */
489 call builtin_trace_exception
491 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
492 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
493 test %rcx,%rcx /* if empty table skip */
496 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
497 mov 0*8(%rsp),xptr /* get xptr */
500 mov 1*8(%rsp),xpc /* get xpc */
502 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
503 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
504 jg ex_table_cont /* if (false) continue */
505 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
506 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
507 jge ex_table_cont /* if (false) continue */
508 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
509 test %rdx,%rdx /* NULL catches everything */
512 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
522 call load_class_bootstrap
531 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
550 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
558 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
559 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
560 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
561 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
562 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
564 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
566 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
570 cmp %edx,%esi /* xptr is instanceof catchtype */
574 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
576 mov 0*8(%rsp),%rax /* restore exception pointer */
577 add $(4*8),%rsp /* free stack frame */
579 jmp *xpc /* jump to the handler */
582 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
583 dec %rcx /* decrement entry counter */
584 test %rcx,%rcx /* if (t0 > 0) next entry */
588 mov 0*8(%rsp),%rax /* restore exception pointer */
589 mov 1*8(%rsp),%r10 /* restore exception pc */
590 mov 2*8(%rsp),%r11 /* restore data segment pointer */
593 mov %rax,%rcx /* save exception pointer */
596 movl IsSync(%r11),%eax /* %rax = SyncOffset */
597 test %rax,%rax /* if zero no monitorexit */
600 #if defined(USE_THREADS)
609 call builtin_monitorexit
618 mov FrameSize(%r11),%eax /* %eax = frame size */
619 add %rax,%rsp /* unwind stack */
620 mov %rsp,%rax /* %rax = pointer to save area */
622 mov IntSave(%r11),%edx /* %edx = saved int register count*/
649 shl $3,%edx /* multiply by 8 bytes */
653 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
676 movq -48(%rax),%xmm10
678 movq -40(%rax),%xmm11
680 movq -32(%rax),%xmm12
682 movq -24(%rax),%xmm13
684 movq -16(%rax),%xmm14
689 pop %r10 /* the new xpc is return address */
690 sub $3,%r10 /* subtract 3 bytes for call */
697 call codegen_findmethod /* get the new data segment ptr */
704 mov %rcx,%rax /* restore saved exception pointer*/
708 mov %rax,0*8(%rsp) /* save exception pointer */
709 mov %r10,1*8(%rsp) /* save exception pc */
710 mov %r11,2*8(%rsp) /* save data segment pointer */
715 /* asm_wrapper_patcher *********************************************************
721 24 pointer to virtual java_objectheader
722 16 machine code (which is patched back later)
723 8 unresolved class/method/field reference
724 0 pointer to patcher function
726 *******************************************************************************/
729 sub $(19*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
731 SAVE_ARGUMENT_REGISTERS(0)
732 SAVE_TEMPORARY_REGISTERS(14)
734 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
735 mov itmp2,16*8(sp) /* can be used by some instructions */
737 mov sp,a0 /* create stackframe info */
739 xor a1,a1 /* if pv is NULL, use findmethod */
740 mov sp,a2 /* pass java sp */
741 add $((5+19)*8+sizestackframeinfo),a2
742 mov ((4+19)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
743 mov a3,a4 /* xpc is equal to ra */
744 call stacktrace_create_extern_stackframeinfo
746 mov sp,a0 /* pass stack pointer */
747 add $((1+19)*8+sizestackframeinfo),a0 /* skip function pointer */
748 mov (19*8+sizestackframeinfo)(sp),itmp3 /* get function pointer */
749 call *itmp3 /* call the patcher function */
750 mov v0,17*8(sp) /* save return value */
752 mov sp,a0 /* remove stackframe info */
754 call stacktrace_remove_stackframeinfo
756 RESTORE_ARGUMENT_REGISTERS(0)
757 RESTORE_TEMPORARY_REGISTERS(14)
759 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
760 mov 16*8(sp),itmp2 /* can be used by some instructions */
761 mov 17*8(sp),itmp3 /* restore return value */
763 add $((4+19)*8+sizestackframeinfo),sp /* remove stack frame, keep ra */
765 test itmp3,itmp3 /* exception thrown? */
766 jz L_asm_wrapper_patcher_exception
767 ret /* call new patched code */
769 L_asm_wrapper_patcher_exception:
770 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
771 call builtin_asm_get_exceptionptrptr
772 mov v0,itmp2 /* v0 == xptr */
774 lea _exceptionptr,itmp2
776 mov (itmp2),xptr /* get the exception pointer */
777 movl $0,(itmp2) /* clear exception pointer */
779 pop xpc /* get and remove return address */
780 jmp asm_handle_exception
783 /* asm_builtin_x2x *************************************************************
785 * Wrapper functions for float to int corner cases *
787 *******************************************************************************/
792 SAVE_ARGUMENT_REGISTERS(0)
797 RESTORE_ARGUMENT_REGISTERS(0)
806 SAVE_ARGUMENT_REGISTERS(0)
811 RESTORE_ARGUMENT_REGISTERS(0)
820 SAVE_ARGUMENT_REGISTERS(0)
825 RESTORE_ARGUMENT_REGISTERS(0)
834 SAVE_ARGUMENT_REGISTERS(0)
839 RESTORE_ARGUMENT_REGISTERS(0)
845 /******************* function asm_initialize_thread_stack **********************
847 * initialized a thread stack *
848 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
850 *******************************************************************************/
852 asm_initialize_thread_stack:
863 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
864 mov %rsi,%rax /* return restorepoint in %rax */
868 /******************* function asm_perform_threadswitch *************************
870 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
872 * performs a threadswitch *
874 *******************************************************************************/
876 asm_perform_threadswitch:
877 sub $(7*8),%rsp /* allocate stack frame */
886 mov 7*8(%rsp),%rax /* save current return address */
889 mov %rsp,(%rdi) /* first argument **from */
890 mov %rsp,(%rdx) /* third argument **stackTop */
892 mov (%rsi),%rsp /* load new stack pointer */
901 mov 6*8(%rsp),%rax /* restore return address */
902 add $(7*8),%rsp /* free stack frame */
907 /********************* function asm_switchstackandcall *************************
909 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
912 * Switches to a new stack, calls a function and switches back. *
913 * a0 (%rdi) new stack pointer *
914 * a1 (%rsi) function pointer *
915 * a2 (%rdx) pointer to variable where stack top should be stored *
916 * a3 (%rcx) pointer to user data, is passed to the function *
918 *******************************************************************************/
920 asm_switchstackandcall:
921 sub $(1*8),%rsp /* keep stack 16-byte aligned */
922 sub $16,%rdi /* allocate new stack */
924 mov 8(%rsp),%rax /* save return address on new stack */
926 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
927 mov %rsp,(%rdx) /* save old stack pointer to variable */
929 mov %rdi,%rsp /* switch to new stack */
931 mov %rcx,%rdi /* pass pointer */
932 call *%rsi /* and call function */
934 mov (%rsp),%r10 /* load return address */
935 mov 8(%rsp),%rsp /* switch to old stack */
936 add $(1*8),%rsp /* free stack space */
937 mov %r10,(%rsp) /* write return adress */
941 asm_getclassvalues_atomic:
944 movl offbaseval(a0),itmp1l
945 movl offdiffval(a0),itmp2l
946 movl offbaseval(a1),itmp3l
948 movl itmp1l,offcast_super_baseval(a2)
949 movl itmp2l,offcast_super_diffval(a2)
950 movl itmp3l,offcast_sub_baseval(a2)
955 asm_criticalsections:
956 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
968 * These are local overrides for various environment variables in Emacs.
969 * Please do not remove this and leave it at the end of the file, where
970 * Emacs will automagically detect them.
971 * ---------------------------------------------------------------------
974 * indent-tabs-mode: t