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 3891 2005-12-05 22:54:42Z 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 0*8(sp),a0 /* pass exception pointer */
502 mov 1*8(sp),a1 /* pass exception pc */
503 mov 2*8(sp),a2 /* pass data segment pointer */
504 call exceptions_handle_exception
507 jz L_asm_handle_exception_not_catched
509 mov v0,xpc /* move handlerpc into xpc */
510 mov 0*8(sp),%rax /* restore exception pointer */
511 add $(4*8),sp /* free stack frame */
513 jmp *xpc /* jump to the handler */
515 L_asm_handle_exception_not_catched:
516 mov 0*8(%rsp),%rax /* restore exception pointer */
517 mov 1*8(%rsp),%r10 /* restore exception pc */
518 mov 2*8(%rsp),%r11 /* restore data segment pointer */
521 mov %rax,%rcx /* save exception pointer */
524 movl IsSync(%r11),%eax /* %rax = SyncOffset */
525 test %rax,%rax /* if zero no monitorexit */
528 #if defined(USE_THREADS)
530 mov -8(%rax),%rdi /* get monitor object from stack */
537 call builtin_monitorexit
546 mov FrameSize(%r11),%eax /* %eax = frame size */
547 add %rax,%rsp /* unwind stack */
548 mov %rsp,%rax /* %rax = pointer to save area */
550 mov IntSave(%r11),%edx /* %edx = saved int register count */
577 shl $3,%edx /* multiply by 8 bytes */
581 mov FltSave(%r11),%edx /* %edx = saved flt register count */
604 movq -48(%rax),%xmm10
606 movq -40(%rax),%xmm11
608 movq -32(%rax),%xmm12
610 movq -24(%rax),%xmm13
612 movq -16(%rax),%xmm14
617 pop %r10 /* the new xpc is return address */
618 sub $3,%r10 /* subtract 3 bytes for call */
625 call codegen_findmethod /* get the new data segment ptr */
632 mov %rcx,%rax /* restore saved exception pointer */
636 mov %rax,0*8(%rsp) /* save exception pointer */
637 mov %r10,1*8(%rsp) /* save exception pc */
638 mov %r11,2*8(%rsp) /* save data segment pointer */
640 mov $1,a3 /* set indent flag */
645 /* asm_wrapper_patcher *********************************************************
651 32 pointer to virtual java_objectheader
652 24 machine code (which is patched back later)
653 16 unresolved class/method/field reference
654 8 data segment displacement from load instructions
655 0 pointer to patcher function
658 *******************************************************************************/
661 push bp /* save base pointer */
662 mov sp,bp /* move actual sp to bp */
663 sub $(18*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
664 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
665 /* leaf functions) */
667 SAVE_ARGUMENT_REGISTERS(0)
668 SAVE_TEMPORARY_REGISTERS(14)
670 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
671 mov itmp2,16*8(sp) /* can be used by some instructions */
673 mov sp,a0 /* create stackframe info */
675 xor a1,a1 /* if pv is NULL, use findmethod */
676 mov bp,a2 /* pass java sp */
678 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
679 mov a3,a4 /* xpc is equal to ra */
680 call stacktrace_create_extern_stackframeinfo
682 mov bp,a0 /* pass stack pointer */
683 add $((1+1)*8),a0 /* skip function pointer */
684 mov 1*8(bp),itmp3 /* get function pointer */
685 call *itmp3 /* call the patcher function */
686 mov v0,17*8(sp) /* save return value */
688 mov sp,a0 /* remove stackframe info */
690 call stacktrace_remove_stackframeinfo
692 RESTORE_ARGUMENT_REGISTERS(0)
693 RESTORE_TEMPORARY_REGISTERS(14)
695 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
696 mov 16*8(sp),itmp2 /* can be used by some instructions */
697 mov 17*8(sp),itmp3 /* restore return value */
699 mov bp,sp /* restore original sp */
700 pop bp /* restore bp */
701 add $(5*8),sp /* remove patcher stackframe, keep ra */
703 test itmp3,itmp3 /* exception thrown? */
704 jz L_asm_wrapper_patcher_exception
705 ret /* call new patched code */
707 L_asm_wrapper_patcher_exception:
708 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
709 call builtin_asm_get_exceptionptrptr
710 mov v0,itmp2 /* v0 == xptr */
712 lea _no_threads_exceptionptr,itmp2
714 mov (itmp2),xptr /* get the exception pointer */
715 movl $0,(itmp2) /* clear exception pointer */
717 pop xpc /* get and remove return address */
718 jmp asm_handle_exception
721 /* asm_builtin_x2x *************************************************************
723 * Wrapper functions for float to int corner cases *
725 *******************************************************************************/
730 SAVE_ARGUMENT_REGISTERS(0)
735 RESTORE_ARGUMENT_REGISTERS(0)
744 SAVE_ARGUMENT_REGISTERS(0)
749 RESTORE_ARGUMENT_REGISTERS(0)
758 SAVE_ARGUMENT_REGISTERS(0)
763 RESTORE_ARGUMENT_REGISTERS(0)
772 SAVE_ARGUMENT_REGISTERS(0)
777 RESTORE_ARGUMENT_REGISTERS(0)
783 /******************* function asm_initialize_thread_stack **********************
785 * initialized a thread stack *
786 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
788 *******************************************************************************/
790 asm_initialize_thread_stack:
801 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
802 mov %rsi,%rax /* return restorepoint in %rax */
806 /******************* function asm_perform_threadswitch *************************
808 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
810 * performs a threadswitch *
812 *******************************************************************************/
814 asm_perform_threadswitch:
815 sub $(7*8),%rsp /* allocate stack frame */
824 mov 7*8(%rsp),%rax /* save current return address */
827 mov %rsp,(%rdi) /* first argument **from */
828 mov %rsp,(%rdx) /* third argument **stackTop */
830 mov (%rsi),%rsp /* load new stack pointer */
839 mov 6*8(%rsp),%rax /* restore return address */
840 add $(7*8),%rsp /* free stack frame */
845 /********************* function asm_switchstackandcall *************************
847 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
850 * Switches to a new stack, calls a function and switches back. *
851 * a0 (%rdi) new stack pointer *
852 * a1 (%rsi) function pointer *
853 * a2 (%rdx) pointer to variable where stack top should be stored *
854 * a3 (%rcx) pointer to user data, is passed to the function *
856 *******************************************************************************/
858 asm_switchstackandcall:
859 sub $(1*8),%rsp /* keep stack 16-byte aligned */
860 sub $16,%rdi /* allocate new stack */
862 mov 8(%rsp),%rax /* save return address on new stack */
864 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
865 mov %rsp,(%rdx) /* save old stack pointer to variable */
867 mov %rdi,%rsp /* switch to new stack */
869 mov %rcx,%rdi /* pass pointer */
870 call *%rsi /* and call function */
872 mov (%rsp),%r10 /* load return address */
873 mov 8(%rsp),%rsp /* switch to old stack */
874 add $(1*8),%rsp /* free stack space */
875 mov %r10,(%rsp) /* write return adress */
879 asm_getclassvalues_atomic:
882 movl offbaseval(a0),itmp1l
883 movl offdiffval(a0),itmp2l
884 movl offbaseval(a1),itmp3l
886 movl itmp1l,offcast_super_baseval(a2)
887 movl itmp2l,offcast_super_diffval(a2)
888 movl itmp3l,offcast_sub_baseval(a2)
893 asm_criticalsections:
894 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
908 * These are local overrides for various environment variables in Emacs.
909 * Please do not remove this and leave it at the end of the file, where
910 * Emacs will automagically detect them.
911 * ---------------------------------------------------------------------
914 * indent-tabs-mode: t