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 665 2003-11-21 18:36:43Z jowenn $ *
16 *******************************************************************************/
23 /********************* exported functions and variables ***********************/
25 .globl has_no_x_instr_set
26 .globl asm_calljavamethod
27 .globl asm_calljavafunction
28 .globl asm_calljavafunction2
29 .globl asm_calljavafunction2long
30 .globl asm_calljavafunction2double
32 .globl asm_call_jit_compiler
33 .globl asm_dumpregistersandcall
34 .globl asm_handle_builtin_exception
35 .globl asm_handle_nat_exception
36 .globl asm_handle_exception
37 .globl asm_builtin_checkcast
38 .globl asm_builtin_checkarraycast
39 .globl asm_builtin_newarray
40 .globl asm_builtin_anewarray
41 .globl asm_builtin_newarray_array
42 .globl asm_builtin_aastore
43 .globl asm_builtin_monitorenter
44 .globl asm_builtin_monitorexit
45 .globl asm_builtin_ldiv
46 .globl asm_builtin_lrem
47 .globl asm_builtin_f2i
48 .globl asm_builtin_f2l
49 .globl asm_builtin_d2i
50 .globl asm_builtin_d2l
51 .globl asm_builtin_arrayinstanceof
52 .globl asm_perform_threadswitch
53 .globl asm_initialize_thread_stack
54 .globl asm_switchstackandcall
55 .globl asm_getcallingmethod
56 .globl asm_builtin_trace
57 .globl asm_builtin_exittrace
59 /*************************** imported functions *******************************/
62 .globl builtin_monitorexit
63 .globl builtin_throw_exception
64 .globl builtin_trace_exception
65 .globl class_java_lang_Object
68 /*********************** function has_no_x_instr_set ***************************
70 * determines if the byte support instruction set (21164a and higher) *
73 * Use it on i386 architecture to init the fpu. *
75 *******************************************************************************/
78 finit /* intitialize the fpu */
80 pushl $0x027f /* Round to nearest, 53-bit mode, exceptions masked */
84 xor %eax,%eax /* result code 0 (not used for i386) */
88 /********************* function asm_calljavamethod *****************************
90 * This function calls a Java-method (which possibly needs compilation) *
91 * with up to 4 parameters. *
93 * This functions calls the JIT-compiler which eventually translates the *
94 * method into machine code. *
96 * An possibly throwed exception will be returned to the caller as function *
97 * return value, so the java method cannot return a fucntion value (this *
98 * function usually calls 'main' and '<clinit>' which do not return a *
102 * javaobject_header *asm_calljavamethod (methodinfo *m, *
103 * void *arg1, void *arg2, void *arg3, void *arg4); *
105 *******************************************************************************/
107 #define MethodPointer -4
113 #define ExTableSize -28
114 #define ExTableStart -28
116 #define ExEntrySize -16
119 #define ExHandlerPC -12
120 #define ExCatchType -16
123 .ascii "calljavamethod\0\0"
127 .long 0 /* catch type all */
128 .long calljava_xhandler /* handler pc */
129 .long calljava_xhandler /* end pc */
130 .long asm_calljavamethod /* start pc */
131 .long 1 /* extable size */
132 .long 0 /* fltsave */
133 .long 0 /* intsave */
136 .long 32 /* frame size */
137 .long 0 /* method pointer (pointer to name) */
140 pushl %ebp /* allocate stack space */
143 push %ebx /* save registers */
147 subl $32,%esp /* pass the remaining parameters */
150 movl %edx,28(%esp) /* convert parms to 8 byte */
166 movl 8(%ebp),%eax /* move function pointer to %eax */
168 lea asm_call_jit_compiler,%ecx
169 call *%ecx /* call JIT compiler */
175 pop %edi /* restore registers */
180 leave /* free stack space */
184 pushl %eax /* pass exception pointer */
185 call builtin_throw_exception
197 /********************* function asm_calljavafunction ***************************
199 * This function calls a Java-method (which possibly needs compilation) *
200 * with up to 4 address parameters. *
202 * This functions calls the JIT-compiler which eventually translates the *
203 * method into machine code. *
206 * javaobject_header *asm_calljavamethod (methodinfo *m, *
207 * void *arg1, void *arg2, void *arg3, void *arg4); *
209 *******************************************************************************/
212 .ascii "calljavafunction\0\0"
216 .long 0 /* catch type all */
217 .long calljava_xhandler2 /* handler pc */
218 .long calljava_xhandler2 /* end pc */
219 .long asm_calljavafunction /* start pc */
220 .long 1 /* extable size */
221 .long 0 /* fltsave */
222 .long 0 /* intsave */
225 .long 32 /* frame size */
226 .long 0 /* method pointer (pointer to name) */
228 asm_calljavafunction:
229 pushl %ebp /* allocate stack space */
232 push %ebx /* save registers */
236 subl $32,%esp /* pass the remaining parameters */
239 movl %edx,28(%esp) /* convert parms to 8 byte */
255 movl 8(%ebp),%eax /* move function pointer to %eax */
257 lea asm_call_jit_compiler,%ecx
258 call *%ecx /* call JIT compiler */
264 pop %edi /* restore registers */
271 pushl %eax /* pass exception pointer */
272 call builtin_throw_exception
276 pop %edi /* restore registers */
284 /********************* function asm_calljavafunction ***************************
286 * This function calls a Java-method (which possibly needs compilation) *
287 * with up to 4 address parameters. *
289 * This functions calls the JIT-compiler which eventually translates the *
290 * method into machine code. *
293 * javaobject_header *asm_calljavamethod (methodinfo *m, *
294 * void *arg1, void *arg2, void *arg3, void *arg4); *
296 *******************************************************************************/
299 .ascii "calljavafunction2\0\0"
303 .long 0 /* catch type all */
304 .long calljava_xhandler3 /* handler pc */
305 .long calljava_xhandler3 /* end pc */
306 .long asm_calljavafunction2 /* start pc */
307 .long 1 /* extable size */
308 .long 0 /* fltsave */
309 .long 0 /* intsave */
312 .long 32 /* frame size */
313 .long 0 /* method pointer (pointer to name) */
315 /********************* function asm_calljavafunction ***************************
317 * This function calls a Java-method (which possibly needs compilation) *
318 * with up to 4 address parameters. *
320 * This functions calls the JIT-compiler which eventually translates the *
321 * method into machine code. *
324 * javaobject_header *asm_calljavamethod (methodinfo *m, *
325 * void *arg1, void *arg2, void *arg3, void *arg4); *
327 *******************************************************************************/
330 .ascii "calljavafunction2double\0\0"
334 .long 0 /* catch type all */
335 .long calljava_xhandler3 /* handler pc */
336 .long calljava_xhandler3 /* end pc */
337 .long asm_calljavafunction2double /* start pc */
338 .long 1 /* extable size */
339 .long 0 /* fltsave */
340 .long 0 /* intsave */
343 .long 32 /* frame size */
344 .long 0 /* method pointer (pointer to name) */
346 /********************* function asm_calljavafunction ***************************
348 * This function calls a Java-method (which possibly needs compilation) *
349 * with up to 4 address parameters. *
351 * This functions calls the JIT-compiler which eventually translates the *
352 * method into machine code. *
355 * javaobject_header *asm_calljavamethod (methodinfo *m, *
356 * void *arg1, void *arg2, void *arg3, void *arg4); *
358 *******************************************************************************/
361 .ascii "calljavafunction2long\0\0"
365 .long 0 /* catch type all */
366 .long calljava_xhandler3 /* handler pc */
367 .long calljava_xhandler3 /* end pc */
368 .long asm_calljavafunction2long /* start pc */
369 .long 1 /* extable size */
370 .long 0 /* fltsave */
371 .long 0 /* intsave */
374 .long 32 /* frame size */
375 .long 0 /* method pointer (pointer to name) */
378 asm_calljavafunction2:
379 asm_calljavafunction2double:
380 asm_calljavafunction2long:
381 pushl %ebp /* save ebp */
384 movl %esp,%eax /*save stackptr*/
388 movl sizejniblock*3+offjniitem+4(%ebp),%ebx
390 movl sizejniblock*3+offjniitem(%ebp),%ebx
393 movl sizejniblock*2+offjniitem+4(%ebp),%ebx
395 movl sizejniblock*2+offjniitem(%ebp),%ebx
399 movl sizejniblock+offjniitem+4(%ebp),%ebx
401 movl sizejniblock+offjniitem(%ebp),%ebx
404 movl offjniitem+4(%ebp),%ebx
406 movl offjniitem(%ebp),%ebx
410 movl 8(%ebp),%eax /* move function pointer to %eax */
412 lea asm_call_jit_compiler,%ecx
413 call *%ecx /* call JIT compiler */
422 pushl %eax /* pass exception pointer */
423 call builtin_throw_exception
434 /****************** function asm_call_jit_compiler *****************************
436 * invokes the compiler for untranslated JavaVM methods. *
438 * Register R0 contains a pointer to the method info structure (prepared *
439 * by createcompilerstub). Using the return address in R26 and the *
440 * offset in the LDA instruction or using the value in methodptr R28 the *
441 * patching address for storing the method address can be computed: *
443 * method address was either loaded using *
445 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
446 * i386_call_reg(REG_ITMP2) *
450 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
451 * i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
452 * i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
453 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
454 * i386_call_reg(REG_ITMP1) *
456 * in the static case the method pointer can be computed using the *
457 * return address and the lda function following the jmp instruction *
459 *******************************************************************************/
462 asm_call_jit_compiler:
464 push %ebx /* save register */
467 mov 12(%esp),%ebp /* get return address (2 push) */
468 mov -1(%ebp),%bl /* get function code */
469 cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%edx)? */
470 jne L_not_static_special
472 sub $6,%ebp /* calculate address of immediate */
473 jmp L_call_jit_compile
475 L_not_static_special:
476 cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%eax) */
477 jne L_not_virtual_interface
479 sub $6,%ebp /* calculate address of offset */
480 mov (%ebp),%ebp /* get offset */
481 add %edx,%ebp /* add base address to get method address */
482 jmp L_call_jit_compile
484 L_not_virtual_interface: /* a call from asm_calljavamethod */
488 push %ebp /* save address for method pointer */
490 push %eax /* push methodpointer on stack */
494 pop %ebp /* restore address for method pointer */
495 test %ebp,%ebp /* is address == 0 (asm_calljavamethod) */
498 mov %eax,(%ebp) /* and now save the new pointer */
502 pop %ebx /* restore registers */
505 jmp *%eax /* ...and now call the new method */
509 /****************** function asm_dumpregistersandcall **************************
511 * This funtion saves all callee saved registers and calls the function *
512 * which is passed as parameter. *
514 * This function is needed by the garbage collector, which needs to access *
515 * all registers which are stored on the stack. Unused registers are *
516 * cleared to avoid interferances with the GC. *
518 * void asm_dumpregistersandcall (functionptr f); *
520 *******************************************************************************/
522 asm_dumpregistersandcall:
531 mov 8(%ebp),%eax /* load function pointer */
532 call *%eax /* call function */
542 /********************* function asm_handle_exception ***************************
544 * This function handles an exception. It does not use the usual calling *
545 * conventions. The exception pointer is passed in REG_ITMP1 and the *
546 * pc from the exception raising position is passed in REG_ITMP2. It searches *
547 * the local exception table for a handler. If no one is found, it unwinds *
548 * stacks and continues searching the callers. *
550 * void asm_handle_exception (exceptionptr, exceptionpc); *
552 *******************************************************************************/
554 asm_handle_builtin_exception:
555 add $4,%esp /* clear return address of this call */
556 mov (%esp),%eax /* get exceptionptr */
557 leave /* leave builtin function */
558 mov (%esp),%edx /* get exceptionpc */
559 sub $2,%edx /* size of builtin call */
560 jmp asm_handle_exception
562 asm_handle_nat_exception:
563 add $4,%esp /* clear return address of native stub */
565 asm_handle_exception:
567 push %edx /* get the data segment ptr */
576 push %eax /* save exception pointer */
578 push %edx /* save exception pc */
579 push %ecx /* save data segment pointer */
588 movl %eax,(%esp) /* exception pointer */
590 movl MethodPointer(%ecx),%eax /* method pointer */
593 movl %edx,8(%esp) /* exception pc */
594 movl $1,12(%esp) /* set no unwind flag */
595 call builtin_trace_exception
599 movl -12(%ebp),%esi /* %esi = data segment pointer */
600 movl ExTableSize(%esi),%ecx /* %ecx = exception table size */
601 test %ecx,%ecx /* if empty table skip */
604 lea ExTableStart(%esi),%edi /* %edi = start of exception table */
605 movl -4(%ebp),%eax /* get xptr */
608 movl -8(%ebp),%edx /* get xpc */
610 movl ExStartPC(%edi),%ebx /* %ebx = exception start pc */
611 cmpl %edx,%ebx /* %ebx = (startpc <= xpc) */
612 jg ex_table_cont /* if (false) continue */
613 movl ExEndPC(%edi),%ebx /* %ebx = exception end pc */
614 cmpl %ebx,%edx /* %ebx = (xpc < endpc) */
615 jge ex_table_cont /* if (false) continue */
616 movl ExCatchType(%edi),%ebx /* arg1 = exception catch type */
617 test %ebx,%ebx /* NULL catches everything */
620 movl offobjvftbl(%eax),%esi /* %esi = vftblptr(xptr) */
621 movl offobjvftbl(%ebx),%ebx /* %ebx = vftblptr(catchtype) class (not obj) */
622 movl offbaseval(%esi),%esi /* %esi = baseval(xptr) */
623 movl offbaseval(%ebx),%edx /* %edx = baseval(catchtype) */
624 movl offdiffval(%ebx),%ebx /* %ebx = diffval(catchtype) */
625 subl %edx,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
626 cmpl %ebx,%esi /* xptr is instanceof catchtype */
630 movl ExHandlerPC(%edi),%edx
636 popl %eax /* pop %ecx (dummy) */
637 popl %eax /* pop %edx (dummy) */
638 popl %eax /* pop %eax */
645 lea ExEntrySize(%edi),%edi
654 popl %ecx /* restore data segment pointer */
656 popl %eax /* restore exception pointer */
659 movl %eax,%edi /* save exception pointer */
662 movl IsSync(%ecx),%eax /* %eax = SyncOffset */
663 test %eax,%eax /* if zero no monitorexit */
668 pusha /* save regs */
670 call builtin_monitorexit
672 popa /* restore regs */
675 movl FrameSize(%ecx),%eax /* %eax = frame size */
676 addl %eax,%esp /* unwind stack */
677 movl %esp,%eax /* %eax = pointer to save area */
679 movl IntSave(%ecx),%edx /* %edx = saved int register count */
691 shll $3,%edx /* multiply by 8 bytes */
695 movl FltSave(%ecx),%edx /* %edx = saved flt register count */
722 popl %edx /* the new xpc is return address */
731 pushl %edx /* get the new data segment ptr */
742 movl %edi,%eax /* restore saved exception pointer */
747 pushl %eax /* save exception pointer */
748 pushl %edx /* save exception pc */
749 pushl %ecx /* save data segment pointer */
757 /********************* function asm_builtin_monitorenter ***********************
759 * Does null check and calls monitorenter or throws an exception *
761 *******************************************************************************/
763 asm_builtin_monitorenter:
765 je nb_monitorenter /* if (null) throw exception */
766 jmp builtin_monitorenter /* else call builtin_monitorenter */
769 popl %edx /* delete return address */
770 subl $2,%edx /* faulting address is return adress - 2 */
771 movl proto_java_lang_NullPointerException,%eax
772 jmp asm_handle_exception
775 /********************* function asm_builtin_monitorexit ************************
777 * Does null check and calls monitorexit or throws an exception *
779 *******************************************************************************/
781 asm_builtin_monitorexit:
783 je nb_monitorexit /* if (null) throw exception */
784 jmp builtin_monitorexit /* else call builtin_monitorenter */
787 popl %edx /* delete return address */
788 subl $2,%edx /* faulting address is return adress - 2 */
789 movl proto_java_lang_NullPointerException,%eax
790 jmp asm_handle_exception
793 /************************ function asm_builtin_ldiv ****************************
795 * Does null check and calls ldiv or throws an exception *
797 *******************************************************************************/
802 test %eax,%eax /* if (null) throw exception */
808 popl %edx /* delete return address */
809 subl $2,%edx /* faulting address is return adress - 2 */
811 movl proto_java_lang_ArithmeticException,%eax
812 jmp asm_handle_exception
815 /************************ function asm_builtin_lrem ****************************
817 * Does null check and calls lrem or throws an exception *
819 *******************************************************************************/
824 test %eax,%eax /* if (null) throw exception */
830 popl %edx /* delete return address */
831 subl $2,%edx /* faulting address is return adress - 2 */
833 movl proto_java_lang_ArithmeticException,%eax
834 jmp asm_handle_exception
837 /************************ function asm_builtin_x2x *****************************
839 * Wrapper functions for corner cases *
841 *******************************************************************************/
872 /*********************** function new_builtin_checkcast ************************
874 * Does the cast check and eventually throws an exception *
876 *******************************************************************************/
878 asm_builtin_checkcast:
884 /******************* function asm_builtin_checkarraycast ***********************
886 * Does the cast check and eventually throws an exception *
888 *******************************************************************************/
890 asm_builtin_checkarraycast:
891 subl $8,%esp /* build stack frame (2 * 4 bytes) */
893 movl 12(%esp),%eax /* 8 (frame) + 4 (return) */
894 movl %eax,(%esp) /* save object pointer */
899 call builtin_checkarraycast /* builtin_checkarraycast */
901 test %eax,%eax /* if (false) throw exception */
904 movl 12(%esp),%eax /* return object pointer */
911 popl %edx /* delete return address */
912 subl $2,%edx /* faulting address is return adress - 2 */
914 movl proto_java_lang_ClassCastException,%eax
915 jmp asm_handle_exception
918 /******************* function asm_builtin_newarray *****************************
920 * Does the cast check and eventually throws an exception *
922 *******************************************************************************/
924 asm_builtin_newarray:
925 subl $8,%esp /* build stack frame (2 * 4 bytes) */
933 call builtin_newarray
939 /******************* function asm_builtin_aastore ******************************
941 * Does the cast check and eventually throws an exception *
943 *******************************************************************************/
946 subl $12,%esp /* build stack frame (3 * 4 bytes) */
948 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
949 test %eax,%eax /* if null pointer throw exception */
952 movl offarraysize(%eax),%edx /* load size */
953 movl 24(%esp),%ecx /* index */
954 cmpl %edx,%ecx /* do bound check */
955 ja nb_aastore_bound /* if out of bounds throw exception */
957 shll $2,%ecx /* index * 4 */
958 addl %eax,%ecx /* add index * 4 to arrayref */
960 movl %ecx,8(%esp) /* save store position */
962 movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
965 movl 32(%esp),%eax /* object is second argument */
968 call builtin_canstore /* builtin_canstore(arrayref,object) */
970 test %eax,%eax /* if (false) throw exception */
975 movl %eax,offobjarrdata(%ecx)/* store objectptr in array */
982 popl %edx /* delete return address */
983 subl $2,%edx /* faulting address is return adress - 2 */
985 movl proto_java_lang_NullPointerException,%eax
986 jmp asm_handle_exception
990 popl %edx /* delete return address */
991 subl $2,%edx /* faulting address is return adress - 2 */
993 movl proto_java_lang_ArrayIndexOutOfBoundsException,%eax
994 jmp asm_handle_exception
998 popl %edx /* delete return address */
999 subl $2,%edx /* faulting address is return adress - 2 */
1001 movl proto_java_lang_ArrayStoreException,%eax
1002 jmp asm_handle_exception
1005 /******************* function asm_builtin_arrayinstanceof **********************
1007 * Does the instanceof check of arrays *
1009 *******************************************************************************/
1011 asm_builtin_arrayinstanceof:
1012 subl $8,%esp /* build stack frame (2 * 4 bytes) */
1020 call builtin_arrayinstanceof
1026 /******************* function asm_initialize_thread_stack **********************
1028 * initialized a thread stack *
1029 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
1031 *******************************************************************************/
1033 asm_initialize_thread_stack:
1034 movl 8(%esp),%eax /* (to)->stackEnd */
1035 subl $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
1047 movl 4(%esp),%edx /* save (u1*) (func) */
1050 ret /* return restorepoint in %eax */
1053 /******************* function asm_perform_threadswitch *************************
1055 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
1057 * performs a threadswitch *
1059 *******************************************************************************/
1061 asm_perform_threadswitch:
1073 movl 36(%esp),%eax /* save current return address */
1076 movl 40(%esp),%eax /* first argument **from */
1079 movl 48(%esp),%eax /* third argument **stackTop */
1082 movl 44(%esp),%eax /* second argument **to */
1083 movl 0(%eax),%esp /* load new stack pointer */
1089 /* skip stack pointer */
1094 addl $32,%esp /* leave return address on stack */
1098 /********************* function asm_switchstackandcall *************************
1100 * int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
1103 * Switches to a new stack, calls a function and switches back. *
1104 * a0 new stack pointer *
1105 * a1 function pointer *
1106 * a2 pointer to variable where stack top should be stored *
1107 * a3 pointer to user data, is passed to the function *
1109 *******************************************************************************/
1111 asm_switchstackandcall:
1112 movl 4(%esp),%edx /* first argument *stack */
1113 subl $8,%edx /* allocate new stack */
1115 movl (%esp),%eax /* save return address on new stack */
1118 movl %esp,4(%edx) /* save old stack pointer on new stack */
1120 movl 12(%esp),%eax /* third argument **stacktopsave */
1121 movl %esp,(%eax) /* save old stack pointer to variable */
1123 movl 8(%esp),%eax /* load function pointer */
1124 movl 16(%esp),%ecx /* fourth argument *p */
1126 movl %edx,%esp /* switch to new stack */
1129 movl %ecx,0(%esp) /* pass pointer */
1130 call *%eax /* and call function */
1133 movl (%esp),%edx /* load return address */
1134 movl 4(%esp),%esp /* switch to old stack */
1139 /********************* function asm_getcallingmethod ***************************
1141 * classinfo *asm_getcallingmethod (); *
1143 * goes back stack frames to get the calling method *
1149 *******************************************************************************/
1151 asm_getcallingmethod:
1153 /* movl $0,(%eax) */
1157 /*********************** function asm_builtin_trace ****************************
1159 * Intended to be called from the native stub. Saves all argument registers *
1160 * and calls builtin_trace_args. *
1162 *******************************************************************************/
1166 subl $68,%esp /* 4 + 8 * 4 + 68 = 104 */
1211 call builtin_trace_args
1218 /********************* function asm_builtin_exittrace **************************
1220 * Intended to be called from the native stub. Saves return value and calls *
1221 * builtin_displaymethodstop. *
1223 *******************************************************************************/
1225 asm_builtin_exittrace:
1229 movl 60(%esp),%eax /* 4 + 8 * 4 + 24 = 60 */
1245 call builtin_displaymethodstop