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
33 $Id: asmpart.S 4357 2006-01-22 23:33:38Z twisti $
40 #include "vm/jit/abi.h"
41 #include "vm/jit/i386/md-abi.h"
42 #include "vm/jit/i386/md-asm.h"
43 #include "vm/jit/i386/offsets.h"
45 #include "vm/jit/methodheader.h"
51 /* exported functions and variables *******************************************/
53 .globl asm_calljavafunction
54 .globl asm_calljavafunction_int
56 .globl asm_calljavafunction2
57 .globl asm_calljavafunction2int
58 .globl asm_calljavafunction2long
59 .globl asm_calljavafunction2float
60 .globl asm_calljavafunction2double
62 .globl asm_call_jit_compiler
63 .globl asm_handle_nat_exception
64 .globl asm_handle_exception
66 .globl asm_wrapper_patcher
68 .globl asm_builtin_f2i
69 .globl asm_builtin_f2l
70 .globl asm_builtin_d2i
71 .globl asm_builtin_d2l
73 .globl asm_perform_threadswitch
74 .globl asm_initialize_thread_stack
75 .globl asm_switchstackandcall
76 .globl asm_criticalsections
77 .globl asm_getclassvalues_atomic
80 /********************* function asm_calljavafunction ***************************
82 * This function calls a Java-method (which possibly needs compilation) *
83 * with up to 4 address parameters. *
85 * This functions calls the JIT-compiler which eventually translates the *
86 * method into machine code. *
89 * javaobject_header *asm_calljavamethod (methodinfo *m, *
90 * void *arg1, void *arg2, void *arg3, void *arg4); *
92 *******************************************************************************/
96 .long 0 /* catch type all */
97 .long calljava_xhandler /* handler pc */
98 .long calljava_xhandler /* end pc */
99 .long asm_calljavafunction /* start pc */
100 .long 1 /* extable size */
101 .long 0 /* line number table start */
102 .long 0 /* line number table size */
103 .long 0 /* fltsave */
104 .long 0 /* intsave */
107 .long 0 /* frame size */
108 .long 0 /* method pointer (pointer to name) */
110 asm_calljavafunction:
111 asm_calljavafunction_int:
112 push bp /* allocate stack space */
115 push %ebx /* save registers */
119 sub $(4*4),sp /* 4 adress parameters * 4 Bytes */
120 mov 5*4(bp),itmp1 /* copy adress parameters to new block*/
132 mov 2*4(bp),itmp1 /* move function pointer to %eax */
134 lea asm_call_jit_compiler,itmp3
135 call *itmp3 /* call JIT compiler */
137 L_asm_calljavafunction_return:
139 pop %edi /* restore registers */
146 push xptr /* pass exception pointer */
147 call builtin_throw_exception
149 xor v0,v0 /* return NULL */
150 jmp L_asm_calljavafunction_return
153 /********************* function asm_calljavafunction ***************************
155 * This function calls a Java-method (which possibly needs compilation) *
156 * with up to 4 address parameters. *
158 * This functions calls the JIT-compiler which eventually translates the *
159 * method into machine code. *
162 * javaobject_header *asm_calljavafunction2(methodinfo *m, *
163 * u4 count, u4 size, void *callblock); *
165 *******************************************************************************/
169 .long 0 /* catch type all */
170 .long calljava_xhandler2 /* handler pc */
171 .long calljava_xhandler2 /* end pc */
172 .long asm_calljavafunction2 /* start pc */
173 .long 1 /* extable size */
174 .long 0 /* line number table start */
175 .long 0 /* line number table size */
176 .long 0 /* fltsave */
177 .long 0 /* intsave */
180 .long 0 /* frame size */
181 .long 0 /* method pointer (pointer to name) */
183 asm_calljavafunction2:
184 asm_calljavafunction2int:
185 asm_calljavafunction2long:
186 asm_calljavafunction2float:
187 asm_calljavafunction2double:
189 mov %esp,%ebp /* save stackptr */
191 push %ebx /* save registers */
195 mov 20(%ebp),%eax /* pointer to arg block (4(push)+4(return)+4+4+4)*/
196 mov 12(%ebp),%ecx /* arg count (4(push)+4(return)+4 */
198 xor %esi,%esi /* clear stackframe size (MUST be */
199 /* before args check, may be zero!!!) */
200 test %ecx,%ecx /* maybe we have no args */
201 jle calljava_copydone
203 mov %ecx,%edx /* calculate stack size */
204 mov %eax,%edi /* save pointer to arg block */
206 calljava_calcstacksize:
207 mov offjniitemtype(%eax),%ebx
208 test $1,%ebx /* two word type? */
209 jz calljava_onewordtype
210 add $4,%esi /* add 1 slot to stackframe size */
212 calljava_onewordtype:
213 add $4,%esi /* add 1 slot to stackframe size */
215 test %edx,%edx /* any args left? */
217 add $sizejniblock,%eax /* goto next argument block */
218 jmp calljava_calcstacksize
221 mov %edi,%eax /* restore pointer to arg block */
222 sub %esi,%esp /* create stackframe for arguments */
223 mov %esp,%edi /* move stackpointer into temp variable */
226 mov offjniitem(%eax),%edx /* copy 4 Byte of Argument */
228 add $4,%edi /* increase sp to next argument */
229 mov offjniitemtype(%eax),%ebx /* type -> ebx */
230 test $1,%ebx /* Two Word Type? */
233 mov offjniitem+4(%eax),%edx /* copy upper 4 Byte of 2 Word Type */
235 add $4,%edi /* increase sp to next argument */
238 sub $1,%ecx /* are there any args left? */
240 jle calljava_copydone
242 add $sizejniblock,%eax /* goto next argument block */
243 jmp calljava_copyloop
246 mov 8(%ebp),%eax /* move function pointer to %eax */
248 lea asm_call_jit_compiler,itmp3
249 call *itmp3 /* call JIT compiler */
251 L_asm_calljavafunction2_return:
252 add %esi,%esp /* remove arg stack frame */
253 pop %edi /* restore registers */
260 push xptr /* pass exception pointer */
261 call builtin_throw_exception
263 xor v0,v0 /* return NULL */
264 jmp L_asm_calljavafunction2_return
267 /****************** function asm_call_jit_compiler *****************************
269 * invokes the compiler for untranslated JavaVM methods. *
271 * Register R0 contains a pointer to the method info structure (prepared *
272 * by createcompilerstub). Using the return address in R26 and the *
273 * offset in the LDA instruction or using the value in methodptr R28 the *
274 * patching address for storing the method address can be computed: *
276 * method address was either loaded using *
278 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
279 * i386_call_reg(REG_ITMP2) *
283 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
284 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
285 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
286 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
287 * i386_call_reg(REG_ITMP1) *
289 * in the static case the method pointer can be computed using the *
290 * return address and the lda function following the jmp instruction *
292 *******************************************************************************/
294 asm_call_jit_compiler:
295 sub $((4+2)*4+sizestackframeinfo),sp /* create stack frame */
296 mov itmp1,(4+0)*4(sp) /* save method pointer */
298 mov (4+2)*4+sizestackframeinfo(sp),itmp3 /* get return address */
299 mov -1(itmp3),itmp1b /* get function code */
300 cmp $0xd1,itmp1b /* called with `call *REG_ITMP2'? */
301 jne L_not_static_special
303 sub $6,itmp3 /* calculate address of immediate */
304 jmp L_call_jit_compile
306 L_not_static_special:
307 cmp $0xd0,itmp1b /* called with `call *REG_ITMP1' */
308 jne L_not_virtual_interface
310 sub $6,itmp3 /* calculate address of offset */
311 mov (itmp3),itmp3 /* get offset */
312 add itmp2,itmp3 /* add base address to get method adr */
313 jmp L_call_jit_compile
315 L_not_virtual_interface:
316 xor itmp3,itmp3 /* a call from asm_calljavafunction */
319 mov itmp3,(4+1)*4(sp) /* save address for method pointer */
321 mov sp,itmp1 /* create stackframe info */
323 mov itmp1,0*4(sp) /* stackframeinfo pointer */
324 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
326 add $((1+4+2)*4+sizestackframeinfo),itmp2 /* pass java sp */
328 mov ((0+4+2)*4+sizestackframeinfo)(sp),itmp3 /* pass java ra */
330 call stacktrace_create_inline_stackframeinfo
332 mov (4+0)*4(sp),itmp1 /* pass method pointer */
335 mov v0,(4+0)*4(sp) /* save return value */
337 mov sp,itmp1 /* remove stackframe info */
339 mov itmp1,0*4(sp) /* stackframeinfo pointer */
340 call stacktrace_remove_stackframeinfo
342 mov (4+0)*4(sp),v0 /* restore return value */
343 mov (4+1)*4(sp),itmp3 /* restore address for method pointer */
345 add $((4+2)*4+sizestackframeinfo),sp /* remove stack frame */
347 test v0,v0 /* check for exception */
348 je L_asm_call_jit_compiler_exception
350 test itmp3,itmp3 /* was this a JIT call? */
353 mov v0,(itmp3) /* save the new method pointer */
356 jmp *v0 /* ...and now call the new method */
358 L_asm_call_jit_compiler_exception:
359 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
360 call builtin_asm_get_exceptionptrptr
361 mov v0,itmp2 /* v0 == itmp1 */
363 lea _exceptionptr,itmp2
365 mov (itmp2),xptr /* get the exception pointer */
366 movl $0,(itmp2) /* clear the exception pointer */
368 pop xpc /* get return address */
369 sub $2,xpc /* faulting address is ra - 2 */
370 jmp asm_handle_exception
373 /* asm_handle_exception ********************************************************
375 * This function handles an exception. It does not use the usual calling *
376 * conventions. The exception pointer is passed in REG_ITMP1 and the *
377 * pc from the exception raising position is passed in REG_ITMP2. It searches *
378 * the local exception table for a handler. If no one is found, it unwinds *
379 * stacks and continues searching the callers. *
381 *******************************************************************************/
383 asm_handle_nat_exception:
384 add $4,sp /* clear return address of native stub*/
386 asm_handle_exception:
387 sub $((ARG_CNT+TMP_CNT)*4),sp /* create maybe-leaf stackframe */
389 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
390 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
392 mov $((ARG_CNT+TMP_CNT)*4),itmp3/* prepare a3 for handle_exception */
393 mov $1,t0 /* set maybe-leaf flag */
395 L_asm_handle_exception_stack_loop:
396 sub $(10*4),sp /* create stackframe */
397 mov xptr,4*4(sp) /* save exception pointer */
398 mov xpc,5*4(sp) /* save exception pc */
399 add sp,itmp3 /* calculate Java sp into a3... */
401 mov itmp3,7*4(sp) /* ...and save it */
402 mov t0,8*4(sp) /* save maybe-leaf flag */
404 mov xpc,0*4(sp) /* pass exception pc */
405 call codegen_findmethod
406 mov v0,6*4(sp) /* save data segment pointer */
408 mov 4*4(sp),itmp3 /* pass exception pointer */
410 mov 5*4(sp),itmp3 /* pass exception pc */
412 mov v0,2*4(sp) /* pass data segment pointer */
413 mov 7*4(sp),itmp3 /* pass Java stack pointer */
415 call exceptions_handle_exception
418 jz L_asm_handle_exception_not_catched
420 mov v0,xpc /* move handlerpc into xpc */
421 mov 4*4(sp),xptr /* restore exception pointer */
422 mov 8*4(sp),t0 /* get maybe-leaf flag */
423 add $(10*4),sp /* free stackframe */
425 test t0,t0 /* test for maybe-leaf flag */
426 jz L_asm_handle_exception_no_leaf
428 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
429 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
431 add $((ARG_CNT+TMP_CNT)*4),sp /* remove maybe-leaf stackframe */
433 L_asm_handle_exception_no_leaf:
434 jmp *xpc /* jump to exception handler */
436 L_asm_handle_exception_not_catched:
437 mov 4*4(sp),xptr /* restore exception pointer */
438 mov 6*4(sp),itmp3 /* restore data segment pointer */
439 mov 8*4(sp),t0 /* get maybe-leaf flag */
440 add $(10*4),sp /* free stackframe */
443 jz L_asm_handle_exception_no_leaf_stack
445 add $((ARG_CNT+TMP_CNT)*4),sp /* remove maybe-leaf stackframe */
446 xor t0,t0 /* clear the maybe-leaf flag */
448 L_asm_handle_exception_no_leaf_stack:
449 mov FrameSize(itmp3),itmp2 /* get frame size */
450 add sp,itmp2 /* pointer to save area */
452 push xptr /* we are out of registers */
454 mov IntSave(itmp3),itmp1 /* itmp1 = saved int register count */
469 shl $2,itmp1 /* multiply by 4 bytes */
474 mov FltSave(itmp3),itmp1 /* itmp1 = saved flt register count */
499 pop xptr /* restore exception pointer */
500 mov FrameSize(itmp3),itmp2 /* get frame size */
501 add itmp2,sp /* unwind stack */
503 pop xpc /* the new xpc is return address */
504 sub $2,xpc /* subtract 2-bytes for call */
506 xor itmp3,itmp3 /* prepare a3 for handle_exception */
508 jmp L_asm_handle_exception_stack_loop
511 /* asm_wrapper_patcher *********************************************************
517 16 pointer to virtual java_objectheader
518 12 last byte of machine code (xmcode)
519 8 machine code (which is patched back later)
520 4 unresolved field reference
521 0 patcher function pointer to call
523 *******************************************************************************/
526 sub $((2+4)*4+sizestackframeinfo),sp /* create stack frame */
528 mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
529 mov itmp2,(1+4)*4(sp) /* may be used by some instructions */
531 mov sp,itmp1 /* create stackframe info */
533 mov itmp1,0*4(sp) /* stackframeinfo pointer */
534 movl $0,1*4(sp) /* if pv is NULL, use findmethod */
536 add $((6+2+4)*4+sizestackframeinfo),itmp2
538 mov ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
540 call stacktrace_create_inline_stackframeinfo
542 mov sp,itmp1 /* pass stack pointer */
543 add $((1+2+4)*4+sizestackframeinfo),itmp1 /* skip function pointer */
545 mov (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer */
546 call *itmp1 /* call the patcher function */
547 mov v0,1*4(sp) /* save return value */
549 mov sp,itmp1 /* remove stackframe info */
551 mov itmp1,0*4(sp) /* stackframeinfo pointer */
552 call stacktrace_remove_stackframeinfo
554 mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
555 mov (1+4)*4(sp),itmp2 /* may be used by some instructions */
556 mov 1*4(sp),itmp3 /* restore return value */
558 add $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
559 test itmp3,itmp3 /* exception thrown? */
560 jz L_asm_wrapper_patcher_exception
561 ret /* call new patched code */
563 L_asm_wrapper_patcher_exception:
564 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
565 call builtin_asm_get_exceptionptrptr
568 lea _exceptionptr,itmp2
570 mov (itmp2),xptr /* get the exception pointer */
571 movl $0,(itmp2) /* clear the exception pointer */
573 pop xpc /* get and remove return address */
574 jmp asm_handle_exception
577 /************************ function asm_builtin_x2x *****************************
579 * Wrapper functions for corner cases *
581 *******************************************************************************/
612 /******************* function asm_initialize_thread_stack **********************
614 * initialized a thread stack *
615 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
617 *******************************************************************************/
619 asm_initialize_thread_stack:
620 mov 8(%esp),%eax /* (to)->stackEnd */
621 sub $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
633 mov 4(%esp),%edx /* save (u1*) (func) */
636 ret /* return restorepoint in %eax */
639 /******************* function asm_perform_threadswitch *************************
641 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
643 * performs a threadswitch *
645 *******************************************************************************/
647 asm_perform_threadswitch:
659 mov 36(%esp),%eax /* save current return address */
662 mov 40(%esp),%eax /* first argument **from */
665 mov 48(%esp),%eax /* third argument **stackTop */
668 mov 44(%esp),%eax /* second argument **to */
669 mov 0(%eax),%esp /* load new stack pointer */
675 /* skip stack pointer */
680 add $32,%esp /* leave return address on stack */
684 /********************* function asm_switchstackandcall *************************
686 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
689 * Switches to a new stack, calls a function and switches back. *
690 * a0 new stack pointer *
691 * a1 function pointer *
692 * a2 pointer to variable where stack top should be stored *
693 * a3 pointer to user data, is passed to the function *
695 *******************************************************************************/
697 asm_switchstackandcall:
698 mov 4(%esp),%edx /* first argument *stack */
699 sub $8,%edx /* allocate new stack */
701 mov (%esp),%eax /* save return address on new stack */
704 mov %esp,4(%edx) /* save old stack pointer on new stack */
706 mov 12(%esp),%eax /* third argument **stacktopsave */
707 mov %esp,(%eax) /* save old stack pointer to variable */
709 mov 8(%esp),%eax /* load function pointer */
710 mov 16(%esp),%ecx /* fourth argument *p */
712 mov %edx,%esp /* switch to new stack */
715 mov %ecx,0(%esp) /* pass pointer */
716 call *%eax /* and call function */
719 mov (%esp),%edx /* load return address */
720 mov 4(%esp),%esp /* switch to old stack */
725 asm_getclassvalues_atomic:
727 mov 4(%esp),%ecx /* super */
728 mov 8(%esp),%edx /* sub */
730 mov offbaseval(%ecx),%eax
731 mov offdiffval(%ecx),%ecx
732 mov offbaseval(%edx),%edx
735 mov 16(%esp),%ebx /* out */
736 mov %eax,offcast_super_baseval(%ebx)
737 mov %ecx,offcast_super_diffval(%ebx)
738 mov %edx,offcast_sub_baseval(%ebx)
744 asm_criticalsections:
745 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
759 * These are local overrides for various environment variables in Emacs.
760 * Please do not remove this and leave it at the end of the file, where
761 * Emacs will automagically detect them.
762 * ---------------------------------------------------------------------
765 * indent-tabs-mode: t