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 3746 2005-11-22 23:45:10Z 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_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 _no_threads_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 */
498 xor a3,a3 /* clear indent flag (only first time)*/
501 mov %rax,a0 /* exception pointer */
502 mov MethodPointer(itmp3),a1 /* method pointer */
503 mov xpc,a2 /* exception pc */
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)
617 mov -8(%rax),%rdi /* get monitor object from stack */
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 */
727 mov $1,a3 /* set indent flag */
732 /* asm_wrapper_patcher *********************************************************
738 32 pointer to virtual java_objectheader
739 24 machine code (which is patched back later)
740 16 unresolved class/method/field reference
741 8 data segment displacement from load instructions
742 0 pointer to patcher function
745 *******************************************************************************/
748 push bp /* save base pointer */
749 mov sp,bp /* move actual sp to bp */
750 sub $(18*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
751 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
752 /* leaf functions) */
754 SAVE_ARGUMENT_REGISTERS(0)
755 SAVE_TEMPORARY_REGISTERS(14)
757 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
758 mov itmp2,16*8(sp) /* can be used by some instructions */
760 mov sp,a0 /* create stackframe info */
762 xor a1,a1 /* if pv is NULL, use findmethod */
763 mov bp,a2 /* pass java sp */
765 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
766 mov a3,a4 /* xpc is equal to ra */
767 call stacktrace_create_extern_stackframeinfo
769 mov bp,a0 /* pass stack pointer */
770 add $((1+1)*8),a0 /* skip function pointer */
771 mov 1*8(bp),itmp3 /* get function pointer */
772 call *itmp3 /* call the patcher function */
773 mov v0,17*8(sp) /* save return value */
775 mov sp,a0 /* remove stackframe info */
777 call stacktrace_remove_stackframeinfo
779 RESTORE_ARGUMENT_REGISTERS(0)
780 RESTORE_TEMPORARY_REGISTERS(14)
782 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
783 mov 16*8(sp),itmp2 /* can be used by some instructions */
784 mov 17*8(sp),itmp3 /* restore return value */
786 mov bp,sp /* restore original sp */
787 pop bp /* restore bp */
788 add $(5*8),sp /* remove patcher stackframe, keep ra */
790 test itmp3,itmp3 /* exception thrown? */
791 jz L_asm_wrapper_patcher_exception
792 ret /* call new patched code */
794 L_asm_wrapper_patcher_exception:
795 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
796 call builtin_asm_get_exceptionptrptr
797 mov v0,itmp2 /* v0 == xptr */
799 lea _no_threads_exceptionptr,itmp2
801 mov (itmp2),xptr /* get the exception pointer */
802 movl $0,(itmp2) /* clear exception pointer */
804 pop xpc /* get and remove return address */
805 jmp asm_handle_exception
808 /* asm_builtin_x2x *************************************************************
810 * Wrapper functions for float to int corner cases *
812 *******************************************************************************/
817 SAVE_ARGUMENT_REGISTERS(0)
822 RESTORE_ARGUMENT_REGISTERS(0)
831 SAVE_ARGUMENT_REGISTERS(0)
836 RESTORE_ARGUMENT_REGISTERS(0)
845 SAVE_ARGUMENT_REGISTERS(0)
850 RESTORE_ARGUMENT_REGISTERS(0)
859 SAVE_ARGUMENT_REGISTERS(0)
864 RESTORE_ARGUMENT_REGISTERS(0)
870 /******************* function asm_initialize_thread_stack **********************
872 * initialized a thread stack *
873 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
875 *******************************************************************************/
877 asm_initialize_thread_stack:
888 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
889 mov %rsi,%rax /* return restorepoint in %rax */
893 /******************* function asm_perform_threadswitch *************************
895 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
897 * performs a threadswitch *
899 *******************************************************************************/
901 asm_perform_threadswitch:
902 sub $(7*8),%rsp /* allocate stack frame */
911 mov 7*8(%rsp),%rax /* save current return address */
914 mov %rsp,(%rdi) /* first argument **from */
915 mov %rsp,(%rdx) /* third argument **stackTop */
917 mov (%rsi),%rsp /* load new stack pointer */
926 mov 6*8(%rsp),%rax /* restore return address */
927 add $(7*8),%rsp /* free stack frame */
932 /********************* function asm_switchstackandcall *************************
934 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
937 * Switches to a new stack, calls a function and switches back. *
938 * a0 (%rdi) new stack pointer *
939 * a1 (%rsi) function pointer *
940 * a2 (%rdx) pointer to variable where stack top should be stored *
941 * a3 (%rcx) pointer to user data, is passed to the function *
943 *******************************************************************************/
945 asm_switchstackandcall:
946 sub $(1*8),%rsp /* keep stack 16-byte aligned */
947 sub $16,%rdi /* allocate new stack */
949 mov 8(%rsp),%rax /* save return address on new stack */
951 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
952 mov %rsp,(%rdx) /* save old stack pointer to variable */
954 mov %rdi,%rsp /* switch to new stack */
956 mov %rcx,%rdi /* pass pointer */
957 call *%rsi /* and call function */
959 mov (%rsp),%r10 /* load return address */
960 mov 8(%rsp),%rsp /* switch to old stack */
961 add $(1*8),%rsp /* free stack space */
962 mov %r10,(%rsp) /* write return adress */
966 asm_getclassvalues_atomic:
969 movl offbaseval(a0),itmp1l
970 movl offdiffval(a0),itmp2l
971 movl offbaseval(a1),itmp3l
973 movl itmp1l,offcast_super_baseval(a2)
974 movl itmp2l,offcast_super_diffval(a2)
975 movl itmp3l,offcast_sub_baseval(a2)
980 asm_criticalsections:
981 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
993 * These are local overrides for various environment variables in Emacs.
994 * Please do not remove this and leave it at the end of the file, where
995 * Emacs will automagically detect them.
996 * ---------------------------------------------------------------------
999 * indent-tabs-mode: t