1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
3 Copyright (C) 1996-2005, 2006, 2007 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
32 #include "vm/jit/i386/arch.h"
33 #include "vm/jit/i386/md-abi.h"
35 #include "vm/jit/abi-asm.h"
36 #include "vm/jit/methodheader.h"
42 /* export functions ***********************************************************/
46 .globl asm_vm_call_method
47 .globl asm_vm_call_method_int
48 .globl asm_vm_call_method_long
49 .globl asm_vm_call_method_float
50 .globl asm_vm_call_method_double
51 .globl asm_vm_call_method_exception_handler
52 .globl asm_vm_call_method_end
54 .globl asm_call_jit_compiler
55 .globl asm_handle_nat_exception
56 .globl asm_handle_exception
58 .globl asm_abstractmethoderror
60 .globl asm_builtin_f2i
61 .globl asm_builtin_f2l
62 .globl asm_builtin_d2i
63 .globl asm_builtin_d2l
65 .globl asm_compare_and_swap
66 .globl asm_memory_barrier
68 .globl asm_get_cycle_count
71 /* asm_md_init *****************************************************************
73 Initialize machine dependent stuff.
75 See: http://www.srware.com/linux_numerics.txt
77 This puts the X86 FPU in 64-bit precision mode. The default under
78 Linux is to use 80-bit mode, which produces subtle differences from
79 FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
80 64-bit mode, 299 in 80-bit mode.
82 Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
84 *******************************************************************************/
87 sub $4,sp /* allocate space for the FPU state */
88 fnstcw (sp) /* get the FPU state */
90 and $0xfcff,%ax /* remove the extended mode flag */
91 or $0x0200,%ax /* put the double mode flag */
92 mov %eax,(sp) /* store new FPU state */
93 fldcw (sp) /* setup new FPU state */
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_vm_call_method(methodinfo *m, *
108 * u4 count, u4 size, void *callblock); *
110 *******************************************************************************/
114 .long 0 /* catch type all */
115 .long 0 /* handler pc */
117 .long 0 /* start pc */
118 .long 1 /* extable size */
119 .long 0 /* line number table start */
120 .long 0 /* line number table size */
121 .long 0 /* fltsave */
122 .long 0 /* intsave */
125 .long 0 /* frame size */
126 .long 0 /* codeinfo pointer */
129 asm_vm_call_method_int:
130 asm_vm_call_method_long:
131 asm_vm_call_method_float:
132 asm_vm_call_method_double:
134 mov sp,bp /* save stackptr */
135 sub $(4*4),sp /* create stackframe */
136 and $0xfffffff0,sp /* align stack to 16-byte */
138 mov t0,0*4(sp) /* save registers */
142 mov sp,s1 /* save stack pointer */
144 mov 3*4(bp),t0 /* address of data structure */
145 mov 4*4(bp),itmp1 /* number of stack arguments */
148 je L_asm_vm_call_method_stack_copy_done
151 add $1,itmp2 /* keep stack 16-byte aligned */
152 and $0xfffffffe,itmp2
153 shl $3,itmp2 /* calculate stack size */
154 sub itmp2,sp /* create stack frame */
155 mov sp,itmp2 /* temporary stack pointer */
157 L_asm_vm_call_method_stack_copy_loop:
158 mov 0(t0),itmp3 /* load argument */
159 mov itmp3,0(itmp2) /* store argument on stack */
163 sub $1,itmp1 /* subtract 1 argument */
164 add $8,t0 /* set address of next argument */
165 add $8,itmp2 /* increase SP */
168 jg L_asm_vm_call_method_stack_copy_loop
170 L_asm_vm_call_method_stack_copy_done:
171 lea (2*4-256)(bp),mptr /* We subtract 256 to force the next */
172 /* move instruction to have a 32-bit */
175 mov (0*4+256)(mptr),itmp3 /* method call as in Java */
176 call *itmp3 /* call JIT compiler */
178 L_asm_vm_call_method_return:
179 mov s1,sp /* restore stackpointer */
181 mov 0*4(sp),t0 /* restore registers */
188 asm_vm_call_method_exception_handler:
189 push xptr /* pass exception pointer */
190 call builtin_throw_exception
192 asm_vm_call_method_end:
193 jmp L_asm_vm_call_method_return
196 /* asm_call_jit_compiler *******************************************************
198 Invokes the compiler for untranslated JavaVM methods.
200 Register R0 contains a pointer to the method info structure (prepared
201 by createcompilerstub). Using the return address in R26 and the
202 offset in the LDA instruction or using the value in methodptr R28 the
203 patching address for storing the method address can be computed:
205 Method address was either loaded using
207 i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special
208 i386_call_reg(REG_ITMP2)
212 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface
213 i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
214 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
215 sizeof(methodptr) * m->vftblindex, REG_ITMP1)
216 i386_call_reg(REG_ITMP1)
218 In the static case the method pointer can be computed using the
219 return address and the lda function following the jmp instruction.
221 *******************************************************************************/
223 asm_call_jit_compiler:
224 L_asm_call_jit_compiler: /* required for PIC code */
225 sub $(4*4),sp /* keep stack 16-byte aligned */
227 mov itmp1,0*4(sp) /* pass methodinfo pointer */
228 mov mptr,1*4(sp) /* pass method pointer */
229 mov sp,itmp2 /* pass java sp */
232 mov 4*4(sp),itmp3 /* pass java ra */
236 add $(4*4),sp /* remove stack frame */
238 test v0,v0 /* check for exception */
239 je L_asm_call_jit_compiler_exception
241 jmp *v0 /* ...and now call the new method */
243 L_asm_call_jit_compiler_exception:
244 call exceptions_get_and_clear_exception
246 pop xpc /* get return address */
247 sub $2,xpc /* faulting address is ra - 2 */
248 jmp L_asm_handle_exception
251 /* asm_handle_exception ********************************************************
253 * This function handles an exception. It does not use the usual calling *
254 * conventions. The exception pointer is passed in REG_ITMP1 and the *
255 * pc from the exception raising position is passed in REG_ITMP2. It searches *
256 * the local exception table for a handler. If no one is found, it unwinds *
257 * stacks and continues searching the callers. *
259 *******************************************************************************/
261 asm_handle_nat_exception:
262 add $4,sp /* clear return address of native stub*/
264 asm_handle_exception:
265 L_asm_handle_exception: /* required for PIC code */
266 sub $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned */
268 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
269 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
271 mov $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
272 mov $1,t0 /* set maybe-leaf flag */
274 L_asm_handle_exception_stack_loop:
275 sub $(12*4),sp /* keep stack 16-byte aligned */
276 mov xptr,4*4(sp) /* save exception pointer */
277 mov xpc,5*4(sp) /* save exception pc */
278 add sp,itmp3 /* calculate Java sp into a3... */
280 mov itmp3,7*4(sp) /* ...and save it */
281 mov t0,8*4(sp) /* save maybe-leaf flag */
283 mov xpc,0*4(sp) /* pass exception pc */
284 call codegen_get_pv_from_pc
285 mov v0,6*4(sp) /* save data segment pointer */
287 mov 4*4(sp),itmp3 /* pass exception pointer */
289 mov 5*4(sp),itmp3 /* pass exception pc */
291 mov v0,2*4(sp) /* pass data segment pointer */
292 mov 7*4(sp),itmp3 /* pass Java stack pointer */
294 call exceptions_handle_exception
297 jz L_asm_handle_exception_not_catched
299 mov v0,xpc /* move handlerpc into xpc */
300 mov 4*4(sp),xptr /* restore exception pointer */
301 mov 8*4(sp),t0 /* get maybe-leaf flag */
302 add $(12*4),sp /* free stackframe */
304 test t0,t0 /* test for maybe-leaf flag */
305 jz L_asm_handle_exception_no_leaf
307 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
308 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
310 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
312 L_asm_handle_exception_no_leaf:
313 jmp *xpc /* jump to exception handler */
315 L_asm_handle_exception_not_catched:
316 mov 4*4(sp),xptr /* restore exception pointer */
317 mov 6*4(sp),itmp3 /* restore data segment pointer */
318 mov 8*4(sp),t0 /* get maybe-leaf flag */
319 add $(12*4),sp /* free stackframe */
322 jz L_asm_handle_exception_no_leaf_stack
324 add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
325 xor t0,t0 /* clear the maybe-leaf flag */
327 L_asm_handle_exception_no_leaf_stack:
328 mov FrameSize(itmp3),itmp2 /* get frame size */
329 add sp,itmp2 /* pointer to save area */
331 push xptr /* we are out of registers */
333 mov IntSave(itmp3),itmp1 /* itmp1 = saved int register count */
348 shl $2,itmp1 /* multiply by 4 bytes */
353 mov FltSave(itmp3),itmp1 /* itmp1 = saved flt register count */
378 pop xptr /* restore exception pointer */
379 mov FrameSize(itmp3),itmp2 /* get frame size */
380 add itmp2,sp /* unwind stack */
382 pop xpc /* the new xpc is return address */
383 sub $2,xpc /* subtract 2-bytes for call */
385 xor itmp3,itmp3 /* prepare a3 for handle_exception */
387 jmp L_asm_handle_exception_stack_loop
390 /* asm_abstractmethoderror *****************************************************
392 Creates and throws an AbstractMethodError.
394 *******************************************************************************/
396 asm_abstractmethoderror:
397 sub $(3*4),sp /* keep stack 16-byte aligned */
398 mov sp,itmp1 /* pass java sp */
401 mov 3*4(sp),itmp2 /* pass exception address */
404 call exceptions_asm_new_abstractmethoderror
405 /* exception pointer is return value */
406 add $(3*4),sp /* remove stack frame */
408 pop xpc /* get exception address */
409 sub $2,xpc /* exception address is ra - 2 */
410 jmp L_asm_handle_exception
413 /************************ function asm_builtin_x2x *****************************
415 * Wrapper functions for corner cases *
417 *******************************************************************************/
448 /* asm_compare_and_swap ********************************************************
450 Does an atomic compare and swap. Required for the lock
453 Atomically do the following: Check if the location still contains
454 `oldval`. If so, replace it by `newval` and return `oldval`.
459 long compare_and_swap(volatile long *p, long oldval, long newval);
461 *******************************************************************************/
463 asm_compare_and_swap:
464 mov 1*4(sp),%ecx /* load p into a register */
465 mov 2*4(sp),%eax /* load oldval into return register */
466 mov 3*4(sp),%edx /* load newval into a register */
467 lock; cmpxchgl %edx,0(%ecx)
471 /* asm_memory_barrier **********************************************************
473 A memory barrier for the Java Memory Model.
475 *******************************************************************************/
482 /* asm_get_cycle_count *********************************************************
484 Get the current time-stamp counter from the CPU.
486 *******************************************************************************/
493 /* disable exec-stacks ********************************************************/
495 #if defined(__linux__) && defined(__ELF__)
496 .section .note.GNU-stack,"",%progbits
501 * These are local overrides for various environment variables in Emacs.
502 * Please do not remove this and leave it at the end of the file, where
503 * Emacs will automagically detect them.
504 * ---------------------------------------------------------------------
507 * indent-tabs-mode: t
511 * vim:noexpandtab:sw=4:ts=4: