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 2999 2005-07-12 11:20:34Z twisti $
39 #include "vm/jit/i386/offsets.h"
40 #include "vm/jit/i386/asmoffsets.h"
43 /* define it like the risc way */
64 /********************* exported functions and variables ***********************/
66 .globl asm_calljavafunction
67 .globl asm_calljavafunction_int
69 .globl asm_calljavafunction2
70 .globl asm_calljavafunction2int
71 .globl asm_calljavafunction2long
72 .globl asm_calljavafunction2float
73 .globl asm_calljavafunction2double
75 .globl asm_call_jit_compiler
76 .globl asm_handle_nat_exception
77 .globl asm_handle_exception
79 .globl asm_wrapper_patcher
81 .globl asm_builtin_f2i
82 .globl asm_builtin_f2l
83 .globl asm_builtin_d2i
84 .globl asm_builtin_d2l
86 .globl asm_perform_threadswitch
87 .globl asm_initialize_thread_stack
88 .globl asm_switchstackandcall
89 .globl asm_criticalsections
90 .globl asm_getclassvalues_atomic
93 /********************* function asm_calljavafunction ***************************
95 * This function calls a Java-method (which possibly needs compilation) *
96 * with up to 4 address parameters. *
98 * This functions calls the JIT-compiler which eventually translates the *
99 * method into machine code. *
102 * javaobject_header *asm_calljavamethod (methodinfo *m, *
103 * void *arg1, void *arg2, void *arg3, void *arg4); *
105 *******************************************************************************/
110 .long 0 /* catch type all */
111 .long calljava_xhandler /* handler pc */
112 .long calljava_xhandler /* end pc */
113 .long asm_calljavafunction /* start pc */
114 .long 1 /* extable size */
115 .long 0 /* line number table start */
116 .long 0 /* line number table size */
117 .long 0 /* fltsave */
118 .long 0 /* intsave */
121 .long 32 /* frame size */
122 .long 0 /* method pointer (pointer to name) */
124 asm_calljavafunction:
125 asm_calljavafunction_int:
126 push %ebp /* allocate stack space */
129 push %ebx /* save registers */
134 sub $16,%esp /* 4 adress parameters * 4 Bytes */
135 mov 24(%ebp),%eax /* copy adress parameters to new block */
147 mov 8(%ebp),%eax /* move function pointer to %eax */
149 lea asm_call_jit_compiler,%edx
150 call *%edx /* call JIT compiler */
153 pop %edi /* restore registers */
160 push %eax /* pass exception pointer */
161 call builtin_throw_exception
165 pop %edi /* restore registers */
169 xor %eax,%eax /* return NULL */
173 /********************* function asm_calljavafunction ***************************
175 * This function calls a Java-method (which possibly needs compilation) *
176 * with up to 4 address parameters. *
178 * This functions calls the JIT-compiler which eventually translates the *
179 * method into machine code. *
182 * javaobject_header *asm_calljavafunction2(methodinfo *m, *
183 * u4 count, u4 size, void *callblock); *
185 *******************************************************************************/
190 .long 0 /* catch type all */
191 .long calljava_xhandler2 /* handler pc */
192 .long calljava_xhandler2 /* end pc */
193 .long asm_calljavafunction2 /* start pc */
194 .long 1 /* extable size */
195 .long 0 /* line number table start */
196 .long 0 /* line number table size */
197 .long 0 /* fltsave */
198 .long 0 /* intsave */
201 .long 32 /* frame size */
202 .long 0 /* method pointer (pointer to name) */
204 asm_calljavafunction2:
205 asm_calljavafunction2int:
206 asm_calljavafunction2long:
207 asm_calljavafunction2float:
208 asm_calljavafunction2double:
210 mov %esp,%ebp /* save stackptr */
212 push %ebx /* save registers */
216 mov 20(%ebp),%eax /* pointer to arg block (4(push)+4(return)+4+4+4)*/
217 mov 12(%ebp),%ecx /* arg count (4(push)+4(return)+4 */
218 test %ecx,%ecx /* maybe we have no args */
219 jle calljava_copydone
221 mov %ecx,%edx /* calculate stack size */
223 mov %eax,%edi /* save pointer to arg block */
224 calljava_calcstacksize:
225 mov offjniitemtype(%eax),%ebx
226 test $1,%ebx /* Two Word Type? */
227 jz calljava_onewordtype
229 calljava_onewordtype:
232 test %edx,%edx /* any args left ?*/
234 add $sizejniblock,%eax /* goto next argument block */
235 jmp calljava_calcstacksize
238 mov %edi,%eax /* restore pointer to arg block */
239 sub %esi,%esp /* stack frame for arguments */
243 mov offjniitem(%eax),%edx /* copy 4 Byte of Argument */
245 add $4,%edi /* increase sp to next argument */
246 mov offjniitemtype(%eax),%ebx /* type -> ebx */
247 test $1,%ebx /* Two Word Type? */
249 mov offjniitem+4(%eax),%edx /* copy upper 4 Byte of 2 Word Type */
251 add $4,%edi /* increase sp to next argument */
253 sub $1,%ecx /* are there any args left? */
255 jle calljava_copydone
257 add $sizejniblock,%eax /* goto next argument block */
258 jmp calljava_copyloop
261 mov 8(%ebp),%eax /* move function pointer to %eax */
263 lea asm_call_jit_compiler,%edx
264 call *%edx /* call JIT compiler */
267 add %esi,%esp /* remove arg stack frame */
268 pop %edi /* restore registers */
275 push %eax /* pass exception pointer */
276 call builtin_throw_exception
279 add %esi,%esp /* remove arg stack frame */
280 pop %edi /* restore registers */
284 xor %eax,%eax /* return NULL */
288 /****************** function asm_call_jit_compiler *****************************
290 * invokes the compiler for untranslated JavaVM methods. *
292 * Register R0 contains a pointer to the method info structure (prepared *
293 * by createcompilerstub). Using the return address in R26 and the *
294 * offset in the LDA instruction or using the value in methodptr R28 the *
295 * patching address for storing the method address can be computed: *
297 * method address was either loaded using *
299 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
300 * i386_call_reg(REG_ITMP2) *
304 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
305 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
306 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
307 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
308 * i386_call_reg(REG_ITMP1) *
310 * in the static case the method pointer can be computed using the *
311 * return address and the lda function following the jmp instruction *
313 *******************************************************************************/
315 asm_call_jit_compiler:
316 push %ebx /* save register */
319 mov 2*4(%esp),%ebp /* get return address (2 push) */
320 mov -1(%ebp),%bl /* get function code */
321 cmp $0xd1,%bl /* called with `call *REG_ITMP2' (%ecx)? */
322 jne L_not_static_special
324 sub $6,%ebp /* calculate address of immediate */
325 jmp L_call_jit_compile
327 L_not_static_special:
328 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%eax) */
329 jne L_not_virtual_interface
331 sub $6,%ebp /* calculate address of offset */
332 mov (%ebp),%ebp /* get offset */
333 add itmp2,%ebp /* add base address to get method address */
334 jmp L_call_jit_compile
336 L_not_virtual_interface: /* a call from asm_calljavafunction */
340 push %ebp /* save address for method pointer */
342 push %eax /* push methodpointer on stack */
346 pop %ebp /* restore address for method pointer */
348 test %eax,%eax /* check for exception */
349 je L_asm_call_jit_compiler_exception
351 test %ebp,%ebp /* is address == 0 (asm_calljavafunction) */
354 mov %eax,(%ebp) /* and now save the new pointer */
357 pop %ebp /* restore registers */
360 jmp *%eax /* ...and now call the new method */
362 L_asm_call_jit_compiler_exception:
363 pop %ebp /* restore registers */
367 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
368 call builtin_asm_get_exceptionptrptr
371 lea _exceptionptr,itmp2
373 mov (itmp2),xptr /* get the exception pointer */
374 movl $0,(itmp2) /* clear the exception pointer */
376 sub $(5*4+sizestackframeinfo),sp
377 mov xptr,4*4(sp) /* save exception pointer */
379 mov sp,itmp1 /* create stackframe info */
381 mov itmp1,0*4(sp) /* stackframeinfo pointer */
382 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
384 add $(6*4+sizestackframeinfo),itmp2
386 mov (5*4+sizestackframeinfo)(sp),itmp3
388 call stacktrace_create_inline_stackframeinfo
390 mov 4*4(sp),itmp1 /* fill in stacktrace */
392 call stacktrace_call_fillInStackTrace
394 mov sp,itmp1 /* remove stackframe info */
396 mov itmp1,0*4(sp) /* stackframeinfo pointer */
397 call stacktrace_remove_stackframeinfo
399 mov 4*4(sp),xptr /* restore exception pointer */
400 add $(5*4+sizestackframeinfo),sp
404 movl $0,0*4(sp) /* we don't have pv handy */
405 mov sp,itmp1 /* pass java sp */
406 add $((1+5)*4),itmp1 /* also skip ra */
408 mov 5*4(sp),itmp2 /* pass java ra */
410 mov itmp2,3*4(sp) /* xpc is equal to ra */
411 call stacktrace_extern_fillInStackTrace
415 pop xpc /* get return address */
416 sub $2,xpc /* faulting address is ra - 2 */
417 jmp asm_handle_exception
420 /********************* function asm_handle_exception ***************************
422 * This function handles an exception. It does not use the usual calling *
423 * conventions. The exception pointer is passed in REG_ITMP1 and the *
424 * pc from the exception raising position is passed in REG_ITMP2. It searches *
425 * the local exception table for a handler. If no one is found, it unwinds *
426 * stacks and continues searching the callers. *
428 * void asm_handle_exception (exceptionptr, exceptionpc); *
430 *******************************************************************************/
432 asm_handle_nat_exception:
433 add $4,%esp /* clear return address of native stub */
435 asm_handle_exception:
436 asm_handle_exception_loop:
440 push %eax /* save exception pointer */
441 push %ecx /* save exception pc */
443 call codegen_findmethod /* get the data segment ptr */
447 mov -8(%ebp),%ecx /* could be changed in findmethod */
449 push %edx /* save data segment pointer */
456 mov %eax,(%esp) /* exception pointer */
457 mov MethodPointer(%edx),%eax /* method pointer */
459 mov %ecx,8(%esp) /* exception pc */
460 movl $0,12(%esp) /* line number */
461 movl $1,16(%esp) /* set no unwind flag */
462 call builtin_trace_exception
464 mov -12(%ebp),%esi /* %esi = data segment pointer */
465 mov ExTableSize(%esi),%ecx /* %ecx = exception table size */
466 test %ecx,%ecx /* if empty table skip */
469 lea ExTableStart(%esi),%edi /* %edi = start of exception table*/
470 mov -4(%ebp),%eax /* get xptr */
473 mov -8(%ebp),%edx /* get xpc */
475 mov ExStartPC(%edi),%ebx /* %ebx = exception start pc */
476 cmp %edx,%ebx /* %ebx = (startpc <= xpc) */
477 jg ex_table_cont /* if (false) continue */
478 mov ExEndPC(%edi),%ebx /* %ebx = exception end pc */
479 cmp %ebx,%edx /* %ebx = (xpc < endpc) */
480 jge ex_table_cont /* if (false) continue */
481 mov ExCatchType(%edi),%ebx /* arg1 = exception catch type */
482 test %ebx,%ebx /* NULL catches everything */
485 cmpl $0,offclassloaded(%ebx) /* check if class is loaded */
489 mov %eax,1*4(%esp) /* save not callee saved regs */
492 mov %ebx,0*4(%esp) /* exception class is argument */
493 call load_class_bootstrap
501 cmpl $0,offclasslinked(%ebx)
505 mov %eax,1*4(%esp) /* save not callee saved regs */
508 mov %ebx,0*4(%esp) /* exception class is argument */
517 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
525 mov offobjvftbl(%eax),%esi /* %esi = vftblptr(xptr) */
526 mov offclassvftbl(%ebx),%ebx /* %ebx = vftblptr(catchtype) class (not obj) */
527 mov offbaseval(%esi),%esi /* %esi = baseval(xptr) */
528 mov offbaseval(%ebx),%edx /* %edx = baseval(catchtype) */
529 mov offdiffval(%ebx),%ebx /* %ebx = diffval(catchtype) */
531 sub %edx,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
533 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
537 cmp %ebx,%esi /* xptr is instanceof catchtype */
541 mov ExHandlerPC(%edi),%edx
543 pop %edi /* restore registers */
546 add $8,%esp /* suck %ecx, %edx */
547 pop %eax /* restore xptr */
550 jmp *%edx /* jump to exception handler */
553 lea ExEntrySize(%edi),%edi
562 pop %edx /* restore data segment pointer */
567 push %eax /* save exception pointer */
570 mov IsSync(%edx),%eax /* %eax = SyncOffset */
571 test %eax,%eax /* if zero no monitorexit */
574 #if defined(USE_THREADS)
576 mov (%eax),%eax /* we have the xptr on the stack (+4-4=0) */
577 push %edx /* save regs */
579 call builtin_monitorexit
581 pop %edx /* restore regs */
586 add FrameSize(%edx),%eax /* %eax = frame size */
587 add $4,%eax /* we have the xptr on the stack */
589 mov IntSave(%edx),%ecx /* %ecx = saved int register count*/
611 shl $2,%ecx /* multiply by 4 bytes */
615 mov FltSave(%edx),%ecx /* %ecx = saved flt register count */
642 pop %eax /* restore exception pointer */
644 mov FrameSize(%edx),%ecx /* %ecx = frame size */
645 add %ecx,%esp /* unwind stack */
647 pop %ecx /* the new xpc is return address */
648 sub $2,%ecx /* -2 -> call */
650 jmp asm_handle_exception_loop
653 /* asm_wrapper_patcher *********************************************************
659 16 pointer to virtual java_objectheader
660 12 last byte of machine code (xmcode)
661 8 machine code (which is patched back later)
662 4 unresolved field reference
663 0 patcher function pointer to call
665 *******************************************************************************/
668 sub $((2+4)*4+sizestackframeinfo),sp /* create stack frame */
670 mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
671 mov itmp2,(1+4)*4(sp) /* may be used by some instructions */
673 mov sp,itmp1 /* create stackframe info */
675 mov itmp1,0*4(sp) /* stackframeinfo pointer */
676 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
678 add $((6+2+4)*4+sizestackframeinfo),itmp2
680 mov ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
682 call stacktrace_create_inline_stackframeinfo
684 mov sp,itmp1 /* pass stack pointer */
685 add $((1+2+4)*4+sizestackframeinfo),itmp1 /* skip function pointer */
687 mov (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer */
688 call *itmp1 /* call the patcher function */
689 mov v0,1*4(sp) /* save return value */
691 mov sp,itmp1 /* remove stackframe info */
693 mov itmp1,0*4(sp) /* stackframeinfo pointer */
694 call stacktrace_remove_stackframeinfo
696 mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
697 mov (1+4)*4(sp),itmp2 /* may be used by some instructions */
698 mov 1*4(sp),itmp3 /* restore return value */
700 add $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
701 test itmp3,itmp3 /* exception thrown? */
702 jz L_asm_wrapper_patcher_exception
703 ret /* call new patched code */
705 L_asm_wrapper_patcher_exception:
706 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
707 call builtin_asm_get_exceptionptrptr
710 lea _exceptionptr,itmp2
712 mov (itmp2),xptr /* get the exception pointer */
713 movl $0,(itmp2) /* clear the exception pointer */
715 pop xpc /* get and remove return address */
716 jmp asm_handle_exception
719 /************************ function asm_builtin_x2x *****************************
721 * Wrapper functions for corner cases *
723 *******************************************************************************/
754 /******************* function asm_initialize_thread_stack **********************
756 * initialized a thread stack *
757 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
759 *******************************************************************************/
761 asm_initialize_thread_stack:
762 mov 8(%esp),%eax /* (to)->stackEnd */
763 sub $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
775 mov 4(%esp),%edx /* save (u1*) (func) */
778 ret /* return restorepoint in %eax */
781 /******************* function asm_perform_threadswitch *************************
783 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
785 * performs a threadswitch *
787 *******************************************************************************/
789 asm_perform_threadswitch:
801 mov 36(%esp),%eax /* save current return address */
804 mov 40(%esp),%eax /* first argument **from */
807 mov 48(%esp),%eax /* third argument **stackTop */
810 mov 44(%esp),%eax /* second argument **to */
811 mov 0(%eax),%esp /* load new stack pointer */
817 /* skip stack pointer */
822 add $32,%esp /* leave return address on stack */
826 /********************* function asm_switchstackandcall *************************
828 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
831 * Switches to a new stack, calls a function and switches back. *
832 * a0 new stack pointer *
833 * a1 function pointer *
834 * a2 pointer to variable where stack top should be stored *
835 * a3 pointer to user data, is passed to the function *
837 *******************************************************************************/
839 asm_switchstackandcall:
840 mov 4(%esp),%edx /* first argument *stack */
841 sub $8,%edx /* allocate new stack */
843 mov (%esp),%eax /* save return address on new stack */
846 mov %esp,4(%edx) /* save old stack pointer on new stack */
848 mov 12(%esp),%eax /* third argument **stacktopsave */
849 mov %esp,(%eax) /* save old stack pointer to variable */
851 mov 8(%esp),%eax /* load function pointer */
852 mov 16(%esp),%ecx /* fourth argument *p */
854 mov %edx,%esp /* switch to new stack */
857 mov %ecx,0(%esp) /* pass pointer */
858 call *%eax /* and call function */
861 mov (%esp),%edx /* load return address */
862 mov 4(%esp),%esp /* switch to old stack */
867 asm_getclassvalues_atomic:
869 mov 4(%esp),%ecx /* super */
870 mov 8(%esp),%edx /* sub */
872 mov offbaseval(%ecx),%eax
873 mov offdiffval(%ecx),%ecx
874 mov offbaseval(%edx),%edx
877 mov 16(%esp),%ebx /* out */
878 mov %eax,offcast_super_baseval(%ebx)
879 mov %ecx,offcast_super_diffval(%ebx)
880 mov %edx,offcast_sub_baseval(%ebx)
886 asm_criticalsections:
887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
899 * These are local overrides for various environment variables in Emacs.
900 * Please do not remove this and leave it at the end of the file, where
901 * Emacs will automagically detect them.
902 * ---------------------------------------------------------------------
905 * indent-tabs-mode: t