1 /* src/vm/jit/powerpc/asmpart.S - Java-C interface functions for PowerPC
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.text; 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: Christian Thalinger
33 $Id: asmpart.S 3234 2005-09-21 12:11:58Z twisti $
43 #include "vm/jit/methodheader.h"
44 #include "vm/jit/powerpc/offsets.h"
51 .globl asm_calljavafunction
52 .globl asm_calljavafunction_int
54 .globl asm_calljavafunction2
55 .globl asm_calljavafunction2int
56 .globl asm_calljavafunction2long
57 .globl asm_calljavafunction2float
58 .globl asm_calljavafunction2double
60 .globl asm_call_jit_compiler
62 .globl asm_handle_nat_exception
63 .globl asm_handle_exception
65 .globl asm_wrapper_patcher
68 .globl asm_initialize_thread_stack
69 .globl asm_perform_threadswitch
70 .globl asm_switchstackandcall
71 .globl asm_criticalsections
72 .globl asm_getclassvalues_atomic
75 /********************* function asm_calljavafunction ***************************
77 * This function calls a Java-method (which possibly needs compilation) *
78 * with up to 4 address parameters. *
80 * This functions calls the JIT-compiler which eventually translates the *
81 * method into machine code. *
84 * javaobject_header *asm_calljavamethod (methodinfo *m, *
85 * void *arg1, void *arg2, void *arg3, void *arg4); *
87 *******************************************************************************/
91 .long 0 /* catch type all */
92 .long calljava_xhandler /* handler pc */
93 .long calljava_xhandler /* end pc */
94 .long asm_calljavafunction /* start pc */
95 .long 1 /* extable size */
96 .long 0 /* line number table start */
97 .long 0 /* line number table size */
102 .long 24 /* frame size */
103 .long 0 /* method pointer (pointer to name) */
105 asm_calljavafunction:
106 asm_calljavafunction_int:
111 stw r0,LA_LR_OFFSET(r1)
114 #if defined(__DARWIN__)
145 #if defined(__DARWIN__)
146 /* addis mptr,r31,ha16(_asm_call_jit_compiler-0b)*/
147 addi mptr,r31,lo16(asm_call_jit_compiler-0b)
149 /* addi mptr,r31,(asm_call_jit_compiler-0b)@l*/
150 lis mptr,asm_call_jit_compiler@ha
151 addi mptr,mptr,asm_call_jit_compiler@l
162 #if defined(__DARWIN__)
163 addi pv,itmp1,lo16(asm_calljavafunction-1b)
165 addi pv,itmp1,(asm_calljavafunction-1b)@l
187 lwz r0,148+LA_LR_OFFSET(r1)
197 bl builtin_throw_exception
198 li v0,0 /* return NULL */
199 b calljava_regrestore
206 .long 0 /* catch type all */
207 .long calljava_xhandler2 /* handler pc */
208 .long calljava_xhandler2 /* end pc */
209 .long asm_calljavafunction2 /* start pc */
210 .long 1 /* extable size */
211 .long 0 /* line number table start */
212 .long 0 /* line number table size */
213 .long 0 /* fltsave */
214 .long 0 /* intsave */
217 .long 24 /* frame size */
218 .long 0 /* method pointer (pointer to name) */
220 asm_calljavafunction2:
221 asm_calljavafunction2int:
222 asm_calljavafunction2long:
223 asm_calljavafunction2float:
224 asm_calljavafunction2double:
229 stw r0,LA_LR_OFFSET(r1)
253 stw r3,36(r1) /* save method pointer for compiler */
254 mr itmp1,r6 /* pointer to arg block */
255 mr itmp2,r4 /* arg count */
258 ble calljava_argsloaded
261 lwz r3,offjniitem+4(itmp1)
263 ble calljava_argsloaded
266 lwz r4,offjniitem+sizejniblock*1+4(itmp1)
268 ble calljava_argsloaded
272 lwz r5,offjniitem+sizejniblock*2+4(itmp1)
274 ble calljava_argsloaded
278 lwz r6,offjniitem+sizejniblock*3+4(itmp1)
280 ble calljava_argsloaded
285 #if defined(__DARWIN__)
286 /* addis mptr,r31,ha16(_asm_call_jit_compiler-0b)*/
287 addi mptr,r31,lo16(asm_call_jit_compiler-0b)
289 addi mptr,r31,(asm_call_jit_compiler-0b)@l
299 #if defined(__DARWIN__)
300 addi pv,itmp1,lo16(asm_calljavafunction2-1b)
302 addi pv,itmp1,(asm_calljavafunction2-1b)@l
305 calljava_regrestore2:
324 lwz r0,148+LA_LR_OFFSET(r1)
334 bl builtin_throw_exception
335 li v0,0 /* return NULL */
336 b calljava_regrestore2
339 /* asm_call_jit_compiler *******************************************************
341 Invokes the compiler for untranslated JavaVM methods.
343 *******************************************************************************/
345 asm_call_jit_compiler:
347 stw r0,LA_LR_OFFSET(r1) /* save return address */
348 stwu r1,-((LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo)(r1)
349 stw itmp1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 1*4)(r1)
351 mr itmp1,r0 /* save return address to other reg. */
369 stw mptr,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 2*4)(r1)
371 #if defined(__DARWIN__)
395 SAVE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1)
398 addi a0,sp,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)
399 li a1,0 /* we don't have pv handy */
400 addi a2,sp,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo
401 lwz a3,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo+LA_LR_OFFSET(sp)
402 mr a4,a3 /* xpc is equal to ra */
403 bl stacktrace_create_extern_stackframeinfo
405 lwz itmp1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 1*4)(r1)
407 bl jit_compile /* compile the Java method */
408 mr pv,r3 /* move address to pv register */
410 addi a0,sp,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)
411 bl stacktrace_remove_stackframeinfo
413 #if defined(__DARWIN__)
437 RESTORE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1)
440 lwz mptr,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 2*4)(r1)
442 lwz itmp1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo+LA_LR_OFFSET(r1)
444 addi r1,r1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo
446 mr. pv,pv /* test for exception */
447 beq L_asm_call_jit_compiler_exception
452 stw pv,0(mptr) /* store method address */
454 mtctr pv /* move method address to control reg */
455 bctr /* and call the Java method */
457 L_asm_call_jit_compiler_exception:
458 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
460 stw r0,LA_LR_OFFSET(r1)
461 stwu r1,-LA_SIZE_ALIGNED(r1) /* preserve linkage area */
462 bl builtin_asm_get_exceptionptrptr
463 lwz r0,LA_SIZE_ALIGNED+LA_LR_OFFSET(r1)
465 addi r1,r1,LA_SIZE_ALIGNED
467 # if defined(__DARWIN__)
468 lwz v0,lo16(_exceptionptr-0b)(pv)
470 lis v0,_exceptionptr@ha
471 addi v0,v0,_exceptionptr@l
474 lwz xptr,0(v0) /* get the exception pointer */
476 stw itmp3,0(v0) /* clear the exception pointer */
480 b asm_handle_nat_exception
483 /********************* function asm_handle_exception ***************************
485 * This function handles an exception. It does not use the usual calling *
486 * conventions. The exception pointer is passed in REG_ITMP1 and the *
487 * pc from the exception raising position is passed in REG_ITMP2. It searches *
488 * the local exception table for a handler. If no one is found, it unwinds *
489 * stacks and continues searching the callers. *
491 * void asm_handle_exception (exceptionptr, exceptionpc); *
493 *******************************************************************************/
495 asm_handle_nat_exception:
503 bne asm_handle_exception
508 asm_handle_exception:
531 addi r1,r1,-4*4 /* allocate stack */
532 stw xptr,0*4(r1) /* save used register */
538 lwz r3,0*4(r1) /* exception pointer */
539 lwz r4,MethodPointer(pv) /* method pointer */
540 mr r5,xpc /* exception pc */
542 li r6,0 /* line number */
543 li r7,4 /* set no unwind flag */
545 /* XXX no valid stack frame chaining here */
546 addi r1,r1,-(24+5*4) /* 24 linkage area + 5 argument * 4 */
547 bl builtin_trace_exception
552 lwz xptr,0*4(r1) /* restore xptr */
557 lwz r3,ExTableSize(pv) /* r3 = exception table size */
558 mr. r3,r3 /* if empty table skip */
561 addi r4,pv,ExTableStart /* r4 = start of exception table */
564 lwz r5,ExStartPC(r4) /* r5 = exception start pc */
565 cmplw r5,xpc /* (startpc <= xpc) */
567 lwz r5,ExEndPC(r4) /* r5 = exception end pc */
568 cmplw xpc,r5 /* (xpc < endpc) */
570 lwz r7,ExCatchType(r4) /* r7 = exception catch type */
574 lwz itmp3,offclassloaded(r7)
578 /* XXX no valid stack frame chaining here */
579 addi r1,r1,-16*4 /* allocate stack */
580 stw r3,7*4(r1) /* save used registers */
581 stw r4,8*4(r1) /* 6*4 (linkage) + 1*4 (arg1) + 7*4 (save) */
589 mr r3,r7 /* arg1 = exceptionclass */
590 bl load_class_bootstrap
603 lwz itmp3,offclasslinked(r7)
605 /* XXX no valid stack frame chaining here */
606 addi r1,r1,-16*4 /* allocate stack */
610 stw r3,7*4(r1) /* save used registers */
611 stw r4,8*4(r1) /* 6*4 (linkage) + 1*4 (arg1) + 7*4 (save) */
618 mr r3,r7 /* arg1 = exceptionclass */
633 lwz r6,offobjvftbl(xptr) /* r6 = vftblptr(xptr) */
634 lwz r7,offclassvftbl(r7) /* r7 = vftblptr(catchtype) class (not obj) */
635 lwz r6,offbaseval(r6) /* r6 = baseval(xptr) */
636 lwz r8,offbaseval(r7) /* r8 = baseval(catchtype) */
637 lwz r7,offdiffval(r7) /* r7 = diffval(catchtype) */
639 subf r6,r8,r6 /* r6 = baseval(xptr) - baseval(catchtype) */
640 cmplw r6,r7 /* xptr is instanceof catchtype */
642 bgt ex_table_cont /* if (false) continue */
645 lwz xpc,ExHandlerPC(r4) /* xpc = exception handler pc */
674 addi r4,r4,ExEntrySize /* next exception table entry */
675 addic. r3,r3,-1 /* decrement entry counter */
676 bgt ex_table_loop /* if (t0 > 0) next entry */
679 mr. r9,r9 /* if here the first time, then */
680 beq ex_already_cleared
681 addi r1,r1,18*4 /* deallocate stack and */
682 li r9,0 /* clear the no unwind flag */
684 lwz r3,IsSync(pv) /* t0 = SyncOffset */
686 beq no_monitor_exit /* if zero no monitorexit */
688 #if defined(USE_THREADS)
702 /* XXX no valid stack frame chaining here */
704 bl builtin_monitorexit
718 lwz r3,FrameSize(pv) /* r3 = frame size */
719 add r1,r1,r3 /* unwind stack */
720 mr r3,r1 /* r3 = pointer to save area */
721 lwz r4,IsLeaf(pv) /* r4 = is leaf procedure */
723 bne ex_no_restore /* if (leaf) skip */
724 lwz r4,LA_LR_OFFSET(r3) /* restore ra */
727 mflr r4 /* the new xpc is ra */
729 lwz r4,IntSave(pv) /* r4 = saved int register count */
733 #if defined(__DARWIN__)
734 addi r5,r5,lo16(ex_int2-ex_int1)
736 addi r5,r5,(ex_int2-ex_int1)@l
760 #if defined(__DARWIN__)
761 addi r5,r5,lo16(ex_flt2-ex_flt1)
763 addi r5,r5,(ex_flt2-ex_flt1)@l
795 /* asm_wrapper_patcher *********************************************************
800 20 return address into JIT code (patch position)
801 16 pointer to virtual java_objectheader
802 12 machine code (which is patched back later)
803 8 unresolved class/method/field reference
804 4 data segment displacement from load instructions
805 0 patcher function pointer to call (pv is saved here afterwards)
807 *******************************************************************************/
811 stw r0,8*4+LA_LR_OFFSET(r1) /* skip stack frame of patcher stub */
812 /* keep stack 16-bytes aligned: 6+1+37 = 44 */
813 stwu r1,-(LA_SIZE+(5+38)*4+sizestackframeinfo)(r1)
816 stw a0,LA_SIZE+(5+0)*4(r1) /* save argument registers */
817 stw a1,LA_SIZE+(5+1)*4(r1) /* preserve linkage area (24 bytes) */
818 stw a2,LA_SIZE+(5+2)*4(r1) /* and 4 bytes for 4 argument */
819 stw a3,LA_SIZE+(5+3)*4(r1)
820 stw a4,LA_SIZE+(5+4)*4(r1)
821 stw a5,LA_SIZE+(5+5)*4(r1)
822 stw a6,LA_SIZE+(5+6)*4(r1)
823 stw a7,LA_SIZE+(5+7)*4(r1)
825 stfd fa0,LA_SIZE+(5+8)*4(sp)
826 stfd fa1,LA_SIZE+(5+10)*4(sp)
827 stfd fa2,LA_SIZE+(5+12)*4(sp)
828 stfd fa3,LA_SIZE+(5+14)*4(sp)
829 stfd fa4,LA_SIZE+(5+16)*4(sp)
830 stfd fa5,LA_SIZE+(5+18)*4(sp)
831 stfd fa6,LA_SIZE+(5+20)*4(sp)
832 stfd fa7,LA_SIZE+(5+22)*4(sp)
833 stfd fa8,LA_SIZE+(5+24)*4(sp)
834 stfd fa9,LA_SIZE+(5+26)*4(sp)
835 stfd fa10,LA_SIZE+(5+28)*4(sp)
836 stfd fa11,LA_SIZE+(5+30)*4(sp)
837 stfd fa12,LA_SIZE+(5+32)*4(sp)
839 SAVE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1) /* save 8 int/13 float arguments */
854 stw itmp1,LA_SIZE+(5+34)*4(sp)
855 stw itmp2,LA_SIZE+(5+35)*4(sp)
856 stw pv,LA_SIZE+(5+36)*4(sp)
858 addi a0,sp,LA_SIZE+(5+38)*4 /* create stackframe info */
860 addi a2,sp,(8+LA_WORD_SIZE+5+38)*4+sizestackframeinfo
861 mr a3,r0 /* this is correct for leafs */
862 mr a4,a3 /* pass xpc */
863 bl stacktrace_create_extern_stackframeinfo
865 addi a0,sp,(0+LA_WORD_SIZE+5+38)*4+sizestackframeinfo /* pass sp */
866 lwz pv,(0+LA_WORD_SIZE+5+38)*4+sizestackframeinfo(sp) /* get function */
867 lwz itmp1,LA_SIZE+(5+36)*4(sp) /* move pv to position of fp */
868 stw itmp1,(0+LA_WORD_SIZE+5+38)*4+sizestackframeinfo(sp)
869 mtctr pv /* call the patcher function */
871 stw r3,LA_SIZE+(5+37)*4(sp) /* save return value */
873 addi a0,sp,LA_SIZE+(5+38)*4
874 bl stacktrace_remove_stackframeinfo /* remove stackframe info */
876 lwz itmp3,LA_SIZE+(5+37)*4(sp) /* restore return value into temp reg.*/
879 lwz a0,LA_SIZE+(5+0)*4(r1)
880 lwz a1,LA_SIZE+(5+1)*4(r1)
881 lwz a2,LA_SIZE+(5+2)*4(r1)
882 lwz a3,LA_SIZE+(5+3)*4(r1)
883 lwz a4,LA_SIZE+(5+4)*4(r1)
884 lwz a5,LA_SIZE+(5+5)*4(r1)
885 lwz a6,LA_SIZE+(5+6)*4(r1)
886 lwz a7,LA_SIZE+(5+7)*4(r1)
888 lfd fa0,LA_SIZE+(5+8)*4(sp)
889 lfd fa1,LA_SIZE+(5+10)*4(sp)
890 lfd fa2,LA_SIZE+(5+12)*4(sp)
891 lfd fa3,LA_SIZE+(5+14)*4(sp)
892 lfd fa4,LA_SIZE+(5+16)*4(sp)
893 lfd fa5,LA_SIZE+(5+18)*4(sp)
894 lfd fa6,LA_SIZE+(5+20)*4(sp)
895 lfd fa7,LA_SIZE+(5+22)*4(sp)
896 lfd fa8,LA_SIZE+(5+24)*4(sp)
897 lfd fa9,LA_SIZE+(5+26)*4(sp)
898 lfd fa10,LA_SIZE+(5+28)*4(sp)
899 lfd fa11,LA_SIZE+(5+30)*4(sp)
900 lfd fa12,LA_SIZE+(5+32)*4(sp)
902 RESTORE_ARGUMENT_REGISTERS(LA_WORD_SIZE+4)/* restore 8 int/13 float args */
917 /* get return address (into JIT code) */
918 lwz itmp1,(5+LA_WORD_SIZE+5+38)*4+sizestackframeinfo(sp)
921 lwz itmp1,LA_SIZE+(5+34)*4(sp)
922 lwz itmp2,LA_SIZE+(5+35)*4(sp)
923 lwz pv,LA_SIZE+(5+36)*4(sp)
925 /* remove stack frame + patcher stub stack */
926 addi r1,r1,(8+LA_WORD_SIZE+5+38)*4+sizestackframeinfo
928 mr. itmp3,itmp3 /* check for an exception */
929 beq L_asm_wrapper_patcher_exception
931 blr /* jump to new patched code */
933 L_asm_wrapper_patcher_exception:
934 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
936 stw r0,LA_LR_OFFSET(r1)
937 stwu r1,-LA_SIZE_ALIGNED(r1) /* preserve linkage area */
938 bl builtin_asm_get_exceptionptrptr
939 lwz r0,LA_SIZE_ALIGNED+LA_LR_OFFSET(r1)
941 addi r1,r1,LA_SIZE_ALIGNED
943 # if defined(__DARWIN__)
944 lwz v0,lo16(_exceptionptr-0b)(pv)
946 lis v0,_exceptionptr@ha
947 addi v0,v0,_exceptionptr@l
951 lwz xptr,0(v0) /* get the exception pointer */
953 stw itmp3,0(v0) /* clear the exception pointer */
956 b asm_handle_exception
989 asm_initialize_thread_stack:
1019 #if defined(__DARWIN__)
1020 lfd fr0,lo16(doublezero-0b)(r3)
1022 lfd fr0,(doublezero-0b)@l(r3)
1049 asm_perform_threadswitch:
1141 asm_switchstackandcall:
1159 asm_getclassvalues_atomic:
1162 lwz r6,offbaseval(r3)
1163 lwz r7,offdiffval(r3)
1164 lwz r8,offbaseval(r4)
1166 stw r6,offcast_super_baseval(r5)
1167 stw r7,offcast_super_diffval(r5)
1168 stw r8,offcast_sub_baseval(r5)
1173 asm_criticalsections:
1174 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1177 .long _crit_restart1
1180 .long _crit_restart2
1186 * These are local overrides for various environment variables in Emacs.
1187 * Please do not remove this and leave it at the end of the file, where
1188 * Emacs will automagically detect them.
1189 * ---------------------------------------------------------------------
1192 * indent-tabs-mode: t