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
33 $Id: asmpart.S 3495 2005-10-26 13:29:53Z twisti $
43 #include "vm/jit/x86_64/arch.h"
44 #include "vm/jit/x86_64/offsets.h"
46 #include "vm/jit/methodheader.h"
52 /********************* exported functions and variables ***********************/
54 .globl asm_calljavafunction
55 .globl asm_calljavafunction_int
57 .globl asm_calljavafunction2
58 .globl asm_calljavafunction2int
59 .globl asm_calljavafunction2long
60 .globl asm_calljavafunction2float
61 .globl asm_calljavafunction2double
63 .globl asm_call_jit_compiler
64 .globl asm_handle_exception
65 .globl asm_handle_nat_exception
67 .globl asm_wrapper_patcher
69 .globl asm_builtin_arraycheckcast
71 .globl asm_builtin_f2i
72 .globl asm_builtin_f2l
73 .globl asm_builtin_d2i
74 .globl asm_builtin_d2l
76 .globl asm_perform_threadswitch
77 .globl asm_initialize_thread_stack
78 .globl asm_switchstackandcall
79 .globl asm_criticalsections
80 .globl asm_getclassvalues_atomic
83 /********************* function asm_calljavafunction ***************************
85 * This function calls a Java-method (which possibly needs compilation) *
86 * with up to 4 address parameters. *
88 * This functions calls the JIT-compiler which eventually translates the *
89 * method into machine code. *
92 * javaobject_header *asm_calljavamethod (methodinfo *m, *
93 * void *arg1, void *arg2, void *arg3, void *arg4); *
95 *******************************************************************************/
100 .quad 0 /* catch type all */
101 .quad calljava_xhandler /* handler pc */
102 .quad calljava_xhandler /* end pc */
103 .quad asm_calljavafunction /* start pc */
104 .long 1 /* extable size */
106 .quad 0 /* line number table start */
107 .quad 0 /* line number table size */
109 .long 0 /* fltsave */
110 .long 0 /* intsave */
113 .long 8 /* frame size */
114 .quad 0 /* method pointer (pointer to name) */
116 asm_calljavafunction:
117 asm_calljavafunction_int:
118 sub $(3*8),%rsp /* keep stack 16-byte aligned */
120 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
121 mov %rdi,%rax /* move function pointer to %rax */
122 /* compilerstub uses this */
124 mov %rsi,%rdi /* pass remaining parameters */
129 lea asm_call_jit_compiler,%r11
130 call *%r11 /* call JIT compiler */
134 add $(3*8),%rsp /* free stack space */
138 mov %rax,%rdi /* pass exception pointer */
139 call builtin_throw_exception
143 xor %rax,%rax /* return NULL */
147 /********************* function asm_calljavafunction ***************************
149 * This function calls a Java-method (which possibly needs compilation) *
150 * with up to 4 address parameters. *
152 * This functions calls the JIT-compiler which eventually translates the *
153 * method into machine code. *
156 * javaobject_header *asm_calljavamethod (methodinfo *m, *
157 * void *arg1, void *arg2, void *arg3, void *arg4); *
159 *******************************************************************************/
164 .quad 0 /* catch type all */
165 .quad calljava_xhandler2 /* handler pc */
166 .quad calljava_xhandler2 /* end pc */
167 .quad asm_calljavafunction2 /* start pc */
168 .long 1 /* extable size */
170 .quad 0 /* line number table start */
171 .quad 0 /* line number table size */
173 .long 0 /* fltsave */
174 .long 0 /* intsave */
177 .long 24 /* frame size */
178 .quad 0 /* method pointer (pointer to name) */
180 asm_calljavafunction2:
181 asm_calljavafunction2int:
182 asm_calljavafunction2long:
183 asm_calljavafunction2float:
184 asm_calljavafunction2double:
185 sub $(7*8),%rsp /* keep stack 16-byte aligned */
186 mov %rbx,0*8(%rsp) /* %rbx is not a callee saved in cacao */
193 mov %rdi,%rax /* move method pointer for compiler */
194 xor %rbp,%rbp /* set argument stack frame to zero */
196 test %rsi,%rsi /* maybe we have no args... */
199 mov %rsi,itmp3 /* arg count */
200 mov %rcx,itmp2 /* pointer to arg block */
202 mov itmp2,%r14 /* save argument block pointer */
203 mov itmp3,%r15 /* save argument count */
205 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
206 add $1,itmp3 /* initialize argument count */
207 xor %r12,%r12 /* initialize integer argument counter */
208 xor %r13,%r13 /* initialize float argument counter */
211 add $sizejniblock,itmp2 /* goto next argument block */
212 dec itmp3 /* argument count - 1 */
213 jz L_register_copy_done
214 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
215 jnz L_register_handle_float /* yes, handle it */
217 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
218 je L_register_copy /* register? yes, next loop */
220 lea jumptable_integer,%rbp
221 mov 0(%rbp,%r12,8),%rbx
222 inc %r12 /* integer argument counter + 1 */
225 L_register_handle_float:
226 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
227 je L_register_copy /* register? yes, next loop */
229 lea jumptable_float,%rbp
230 mov 0(%rbp,%r13,8),%rbx
231 inc %r13 /* float argument counter + 1 */
234 L_register_copy_done:
235 mov %r15,%rbp /* calculate remaining arguments */
236 sub %r12,%rbp /* - integer arguments in registers */
237 sub %r13,%rbp /* - float arguments in registers */
238 jle L_copy_done /* are all assigned to registers? */
240 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
241 shl $3,%rbp /* calculate stack size */
242 sub %rbp,%rsp /* stack frame for arguments */
243 mov %rsp,%rbx /* use %rbx as temp sp */
245 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
246 add $1,%r15 /* initialize argument count */
249 add $sizejniblock,%r14 /* goto next argument block */
250 dec %r15 /* are there any arguments left? */
251 jz L_copy_done /* no test needed after dec */
253 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
254 jnz L_stack_handle_float
255 dec %r12 /* arguments assigned to registers */
256 jge L_stack_copy_loop
259 L_stack_handle_float:
260 dec %r13 /* arguments assigned to registers */
261 jge L_stack_copy_loop
264 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
266 add $8,%rbx /* increase sp to next argument */
267 jmp L_stack_copy_loop
270 lea asm_call_jit_compiler,%r11/* %rax still contains method pointer */
271 call *%r11 /* call JIT compiler */
273 add %rbp,%rsp /* remove argument stack frame if any */
275 mov 5*8(%rsp),%r15 /* restore callee saved registers */
281 add $(7*8),%rsp /* free stack space */
285 mov %rax,%rdi /* pass exception pointer */
286 call builtin_throw_exception
288 mov 5*8(%rsp),%r15 /* restore callee saved registers */
294 add $(7*8),%rsp /* free stack space */
295 xor %rax,%rax /* return NULL */
308 mov offjniitem(itmp2),a0
311 mov offjniitem(itmp2),a1
314 mov offjniitem(itmp2),a2
317 mov offjniitem(itmp2),a3
320 mov offjniitem(itmp2),a4
323 mov offjniitem(itmp2),a5
338 movq offjniitem(itmp2),fa0
341 movq offjniitem(itmp2),fa1
344 movq offjniitem(itmp2),fa2
347 movq offjniitem(itmp2),fa3
350 movq offjniitem(itmp2),fa4
353 movq offjniitem(itmp2),fa5
356 movq offjniitem(itmp2),fa6
359 movq offjniitem(itmp2),fa7
363 /****************** function asm_call_jit_compiler *****************************
365 * invokes the compiler for untranslated JavaVM methods. *
367 * Register R0 contains a pointer to the method info structure (prepared *
368 * by createcompilerstub). Using the return address in R26 and the *
369 * offset in the LDA instruction or using the value in methodptr R28 the *
370 * patching address for storing the method address can be computed: *
372 * method address was either loaded using *
374 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
375 * i386_call_reg(REG_ITMP2) *
379 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
380 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
381 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
382 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
383 * i386_call_reg(REG_ITMP1) *
385 * in the static case the method pointer can be computed using the *
386 * return address and the lda function following the jmp instruction *
388 *******************************************************************************/
390 asm_call_jit_compiler:
391 sub $((3+24)*8+sizestackframeinfo),sp /* keep stack 16-byte aligned */
393 mov %rbx,0*8(%rsp) /* save register */
395 mov (3+24)*8+sizestackframeinfo(%rsp),itmp3 /* get return address */
396 mov -1(itmp3),%bl /* get function code */
397 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
398 jne L_not_static_special
400 sub $11,itmp3 /* calculate address of immediate */
401 jmp L_call_jit_compile
403 L_not_static_special:
404 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
405 jne L_not_virtual_interface
407 sub $7,itmp3 /* calculate address of offset */
408 mov (itmp3),itmp3l /* get offset (32-bit) */
409 add itmp2,itmp3 /* add base address to get method address */
410 jmp L_call_jit_compile
412 L_not_virtual_interface: /* a call from asm_calljavamethod */
416 mov 0*8(sp),%rbx /* restore register */
417 mov itmp3,0*8(sp) /* save address for method pointer */
418 mov itmp1,1*8(sp) /* save method pointer */
420 SAVE_ARGUMENT_REGISTERS(2)
422 mov sp,a0 /* create stackframe info */
423 add $((3+24)*8),a0 /* pass sfi */
424 xor a1,a1 /* if pv is NULL, use findmethod */
425 mov sp,a2 /* pass java sp */
426 add $((1+3+24)*8+sizestackframeinfo),a2
427 mov ((3+24)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
428 mov a3,a4 /* xpc is equal to ra */
429 call stacktrace_create_extern_stackframeinfo
431 mov 1*8(sp),a0 /* pass method pointer */
433 mov v0,1*8(sp) /* save return value */
435 mov sp,a0 /* remove stackframe info */
436 add $((3+24)*8),a0 /* pass sfi */
437 call stacktrace_remove_stackframeinfo
439 mov 0*8(sp),itmp3 /* restore address for method pointer */
440 mov 1*8(sp),v0 /* restore return value */
442 RESTORE_ARGUMENT_REGISTERS(2)
444 add $((3+24)*8+sizestackframeinfo),sp /* remove stack frame */
446 test v0,v0 /* check for exception */
447 je L_asm_call_jit_compiler_exception
449 test %r11,%r11 /* is address == 0 (asm_calljavamethod*/
452 mov %rax,(%r11) /* and now save the new pointer */
455 jmp *%rax /* ...and now call the new method */
457 L_asm_call_jit_compiler_exception:
458 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
459 call builtin_asm_get_exceptionptrptr
460 mov v0,itmp2 /* v0 == xptr */
462 lea _no_threads_exceptionptr,itmp2
464 mov (itmp2),xptr /* get the exception pointer */
465 movl $0,(itmp2) /* clear exception pointer */
467 pop xpc /* delete return address */
468 sub $5,xpc /* faulting address is ra - 5 */
469 jmp asm_handle_exception
472 /********************* function asm_handle_exception ***************************
474 * This function handles an exception. It does not use the usual calling *
475 * conventions. The exception pointer is passed in REG_ITMP1 and the *
476 * pc from the exception raising position is passed in REG_ITMP2. It searches *
477 * the local exception table for a handler. If no one is found, it unwinds *
478 * stacks and continues searching the callers. *
480 * void asm_handle_exception (exceptionptr, exceptionpc); *
482 *******************************************************************************/
484 asm_handle_nat_exception:
485 add $8,%rsp /* clear return address of native stub*/
487 asm_handle_exception:
489 mov xptr,0*8(%rsp) /* save exception pointer */
490 mov xpc,1*8(%rsp) /* save exception pc */
492 mov xpc,%rdi /* exception pc */
493 call codegen_findmethod
495 mov %rax,2*8(%rsp) /* save data segment pointer */
497 mov 0*8(%rsp),%rax /* restore exception pointer */
498 mov 1*8(%rsp),%r10 /* restore exception pc */
500 xor a3,a3 /* clear indent flag (only first time)*/
503 mov %rax,a0 /* exception pointer */
504 mov MethodPointer(itmp3),a1 /* method pointer */
505 mov xpc,a2 /* exception pc */
506 call builtin_trace_exception
508 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
509 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
510 test %rcx,%rcx /* if empty table skip */
513 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
514 mov 0*8(%rsp),xptr /* get xptr */
517 mov 1*8(%rsp),xpc /* get xpc */
519 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
520 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
521 jg ex_table_cont /* if (false) continue */
522 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
523 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
524 jge ex_table_cont /* if (false) continue */
525 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
526 test %rdx,%rdx /* NULL catches everything */
529 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
539 call load_class_bootstrap
548 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
567 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
575 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
576 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
577 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
578 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
579 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
581 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
583 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
587 cmp %edx,%esi /* xptr is instanceof catchtype */
591 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
593 mov 0*8(%rsp),%rax /* restore exception pointer */
594 add $(4*8),%rsp /* free stack frame */
596 jmp *xpc /* jump to the handler */
599 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
600 dec %rcx /* decrement entry counter */
601 test %rcx,%rcx /* if (t0 > 0) next entry */
605 mov 0*8(%rsp),%rax /* restore exception pointer */
606 mov 1*8(%rsp),%r10 /* restore exception pc */
607 mov 2*8(%rsp),%r11 /* restore data segment pointer */
610 mov %rax,%rcx /* save exception pointer */
613 movl IsSync(%r11),%eax /* %rax = SyncOffset */
614 test %rax,%rax /* if zero no monitorexit */
617 #if defined(USE_THREADS)
626 call builtin_monitorexit
635 mov FrameSize(%r11),%eax /* %eax = frame size */
636 add %rax,%rsp /* unwind stack */
637 mov %rsp,%rax /* %rax = pointer to save area */
639 mov IntSave(%r11),%edx /* %edx = saved int register count */
666 shl $3,%edx /* multiply by 8 bytes */
670 mov FltSave(%r11),%edx /* %edx = saved flt register count */
693 movq -48(%rax),%xmm10
695 movq -40(%rax),%xmm11
697 movq -32(%rax),%xmm12
699 movq -24(%rax),%xmm13
701 movq -16(%rax),%xmm14
706 pop %r10 /* the new xpc is return address */
707 sub $3,%r10 /* subtract 3 bytes for call */
714 call codegen_findmethod /* get the new data segment ptr */
721 mov %rcx,%rax /* restore saved exception pointer */
725 mov %rax,0*8(%rsp) /* save exception pointer */
726 mov %r10,1*8(%rsp) /* save exception pc */
727 mov %r11,2*8(%rsp) /* save data segment pointer */
729 mov $1,a3 /* set indent flag */
734 /* asm_wrapper_patcher *********************************************************
740 32 pointer to virtual java_objectheader
741 24 machine code (which is patched back later)
742 16 unresolved class/method/field reference
743 8 data segment displacement from load instructions
744 0 pointer to patcher function
746 *******************************************************************************/
749 sub $(18*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
751 SAVE_ARGUMENT_REGISTERS(0)
752 SAVE_TEMPORARY_REGISTERS(14)
754 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
755 mov itmp2,16*8(sp) /* can be used by some instructions */
757 mov sp,a0 /* create stackframe info */
759 xor a1,a1 /* if pv is NULL, use findmethod */
760 mov sp,a2 /* pass java sp */
761 add $((6+18)*8+sizestackframeinfo),a2
762 mov ((5+18)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
763 mov a3,a4 /* xpc is equal to ra */
764 call stacktrace_create_extern_stackframeinfo
766 mov sp,a0 /* pass stack pointer */
767 add $((1+18)*8+sizestackframeinfo),a0 /* skip function pointer */
768 mov (18*8+sizestackframeinfo)(sp),itmp3 /* get function pointer */
769 call *itmp3 /* call the patcher function */
770 mov v0,17*8(sp) /* save return value */
772 mov sp,a0 /* remove stackframe info */
774 call stacktrace_remove_stackframeinfo
776 RESTORE_ARGUMENT_REGISTERS(0)
777 RESTORE_TEMPORARY_REGISTERS(14)
779 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
780 mov 16*8(sp),itmp2 /* can be used by some instructions */
781 mov 17*8(sp),itmp3 /* restore return value */
783 add $((5+18)*8+sizestackframeinfo),sp /* remove stack frame, keep ra */
785 test itmp3,itmp3 /* exception thrown? */
786 jz L_asm_wrapper_patcher_exception
787 ret /* call new patched code */
789 L_asm_wrapper_patcher_exception:
790 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
791 call builtin_asm_get_exceptionptrptr
792 mov v0,itmp2 /* v0 == xptr */
794 lea _no_threads_exceptionptr,itmp2
796 mov (itmp2),xptr /* get the exception pointer */
797 movl $0,(itmp2) /* clear exception pointer */
799 pop xpc /* get and remove return address */
800 jmp asm_handle_exception
803 /* asm_builtin_x2x *************************************************************
805 * Wrapper functions for float to int corner cases *
807 *******************************************************************************/
812 SAVE_ARGUMENT_REGISTERS(0)
817 RESTORE_ARGUMENT_REGISTERS(0)
826 SAVE_ARGUMENT_REGISTERS(0)
831 RESTORE_ARGUMENT_REGISTERS(0)
840 SAVE_ARGUMENT_REGISTERS(0)
845 RESTORE_ARGUMENT_REGISTERS(0)
854 SAVE_ARGUMENT_REGISTERS(0)
859 RESTORE_ARGUMENT_REGISTERS(0)
865 /******************* function asm_initialize_thread_stack **********************
867 * initialized a thread stack *
868 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
870 *******************************************************************************/
872 asm_initialize_thread_stack:
883 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
884 mov %rsi,%rax /* return restorepoint in %rax */
888 /******************* function asm_perform_threadswitch *************************
890 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
892 * performs a threadswitch *
894 *******************************************************************************/
896 asm_perform_threadswitch:
897 sub $(7*8),%rsp /* allocate stack frame */
906 mov 7*8(%rsp),%rax /* save current return address */
909 mov %rsp,(%rdi) /* first argument **from */
910 mov %rsp,(%rdx) /* third argument **stackTop */
912 mov (%rsi),%rsp /* load new stack pointer */
921 mov 6*8(%rsp),%rax /* restore return address */
922 add $(7*8),%rsp /* free stack frame */
927 /********************* function asm_switchstackandcall *************************
929 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
932 * Switches to a new stack, calls a function and switches back. *
933 * a0 (%rdi) new stack pointer *
934 * a1 (%rsi) function pointer *
935 * a2 (%rdx) pointer to variable where stack top should be stored *
936 * a3 (%rcx) pointer to user data, is passed to the function *
938 *******************************************************************************/
940 asm_switchstackandcall:
941 sub $(1*8),%rsp /* keep stack 16-byte aligned */
942 sub $16,%rdi /* allocate new stack */
944 mov 8(%rsp),%rax /* save return address on new stack */
946 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
947 mov %rsp,(%rdx) /* save old stack pointer to variable */
949 mov %rdi,%rsp /* switch to new stack */
951 mov %rcx,%rdi /* pass pointer */
952 call *%rsi /* and call function */
954 mov (%rsp),%r10 /* load return address */
955 mov 8(%rsp),%rsp /* switch to old stack */
956 add $(1*8),%rsp /* free stack space */
957 mov %r10,(%rsp) /* write return adress */
961 asm_getclassvalues_atomic:
964 movl offbaseval(a0),itmp1l
965 movl offdiffval(a0),itmp2l
966 movl offbaseval(a1),itmp3l
968 movl itmp1l,offcast_super_baseval(a2)
969 movl itmp2l,offcast_super_diffval(a2)
970 movl itmp3l,offcast_sub_baseval(a2)
975 asm_criticalsections:
976 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
988 * These are local overrides for various environment variables in Emacs.
989 * Please do not remove this and leave it at the end of the file, where
990 * Emacs will automagically detect them.
991 * ---------------------------------------------------------------------
994 * indent-tabs-mode: t