1 /* jit/i386/asmpart.S - Java-C interface functions for i386
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
32 $Id: asmpart.S 771 2003-12-13 23:11:08Z stefan $
39 /* data segment offsets */
41 #define MethodPointer -4
47 #define ExTableSize -28
48 #define ExTableStart -28
50 #define ExEntrySize -16
53 #define ExHandlerPC -12
54 #define ExCatchType -16
60 /********************* exported functions and variables ***********************/
62 .globl has_no_x_instr_set
63 .globl asm_calljavafunction
64 .globl asm_calljavafunction2
65 .globl asm_calljavafunction2long
66 .globl asm_calljavafunction2double
68 .globl asm_call_jit_compiler
69 .globl asm_dumpregistersandcall
70 .globl asm_handle_builtin_exception
71 .globl asm_handle_nat_exception
72 .globl asm_handle_exception
73 .globl asm_builtin_checkcast
74 .globl asm_builtin_checkarraycast
75 .globl asm_builtin_newarray
76 .globl asm_builtin_anewarray
77 .globl asm_builtin_newarray_array
78 .globl asm_builtin_aastore
79 .globl asm_builtin_monitorenter
80 .globl asm_builtin_monitorexit
81 .globl asm_builtin_ldiv
82 .globl asm_builtin_lrem
83 .globl asm_builtin_f2i
84 .globl asm_builtin_f2l
85 .globl asm_builtin_d2i
86 .globl asm_builtin_d2l
87 .globl asm_builtin_arrayinstanceof
88 .globl asm_perform_threadswitch
89 .globl asm_initialize_thread_stack
90 .globl asm_switchstackandcall
91 .globl asm_getcallingmethod
92 .globl asm_builtin_trace
93 .globl asm_builtin_exittrace
96 /*************************** imported functions *******************************/
99 .globl builtin_monitorexit
100 .globl builtin_throw_exception
101 .globl builtin_trace_exception
102 .globl class_java_lang_Object
104 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
109 /*********************** function has_no_x_instr_set ***************************
111 * determines if the byte support instruction set (21164a and higher) *
114 * Use it on i386 architecture to init the fpu. *
116 *******************************************************************************/
119 finit /* intitialize the fpu */
121 pushl $0x027f /* Round to nearest, 53-bit mode, exceptions masked */
125 xor %eax,%eax /* result code 0 (not used for i386) */
129 /********************* function asm_calljavafunction ***************************
131 * This function calls a Java-method (which possibly needs compilation) *
132 * with up to 4 address parameters. *
134 * This functions calls the JIT-compiler which eventually translates the *
135 * method into machine code. *
138 * javaobject_header *asm_calljavamethod (methodinfo *m, *
139 * void *arg1, void *arg2, void *arg3, void *arg4); *
141 *******************************************************************************/
144 .ascii "calljavafunction\0\0"
147 .long 0 /* catch type all */
148 .long calljava_xhandler2 /* handler pc */
149 .long calljava_xhandler2 /* end pc */
150 .long asm_calljavafunction /* start pc */
151 .long 1 /* extable size */
152 .long 0 /* fltsave */
153 .long 0 /* intsave */
156 .long 32 /* frame size */
157 .long 0 /* method pointer (pointer to name) */
159 asm_calljavafunction:
160 push %ebp /* allocate stack space */
163 push %ebx /* save registers */
167 sub $32,%esp /* pass the remaining parameters */
170 mov %edx,28(%esp) /* convert parms to 8 byte */
186 mov 8(%ebp),%eax /* move function pointer to %eax */
188 lea asm_call_jit_compiler,%edx
189 call *%edx /* call JIT compiler */
195 pop %edi /* restore registers */
202 push %eax /* pass exception pointer */
203 call builtin_throw_exception
207 pop %edi /* restore registers */
215 /********************* function asm_calljavafunction ***************************
217 * This function calls a Java-method (which possibly needs compilation) *
218 * with up to 4 address parameters. *
220 * This functions calls the JIT-compiler which eventually translates the *
221 * method into machine code. *
224 * javaobject_header *asm_calljavamethod (methodinfo *m, *
225 * void *arg1, void *arg2, void *arg3, void *arg4); *
227 *******************************************************************************/
230 .ascii "calljavafunction2\0\0"
233 .long 0 /* catch type all */
234 .long calljava_xhandler3 /* handler pc */
235 .long calljava_xhandler3 /* end pc */
236 .long asm_calljavafunction2 /* start pc */
237 .long 1 /* extable size */
238 .long 0 /* fltsave */
239 .long 0 /* intsave */
242 .long 32 /* frame size */
243 .long 0 /* method pointer (pointer to name) */
245 /********************* function asm_calljavafunction ***************************
247 * This function calls a Java-method (which possibly needs compilation) *
248 * with up to 4 address parameters. *
250 * This functions calls the JIT-compiler which eventually translates the *
251 * method into machine code. *
254 * javaobject_header *asm_calljavamethod (methodinfo *m, *
255 * void *arg1, void *arg2, void *arg3, void *arg4); *
257 *******************************************************************************/
260 .ascii "calljavafunction2double\0\0"
263 .long 0 /* catch type all */
264 .long calljava_xhandler3 /* handler pc */
265 .long calljava_xhandler3 /* end pc */
266 .long asm_calljavafunction2double /* start pc */
267 .long 1 /* extable size */
268 .long 0 /* fltsave */
269 .long 0 /* intsave */
272 .long 32 /* frame size */
273 .long 0 /* method pointer (pointer to name) */
275 /********************* function asm_calljavafunction ***************************
277 * This function calls a Java-method (which possibly needs compilation) *
278 * with up to 4 address parameters. *
280 * This functions calls the JIT-compiler which eventually translates the *
281 * method into machine code. *
284 * javaobject_header *asm_calljavamethod (methodinfo *m, *
285 * void *arg1, void *arg2, void *arg3, void *arg4); *
287 *******************************************************************************/
290 .ascii "calljavafunction2long\0\0"
293 .long 0 /* catch type all */
294 .long calljava_xhandler3 /* handler pc */
295 .long calljava_xhandler3 /* end pc */
296 .long asm_calljavafunction2long /* start pc */
297 .long 1 /* extable size */
298 .long 0 /* fltsave */
299 .long 0 /* intsave */
302 .long 32 /* frame size */
303 .long 0 /* method pointer (pointer to name) */
306 asm_calljavafunction2:
307 asm_calljavafunction2double:
308 asm_calljavafunction2long:
309 push %ebp /* save ebp */
311 mov %esp,%eax /* save stackptr */
314 push %ebx /* save registers */
320 mov sizejniblock*3+offjniitem+4(%ebp),%ebx
322 mov sizejniblock*3+offjniitem(%ebp),%ebx
325 mov sizejniblock*2+offjniitem+4(%ebp),%ebx
327 mov sizejniblock*2+offjniitem(%ebp),%ebx
331 mov sizejniblock+offjniitem+4(%ebp),%ebx
333 mov sizejniblock+offjniitem(%ebp),%ebx
336 mov offjniitem+4(%ebp),%ebx
338 mov offjniitem(%ebp),%ebx
342 mov 8(%ebp),%eax /* move function pointer to %eax */
344 lea asm_call_jit_compiler,%edx
345 call *%edx /* call JIT compiler */
351 pop %edi /* restore registers */
358 push %eax /* pass exception pointer */
359 call builtin_throw_exception
363 pop %edi /* restore registers */
370 /****************** function asm_call_jit_compiler *****************************
372 * invokes the compiler for untranslated JavaVM methods. *
374 * Register R0 contains a pointer to the method info structure (prepared *
375 * by createcompilerstub). Using the return address in R26 and the *
376 * offset in the LDA instruction or using the value in methodptr R28 the *
377 * patching address for storing the method address can be computed: *
379 * method address was either loaded using *
381 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
382 * i386_call_reg(REG_ITMP2) *
386 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
387 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
388 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
389 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
390 * i386_call_reg(REG_ITMP1) *
392 * in the static case the method pointer can be computed using the *
393 * return address and the lda function following the jmp instruction *
395 *******************************************************************************/
398 asm_call_jit_compiler:
399 push %ebx /* save register */
402 mov 8(%esp),%ebp /* get return address (2 push) */
403 mov -1(%ebp),%bl /* get function code */
404 cmp $0xd1,%bl /* called with `call *REG_ITMP2' (%ecx)? */
405 jne L_not_static_special
407 sub $6,%ebp /* calculate address of immediate */
408 jmp L_call_jit_compile
410 L_not_static_special:
411 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%eax) */
412 jne L_not_virtual_interface
414 sub $6,%ebp /* calculate address of offset */
415 mov (%ebp),%ebp /* get offset */
416 add %ecx,%ebp /* add base address to get method address */
417 jmp L_call_jit_compile
419 L_not_virtual_interface: /* a call from asm_calljavamethod */
423 push %ebp /* save address for method pointer */
425 push %eax /* push methodpointer on stack */
429 pop %ebp /* restore address for method pointer */
430 test %ebp,%ebp /* is address == 0 (asm_calljavamethod) */
433 mov %eax,(%ebp) /* and now save the new pointer */
436 pop %ebp /* restore registers */
439 jmp *%eax /* ...and now call the new method */
443 /****************** function asm_dumpregistersandcall **************************
445 * This funtion saves all callee saved registers and calls the function *
446 * which is passed as parameter. *
448 * This function is needed by the garbage collector, which needs to access *
449 * all registers which are stored on the stack. Unused registers are *
450 * cleared to avoid interferances with the GC. *
452 * void asm_dumpregistersandcall (functionptr f); *
454 *******************************************************************************/
456 asm_dumpregistersandcall:
467 mov 4(%ebp),%eax /* load function pointer */
468 call *%eax /* call function */
480 /********************* function asm_handle_exception ***************************
482 * This function handles an exception. It does not use the usual calling *
483 * conventions. The exception pointer is passed in REG_ITMP1 and the *
484 * pc from the exception raising position is passed in REG_ITMP2. It searches *
485 * the local exception table for a handler. If no one is found, it unwinds *
486 * stacks and continues searching the callers. *
488 * void asm_handle_exception (exceptionptr, exceptionpc); *
490 *******************************************************************************/
492 asm_handle_builtin_exception:
493 add $4,%esp /* clear return address of this call */
494 mov (%esp),%eax /* get exceptionptr */
495 leave /* leave builtin function */
496 mov (%esp),%edx /* get exceptionpc */
497 sub $2,%edx /* size of builtin call */
498 jmp asm_handle_exception
500 asm_handle_nat_exception:
501 add $4,%esp /* clear return address of native stub */
503 asm_handle_exception:
507 push %eax /* save exception pointer */
508 push %ecx /* save exception pc */
510 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
514 call findmethod /* get the data segment ptr */
518 mov -8(%ebp),%ecx /* could be changed in findmethod */
520 push %edx /* save data segment pointer */
527 mov %eax,(%esp) /* exception pointer */
528 mov MethodPointer(%edx),%eax /* method pointer */
530 mov %ecx,8(%esp) /* exception pc */
531 movl $1,12(%esp) /* set no unwind flag */
532 call builtin_trace_exception
535 mov -12(%ebp),%esi /* %esi = data segment pointer */
536 mov ExTableSize(%esi),%ecx /* %ecx = exception table size */
537 test %ecx,%ecx /* if empty table skip */
540 lea ExTableStart(%esi),%edi /* %edi = start of exception table*/
541 mov -4(%ebp),%eax /* get xptr */
544 mov -8(%ebp),%edx /* get xpc */
546 mov ExStartPC(%edi),%ebx /* %ebx = exception start pc */
547 cmp %edx,%ebx /* %ebx = (startpc <= xpc) */
548 jg ex_table_cont /* if (false) continue */
549 mov ExEndPC(%edi),%ebx /* %ebx = exception end pc */
550 cmp %ebx,%edx /* %ebx = (xpc < endpc) */
551 jge ex_table_cont /* if (false) continue */
552 mov ExCatchType(%edi),%ebx /* arg1 = exception catch type */
553 test %ebx,%ebx /* NULL catches everything */
556 mov offobjvftbl(%eax),%esi /* %esi = vftblptr(xptr) */
557 mov offclassvftbl(%ebx),%ebx /* %ebx = vftblptr(catchtype) class (not obj) */
558 mov offbaseval(%esi),%esi /* %esi = baseval(xptr) */
559 mov offbaseval(%ebx),%edx /* %edx = baseval(catchtype) */
560 mov offdiffval(%ebx),%ebx /* %ebx = diffval(catchtype) */
561 sub %edx,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
562 cmp %ebx,%esi /* xptr is instanceof catchtype */
566 mov ExHandlerPC(%edi),%edx
568 pop %edi /* restore registers */
571 add $8,%esp /* suck %ecx, %edx */
572 pop %eax /* restore xptr */
574 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
579 jmp *%edx /* jump to exception handler */
582 lea ExEntrySize(%edi),%edi
591 pop %edx /* restore data segment pointer */
596 push %eax /* save exception pointer */
599 mov IsSync(%edx),%eax /* %eax = SyncOffset */
600 test %eax,%eax /* if zero no monitorexit */
604 mov -4(%eax),%eax /* we have the xptr on the stack */
605 push %edx /* save regs */
607 call builtin_monitorexit
609 pop %edx /* restore regs */
613 add FrameSize(%edx),%eax /* %eax = frame size */
614 add $4,%eax /* we have the xptr on the stack */
616 mov IntSave(%edx),%ecx /* %ecx = saved int register count*/
638 shl $3,%ecx /* multiply by 8 bytes */
642 mov FltSave(%edx),%ecx /* %ecx = saved flt register count */
669 pop %eax /* restore exception pointer */
671 mov FrameSize(%edx),%ecx /* %ecx = frame size */
672 add %ecx,%esp /* unwind stack */
674 pop %ecx /* the new xpc is return address */
677 jmp asm_handle_exception
680 /********************* function asm_builtin_monitorenter ***********************
682 * Does null check and calls monitorenter or throws an exception *
684 *******************************************************************************/
686 asm_builtin_monitorenter:
688 je nb_monitorenter /* if (null) throw exception */
689 jmp builtin_monitorenter /* else call builtin_monitorenter */
692 popl %ecx /* delete return address */
693 subl $2,%ecx /* faulting address is return adress - 2 */
694 movl proto_java_lang_NullPointerException,%eax
695 jmp asm_handle_exception
698 /********************* function asm_builtin_monitorexit ************************
700 * Does null check and calls monitorexit or throws an exception *
702 *******************************************************************************/
704 asm_builtin_monitorexit:
707 je nb_monitorexit /* if (null) throw exception */
708 push %ecx /* save registers which could be used */
711 call builtin_monitorexit /* else call builtin_monitorenter */
713 pop %edx /* restore registers which could be used */
718 popl %ecx /* delete return address */
719 subl $2,%ecx /* faulting address is return adress - 2 */
720 movl proto_java_lang_NullPointerException,%eax
721 jmp asm_handle_exception
724 /************************ function asm_builtin_ldiv ****************************
726 * Does null check and calls ldiv or throws an exception *
728 *******************************************************************************/
733 test %eax,%eax /* if (null) throw exception */
739 popl %ecx /* delete return address */
740 subl $2,%ecx /* faulting address is return adress - 2 */
741 movl proto_java_lang_ArithmeticException,%eax
742 jmp asm_handle_exception
745 /************************ function asm_builtin_lrem ****************************
747 * Does null check and calls lrem or throws an exception *
749 *******************************************************************************/
754 test %eax,%eax /* if (null) throw exception */
760 popl %ecx /* delete return address */
761 subl $2,%ecx /* faulting address is return adress - 2 */
762 movl proto_java_lang_ArithmeticException,%eax
763 jmp asm_handle_exception
766 /************************ function asm_builtin_x2x *****************************
768 * Wrapper functions for corner cases *
770 *******************************************************************************/
801 /*********************** function new_builtin_checkcast ************************
803 * Does the cast check and eventually throws an exception *
805 *******************************************************************************/
807 asm_builtin_checkcast:
813 /******************* function asm_builtin_checkarraycast ***********************
815 * Does the cast check and eventually throws an exception *
817 *******************************************************************************/
819 asm_builtin_checkarraycast:
820 subl $8,%esp /* build stack frame (2 * 4 bytes) */
822 movl 12(%esp),%eax /* 8 (frame) + 4 (return) */
823 movl %eax,(%esp) /* save object pointer */
828 call builtin_checkarraycast /* builtin_checkarraycast */
830 test %eax,%eax /* if (false) throw exception */
833 movl 12(%esp),%eax /* return object pointer */
840 popl %ecx /* delete return address */
841 subl $2,%ecx /* faulting address is return adress - 2 */
842 movl proto_java_lang_ClassCastException,%eax
843 jmp asm_handle_exception
846 /******************* function asm_builtin_newarray *****************************
848 * Does the cast check and eventually throws an exception *
850 *******************************************************************************/
852 asm_builtin_newarray:
853 subl $8,%esp /* build stack frame (2 * 4 bytes) */
861 call builtin_newarray
867 /******************* function asm_builtin_aastore ******************************
869 * Does the cast check and eventually throws an exception *
871 *******************************************************************************/
874 subl $12,%esp /* build stack frame (3 * 4 bytes) */
876 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
877 test %eax,%eax /* if null pointer throw exception */
880 movl offarraysize(%eax),%edx /* load size */
881 movl 24(%esp),%ecx /* index */
882 cmpl %edx,%ecx /* do bound check */
883 ja nb_aastore_bound /* if out of bounds throw exception */
885 shll $2,%ecx /* index * 4 */
886 addl %eax,%ecx /* add index * 4 to arrayref */
888 movl %ecx,8(%esp) /* save store position */
890 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
893 movl 32(%esp),%eax /* object is second argument */
896 call builtin_canstore /* builtin_canstore(arrayref,object) */
898 test %eax,%eax /* if (false) throw exception */
903 movl %eax,offobjarrdata(%ecx)/* store objectptr in array */
910 popl %ecx /* delete return address */
911 subl $2,%ecx /* faulting address is return adress - 2 */
912 movl proto_java_lang_NullPointerException,%eax
913 jmp asm_handle_exception
917 popl %ecx /* delete return address */
918 subl $2,%ecx /* faulting address is return adress - 2 */
919 movl proto_java_lang_ArrayIndexOutOfBoundsException,%eax
920 jmp asm_handle_exception
924 popl %ecx /* delete return address */
925 subl $2,%ecx /* faulting address is return adress - 2 */
926 movl proto_java_lang_ArrayStoreException,%eax
927 jmp asm_handle_exception
930 /******************* function asm_builtin_arrayinstanceof **********************
932 * Does the instanceof check of arrays *
934 *******************************************************************************/
936 asm_builtin_arrayinstanceof:
937 subl $8,%esp /* build stack frame (2 * 4 bytes) */
945 call builtin_arrayinstanceof
951 /******************* function asm_initialize_thread_stack **********************
953 * initialized a thread stack *
954 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
956 *******************************************************************************/
958 asm_initialize_thread_stack:
959 movl 8(%esp),%eax /* (to)->stackEnd */
960 subl $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
972 movl 4(%esp),%edx /* save (u1*) (func) */
975 ret /* return restorepoint in %eax */
978 /******************* function asm_perform_threadswitch *************************
980 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
982 * performs a threadswitch *
984 *******************************************************************************/
986 asm_perform_threadswitch:
998 movl 36(%esp),%eax /* save current return address */
1001 movl 40(%esp),%eax /* first argument **from */
1004 movl 48(%esp),%eax /* third argument **stackTop */
1007 movl 44(%esp),%eax /* second argument **to */
1008 movl 0(%eax),%esp /* load new stack pointer */
1014 /* skip stack pointer */
1019 addl $32,%esp /* leave return address on stack */
1023 /********************* function asm_switchstackandcall *************************
1025 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
1028 * Switches to a new stack, calls a function and switches back. *
1029 * a0 new stack pointer *
1030 * a1 function pointer *
1031 * a2 pointer to variable where stack top should be stored *
1032 * a3 pointer to user data, is passed to the function *
1034 *******************************************************************************/
1036 asm_switchstackandcall:
1037 movl 4(%esp),%edx /* first argument *stack */
1038 subl $8,%edx /* allocate new stack */
1040 movl (%esp),%eax /* save return address on new stack */
1043 movl %esp,4(%edx) /* save old stack pointer on new stack*/
1045 movl 12(%esp),%eax /* third argument **stacktopsave */
1046 movl %esp,(%eax) /* save old stack pointer to variable */
1048 movl 8(%esp),%eax /* load function pointer */
1049 movl 16(%esp),%ecx /* fourth argument *p */
1051 movl %edx,%esp /* switch to new stack */
1054 movl %ecx,0(%esp) /* pass pointer */
1055 call *%eax /* and call function */
1058 movl (%esp),%edx /* load return address */
1059 movl 4(%esp),%esp /* switch to old stack */
1064 /********************* function asm_getcallingmethod ***************************
1066 * classinfo *asm_getcallingmethod (); *
1068 * goes back stack frames to get the calling method *
1074 *******************************************************************************/
1076 asm_getcallingmethod:
1078 /* movl $0,(%eax) */
1082 /*********************** function asm_builtin_trace ****************************
1084 * Intended to be called from the native stub. Saves all argument registers *
1085 * and calls builtin_trace_args. *
1087 *******************************************************************************/
1091 subl $68,%esp /* 4 + 8 * 4 + 68 = 104 */
1136 call builtin_trace_args
1143 /********************* function asm_builtin_exittrace **************************
1145 * Intended to be called from the native stub. Saves return value and calls *
1146 * builtin_displaymethodstop. *
1148 *******************************************************************************/
1150 asm_builtin_exittrace:
1154 movl 60(%esp),%eax /* 4 + 8 * 4 + 24 = 60 */
1170 call builtin_displaymethodstop
1178 * These are local overrides for various environment variables in Emacs.
1179 * Please do not remove this and leave it at the end of the file, where
1180 * Emacs will automagically detect them.
1181 * ---------------------------------------------------------------------
1184 * indent-tabs-mode: t