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 926 2004-02-26 00:16:50Z twisti $
42 /********************* exported functions and variables ***********************/
44 .globl asm_calljavafunction
45 .globl asm_calljavafunction2
46 .globl asm_calljavafunction2long
47 .globl asm_calljavafunction2double
48 .globl asm_call_jit_compiler
49 .globl asm_dumpregistersandcall
50 .globl asm_handle_exception
51 .globl asm_handle_nat_exception
52 .globl asm_check_clinit
53 .globl asm_builtin_checkcast
54 .globl asm_builtin_checkarraycast
55 .globl asm_builtin_anewarray
56 .globl asm_builtin_newarray_array
57 .globl asm_builtin_aastore
58 .globl asm_builtin_monitorenter
59 .globl asm_builtin_monitorexit
60 .globl asm_builtin_f2i
61 .globl asm_builtin_f2l
62 .globl asm_builtin_d2i
63 .globl asm_builtin_d2l
64 .globl asm_builtin_arrayinstanceof
65 .globl asm_perform_threadswitch
66 .globl asm_initialize_thread_stack
67 .globl asm_switchstackandcall
68 .globl asm_getcallingmethod
69 .globl asm_builtin_trace
70 .globl asm_builtin_exittrace
72 /*************************** imported functions *******************************/
75 .globl builtin_monitorexit
76 .globl builtin_throw_exception
77 .globl builtin_trace_exception
82 #define MethodPointer -8
88 #define ExTableSize -32
89 #define ExTableStart -32
91 #define ExEntrySize -32
94 #define ExHandlerPC -24
95 #define ExCatchType -32
98 /********************* function asm_calljavafunction ***************************
100 * This function calls a Java-method (which possibly needs compilation) *
101 * with up to 4 address parameters. *
103 * This functions calls the JIT-compiler which eventually translates the *
104 * method into machine code. *
107 * javaobject_header *asm_calljavamethod (methodinfo *m, *
108 * void *arg1, void *arg2, void *arg3, void *arg4); *
110 *******************************************************************************/
113 .ascii "calljavafunction\0\0"
116 .quad 0 /* catch type all */
117 .quad calljava_xhandler /* handler pc */
118 .quad calljava_xhandler /* end pc */
119 .quad asm_calljavafunction /* start pc */
120 .long 1 /* extable size */
121 .long 0 /* fltsave */
122 .long 0 /* intsave */
125 .long 8 /* frame size */
126 .quad 0 /* method pointer (pointer to name) */
128 asm_calljavafunction:
129 sub $(3*8),%rsp /* keep stack 16-byte aligned */
131 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
132 mov %rdi,%rax /* move function pointer to %rax */
133 /* compilerstub uses this */
135 mov %rsi,%rdi /* pass remaining parameters */
140 lea asm_call_jit_compiler,%r11
141 call *%r11 /* call JIT compiler */
148 add $(3*8),%rsp /* free stack space */
152 mov %rax,%rdi /* pass exception pointer */
153 call builtin_throw_exception
160 /********************* function asm_calljavafunction ***************************
162 * This function calls a Java-method (which possibly needs compilation) *
163 * with up to 4 address parameters. *
165 * This functions calls the JIT-compiler which eventually translates the *
166 * method into machine code. *
169 * javaobject_header *asm_calljavamethod (methodinfo *m, *
170 * void *arg1, void *arg2, void *arg3, void *arg4); *
172 *******************************************************************************/
175 .ascii "calljavafunction2\0\0"
178 .quad 0 /* catch type all */
179 .quad calljava_xhandler2 /* handler pc */
180 .quad calljava_xhandler2 /* end pc */
181 .quad asm_calljavafunction2 /* start pc */
182 .long 1 /* extable size */
183 .long 0 /* fltsave */
184 .long 0 /* intsave */
187 .long 8 /* frame size */
188 .quad 0 /* method pointer (pointer to name) */
190 asm_calljavafunction2:
191 asm_calljavafunction2double:
192 asm_calljavafunction2long:
193 sub $8,%rsp /* keep stack 16-byte aligned */
195 mov %rdi,%rax /* save method pointer for compiler */
196 mov %rcx,%r10 /* pointer to arg block */
198 mov offjniitem(%r10),%rdi /* move args into registers */
199 mov offjniitem + sizejniblock * 1(%r10),%rsi
200 mov offjniitem + sizejniblock * 2(%r10),%rdx
201 mov offjniitem + sizejniblock * 3(%r10),%rcx
203 lea asm_call_jit_compiler,%r11
204 call *%r11 /* call JIT compiler */
209 add $8,%rsp /* free stack space */
213 mov %rax,%rdi /* pass exception pointer */
214 call builtin_throw_exception
219 /****************** function asm_call_jit_compiler *****************************
221 * invokes the compiler for untranslated JavaVM methods. *
223 * Register R0 contains a pointer to the method info structure (prepared *
224 * by createcompilerstub). Using the return address in R26 and the *
225 * offset in the LDA instruction or using the value in methodptr R28 the *
226 * patching address for storing the method address can be computed: *
228 * method address was either loaded using *
230 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
231 * i386_call_reg(REG_ITMP2) *
235 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
236 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
237 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
238 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
239 * i386_call_reg(REG_ITMP1) *
241 * in the static case the method pointer can be computed using the *
242 * return address and the lda function following the jmp instruction *
244 *******************************************************************************/
246 asm_call_jit_compiler:
247 sub $8,%rsp /* keep stack 16-byte aligned */
249 mov %rbx,(%rsp) /* save register */
251 mov 8(%rsp),%r11 /* get return address */
252 mov -1(%r11),%bl /* get function code */
253 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%r10)? */
254 jne L_not_static_special
256 sub $11,%r11 /* calculate address of immediate */
257 jmp L_call_jit_compile
259 L_not_static_special:
260 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
261 jne L_not_virtual_interface
263 sub $7,%r11 /* calculate address of offset */
264 mov (%r11),%r11d /* get offset (32-bit) */
265 add %r10,%r11 /* add base address to get method address */
266 jmp L_call_jit_compile
268 L_not_virtual_interface: /* a call from asm_calljavamethod */
272 mov (%rsp),%rbx /* restore register */
274 sub $(24*8),%rsp /* 8 + 48 + 64 + 64 */
276 mov %r11,0*8(%rsp) /* save address for method pointer */
278 mov %rdi,1*8(%rsp) /* save arguments */
288 movq %xmm3,10*8(%rsp)
289 movq %xmm4,11*8(%rsp)
290 movq %xmm5,12*8(%rsp)
291 movq %xmm6,13*8(%rsp)
292 movq %xmm7,14*8(%rsp)
294 movq %xmm8,15*8(%rsp)/* we use them as callee saved registers */
295 movq %xmm9,16*8(%rsp)
296 movq %xmm10,17*8(%rsp)
297 movq %xmm11,18*8(%rsp)
298 movq %xmm12,19*8(%rsp)
299 movq %xmm13,20*8(%rsp)
300 movq %xmm14,21*8(%rsp)
301 movq %xmm15,22*8(%rsp)
303 mov %rax,%rdi /* pass method pointer */
318 movq 10*8(%rsp),%xmm3
319 movq 11*8(%rsp),%xmm4
320 movq 12*8(%rsp),%xmm5
321 movq 13*8(%rsp),%xmm6
322 movq 14*8(%rsp),%xmm7
324 movq 15*8(%rsp),%xmm8
325 movq 16*8(%rsp),%xmm9
326 movq 17*8(%rsp),%xmm10
327 movq 18*8(%rsp),%xmm11
328 movq 19*8(%rsp),%xmm12
329 movq 20*8(%rsp),%xmm13
330 movq 21*8(%rsp),%xmm14
331 movq 22*8(%rsp),%xmm15
335 test %r11,%r11 /* is address == 0 (asm_calljavamethod) */
338 mov %rax,(%r11) /* and now save the new pointer */
341 add $8,%rsp /* keep stack 16-byte aligned */
342 jmp *%rax /* ...and now call the new method */
346 /****************** function asm_dumpregistersandcall **************************
348 * This funtion saves all callee saved registers and calls the function *
349 * which is passed as parameter. *
351 * This function is needed by the garbage collector, which needs to access *
352 * all registers which are stored on the stack. Unused registers are *
353 * cleared to avoid interferances with the GC. *
355 * void asm_dumpregistersandcall (functionptr f); *
357 *******************************************************************************/
359 asm_dumpregistersandcall:
360 sub $(7*8),%rsp /* allocate stack space */
362 mov %rbx,0*8(%rsp) /* save all callee saved registers */
370 xor %rax,%rax /* intialize the remaining registers */
379 call *%rdi /* call function */
393 /********************* function asm_handle_exception ***************************
395 * This function handles an exception. It does not use the usual calling *
396 * conventions. The exception pointer is passed in REG_ITMP1 and the *
397 * pc from the exception raising position is passed in REG_ITMP2. It searches *
398 * the local exception table for a handler. If no one is found, it unwinds *
399 * stacks and continues searching the callers. *
401 * void asm_handle_exception (exceptionptr, exceptionpc); *
403 *******************************************************************************/
405 asm_handle_nat_exception:
406 add $8,%rsp /* clear return address of native stub */
408 asm_handle_exception:
410 mov %rax,0*8(%rsp) /* save exception pointer */
411 mov %r10,1*8(%rsp) /* save exception pc */
413 mov %r10,%rdi /* exception pc */
416 mov %rax,2*8(%rsp) /* save data segment pointer */
418 mov 0*8(%rsp),%rax /* restore exception pointer */
419 mov 1*8(%rsp),%r10 /* restore exception pc */
422 mov %rax,%rdi /* exception pointer */
423 mov MethodPointer(%r11),%rsi /* method pointer */
424 mov %r10,%rdx /* exception pc */
425 mov $1,%rcx /* set noindent flag */
426 call builtin_trace_exception
428 mov 2*8(%rsp),%r11 /* %r11 = data segment pointer */
429 mov ExTableSize(%r11),%rcx /* %rcx = exception table size */
430 test %rcx,%rcx /* if empty table skip */
433 lea ExTableStart(%r11),%rdi /* %rdi = start of exception table*/
434 mov 0*8(%rsp),%rax /* get xptr */
437 mov 1*8(%rsp),%r10 /* get xpc */
439 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
440 cmp %r10,%rdx /* %rdx = (startpc <= xpc) */
441 jg ex_table_cont /* if (false) continue */
442 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
443 cmp %rdx,%r10 /* %rdx = (xpc < endpc) */
444 jge ex_table_cont /* if (false) continue */
445 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
446 test %rdx,%rdx /* NULL catches everything */
449 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
450 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
451 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
452 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
453 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
454 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
455 cmp %edx,%esi /* xptr is instanceof catchtype */
459 mov ExHandlerPC(%rdi),%r10 /* xpc = exception handler pc */
461 mov 0*8(%rsp),%rax /* restore exception pointer */
462 add $(4*8),%rsp /* free stack frame */
464 jmp *%r10 /* jump to the handler */
467 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
468 dec %rcx /* decrement entry counter */
469 test %rcx,%rcx /* if (t0 > 0) next entry */
473 mov 0*8(%rsp),%rax /* restore exception pointer */
474 mov 1*8(%rsp),%r10 /* restore exception pc */
475 mov 2*8(%rsp),%r11 /* restore data segment pointer */
478 mov %rax,%rcx /* save exception pointer */
481 movl IsSync(%r11),%eax /* %rax = SyncOffset */
482 test %rax,%rax /* if zero no monitorexit */
493 call builtin_monitorexit
501 mov FrameSize(%r11),%eax /* %eax = frame size */
502 add %rax,%rsp /* unwind stack */
503 mov %rsp,%rax /* %rax = pointer to save area */
505 mov IntSave(%r11),%edx /* %edx = saved int register count*/
532 shl $3,%edx /* multiply by 8 bytes */
536 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
559 movq -48(%rax),%xmm10
561 movq -40(%rax),%xmm11
563 movq -32(%rax),%xmm12
565 movq -24(%rax),%xmm13
567 movq -16(%rax),%xmm14
572 pop %r10 /* the new xpc is return address */
573 sub $3,%r10 /* subtract 3 bytes for call */
580 call findmethod /* get the new data segment ptr */
587 mov %rcx,%rax /* restore saved exception pointer*/
591 mov %rax,0*8(%rsp) /* save exception pointer */
592 mov %r10,1*8(%rsp) /* save exception pc */
593 mov %r11,2*8(%rsp) /* save data segment pointer */
598 /********************* function asm_check_clinit *******************************
600 * Does null check and calls monitorenter or throws an exception *
602 *******************************************************************************/
605 mov offclassinit(%rax),%r10d /* get initialized flag (int) */
609 sub $(7*8),%rsp /* keep stack 16-byte aligned */
610 mov %rdi,0*8(%rsp) /* save argument registers */
617 mov %rax,%rdi /* pass classinfo pointer */
618 call class_init /* call class_init function */
620 mov 0*8(%rsp),%rdi /* restore argument registers */
629 mov (%rsp),%rax /* get return address */
630 sub $23,%rax /* asm_putstatic call code size */
631 movb $0xeb,(%rax) /* jmp rel8 */
632 movb $21,1(%rax) /* 8-bit offset */
636 /********************* function asm_builtin_monitorenter ***********************
638 * Does null check and calls monitorenter or throws an exception *
640 *******************************************************************************/
642 asm_builtin_monitorenter:
644 je nb_monitorenter /* if (null) throw exception */
645 jmp builtin_monitorenter /* else call builtin_monitorenter */
648 pop %r10 /* delete return address */
649 sub $3,%r10 /* faulting address is return adress - 3 */
650 mov proto_java_lang_NullPointerException,%rax
651 jmp asm_handle_exception
654 /********************* function asm_builtin_monitorexit ************************
656 * Does null check and calls monitorexit or throws an exception *
658 *******************************************************************************/
660 asm_builtin_monitorexit:
662 je nb_monitorexit /* if (null) throw exception */
663 jmp builtin_monitorexit /* else call builtin_monitorenter */
666 pop %r10 /* delete return address */
667 sub $3,%r10 /* faulting address is return adress - 3 */
668 mov proto_java_lang_NullPointerException,%rax
669 jmp asm_handle_exception
672 /********************* function asm_builtin_x2x ********************************
674 * Wrapper functions for float to int corner cases *
676 *******************************************************************************/
692 movq %xmm4,10*8(%rsp)
693 movq %xmm5,11*8(%rsp)
694 movq %xmm6,12*8(%rsp)
695 movq %xmm7,13*8(%rsp)
711 movq 10*8(%rsp),%xmm4
712 movq 11*8(%rsp),%xmm5
713 movq 12*8(%rsp),%xmm6
714 movq 13*8(%rsp),%xmm7
733 movq %xmm4,10*8(%rsp)
734 movq %xmm5,11*8(%rsp)
735 movq %xmm6,12*8(%rsp)
736 movq %xmm7,13*8(%rsp)
752 movq 10*8(%rsp),%xmm4
753 movq 11*8(%rsp),%xmm5
754 movq 12*8(%rsp),%xmm6
755 movq 13*8(%rsp),%xmm7
775 movq %xmm4,10*8(%rsp)
776 movq %xmm5,11*8(%rsp)
777 movq %xmm6,12*8(%rsp)
778 movq %xmm7,13*8(%rsp)
794 movq 10*8(%rsp),%xmm4
795 movq 11*8(%rsp),%xmm5
796 movq 12*8(%rsp),%xmm6
797 movq 13*8(%rsp),%xmm7
817 movq %xmm4,10*8(%rsp)
818 movq %xmm5,11*8(%rsp)
819 movq %xmm6,12*8(%rsp)
820 movq %xmm7,13*8(%rsp)
836 movq 10*8(%rsp),%xmm4
837 movq 11*8(%rsp),%xmm5
838 movq 12*8(%rsp),%xmm6
839 movq 13*8(%rsp),%xmm7
845 /*********************** function new_builtin_checkcast ************************
847 * Does the cast check and eventually throws an exception *
849 *******************************************************************************/
851 asm_builtin_checkcast:
857 /******************* function asm_builtin_checkarraycast ***********************
859 * Does the cast check and eventually throws an exception *
861 *******************************************************************************/
863 asm_builtin_checkarraycast:
864 sub $24,%rsp /* keep stack 16-byte aligned */
865 mov %rdi,(%rsp) /* save object pointer */
866 call builtin_checkarraycast /* builtin_checkarraycast */
867 test %rax,%rax /* if (false) throw exception */
869 mov (%rsp),%rax /* return object pointer */
870 add $24,%rsp /* free stack space */
875 pop %r10 /* delete return address */
876 sub $3,%r10 /* faulting address is return adress - 3 */
877 mov proto_java_lang_ClassCastException,%rax
878 jmp asm_handle_exception
881 /******************* function asm_builtin_aastore ******************************
883 * Does the cast check and eventually throws an exception *
885 *******************************************************************************/
888 sub $24,%rsp /* allocate stack space */
889 test %rdi,%rdi /* if null pointer throw exception */
892 movl offarraysize(%rdi),%eax /* load size */
893 cmpl %eax,%esi /* do bound check */
894 ja nb_aastore_bound /* if out of bounds throw exception */
896 shl $3,%rsi /* index * 8 */
898 add %rsi,%r10 /* add index * 8 to arrayref */
900 mov %r10,(%rsp) /* save store position */
901 mov %rdx,8(%rsp) /* save object */
903 mov %rdx,%rsi /* object is second argument */
904 call builtin_canstore /* builtin_canstore(arrayref,object) */
905 test %rax,%rax /* if (false) throw exception */
908 mov (%rsp),%r10 /* restore store position */
909 mov 8(%rsp),%rdx /* restore object */
910 mov %rdx,offobjarrdata(%r10)/* store objectptr in array */
911 add $24,%rsp /* free stack space */
916 pop %r10 /* delete return address */
917 sub $3,%r10 /* faulting address is return adress - 3 */
919 mov proto_java_lang_NullPointerException,%rax
920 jmp asm_handle_exception
924 pop %r10 /* delete return address */
925 sub $3,%r10 /* faulting address is return adress - 3 */
927 mov proto_java_lang_ArrayIndexOutOfBoundsException,%rax
928 jmp asm_handle_exception
932 pop %r10 /* delete return address */
933 sub $3,%r10 /* faulting address is return adress - 3 */
935 mov proto_java_lang_ArrayStoreException,%rax
936 jmp asm_handle_exception
939 /******************* function asm_initialize_thread_stack **********************
941 * initialized a thread stack *
942 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
944 *******************************************************************************/
946 asm_initialize_thread_stack:
957 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
958 mov %rsi,%rax /* return restorepoint in %rax */
962 /******************* function asm_perform_threadswitch *************************
964 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
966 * performs a threadswitch *
968 *******************************************************************************/
970 asm_perform_threadswitch:
971 sub $(7*8),%rsp /* allocate stack frame */
980 mov 7*8(%rsp),%rax /* save current return address */
983 mov %rsp,(%rdi) /* first argument **from */
984 mov %rsp,(%rdx) /* third argument **stackTop */
986 mov (%rsi),%rsp /* load new stack pointer */
995 mov 6*8(%rsp),%rax /* restore return address */
996 add $(7*8),%rsp /* free stack frame */
1001 /********************* function asm_switchstackandcall *************************
1003 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
1006 * Switches to a new stack, calls a function and switches back. *
1007 * a0 (%rdi) new stack pointer *
1008 * a1 (%rsi) function pointer *
1009 * a2 (%rdx) pointer to variable where stack top should be stored *
1010 * a3 (%rcx) pointer to user data, is passed to the function *
1012 *******************************************************************************/
1014 asm_switchstackandcall:
1015 sub $(1*8),%rsp /* keep stack 16-byte aligned */
1016 sub $16,%rdi /* allocate new stack */
1018 mov 8(%rsp),%rax /* save return address on new stack */
1020 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
1021 mov %rsp,(%rdx) /* save old stack pointer to variable */
1023 mov %rdi,%rsp /* switch to new stack */
1025 mov %rcx,%rdi /* pass pointer */
1026 call *%rsi /* and call function */
1028 mov (%rsp),%r10 /* load return address */
1029 mov 8(%rsp),%rsp /* switch to old stack */
1030 add $(1*8),%rsp /* free stack space */
1031 mov %r10,(%rsp) /* write return adress */
1035 /********************* function asm_getcallingmethod ***************************
1037 * classinfo *asm_getcallingmethod (); *
1039 * goes back stack frames to get the calling method *
1048 * Java_java_lang_System_getCallerClass *
1050 *******************************************************************************/
1052 asm_getcallingmethod:
1053 mov %rbp,%rax /* return address of native function */
1054 add $(2*8),%rax /* %rsp, return address */
1055 add $(7*8),%rax /* native stub stackframe */
1056 mov (%rax),%rdi /* return address to java function */
1058 mov MethodPointer(%rax),%rax
1103 * These are local overrides for various environment variables in Emacs.
1104 * Please do not remove this and leave it at the end of the file, where
1105 * Emacs will automagically detect them.
1106 * ---------------------------------------------------------------------
1109 * indent-tabs-mode: t