1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
31 Changes: Joseph Wenninger
34 $Id: asmpart.S 6265 2007-01-02 20:40:57Z edwin $
43 #include "vm/jit/i386/arch.h"
44 #include "vm/jit/i386/md-abi.h"
45 #include "vm/jit/i386/offsets.h"
47 #include "vm/jit/abi-asm.h"
48 #include "vm/jit/methodheader.h"
54 /* export functions ***********************************************************/
58 .globl asm_vm_call_method
59 .globl asm_vm_call_method_int
60 .globl asm_vm_call_method_long
61 .globl asm_vm_call_method_float
62 .globl asm_vm_call_method_double
63 .globl asm_vm_call_method_exception_handler
65 .globl asm_call_jit_compiler
66 .globl asm_handle_nat_exception
67 .globl asm_handle_exception
69 .globl asm_abstractmethoderror
71 .globl asm_patcher_wrapper
73 #if defined(ENABLE_REPLACEMENT)
74 .globl asm_replacement_out
75 .globl asm_replacement_in
78 .globl asm_builtin_f2i
79 .globl asm_builtin_f2l
80 .globl asm_builtin_d2i
81 .globl asm_builtin_d2l
83 .globl asm_criticalsections
84 .globl asm_getclassvalues_atomic
86 .globl asm_get_cycle_count
89 /* asm_md_init *****************************************************************
91 Initialize machine dependent stuff.
93 See: http://www.srware.com/linux_numerics.txt
95 This puts the X86 FPU in 64-bit precision mode. The default under
96 Linux is to use 80-bit mode, which produces subtle differences from
97 FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
98 64-bit mode, 299 in 80-bit mode.
100 Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
102 *******************************************************************************/
105 sub $4,sp /* allocate space for the FPU state */
106 fnstcw (sp) /* get the FPU state */
108 and $0xfcff,%ax /* remove the extended mode flag */
109 or $0x0200,%ax /* put the double mode flag */
110 mov %eax,(sp) /* store new FPU state */
111 fldcw (sp) /* setup new FPU state */
116 /********************* function asm_calljavafunction ***************************
118 * This function calls a Java-method (which possibly needs compilation) *
119 * with up to 4 address parameters. *
121 * This functions calls the JIT-compiler which eventually translates the *
122 * method into machine code. *
125 * javaobject_header *asm_vm_call_method(methodinfo *m, *
126 * u4 count, u4 size, void *callblock); *
128 *******************************************************************************/
132 .long 0 /* catch type all */
133 .long 0 /* handler pc */
135 .long 0 /* start pc */
136 .long 1 /* extable size */
137 .long 0 /* line number table start */
138 .long 0 /* line number table size */
139 .long 0 /* fltsave */
140 .long 0 /* intsave */
143 .long 0 /* frame size */
144 .long 0 /* codeinfo pointer */
147 asm_vm_call_method_int:
148 asm_vm_call_method_long:
149 asm_vm_call_method_float:
150 asm_vm_call_method_double:
152 mov sp,bp /* save stackptr */
153 sub $(4*4),sp /* create stackframe */
154 and $0xfffffff0,sp /* align stack to 16-byte */
156 mov t0,0*4(sp) /* save registers */
160 mov 4*4(bp),itmp1 /* pointer to arg block (4(push)+4(return)+4+4)*/
161 mov 3*4(bp),itmp2 /* arg count (4(push)+4(return)+4 */
163 mov sp,s1 /* save the stackpointer */
165 test itmp2,itmp2 /* maybe we have no args */
166 jle L_asm_vm_call_method_copy_done
168 mov itmp2,itmp3 /* calculate stack size */
169 mov itmp1,%edi /* save pointer to arg block */
171 calljava_calcstacksize:
172 mov offvmargtype(itmp1),t0
173 test $1,t0 /* two word type? */
174 jz calljava_onewordtype
176 sub $4,sp /* add 1 slot to stackframe size */
178 calljava_onewordtype:
179 sub $4,sp /* add 1 slot to stackframe size */
181 test itmp3,itmp3 /* any args left? */
184 add $sizevmarg,itmp1 /* goto next argument block */
185 jmp calljava_calcstacksize
188 mov %edi,itmp1 /* restore pointer to arg block */
189 and $0xfffffff0,sp /* align stack to 16-byte */
190 mov sp,itmp3 /* initialize pointer for copying */
193 mov offvmargdata(itmp1),t0 /* get 4-bytes of argument */
194 mov t0,(itmp3) /* and store them on the stack */
195 add $4,itmp3 /* increase sp to next argument */
197 mov offvmargtype(itmp1),t0 /* get the argument type */
198 test $1,t0 /* two word type? */
201 mov offvmargdata+4(itmp1),t0 /* get upper 4-bytes of 2 word type */
203 add $4,itmp3 /* increase sp to next argument */
206 sub $1,itmp2 /* are there any args left? */
208 jle L_asm_vm_call_method_copy_done
210 add $sizevmarg,itmp1 /* goto next argument block */
211 jmp calljava_copyloop
213 L_asm_vm_call_method_copy_done:
214 mov 2*4(bp),itmp1 /* move function pointer to itmp1 */
216 lea L_asm_call_jit_compiler,mptr
218 lea (3*4-256)(s1),mptr /* We subtract 256 to force the next */
219 /* move instruction to have a 32-bit */
222 mov (0*4+256)(mptr),itmp3 /* method call as in Java */
223 call *itmp3 /* call JIT compiler */
225 L_asm_vm_call_method_return:
226 mov s1,sp /* restore stackpointer */
228 mov 0*4(sp),t0 /* restore registers */
235 asm_vm_call_method_exception_handler:
236 push xptr /* pass exception pointer */
237 call builtin_throw_exception
239 jmp L_asm_vm_call_method_return
242 /* asm_call_jit_compiler *******************************************************
244 Invokes the compiler for untranslated JavaVM methods.
246 Register R0 contains a pointer to the method info structure (prepared
247 by createcompilerstub). Using the return address in R26 and the
248 offset in the LDA instruction or using the value in methodptr R28 the
249 patching address for storing the method address can be computed:
251 Method address was either loaded using
253 i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special
254 i386_call_reg(REG_ITMP2)
258 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface
259 i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
260 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
261 sizeof(methodptr) * m->vftblindex, REG_ITMP1)
262 i386_call_reg(REG_ITMP1)
264 In the static case the method pointer can be computed using the
265 return address and the lda function following the jmp instruction.
267 *******************************************************************************/
269 asm_call_jit_compiler:
270 L_asm_call_jit_compiler: /* required for PIC code */
271 sub $(4*4),sp /* keep stack 16-byte aligned */
273 mov itmp1,0*4(sp) /* pass methodinfo pointer */
274 mov mptr,1*4(sp) /* pass method pointer */
275 mov sp,itmp2 /* pass java sp */
278 mov 4*4(sp),itmp3 /* pass java ra */
282 add $(4*4),sp /* remove stack frame */
284 test v0,v0 /* check for exception */
285 je L_asm_call_jit_compiler_exception
287 jmp *v0 /* ...and now call the new method */
289 L_asm_call_jit_compiler_exception:
290 call exceptions_get_and_clear_exception
292 pop xpc /* get return address */
293 sub $2,xpc /* faulting address is ra - 2 */
294 jmp L_asm_handle_exception
297 /* asm_handle_exception ********************************************************
299 * This function handles an exception. It does not use the usual calling *
300 * conventions. The exception pointer is passed in REG_ITMP1 and the *
301 * pc from the exception raising position is passed in REG_ITMP2. It searches *
302 * the local exception table for a handler. If no one is found, it unwinds *
303 * stacks and continues searching the callers. *
305 *******************************************************************************/
307 asm_handle_nat_exception:
308 add $4,sp /* clear return address of native stub*/
310 asm_handle_exception:
311 L_asm_handle_exception: /* required for PIC code */
312 sub $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned */
314 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
315 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
317 mov $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
318 mov $1,t0 /* set maybe-leaf flag */
320 L_asm_handle_exception_stack_loop:
321 sub $(12*4),sp /* keep stack 16-byte aligned */
322 mov xptr,4*4(sp) /* save exception pointer */
323 mov xpc,5*4(sp) /* save exception pc */
324 add sp,itmp3 /* calculate Java sp into a3... */
326 mov itmp3,7*4(sp) /* ...and save it */
327 mov t0,8*4(sp) /* save maybe-leaf flag */
329 mov xpc,0*4(sp) /* pass exception pc */
330 call codegen_get_pv_from_pc
331 mov v0,6*4(sp) /* save data segment pointer */
333 mov 4*4(sp),itmp3 /* pass exception pointer */
335 mov 5*4(sp),itmp3 /* pass exception pc */
337 mov v0,2*4(sp) /* pass data segment pointer */
338 mov 7*4(sp),itmp3 /* pass Java stack pointer */
340 call exceptions_handle_exception
343 jz L_asm_handle_exception_not_catched
345 mov v0,xpc /* move handlerpc into xpc */
346 mov 4*4(sp),xptr /* restore exception pointer */
347 mov 8*4(sp),t0 /* get maybe-leaf flag */
348 add $(12*4),sp /* free stackframe */
350 test t0,t0 /* test for maybe-leaf flag */
351 jz L_asm_handle_exception_no_leaf
353 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
354 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
356 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
358 L_asm_handle_exception_no_leaf:
359 jmp *xpc /* jump to exception handler */
361 L_asm_handle_exception_not_catched:
362 mov 4*4(sp),xptr /* restore exception pointer */
363 mov 6*4(sp),itmp3 /* restore data segment pointer */
364 mov 8*4(sp),t0 /* get maybe-leaf flag */
365 add $(12*4),sp /* free stackframe */
368 jz L_asm_handle_exception_no_leaf_stack
370 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
371 xor t0,t0 /* clear the maybe-leaf flag */
373 L_asm_handle_exception_no_leaf_stack:
374 mov FrameSize(itmp3),itmp2 /* get frame size */
375 add sp,itmp2 /* pointer to save area */
377 push xptr /* we are out of registers */
379 mov IntSave(itmp3),itmp1 /* itmp1 = saved int register count */
394 shl $2,itmp1 /* multiply by 4 bytes */
399 mov FltSave(itmp3),itmp1 /* itmp1 = saved flt register count */
424 pop xptr /* restore exception pointer */
425 mov FrameSize(itmp3),itmp2 /* get frame size */
426 add itmp2,sp /* unwind stack */
428 pop xpc /* the new xpc is return address */
429 sub $2,xpc /* subtract 2-bytes for call */
431 xor itmp3,itmp3 /* prepare a3 for handle_exception */
433 jmp L_asm_handle_exception_stack_loop
436 /* asm_abstractmethoderror *****************************************************
438 Creates and throws an AbstractMethodError.
440 *******************************************************************************/
442 asm_abstractmethoderror:
443 sub $(3*4),sp /* keep stack 16-byte aligned */
444 mov sp,itmp1 /* pass java sp */
447 mov 3*4(sp),itmp2 /* pass exception address */
450 call exceptions_asm_new_abstractmethoderror
451 /* exception pointer is return value */
452 add $(3*4),sp /* remove stack frame */
454 pop xpc /* get exception address */
455 sub $2,xpc /* exception address is ra - 2 */
456 jmp L_asm_handle_exception
459 /* asm_patcher_wrapper *********************************************************
466 16 pointer to virtual java_objectheader
467 12 last byte of machine code (xmcode)
468 8 machine code (which is patched back later)
469 4 unresolved field reference
470 0 patcher function pointer to call
472 *******************************************************************************/
475 sub $((1+4+4)*4),sp /* keep stack 16-byte aligned */
477 mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
478 mov itmp2,(1+4)*4(sp)
480 mov sp,itmp1 /* pass SP of patcher stub */
481 add $((1+4+4)*4),itmp1
483 movl $0,1*4(sp) /* pass PV (if NULL, use findmethod) */
484 movl $0,2*4(sp) /* pass RA (it's on the stack) */
486 mov v0,itmp3 /* save return value */
488 mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
489 mov (1+4)*4(sp),itmp2
491 test itmp3,itmp3 /* exception thrown? */
492 jne L_asm_patcher_wrapper_exception
494 mov (5+1+4+4)*4(sp),itmp3 /* restore itmp3 */
495 add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
497 ret /* jump to new patched code */
499 L_asm_patcher_wrapper_exception:
500 add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
501 mov itmp3,xptr /* get exception */
502 pop xpc /* get and remove return address */
503 jmp L_asm_handle_exception
505 #if defined(ENABLE_REPLACEMENT)
507 /* asm_replacement_out *********************************************************
509 This code is jumped to from the replacement-out stubs that are executed
510 when a thread reaches an activated replacement point.
512 The purpose of asm_replacement_out is to read out the parts of the
513 execution state that cannot be accessed from C code, store this state,
514 and then call the C function replace_me.
517 4 start of stack inside method to replace
518 0 rplpoint * info on the replacement point that was reached
520 *******************************************************************************/
522 /* some room to accomodate changes of the stack frame size during replacement */
523 /* XXX we should find a cleaner solution here */
524 #define REPLACEMENT_ROOM 512
527 /* create stack frame */
528 sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
530 /* save registers in execution state */
531 mov %eax,(EAX*4+offes_intregs)(sp)
532 mov %ebx,(EBX*4+offes_intregs)(sp)
533 mov %ecx,(ECX*4+offes_intregs)(sp)
534 mov %edx,(EDX*4+offes_intregs)(sp)
535 mov %esi,(ESI*4+offes_intregs)(sp)
536 mov %edi,(EDI*4+offes_intregs)(sp)
537 mov %ebp,(EBP*4+offes_intregs)(sp)
538 movl $0 ,(ESP*4+offes_intregs)(sp) /* not used */
540 /* calculate sp of method */
542 add $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
543 mov itmp1,(offes_sp)(sp)
545 /* pv must be looked up via AVL tree */
546 movl $0,(offes_pv)(sp)
548 /* call replace_me */
549 mov -4(itmp1),itmp1 /* rplpoint * */
550 push sp /* arg1: execution state */
551 push itmp1 /* arg0: replacement point */
552 call replace_me /* call C function replace_me */
555 /* asm_replacement_in **********************************************************
557 This code writes the given execution state and jumps to the replacement
560 This function never returns!
563 void asm_replacement_in(executionstate *es, replace_safestack_t *st);
565 *******************************************************************************/
569 mov 8(sp),%esi /* replace_safestack_t *st */
570 mov 4(sp),%ebp /* executionstate *es == safe stack */
572 /* switch to the safe stack and build a stack frame */
576 /* call replace_build_execution_state(st) */
578 call replace_build_execution_state
581 mov (offes_sp)(%ebp),sp
583 /* push address of new code */
584 push (offes_pc)(%ebp)
586 /* allocate an executionstate_t on the stack */
587 sub $(sizeexecutionstate),sp
589 /* call replace_free_safestack(st,& of allocated executionstate_t) */
592 call replace_free_safestack
595 /* copy registers from execution state */
596 mov (EAX*4+offes_intregs)(sp),%eax
597 mov (EBX*4+offes_intregs)(sp),%ebx
598 mov (ECX*4+offes_intregs)(sp),%ecx
599 mov (EDX*4+offes_intregs)(sp),%edx
600 mov (ESI*4+offes_intregs)(sp),%esi
601 mov (EDI*4+offes_intregs)(sp),%edi
602 mov (EBP*4+offes_intregs)(sp),%ebp
604 /* pop the execution state off the stack */
605 add $(sizeexecutionstate),sp
607 /* jump to new code, hold your thumbs! ;) */
610 #endif /* defined(ENABLE_REPLACEMENT) */
613 /************************ function asm_builtin_x2x *****************************
615 * Wrapper functions for corner cases *
617 *******************************************************************************/
648 asm_getclassvalues_atomic:
650 mov 4(%esp),%ecx /* super */
651 mov 8(%esp),%edx /* sub */
653 mov offbaseval(%ecx),%eax
654 mov offdiffval(%ecx),%ecx
655 mov offbaseval(%edx),%edx
658 mov 16(%esp),%ebx /* out */
659 mov %eax,offcast_super_baseval(%ebx)
660 mov %ecx,offcast_super_diffval(%ebx)
661 mov %edx,offcast_sub_baseval(%ebx)
667 asm_criticalsections:
668 #if defined(ENABLE_THREADS)
681 /* Disable exec-stacks, required for Gentoo ***********************************/
683 #if defined(__GCC__) && defined(__ELF__)
684 .section .note.GNU-stack,"",@progbits
688 /* asm_get_cycle_count *********************************************************
690 Get the current time-stamp counter from the CPU.
692 *******************************************************************************/
700 * These are local overrides for various environment variables in Emacs.
701 * Please do not remove this and leave it at the end of the file, where
702 * Emacs will automagically detect them.
703 * ---------------------------------------------------------------------
706 * indent-tabs-mode: t
710 * vim:noexpandtab:sw=4:ts=4: