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 3096 2005-07-21 14:01:02Z 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 $((3+24)*8+sizestackframeinfo),sp /* keep stack 16-byte aligned */
390 mov %rbx,0*8(%rsp) /* save register */
392 mov (3+24)*8+sizestackframeinfo(%rsp),itmp3 /* get return address */
393 mov -1(itmp3),%bl /* get function code */
394 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
395 jne L_not_static_special
397 sub $11,itmp3 /* 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,itmp3 /* calculate address of offset */
405 mov (itmp3),itmp3l /* get offset (32-bit) */
406 add itmp2,itmp3 /* 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 0*8(sp),%rbx /* restore register */
414 mov itmp3,0*8(sp) /* save address for method pointer */
415 mov itmp1,1*8(sp) /* save method pointer */
417 SAVE_ARGUMENT_REGISTERS(2)
419 mov sp,a0 /* create stackframe info */
420 add $((3+24)*8),a0 /* pass sfi */
421 xor a1,a1 /* if pv is NULL, use findmethod */
422 mov sp,a2 /* pass java sp */
423 add $((1+3+24)*8+sizestackframeinfo),a2
424 mov ((3+24)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
425 mov a3,a4 /* xpc is equal to ra */
426 call stacktrace_create_extern_stackframeinfo
428 mov 1*8(sp),a0 /* pass method pointer */
430 mov v0,1*8(sp) /* save return value */
432 mov sp,a0 /* remove stackframe info */
433 add $((3+24)*8),a0 /* pass sfi */
434 call stacktrace_remove_stackframeinfo
436 mov 0*8(sp),itmp3 /* restore address for method pointer */
437 mov 1*8(sp),v0 /* restore return value */
439 RESTORE_ARGUMENT_REGISTERS(2)
441 add $((3+24)*8+sizestackframeinfo),sp /* remove stack frame */
443 test v0,v0 /* check for exception */
444 je L_asm_call_jit_compiler_exception
446 test %r11,%r11 /* is address == 0 (asm_calljavamethod*/
449 mov %rax,(%r11) /* and now save the new pointer */
452 jmp *%rax /* ...and now call the new method */
454 L_asm_call_jit_compiler_exception:
455 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
456 call builtin_asm_get_exceptionptrptr
457 mov v0,itmp2 /* v0 == xptr */
459 lea _exceptionptr,itmp2
461 mov (itmp2),xptr /* get the exception pointer */
462 movl $0,(itmp2) /* clear exception pointer */
464 pop xpc /* delete return address */
465 sub $5,xpc /* faulting address is ra - 5 */
466 jmp asm_handle_exception
469 /********************* function asm_handle_exception ***************************
471 * This function handles an exception. It does not use the usual calling *
472 * conventions. The exception pointer is passed in REG_ITMP1 and the *
473 * pc from the exception raising position is passed in REG_ITMP2. It searches *
474 * the local exception table for a handler. If no one is found, it unwinds *
475 * stacks and continues searching the callers. *
477 * void asm_handle_exception (exceptionptr, exceptionpc); *
479 *******************************************************************************/
481 asm_handle_nat_exception:
482 add $8,%rsp /* clear return address of native stub*/
484 asm_handle_exception:
486 mov xptr,0*8(%rsp) /* save exception pointer */
487 mov xpc,1*8(%rsp) /* save exception pc */
489 mov xpc,%rdi /* exception pc */
490 call codegen_findmethod
492 mov %rax,2*8(%rsp) /* save data segment pointer */
494 mov 0*8(%rsp),%rax /* restore exception pointer */
495 mov 1*8(%rsp),%r10 /* restore exception pc */
498 mov %rax,%rdi /* exception pointer */
499 mov MethodPointer(itmp3),%rsi /* method pointer */
500 mov xpc,%rdx /* exception pc */
502 mov $1,%r8 /* set noindent flag */
503 call builtin_trace_exception
505 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
506 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
507 test %rcx,%rcx /* if empty table skip */
510 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
511 mov 0*8(%rsp),xptr /* get xptr */
514 mov 1*8(%rsp),xpc /* get xpc */
516 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
517 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
518 jg ex_table_cont /* if (false) continue */
519 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
520 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
521 jge ex_table_cont /* if (false) continue */
522 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
523 test %rdx,%rdx /* NULL catches everything */
526 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
536 call load_class_bootstrap
545 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
564 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
572 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
573 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
574 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
575 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
576 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
578 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
580 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
584 cmp %edx,%esi /* xptr is instanceof catchtype */
588 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
590 mov 0*8(%rsp),%rax /* restore exception pointer */
591 add $(4*8),%rsp /* free stack frame */
593 jmp *xpc /* jump to the handler */
596 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
597 dec %rcx /* decrement entry counter */
598 test %rcx,%rcx /* if (t0 > 0) next entry */
602 mov 0*8(%rsp),%rax /* restore exception pointer */
603 mov 1*8(%rsp),%r10 /* restore exception pc */
604 mov 2*8(%rsp),%r11 /* restore data segment pointer */
607 mov %rax,%rcx /* save exception pointer */
610 movl IsSync(%r11),%eax /* %rax = SyncOffset */
611 test %rax,%rax /* if zero no monitorexit */
614 #if defined(USE_THREADS)
623 call builtin_monitorexit
632 mov FrameSize(%r11),%eax /* %eax = frame size */
633 add %rax,%rsp /* unwind stack */
634 mov %rsp,%rax /* %rax = pointer to save area */
636 mov IntSave(%r11),%edx /* %edx = saved int register count*/
663 shl $3,%edx /* multiply by 8 bytes */
667 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
690 movq -48(%rax),%xmm10
692 movq -40(%rax),%xmm11
694 movq -32(%rax),%xmm12
696 movq -24(%rax),%xmm13
698 movq -16(%rax),%xmm14
703 pop %r10 /* the new xpc is return address */
704 sub $3,%r10 /* subtract 3 bytes for call */
711 call codegen_findmethod /* get the new data segment ptr */
718 mov %rcx,%rax /* restore saved exception pointer*/
722 mov %rax,0*8(%rsp) /* save exception pointer */
723 mov %r10,1*8(%rsp) /* save exception pc */
724 mov %r11,2*8(%rsp) /* save data segment pointer */
729 /* asm_wrapper_patcher *********************************************************
735 32 pointer to virtual java_objectheader
736 24 machine code (which is patched back later)
737 16 unresolved class/method/field reference
738 8 data segment displacement from load instructions
739 0 pointer to patcher function
741 *******************************************************************************/
744 sub $(19*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
746 SAVE_ARGUMENT_REGISTERS(0)
747 SAVE_TEMPORARY_REGISTERS(14)
749 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
750 mov itmp2,16*8(sp) /* can be used by some instructions */
752 mov sp,a0 /* create stackframe info */
754 xor a1,a1 /* if pv is NULL, use findmethod */
755 mov sp,a2 /* pass java sp */
756 add $((6+19)*8+sizestackframeinfo),a2
757 mov ((5+19)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
758 mov a3,a4 /* xpc is equal to ra */
759 call stacktrace_create_extern_stackframeinfo
761 mov sp,a0 /* pass stack pointer */
762 add $((1+19)*8+sizestackframeinfo),a0 /* skip function pointer */
763 mov (19*8+sizestackframeinfo)(sp),itmp3 /* get function pointer */
764 call *itmp3 /* call the patcher function */
765 mov v0,17*8(sp) /* save return value */
767 mov sp,a0 /* remove stackframe info */
769 call stacktrace_remove_stackframeinfo
771 RESTORE_ARGUMENT_REGISTERS(0)
772 RESTORE_TEMPORARY_REGISTERS(14)
774 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
775 mov 16*8(sp),itmp2 /* can be used by some instructions */
776 mov 17*8(sp),itmp3 /* restore return value */
778 add $((5+19)*8+sizestackframeinfo),sp /* remove stack frame, keep ra */
780 test itmp3,itmp3 /* exception thrown? */
781 jz L_asm_wrapper_patcher_exception
782 ret /* call new patched code */
784 L_asm_wrapper_patcher_exception:
785 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
786 call builtin_asm_get_exceptionptrptr
787 mov v0,itmp2 /* v0 == xptr */
789 lea _exceptionptr,itmp2
791 mov (itmp2),xptr /* get the exception pointer */
792 movl $0,(itmp2) /* clear exception pointer */
794 pop xpc /* get and remove return address */
795 jmp asm_handle_exception
798 /* asm_builtin_x2x *************************************************************
800 * Wrapper functions for float to int corner cases *
802 *******************************************************************************/
807 SAVE_ARGUMENT_REGISTERS(0)
812 RESTORE_ARGUMENT_REGISTERS(0)
821 SAVE_ARGUMENT_REGISTERS(0)
826 RESTORE_ARGUMENT_REGISTERS(0)
835 SAVE_ARGUMENT_REGISTERS(0)
840 RESTORE_ARGUMENT_REGISTERS(0)
849 SAVE_ARGUMENT_REGISTERS(0)
854 RESTORE_ARGUMENT_REGISTERS(0)
860 /******************* function asm_initialize_thread_stack **********************
862 * initialized a thread stack *
863 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
865 *******************************************************************************/
867 asm_initialize_thread_stack:
878 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
879 mov %rsi,%rax /* return restorepoint in %rax */
883 /******************* function asm_perform_threadswitch *************************
885 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
887 * performs a threadswitch *
889 *******************************************************************************/
891 asm_perform_threadswitch:
892 sub $(7*8),%rsp /* allocate stack frame */
901 mov 7*8(%rsp),%rax /* save current return address */
904 mov %rsp,(%rdi) /* first argument **from */
905 mov %rsp,(%rdx) /* third argument **stackTop */
907 mov (%rsi),%rsp /* load new stack pointer */
916 mov 6*8(%rsp),%rax /* restore return address */
917 add $(7*8),%rsp /* free stack frame */
922 /********************* function asm_switchstackandcall *************************
924 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
927 * Switches to a new stack, calls a function and switches back. *
928 * a0 (%rdi) new stack pointer *
929 * a1 (%rsi) function pointer *
930 * a2 (%rdx) pointer to variable where stack top should be stored *
931 * a3 (%rcx) pointer to user data, is passed to the function *
933 *******************************************************************************/
935 asm_switchstackandcall:
936 sub $(1*8),%rsp /* keep stack 16-byte aligned */
937 sub $16,%rdi /* allocate new stack */
939 mov 8(%rsp),%rax /* save return address on new stack */
941 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
942 mov %rsp,(%rdx) /* save old stack pointer to variable */
944 mov %rdi,%rsp /* switch to new stack */
946 mov %rcx,%rdi /* pass pointer */
947 call *%rsi /* and call function */
949 mov (%rsp),%r10 /* load return address */
950 mov 8(%rsp),%rsp /* switch to old stack */
951 add $(1*8),%rsp /* free stack space */
952 mov %r10,(%rsp) /* write return adress */
956 asm_getclassvalues_atomic:
959 movl offbaseval(a0),itmp1l
960 movl offdiffval(a0),itmp2l
961 movl offbaseval(a1),itmp3l
963 movl itmp1l,offcast_super_baseval(a2)
964 movl itmp2l,offcast_super_diffval(a2)
965 movl itmp3l,offcast_sub_baseval(a2)
970 asm_criticalsections:
971 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
983 * These are local overrides for various environment variables in Emacs.
984 * Please do not remove this and leave it at the end of the file, where
985 * Emacs will automagically detect them.
986 * ---------------------------------------------------------------------
989 * indent-tabs-mode: t