1 /* -*- mode: asm; tab-width: 4 -*- */
2 /****************************** asmpart.c **************************************
4 * It contains the Java-C interface functions for i386 processors. *
6 * Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst *
8 * See file COPYRIGHT for information on usage and disclaimer of warranties *
10 * Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at *
11 * Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at *
12 * Christian Thalinger *
14 * Last Change: $Id: asmpart.S 557 2003-11-02 22:51:59Z twisti $ *
16 *******************************************************************************/
23 /********************* exported functions and variables ***********************/
25 .globl has_no_x_instr_set
26 .globl asm_calljavamethod
27 .globl asm_calljavafunction
28 .globl asm_call_jit_compiler
29 .globl asm_dumpregistersandcall
30 .globl asm_handle_exception
31 .globl asm_handle_nat_exception
32 .globl asm_builtin_checkcast
33 .globl asm_builtin_checkarraycast
34 .globl asm_builtin_anewarray
35 .globl asm_builtin_newarray_array
36 .globl asm_builtin_aastore
37 .globl asm_builtin_monitorenter
38 .globl asm_builtin_monitorexit
39 .globl asm_builtin_ldiv
40 .globl asm_builtin_lrem
41 .globl asm_builtin_f2i
42 .globl asm_builtin_f2l
43 .globl asm_builtin_d2i
44 .globl asm_builtin_d2l
45 .globl asm_builtin_arrayinstanceof
46 .globl asm_perform_threadswitch
47 .globl asm_initialize_thread_stack
48 .globl asm_switchstackandcall
49 .globl asm_getcallingmethod
50 .globl asm_builtin_trace
51 .globl asm_builtin_exittrace
53 /*************************** imported functions *******************************/
56 .globl builtin_monitorexit
57 .globl builtin_throw_exception
58 .globl builtin_trace_exception
59 .globl class_java_lang_Object
62 /*********************** function has_no_x_instr_set ***************************
64 * determines if the byte support instruction set (21164a and higher) *
67 * Use it on i386 architecture to init the fpu. *
69 *******************************************************************************/
72 finit /* intitialize the fpu */
74 pushl $0x027f /* Round to nearest, 53-bit mode, exceptions masked */
78 xor %eax,%eax /* result code 0 (not used for i386) */
82 /********************* function asm_calljavamethod *****************************
84 * This function calls a Java-method (which possibly needs compilation) *
85 * with up to 4 parameters. *
87 * This functions calls the JIT-compiler which eventually translates the *
88 * method into machine code. *
90 * An possibly throwed exception will be returned to the caller as function *
91 * return value, so the java method cannot return a fucntion value (this *
92 * function usually calls 'main' and '<clinit>' which do not return a *
96 * javaobject_header *asm_calljavamethod (methodinfo *m, *
97 * void *arg1, void *arg2, void *arg3, void *arg4); *
99 *******************************************************************************/
101 #define MethodPointer -4
107 #define ExTableSize -28
108 #define ExTableStart -28
110 #define ExEntrySize -16
113 #define ExHandlerPC -12
114 #define ExCatchType -16
117 .ascii "calljavamethod\0\0"
121 .long 0 /* catch type all */
122 .long calljava_xhandler /* handler pc */
123 .long calljava_xhandler /* end pc */
124 .long asm_calljavamethod /* start pc */
125 .long 1 /* extable size */
126 .long 0 /* fltsave */
127 .long 0 /* intsave */
130 .long 32 /* frame size */
131 .long 0 /* method pointer (pointer to name) */
134 pushl %ebp /* allocate stack space */
137 subl $32,%esp /* pass the remaining parameters */
140 movl %edx,28(%esp) /* convert parms to 8 byte */
156 movl 8(%ebp),%eax /* move function pointer to %eax */
158 lea asm_call_jit_compiler,%ecx
159 call *%ecx /* call JIT compiler */
165 leave /* free stack space */
169 pushl %eax /* pass exception pointer */
170 call builtin_throw_exception
177 /********************* function asm_calljavafunction ***************************
179 * This function calls a Java-method (which possibly needs compilation) *
180 * with up to 4 address parameters. *
182 * This functions calls the JIT-compiler which eventually translates the *
183 * method into machine code. *
186 * javaobject_header *asm_calljavamethod (methodinfo *m, *
187 * void *arg1, void *arg2, void *arg3, void *arg4); *
189 *******************************************************************************/
192 .ascii "calljavafunction\0\0"
196 .long 0 /* catch type all */
197 .long calljava_xhandler2 /* handler pc */
198 .long calljava_xhandler2 /* end pc */
199 .long asm_calljavafunction /* start pc */
200 .long 1 /* extable size */
201 .long 0 /* fltsave */
202 .long 0 /* intsave */
205 .long 32 /* frame size */
206 .long 0 /* method pointer (pointer to name) */
208 asm_calljavafunction:
209 pushl %ebp /* allocate stack space */
212 subl $32,%esp /* pass the remaining parameters */
215 movl %edx,28(%esp) /* convert parms to 8 byte */
231 movl 8(%ebp),%eax /* move function pointer to %eax */
233 lea asm_call_jit_compiler,%ecx
234 call *%ecx /* call JIT compiler */
243 pushl %eax /* pass exception pointer */
244 call builtin_throw_exception
251 /****************** function asm_call_jit_compiler *****************************
253 * invokes the compiler for untranslated JavaVM methods. *
255 * Register R0 contains a pointer to the method info structure (prepared *
256 * by createcompilerstub). Using the return address in R26 and the *
257 * offset in the LDA instruction or using the value in methodptr R28 the *
258 * patching address for storing the method address can be computed: *
260 * method address was either loaded using *
262 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
263 * i386_call_reg(REG_ITMP2) *
267 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
268 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
269 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
270 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
271 * i386_call_reg(REG_ITMP1) *
273 * in the static case the method pointer can be computed using the *
274 * return address and the lda function following the jmp instruction *
276 *******************************************************************************/
279 asm_call_jit_compiler:
281 push %ebx /* save register */
284 mov 12(%esp),%ebp /* get return address (2 push) */
285 mov -1(%ebp),%bl /* get function code */
286 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%edx)? */
287 jne L_not_static_special
289 sub $6,%ebp /* calculate address of immediate */
290 jmp L_call_jit_compile
292 L_not_static_special:
293 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%eax) */
294 jne L_not_virtual_interface
296 sub $6,%ebp /* calculate address of offset */
297 mov (%ebp),%ebp /* get offset */
298 add %edx,%ebp /* add base address to get method address */
299 jmp L_call_jit_compile
301 L_not_virtual_interface: /* a call from asm_calljavamethod */
305 push %ebp /* save address for method pointer */
307 push %eax /* push methodpointer on stack */
311 pop %ebp /* restore address for method pointer */
312 test %ebp,%ebp /* is address == 0 (asm_calljavamethod) */
315 mov %eax,(%ebp) /* and now save the new pointer */
319 pop %ebx /* restore registers */
322 jmp *%eax /* ...and now call the new method */
326 /****************** function asm_dumpregistersandcall **************************
328 * This funtion saves all callee saved registers and calls the function *
329 * which is passed as parameter. *
331 * This function is needed by the garbage collector, which needs to access *
332 * all registers which are stored on the stack. Unused registers are *
333 * cleared to avoid interferances with the GC. *
335 * void asm_dumpregistersandcall (functionptr f); *
337 *******************************************************************************/
339 asm_dumpregistersandcall:
348 mov 8(%ebp),%eax /* load function pointer */
349 call *%eax /* call function */
359 /********************* function asm_handle_exception ***************************
361 * This function handles an exception. It does not use the usual calling *
362 * conventions. The exception pointer is passed in REG_ITMP1 and the *
363 * pc from the exception raising position is passed in REG_ITMP2. It searches *
364 * the local exception table for a handler. If no one is found, it unwinds *
365 * stacks and continues searching the callers. *
367 * void asm_handle_exception (exceptionptr, exceptionpc); *
369 *******************************************************************************/
371 asm_handle_nat_exception:
372 add $4,%esp /* clear return address of native stub */
374 asm_handle_exception:
376 push %edx /* get the data segment ptr */
385 push %eax /* save exception pointer */
387 push %edx /* save exception pc */
388 push %ecx /* save data segment pointer */
397 movl %eax,(%esp) /* exception pointer */
399 movl MethodPointer(%ecx),%eax /* method pointer */
402 movl %edx,8(%esp) /* exception pc */
403 movl $1,12(%esp) /* set no unwind flag */
404 call builtin_trace_exception
408 movl -12(%ebp),%esi /* %esi = data segment pointer */
409 movl ExTableSize(%esi),%ecx /* %ecx = exception table size */
410 test %ecx,%ecx /* if empty table skip */
413 lea ExTableStart(%esi),%edi /* %edi = start of exception table */
414 movl -4(%ebp),%eax /* get xptr */
417 movl -8(%ebp),%edx /* get xpc */
419 movl ExStartPC(%edi),%ebx /* %ebx = exception start pc */
420 cmpl %edx,%ebx /* %ebx = (startpc <= xpc) */
421 jg ex_table_cont /* if (false) continue */
422 movl ExEndPC(%edi),%ebx /* %ebx = exception end pc */
423 cmpl %ebx,%edx /* %ebx = (xpc < endpc) */
424 jge ex_table_cont /* if (false) continue */
425 movl ExCatchType(%edi),%ebx /* arg1 = exception catch type */
426 test %ebx,%ebx /* NULL catches everything */
429 movl offobjvftbl(%eax),%esi /* %esi = vftblptr(xptr) */
430 movl offobjvftbl(%ebx),%ebx /* %ebx = vftblptr(catchtype) class (not obj) */
431 movl offbaseval(%esi),%esi /* %esi = baseval(xptr) */
432 movl offbaseval(%ebx),%edx /* %edx = baseval(catchtype) */
433 movl offdiffval(%ebx),%ebx /* %ebx = diffval(catchtype) */
434 subl %edx,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
435 cmpl %ebx,%esi /* xptr is instanceof catchtype */
439 movl ExHandlerPC(%edi),%edx
445 popl %eax /* pop %ecx (dummy) */
446 popl %eax /* pop %edx (dummy) */
447 popl %eax /* pop %eax */
454 lea ExEntrySize(%edi),%edi
463 popl %ecx /* restore data segment pointer */
465 popl %eax /* restore exception pointer */
468 movl %eax,%edi /* save exception pointer */
471 movl IsSync(%ecx),%eax /* %eax = SyncOffset */
472 test %eax,%eax /* if zero no monitorexit */
477 pusha /* save regs */
479 call builtin_monitorexit
481 popa /* restore regs */
484 movl FrameSize(%ecx),%eax /* %eax = frame size */
485 addl %eax,%esp /* unwind stack */
486 movl %esp,%eax /* %eax = pointer to save area */
488 movl IntSave(%ecx),%edx /* %edx = saved int register count */
500 shll $3,%edx /* multiply by 8 bytes */
504 movl FltSave(%ecx),%edx /* %edx = saved flt register count */
531 popl %edx /* the new xpc is return address */
540 pushl %edx /* get the new data segment ptr */
551 movl %edi,%eax /* restore saved exception pointer */
556 pushl %eax /* save exception pointer */
557 pushl %edx /* save exception pc */
558 pushl %ecx /* save data segment pointer */
566 /********************* function asm_builtin_monitorenter ***********************
568 * Does null check and calls monitorenter or throws an exception *
570 *******************************************************************************/
572 asm_builtin_monitorenter:
574 je nb_monitorenter /* if (null) throw exception */
575 jmp builtin_monitorenter /* else call builtin_monitorenter */
578 popl %edx /* delete return address */
579 subl $2,%edx /* faulting address is return adress - 2 */
580 movl proto_java_lang_NullPointerException,%eax
581 jmp asm_handle_exception
584 /********************* function asm_builtin_monitorexit ************************
586 * Does null check and calls monitorexit or throws an exception *
588 *******************************************************************************/
590 asm_builtin_monitorexit:
592 je nb_monitorexit /* if (null) throw exception */
593 jmp builtin_monitorexit /* else call builtin_monitorenter */
596 popl %edx /* delete return address */
597 subl $2,%edx /* faulting address is return adress - 2 */
598 movl proto_java_lang_NullPointerException,%eax
599 jmp asm_handle_exception
602 /************************ function asm_builtin_ldiv ****************************
604 * Does null check and calls ldiv or throws an exception *
606 *******************************************************************************/
611 test %eax,%eax /* if (null) throw exception */
617 popl %edx /* delete return address */
618 subl $2,%edx /* faulting address is return adress - 2 */
620 movl proto_java_lang_ArithmeticException,%eax
621 jmp asm_handle_exception
624 /************************ function asm_builtin_lrem ****************************
626 * Does null check and calls lrem or throws an exception *
628 *******************************************************************************/
633 test %eax,%eax /* if (null) throw exception */
639 popl %edx /* delete return address */
640 subl $2,%edx /* faulting address is return adress - 2 */
642 movl proto_java_lang_ArithmeticException,%eax
643 jmp asm_handle_exception
646 /************************ function asm_builtin_x2x *****************************
648 * Wrapper functions for corner cases *
650 *******************************************************************************/
681 /*********************** function new_builtin_checkcast ************************
683 * Does the cast check and eventually throws an exception *
685 *******************************************************************************/
687 asm_builtin_checkcast:
693 /******************* function asm_builtin_checkarraycast ***********************
695 * Does the cast check and eventually throws an exception *
697 *******************************************************************************/
699 asm_builtin_checkarraycast:
700 subl $8,%esp /* build stack frame (2 * 4 bytes) */
702 movl 12(%esp),%eax /* 8 (frame) + 4 (return) */
703 movl %eax,(%esp) /* save object pointer */
708 call builtin_checkarraycast /* builtin_checkarraycast */
710 test %eax,%eax /* if (false) throw exception */
713 movl 12(%esp),%eax /* return object pointer */
720 popl %edx /* delete return address */
721 subl $2,%edx /* faulting address is return adress - 2 */
723 movl proto_java_lang_ClassCastException,%eax
724 jmp asm_handle_exception
727 /******************* function asm_builtin_anewarray ****************************
729 * Does the cast check and eventually throws an exception *
731 *******************************************************************************/
733 asm_builtin_anewarray:
734 subl $8,%esp /* build stack frame (2 * 4 bytes) */
742 call builtin_anewarray
748 /******************* function asm_builtin_newarray_array ***********************
750 * Does the cast check and eventually throws an exception *
752 *******************************************************************************/
754 asm_builtin_newarray_array:
755 subl $8,%esp /* build stack frame (2 * 4 bytes) */
763 call builtin_newarray_array
769 /******************* function asm_builtin_aastore ******************************
771 * Does the cast check and eventually throws an exception *
773 *******************************************************************************/
776 subl $12,%esp /* build stack frame (3 * 4 bytes) */
778 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
779 test %eax,%eax /* if null pointer throw exception */
782 movl offarraysize(%eax),%edx /* load size */
783 movl 24(%esp),%ecx /* index */
784 cmpl %edx,%ecx /* do bound check */
785 ja nb_aastore_bound /* if out of bounds throw exception */
787 shll $2,%ecx /* index * 4 */
788 addl %eax,%ecx /* add index * 4 to arrayref */
790 movl %ecx,8(%esp) /* save store position */
792 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
795 movl 32(%esp),%eax /* object is second argument */
798 call builtin_canstore /* builtin_canstore(arrayref,object) */
800 test %eax,%eax /* if (false) throw exception */
805 movl %eax,offobjarrdata(%ecx)/* store objectptr in array */
812 popl %edx /* delete return address */
813 subl $2,%edx /* faulting address is return adress - 2 */
815 movl proto_java_lang_NullPointerException,%eax
816 jmp asm_handle_exception
820 popl %edx /* delete return address */
821 subl $2,%edx /* faulting address is return adress - 2 */
823 movl proto_java_lang_ArrayIndexOutOfBoundsException,%eax
824 jmp asm_handle_exception
828 popl %edx /* delete return address */
829 subl $2,%edx /* faulting address is return adress - 2 */
831 movl proto_java_lang_ArrayStoreException,%eax
832 jmp asm_handle_exception
835 /******************* function asm_builtin_arrayinstanceof **********************
837 * Does the instanceof check of arrays *
839 *******************************************************************************/
841 asm_builtin_arrayinstanceof:
842 subl $8,%esp /* build stack frame (2 * 4 bytes) */
850 call builtin_arrayinstanceof
856 /******************* function asm_initialize_thread_stack **********************
858 * initialized a thread stack *
859 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
861 *******************************************************************************/
863 asm_initialize_thread_stack:
864 movl 8(%esp),%eax /* (to)->stackEnd */
865 subl $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
877 movl 4(%esp),%edx /* save (u1*) (func) */
880 ret /* return restorepoint in %eax */
883 /******************* function asm_perform_threadswitch *************************
885 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
887 * performs a threadswitch *
889 *******************************************************************************/
891 asm_perform_threadswitch:
903 movl 36(%esp),%eax /* save current return address */
906 movl 40(%esp),%eax /* first argument **from */
909 movl 48(%esp),%eax /* third argument **stackTop */
912 movl 44(%esp),%eax /* second argument **to */
913 movl 0(%eax),%esp /* load new stack pointer */
919 /* skip stack pointer */
924 addl $32,%esp /* leave return address on stack */
928 /********************* function asm_switchstackandcall *************************
930 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
933 * Switches to a new stack, calls a function and switches back. *
934 * a0 new stack pointer *
935 * a1 function pointer *
936 * a2 pointer to variable where stack top should be stored *
937 * a3 pointer to user data, is passed to the function *
939 *******************************************************************************/
941 asm_switchstackandcall:
942 movl 4(%esp),%edx /* first argument *stack */
943 subl $8,%edx /* allocate new stack */
945 movl (%esp),%eax /* save return address on new stack */
948 movl %esp,4(%edx) /* save old stack pointer on new stack */
950 movl 12(%esp),%eax /* third argument **stacktopsave */
951 movl %esp,(%eax) /* save old stack pointer to variable */
953 movl 8(%esp),%eax /* load function pointer */
954 movl 16(%esp),%ecx /* fourth argument *p */
956 movl %edx,%esp /* switch to new stack */
959 movl %ecx,0(%esp) /* pass pointer */
960 call *%eax /* and call function */
963 movl (%esp),%edx /* load return address */
964 movl 4(%esp),%esp /* switch to old stack */
969 /********************* function asm_getcallingmethod ***************************
971 * classinfo *asm_getcallingmethod (); *
973 * goes back stack frames to get the calling method *
979 *******************************************************************************/
981 asm_getcallingmethod:
987 /*********************** function asm_builtin_trace ****************************
989 * Intended to be called from the native stub. Saves all argument registers *
990 * and calls builtin_trace_args. *
992 *******************************************************************************/
996 subl $68,%esp /* 4 + 8 * 4 + 68 = 104 */
1041 call builtin_trace_args
1048 /********************* function asm_builtin_exittrace **************************
1050 * Intended to be called from the native stub. Saves return value and calls *
1051 * builtin_displaymethodstop. *
1053 *******************************************************************************/
1055 asm_builtin_exittrace:
1059 movl 60(%esp),%eax /* 4 + 8 * 4 + 24 = 60 */
1075 call builtin_displaymethodstop