1 /* jit/x86_64/asmpart.S - Java-C interface functions for x86_64
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
32 $Id: asmpart.S 1065 2004-05-16 15:36:57Z twisti $
39 #define MethodPointer -8
45 #define ExTableSize -32
46 #define ExTableStart -32
48 #define ExEntrySize -32
51 #define ExHandlerPC -24
52 #define ExCatchType -32
66 /********************* exported functions and variables ***********************/
68 .globl asm_calljavafunction
69 .globl asm_calljavafunction2
70 .globl asm_calljavafunction2long
71 .globl asm_calljavafunction2double
72 .globl asm_call_jit_compiler
73 .globl asm_handle_exception
74 .globl asm_handle_nat_exception
75 .globl asm_check_clinit
76 .globl asm_builtin_checkarraycast
77 .globl asm_builtin_anewarray
78 .globl asm_builtin_newarray_array
79 .globl asm_builtin_aastore
80 .globl asm_builtin_monitorenter
81 .globl asm_builtin_monitorexit
82 .globl asm_builtin_f2i
83 .globl asm_builtin_f2l
84 .globl asm_builtin_d2i
85 .globl asm_builtin_d2l
86 .globl asm_builtin_arrayinstanceof
87 .globl asm_perform_threadswitch
88 .globl asm_initialize_thread_stack
89 .globl asm_switchstackandcall
92 /*************************** imported functions *******************************/
95 .globl builtin_monitorexit
96 .globl builtin_throw_exception
97 .globl builtin_trace_exception
101 /********************* function asm_calljavafunction ***************************
103 * This function calls a Java-method (which possibly needs compilation) *
104 * with up to 4 address parameters. *
106 * This functions calls the JIT-compiler which eventually translates the *
107 * method into machine code. *
110 * javaobject_header *asm_calljavamethod (methodinfo *m, *
111 * void *arg1, void *arg2, void *arg3, void *arg4); *
113 *******************************************************************************/
116 .ascii "calljavafunction\0\0"
119 .quad 0 /* catch type all */
120 .quad calljava_xhandler /* handler pc */
121 .quad calljava_xhandler /* end pc */
122 .quad asm_calljavafunction /* start pc */
123 .long 1 /* extable size */
124 .long 0 /* fltsave */
125 .long 0 /* intsave */
128 .long 8 /* frame size */
129 .quad 0 /* method pointer (pointer to name) */
131 asm_calljavafunction:
132 sub $(3*8),%rsp /* keep stack 16-byte aligned */
134 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
135 mov %rdi,%rax /* move function pointer to %rax */
136 /* compilerstub uses this */
138 mov %rsi,%rdi /* pass remaining parameters */
143 lea asm_call_jit_compiler,%r11
144 call *%r11 /* call JIT compiler */
151 add $(3*8),%rsp /* free stack space */
155 mov %rax,%rdi /* pass exception pointer */
156 call builtin_throw_exception
163 /********************* function asm_calljavafunction ***************************
165 * This function calls a Java-method (which possibly needs compilation) *
166 * with up to 4 address parameters. *
168 * This functions calls the JIT-compiler which eventually translates the *
169 * method into machine code. *
172 * javaobject_header *asm_calljavamethod (methodinfo *m, *
173 * void *arg1, void *arg2, void *arg3, void *arg4); *
175 *******************************************************************************/
178 .ascii "calljavafunction2\0\0"
181 .quad 0 /* catch type all */
182 .quad calljava_xhandler2 /* handler pc */
183 .quad calljava_xhandler2 /* end pc */
184 .quad asm_calljavafunction2 /* start pc */
185 .long 1 /* extable size */
186 .long 0 /* fltsave */
187 .long 0 /* intsave */
190 .long 8 /* frame size */
191 .quad 0 /* method pointer (pointer to name) */
193 asm_calljavafunction2:
194 asm_calljavafunction2double:
195 asm_calljavafunction2long:
196 sub $(1*8),%rsp /* keep stack 16-byte aligned */
197 mov %rbx,0*8(%rsp) /* %rbx is not a callee saved in cacao */
199 mov %rdi,%rax /* save method pointer for compiler */
200 mov %rsi,%r11 /* arg count */
201 mov %rcx,%r10 /* pointer to arg block */
203 test %r11,%r11 /* maybe we have no args */
204 jle calljava_copydone
206 mov offjniitem(%r10),%rdi /* move args into registers */
211 mov offjniitem+sizejniblock*1(%r10),%rsi
216 mov offjniitem+sizejniblock*2(%r10),%rdx
217 mov offjniitem+sizejniblock*3(%r10),%rcx
220 lea asm_call_jit_compiler,%r11
221 call *%r11 /* call JIT compiler */
224 add $(1*8),%rsp /* free stack space */
228 mov %rax,%rdi /* pass exception pointer */
229 call builtin_throw_exception
235 /****************** function asm_call_jit_compiler *****************************
237 * invokes the compiler for untranslated JavaVM methods. *
239 * Register R0 contains a pointer to the method info structure (prepared *
240 * by createcompilerstub). Using the return address in R26 and the *
241 * offset in the LDA instruction or using the value in methodptr R28 the *
242 * patching address for storing the method address can be computed: *
244 * method address was either loaded using *
246 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
247 * i386_call_reg(REG_ITMP2) *
251 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
252 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
253 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
254 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
255 * i386_call_reg(REG_ITMP1) *
257 * in the static case the method pointer can be computed using the *
258 * return address and the lda function following the jmp instruction *
260 *******************************************************************************/
262 asm_call_jit_compiler:
263 sub $8,%rsp /* keep stack 16-byte aligned */
265 mov %rbx,(%rsp) /* save register */
267 mov 8(%rsp),%r11 /* get return address */
268 mov -1(%r11),%bl /* get function code */
269 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%r10)? */
270 jne L_not_static_special
272 sub $11,%r11 /* calculate address of immediate */
273 jmp L_call_jit_compile
275 L_not_static_special:
276 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
277 jne L_not_virtual_interface
279 sub $7,%r11 /* calculate address of offset */
280 mov (%r11),%r11d /* get offset (32-bit) */
281 add %r10,%r11 /* add base address to get method address */
282 jmp L_call_jit_compile
284 L_not_virtual_interface: /* a call from asm_calljavamethod */
288 mov (%rsp),%rbx /* restore register */
290 sub $(24*8),%rsp /* 8 + 48 + 64 + 64 */
292 mov %r11,0*8(%rsp) /* save address for method pointer */
294 mov %rdi,1*8(%rsp) /* save arguments */
304 movq %xmm3,10*8(%rsp)
305 movq %xmm4,11*8(%rsp)
306 movq %xmm5,12*8(%rsp)
307 movq %xmm6,13*8(%rsp)
308 movq %xmm7,14*8(%rsp)
310 movq %xmm8,15*8(%rsp)/* we use them as callee saved registers */
311 movq %xmm9,16*8(%rsp)
312 movq %xmm10,17*8(%rsp)
313 movq %xmm11,18*8(%rsp)
314 movq %xmm12,19*8(%rsp)
315 movq %xmm13,20*8(%rsp)
316 movq %xmm14,21*8(%rsp)
317 movq %xmm15,22*8(%rsp)
319 mov %rax,%rdi /* pass method pointer */
334 movq 10*8(%rsp),%xmm3
335 movq 11*8(%rsp),%xmm4
336 movq 12*8(%rsp),%xmm5
337 movq 13*8(%rsp),%xmm6
338 movq 14*8(%rsp),%xmm7
340 movq 15*8(%rsp),%xmm8
341 movq 16*8(%rsp),%xmm9
342 movq 17*8(%rsp),%xmm10
343 movq 18*8(%rsp),%xmm11
344 movq 19*8(%rsp),%xmm12
345 movq 20*8(%rsp),%xmm13
346 movq 21*8(%rsp),%xmm14
347 movq 22*8(%rsp),%xmm15
351 test %r11,%r11 /* is address == 0 (asm_calljavamethod) */
354 mov %rax,(%r11) /* and now save the new pointer */
357 add $8,%rsp /* keep stack 16-byte aligned */
358 jmp *%rax /* ...and now call the new method */
361 /********************* function asm_handle_exception ***************************
363 * This function handles an exception. It does not use the usual calling *
364 * conventions. The exception pointer is passed in REG_ITMP1 and the *
365 * pc from the exception raising position is passed in REG_ITMP2. It searches *
366 * the local exception table for a handler. If no one is found, it unwinds *
367 * stacks and continues searching the callers. *
369 * void asm_handle_exception (exceptionptr, exceptionpc); *
371 *******************************************************************************/
373 asm_handle_nat_exception:
374 add $8,%rsp /* clear return address of native stub*/
376 asm_handle_exception:
378 mov xptr,0*8(%rsp) /* save exception pointer */
379 mov xpc,1*8(%rsp) /* save exception pc */
381 mov xpc,%rdi /* exception pc */
384 mov %rax,2*8(%rsp) /* save data segment pointer */
386 mov 0*8(%rsp),%rax /* restore exception pointer */
387 mov 1*8(%rsp),%r10 /* restore exception pc */
390 mov %rax,%rdi /* exception pointer */
391 mov MethodPointer(itmp3),%rsi /* method pointer */
392 mov xpc,%rdx /* exception pc */
394 mov $1,%r8 /* set noindent flag */
395 call builtin_trace_exception
397 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
398 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
399 test %rcx,%rcx /* if empty table skip */
402 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
403 mov 0*8(%rsp),xptr /* get xptr */
406 mov 1*8(%rsp),xpc /* get xpc */
408 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
409 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
410 jg ex_table_cont /* if (false) continue */
411 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
412 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
413 jge ex_table_cont /* if (false) continue */
414 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
415 test %rdx,%rdx /* NULL catches everything */
418 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
437 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
456 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
457 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
458 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
459 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
460 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
461 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
462 cmp %edx,%esi /* xptr is instanceof catchtype */
466 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
468 mov 0*8(%rsp),%rax /* restore exception pointer */
469 add $(4*8),%rsp /* free stack frame */
471 jmp *xpc /* jump to the handler */
474 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
475 dec %rcx /* decrement entry counter */
476 test %rcx,%rcx /* if (t0 > 0) next entry */
480 mov 0*8(%rsp),%rax /* restore exception pointer */
481 mov 1*8(%rsp),%r10 /* restore exception pc */
482 mov 2*8(%rsp),%r11 /* restore data segment pointer */
485 mov %rax,%rcx /* save exception pointer */
488 movl IsSync(%r11),%eax /* %rax = SyncOffset */
489 test %rax,%rax /* if zero no monitorexit */
500 call builtin_monitorexit
508 mov FrameSize(%r11),%eax /* %eax = frame size */
509 add %rax,%rsp /* unwind stack */
510 mov %rsp,%rax /* %rax = pointer to save area */
512 mov IntSave(%r11),%edx /* %edx = saved int register count*/
539 shl $3,%edx /* multiply by 8 bytes */
543 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
566 movq -48(%rax),%xmm10
568 movq -40(%rax),%xmm11
570 movq -32(%rax),%xmm12
572 movq -24(%rax),%xmm13
574 movq -16(%rax),%xmm14
579 pop %r10 /* the new xpc is return address */
580 sub $3,%r10 /* subtract 3 bytes for call */
587 call findmethod /* get the new data segment ptr */
594 mov %rcx,%rax /* restore saved exception pointer*/
598 mov %rax,0*8(%rsp) /* save exception pointer */
599 mov %r10,1*8(%rsp) /* save exception pc */
600 mov %r11,2*8(%rsp) /* save data segment pointer */
605 /********************* function asm_check_clinit *******************************
607 * Does null check and calls monitorenter or throws an exception *
609 *******************************************************************************/
612 mov offclassinit(%rax),%r10d /* get initialized flag (int) */
616 sub $(7*8),%rsp /* keep stack 16-byte aligned */
617 mov %rdi,0*8(%rsp) /* save argument registers */
624 mov %rax,%rdi /* pass classinfo pointer */
625 call class_init /* call class_init function */
627 mov 0*8(%rsp),%rdi /* restore argument registers */
635 test %rax,%rax /* we had an exception */
636 je L_initializererror
639 mov (%rsp),%rax /* get return address */
640 sub $23,%rax /* asm_putstatic call code size */
641 movb $0xeb,(%rax) /* jmp rel8 */
642 movb $21,1(%rax) /* 8-bit offset */
646 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
647 call builtin_asm_get_exceptionptrptr
649 mov (itmp2),xptr /* get the exception pointer */
650 movl $0,(itmp2) /* clear the exception pointer */
652 lea _exceptionptr,itmp2
653 mov (itmp2),xptr /* get the exception pointer */
654 movl $0,(itmp2) /* clear the exception pointer */
657 pop xpc /* delete return address */
658 sub $3,xpc /* faulting address is return adress - 3 */
660 jmp asm_handle_exception
663 /********************* function asm_builtin_monitorenter ***********************
665 * Does null check and calls monitorenter or throws an exception *
667 *******************************************************************************/
669 asm_builtin_monitorenter:
671 je nb_monitorenter /* if (null) throw exception */
672 jmp builtin_monitorenter /* else call builtin_monitorenter */
675 mov string_java_lang_NullPointerException,%rdi
678 pop %r10 /* delete return address */
679 sub $3,%r10 /* faulting address is return adress - 3 */
680 jmp asm_handle_exception
683 /********************* function asm_builtin_monitorexit ************************
685 * Does null check and calls monitorexit or throws an exception *
687 *******************************************************************************/
689 asm_builtin_monitorexit:
691 je nb_monitorexit /* if (null) throw exception */
692 jmp builtin_monitorexit /* else call builtin_monitorenter */
695 mov string_java_lang_NullPointerException,%rdi
698 pop %r10 /* delete return address */
699 sub $3,%r10 /* faulting address is return adress - 3 */
700 jmp asm_handle_exception
703 /********************* function asm_builtin_x2x ********************************
705 * Wrapper functions for float to int corner cases *
707 *******************************************************************************/
723 movq %xmm4,10*8(%rsp)
724 movq %xmm5,11*8(%rsp)
725 movq %xmm6,12*8(%rsp)
726 movq %xmm7,13*8(%rsp)
742 movq 10*8(%rsp),%xmm4
743 movq 11*8(%rsp),%xmm5
744 movq 12*8(%rsp),%xmm6
745 movq 13*8(%rsp),%xmm7
765 movq %xmm4,10*8(%rsp)
766 movq %xmm5,11*8(%rsp)
767 movq %xmm6,12*8(%rsp)
768 movq %xmm7,13*8(%rsp)
784 movq 10*8(%rsp),%xmm4
785 movq 11*8(%rsp),%xmm5
786 movq 12*8(%rsp),%xmm6
787 movq 13*8(%rsp),%xmm7
807 movq %xmm4,10*8(%rsp)
808 movq %xmm5,11*8(%rsp)
809 movq %xmm6,12*8(%rsp)
810 movq %xmm7,13*8(%rsp)
826 movq 10*8(%rsp),%xmm4
827 movq 11*8(%rsp),%xmm5
828 movq 12*8(%rsp),%xmm6
829 movq 13*8(%rsp),%xmm7
849 movq %xmm4,10*8(%rsp)
850 movq %xmm5,11*8(%rsp)
851 movq %xmm6,12*8(%rsp)
852 movq %xmm7,13*8(%rsp)
868 movq 10*8(%rsp),%xmm4
869 movq 11*8(%rsp),%xmm5
870 movq 12*8(%rsp),%xmm6
871 movq 13*8(%rsp),%xmm7
877 /******************* function asm_builtin_checkarraycast ***********************
879 * Does the cast check and eventually throws an exception *
881 *******************************************************************************/
883 asm_builtin_checkarraycast:
884 sub $24,%rsp /* keep stack 16-byte aligned */
885 mov %rdi,(%rsp) /* save object pointer */
886 call builtin_checkarraycast /* builtin_checkarraycast */
887 test %rax,%rax /* if (false) throw exception */
889 mov (%rsp),%rax /* return object pointer */
890 add $24,%rsp /* free stack space */
894 mov string_java_lang_ClassCastException,%rdi
898 pop %r10 /* delete return address */
899 sub $3,%r10 /* faulting address is return adress - 3 */
900 jmp asm_handle_exception
903 /******************* function asm_builtin_aastore ******************************
905 * Does the cast check and eventually throws an exception *
907 *******************************************************************************/
910 sub $(3*8),%rsp /* allocate stack space */
911 test %rdi,%rdi /* if null pointer throw exception */
914 movl offarraysize(%rdi),%eax /* load size */
915 cmpl %eax,%esi /* do bound check */
916 jae nb_aastore_bound /* if out of bounds throw exception */
918 shl $3,%rsi /* index * 8 */
920 add %rsi,%r10 /* add index * 8 to arrayref */
922 mov %r10,(%rsp) /* save store position */
923 mov %rdx,8(%rsp) /* save object */
925 mov %rdx,%rsi /* object is second argument */
926 call builtin_canstore /* builtin_canstore(arrayref,object) */
927 test %rax,%rax /* if (false) throw exception */
930 mov (%rsp),%r10 /* restore store position */
931 mov 8(%rsp),%rdx /* restore object */
932 mov %rdx,offobjarrdata(%r10)/* store objectptr in array */
933 add $(3*8),%rsp /* free stack space */
937 mov string_java_lang_NullPointerException,%rdi
941 pop %r10 /* delete return address */
942 sub $3,%r10 /* faulting address is return adress - 3 */
943 jmp asm_handle_exception
946 mov string_java_lang_ArrayIndexOutOfBoundsException,%rdi
947 call new_exception_int /* %rsi already contains the index */
950 pop %r10 /* delete return address */
951 sub $3,%r10 /* faulting address is return adress - 3 */
952 jmp asm_handle_exception
955 mov string_java_lang_ArrayStoreException,%rdi
959 pop %r10 /* delete return address */
960 sub $3,%r10 /* faulting address is return adress - 3 */
961 jmp asm_handle_exception
964 /******************* function asm_initialize_thread_stack **********************
966 * initialized a thread stack *
967 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
969 *******************************************************************************/
971 asm_initialize_thread_stack:
982 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
983 mov %rsi,%rax /* return restorepoint in %rax */
987 /******************* function asm_perform_threadswitch *************************
989 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
991 * performs a threadswitch *
993 *******************************************************************************/
995 asm_perform_threadswitch:
996 sub $(7*8),%rsp /* allocate stack frame */
1005 mov 7*8(%rsp),%rax /* save current return address */
1008 mov %rsp,(%rdi) /* first argument **from */
1009 mov %rsp,(%rdx) /* third argument **stackTop */
1011 mov (%rsi),%rsp /* load new stack pointer */
1020 mov 6*8(%rsp),%rax /* restore return address */
1021 add $(7*8),%rsp /* free stack frame */
1026 /********************* function asm_switchstackandcall *************************
1028 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
1031 * Switches to a new stack, calls a function and switches back. *
1032 * a0 (%rdi) new stack pointer *
1033 * a1 (%rsi) function pointer *
1034 * a2 (%rdx) pointer to variable where stack top should be stored *
1035 * a3 (%rcx) pointer to user data, is passed to the function *
1037 *******************************************************************************/
1039 asm_switchstackandcall:
1040 sub $(1*8),%rsp /* keep stack 16-byte aligned */
1041 sub $16,%rdi /* allocate new stack */
1043 mov 8(%rsp),%rax /* save return address on new stack */
1045 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
1046 mov %rsp,(%rdx) /* save old stack pointer to variable */
1048 mov %rdi,%rsp /* switch to new stack */
1050 mov %rcx,%rdi /* pass pointer */
1051 call *%rsi /* and call function */
1053 mov (%rsp),%r10 /* load return address */
1054 mov 8(%rsp),%rsp /* switch to old stack */
1055 add $(1*8),%rsp /* free stack space */
1056 mov %r10,(%rsp) /* write return adress */
1101 * These are local overrides for various environment variables in Emacs.
1102 * Please do not remove this and leave it at the end of the file, where
1103 * Emacs will automagically detect them.
1104 * ---------------------------------------------------------------------
1107 * indent-tabs-mode: t