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 5255 2006-08-21 15:17:48Z twisti $
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 .globl asm_replacement_out
74 .globl asm_replacement_in
76 .globl asm_builtin_f2i
77 .globl asm_builtin_f2l
78 .globl asm_builtin_d2i
79 .globl asm_builtin_d2l
81 .globl asm_criticalsections
82 .globl asm_getclassvalues_atomic
84 .globl asm_get_cycle_count
87 /* asm_md_init *****************************************************************
89 Initialize machine dependent stuff.
91 See: http://www.srware.com/linux_numerics.txt
93 This puts the X86 FPU in 64-bit precision mode. The default under
94 Linux is to use 80-bit mode, which produces subtle differences from
95 FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
96 64-bit mode, 299 in 80-bit mode.
98 Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
100 *******************************************************************************/
103 sub $4,sp /* allocate space for the FPU state */
104 fnstcw (sp) /* get the FPU state */
106 and $0xfcff,%ax /* remove the extended mode flag */
107 or $0x0200,%ax /* put the double mode flag */
108 mov %eax,(sp) /* store new FPU state */
109 fldcw (sp) /* setup new FPU state */
114 /********************* function asm_calljavafunction ***************************
116 * This function calls a Java-method (which possibly needs compilation) *
117 * with up to 4 address parameters. *
119 * This functions calls the JIT-compiler which eventually translates the *
120 * method into machine code. *
123 * javaobject_header *asm_vm_call_method(methodinfo *m, *
124 * u4 count, u4 size, void *callblock); *
126 *******************************************************************************/
130 .long 0 /* catch type all */
131 .long 0 /* handler pc */
133 .long 0 /* start pc */
134 .long 1 /* extable size */
135 .long 0 /* line number table start */
136 .long 0 /* line number table size */
137 .long 0 /* fltsave */
138 .long 0 /* intsave */
141 .long 0 /* frame size */
142 .long 0 /* codeinfo pointer */
145 asm_vm_call_method_int:
146 asm_vm_call_method_long:
147 asm_vm_call_method_float:
148 asm_vm_call_method_double:
150 mov sp,bp /* save stackptr */
151 sub $(4*4),sp /* create stackframe */
152 and $0xfffffff0,sp /* align stack to 16-byte */
154 mov t0,0*4(sp) /* save registers */
158 mov 4*4(bp),itmp1 /* pointer to arg block (4(push)+4(return)+4+4)*/
159 mov 3*4(bp),itmp2 /* arg count (4(push)+4(return)+4 */
161 mov sp,s1 /* save the stackpointer */
163 test itmp2,itmp2 /* maybe we have no args */
164 jle L_asm_vm_call_method_copy_done
166 mov itmp2,itmp3 /* calculate stack size */
167 mov itmp1,%edi /* save pointer to arg block */
169 calljava_calcstacksize:
170 mov offvmargtype(itmp1),t0
171 test $1,t0 /* two word type? */
172 jz calljava_onewordtype
174 sub $4,sp /* add 1 slot to stackframe size */
176 calljava_onewordtype:
177 sub $4,sp /* add 1 slot to stackframe size */
179 test itmp3,itmp3 /* any args left? */
182 add $sizevmarg,itmp1 /* goto next argument block */
183 jmp calljava_calcstacksize
186 mov %edi,itmp1 /* restore pointer to arg block */
187 and $0xfffffff0,sp /* align stack to 16-byte */
188 mov sp,itmp3 /* initialize pointer for copying */
191 mov offvmargdata(itmp1),t0 /* get 4-bytes of argument */
192 mov t0,(itmp3) /* and store them on the stack */
193 add $4,itmp3 /* increase sp to next argument */
195 mov offvmargtype(itmp1),t0 /* get the argument type */
196 test $1,t0 /* two word type? */
199 mov offvmargdata+4(itmp1),t0 /* get upper 4-bytes of 2 word type */
201 add $4,itmp3 /* increase sp to next argument */
204 sub $1,itmp2 /* are there any args left? */
206 jle L_asm_vm_call_method_copy_done
208 add $sizevmarg,itmp1 /* goto next argument block */
209 jmp calljava_copyloop
211 L_asm_vm_call_method_copy_done:
212 mov 2*4(bp),itmp1 /* move function pointer to itmp1 */
214 lea L_asm_call_jit_compiler,mptr
216 lea (3*4-256)(s1),mptr /* We subtract 256 to force the next */
217 /* move instruction to have a 32-bit */
220 mov (0*4+256)(mptr),itmp3 /* method call as in Java */
221 call *itmp3 /* call JIT compiler */
223 L_asm_vm_call_method_return:
224 mov s1,sp /* restore stackpointer */
226 mov 0*4(sp),t0 /* restore registers */
233 asm_vm_call_method_exception_handler:
234 push xptr /* pass exception pointer */
235 call builtin_throw_exception
237 jmp L_asm_vm_call_method_return
240 /* asm_call_jit_compiler *******************************************************
242 Invokes the compiler for untranslated JavaVM methods.
244 Register R0 contains a pointer to the method info structure (prepared
245 by createcompilerstub). Using the return address in R26 and the
246 offset in the LDA instruction or using the value in methodptr R28 the
247 patching address for storing the method address can be computed:
249 Method address was either loaded using
251 i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special
252 i386_call_reg(REG_ITMP2)
256 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface
257 i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
258 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
259 sizeof(methodptr) * m->vftblindex, REG_ITMP1)
260 i386_call_reg(REG_ITMP1)
262 In the static case the method pointer can be computed using the
263 return address and the lda function following the jmp instruction.
265 *******************************************************************************/
267 asm_call_jit_compiler:
268 L_asm_call_jit_compiler: /* required for PIC code */
269 sub $(4*4),sp /* keep stack 16-byte aligned */
271 mov itmp1,0*4(sp) /* pass methodinfo pointer */
272 mov mptr,1*4(sp) /* pass method pointer */
273 mov sp,itmp2 /* pass java sp */
276 mov 4*4(sp),itmp3 /* pass java ra */
280 add $(4*4),sp /* remove stack frame */
282 test v0,v0 /* check for exception */
283 je L_asm_call_jit_compiler_exception
285 jmp *v0 /* ...and now call the new method */
287 L_asm_call_jit_compiler_exception:
288 call exceptions_get_and_clear_exception
290 pop xpc /* get return address */
291 sub $2,xpc /* faulting address is ra - 2 */
292 jmp L_asm_handle_exception
295 /* asm_handle_exception ********************************************************
297 * This function handles an exception. It does not use the usual calling *
298 * conventions. The exception pointer is passed in REG_ITMP1 and the *
299 * pc from the exception raising position is passed in REG_ITMP2. It searches *
300 * the local exception table for a handler. If no one is found, it unwinds *
301 * stacks and continues searching the callers. *
303 *******************************************************************************/
305 asm_handle_nat_exception:
306 add $4,sp /* clear return address of native stub*/
308 asm_handle_exception:
309 L_asm_handle_exception: /* required for PIC code */
310 sub $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned */
312 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
313 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
315 mov $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
316 mov $1,t0 /* set maybe-leaf flag */
318 L_asm_handle_exception_stack_loop:
319 sub $(12*4),sp /* keep stack 16-byte aligned */
320 mov xptr,4*4(sp) /* save exception pointer */
321 mov xpc,5*4(sp) /* save exception pc */
322 add sp,itmp3 /* calculate Java sp into a3... */
324 mov itmp3,7*4(sp) /* ...and save it */
325 mov t0,8*4(sp) /* save maybe-leaf flag */
327 mov xpc,0*4(sp) /* pass exception pc */
328 call codegen_get_pv_from_pc
329 mov v0,6*4(sp) /* save data segment pointer */
331 mov 4*4(sp),itmp3 /* pass exception pointer */
333 mov 5*4(sp),itmp3 /* pass exception pc */
335 mov v0,2*4(sp) /* pass data segment pointer */
336 mov 7*4(sp),itmp3 /* pass Java stack pointer */
338 call exceptions_handle_exception
341 jz L_asm_handle_exception_not_catched
343 mov v0,xpc /* move handlerpc into xpc */
344 mov 4*4(sp),xptr /* restore exception pointer */
345 mov 8*4(sp),t0 /* get maybe-leaf flag */
346 add $(12*4),sp /* free stackframe */
348 test t0,t0 /* test for maybe-leaf flag */
349 jz L_asm_handle_exception_no_leaf
351 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
352 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
354 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
356 L_asm_handle_exception_no_leaf:
357 jmp *xpc /* jump to exception handler */
359 L_asm_handle_exception_not_catched:
360 mov 4*4(sp),xptr /* restore exception pointer */
361 mov 6*4(sp),itmp3 /* restore data segment pointer */
362 mov 8*4(sp),t0 /* get maybe-leaf flag */
363 add $(12*4),sp /* free stackframe */
366 jz L_asm_handle_exception_no_leaf_stack
368 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
369 xor t0,t0 /* clear the maybe-leaf flag */
371 L_asm_handle_exception_no_leaf_stack:
372 mov FrameSize(itmp3),itmp2 /* get frame size */
373 add sp,itmp2 /* pointer to save area */
375 push xptr /* we are out of registers */
377 mov IntSave(itmp3),itmp1 /* itmp1 = saved int register count */
392 shl $2,itmp1 /* multiply by 4 bytes */
397 mov FltSave(itmp3),itmp1 /* itmp1 = saved flt register count */
422 pop xptr /* restore exception pointer */
423 mov FrameSize(itmp3),itmp2 /* get frame size */
424 add itmp2,sp /* unwind stack */
426 pop xpc /* the new xpc is return address */
427 sub $2,xpc /* subtract 2-bytes for call */
429 xor itmp3,itmp3 /* prepare a3 for handle_exception */
431 jmp L_asm_handle_exception_stack_loop
434 /* asm_abstractmethoderror *****************************************************
436 Creates and throws an AbstractMethodError.
438 *******************************************************************************/
440 asm_abstractmethoderror:
441 sub $(3*4),sp /* keep stack 16-byte aligned */
442 mov sp,itmp1 /* pass java sp */
445 mov 3*4(sp),itmp2 /* pass exception address */
448 call exceptions_asm_new_abstractmethoderror
449 /* exception pointer is return value */
450 add $(3*4),sp /* remove stack frame */
452 pop xpc /* get exception address */
453 sub $2,xpc /* exception address is ra - 2 */
454 jmp L_asm_handle_exception
457 /* asm_patcher_wrapper *********************************************************
464 16 pointer to virtual java_objectheader
465 12 last byte of machine code (xmcode)
466 8 machine code (which is patched back later)
467 4 unresolved field reference
468 0 patcher function pointer to call
470 *******************************************************************************/
473 sub $((1+4+4)*4),sp /* keep stack 16-byte aligned */
475 mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
476 mov itmp2,(1+4)*4(sp)
478 mov sp,itmp1 /* pass SP of patcher stub */
479 add $((1+4+4)*4),itmp1
481 movl $0,1*4(sp) /* pass PV (if NULL, use findmethod) */
482 movl $0,2*4(sp) /* pass RA (it's on the stack) */
484 mov v0,itmp3 /* save return value */
486 mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
487 mov (1+4)*4(sp),itmp2
489 test itmp3,itmp3 /* exception thrown? */
490 jne L_asm_patcher_wrapper_exception
492 mov (5+1+4+4)*4(sp),itmp3 /* restore itmp3 */
493 add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
495 ret /* jump to new patched code */
497 L_asm_patcher_wrapper_exception:
498 add $((6+2+4)*4),sp /* remove stack frame, keep RA */
499 add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
500 mov itmp3,xptr /* get exception */
501 pop xpc /* get and remove return address */
502 jmp L_asm_handle_exception
505 /* asm_replacement_out *********************************************************
507 This code is jumped to from the replacement-out stubs that are executed
508 when a thread reaches an activated replacement point.
510 The purpose of asm_replacement_out is to read out the parts of the
511 execution state that cannot be accessed from C code, store this state,
512 and then call the C function replace_me.
515 4 start of stack inside method to replace
516 0 rplpoint * info on the replacement point that was reached
518 *******************************************************************************/
520 /* some room to accomodate changes of the stack frame size during replacement */
521 /* XXX we should find a cleaner solution here */
522 #define REPLACEMENT_ROOM 512
525 /* create stack frame */
526 sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
528 /* save registers in execution state */
529 mov %eax,(EAX*8+offes_intregs)(sp)
530 mov %ebx,(EBX*8+offes_intregs)(sp)
531 mov %ecx,(ECX*8+offes_intregs)(sp)
532 mov %edx,(EDX*8+offes_intregs)(sp)
533 mov %esi,(ESI*8+offes_intregs)(sp)
534 mov %edi,(EDI*8+offes_intregs)(sp)
535 mov %ebp,(EBP*8+offes_intregs)(sp)
536 movl $0 ,(ESP*8+offes_intregs)(sp) /* not used */
539 /* clear high 32bit */
540 movl $0,(4+0*8+offes_intregs)(sp)
541 movl $0,(4+1*8+offes_intregs)(sp)
542 movl $0,(4+2*8+offes_intregs)(sp)
543 movl $0,(4+3*8+offes_intregs)(sp)
544 movl $0,(4+4*8+offes_intregs)(sp)
545 movl $0,(4+5*8+offes_intregs)(sp)
546 movl $0,(4+6*8+offes_intregs)(sp)
547 movl $0,(4+7*8+offes_intregs)(sp)
550 /* calculate sp of method */
552 add $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
553 mov itmp1,(offes_sp)(sp)
555 /* pv must be looked up via AVL tree */
556 movl $0,(offes_pv)(sp)
558 /* call replace_me */
559 mov -4(itmp1),itmp1 /* rplpoint * */
560 push sp /* arg1: execution state */
561 push itmp1 /* arg0: replacement point */
562 call replace_me /* call C function replace_me */
565 /* asm_replacement_in **********************************************************
567 This code writes the given execution state and jumps to the replacement
570 This function never returns!
573 void asm_replacement_in(executionstate *es);
575 *******************************************************************************/
578 mov 4(sp),%ebp /* executionstate *es */
581 mov (offes_sp)(%ebp),%esp
583 /* store address of new code */
584 push (offes_pc)(%ebp)
586 /* copy registers from execution state */
587 mov (EAX*8+offes_intregs)(%ebp),%eax
588 mov (EBX*8+offes_intregs)(%ebp),%ebx
589 mov (ECX*8+offes_intregs)(%ebp),%ecx
590 mov (EDX*8+offes_intregs)(%ebp),%edx
591 mov (ESI*8+offes_intregs)(%ebp),%esi
592 mov (EDI*8+offes_intregs)(%ebp),%edi
594 mov (EBP*8+offes_intregs)(%ebp),%ebp
596 /* jump to new code */
600 /************************ function asm_builtin_x2x *****************************
602 * Wrapper functions for corner cases *
604 *******************************************************************************/
635 asm_getclassvalues_atomic:
637 mov 4(%esp),%ecx /* super */
638 mov 8(%esp),%edx /* sub */
640 mov offbaseval(%ecx),%eax
641 mov offdiffval(%ecx),%ecx
642 mov offbaseval(%edx),%edx
645 mov 16(%esp),%ebx /* out */
646 mov %eax,offcast_super_baseval(%ebx)
647 mov %ecx,offcast_super_diffval(%ebx)
648 mov %edx,offcast_sub_baseval(%ebx)
654 asm_criticalsections:
655 #if defined(ENABLE_THREADS)
668 /* Disable exec-stacks, required for Gentoo ***********************************/
670 #if defined(__GCC__) && defined(__ELF__)
671 .section .note.GNU-stack,"",@progbits
675 /* asm_get_cycle_count *********************************************************
677 Get the current time-stamp counter from the CPU.
679 *******************************************************************************/
687 * These are local overrides for various environment variables in Emacs.
688 * Please do not remove this and leave it at the end of the file, where
689 * Emacs will automagically detect them.
690 * ---------------------------------------------------------------------
693 * indent-tabs-mode: t
697 * vim:noexpandtab:sw=4:ts=4: