1 /* -*- mode: asm; tab-width: 4 -*- */
2 /****************************** asmpart.c **************************************
4 * is an assembly language file, but called .c to fake the preprocessor. *
5 * It contains the Java-C interface functions for Alpha processors. *
7 * Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst *
9 * See file COPYRIGHT for information on usage and disclaimer of warranties *
11 * Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at *
12 * Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at *
14 * Last Change: 1998/11/01 *
16 *******************************************************************************/
85 /********************* exported functions and variables ***********************/
87 .globl has_no_x_instr_set
88 .globl synchronize_caches
89 .globl asm_calljavamethod
90 .globl asm_call_jit_compiler
91 .globl asm_dumpregistersandcall
92 .globl asm_handle_exception
93 .globl asm_handle_nat_exception
94 .globl asm_builtin_checkarraycast
95 .globl asm_builtin_aastore
96 .globl asm_builtin_monitorenter
97 .globl asm_builtin_monitorexit
98 .globl asm_builtin_idiv
99 .globl asm_builtin_irem
100 .globl asm_builtin_ldiv
101 .globl asm_builtin_lrem
102 .globl perform_alpha_threadswitch
103 .globl initialize_thread_stack
104 .globl asm_switchstackandcall
107 /*************************** imported variables *******************************/
112 /*************************** imported functions *******************************/
115 .globl builtin_monitorexit
116 .globl builtin_throw_exception
117 .globl builtin_trace_exception
118 .globl class_java_lang_Object
121 /*********************** function has_no_x_instr_set ***************************
123 * determines if the byte support instruction set (21164a and higher) *
126 *******************************************************************************/
128 .ent has_no_x_instr_set
131 .long 0x47e03c20 /* amask 1,v0 */
132 jmp zero,(ra) /* return */
134 .end has_no_x_instr_set
137 /********************* function synchronize_caches ****************************/
139 .ent synchronize_caches
142 call_pal PAL_imb /* synchronise instruction cache */
143 jmp zero,(ra) /* return */
145 .end synchronize_caches
148 /********************* function asm_calljavamethod *****************************
150 * This function calls a Java-method (which possibly needs compilation) *
151 * with up to 4 parameters. *
153 * This functions calls the JIT-compiler which eventually translates the *
154 * method into machine code. *
156 * An possibly throwed exception will be returned to the caller as function *
157 * return value, so the java method cannot return a fucntion value (this *
158 * function usually calls 'main' and '<clinit>' which do not return a *
162 * javaobject_header *asm_calljavamethod (methodinfo *m, *
163 * void *arg1, void *arg2, void *arg3, void *arg4); *
165 *******************************************************************************/
167 #define MethodPointer -8
168 #define FrameSize -12
173 #define ExTableSize -32
174 #define ExTableStart -32
176 #define ExEntrySize -32
179 #define ExHandlerPC -24
180 #define ExCatchType -32
182 .ent asm_calljavamethod
185 .ascii "calljavamethod\0\0"
188 .quad 0 /* catch type all */
189 .quad calljava_xhandler /* end pc */
190 .quad calljava_xhandler /* end pc */
191 .quad asm_calljavamethod /* start pc */
192 .long 1 /* extable size */
193 .long 0 /* fltsave */
194 .long 0 /* intsave */
197 .long 32 /* frame size */
198 .quad 0 /* method pointer (pointer to name) */
203 lda sp,-32(sp) /* allocate stack space */
204 stq gp,24(sp) /* save global pointer */
205 stq ra,0(sp) /* save return address */
207 stq a0,16(sp) /* save method pointer for compiler */
208 lda v0,16(sp) /* pass pointer to method pointer via v0*/
210 mov a1,a0 /* pass the remaining parameters */
215 lda $28,asm_call_jit_compiler /* fake virtual function call (2 instr) */
216 stq $28,8(sp) /* store function address */
217 mov sp,$28 /* set method pointer */
219 ldq pv,8($28) /* method call as in Java */
220 jmp ra,(pv) /* call JIT compiler */
222 lda pv,-64(ra) /* asm_calljavamethod-calljava_jit !!!!!*/
226 ldq ra,0(sp) /* restore return address */
227 ldq gp,24(sp) /* restore global pointer */
228 lda sp,32(sp) /* free stack space */
229 ldl v0,newcompiler /* load newcompiler flag */
230 subq v0,1,v0 /* negate for clearing v0 */
231 beq v0,calljava_ret /* if newcompiler skip ex copying */
232 mov $1,v0 /* pass exception to caller (C) */
238 ldq gp,24(sp) /* restore global pointer */
240 jsr ra,builtin_throw_exception
241 ldq ra,0(sp) /* restore return address */
242 lda sp,32(sp) /* free stack space */
244 .end asm_calljavamethod
247 /****************** function asm_call_jit_compiler *****************************
249 * invokes the compiler for untranslated JavaVM methods. *
251 * Register R0 contains a pointer to the method info structure (prepared *
252 * by createcompilerstub). Using the return address in R26 and the *
253 * offset in the LDA instruction or using the value in methodptr R28 the *
254 * patching address for storing the method address can be computed: *
256 * method address was either loaded using *
257 * M_LDQ (REG_PV, REG_PV, a) ; invokestatic/special ($27) *
258 * M_LDA (REG_PV, REG_RA, low) *
259 * M_LDAH(REG_PV, REG_RA, high) ; optional *
261 * M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($28) *
262 * in the static case the method pointer can be computed using the *
263 * return address and the lda function following the jmp instruction *
265 *******************************************************************************/
268 .ent asm_call_jit_compiler
269 asm_call_jit_compiler:
272 ldl t8,-8(ra) /* load instruction LDQ PV,xxx($yy) */
273 srl t8,16,t8 /* shift right register number $yy */
274 and t8,31,t8 /* isolate register number */
275 subl t8,28,t8 /* test for REG_METHODPTR */
277 ldl t8,0(ra) /* load instruction LDA PV,xxx(RA) */
279 sra t8,48,t8 /* isolate offset */
280 addq t8,ra,$28 /* compute update address */
281 ldl t8,4(ra) /* load instruction LDAH PV,xxx(PV) */
282 srl t8,16,t8 /* isolate instruction code */
283 lda t8,-0x177b(t8) /* test for LDAH */
285 ldl t8,4(ra) /* load instruction LDAH PV,xxx(PV) */
286 sll t8,16,t8 /* compute high offset */
287 addl t8,0,t8 /* sign extend high offset */
288 addq t8,$28,$28 /* compute update address */
290 lda sp,-14*8(sp) /* reserve stack space */
291 stq a0,0*8(sp) /* save all argument registers */
292 stq a1,1*8(sp) /* they could be used by method */
303 stq $28,12*8(sp) /* save method pointer */
304 stq ra,13*8(sp) /* save return address */
306 ldq a0,0(v0) /* pass 'methodinfo' pointer to */
307 jsr ra,jit_compile /* jit compiler */
310 call_pal PAL_imb /* synchronise instruction cache */
312 ldq a0,0*8(sp) /* load argument registers */
324 ldq $28,12*8(sp) /* load method pointer */
325 ldq ra,13*8(sp) /* load return address */
326 lda sp,14*8(sp) /* deallocate stack area */
328 ldl t8,-8(ra) /* load instruction LDQ PV,xxx($yy) */
330 sra t8,48,t8 /* isolate offset */
332 addq t8,$28,t8 /* compute update address via method pointer*/
333 stq v0,0(t8) /* save new method address there */
335 mov v0,pv /* load method address into pv */
337 jmp zero,(pv) /* and call method. The method returns */
338 /* directly to the caller (ra). */
340 .end asm_call_jit_compiler
343 /****************** function asm_dumpregistersandcall **************************
345 * This funtion saves all callee saved registers and calls the function *
346 * which is passed as parameter. *
348 * This function is needed by the garbage collector, which needs to access *
349 * all registers which are stored on the stack. Unused registers are *
350 * cleared to avoid interferances with the GC. *
352 * void asm_dumpregistersandcall (functionptr f); *
354 *******************************************************************************/
356 .ent asm_dumpregistersandcall
357 asm_dumpregistersandcall:
358 lda sp,-16*8(sp) /* allocate stack */
359 stq ra,0(sp) /* save return address */
361 stq s0,1*8(sp) /* save all callee saved registers */
362 stq s1,2*8(sp) /* intialize the remaining registers */
377 clr v0 /* intialize the remaining registers */
422 mov a0,pv /* load function pointer */
423 jmp ra,(pv) /* and call function */
425 ldq ra,0(sp) /* load return address */
426 lda sp,16*8(sp) /* deallocate stack */
427 jmp zero,(ra) /* return */
429 .end asm_dumpregistersandcall
432 /********************* function asm_handle_exception ***************************
434 * This function handles an exception. It does not use the usual calling *
435 * conventions. The exception pointer is passed in REG_ITMP1 and the *
436 * pc from the exception raising position is passed in REG_ITMP2. It searches *
437 * the local exception table for a handler. If no one is found, it unwinds *
438 * stacks and continues searching the callers. *
440 * void asm_handle_exception (exceptionptr, exceptionpc); *
442 *******************************************************************************/
444 .ent asm_handle_nat_exception
445 asm_handle_nat_exception:
447 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
449 sra t0,48,t0 /* isolate offset */
450 addq t0,ra,pv /* compute update address */
451 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
452 srl t0,16,t0 /* isolate instruction code */
453 lda t0,-0x177b(t0) /* test for LDAH */
454 bne t0,asm_handle_exception
455 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
456 sll t0,16,t0 /* compute high offset */
457 addl t0,0,t0 /* sign extend high offset */
458 addq t0,pv,pv /* compute update address */
460 .aent asm_handle_exception
461 asm_handle_exception:
463 lda sp,-18*8(sp) /* allocate stack */
464 stq t0,0*8(sp) /* save possible used registers */
465 stq t1,1*8(sp) /* also registers used by trace_exception */
483 lda t3,1(zero) /* set no unwind flag */
485 lda sp,-5*8(sp) /* allocate stack */
486 stq xptr,0*8(sp) /* save used register */
493 ldq a1,MethodPointer(pv)
496 br ra,ex_trace /* set ra for gp loading */
498 ldgp gp,0(ra) /* load gp */
499 jsr ra,builtin_trace_exception /* trace_exception(xptr,methodptr) */
501 ldq xptr,0*8(sp) /* restore used register */
506 lda sp,5*8(sp) /* deallocate stack */
508 ldl t0,ExTableSize(pv) /* t0 = exception table size */
509 beq t0,empty_table /* if empty table skip */
510 lda t1,ExTableStart(pv) /* t1 = start of exception table */
513 ldq t2,ExStartPC(t1) /* t2 = exception start pc */
514 cmple t2,xpc,t2 /* t2 = (startpc <= xpc) */
515 beq t2,ex_table_cont /* if (false) continue */
516 ldq t2,ExEndPC(t1) /* t2 = exception end pc */
517 cmplt xpc,t2,t2 /* t2 = (xpc < endpc) */
518 beq t2,ex_table_cont /* if (false) continue */
519 ldq a1,ExCatchType(t1) /* arg1 = exception catch type */
520 beq a1,ex_handle_it /* NULL catches everything */
522 ldq a0,offobjvftbl(xptr) /* a0 = vftblptr(xptr) */
523 ldq a1,offobjvftbl(a1) /* a1 = vftblptr(catchtype) class (not obj) */
524 ldl a0,offbaseval(a0) /* a0 = baseval(xptr) */
525 ldl v0,offbaseval(a1) /* a2 = baseval(catchtype) */
526 ldl a1,offdiffval(a1) /* a1 = diffval(catchtype) */
527 subl a0,v0,a0 /* a0 = baseval(xptr) - baseval(catchtype) */
528 cmpule a0,a1,v0 /* v0 = xptr is instanceof catchtype */
529 beq v0,ex_table_cont /* if (false) continue */
533 ldq xpc,ExHandlerPC(t1) /* xpc = exception handler pc */
535 beq t3,ex_jump /* if (!(no stack unwinding) skip */
537 ldq t0,0*8(sp) /* restore possible used registers */
538 ldq t1,1*8(sp) /* also registers used by trace_exception */
555 lda sp,18*8(sp) /* deallocate stack */
558 jmp zero,(xpc) /* jump to the handler */
561 lda t1,ExEntrySize(t1) /* next exception table entry */
562 subl t0,1,t0 /* decrement entry counter */
563 bgt t0,ex_table_loop /* if (t0 > 0) next entry */
566 beq t3,ex_already_cleared /* if here the first time, then */
567 lda sp,18*8(sp) /* deallocate stack and */
568 clr t3 /* clear the no unwind flag */
570 ldl t0,IsSync(pv) /* t0 = SyncOffset */
571 beq t0,no_monitor_exit /* if zero no monitorexit */
572 addq sp,t0,t0 /* add Offset to stackptr */
573 ldq a0,-8(t0) /* load monitorexit pointer */
575 lda sp,-7*8(sp) /* allocate stack */
576 stq t0,0*8(sp) /* save used register */
584 br ra,ex_mon_load /* set ra for gp loading */
586 ldgp gp,0(ra) /* load gp */
587 jsr ra,builtin_monitorexit/* builtin_monitorexit(objectptr) */
589 ldq t0,0*8(sp) /* restore used register */
596 lda sp,7*8(sp) /* deallocate stack */
599 ldl t0,FrameSize(pv) /* t0 = frame size */
600 addq sp,t0,sp /* unwind stack */
601 mov sp,t0 /* t0 = pointer to save area */
602 ldl t1,IsLeaf(pv) /* t1 = is leaf procedure */
603 bne t1,ex_no_restore /* if (leaf) skip */
604 ldq ra,-8(t0) /* restore ra */
605 lda t0,-8(t0) /* t0-- */
607 mov ra,xpc /* the new xpc is ra */
608 ldl t1,IntSave(pv) /* t1 = saved int register count */
609 br t2,ex_int1 /* t2 = current pc */
611 lda t2,44(t2) /* lda t2,ex_int2-ex_int1(t2) !!!!!!!!!!!!! */
612 negl t1,t1 /* negate register count */
613 s4addq t1,t2,t2 /* t2 = ex_int_sav - 4 * register count */
614 jmp zero,(t2) /* jump to save position */
623 s8addq t1,t0,t0 /* t0 = t0 - 8 * register count */
625 ldl t1,FltSave(pv) /* t1 = saved flt register count */
626 br t2,ex_flt1 /* t2 = current pc */
628 lda t2,48(t2) /* lda t2,ex_flt2-ex_flt1(t2) !!!!!!!!!!!!! */
629 negl t1,t1 /* negate register count */
630 s4addq t1,t2,t2 /* t2 = ex_flt_sav - 4 * register count */
631 jmp zero,(t2) /* jump to save position */
641 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
643 sra t0,48,t0 /* isolate offset */
644 addq t0,ra,pv /* compute update address */
645 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
646 srl t0,16,t0 /* isolate instruction code */
647 lda t0,-0x177b(t0) /* test for LDAH */
649 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
650 sll t0,16,t0 /* compute high offset */
651 addl t0,0,t0 /* sign extend high offset */
652 addq t0,pv,pv /* compute update address */
655 .end asm_handle_exception
658 /********************* function asm_builtin_monitorenter ***********************
660 * Does null check and calls monitorenter or throws an exception *
662 *******************************************************************************/
664 .ent asm_builtin_monitorenter
665 asm_builtin_monitorenter:
668 lda pv,builtin_monitorenter
669 beq a0,nb_monitorenter /* if (null) throw exception */
670 jmp zero,(pv) /* else call builtin_monitorenter */
673 ldq xptr,proto_java_lang_NullPointerException
674 lda xpc,-4(ra) /* faulting address is return adress - 4*/
675 br asm_handle_nat_exception
676 .end asm_builtin_monitorenter
679 /********************* function asm_builtin_monitorexit ************************
681 * Does null check and calls monitorexit or throws an exception *
683 *******************************************************************************/
685 .ent asm_builtin_monitorexit
686 asm_builtin_monitorexit:
689 lda pv,builtin_monitorexit
690 beq a0,nb_monitorexit /* if (null) throw exception */
691 jmp zero,(pv) /* else call builtin_monitorexit */
694 ldq xptr,proto_java_lang_NullPointerException
695 lda xpc,-4(ra) /* faulting address is return adress - 4*/
696 br asm_handle_nat_exception
697 .end asm_builtin_monitorenter
700 /************************ function asm_builtin_idiv ****************************
702 * Does null check and calls idiv or throws an exception *
704 *******************************************************************************/
706 .ent asm_builtin_idiv
711 beq a1,nb_idiv /* if (null) throw exception */
712 jmp zero,(pv) /* else call builtin_idiv */
715 ldq xptr,proto_java_lang_ArithmeticException
716 lda xpc,-4(ra) /* faulting address is return adress - 4*/
717 br asm_handle_nat_exception
718 .end asm_builtin_idiv
721 /************************ function asm_builtin_ldiv ****************************
723 * Does null check and calls ldiv or throws an exception *
725 *******************************************************************************/
727 .ent asm_builtin_ldiv
732 beq a1,nb_ldiv /* if (null) throw exception */
733 jmp zero,(pv) /* else call builtin_ldiv */
736 ldq xptr,proto_java_lang_ArithmeticException
737 lda xpc,-4(ra) /* faulting address is return adress - 4*/
738 br asm_handle_nat_exception
739 .end asm_builtin_ldiv
742 /************************ function asm_builtin_irem ****************************
744 * Does null check and calls irem or throws an exception *
746 *******************************************************************************/
748 .ent asm_builtin_irem
753 beq a1,nb_irem /* if (null) throw exception */
754 jmp zero,(pv) /* else call builtin_irem */
757 ldq xptr,proto_java_lang_ArithmeticException
758 lda xpc,-4(ra) /* faulting address is return adress - 4*/
759 br asm_handle_nat_exception
760 .end asm_builtin_irem
763 /************************ function asm_builtin_lrem ****************************
765 * Does null check and calls lrem or throws an exception *
767 *******************************************************************************/
769 .ent asm_builtin_lrem
774 beq a1,nb_lrem /* if (null) throw exception */
775 jmp zero,(pv) /* else call builtin_lrem */
778 ldq xptr,proto_java_lang_ArithmeticException
779 lda xpc,-4(ra) /* faulting address is return adress - 4*/
780 br asm_handle_nat_exception
781 .end asm_builtin_lrem
784 /******************* function asm_builtin_checkarraycast ***********************
786 * Does the cast check and eventually throws an exception *
788 *******************************************************************************/
790 .ent asm_builtin_checkarraycast
791 asm_builtin_checkarraycast:
794 lda sp,-16(sp) /* allocate stack space */
795 stq ra,0(sp) /* save return address */
796 stq a0,8(sp) /* save object pointer */
797 jsr ra,builtin_checkarraycast /* builtin_checkarraycast */
799 beq v0,nb_carray_throw /* if (false) throw exception */
800 ldq ra,0(sp) /* restore return address */
801 ldq v0,8(sp) /* return object pointer */
802 lda sp,16(sp) /* free stack space */
806 ldq xptr,proto_java_lang_ClassCastException
807 ldq ra,0(sp) /* restore return address */
808 lda sp,16(sp) /* free stack space */
809 lda xpc,-4(ra) /* faulting address is return adress - 4*/
810 br asm_handle_nat_exception
811 .end asm_builtin_checkarraycast
814 /******************* function asm_builtin_aastore ******************************
816 * Does the cast check and eventually throws an exception *
818 *******************************************************************************/
820 .ent asm_builtin_aastore
824 beq a0,nb_aastore_null /* if null pointer throw exception */
825 ldl t0,offarraysize(a0) /* load size */
826 lda sp,-24(sp) /* allocate stack space */
827 stq ra,0(sp) /* save return address */
828 s8addq a1,a0,t1 /* add index*8 to arrayref */
829 cmpult a1,t0,t0 /* do bound check */
830 beq t0,nb_aastore_bound /* if out of bounds throw exception */
831 mov a2,a1 /* object is second argument */
832 stq t1,8(sp) /* save store position */
833 stq a1,16(sp) /* save object */
834 jsr ra,builtin_canstore /* builtin_canstore(arrayref,object) */
836 ldq ra,0(sp) /* restore return address */
837 ldq a0,8(sp) /* restore store position */
838 ldq a1,16(sp) /* restore object */
839 lda sp,24(sp) /* free stack space */
840 beq v0,nb_aastore_throw /* if (false) throw exception */
841 stq a1,offobjarrdata(a0) /* store objectptr in array */
845 ldq xptr,proto_java_lang_NullPointerException
846 mov ra,xpc /* faulting address is return adress */
847 br asm_handle_nat_exception
850 ldq xptr,proto_java_lang_ArrayIndexOutOfBoundsException
851 lda sp,24(sp) /* free stack space */
852 mov ra,xpc /* faulting address is return adress */
853 br asm_handle_nat_exception
856 ldq xptr,proto_java_lang_ArrayStoreException
857 mov ra,xpc /* faulting address is return adress */
858 br asm_handle_nat_exception
860 .end asm_builtin_aastore
863 /********************** function initialize_thread_stack ***********************
865 * initialized a thread stack *
867 *******************************************************************************/
869 .ent initialize_thread_stack
870 initialize_thread_stack:
891 .end initialize_thread_stack
894 /******************* function perform_alpha_threadswitch ***********************
896 * void perform_alpha_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
898 * performs a threadswitch *
900 *******************************************************************************/
902 .ent perform_alpha_threadswitch
903 perform_alpha_threadswitch:
944 .end perform_alpha_threadswitch
947 /********************* function asm_switchstackandcall *************************
949 * void asm_switchstackandcall (void *stack, void *func); *
951 * Switches to a new stack, calls a function and switches back. *
952 * a0 new stack pointer *
953 * a1 function pointer *
955 *******************************************************************************/
958 .ent asm_switchstackandcall
959 asm_switchstackandcall:
960 lda a0,-2*8(a0) /* allocate new stack */
961 stq ra,0(a0) /* save return address */
962 stq sp,1*8(a0) /* save old stack pointer */
963 mov a0,sp /* switch to new stack */
965 mov a1,pv /* load function pointer */
966 jmp ra,(pv) /* and call funciton */
968 ldq ra,0(sp) /* load return address */
969 ldq sp,1*8(sp) /* switch to old stack */
971 jmp zero,(ra) /* return */
973 .end asm_switchstackandcall