1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
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 Changes: Joseph Wenninger
33 $Id: asmpart.S 3894 2005-12-06 22:30:30Z twisti $
39 #include "vm/jit/i386/offsets.h"
41 #include "vm/jit/methodheader.h"
44 /* define it like the risc way */
66 /********************* exported functions and variables ***********************/
68 .globl asm_calljavafunction
69 .globl asm_calljavafunction_int
71 .globl asm_calljavafunction2
72 .globl asm_calljavafunction2int
73 .globl asm_calljavafunction2long
74 .globl asm_calljavafunction2float
75 .globl asm_calljavafunction2double
77 .globl asm_call_jit_compiler
78 .globl asm_handle_nat_exception
79 .globl asm_handle_exception
81 .globl asm_wrapper_patcher
83 .globl asm_builtin_f2i
84 .globl asm_builtin_f2l
85 .globl asm_builtin_d2i
86 .globl asm_builtin_d2l
88 .globl asm_perform_threadswitch
89 .globl asm_initialize_thread_stack
90 .globl asm_switchstackandcall
91 .globl asm_criticalsections
92 .globl asm_getclassvalues_atomic
95 /********************* function asm_calljavafunction ***************************
97 * This function calls a Java-method (which possibly needs compilation) *
98 * with up to 4 address parameters. *
100 * This functions calls the JIT-compiler which eventually translates the *
101 * method into machine code. *
104 * javaobject_header *asm_calljavamethod (methodinfo *m, *
105 * void *arg1, void *arg2, void *arg3, void *arg4); *
107 *******************************************************************************/
112 .long 0 /* catch type all */
113 .long calljava_xhandler /* handler pc */
114 .long calljava_xhandler /* end pc */
115 .long asm_calljavafunction /* start pc */
116 .long 1 /* extable size */
117 .long 0 /* line number table start */
118 .long 0 /* line number table size */
119 .long 0 /* fltsave */
120 .long 0 /* intsave */
123 .long 32 /* frame size */
124 .long 0 /* method pointer (pointer to name) */
126 asm_calljavafunction:
127 asm_calljavafunction_int:
128 push %ebp /* allocate stack space */
131 push %ebx /* save registers */
136 sub $16,%esp /* 4 adress parameters * 4 Bytes */
137 mov 24(%ebp),%eax /* copy adress parameters to new block*/
149 mov 8(%ebp),%eax /* move function pointer to %eax */
151 lea asm_call_jit_compiler,%edx
152 call *%edx /* call JIT compiler */
155 pop %edi /* restore registers */
162 push %eax /* pass exception pointer */
163 call builtin_throw_exception
167 pop %edi /* restore registers */
171 xor v0,v0 /* return NULL */
175 /********************* function asm_calljavafunction ***************************
177 * This function calls a Java-method (which possibly needs compilation) *
178 * with up to 4 address parameters. *
180 * This functions calls the JIT-compiler which eventually translates the *
181 * method into machine code. *
184 * javaobject_header *asm_calljavafunction2(methodinfo *m, *
185 * u4 count, u4 size, void *callblock); *
187 *******************************************************************************/
192 .long 0 /* catch type all */
193 .long calljava_xhandler2 /* handler pc */
194 .long calljava_xhandler2 /* end pc */
195 .long asm_calljavafunction2 /* start pc */
196 .long 1 /* extable size */
197 .long 0 /* line number table start */
198 .long 0 /* line number table size */
199 .long 0 /* fltsave */
200 .long 0 /* intsave */
203 .long 32 /* frame size */
204 .long 0 /* method pointer (pointer to name) */
206 asm_calljavafunction2:
207 asm_calljavafunction2int:
208 asm_calljavafunction2long:
209 asm_calljavafunction2float:
210 asm_calljavafunction2double:
212 mov %esp,%ebp /* save stackptr */
214 push %ebx /* save registers */
218 mov 20(%ebp),%eax /* pointer to arg block (4(push)+4(return)+4+4+4)*/
219 mov 12(%ebp),%ecx /* arg count (4(push)+4(return)+4 */
221 xor %esi,%esi /* clear stackframe size (MUST be */
222 /* before args check, may be zero!!!) */
223 test %ecx,%ecx /* maybe we have no args */
224 jle calljava_copydone
226 mov %ecx,%edx /* calculate stack size */
227 mov %eax,%edi /* save pointer to arg block */
229 calljava_calcstacksize:
230 mov offjniitemtype(%eax),%ebx
231 test $1,%ebx /* two word type? */
232 jz calljava_onewordtype
233 add $4,%esi /* add 1 slot to stackframe size */
235 calljava_onewordtype:
236 add $4,%esi /* add 1 slot to stackframe size */
238 test %edx,%edx /* any args left? */
240 add $sizejniblock,%eax /* goto next argument block */
241 jmp calljava_calcstacksize
244 mov %edi,%eax /* restore pointer to arg block */
245 sub %esi,%esp /* create stackframe for arguments */
246 mov %esp,%edi /* move stackpointer into temp variable */
249 mov offjniitem(%eax),%edx /* copy 4 Byte of Argument */
251 add $4,%edi /* increase sp to next argument */
252 mov offjniitemtype(%eax),%ebx /* type -> ebx */
253 test $1,%ebx /* Two Word Type? */
256 mov offjniitem+4(%eax),%edx /* copy upper 4 Byte of 2 Word Type */
258 add $4,%edi /* increase sp to next argument */
261 sub $1,%ecx /* are there any args left? */
263 jle calljava_copydone
265 add $sizejniblock,%eax /* goto next argument block */
266 jmp calljava_copyloop
269 mov 8(%ebp),%eax /* move function pointer to %eax */
271 lea asm_call_jit_compiler,%edx
272 call *%edx /* call JIT compiler */
274 add %esi,%esp /* remove arg stack frame */
275 pop %edi /* restore registers */
282 push xptr /* pass exception pointer */
283 call builtin_throw_exception
286 add %esi,%esp /* remove arg stack frame */
287 pop %edi /* restore registers */
291 xor v0,v0 /* return NULL */
295 /****************** function asm_call_jit_compiler *****************************
297 * invokes the compiler for untranslated JavaVM methods. *
299 * Register R0 contains a pointer to the method info structure (prepared *
300 * by createcompilerstub). Using the return address in R26 and the *
301 * offset in the LDA instruction or using the value in methodptr R28 the *
302 * patching address for storing the method address can be computed: *
304 * method address was either loaded using *
306 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
307 * i386_call_reg(REG_ITMP2) *
311 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
312 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
313 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
314 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
315 * i386_call_reg(REG_ITMP1) *
317 * in the static case the method pointer can be computed using the *
318 * return address and the lda function following the jmp instruction *
320 *******************************************************************************/
322 asm_call_jit_compiler:
323 sub $((4+2)*4+sizestackframeinfo),sp /* create stack frame */
324 mov itmp1,(4+0)*4(sp) /* save method pointer */
326 mov (4+2)*4+sizestackframeinfo(sp),itmp3 /* get return address */
327 mov -1(itmp3),itmp1b /* get function code */
328 cmp $0xd1,itmp1b /* called with `call *REG_ITMP2'? */
329 jne L_not_static_special
331 sub $6,itmp3 /* calculate address of immediate */
332 jmp L_call_jit_compile
334 L_not_static_special:
335 cmp $0xd0,itmp1b /* called with `call *REG_ITMP1' */
336 jne L_not_virtual_interface
338 sub $6,itmp3 /* calculate address of offset */
339 mov (itmp3),itmp3 /* get offset */
340 add itmp2,itmp3 /* add base address to get method adr */
341 jmp L_call_jit_compile
343 L_not_virtual_interface:
344 xor itmp3,itmp3 /* a call from asm_calljavafunction */
347 mov itmp3,(4+1)*4(sp) /* save address for method pointer */
349 mov sp,itmp1 /* create stackframe info */
351 mov itmp1,0*4(sp) /* stackframeinfo pointer */
352 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
354 add $((1+4+2)*4+sizestackframeinfo),itmp2 /* pass java sp */
356 mov ((0+4+2)*4+sizestackframeinfo)(sp),itmp3 /* pass java ra */
358 call stacktrace_create_inline_stackframeinfo
360 mov (4+0)*4(sp),itmp1 /* pass method pointer */
363 mov v0,(4+0)*4(sp) /* save return value */
365 mov sp,itmp1 /* remove stackframe info */
367 mov itmp1,0*4(sp) /* stackframeinfo pointer */
368 call stacktrace_remove_stackframeinfo
370 mov (4+0)*4(sp),v0 /* restore return value */
371 mov (4+1)*4(sp),itmp3 /* restore address for method pointer */
373 add $((4+2)*4+sizestackframeinfo),sp /* remove stack frame */
375 test v0,v0 /* check for exception */
376 je L_asm_call_jit_compiler_exception
378 test itmp3,itmp3 /* was this a JIT call? */
381 mov v0,(itmp3) /* save the new method pointer */
384 jmp *v0 /* ...and now call the new method */
386 L_asm_call_jit_compiler_exception:
387 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
388 call builtin_asm_get_exceptionptrptr
389 mov v0,itmp2 /* v0 == itmp1 */
391 lea _exceptionptr,itmp2
393 mov (itmp2),xptr /* get the exception pointer */
394 movl $0,(itmp2) /* clear the exception pointer */
396 pop xpc /* get return address */
397 sub $2,xpc /* faulting address is ra - 2 */
398 jmp asm_handle_exception
401 /* asm_handle_exception ********************************************************
403 * This function handles an exception. It does not use the usual calling *
404 * conventions. The exception pointer is passed in REG_ITMP1 and the *
405 * pc from the exception raising position is passed in REG_ITMP2. It searches *
406 * the local exception table for a handler. If no one is found, it unwinds *
407 * stacks and continues searching the callers. *
409 *******************************************************************************/
411 asm_handle_nat_exception:
412 add $4,sp /* clear return address of native stub*/
414 asm_handle_exception:
416 xor %edi,%edi /* clear indent flag (only first time)*/
419 L_asm_handle_exception_stack_loop:
420 sub $(10*4),sp /* create stackframe */
421 mov xptr,4*4(sp) /* save exception pointer */
422 mov xpc,5*4(sp) /* save exception pc */
425 mov %ebx,7*4(sp) /* save registers (non-callee) */
429 mov xpc,0*4(sp) /* pass exception pc */
430 call codegen_findmethod
431 mov v0,6*4(sp) /* save data segment pointer */
433 mov 4*4(sp),itmp3 /* pass exception pointer */
435 mov 5*4(sp),itmp3 /* pass exception pc */
437 mov v0,2*4(sp) /* pass data segment pointer */
438 mov sp,itmp3 /* pass Java stack pointer */
441 call exceptions_handle_exception
444 jz L_asm_handle_exception_not_catched
446 mov v0,xpc /* move handlerpc into xpc */
447 mov 4*4(sp),xptr /* restore exception pointer */
449 mov 7*4(sp),%ebx /* restore registers (non-callee) */
452 add $(10*4),sp /* free stackframe */
454 jmp *xpc /* jump to exception handler */
456 L_asm_handle_exception_not_catched:
457 mov 4*4(sp),xptr /* restore exception pointer */
458 mov 6*4(sp),itmp3 /* restore data segment pointer */
460 mov 7*4(sp),%ebx /* restore registers (non-callee) */
463 add $(10*4),sp /* free stackframe */
465 mov FrameSize(itmp3),itmp2 /* get frame size */
466 add itmp2,sp /* unwind stack */
467 mov sp,itmp2 /* pointer to save area */
469 mov IntSave(itmp3),%ebx /* %ecx = saved int register count */
484 shl $2,%ebx /* multiply by 4 bytes */
488 mov FltSave(itmp3),%ebx /* %ecx = saved flt register count */
512 /* exception pointer is still set */
513 pop xpc /* the new xpc is return address */
514 sub $2,xpc /* subtract 2-bytes for call */
517 mov $1,%edi /* set indent flag */
520 jmp L_asm_handle_exception_stack_loop
523 /* asm_wrapper_patcher *********************************************************
529 16 pointer to virtual java_objectheader
530 12 last byte of machine code (xmcode)
531 8 machine code (which is patched back later)
532 4 unresolved field reference
533 0 patcher function pointer to call
535 *******************************************************************************/
538 sub $((2+4)*4+sizestackframeinfo),sp /* create stack frame */
540 mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
541 mov itmp2,(1+4)*4(sp) /* may be used by some instructions */
543 mov sp,itmp1 /* create stackframe info */
545 mov itmp1,0*4(sp) /* stackframeinfo pointer */
546 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
548 add $((6+2+4)*4+sizestackframeinfo),itmp2
550 mov ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
552 call stacktrace_create_inline_stackframeinfo
554 mov sp,itmp1 /* pass stack pointer */
555 add $((1+2+4)*4+sizestackframeinfo),itmp1 /* skip function pointer */
557 mov (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer */
558 call *itmp1 /* call the patcher function */
559 mov v0,1*4(sp) /* save return value */
561 mov sp,itmp1 /* remove stackframe info */
563 mov itmp1,0*4(sp) /* stackframeinfo pointer */
564 call stacktrace_remove_stackframeinfo
566 mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
567 mov (1+4)*4(sp),itmp2 /* may be used by some instructions */
568 mov 1*4(sp),itmp3 /* restore return value */
570 add $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
571 test itmp3,itmp3 /* exception thrown? */
572 jz L_asm_wrapper_patcher_exception
573 ret /* call new patched code */
575 L_asm_wrapper_patcher_exception:
576 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
577 call builtin_asm_get_exceptionptrptr
580 lea _exceptionptr,itmp2
582 mov (itmp2),xptr /* get the exception pointer */
583 movl $0,(itmp2) /* clear the exception pointer */
585 pop xpc /* get and remove return address */
586 jmp asm_handle_exception
589 /************************ function asm_builtin_x2x *****************************
591 * Wrapper functions for corner cases *
593 *******************************************************************************/
624 /******************* function asm_initialize_thread_stack **********************
626 * initialized a thread stack *
627 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
629 *******************************************************************************/
631 asm_initialize_thread_stack:
632 mov 8(%esp),%eax /* (to)->stackEnd */
633 sub $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
645 mov 4(%esp),%edx /* save (u1*) (func) */
648 ret /* return restorepoint in %eax */
651 /******************* function asm_perform_threadswitch *************************
653 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
655 * performs a threadswitch *
657 *******************************************************************************/
659 asm_perform_threadswitch:
671 mov 36(%esp),%eax /* save current return address */
674 mov 40(%esp),%eax /* first argument **from */
677 mov 48(%esp),%eax /* third argument **stackTop */
680 mov 44(%esp),%eax /* second argument **to */
681 mov 0(%eax),%esp /* load new stack pointer */
687 /* skip stack pointer */
692 add $32,%esp /* leave return address on stack */
696 /********************* function asm_switchstackandcall *************************
698 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
701 * Switches to a new stack, calls a function and switches back. *
702 * a0 new stack pointer *
703 * a1 function pointer *
704 * a2 pointer to variable where stack top should be stored *
705 * a3 pointer to user data, is passed to the function *
707 *******************************************************************************/
709 asm_switchstackandcall:
710 mov 4(%esp),%edx /* first argument *stack */
711 sub $8,%edx /* allocate new stack */
713 mov (%esp),%eax /* save return address on new stack */
716 mov %esp,4(%edx) /* save old stack pointer on new stack */
718 mov 12(%esp),%eax /* third argument **stacktopsave */
719 mov %esp,(%eax) /* save old stack pointer to variable */
721 mov 8(%esp),%eax /* load function pointer */
722 mov 16(%esp),%ecx /* fourth argument *p */
724 mov %edx,%esp /* switch to new stack */
727 mov %ecx,0(%esp) /* pass pointer */
728 call *%eax /* and call function */
731 mov (%esp),%edx /* load return address */
732 mov 4(%esp),%esp /* switch to old stack */
737 asm_getclassvalues_atomic:
739 mov 4(%esp),%ecx /* super */
740 mov 8(%esp),%edx /* sub */
742 mov offbaseval(%ecx),%eax
743 mov offdiffval(%ecx),%ecx
744 mov offbaseval(%edx),%edx
747 mov 16(%esp),%ebx /* out */
748 mov %eax,offcast_super_baseval(%ebx)
749 mov %ecx,offcast_super_diffval(%ebx)
750 mov %edx,offcast_sub_baseval(%ebx)
756 asm_criticalsections:
757 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
771 * These are local overrides for various environment variables in Emacs.
772 * Please do not remove this and leave it at the end of the file, where
773 * Emacs will automagically detect them.
774 * ---------------------------------------------------------------------
777 * indent-tabs-mode: t