1 /* src/vm/jit/mips/asmpart.S - Java-C interface functions for mips
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; 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
29 Changes: Christian Thalinger
31 $Id: asmpart.S 3002 2005-07-12 16:02:45Z twisti $
38 #include "vm/jit/mips/offsets.h"
39 #include "vm/jit/mips/asmoffsets.h"
40 #include "vm/jit/mips/md-asm.h"
47 /* exported functions and variables *******************************************/
49 .globl asm_calljavafunction
50 .globl asm_calljavafunction_int
52 .globl asm_calljavafunction2
53 .globl asm_calljavafunction2int
54 .globl asm_calljavafunction2long
55 .globl asm_calljavafunction2float
56 .globl asm_calljavafunction2double
58 .globl asm_call_jit_compiler
59 .globl asm_handle_exception
60 .globl asm_handle_nat_exception
62 .globl asm_wrapper_patcher
64 .globl asm_perform_threadswitch
65 .globl asm_initialize_thread_stack
66 .globl asm_switchstackandcall
67 .globl asm_getclassvalues_atomic
68 .globl asm_criticalsections
70 .globl compare_and_swap
73 /********************* function asm_calljavafunction ***************************
75 * This function calls a Java-method (which possibly needs compilation) *
76 * with up to 4 address parameters. *
78 * This functions calls the JIT-compiler which eventually translates the *
79 * method into machine code. *
81 * A possibly throwed exception will be returned to the caller as function *
82 * return value, so the java method cannot return a fucntion value (this *
83 * function usually calls 'main' and '<clinit>' which do not return a *
87 * javaobject_header *asm_calljavafunction (methodinfo *m, *
88 * void *arg1, void *arg2, void *arg3, void *arg4); *
90 *******************************************************************************/
92 .ent asm_calljavafunction
96 .dword 0 /* catch type all */
97 .dword calljava_xhandler /* handler pc */
98 .dword calljava_xhandler /* end pc */
99 .dword asm_calljavafunction /* start pc */
100 .word 1 /* extable size */
101 .word 0 /* fltsave */
102 .word 0 /* intsave */
105 .word 10*8 /* frame size */
106 .dword 0 /* method pointer (pointer to name) */
108 asm_calljavafunction:
109 asm_calljavafunction_int:
110 aaddiu sp,sp,-10*8 /* allocate stack space */
111 ast ra,0(sp) /* save return address */
116 ast pv,3*8(sp) /* procedure vector (delay slot) */
122 sdc1 fss0,4*8(sp) /* save non JavaABI saved flt registers */
129 move itmp1,a0 /* pass method pointer via tmp1 */
131 move a0,a1 /* pass the remaining parameters */
136 ala mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
137 ast mptr,1*8(sp) /* store function address */
138 move mptr,sp /* set method pointer */
142 ald pv,1*8(mptr) /* method call as in Java */
143 jalr pv /* call JIT compiler */
145 aaddiu pv,ra,-22*4 /* recompute procedure vector */
150 ald ra,0(sp) /* restore return address */
151 ald pv,3*8(sp) /* restore procedure vector */
153 ldc1 fss0,4*8(sp) /* restore non JavaABI saved flt regs */
160 aaddiu sp,sp,10*8 /* free stack space */
165 jal builtin_throw_exception
166 move v0,zero /* clear return value for exception */
169 .end asm_calljavafunction
172 .ent asm_calljavafunction2
176 .dword 0 /* catch type all */
177 .dword calljava_xhandler2 /* handler pc */
178 .dword calljava_xhandler2 /* end pc */
179 .dword asm_calljavafunction2 /* start pc */
180 .word 1 /* extable size */
181 .word 0 /* fltsave */
182 .word 1 /* intsave */
185 .word 12*8 /* frame size */
186 .dword 0 /* method pointer (pointer to name) */
188 asm_calljavafunction2:
189 asm_calljavafunction2int:
190 asm_calljavafunction2long:
191 asm_calljavafunction2float:
192 asm_calljavafunction2double:
193 aaddiu sp,sp,-12*8 /* allocate stack space (only 11 needed)*/
194 ast ra,0(sp) /* save return address */
198 ast pv,1*8(sp) /* procedure vector */
205 sdc1 fss0,5*8(sp) /* save non JavaABI saved flt registers */
212 ast a0,4*8(sp) /* save method pointer for compiler */
216 blez s7,calljava_argsloaded
218 ald a0,offjniitem(t0)
219 ldc1 fa0,offjniitem(t0)
221 blez s7,calljava_argsloaded
223 ald a1,offjniitem+sizejniblock*1(t0)
224 ldc1 fa1,offjniitem+sizejniblock*1(t0)
226 blez s7,calljava_argsloaded
228 ald a2,offjniitem+sizejniblock*2(t0)
229 ldc1 fa2,offjniitem+sizejniblock*2(t0)
231 blez s7,calljava_argsloaded
233 ald a3,offjniitem+sizejniblock*3(t0)
234 ldc1 fa3,offjniitem+sizejniblock*3(t0)
236 blez s7,calljava_argsloaded
238 ald a4,offjniitem+sizejniblock*4(t0)
239 ldc1 fa4,offjniitem+sizejniblock*4(t0)
241 blez s7,calljava_argsloaded
243 ald a5,offjniitem+sizejniblock*5(t0)
244 ldc1 fa5,offjniitem+sizejniblock*5(t0)
246 blez s7,calljava_argsloaded
248 ald a6,offjniitem+sizejniblock*6(t0)
249 ldc1 fa6,offjniitem+sizejniblock*6(t0)
251 blez s7,calljava_argsloaded
253 ald a7,offjniitem+sizejniblock*7(t0)
254 ldc1 fa7,offjniitem+sizejniblock*7(t0)
258 move t8,sp /* save stack pointer */
259 blez s7,calljava_nocopy
266 ald t3,offjniitem+sizejniblock*8(t0)
269 ala t0,sizejniblock(t0)
271 bnez t1,calljava_copyloop
274 ald itmp1,4*8(t8) /* pass method pointer via itmp1 */
276 ala mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
277 ast mptr,2*8(sp) /* store function address */
278 ala mptr,1*8(sp) /* set method pointer */
282 ald pv,1*8(mptr) /* method call as in Java */
283 jalr pv /* call JIT compiler */
285 aaddiu pv,ra,-76*4 /* recompute procedure vector */
290 ald ra,0(sp) /* restore return address */
291 ald pv,8(sp) /* restore procedure vector */
294 ldc1 fss0,5*8(sp) /* restore non JavaABI saved flt regs */
301 aaddiu sp,sp,12*8 /* free stack space */
308 jal builtin_throw_exception
311 .end asm_calljavafunction2
314 /****************** function asm_call_jit_compiler *****************************
316 * invokes the compiler for untranslated JavaVM methods. *
318 * Register REG_ITEMP1 contains a pointer to the method info structure *
319 * (prepared by createcompilerstub). Using the return address in R31 and the *
320 * offset in the LDA instruction or using the value in methodptr R25 the *
321 * patching address for storing the method address can be computed: *
323 * method address was either loaded using *
324 * M_ALD (REG_PV, REG_PV, a) ; invokestatic/special ($28) *
325 * M_JSR (REG_RA, REG_PV); *
327 * M_LDA (REG_PV, REG_RA, val) *
329 * M_ALD (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($25) *
330 * M_JSR (REG_RA, REG_PV); *
332 * in the static case the method pointer can be computed using the *
333 * return address and the lda function following the jmp instruction *
335 *******************************************************************************/
338 .ent asm_call_jit_compiler
340 asm_call_jit_compiler:
341 lw t0,-12(ra) /* load instruction LD PV,xxx($y) */
342 srl t0,t0,21 /* shift right register number $y */
343 and t0,t0,31 /* isolate register number */
344 addiu t0,t0,-mptrreg /* test for REG_METHODPTR */
347 lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
349 sra t0,t0,16 /* isolate offset */
350 aaddu mptr,t0,ra /* compute update address */
353 aaddiu sp,sp,-18*8 /* allocate stack space */
355 SAVE_ARGUMENT_REGISTERS(0)
357 sd mptr,16*8(sp) /* save method pointer */
358 sd ra,17*8(sp) /* save return address */
360 move a0,itmp1 /* pass 'methodinfo' pointer to */
361 jal jit_compile /* jit compiler */
363 RESTORE_ARGUMENT_REGISTERS(0)
365 ld mptr,16*8(sp) /* restore method pointer */
366 ld ra,17*8(sp) /* restore return address */
367 aaddiu sp,sp,18*8 /* deallocate stack area */
369 beqz v0,L_asm_call_jit_compiler_exception
371 lw t0,-12(ra) /* load instruction LDQ PV,xxx($yy) */
373 sra t0,t0,16 /* isolate offset */
375 aaddu t0,t0,mptr /* compute update address via method pointer*/
376 ast v0,0(t0) /* save new method address there */
378 move pv,v0 /* move method address into pv */
380 jr pv /* and call method. The method returns */
381 /* directly to the caller (ra). */
383 L_asm_call_jit_compiler_exception:
384 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
387 jal builtin_asm_get_exceptionptrptr
393 ald xptr,0(v0) /* get the exception pointer */
394 ast zero,0(v0) /* clear the exception pointer */
396 aaddiu xpc,ra,-4 /* faulting address is return adress - 4 */
397 b asm_handle_nat_exception
399 .end asm_call_jit_compiler
402 /********************* function asm_handle_exception ***************************
404 * This function handles an exception. It does not use the usual calling *
405 * conventions. The exception pointer is passed in REG_ITMP1 and the *
406 * pc from the exception raising position is passed in REG_ITMP2. It searches *
407 * the local exception table for a handler. If no one is found, it unwinds *
408 * stacks and continues searching the callers. *
410 * void asm_handle_exception (exceptionptr, exceptionpc); *
412 *******************************************************************************/
414 .ent asm_handle_nat_exception
416 asm_handle_nat_exception:
417 lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
419 sra t0,t0,16 /* isolate offset */
420 aaddu pv,t0,ra /* compute update address */
422 .aent asm_handle_exception
424 asm_handle_exception:
425 aaddiu sp,sp,-14*8 /* allocate stack */
427 sd v0,0*8(sp) /* save possible used registers */
428 sd t0,1*8(sp) /* also registers used by trace_exception */
442 addu t3,zero,1 /* set no unwind flag */
444 aaddiu sp,sp,-6*8 /* allocate stack */
445 sd xptr,0*8(sp) /* save used registers */
452 ald a1,MethodPointer(pv)
457 jal builtin_trace_exception /* trace_exception(xptr,methodptr) */
459 ld xptr,0*8(sp) /* restore used register */
464 aaddiu sp,sp,6*8 /* deallocate stack */
466 lw t0,ExTableSize(pv) /* t0 = exception table size */
467 beqz t0,empty_table /* if empty table skip */
468 aaddiu t1,pv,ExTableStart /* t1 = start of exception table */
471 ald t2,ExStartPC(t1) /* t2 = exception start pc */
472 sle t2,t2,xpc /* t2 = (startpc <= xpc) */
473 beqz t2,ex_table_cont /* if (false) continue */
474 ald t2,ExEndPC(t1) /* t2 = exception end pc */
475 slt t2,xpc,t2 /* t2 = (xpc < endpc) */
476 beqz t2,ex_table_cont /* if (false) continue */
477 ald a1,ExCatchType(t1) /* arg1 = exception catch type */
478 beqz a1,ex_handle_it /* NULL catches everything */
480 lw itmp3,offclassloaded(a1)
481 bnez itmp3,L_class_loaded
483 aaddiu sp,sp,-8*8 /* allocate stack */
484 sd t0,0*8(sp) /* save used register */
494 jal load_class_bootstrap
496 ld t0,0*8(sp) /* restore used register */
504 aaddiu sp,sp,8*8 /* deallocate stack */
507 lw itmp3,offclasslinked(a1)
508 aaddiu sp,sp,-8*8 /* allocate stack */
510 bnez itmp3,L_class_linked
512 sd t0,0*8(sp) /* save used register */
523 ld t0,0*8(sp) /* restore used register */
535 ald a0,offobjvftbl(xptr) /* a0 = vftblptr(xptr) */
536 ald a1,offclassvftbl(a1) /* a1 = vftblptr(catchtype) class (not obj) */
537 lw a0,offbaseval(a0) /* a0 = baseval(xptr) */
538 lw v0,offbaseval(a1) /* a2 = baseval(catchtype) */
539 lw a1,offdiffval(a1) /* a1 = diffval(catchtype) */
541 subu a0,a0,v0 /* a0 = baseval(xptr) - baseval(catchtype) */
542 sltu v0,a1,a0 /* v0 = xptr is instanceof catchtype */
543 aaddiu sp,sp,8*8 /* deallocate stack */
544 bnez v0,ex_table_cont /* if (false) continue */
547 ald xpc,ExHandlerPC(t1) /* xpc = exception handler pc */
549 beqz t3,ex_jump /* if (!(no stack unwinding) skip */
551 ld v0,0*8(sp) /* restore possible used registers */
552 ld t0,1*8(sp) /* also registers used by trace_exception */
566 aaddiu sp,sp,14*8 /* deallocate stack */
569 jr xpc /* jump to the handler */
572 aaddiu t1,t1,ExEntrySize /* next exception table entry */
573 addiu t0,t0,-1 /* decrement entry counter */
574 bgtz t0,ex_table_loop /* if (t0 > 0) next entry */
577 beqz t3,ex_already_cleared /* if here the first time, then */
578 aaddiu sp,sp,14*8 /* deallocate stack and */
579 move t3,zero /* clear the no unwind flag */
581 lw t0,IsSync(pv) /* t0 = SyncOffset */
582 beqz t0,no_monitor_exit /* if zero no monitorexit */
584 #if defined(USE_THREADS)
585 aaddu t0,sp,t0 /* add stackptr to Offset */
586 ald a0,-8(t0) /* load monitorexit pointer */
588 aaddiu sp,sp,-8*8 /* allocate stack */
589 sd t0,0*8(sp) /* save used register */
597 jal builtin_monitorexit /* builtin_monitorexit(objectptr) */
599 ld t0,0*8(sp) /* restore used register */
606 aaddiu sp,sp,8*8 /* deallocate stack */
610 lw t0,FrameSize(pv) /* t0 = frame size */
611 aaddu sp,sp,t0 /* unwind stack */
612 move t0,sp /* t0 = pointer to save area */
613 lw t1,IsLeaf(pv) /* t1 = is leaf procedure */
614 bnez t1,ex_no_restore /* if (leaf) skip */
615 ld ra,-8(t0) /* restore ra */
616 aaddiu t0,t0,-8 /* t0-- */
618 move xpc,ra /* the new xpc is ra */
619 lw t1,IntSave(pv) /* t1 = saved int register count */
620 ala t2,ex_int2 /* t2 = current pc */
621 sll t1,t1,2 /* t1 = register count * 4 */
622 asubu t2,t2,t1 /* t2 = ex_int_sav - 4 * register count */
623 jr t2 /* jump to save position */
633 sll t1,t1,1 /* t1 = register count * 4 * 2 */
634 asubu t0,t0,t1 /* t0 = t0 - 8 * register count */
636 lw t1,FltSave(pv) /* t1 = saved flt register count */
637 ala t2,ex_flt2 /* t2 = current pc */
638 sll t1,t1,2 /* t1 = register count * 4 */
639 asubu t2,t2,t1 /* t2 = ex_int_sav - 4 * register count */
640 jr t2 /* jump to save position */
646 lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
648 sra t0,t0,16 /* isolate offset */
649 aaddu pv,t0,ra /* compute update address */
652 .end asm_handle_nat_exception
655 /* asm_wrapper_patcher *********************************************************
660 32 return address into JIT code (patch position)
661 24 pointer to virtual java_objectheader
662 16 machine code (which is patched back later)
663 8 unresolved class/method/field reference
664 0 patcher function pointer to call
666 *******************************************************************************/
668 .ent asm_wrapper_patcher
671 aaddiu sp,sp,-(16+21+4+1)*8 /* create stack frame */
673 SAVE_ARGUMENT_REGISTERS(0) /* save 8 int/8 float argument registers */
674 SAVE_TEMPORARY_REGISTERS(16) /* save 5 int/16 float temporary registers */
676 ast itmp1,(16+21+0)*8(sp) /* save itmp1 */
677 ast itmp2,(16+21+1)*8(sp) /* save itmp2 */
678 ast ra,(16+21+2+1)*8(sp) /* save method return address (for leafs) */
679 ast pv,(16+21+3+1)*8(sp) /* save pv of calling java function */
681 aaddiu a0,sp,(0+16+21+4+1)*8 /* pass sp */
682 ald itmp3,(0+16+21+4+1)*8(sp) /* get function pointer */
683 ald itmp1,(16+21+3+1)*8(sp) /* save pv to the position of fp */
684 ast itmp1,(0+16+21+4+1)*8(sp)
687 RESTORE_ARGUMENT_REGISTERS(0) /* restore 8 int/8 float argument registers */
688 RESTORE_TEMPORARY_REGISTERS(16) /* restore 5 int/16 float temporary reg. */
690 ald itmp1,(16+21+0)*8(sp) /* restore itmp1 */
691 ald itmp2,(16+21+1)*8(sp) /* restore itmp2 */
692 ald ra,(16+21+2+1)*8(sp) /* restore method return address (for leafs)*/
693 ald pv,(16+21+3+1)*8(sp) /* restore pv of calling java function */
695 ald itmp3,(4+16+21+4+1)*8(sp) /* get return address (into JIT code) */
696 aaddiu sp,sp,(5+16+21+4+1)*8 /* remove stack frame */
698 beqz v0,L_asm_wrapper_patcher_exception
700 jr itmp3 /* jump to new patched code */
702 L_asm_wrapper_patcher_exception:
703 move xpc,itmp3 /* return address into JIT code is xpc */
705 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
710 jal builtin_asm_get_exceptionptrptr
718 ld xptr,0(v0) /* get the exception pointer */
719 sd zero,0(v0) /* clear the exception pointer */
720 b asm_handle_exception
722 .end asm_wrapper_patcher
725 /******************* function asm_initialize_thread_stack **********************
727 * u1* asm_initialize_thread_stack (void *func, u1 *stack); *
729 * initialize a thread stack *
731 *******************************************************************************/
733 .ent asm_initialize_thread_stack
735 asm_initialize_thread_stack:
736 aaddiu a1,a1,-14*8 /* allocate save area */
737 sd zero, 0*8(a1) /* s0 initalize thread area */
738 sd zero, 1*8(a1) /* s1 */
739 sd zero, 2*8(a1) /* s2 */
740 sd zero, 3*8(a1) /* s3 */
741 sd zero, 4*8(a1) /* s4 */
742 sd zero, 5*8(a1) /* s5 */
743 sd zero, 6*8(a1) /* s6 */
744 sd zero, 7*8(a1) /* s7 */
745 sd zero, 8*8(a1) /* s8 */
746 sd zero, 9*8(a1) /* fs0 */
747 sd zero,10*8(a1) /* fs1 */
748 sd zero,11*8(a1) /* fs2 */
749 sd zero,12*8(a1) /* fs3 */
754 .end asm_initialize_thread_stack
757 /******************* function asm_perform_threadswitch *************************
759 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
761 * performs a threadswitch *
763 *******************************************************************************/
765 .ent asm_perform_threadswitch
767 asm_perform_threadswitch:
768 aaddiu sp,sp,-14*8 /* allocate new stack */
769 sd s0, 0*8(sp) /* save saved registers of old thread */
783 ast sp,0(a0) /* save old stack pointer */
784 ast sp,0(a2) /* stackTop = old stack pointer */
785 ald sp,0(a1) /* load new stack pointer */
786 ld s0, 0*8(sp) /* load saved registers of new thread */
800 aaddiu sp,sp,14*8 /* deallocate new stack */
804 .end asm_perform_threadswitch
807 /********************* function asm_switchstackandcall *************************
809 * void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
811 * Switches to a new stack, calls a function and switches back. *
812 * a0 new stack pointer *
813 * a1 function pointer *
814 * a2 pointer to variable where stack top should be stored *
816 *******************************************************************************/
818 .ent asm_switchstackandcall
820 asm_switchstackandcall:
821 aaddiu a0,a0,-16 /* allocate new stack */
822 sd ra,0(a0) /* save return address on new stack */
823 sd sp,8(a0) /* save old stack pointer on new stack */
824 sd sp,0(a2) /* save old stack pointer to variable */
825 move sp,a0 /* switch to new stack */
829 jalr itmp3 /* and call function */
831 ld ra,0(sp) /* load return address */
832 ld sp,8(sp) /* switch to old stack */
836 .end asm_switchstackandcall
839 .ent asm_getclassvalues_atomic
841 asm_getclassvalues_atomic:
848 sw t0,offcast_super_baseval(a2)
849 sw t1,offcast_super_diffval(a2)
850 sw t2,offcast_sub_baseval(a2)
853 .end asm_getclassvalues_atomic
857 asm_criticalsections:
858 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
861 .dword _crit_restart1
864 .dword _crit_restart2
871 .ent compare_and_swap
884 .end compare_and_swap
888 * These are local overrides for various environment variables in Emacs.
889 * Please do not remove this and leave it at the end of the file, where
890 * Emacs will automagically detect them.
891 * ---------------------------------------------------------------------
894 * indent-tabs-mode: t