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 3892 2005-12-06 20:13:26Z 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 /* 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 *******************************************************************************/
480 asm_handle_nat_exception:
481 add $8,%rsp /* clear return address of native stub*/
483 asm_handle_exception:
484 xor a3,a3 /* clear indent flag (only first time)*/
486 L_asm_handle_exception_stack_loop:
488 mov xptr,0*8(sp) /* save exception pointer */
489 mov xpc,1*8(sp) /* save exception pc */
491 mov xpc,a0 /* exception pc */
492 call codegen_findmethod
493 mov v0,2*8(sp) /* save data segment pointer */
495 mov 0*8(sp),a0 /* pass exception pointer */
496 mov 1*8(sp),a1 /* pass exception pc */
497 mov v0,a2 /* pass data segment pointer */
499 add $(4*8),a3 /* pass Java stack pointer */
500 call exceptions_handle_exception
503 jz L_asm_handle_exception_not_catched
505 mov v0,xpc /* move handlerpc into xpc */
506 mov 0*8(sp),xptr /* restore exception pointer */
507 add $(4*8),sp /* free stack frame */
509 jmp *xpc /* jump to the handler */
511 L_asm_handle_exception_not_catched:
512 mov 0*8(sp),xptr /* restore exception pointer */
513 mov 2*8(sp),itmp3 /* restore data segment pointer */
516 mov FrameSize(itmp3),itmp2l /* get frame size */
517 add itmp2,sp /* unwind stack */
518 mov sp,itmp2 /* pointer to save area */
520 mov IntSave(itmp3),%edx /* %edx = saved int register count */
547 shl $3,%edx /* multiply by 8 bytes */
551 mov FltSave(itmp3),%edx /* %edx = saved flt register count */
570 movq -64(itmp2),%xmm8
572 movq -56(itmp2),%xmm9
574 movq -48(itmp2),%xmm10
576 movq -40(itmp2),%xmm11
578 movq -32(itmp2),%xmm12
580 movq -24(itmp2),%xmm13
582 movq -16(itmp2),%xmm14
584 movq -8(itmp2),%xmm15
587 /* exception pointer is still set */
588 pop xpc /* the new xpc is return address */
589 sub $3,xpc /* subtract 3 bytes for call */
591 mov $1,a3 /* set indent flag */
593 jmp L_asm_handle_exception_stack_loop
596 /* asm_wrapper_patcher *********************************************************
602 32 pointer to virtual java_objectheader
603 24 machine code (which is patched back later)
604 16 unresolved class/method/field reference
605 8 data segment displacement from load instructions
606 0 pointer to patcher function
609 *******************************************************************************/
612 push bp /* save base pointer */
613 mov sp,bp /* move actual sp to bp */
614 sub $(18*8+sizestackframeinfo),sp /* stack frame (16-byte aligned) */
615 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
616 /* leaf functions) */
618 SAVE_ARGUMENT_REGISTERS(0)
619 SAVE_TEMPORARY_REGISTERS(14)
621 mov itmp1,15*8(sp) /* save itmp1 and itmp2 */
622 mov itmp2,16*8(sp) /* can be used by some instructions */
624 mov sp,a0 /* create stackframe info */
626 xor a1,a1 /* if pv is NULL, use findmethod */
627 mov bp,a2 /* pass java sp */
629 mov ((5+1)*8)(bp),a3 /* pass ra to java function */
630 mov a3,a4 /* xpc is equal to ra */
631 call stacktrace_create_extern_stackframeinfo
633 mov bp,a0 /* pass stack pointer */
634 add $((1+1)*8),a0 /* skip function pointer */
635 mov 1*8(bp),itmp3 /* get function pointer */
636 call *itmp3 /* call the patcher function */
637 mov v0,17*8(sp) /* save return value */
639 mov sp,a0 /* remove stackframe info */
641 call stacktrace_remove_stackframeinfo
643 RESTORE_ARGUMENT_REGISTERS(0)
644 RESTORE_TEMPORARY_REGISTERS(14)
646 mov 15*8(sp),itmp1 /* restore itmp1 and itmp2 */
647 mov 16*8(sp),itmp2 /* can be used by some instructions */
648 mov 17*8(sp),itmp3 /* restore return value */
650 mov bp,sp /* restore original sp */
651 pop bp /* restore bp */
652 add $(5*8),sp /* remove patcher stackframe, keep ra */
654 test itmp3,itmp3 /* exception thrown? */
655 jz L_asm_wrapper_patcher_exception
656 ret /* call new patched code */
658 L_asm_wrapper_patcher_exception:
659 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
660 call builtin_asm_get_exceptionptrptr
661 mov v0,itmp2 /* v0 == xptr */
663 lea _no_threads_exceptionptr,itmp2
665 mov (itmp2),xptr /* get the exception pointer */
666 movl $0,(itmp2) /* clear exception pointer */
668 pop xpc /* get and remove return address */
669 jmp asm_handle_exception
672 /* asm_builtin_x2x *************************************************************
674 * Wrapper functions for float to int corner cases *
676 *******************************************************************************/
681 SAVE_ARGUMENT_REGISTERS(0)
686 RESTORE_ARGUMENT_REGISTERS(0)
695 SAVE_ARGUMENT_REGISTERS(0)
700 RESTORE_ARGUMENT_REGISTERS(0)
709 SAVE_ARGUMENT_REGISTERS(0)
714 RESTORE_ARGUMENT_REGISTERS(0)
723 SAVE_ARGUMENT_REGISTERS(0)
728 RESTORE_ARGUMENT_REGISTERS(0)
734 /******************* function asm_initialize_thread_stack **********************
736 * initialized a thread stack *
737 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
739 *******************************************************************************/
741 asm_initialize_thread_stack:
752 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
753 mov %rsi,%rax /* return restorepoint in %rax */
757 /******************* function asm_perform_threadswitch *************************
759 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
761 * performs a threadswitch *
763 *******************************************************************************/
765 asm_perform_threadswitch:
766 sub $(7*8),%rsp /* allocate stack frame */
775 mov 7*8(%rsp),%rax /* save current return address */
778 mov %rsp,(%rdi) /* first argument **from */
779 mov %rsp,(%rdx) /* third argument **stackTop */
781 mov (%rsi),%rsp /* load new stack pointer */
790 mov 6*8(%rsp),%rax /* restore return address */
791 add $(7*8),%rsp /* free stack frame */
796 /********************* function asm_switchstackandcall *************************
798 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
801 * Switches to a new stack, calls a function and switches back. *
802 * a0 (%rdi) new stack pointer *
803 * a1 (%rsi) function pointer *
804 * a2 (%rdx) pointer to variable where stack top should be stored *
805 * a3 (%rcx) pointer to user data, is passed to the function *
807 *******************************************************************************/
809 asm_switchstackandcall:
810 sub $(1*8),%rsp /* keep stack 16-byte aligned */
811 sub $16,%rdi /* allocate new stack */
813 mov 8(%rsp),%rax /* save return address on new stack */
815 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
816 mov %rsp,(%rdx) /* save old stack pointer to variable */
818 mov %rdi,%rsp /* switch to new stack */
820 mov %rcx,%rdi /* pass pointer */
821 call *%rsi /* and call function */
823 mov (%rsp),%r10 /* load return address */
824 mov 8(%rsp),%rsp /* switch to old stack */
825 add $(1*8),%rsp /* free stack space */
826 mov %r10,(%rsp) /* write return adress */
830 asm_getclassvalues_atomic:
833 movl offbaseval(a0),itmp1l
834 movl offdiffval(a0),itmp2l
835 movl offbaseval(a1),itmp3l
837 movl itmp1l,offcast_super_baseval(a2)
838 movl itmp2l,offcast_super_diffval(a2)
839 movl itmp3l,offcast_sub_baseval(a2)
844 asm_criticalsections:
845 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
859 * These are local overrides for various environment variables in Emacs.
860 * Please do not remove this and leave it at the end of the file, where
861 * Emacs will automagically detect them.
862 * ---------------------------------------------------------------------
865 * indent-tabs-mode: t