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 3237 2005-09-21 13:22:49Z twisti $
41 #include "vm/jit/x86_64/arch.h"
42 #include "vm/jit/x86_64/offsets.h"
44 #include "vm/jit/methodheader.h"
50 /********************* exported functions and variables ***********************/
52 .globl asm_calljavafunction
53 .globl asm_calljavafunction_int
55 .globl asm_calljavafunction2
56 .globl asm_calljavafunction2int
57 .globl asm_calljavafunction2long
58 .globl asm_calljavafunction2float
59 .globl asm_calljavafunction2double
61 .globl asm_call_jit_compiler
62 .globl asm_handle_exception
63 .globl asm_handle_nat_exception
65 .globl asm_wrapper_patcher
67 .globl asm_builtin_arraycheckcast
69 .globl asm_builtin_f2i
70 .globl asm_builtin_f2l
71 .globl asm_builtin_d2i
72 .globl asm_builtin_d2l
74 .globl asm_perform_threadswitch
75 .globl asm_initialize_thread_stack
76 .globl asm_switchstackandcall
77 .globl asm_criticalsections
78 .globl asm_getclassvalues_atomic
81 /********************* function asm_calljavafunction ***************************
83 * This function calls a Java-method (which possibly needs compilation) *
84 * with up to 4 address parameters. *
86 * This functions calls the JIT-compiler which eventually translates the *
87 * method into machine code. *
90 * javaobject_header *asm_calljavamethod (methodinfo *m, *
91 * void *arg1, void *arg2, void *arg3, void *arg4); *
93 *******************************************************************************/
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),%rsp /* keep stack 16-byte aligned */
118 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
119 mov %rdi,%rax /* move function pointer to %rax */
120 /* compilerstub uses this */
122 mov %rsi,%rdi /* pass remaining parameters */
127 lea asm_call_jit_compiler,%r11
128 call *%r11 /* call JIT compiler */
132 add $(3*8),%rsp /* free stack space */
136 mov %rax,%rdi /* pass exception pointer */
137 call builtin_throw_exception
141 xor %rax,%rax /* return NULL */
145 /********************* function asm_calljavafunction ***************************
147 * This function calls a Java-method (which possibly needs compilation) *
148 * with up to 4 address parameters. *
150 * This functions calls the JIT-compiler which eventually translates the *
151 * method into machine code. *
154 * javaobject_header *asm_calljavamethod (methodinfo *m, *
155 * void *arg1, void *arg2, void *arg3, void *arg4); *
157 *******************************************************************************/
162 .quad 0 /* catch type all */
163 .quad calljava_xhandler2 /* handler pc */
164 .quad calljava_xhandler2 /* end pc */
165 .quad asm_calljavafunction2 /* start pc */
166 .long 1 /* extable size */
168 .quad 0 /* line number table start */
169 .quad 0 /* line number table size */
171 .long 0 /* fltsave */
172 .long 0 /* intsave */
175 .long 24 /* frame size */
176 .quad 0 /* method pointer (pointer to name) */
178 asm_calljavafunction2:
179 asm_calljavafunction2int:
180 asm_calljavafunction2long:
181 asm_calljavafunction2float:
182 asm_calljavafunction2double:
183 sub $(7*8),%rsp /* keep stack 16-byte aligned */
184 mov %rbx,0*8(%rsp) /* %rbx is not a callee saved in cacao */
191 mov %rdi,%rax /* move method pointer for compiler */
192 xor %rbp,%rbp /* set argument stack frame to zero */
194 test %rsi,%rsi /* maybe we have no args... */
197 mov %rsi,itmp3 /* arg count */
198 mov %rcx,itmp2 /* pointer to arg block */
200 mov itmp2,%r14 /* save argument block pointer */
201 mov itmp3,%r15 /* save argument count */
203 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
204 add $1,itmp3 /* initialize argument count */
205 xor %r12,%r12 /* initialize integer argument counter */
206 xor %r13,%r13 /* initialize float argument counter */
209 add $sizejniblock,itmp2 /* goto next argument block */
210 dec itmp3 /* argument count - 1 */
211 jz L_register_copy_done
212 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
213 jnz L_register_handle_float /* yes, handle it */
215 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
216 je L_register_copy /* register? yes, next loop */
218 lea jumptable_integer,%rbp
219 mov 0(%rbp,%r12,8),%rbx
220 inc %r12 /* integer argument counter + 1 */
223 L_register_handle_float:
224 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
225 je L_register_copy /* register? yes, next loop */
227 lea jumptable_float,%rbp
228 mov 0(%rbp,%r13,8),%rbx
229 inc %r13 /* float argument counter + 1 */
232 L_register_copy_done:
233 mov %r15,%rbp /* calculate remaining arguments */
234 sub %r12,%rbp /* - integer arguments in registers */
235 sub %r13,%rbp /* - float arguments in registers */
236 jle L_copy_done /* are all assigned to registers? */
238 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
239 shl $3,%rbp /* calculate stack size */
240 sub %rbp,%rsp /* stack frame for arguments */
241 mov %rsp,%rbx /* use %rbx as temp sp */
243 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
244 add $1,%r15 /* initialize argument count */
247 add $sizejniblock,%r14 /* goto next argument block */
248 dec %r15 /* are there any arguments left? */
249 jz L_copy_done /* no test needed after dec */
251 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
252 jnz L_stack_handle_float
253 dec %r12 /* arguments assigned to registers */
254 jge L_stack_copy_loop
257 L_stack_handle_float:
258 dec %r13 /* arguments assigned to registers */
259 jge L_stack_copy_loop
262 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
264 add $8,%rbx /* increase sp to next argument */
265 jmp L_stack_copy_loop
268 lea asm_call_jit_compiler,%r11/* %rax still contains method pointer */
269 call *%r11 /* call JIT compiler */
271 add %rbp,%rsp /* remove argument stack frame if any */
273 mov 5*8(%rsp),%r15 /* restore callee saved registers */
279 add $(7*8),%rsp /* free stack space */
283 mov %rax,%rdi /* pass exception pointer */
284 call builtin_throw_exception
286 mov 5*8(%rsp),%r15 /* restore callee saved registers */
292 add $(7*8),%rsp /* free stack space */
293 xor %rax,%rax /* return NULL */
306 mov offjniitem(itmp2),a0
309 mov offjniitem(itmp2),a1
312 mov offjniitem(itmp2),a2
315 mov offjniitem(itmp2),a3
318 mov offjniitem(itmp2),a4
321 mov offjniitem(itmp2),a5
336 movq offjniitem(itmp2),fa0
339 movq offjniitem(itmp2),fa1
342 movq offjniitem(itmp2),fa2
345 movq offjniitem(itmp2),fa3
348 movq offjniitem(itmp2),fa4
351 movq offjniitem(itmp2),fa5
354 movq offjniitem(itmp2),fa6
357 movq offjniitem(itmp2),fa7
361 /****************** function asm_call_jit_compiler *****************************
363 * invokes the compiler for untranslated JavaVM methods. *
365 * Register R0 contains a pointer to the method info structure (prepared *
366 * by createcompilerstub). Using the return address in R26 and the *
367 * offset in the LDA instruction or using the value in methodptr R28 the *
368 * patching address for storing the method address can be computed: *
370 * method address was either loaded using *
372 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
373 * i386_call_reg(REG_ITMP2) *
377 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
378 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
379 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
380 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
381 * i386_call_reg(REG_ITMP1) *
383 * in the static case the method pointer can be computed using the *
384 * return address and the lda function following the jmp instruction *
386 *******************************************************************************/
388 asm_call_jit_compiler:
389 sub $((3+24)*8+sizestackframeinfo),sp /* keep stack 16-byte aligned */
391 mov %rbx,0*8(%rsp) /* save register */
393 mov (3+24)*8+sizestackframeinfo(%rsp),itmp3 /* get return address */
394 mov -1(itmp3),%bl /* get function code */
395 cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */
396 jne L_not_static_special
398 sub $11,itmp3 /* calculate address of immediate */
399 jmp L_call_jit_compile
401 L_not_static_special:
402 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
403 jne L_not_virtual_interface
405 sub $7,itmp3 /* calculate address of offset */
406 mov (itmp3),itmp3l /* get offset (32-bit) */
407 add itmp2,itmp3 /* add base address to get method address */
408 jmp L_call_jit_compile
410 L_not_virtual_interface: /* a call from asm_calljavamethod */
414 mov 0*8(sp),%rbx /* restore register */
415 mov itmp3,0*8(sp) /* save address for method pointer */
416 mov itmp1,1*8(sp) /* save method pointer */
418 SAVE_ARGUMENT_REGISTERS(2)
420 mov sp,a0 /* create stackframe info */
421 add $((3+24)*8),a0 /* pass sfi */
422 xor a1,a1 /* if pv is NULL, use findmethod */
423 mov sp,a2 /* pass java sp */
424 add $((1+3+24)*8+sizestackframeinfo),a2
425 mov ((3+24)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
426 mov a3,a4 /* xpc is equal to ra */
427 call stacktrace_create_extern_stackframeinfo
429 mov 1*8(sp),a0 /* pass method pointer */
431 mov v0,1*8(sp) /* save return value */
433 mov sp,a0 /* remove stackframe info */
434 add $((3+24)*8),a0 /* pass sfi */
435 call stacktrace_remove_stackframeinfo
437 mov 0*8(sp),itmp3 /* restore address for method pointer */
438 mov 1*8(sp),v0 /* restore return value */
440 RESTORE_ARGUMENT_REGISTERS(2)
442 add $((3+24)*8+sizestackframeinfo),sp /* remove stack frame */
444 test v0,v0 /* check for exception */
445 je L_asm_call_jit_compiler_exception
447 test %r11,%r11 /* is address == 0 (asm_calljavamethod*/
450 mov %rax,(%r11) /* and now save the new pointer */
453 jmp *%rax /* ...and now call the new method */
455 L_asm_call_jit_compiler_exception:
456 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
457 call builtin_asm_get_exceptionptrptr
458 mov v0,itmp2 /* v0 == xptr */
460 lea _exceptionptr,itmp2
462 mov (itmp2),xptr /* get the exception pointer */
463 movl $0,(itmp2) /* clear exception pointer */
465 pop xpc /* delete return address */
466 sub $5,xpc /* faulting address is ra - 5 */
467 jmp asm_handle_exception
470 /********************* function asm_handle_exception ***************************
472 * This function handles an exception. It does not use the usual calling *
473 * conventions. The exception pointer is passed in REG_ITMP1 and the *
474 * pc from the exception raising position is passed in REG_ITMP2. It searches *
475 * the local exception table for a handler. If no one is found, it unwinds *
476 * stacks and continues searching the callers. *
478 * void asm_handle_exception (exceptionptr, exceptionpc); *
480 *******************************************************************************/
482 asm_handle_nat_exception:
483 add $8,%rsp /* clear return address of native stub*/
485 asm_handle_exception:
487 mov xptr,0*8(%rsp) /* save exception pointer */
488 mov xpc,1*8(%rsp) /* save exception pc */
490 mov xpc,%rdi /* exception pc */
491 call codegen_findmethod
493 mov %rax,2*8(%rsp) /* save data segment pointer */
495 mov 0*8(%rsp),%rax /* restore exception pointer */
496 mov 1*8(%rsp),%r10 /* restore exception pc */
499 mov %rax,%rdi /* exception pointer */
500 mov MethodPointer(itmp3),%rsi /* method pointer */
501 mov xpc,%rdx /* exception pc */
503 mov $1,%r8 /* set noindent flag */
504 call builtin_trace_exception
506 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
507 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
508 test %rcx,%rcx /* if empty table skip */
511 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
512 mov 0*8(%rsp),xptr /* get xptr */
515 mov 1*8(%rsp),xpc /* get xpc */
517 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
518 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
519 jg ex_table_cont /* if (false) continue */
520 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
521 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
522 jge ex_table_cont /* if (false) continue */
523 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
524 test %rdx,%rdx /* NULL catches everything */
527 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
537 call load_class_bootstrap
546 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
565 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
573 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
574 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
575 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
576 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
577 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
579 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
581 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
585 cmp %edx,%esi /* xptr is instanceof catchtype */
589 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
591 mov 0*8(%rsp),%rax /* restore exception pointer */
592 add $(4*8),%rsp /* free stack frame */
594 jmp *xpc /* jump to the handler */
597 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
598 dec %rcx /* decrement entry counter */
599 test %rcx,%rcx /* if (t0 > 0) next entry */
603 mov 0*8(%rsp),%rax /* restore exception pointer */
604 mov 1*8(%rsp),%r10 /* restore exception pc */
605 mov 2*8(%rsp),%r11 /* restore data segment pointer */
608 mov %rax,%rcx /* save exception pointer */
611 movl IsSync(%r11),%eax /* %rax = SyncOffset */
612 test %rax,%rax /* if zero no monitorexit */
615 #if defined(USE_THREADS)
624 call builtin_monitorexit
633 mov FrameSize(%r11),%eax /* %eax = frame size */
634 add %rax,%rsp /* unwind stack */
635 mov %rsp,%rax /* %rax = pointer to save area */
637 mov IntSave(%r11),%edx /* %edx = saved int register count*/
664 shl $3,%edx /* multiply by 8 bytes */
668 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
691 movq -48(%rax),%xmm10
693 movq -40(%rax),%xmm11
695 movq -32(%rax),%xmm12
697 movq -24(%rax),%xmm13
699 movq -16(%rax),%xmm14
704 pop %r10 /* the new xpc is return address */
705 sub $3,%r10 /* subtract 3 bytes for call */
712 call codegen_findmethod /* get the new data segment ptr */
719 mov %rcx,%rax /* restore saved exception pointer*/
723 mov %rax,0*8(%rsp) /* save exception pointer */
724 mov %r10,1*8(%rsp) /* save exception pc */
725 mov %r11,2*8(%rsp) /* save data segment pointer */
730 /* asm_wrapper_patcher *********************************************************
736 32 pointer to virtual java_objectheader
737 24 machine code (which is patched back later)
738 16 unresolved class/method/field reference
739 8 data segment displacement from load instructions
740 0 pointer to patcher function
742 *******************************************************************************/
745 sub $(20*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
747 SAVE_ARGUMENT_REGISTERS(0)
748 SAVE_TEMPORARY_REGISTERS(14)
750 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
751 mov itmp2,16*8(sp) /* can be used by some instructions */
753 mov sp,a0 /* create stackframe info */
755 xor a1,a1 /* if pv is NULL, use findmethod */
756 mov sp,a2 /* pass java sp */
757 add $((6+20)*8+sizestackframeinfo),a2
758 mov ((5+20)*8+sizestackframeinfo)(sp),a3 /* pass ra to java function */
759 mov a3,a4 /* xpc is equal to ra */
760 call stacktrace_create_extern_stackframeinfo
762 mov sp,a0 /* pass stack pointer */
763 add $((1+20)*8+sizestackframeinfo),a0 /* skip function pointer */
764 mov (20*8+sizestackframeinfo)(sp),itmp3 /* get function pointer */
765 call *itmp3 /* call the patcher function */
766 mov v0,17*8(sp) /* save return value */
768 mov sp,a0 /* remove stackframe info */
770 call stacktrace_remove_stackframeinfo
772 RESTORE_ARGUMENT_REGISTERS(0)
773 RESTORE_TEMPORARY_REGISTERS(14)
775 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
776 mov 16*8(sp),itmp2 /* can be used by some instructions */
777 mov 17*8(sp),itmp3 /* restore return value */
779 add $((5+20)*8+sizestackframeinfo),sp /* remove stack frame, keep ra */
781 test itmp3,itmp3 /* exception thrown? */
782 jz L_asm_wrapper_patcher_exception
783 ret /* call new patched code */
785 L_asm_wrapper_patcher_exception:
786 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
787 call builtin_asm_get_exceptionptrptr
788 mov v0,itmp2 /* v0 == xptr */
790 lea _exceptionptr,itmp2
792 mov (itmp2),xptr /* get the exception pointer */
793 movl $0,(itmp2) /* clear exception pointer */
795 pop xpc /* get and remove return address */
796 jmp asm_handle_exception
799 /* asm_builtin_x2x *************************************************************
801 * Wrapper functions for float to int corner cases *
803 *******************************************************************************/
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)
850 SAVE_ARGUMENT_REGISTERS(0)
855 RESTORE_ARGUMENT_REGISTERS(0)
861 /******************* function asm_initialize_thread_stack **********************
863 * initialized a thread stack *
864 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
866 *******************************************************************************/
868 asm_initialize_thread_stack:
879 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
880 mov %rsi,%rax /* return restorepoint in %rax */
884 /******************* function asm_perform_threadswitch *************************
886 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
888 * performs a threadswitch *
890 *******************************************************************************/
892 asm_perform_threadswitch:
893 sub $(7*8),%rsp /* allocate stack frame */
902 mov 7*8(%rsp),%rax /* save current return address */
905 mov %rsp,(%rdi) /* first argument **from */
906 mov %rsp,(%rdx) /* third argument **stackTop */
908 mov (%rsi),%rsp /* load new stack pointer */
917 mov 6*8(%rsp),%rax /* restore return address */
918 add $(7*8),%rsp /* free stack frame */
923 /********************* function asm_switchstackandcall *************************
925 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
928 * Switches to a new stack, calls a function and switches back. *
929 * a0 (%rdi) new stack pointer *
930 * a1 (%rsi) function pointer *
931 * a2 (%rdx) pointer to variable where stack top should be stored *
932 * a3 (%rcx) pointer to user data, is passed to the function *
934 *******************************************************************************/
936 asm_switchstackandcall:
937 sub $(1*8),%rsp /* keep stack 16-byte aligned */
938 sub $16,%rdi /* allocate new stack */
940 mov 8(%rsp),%rax /* save return address on new stack */
942 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
943 mov %rsp,(%rdx) /* save old stack pointer to variable */
945 mov %rdi,%rsp /* switch to new stack */
947 mov %rcx,%rdi /* pass pointer */
948 call *%rsi /* and call function */
950 mov (%rsp),%r10 /* load return address */
951 mov 8(%rsp),%rsp /* switch to old stack */
952 add $(1*8),%rsp /* free stack space */
953 mov %r10,(%rsp) /* write return adress */
957 asm_getclassvalues_atomic:
960 movl offbaseval(a0),itmp1l
961 movl offdiffval(a0),itmp2l
962 movl offbaseval(a1),itmp3l
964 movl itmp1l,offcast_super_baseval(a2)
965 movl itmp2l,offcast_super_diffval(a2)
966 movl itmp3l,offcast_sub_baseval(a2)
971 asm_criticalsections:
972 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
984 * These are local overrides for various environment variables in Emacs.
985 * Please do not remove this and leave it at the end of the file, where
986 * Emacs will automagically detect them.
987 * ---------------------------------------------------------------------
990 * indent-tabs-mode: t