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
31 $Id: asmpart.S 2272 2005-04-11 15:49:51Z twisti $
37 #include "vm/jit/x86_64/arch.h"
38 #include "vm/jit/x86_64/offsets.h"
39 #include "vm/jit/x86_64/asmoffsets.h"
42 /* XXX Don't remove this!!! ***************************************************/
45 #error OFFSET(java_objectheader, vftbl) != 0: this will break code patching!
48 #if offvftblinterfacetable != 0
49 #error OFFSET(vftbl_t, interfacetable[0]) != 0: this will break code patching!
52 /******************************************************************************/
55 /* define it like the risc way */
92 /* save and restore macros ****************************************************/
94 #define SAVE_ARGUMENT_REGISTERS \
101 movq fa0,6*8(%rsp) ; \
102 movq fa1,7*8(%rsp) ; \
103 movq fa2,8*8(%rsp) ; \
104 movq fa3,9*8(%rsp) ; \
105 movq fa4,10*8(%rsp) ; \
106 movq fa5,11*8(%rsp) ; \
107 movq fa6,12*8(%rsp) ; \
108 movq fa7,13*8(%rsp) ;
111 #define RESTORE_ARGUMENT_REGISTERS \
118 movq 6*8(%rsp),fa0 ; \
119 movq 7*8(%rsp),fa1 ; \
120 movq 8*8(%rsp),fa2 ; \
121 movq 9*8(%rsp),fa3 ; \
122 movq 10*8(%rsp),fa4 ; \
123 movq 11*8(%rsp),fa5 ; \
124 movq 12*8(%rsp),fa6 ; \
125 movq 13*8(%rsp),fa7 ;
128 #define SAVE_TEMPORARY_REGISTERS \
132 #define RESTORE_TEMPORARY_REGISTERS \
139 /********************* exported functions and variables ***********************/
141 .globl asm_calljavafunction
142 .globl asm_calljavafunction_int
144 .globl asm_calljavafunction2
145 .globl asm_calljavafunction2int
146 .globl asm_calljavafunction2long
147 .globl asm_calljavafunction2float
148 .globl asm_calljavafunction2double
150 .globl asm_call_jit_compiler
151 .globl asm_handle_exception
152 .globl asm_handle_nat_exception
154 .globl asm_get_putstatic
155 .globl asm_get_putfield
156 .globl asm_builtin_new
157 .globl asm_builtin_newarray
158 .globl asm_builtin_multianewarray
159 .globl asm_invokestatic_special
160 .globl asm_invokevirtual
161 .globl asm_invokeinterface
162 .globl asm_checkcast_instanceof_flags
163 .globl asm_checkcast_instanceof_interface
164 .globl asm_checkcast_class
165 .globl asm_instanceof_class
166 .globl asm_check_clinit
168 .globl asm_builtin_checkarraycast
169 .globl asm_builtin_aastore
171 #if defined(USE_THREADS)
172 .globl asm_builtin_monitorenter
173 .globl asm_builtin_monitorexit
176 .globl asm_builtin_f2i
177 .globl asm_builtin_f2l
178 .globl asm_builtin_d2i
179 .globl asm_builtin_d2l
181 .globl asm_perform_threadswitch
182 .globl asm_initialize_thread_stack
183 .globl asm_switchstackandcall
184 .globl asm_criticalsections
185 .globl asm_getclassvalues_atomic
188 /********************* function asm_calljavafunction ***************************
190 * This function calls a Java-method (which possibly needs compilation) *
191 * with up to 4 address parameters. *
193 * This functions calls the JIT-compiler which eventually translates the *
194 * method into machine code. *
197 * javaobject_header *asm_calljavamethod (methodinfo *m, *
198 * void *arg1, void *arg2, void *arg3, void *arg4); *
200 *******************************************************************************/
205 .quad 0 /* catch type all */
206 .quad calljava_xhandler /* handler pc */
207 .quad calljava_xhandler /* end pc */
208 .quad asm_calljavafunction /* start pc */
209 .long 1 /* extable size */
210 .long 0 /* fltsave */
211 .long 0 /* intsave */
214 .long 8 /* frame size */
215 .quad 0 /* method pointer (pointer to name) */
217 asm_calljavafunction:
218 asm_calljavafunction_int:
219 sub $(3*8),%rsp /* keep stack 16-byte aligned */
221 mov %rbx,1*8(%rsp) /* %rbx is not a callee saved in cacao */
222 mov %rdi,%rax /* move function pointer to %rax */
223 /* compilerstub uses this */
225 mov %rsi,%rdi /* pass remaining parameters */
230 lea asm_call_jit_compiler,%r11
231 call *%r11 /* call JIT compiler */
235 add $(3*8),%rsp /* free stack space */
239 mov %rax,%rdi /* pass exception pointer */
240 call builtin_throw_exception
244 xor %rax,%rax /* return NULL */
248 /********************* function asm_calljavafunction ***************************
250 * This function calls a Java-method (which possibly needs compilation) *
251 * with up to 4 address parameters. *
253 * This functions calls the JIT-compiler which eventually translates the *
254 * method into machine code. *
257 * javaobject_header *asm_calljavamethod (methodinfo *m, *
258 * void *arg1, void *arg2, void *arg3, void *arg4); *
260 *******************************************************************************/
265 .quad 0 /* catch type all */
266 .quad calljava_xhandler2 /* handler pc */
267 .quad calljava_xhandler2 /* end pc */
268 .quad asm_calljavafunction2 /* start pc */
269 .long 1 /* extable size */
270 .long 0 /* fltsave */
271 .long 0 /* intsave */
274 .long 24 /* frame size */
275 .quad 0 /* method pointer (pointer to name) */
277 asm_calljavafunction2:
278 asm_calljavafunction2int:
279 asm_calljavafunction2long:
280 asm_calljavafunction2float:
281 asm_calljavafunction2double:
282 sub $(7*8),%rsp /* keep stack 16-byte aligned */
283 mov %rbx,0*8(%rsp) /* %rbx is not a callee saved in cacao */
290 mov %rdi,%rax /* move method pointer for compiler */
291 xor %rbp,%rbp /* set argument stack frame to zero */
293 test %rsi,%rsi /* maybe we have no args... */
296 mov %rsi,itmp3 /* arg count */
297 mov %rcx,itmp2 /* pointer to arg block */
299 mov itmp2,%r14 /* save argument block pointer */
300 mov itmp3,%r15 /* save argument count */
302 sub $sizejniblock,itmp2 /* initialize pointer (smaller code) */
303 add $1,itmp3 /* initialize argument count */
304 xor %r12,%r12 /* initialize integer argument counter */
305 xor %r13,%r13 /* initialize float argument counter */
308 add $sizejniblock,itmp2 /* goto next argument block */
309 dec itmp3 /* argument count - 1 */
310 jz L_register_copy_done
311 andb $0x02,offjniitemtype(itmp2) /* is this a float/double type? */
312 jnz L_register_handle_float /* yes, handle it */
314 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
315 je L_register_copy /* register? yes, next loop */
317 lea jumptable_integer,%rbp
318 mov 0(%rbp,%r12,8),%rbx
319 inc %r12 /* integer argument counter + 1 */
322 L_register_handle_float:
323 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
324 je L_register_copy /* register? yes, next loop */
326 lea jumptable_float,%rbp
327 mov 0(%rbp,%r13,8),%rbx
328 inc %r13 /* float argument counter + 1 */
331 L_register_copy_done:
332 mov %r15,%rbp /* calculate remaining arguments */
333 sub %r12,%rbp /* - integer arguments in registers */
334 sub %r13,%rbp /* - float arguments in registers */
335 jle L_copy_done /* are all assigned to registers? */
337 shl $3,%rbp /* calculate stack size */
338 sub %rbp,%rsp /* stack frame for arguments */
339 mov %rsp,%rbx /* use %rbx as temp sp */
341 sub $sizejniblock,%r14 /* initialize pointer (smaller code) */
342 add $1,%r15 /* initialize argument count */
345 add $sizejniblock,%r14 /* goto next argument block */
346 dec %r15 /* are there any arguments left? */
347 jz L_copy_done /* no test needed after dec */
349 andb $0x02,offjniitemtype(%r14) /* is this a float/double type? */
350 jnz L_stack_handle_float
351 dec %r12 /* arguments assigned to registers */
352 jge L_stack_copy_loop
355 L_stack_handle_float:
356 dec %r13 /* arguments assigned to registers */
357 jge L_stack_copy_loop
360 mov offjniitem(%r14),itmp3 /* copy s8 argument onto stack */
362 add $8,%rbx /* increase sp to next argument */
363 jmp L_stack_copy_loop
366 lea asm_call_jit_compiler,%r11/* %rax still contains method pointer */
367 call *%r11 /* call JIT compiler */
369 add %rbp,%rsp /* remove argument stack frame if any */
371 mov 5*8(%rsp),%r15 /* restore callee saved registers */
377 add $(7*8),%rsp /* free stack space */
381 mov %rax,%rdi /* pass exception pointer */
382 call builtin_throw_exception
384 mov 5*8(%rsp),%r15 /* restore callee saved registers */
390 add $(7*8),%rsp /* free stack space */
391 xor %rax,%rax /* return NULL */
404 mov offjniitem(itmp2),a0
407 mov offjniitem(itmp2),a1
410 mov offjniitem(itmp2),a2
413 mov offjniitem(itmp2),a3
416 mov offjniitem(itmp2),a4
419 mov offjniitem(itmp2),a5
434 movq offjniitem(itmp2),fa0
437 movq offjniitem(itmp2),fa1
440 movq offjniitem(itmp2),fa2
443 movq offjniitem(itmp2),fa3
446 movq offjniitem(itmp2),fa4
449 movq offjniitem(itmp2),fa5
452 movq offjniitem(itmp2),fa6
455 movq offjniitem(itmp2),fa7
459 /****************** function asm_call_jit_compiler *****************************
461 * invokes the compiler for untranslated JavaVM methods. *
463 * Register R0 contains a pointer to the method info structure (prepared *
464 * by createcompilerstub). Using the return address in R26 and the *
465 * offset in the LDA instruction or using the value in methodptr R28 the *
466 * patching address for storing the method address can be computed: *
468 * method address was either loaded using *
470 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
471 * i386_call_reg(REG_ITMP2) *
475 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
476 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
477 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
478 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
479 * i386_call_reg(REG_ITMP1) *
481 * in the static case the method pointer can be computed using the *
482 * return address and the lda function following the jmp instruction *
484 *******************************************************************************/
486 asm_call_jit_compiler:
487 sub $8,%rsp /* keep stack 16-byte aligned */
489 mov %rbx,(%rsp) /* save register */
491 mov 8(%rsp),%r11 /* get return address */
492 mov -1(%r11),%bl /* get function code */
493 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%r10)? */
494 jne L_not_static_special
496 sub $11,%r11 /* calculate address of immediate */
497 jmp L_call_jit_compile
499 L_not_static_special:
500 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%rax) */
501 jne L_not_virtual_interface
503 sub $7,%r11 /* calculate address of offset */
504 mov (%r11),%r11d /* get offset (32-bit) */
505 add %r10,%r11 /* add base address to get method address */
506 jmp L_call_jit_compile
508 L_not_virtual_interface: /* a call from asm_calljavamethod */
512 mov (%rsp),%rbx /* restore register */
514 sub $(24*8),%rsp /* 8 + 6*8 + 8*8 + 8*8 */
516 mov %r11,0*8(%rsp) /* save address for method pointer */
518 mov a0,1*8(%rsp) /* save arguments */
534 movq %xmm8,15*8(%rsp)/* we use them as callee saved registers */
535 movq %xmm9,16*8(%rsp)
536 movq %xmm10,17*8(%rsp)
537 movq %xmm11,18*8(%rsp)
538 movq %xmm12,19*8(%rsp)
539 movq %xmm13,20*8(%rsp)
540 movq %xmm14,21*8(%rsp)
541 movq %xmm15,22*8(%rsp)
543 mov %rax,%rdi /* pass method pointer */
564 movq 15*8(%rsp),%xmm8
565 movq 16*8(%rsp),%xmm9
566 movq 17*8(%rsp),%xmm10
567 movq 18*8(%rsp),%xmm11
568 movq 19*8(%rsp),%xmm12
569 movq 20*8(%rsp),%xmm13
570 movq 21*8(%rsp),%xmm14
571 movq 22*8(%rsp),%xmm15
574 add $8,%rsp /* keep stack 16-byte aligned */
576 test %rax,%rax /* check for exception */
577 je L_asm_call_jit_compiler_exception
579 test %r11,%r11 /* is address == 0 (asm_calljavamethod) */
582 mov %rax,(%r11) /* and now save the new pointer */
585 jmp *%rax /* ...and now call the new method */
587 L_asm_call_jit_compiler_exception:
588 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
589 call builtin_asm_get_exceptionptrptr
592 lea _exceptionptr,itmp2
594 mov (itmp2),xptr /* get the exception pointer */
595 movl $0,(itmp2) /* clear the exception pointer */
597 pop xpc /* delete return address */
598 sub $5,xpc /* faulting address is ra - 5 */
600 jmp asm_handle_exception
603 /********************* function asm_handle_exception ***************************
605 * This function handles an exception. It does not use the usual calling *
606 * conventions. The exception pointer is passed in REG_ITMP1 and the *
607 * pc from the exception raising position is passed in REG_ITMP2. It searches *
608 * the local exception table for a handler. If no one is found, it unwinds *
609 * stacks and continues searching the callers. *
611 * void asm_handle_exception (exceptionptr, exceptionpc); *
613 *******************************************************************************/
615 asm_handle_nat_exception:
616 add $8,%rsp /* clear return address of native stub*/
618 asm_handle_exception:
620 mov xptr,0*8(%rsp) /* save exception pointer */
621 mov xpc,1*8(%rsp) /* save exception pc */
623 mov xpc,%rdi /* exception pc */
624 call codegen_findmethod
626 mov %rax,2*8(%rsp) /* save data segment pointer */
628 mov 0*8(%rsp),%rax /* restore exception pointer */
629 mov 1*8(%rsp),%r10 /* restore exception pc */
632 mov %rax,%rdi /* exception pointer */
633 mov MethodPointer(itmp3),%rsi /* method pointer */
634 mov xpc,%rdx /* exception pc */
636 mov $1,%r8 /* set noindent flag */
637 call builtin_trace_exception
639 mov 2*8(%rsp),itmp3 /* %r11 = data segment pointer */
640 mov ExTableSize(itmp3),%rcx /* %rcx = exception table size */
641 test %rcx,%rcx /* if empty table skip */
644 lea ExTableStart(itmp3),%rdi /* %rdi = start of exception table */
645 mov 0*8(%rsp),xptr /* get xptr */
648 mov 1*8(%rsp),xpc /* get xpc */
650 mov ExStartPC(%rdi),%rdx /* %rdx = exception start pc */
651 cmp xpc,%rdx /* %rdx = (startpc <= xpc) */
652 jg ex_table_cont /* if (false) continue */
653 mov ExEndPC(%rdi),%rdx /* %rdx = exception end pc */
654 cmp %rdx,xpc /* %rdx = (xpc < endpc) */
655 jge ex_table_cont /* if (false) continue */
656 mov ExCatchType(%rdi),%rdx /* %rdx = exception catch type */
657 test %rdx,%rdx /* NULL catches everything */
660 cmpl $0,offclassloaded(%rdx) /* check if class is loaded */
670 call load_class_bootstrap
679 cmpl $0,offclasslinked(%rdx) /* check if class is linked */
698 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
706 mov offobjvftbl(%rax),%rsi /* %rsi = vftblptr(xptr) */
707 mov offclassvftbl(%rdx),%rdx /* %rdx = vftblptr(catchtype) class (not obj) */
708 mov offbaseval(%rsi),%esi /* %esi = baseval(xptr) */
709 mov offbaseval(%rdx),%r10d /* %r10d = baseval(catchtype) */
710 mov offdiffval(%rdx),%edx /* %edx = diffval(catchtype) */
712 sub %r10d,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
714 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
718 cmp %edx,%esi /* xptr is instanceof catchtype */
722 mov ExHandlerPC(%rdi),xpc /* xpc = exception handler pc */
724 mov 0*8(%rsp),%rax /* restore exception pointer */
725 add $(4*8),%rsp /* free stack frame */
727 jmp *xpc /* jump to the handler */
730 lea ExEntrySize(%rdi),%rdi /* next exception table entry */
731 dec %rcx /* decrement entry counter */
732 test %rcx,%rcx /* if (t0 > 0) next entry */
736 mov 0*8(%rsp),%rax /* restore exception pointer */
737 mov 1*8(%rsp),%r10 /* restore exception pc */
738 mov 2*8(%rsp),%r11 /* restore data segment pointer */
741 mov %rax,%rcx /* save exception pointer */
744 movl IsSync(%r11),%eax /* %rax = SyncOffset */
745 test %rax,%rax /* if zero no monitorexit */
748 #if defined(USE_THREADS)
757 call builtin_monitorexit
766 mov FrameSize(%r11),%eax /* %eax = frame size */
767 add %rax,%rsp /* unwind stack */
768 mov %rsp,%rax /* %rax = pointer to save area */
770 mov IntSave(%r11),%edx /* %edx = saved int register count*/
797 shl $3,%edx /* multiply by 8 bytes */
801 mov FltSave(%r11),%edx /* %edx = saved flt register count*/
824 movq -48(%rax),%xmm10
826 movq -40(%rax),%xmm11
828 movq -32(%rax),%xmm12
830 movq -24(%rax),%xmm13
832 movq -16(%rax),%xmm14
837 pop %r10 /* the new xpc is return address */
838 sub $3,%r10 /* subtract 3 bytes for call */
845 call codegen_findmethod /* get the new data segment ptr */
852 mov %rcx,%rax /* restore saved exception pointer*/
856 mov %rax,0*8(%rsp) /* save exception pointer */
857 mov %r10,1*8(%rsp) /* save exception pc */
858 mov %r11,2*8(%rsp) /* save data segment pointer */
863 /* asm_get_putstatic ***********************************************************
869 8 machine code (which is patched back later)
870 0 unresolved field reference
872 *******************************************************************************/
875 sub $(15*8),%rsp /* stack frame (16-byte aligned) */
877 SAVE_ARGUMENT_REGISTERS
878 SAVE_TEMPORARY_REGISTERS
880 mov (0+15)*8(%rsp),a0 /* pass unresolved_field pointer */
881 call helper_resolve_fieldinfo_value_address /* call the helper function*/
883 RESTORE_ARGUMENT_REGISTERS
884 RESTORE_TEMPORARY_REGISTERS
886 mov (1+15)*8(%rsp),itmp3 /* get machine code */
887 add $((2+15)*8),%rsp /* remove stack frame, keep ra */
889 test v0,v0 /* exception thrown? */
890 jz L_asm_codepatcher_exception
892 pop itmp2 /* get return address */
893 sub $5,itmp2 /* remove size of `call rel32' */
894 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
896 movswq 3(itmp2),itmp3 /* get %rip offset */
897 add itmp2,itmp3 /* add return address (%rip) */
898 add $7,itmp3 /* add mov instruction size */
899 mov v0,(itmp3) /* move field address to data segment */
900 jmp *itmp2 /* call new patched code */
902 L_asm_codepatcher_exception:
903 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
904 call builtin_asm_get_exceptionptrptr
907 lea _exceptionptr,itmp2
909 mov (itmp2),xptr /* get the exception pointer */
910 movl $0,(itmp2) /* clear the exception pointer */
912 pop xpc /* get and remove return address */
913 sub $5,xpc /* faulting address is ra - 5 */
914 jmp asm_handle_exception
917 /* asm_get_putfield ************************************************************
923 8 machine code (which is patched back later)
924 0 unresolved field reference
926 *******************************************************************************/
929 sub $(17*8),%rsp /* stack frame (16-byte aligned) */
931 SAVE_ARGUMENT_REGISTERS
932 SAVE_TEMPORARY_REGISTERS
934 mov itmp1,15*8(%rsp) /* save itmp1 and itmp2 */
935 mov itmp2,16*8(%rsp) /* can be used by field instructions */
937 mov (0+17)*8(%rsp),a0 /* pass unresolved_method pointer */
938 call helper_resolve_fieldinfo_offset /* call the helper function */
940 RESTORE_ARGUMENT_REGISTERS
941 RESTORE_TEMPORARY_REGISTERS
943 cmp $-1,v0l /* exception thrown? test for -1, */
944 /* because field offset can be 0 */
945 jz L_asm_codepatcher_exception_with_stack_frame
947 mov (1+17)*8(%rsp),itmp3 /* get machine code */
948 mov (2+17)*8(%rsp),itmp2 /* get return address */
949 sub $5,itmp2 /* remove size of `call rel32' */
950 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
952 cmpb $0xf2,(itmp2) /* test for movsd */
953 je L_asm_get_putfield_float
954 cmpb $0xf3,(itmp2) /* test for movss */
955 je L_asm_get_putfield_float
956 cmpb $0x24,3(itmp2) /* check for (%rsp) or (%r12) */
957 je L_asm_get_putfield_r12_membase
959 mov v0l,3(itmp2) /* patch field offset */
960 jmp L_asm_get_putfield_normal
962 L_asm_get_putfield_float:
963 mov v0l,5(itmp2) /* patch field offset (position + 2) */
964 jmp L_asm_get_putfield_normal
966 L_asm_get_putfield_r12_membase:
967 mov v0l,4(itmp2) /* patch field offset (position + 1) */
969 L_asm_get_putfield_normal:
972 mov 15*8(%rsp),itmp1 /* restore itmp1 and itmp2 */
973 mov 16*8(%rsp),itmp2 /* can be used by field instructions */
975 add $((3+17)*8),%rsp /* remove stack frame */
976 jmp *itmp3 /* call new patched code */
978 L_asm_codepatcher_exception_with_stack_frame:
979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
980 call builtin_asm_get_exceptionptrptr
983 lea _exceptionptr,itmp2
985 mov (itmp2),xptr /* get the exception pointer */
986 movl $0,(itmp2) /* clear the exception pointer */
988 mov (2+17)*8(%rsp),xpc /* get return address */
989 sub $5,xpc /* faulting address is ra - 5 */
990 add $((3+17)*8),%rsp /* remove stack frame */
991 jmp asm_handle_exception
994 /* asm_builtin_new *************************************************************
999 a0 contains the class reference
1001 *******************************************************************************/
1004 sub $(8*1),%rsp /* stack frame (16-byte aligned) */
1005 call helper_resolve_classinfo /* call the helper function */
1006 add $(8*1),%rsp /* remove stack frame */
1007 test v0,v0 /* exception thrown? */
1008 jz L_asm_codepatcher_exception
1010 pop itmp2 /* get return address */
1011 sub $(3+10+10),itmp2 /* 3 (callq) + 10 (movi) + 10 (movi) */
1012 mov v0,2(itmp2) /* patch in new classinfo*: 2 (mov) */
1014 lea builtin_new,itmp1 /* get address from builtin_new */
1015 mov itmp1,12(itmp2) /* patch back function address */
1016 jmp *itmp2 /* call new patched code */
1019 /* asm_builtin_newarray ********************************************************
1024 a1 contains the class reference
1026 *******************************************************************************/
1028 asm_builtin_newarray:
1029 sub $(8*1),%rsp /* stack frame (16-byte aligned) */
1030 mov a0,0*8(%rsp) /* save argument */
1031 mov a1,a0 /* pass class reference */
1032 call helper_resolve_classinfo_vftbl /* call the helper function */
1033 mov 0*8(%rsp),a0 /* restore argument */
1034 add $(8*1),%rsp /* remove stack frame */
1035 test v0,v0 /* exception thrown? */
1036 jz L_asm_codepatcher_exception
1038 pop itmp2 /* get return address */
1039 sub $(3+10+10),itmp2 /* 3 (callq) + 10 (movi) + 10 (movi) */
1040 mov v0,2(itmp2) /* patch in new vftbl*: 2 (mov) */
1042 lea builtin_newarray,itmp1 /* get address from builtin_newarray */
1043 mov itmp1,12(itmp2) /* patch back function address */
1044 jmp *itmp2 /* call new patched code */
1047 /* asm_builtin_multianewarray **************************************************
1052 a1 contains the class reference
1054 *******************************************************************************/
1056 asm_builtin_multianewarray:
1057 sub $(1*8),%rsp /* stack frame (16-byte aligned) */
1058 mov a1,a0 /* pass class reference */
1059 call helper_resolve_classinfo_vftbl /* call the helper function */
1060 add $(1*8),%rsp /* remove stack frame */
1061 test v0,v0 /* exception thrown? */
1062 jz L_asm_codepatcher_exception
1064 pop itmp2 /* get return address */
1065 sub $(3+10+3+10+10),itmp2 /* go back to a0 mov */
1066 mov v0,10+2(itmp2) /* patch in new vftbl*: 10 (movi) + 2 */
1068 lea builtin_nmultianewarray,itmp1 /* get function address */
1069 mov itmp1,10+10+3+2(itmp2) /* patch back function address */
1070 jmp *itmp2 /* call new patched code */
1073 /* asm_invokestatic_special ****************************************************
1079 8 machine code (which is patched back later)
1080 0 unresolved method reference
1082 *******************************************************************************/
1084 asm_invokestatic_special:
1085 sub $(15*8),%rsp /* stack frame (16-byte aligned) */
1087 SAVE_ARGUMENT_REGISTERS
1089 mov (0+15)*8(%rsp),a0 /* pass unresolved_method pointer */
1090 call helper_resolve_methodinfo_stubroutine /* call the helper function */
1092 RESTORE_ARGUMENT_REGISTERS
1094 mov (1+15)*8(%rsp),itmp3 /* get machine code */
1095 add $((2+15)*8),%rsp /* remove stack frame, keep ra */
1097 test v0,v0 /* exception thrown? */
1098 jz L_asm_codepatcher_exception
1100 pop itmp2 /* get return address */
1101 sub $5,itmp2 /* remove size of `call rel32' */
1102 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1104 mov v0,2(itmp2) /* patch stubroutine: 2 (mov) */
1105 jmp *itmp2 /* call new patched code */
1108 /* asm_invokevirtual ***********************************************************
1114 8 machine code (which is patched back later)
1115 0 unresolved method reference
1117 *******************************************************************************/
1120 sub $(15*8),%rsp /* stack frame (16-byte aligned) */
1122 SAVE_ARGUMENT_REGISTERS
1124 mov (0+15)*8(%rsp),a0 /* pass unresolved_method pointer */
1125 call helper_resolve_methodinfo_vftblindex /* call the helper function */
1127 RESTORE_ARGUMENT_REGISTERS
1129 mov (1+15)*8(%rsp),itmp3 /* get machine code */
1130 add $((2+15)*8),%rsp /* remove stack frame, keep ra */
1132 cmp $-1,v0l /* exception thrown? test for -1, */
1133 /* because vftblindex can be 0 */
1134 je L_asm_codepatcher_exception
1136 pop itmp2 /* get return address */
1137 sub $5,itmp2 /* remove size of `call rel32' */
1138 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1140 shl $3,v0l /* sizeof(methodptr) * lm->vftblindex */
1141 add $offvftbltable,v0l /* + OFFSET(vftbl_t, table[0]) */
1142 movl v0l,3+3(itmp2) /* patch 32 bit offset: 3 (mov) + 3 */
1143 jmp *itmp2 /* call new patched code */
1146 /* asm_invokeinterface *********************************************************
1152 8 machine code (which is patched back later)
1153 0 unresolved method reference
1155 *******************************************************************************/
1157 asm_invokeinterface:
1158 sub $(15*8),%rsp /* stack frame (16-byte aligned) */
1160 SAVE_ARGUMENT_REGISTERS
1162 mov (0+15)*8(%rsp),a0 /* pass unresolved_method pointer */
1163 call helper_resolve_methodinfo /* call the helper function */
1165 RESTORE_ARGUMENT_REGISTERS
1167 mov (1+15)*8(%rsp),itmp3 /* get machine code */
1168 add $((2+15)*8),%rsp /* remove stack frame, keep ra */
1170 test v0,v0 /* exception thrown? */
1171 jz L_asm_codepatcher_exception
1173 pop itmp2 /* get return address */
1174 sub $5,itmp2 /* remove size of `call rel32' */
1175 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1177 mov offmethodclass(v0),itmp3 /* ci = lm->class */
1178 mov offclassindex(itmp3),itmp3l /* ci->index (s4) */
1179 shl $3,itmp3l /* * sizeof(methodptr) */
1180 neg itmp3l /* OFFSET(vftbl_t, interfacetable[0]) */
1181 /* XXX the offset is always 0!!! */
1182 mov itmp3l,3+3(itmp2) /* patch 32 bit offset: 3 (mov) + 3 */
1184 mov offmethodclass(v0),itmp3 /* ci = lm->class */
1185 sub offclassmethods(itmp3),v0 /* lm - ci->methods */
1189 mov $sizemethodinfo,itmp3l
1193 shl $3,v0 /* * sizeof(methodptr) */
1194 mov v0l,3+7+3(itmp2) /* patch 32bit offset: 3 + 7 (mov) + 3*/
1195 jmp *itmp2 /* call new patched code */
1198 /* asm_checkcast_instanceof_flags **********************************************
1204 8 machine code (which is patched back later)
1205 0 unresolved field reference
1207 *******************************************************************************/
1209 asm_checkcast_instanceof_flags:
1210 sub $(17*8),%rsp /* stack frame (16-byte aligned) */
1212 SAVE_ARGUMENT_REGISTERS
1213 SAVE_TEMPORARY_REGISTERS
1215 mov itmp1,15*8(%rsp) /* save itmp1 and itmp2 */
1216 mov itmp2,16*8(%rsp) /* can be used by CHECKCAST */
1218 mov (0+17)*8(%rsp),a0 /* pass unresolved_method pointer */
1219 call helper_resolve_classinfo_flags /* call the helper function */
1221 RESTORE_ARGUMENT_REGISTERS
1222 RESTORE_TEMPORARY_REGISTERS
1224 cmp $-1,v0l /* exception thrown? test for -1, */
1225 /* because class flags can be 0 */
1226 jz L_asm_codepatcher_exception_with_stack_frame
1228 mov (1+17)*8(%rsp),itmp3 /* get machine code */
1229 mov (2+17)*8(%rsp),itmp2 /* get return address */
1230 sub $5,itmp2 /* remove size of `call rel32' */
1231 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1233 mov v0l,2(itmp2) /* patch super->flags */
1235 mov itmp2,itmp3 /* move return address */
1236 mov 15*8(%rsp),itmp1 /* restore itmp1 and itmp2 */
1237 mov 16*8(%rsp),itmp2 /* can be used by field instructions */
1238 add $((3+17)*8),%rsp /* remove stack frame */
1239 jmp *itmp3 /* call new patched code */
1242 /* asm_checkcast_instanceof_interface ******************************************
1248 8 machine code (which is patched back later)
1249 0 unresolved field reference
1251 *******************************************************************************/
1253 asm_checkcast_instanceof_interface:
1254 sub $(17*8),%rsp /* stack frame (16-byte aligned) */
1256 SAVE_ARGUMENT_REGISTERS
1257 SAVE_TEMPORARY_REGISTERS
1259 mov itmp1,15*8(%rsp) /* save itmp1 and itmp2 */
1260 mov itmp2,16*8(%rsp) /* can be used by CHECKCAST */
1262 mov (0+17)*8(%rsp),a0 /* pass unresolved_method pointer */
1263 call helper_resolve_classinfo_index /* call the helper function */
1265 RESTORE_ARGUMENT_REGISTERS
1266 RESTORE_TEMPORARY_REGISTERS
1268 cmp $-1,v0l /* exception thrown? test for -1, */
1269 /* because class index can be 0 */
1270 jz L_asm_codepatcher_exception_with_stack_frame
1272 mov (1+17)*8(%rsp),itmp3 /* get machine code */
1273 mov (2+17)*8(%rsp),itmp2 /* get return address */
1274 sub $5,itmp2 /* remove size of `call rel32' */
1275 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1277 mov v0l,7+3(itmp2) /* patch super->index */
1279 shl $3,v0l /* super->index * sizeof(methodptr) */
1280 neg v0l /* OFFSET(vftbl_t, interfacetable[0]) */
1281 /* XXX the offset is always 0!!! */
1282 mov v0l,7+7+3+6+3(itmp2) /* patch calculated value */
1284 mov itmp2,itmp3 /* move return address */
1285 mov 15*8(%rsp),itmp1 /* restore itmp1 and itmp2 */
1286 mov 16*8(%rsp),itmp2 /* can be used by field instructions */
1287 add $((3+17)*8),%rsp /* remove stack frame */
1288 jmp *itmp3 /* call new patched code */
1291 /* asm_checkcast_class *********************************************************
1297 8 machine code (which is patched back later)
1298 0 unresolved field reference
1300 *******************************************************************************/
1302 asm_checkcast_class:
1303 sub $(17*8),%rsp /* stack frame (16-byte aligned) */
1305 SAVE_ARGUMENT_REGISTERS
1306 SAVE_TEMPORARY_REGISTERS
1308 mov itmp1,15*8(%rsp) /* save itmp1 and itmp2 */
1309 mov itmp2,16*8(%rsp) /* can be used by CHECKCAST */
1311 mov (0+17)*8(%rsp),a0 /* pass unresolved_method pointer */
1312 call helper_resolve_classinfo_vftbl /* call the helper function */
1314 RESTORE_ARGUMENT_REGISTERS
1315 RESTORE_TEMPORARY_REGISTERS
1317 test v0,v0 /* exception thrown? */
1318 jz L_asm_codepatcher_exception_with_stack_frame
1320 mov (1+17)*8(%rsp),itmp3 /* get machine code */
1321 mov (2+17)*8(%rsp),itmp2 /* get return address */
1322 sub $5,itmp2 /* remove size of `call rel32' */
1323 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1325 mov v0,2(itmp2) /* patch super->vftbl */
1326 mov v0,10+7+7+3+2(itmp2) /* patch super->vftbl */
1328 mov itmp2,itmp3 /* move return address */
1329 mov 15*8(%rsp),itmp1 /* restore itmp1 and itmp2 */
1330 mov 16*8(%rsp),itmp2
1331 add $((3+17)*8),%rsp /* remove stack frame */
1332 jmp *itmp3 /* call new patched code */
1335 /* asm_instanceof_class ********************************************************
1341 8 machine code (which is patched back later)
1342 0 unresolved field reference
1344 *******************************************************************************/
1346 asm_instanceof_class:
1347 sub $(17*8),%rsp /* stack frame (16-byte aligned) */
1349 SAVE_ARGUMENT_REGISTERS
1350 SAVE_TEMPORARY_REGISTERS
1352 mov itmp1,15*8(%rsp) /* save itmp1 and itmp2 */
1353 mov itmp2,16*8(%rsp) /* can be used by INSTANCEOF */
1355 mov (0+17)*8(%rsp),a0 /* pass unresolved_method pointer */
1356 call helper_resolve_classinfo_vftbl /* call the helper function */
1358 RESTORE_ARGUMENT_REGISTERS
1359 RESTORE_TEMPORARY_REGISTERS
1361 test v0,v0 /* exception thrown? */
1362 jz L_asm_codepatcher_exception_with_stack_frame
1364 mov (1+17)*8(%rsp),itmp3 /* get machine code */
1365 mov (2+17)*8(%rsp),itmp2 /* get return address */
1366 sub $5,itmp2 /* remove size of `call rel32' */
1367 mov itmp3,(itmp2) /* patch back original code (8 bytes) */
1369 mov v0,2(itmp2) /* patch super->vftbl */
1371 mov itmp2,itmp3 /* move return address */
1372 mov 15*8(%rsp),itmp1 /* restore itmp1 and itmp2 */
1373 mov 16*8(%rsp),itmp2
1374 add $((3+17)*8),%rsp /* remove stack frame */
1375 jmp *itmp3 /* call new patched code */
1378 /* asm_check_clinit ************************************************************
1384 8 machine code (which is patched back later)
1387 *******************************************************************************/
1390 mov 0*8(%rsp),itmp1 /* get classinfo pointer */
1391 mov offclassinit(itmp1),itmp2l /* get initialized flag (int) */
1393 jnz L_asm_check_clinit_is_initialized
1395 sub $(15*8),%rsp /* keep stack 16-byte aligned */
1397 SAVE_ARGUMENT_REGISTERS
1398 SAVE_TEMPORARY_REGISTERS
1400 mov (0+15)*8(%rsp),a0 /* pass classinfo pointer */
1401 call initialize_class /* call class initialize function */
1403 RESTORE_ARGUMENT_REGISTERS
1404 RESTORE_TEMPORARY_REGISTERS
1406 add $(15*8),%rsp /* remove stack frame, keep ra */
1408 test v0,v0 /* exception thrown? */
1409 je L_asm_check_clinit_exception
1411 L_asm_check_clinit_is_initialized:
1412 add $(1*8),%rsp /* remove classinfo pointer */
1413 pop itmp3 /* get machine code */
1414 pop itmp2 /* get return address */
1415 sub $5,itmp2 /* remove size of `call rel32' */
1416 mov itmp3,(itmp2) /* patch back in 8 bytes */
1417 jmp *itmp2 /* jump to patched code an execute it */
1419 L_asm_check_clinit_exception:
1420 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1421 call builtin_asm_get_exceptionptrptr
1424 lea _exceptionptr,itmp2
1426 mov (itmp2),xptr /* get the exception pointer */
1427 movl $0,(itmp2) /* clear the exception pointer */
1429 add $(2*8),%rsp /* remove stack frame, keep ra */
1430 pop xpc /* delete return address */
1431 sub $5,xpc /* faulting address is ra - 5 */
1432 jmp asm_handle_exception
1435 /********************* function asm_builtin_monitorenter ***********************
1437 * Does null check and calls monitorenter or throws an exception *
1439 *******************************************************************************/
1441 #if defined(USE_THREADS)
1442 asm_builtin_monitorenter:
1444 je nb_monitorenter /* if (null) throw exception */
1445 jmp builtin_monitorenter /* else call builtin_monitorenter */
1448 call new_nullpointerexception
1449 pop %r10 /* delete return address */
1450 sub $3,%r10 /* faulting address is ra - 3 */
1451 jmp asm_handle_exception
1455 /********************* function asm_builtin_monitorexit ************************
1457 * Does null check and calls monitorexit or throws an exception *
1459 *******************************************************************************/
1461 #if defined(USE_THREADS)
1462 asm_builtin_monitorexit:
1464 je nb_monitorexit /* if (null) throw exception */
1465 jmp builtin_monitorexit /* else call builtin_monitorenter */
1468 call new_nullpointerexception
1469 pop %r10 /* delete return address */
1470 sub $3,%r10 /* faulting address is ra - 3 */
1471 jmp asm_handle_exception
1475 /********************* function asm_builtin_x2x ********************************
1477 * Wrapper functions for float to int corner cases *
1479 *******************************************************************************/
1484 SAVE_ARGUMENT_REGISTERS
1489 RESTORE_ARGUMENT_REGISTERS
1498 SAVE_ARGUMENT_REGISTERS
1503 RESTORE_ARGUMENT_REGISTERS
1512 SAVE_ARGUMENT_REGISTERS
1517 RESTORE_ARGUMENT_REGISTERS
1526 SAVE_ARGUMENT_REGISTERS
1531 RESTORE_ARGUMENT_REGISTERS
1537 /* asm_builtin_checkarraycast **************************************************
1539 Does the cast check and eventually throws an exception.
1541 *******************************************************************************/
1543 asm_builtin_checkarraycast:
1544 sub $24,%rsp /* keep stack 16-byte aligned */
1545 mov %rdi,(%rsp) /* save object pointer */
1546 call builtin_checkarraycast /* builtin_checkarraycast */
1547 test %rax,%rax /* if (false) throw exception */
1549 mov (%rsp),%rax /* return object pointer */
1550 add $24,%rsp /* free stack space */
1554 call new_classcastexception
1556 pop %r10 /* delete return address */
1557 sub $3,%r10 /* faulting address is ra - 3 */
1558 jmp asm_handle_exception
1561 /* asm_builtin_aastore *********************************************************
1563 Checks if the object can be stored in the given array and stores the
1564 address if it's possible. This function can also throw some exceptions.
1566 *******************************************************************************/
1568 asm_builtin_aastore:
1569 sub $(3*8),%rsp /* allocate stack space */
1570 test %rdi,%rdi /* if null pointer throw exception */
1573 movl offarraysize(%rdi),%eax /* load size */
1574 cmpl %eax,%esi /* do bound check */
1575 jae nb_aastore_bound /* if out of bounds throw exception */
1577 shl $3,%rsi /* index * 8 */
1579 add %rsi,%r10 /* add index * 8 to arrayref */
1581 mov %r10,(%rsp) /* save store position */
1582 mov %rdx,8(%rsp) /* save object */
1584 mov %rdx,%rsi /* object is second argument */
1585 call builtin_canstore /* builtin_canstore(arrayref,object) */
1586 test %rax,%rax /* if (false) throw exception */
1589 mov (%rsp),%r10 /* restore store position */
1590 mov 8(%rsp),%rdx /* restore object */
1591 mov %rdx,offobjarrdata(%r10)/* store objectptr in array */
1592 add $(3*8),%rsp /* free stack space */
1596 call new_nullpointerexception
1598 pop %r10 /* delete return address */
1599 sub $3,%r10 /* faulting address is return adress - 3 */
1600 jmp asm_handle_exception
1603 mov %rsi,%rdi /* move index into a0 */
1604 call new_arrayindexoutofboundsexception
1606 pop %r10 /* delete return address */
1607 sub $3,%r10 /* faulting address is return adress - 3 */
1608 jmp asm_handle_exception
1611 call new_arraystoreexception
1613 pop %r10 /* delete return address */
1614 sub $3,%r10 /* faulting address is return adress - 3 */
1615 jmp asm_handle_exception
1618 /******************* function asm_initialize_thread_stack **********************
1620 * initialized a thread stack *
1621 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
1623 *******************************************************************************/
1625 asm_initialize_thread_stack:
1636 mov %rdi,6*8(%rsi) /* save (u1*) (func) */
1637 mov %rsi,%rax /* return restorepoint in %rax */
1641 /******************* function asm_perform_threadswitch *************************
1643 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
1645 * performs a threadswitch *
1647 *******************************************************************************/
1649 asm_perform_threadswitch:
1650 sub $(7*8),%rsp /* allocate stack frame */
1659 mov 7*8(%rsp),%rax /* save current return address */
1662 mov %rsp,(%rdi) /* first argument **from */
1663 mov %rsp,(%rdx) /* third argument **stackTop */
1665 mov (%rsi),%rsp /* load new stack pointer */
1674 mov 6*8(%rsp),%rax /* restore return address */
1675 add $(7*8),%rsp /* free stack frame */
1680 /********************* function asm_switchstackandcall *************************
1682 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
1685 * Switches to a new stack, calls a function and switches back. *
1686 * a0 (%rdi) new stack pointer *
1687 * a1 (%rsi) function pointer *
1688 * a2 (%rdx) pointer to variable where stack top should be stored *
1689 * a3 (%rcx) pointer to user data, is passed to the function *
1691 *******************************************************************************/
1693 asm_switchstackandcall:
1694 sub $(1*8),%rsp /* keep stack 16-byte aligned */
1695 sub $16,%rdi /* allocate new stack */
1697 mov 8(%rsp),%rax /* save return address on new stack */
1699 mov %rsp,8(%rdi) /* save old stack pointer on new stack*/
1700 mov %rsp,(%rdx) /* save old stack pointer to variable */
1702 mov %rdi,%rsp /* switch to new stack */
1704 mov %rcx,%rdi /* pass pointer */
1705 call *%rsi /* and call function */
1707 mov (%rsp),%r10 /* load return address */
1708 mov 8(%rsp),%rsp /* switch to old stack */
1709 add $(1*8),%rsp /* free stack space */
1710 mov %r10,(%rsp) /* write return adress */
1714 asm_getclassvalues_atomic:
1717 movl offbaseval(a0),itmp1l
1718 movl offdiffval(a0),itmp2l
1719 movl offbaseval(a1),itmp3l
1721 movl itmp1l,offcast_super_baseval(a2)
1722 movl itmp2l,offcast_super_diffval(a2)
1723 movl itmp3l,offcast_sub_baseval(a2)
1728 asm_criticalsections:
1729 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1732 .quad _crit_restart1
1735 .quad _crit_restart2
1741 * These are local overrides for various environment variables in Emacs.
1742 * Please do not remove this and leave it at the end of the file, where
1743 * Emacs will automagically detect them.
1744 * ---------------------------------------------------------------------
1747 * indent-tabs-mode: t