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 2956 2005-07-09 14:04:34Z 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 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
444 call builtin_asm_get_exceptionptrptr
447 lea _exceptionptr,itmp2
449 mov (itmp2),xptr /* get the exception pointer */
450 movl $0,(itmp2) /* clear the exception pointer */
452 pop xpc /* delete return address */
453 sub $5,xpc /* faulting address is ra - 5 */
455 jmp asm_handle_exception
458 /********************* function asm_handle_exception ***************************
460 * This function handles an exception. It does not use the usual calling *
461 * conventions. The exception pointer is passed in REG_ITMP1 and the *
462 * pc from the exception raising position is passed in REG_ITMP2. It searches *
463 * the local exception table for a handler. If no one is found, it unwinds *
464 * stacks and continues searching the callers. *
466 * void asm_handle_exception (exceptionptr, exceptionpc); *
468 *******************************************************************************/
470 asm_handle_nat_exception:
471 add $8,%rsp /* clear return address of native stub*/
473 asm_handle_exception:
475 mov xptr,0*8(%rsp) /* save exception pointer */
476 mov xpc,1*8(%rsp) /* save exception pc */
478 mov xpc,%rdi /* exception pc */
479 call codegen_findmethod
481 mov %rax,2*8(%rsp) /* save data segment pointer */
483 mov 0*8(%rsp),%rax /* restore exception pointer */
484 mov 1*8(%rsp),%r10 /* restore exception pc */
487 mov %rax,%rdi /* exception pointer */
488 mov MethodPointer(itmp3),%rsi /* method pointer */
489 mov xpc,%rdx /* exception pc */
491 mov $1,%r8 /* set noindent flag */
492 call builtin_trace_exception
494 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
495 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
496 test %rcx,%rcx /* if empty table skip */
499 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
500 mov 0*8(%rsp),xptr /* get xptr */
503 mov 1*8(%rsp),xpc /* get xpc */
505 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
506 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
507 jg ex_table_cont /* if (false) continue */
508 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
509 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
510 jge ex_table_cont /* if (false) continue */
511 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
512 test %rdx,%rdx /* NULL catches everything */
515 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
525 call load_class_bootstrap
534 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
553 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
561 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
562 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
563 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
564 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
565 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
567 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
569 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
573 cmp %edx,%esi /* xptr is instanceof catchtype */
577 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
579 mov 0*8(%rsp),%rax /* restore exception pointer */
580 add $(4*8),%rsp /* free stack frame */
582 jmp *xpc /* jump to the handler */
585 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
586 dec %rcx /* decrement entry counter */
587 test %rcx,%rcx /* if (t0 > 0) next entry */
591 mov 0*8(%rsp),%rax /* restore exception pointer */
592 mov 1*8(%rsp),%r10 /* restore exception pc */
593 mov 2*8(%rsp),%r11 /* restore data segment pointer */
596 mov %rax,%rcx /* save exception pointer */
599 movl IsSync(%r11),%eax /* %rax = SyncOffset */
600 test %rax,%rax /* if zero no monitorexit */
603 #if defined(USE_THREADS)
612 call builtin_monitorexit
621 mov FrameSize(%r11),%eax /* %eax = frame size */
622 add %rax,%rsp /* unwind stack */
623 mov %rsp,%rax /* %rax = pointer to save area */
625 mov IntSave(%r11),%edx /* %edx = saved int register count*/
652 shl $3,%edx /* multiply by 8 bytes */
656 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
679 movq -48(%rax),%xmm10
681 movq -40(%rax),%xmm11
683 movq -32(%rax),%xmm12
685 movq -24(%rax),%xmm13
687 movq -16(%rax),%xmm14
692 pop %r10 /* the new xpc is return address */
693 sub $3,%r10 /* subtract 3 bytes for call */
700 call codegen_findmethod /* get the new data segment ptr */
707 mov %rcx,%rax /* restore saved exception pointer*/
711 mov %rax,0*8(%rsp) /* save exception pointer */
712 mov %r10,1*8(%rsp) /* save exception pc */
713 mov %r11,2*8(%rsp) /* save data segment pointer */
718 /* asm_wrapper_patcher *********************************************************
724 24 pointer to virtual java_objectheader
725 16 machine code (which is patched back later)
726 8 unresolved class/method/field reference
727 0 pointer to patcher function
729 *******************************************************************************/
732 sub $(19*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
734 SAVE_ARGUMENT_REGISTERS(0)
735 SAVE_TEMPORARY_REGISTERS(14)
737 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
738 mov itmp2,16*8(sp) /* can be used by some instructions */
740 mov sp,a0 /* create stackframe info */
742 xor a1,a1 /* if pv is NULL, use findmethod */
744 add $((5+19)*8+sizestackframeinfo),a2
745 mov ((4+19)*8+sizestackframeinfo)(sp),a3
746 call stacktrace_create_inline_stackframeinfo
748 mov sp,a0 /* pass stack pointer */
749 add $((1+19)*8+sizestackframeinfo),a0 /* skip function pointer */
750 mov (19*8+sizestackframeinfo)(sp),itmp3 /* get function pointer */
751 call *itmp3 /* call the patcher function */
752 mov v0,17*8(sp) /* save return value */
754 mov sp,a0 /* remove stackframe info */
756 call stacktrace_remove_stackframeinfo
758 RESTORE_ARGUMENT_REGISTERS(0)
759 RESTORE_TEMPORARY_REGISTERS(14)
761 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
762 mov 16*8(sp),itmp2 /* can be used by some instructions */
763 mov 17*8(sp),itmp3 /* restore return value */
765 add $((4+19)*8+sizestackframeinfo),sp /* remove stack frame, keep ra */
767 test itmp3,itmp3 /* exception thrown? */
768 jz L_asm_wrapper_patcher_exception
769 ret /* call new patched code */
771 L_asm_wrapper_patcher_exception:
772 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
773 call builtin_asm_get_exceptionptrptr
774 mov v0,itmp2 /* v0 == xptr */
776 lea _exceptionptr,itmp2
778 mov (itmp2),xptr /* get the exception pointer */
779 movl $0,(itmp2) /* clear exception pointer */
781 pop xpc /* get and remove return address */
782 jmp asm_handle_exception
785 /* asm_builtin_x2x *************************************************************
787 * Wrapper functions for float to int corner cases *
789 *******************************************************************************/
794 SAVE_ARGUMENT_REGISTERS(0)
799 RESTORE_ARGUMENT_REGISTERS(0)
808 SAVE_ARGUMENT_REGISTERS(0)
813 RESTORE_ARGUMENT_REGISTERS(0)
822 SAVE_ARGUMENT_REGISTERS(0)
827 RESTORE_ARGUMENT_REGISTERS(0)
836 SAVE_ARGUMENT_REGISTERS(0)
841 RESTORE_ARGUMENT_REGISTERS(0)
847 /******************* function asm_initialize_thread_stack **********************
849 * initialized a thread stack *
850 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
852 *******************************************************************************/
854 asm_initialize_thread_stack:
865 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
866 mov %rsi,%rax /* return restorepoint in %rax */
870 /******************* function asm_perform_threadswitch *************************
872 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
874 * performs a threadswitch *
876 *******************************************************************************/
878 asm_perform_threadswitch:
879 sub $(7*8),%rsp /* allocate stack frame */
888 mov 7*8(%rsp),%rax /* save current return address */
891 mov %rsp,(%rdi) /* first argument **from */
892 mov %rsp,(%rdx) /* third argument **stackTop */
894 mov (%rsi),%rsp /* load new stack pointer */
903 mov 6*8(%rsp),%rax /* restore return address */
904 add $(7*8),%rsp /* free stack frame */
909 /********************* function asm_switchstackandcall *************************
911 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
914 * Switches to a new stack, calls a function and switches back. *
915 * a0 (%rdi) new stack pointer *
916 * a1 (%rsi) function pointer *
917 * a2 (%rdx) pointer to variable where stack top should be stored *
918 * a3 (%rcx) pointer to user data, is passed to the function *
920 *******************************************************************************/
922 asm_switchstackandcall:
923 sub $(1*8),%rsp /* keep stack 16-byte aligned */
924 sub $16,%rdi /* allocate new stack */
926 mov 8(%rsp),%rax /* save return address on new stack */
928 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
929 mov %rsp,(%rdx) /* save old stack pointer to variable */
931 mov %rdi,%rsp /* switch to new stack */
933 mov %rcx,%rdi /* pass pointer */
934 call *%rsi /* and call function */
936 mov (%rsp),%r10 /* load return address */
937 mov 8(%rsp),%rsp /* switch to old stack */
938 add $(1*8),%rsp /* free stack space */
939 mov %r10,(%rsp) /* write return adress */
943 asm_getclassvalues_atomic:
946 movl offbaseval(a0),itmp1l
947 movl offdiffval(a0),itmp2l
948 movl offbaseval(a1),itmp3l
950 movl itmp1l,offcast_super_baseval(a2)
951 movl itmp2l,offcast_super_diffval(a2)
952 movl itmp3l,offcast_sub_baseval(a2)
957 asm_criticalsections:
958 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
970 * These are local overrides for various environment variables in Emacs.
971 * Please do not remove this and leave it at the end of the file, where
972 * Emacs will automagically detect them.
973 * ---------------------------------------------------------------------
976 * indent-tabs-mode: t