1 /* src/vm/jit/alpha/asmpart.S - Java-C interface functions for alpha
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Joseph Wenninger
33 $Id: asmpart.S 4561 2006-03-05 23:53:19Z twisti $
40 #include "vm/jit/alpha/md-abi.h"
41 #include "vm/jit/alpha/md-asm.h"
42 #include "vm/jit/alpha/offsets.h"
44 #include "vm/jit/abi.h"
45 #include "vm/jit/methodheader.h"
53 /********************* exported functions and variables ***********************/
57 .globl asm_sync_instruction_cache
59 .globl asm_vm_call_method
60 .globl asm_vm_call_method_int
61 .globl asm_vm_call_method_long
62 .globl asm_vm_call_method_float
63 .globl asm_vm_call_method_double
65 .globl asm_call_jit_compiler
66 .globl asm_handle_exception
67 .globl asm_handle_nat_exception
69 .globl asm_wrapper_patcher
71 .globl asm_perform_threadswitch
72 .globl asm_initialize_thread_stack
73 .globl asm_switchstackandcall
74 .globl asm_criticalsections
75 .globl asm_getclassvalues_atomic
78 /* asm_sync_instruction_cache **************************************************
82 *******************************************************************************/
84 .ent asm_sync_instruction_cache
86 asm_sync_instruction_cache:
87 call_pal PAL_imb /* synchronize instruction cache */
90 .end asm_sync_instruction_cache
93 /* asm_md_init *****************************************************************
95 Initialize machine dependent stuff.
97 Determines if the byte support instruction set (21164a and higher)
100 *******************************************************************************/
106 .long 0x47e03c20 /* amask 1,v0 */
107 jmp zero,(ra) /* return */
112 /* asm_vm_call_method **********************************************************
114 * This function calls a Java-method (which possibly needs compilation) *
115 * with up to 4 address parameters. *
117 * This functions calls the JIT-compiler which eventually translates the *
118 * method into machine code. *
121 * javaobject_header *asm_calljavafunction (methodinfo *m, *
122 * void *arg1, void *arg2, void *arg3, void *arg4); *
124 *******************************************************************************/
126 .ent asm_vm_call_method
130 .quad 0 /* catch type all */
131 .quad calljava_xhandler2 /* handler pc */
132 .quad calljava_xhandler2 /* end pc */
133 .quad asm_vm_call_method /* start pc */
134 .long 1 /* extable size */
135 .long 0 /* ALIGNMENT PADDING */
136 .quad 0 /* line number table start */
137 .quad 0 /* line number table size */
138 .long 0 /* ALIGNMENT PADDING */
139 .long 0 /* fltsave */
140 .long 1 /* intsave */
143 .long 0 /* frame size */
144 .quad 0 /* method pointer (pointer to name) */
147 asm_vm_call_method_int:
148 asm_vm_call_method_long:
149 asm_vm_call_method_float:
150 asm_vm_call_method_double:
152 lda sp,-5*8(sp) /* allocate stack space */
153 stq ra,0*8(sp) /* save return address */
154 stq gp,1*8(sp) /* save global pointer */
157 stq a0,4*8(sp) /* save method pointer for compiler */
159 mov a2,t0 /* pointer to arg block */
160 mov a1,s6 /* arg count */
162 ble s6,calljava_argsloaded
164 ldq a0,offvmargdata(t0)
165 ldt $f16,offvmargdata(t0)
166 ble s6,calljava_argsloaded
169 ldq a1,offvmargdata+sizevmarg*1(t0)
170 ldt $f17,offvmargdata+sizevmarg*1(t0)
171 ble s6,calljava_argsloaded
174 ldq a2,offvmargdata+sizevmarg*2(t0)
175 ldt $f18,offvmargdata+sizevmarg*2(t0)
176 ble s6,calljava_argsloaded
179 ldq a3,offvmargdata+sizevmarg*3(t0)
180 ldt $f19,offvmargdata+sizevmarg*3(t0)
181 ble s6,calljava_argsloaded
184 ldq a4,offvmargdata+sizevmarg*4(t0)
185 ldt $f20,offvmargdata+sizevmarg*4(t0)
186 ble s6,calljava_argsloaded
189 ldq a5,offvmargdata+sizevmarg*5(t0)
190 ldt $f21,offvmargdata+sizevmarg*5(t0)
193 ble s6,calljava_nocopy
199 ldq t3,offvmargdata+sizevmarg*6(t0)
204 bne t1,calljava_copyloop
207 ldq itmp1,4*8(t4) /* pass method pointer via itmp1 */
209 lda mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
210 stq mptr,2*8(t4) /* store function address */
211 lda mptr,1*8(t4) /* set method pointer */
213 ldq pv,1*8(mptr) /* method call as in Java */
214 jmp ra,(pv) /* call JIT compiler */
216 lda pv,(asm_vm_call_method - calljava_jit2)(ra)
220 ldq ra,0*8(sp) /* restore return address */
221 ldq gp,1*8(sp) /* restore global pointer */
223 lda sp,5*8(sp) /* free stack space */
230 ldq gp,1*8(sp) /* restore global pointer */
232 jsr ra,builtin_throw_exception
233 ldq ra,0*8(sp) /* restore return address */
235 lda sp,5*8(sp) /* free stack space */
236 mov zero,v0 /* return NULL */
239 .end asm_vm_call_method
242 /****************** function asm_call_jit_compiler *****************************
244 * invokes the compiler for untranslated JavaVM methods. *
246 * Register R0 contains a pointer to the method info structure (prepared *
247 * by createcompilerstub). Using the return address in R26 and the *
248 * offset in the LDA instruction or using the value in methodptr R28 the *
249 * patching address for storing the method address can be computed: *
251 * method address was either loaded using *
252 * M_LDQ (REG_PV, REG_PV, a) ; invokestatic/special ($27) *
253 * M_LDA (REG_PV, REG_RA, low) *
254 * M_LDAH(REG_PV, REG_RA, high) ; optional *
256 * M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($28) *
257 * in the static case the method pointer can be computed using the *
258 * return address and the lda function following the jmp instruction *
260 *******************************************************************************/
262 .ent asm_call_jit_compiler
264 asm_call_jit_compiler:
266 lda sp,-(15*8+sizestackframeinfo)(sp) /* reserve stack space */
268 SAVE_ARGUMENT_REGISTERS(0) /* save 6 int/6 float argument registers */
270 stq mptr,12*8(sp) /* save method pointer */
271 stq ra,13*8(sp) /* save return address */
272 stq itmp1,14*8(sp) /* save methodinfo pointer */
274 lda a0,15*8(sp) /* create stackframe info */
275 mov zero,a1 /* we don't have pv handy */
276 lda a2,15*8+sizestackframeinfo(sp) /* pass java sp */
277 mov ra,a3 /* pass Java ra */
278 mov a3,a4 /* xpc is equal to ra */
279 jsr ra,stacktrace_create_extern_stackframeinfo
282 ldq a0,14*8(sp) /* pass methodinfo pointer */
283 jsr ra,jit_compile /* call jit compiler */
285 stq v0,14*8(sp) /* save return value */
287 ldq a0,13*8(sp) /* pass return address */
288 lda a1,15*8(sp) /* pass stackframeinfo (for PV) */
289 ldq a2,12*8(sp) /* pass method pointer */
290 jsr ra,md_assembler_get_patch_address /* get address of patch position*/
292 stq v0,12*8(sp) /* store patch address for later use */
294 lda a0,15*8(sp) /* remove stackframe info */
295 jsr ra,stacktrace_remove_stackframeinfo
298 RESTORE_ARGUMENT_REGISTERS(0) /* restore 6 int/6 float argument registers */
300 ldq t0,12*8(sp) /* load patch address */
301 ldq ra,13*8(sp) /* load return address */
302 ldq pv,14*8(sp) /* restore method entry point */
303 lda sp,15*8+sizestackframeinfo(sp) /* deallocate stack area */
305 beq pv,L_asm_call_jit_compiler_exception
307 stq pv,0(t0) /* patch method entry point */
309 call_pal PAL_imb /* synchronise instruction cache */
311 jmp zero,(pv) /* and call method, the method returns */
312 /* directly to the caller (ra). */
314 L_asm_call_jit_compiler_exception:
315 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
317 stq ra,0*8(sp) /* save return address (xpc) */
318 jsr ra,builtin_asm_get_exceptionptrptr
319 ldq ra,0*8(sp) /* restore return address (xpc) */
324 ldq xptr,0(v0) /* get the exception pointer */
325 stq zero,0(v0) /* clear the exception pointer */
328 br L_asm_handle_nat_exception
330 .end asm_call_jit_compiler
333 /* asm_handle_exception ********************************************************
335 This function handles an exception. It does not use the usual calling
336 conventions. The exception pointer is passed in REG_ITMP1 and the
337 pc from the exception raising position is passed in REG_ITMP2. It searches
338 the local exception table for a handler. If no one is found, it unwinds
339 stacks and continues searching the callers.
341 ATTENTION: itmp3 == gp!
343 *******************************************************************************/
345 .ent asm_handle_nat_exception
347 asm_handle_nat_exception:
348 L_asm_handle_nat_exception: /* required for PIC code */
349 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
351 sra t0,48,t0 /* isolate offset */
352 addq t0,ra,pv /* compute update address */
353 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
354 srl t0,16,t0 /* isolate instruction code */
355 lda t0,-0x177b(t0) /* test for LDAH */
356 bne t0,L_asm_handle_exception
357 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
358 sll t0,16,t0 /* compute high offset */
359 addl t0,0,t0 /* sign extend high offset */
360 addq t0,pv,pv /* compute update address */
362 .aent asm_handle_exception
364 asm_handle_exception:
365 L_asm_handle_exception: /* required for PIC code */
366 lda sp,-(ARG_CNT+TMP_CNT)*8(sp) /* create maybe-leaf stackframe */
368 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
369 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
371 lda a3,(ARG_CNT+TMP_CNT)*8(zero)/* prepare a3 for handle_exception */
372 lda a4,1(zero) /* set maybe-leaf flag */
374 L_asm_handle_exception_stack_loop:
375 lda sp,-5*8(sp) /* allocate stack */
376 stq xptr,0*8(sp) /* save exception pointer */
377 stq xpc,1*8(sp) /* save exception pc */
378 stq pv,2*8(sp) /* save data segment pointer */
379 stq ra,3*8(sp) /* save return address */
380 addq a3,sp,a3 /* calculate Java sp into a3... */
382 stq a4,4*8(sp) /* save maybe-leaf flag */
384 br ra,L_asm_handle_exception_load_gp /* set ra for gp loading */
385 L_asm_handle_exception_load_gp:
386 ldgp gp,0(ra) /* load gp */
388 mov xptr,a0 /* pass exception pointer */
389 mov xpc,a1 /* pass exception pc */
390 mov pv,a2 /* pass data segment pointer */
391 /* a3 is still set */
392 jsr ra,exceptions_handle_exception
394 beq v0,L_asm_handle_exception_not_catched
396 mov v0,xpc /* move handlerpc into xpc */
397 ldq xptr,0*8(sp) /* restore exception pointer */
398 ldq pv,2*8(sp) /* restore data segment pointer */
399 ldq ra,3*8(sp) /* restore return address */
400 ldq a4,4*8(sp) /* get maybe-leaf flag */
401 lda sp,5*8(sp) /* free stack frame */
403 beq a4,L_asm_handle_exception_no_leaf
405 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
406 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
408 lda sp,(ARG_CNT+TMP_CNT)*8(sp) /* remove maybe-leaf stackframe */
410 L_asm_handle_exception_no_leaf:
411 jmp zero,(xpc) /* jump to the handler */
413 L_asm_handle_exception_not_catched:
414 ldq xptr,0*8(sp) /* restore exception pointer */
415 ldq pv,2*8(sp) /* restore data segment pointer */
416 ldq ra,3*8(sp) /* restore return address */
417 ldq a4,4*8(sp) /* get maybe-leaf flag */
420 beq a4,L_asm_handle_exception_no_leaf_stack
422 lda sp,(ARG_CNT+TMP_CNT)*8(sp) /* remove maybe-leaf stackframe */
423 mov zero,a4 /* clear the maybe-leaf flag */
425 L_asm_handle_exception_no_leaf_stack:
426 ldl t0,FrameSize(pv) /* get frame size */
427 addq t0,sp,t0 /* pointer to save area */
429 ldl t1,IsLeaf(pv) /* is leaf procedure */
430 bne t1,L_asm_handle_exception_no_ra_restore
432 ldq ra,-1*8(t0) /* restore ra */
433 subq t0,8,t0 /* t0-- */
435 L_asm_handle_exception_no_ra_restore:
436 mov ra,xpc /* the new xpc is ra */
437 ldl t1,IntSave(pv) /* t1 = saved int register count */
438 br t2,ex_int1 /* t2 = current pc */
440 lda t2,(ex_int2-ex_int1)(t2)
441 negl t1,t1 /* negate register count */
442 s4addq t1,t2,t2 /* t2 = IntSave - register count * 4 */
443 jmp zero,(t2) /* jump to save position */
454 s8addq t1,t0,t0 /* t0 = t0 - 8 * register count */
456 ldl t1,FltSave(pv) /* t1 = saved flt register count */
457 br t2,ex_flt1 /* t2 = current pc */
459 lda t2,(ex_flt2-ex_flt1)(t2)
460 negl t1,t1 /* negate register count */
461 s4addq t1,t2,t2 /* t2 = FltSave - 4 * register count */
462 jmp zero,(t2) /* jump to save position */
474 ldl t0,FrameSize(pv) /* get frame size */
475 addq sp,t0,sp /* unwind stack */
476 mov zero,a3 /* prepare a3 for handle_exception */
478 ldl t0,0(ra) /* load instruction LDA PV,xxx(RA) */
480 sra t0,48,t0 /* isolate offset */
481 addq t0,ra,pv /* compute update address */
482 ldl t0,4(ra) /* load instruction LDAH PV,xxx(PV) */
483 srl t0,16,t0 /* isolate instruction code */
484 lda t0,-0x177b(t0) /* test for LDAH */
485 bne t0,L_asm_handle_exception_stack_loop
486 ldl t0,4(ra) /* load instruction LDAH PV,xxx(RA) */
487 sll t0,16,t0 /* compute high offset */
488 addl t0,0,t0 /* sign extend high offset */
489 addq t0,pv,pv /* compute update address */
491 br L_asm_handle_exception_stack_loop
493 .end asm_handle_nat_exception
496 /* asm_wrapper_patcher *********************************************************
501 40 return address into JIT code (patch position)
502 32 pointer to virtual java_objectheader
503 24 machine code (which is patched back later)
504 16 unresolved class/method/field reference
505 8 data segment displacement from load instructions
506 0 patcher function pointer to call (pv afterwards)
508 ATTENTION: itmp3 == gp! But we don't need gp do call the patcher function.
510 *******************************************************************************/
512 .ent asm_wrapper_patcher
515 lda sp,-((2+12+27+4)*8+sizestackframeinfo)(sp) /* create stack frame */
517 SAVE_RETURN_REGISTERS(0) /* save 1 int/1 float return registers */
518 SAVE_ARGUMENT_REGISTERS(2) /* save 6 int/6 float argument registers */
519 SAVE_TEMPORARY_REGISTERS(14) /* save 11 int/16 float temporary registers */
521 stq itmp1,(2+12+27+0)*8(sp) /* save itmp1 */
522 stq itmp2,(2+12+27+1)*8(sp) /* save itmp2 */
523 stq ra,(2+12+27+2)*8(sp) /* save method return address (for leafs) */
524 stq pv,(2+12+27+3)*8(sp) /* save pv of calling java function */
526 br ra,L_asm_wrapper_patcher_load_gp
527 L_asm_wrapper_patcher_load_gp:
528 ldgp gp,0(ra) /* load gp (it's not set correctly in jit) */
530 lda a0,(2+12+27+4)*8(sp) /* create stackframe info */
531 mov pv,a1 /* pass java pv */
532 lda a2,((6+2+12+27+4)*8+sizestackframeinfo)(sp) /* pass java sp */
533 ldq a3,(2+12+27+2)*8(sp) /* this is correct for leafs */
534 ldq a4,((5+2+12+27+4)*8+sizestackframeinfo)(sp) /* pass xpc */
535 jsr ra,stacktrace_create_extern_stackframeinfo
538 lda a0,((0+2+12+27+4)*8+sizestackframeinfo)(sp) /* pass sp */
539 ldq pv,((0+2+12+27+4)*8+sizestackframeinfo)(sp) /* get function */
540 ldq itmp1,(2+12+27+3)*8(sp) /* save pv to the position of fp */
541 stq itmp1,((0+2+12+27+4)*8+sizestackframeinfo)(sp)
542 jmp ra,(pv) /* call the patcher function */
544 stq v0,((0+2+12+27+4)*8+sizestackframeinfo)(sp) /* save return value */
546 lda a0,(2+12+27+4)*8(sp) /* remove stackframe info */
547 jsr ra,stacktrace_remove_stackframeinfo
550 RESTORE_RETURN_REGISTERS(0) /* restore 1 int/1 float return registers */
551 RESTORE_ARGUMENT_REGISTERS(2) /* restore 6 int/6 float argument registers */
552 RESTORE_TEMPORARY_REGISTERS(14) /* restore 11 integer temporary registers */
554 ldq itmp1,(2+12+27+0)*8(sp) /* restore itmp1 */
555 ldq itmp2,(2+12+27+1)*8(sp) /* restore itmp2 */
556 ldq ra,(2+12+27+2)*8(sp) /* restore method return address (for leafs)*/
557 ldq pv,(2+12+27+3)*8(sp) /* restore pv of calling java function */
559 ldq itmp3,((0+2+12+27+4)*8+sizestackframeinfo)(sp) /* get return value*/
560 beq itmp3,L_asm_wrapper_patcher_exception
562 ldq itmp3,((5+2+12+27+4)*8+sizestackframeinfo)(sp)/* get RA to JIT */
563 lda sp,((6+2+12+27+4)*8+sizestackframeinfo)(sp) /* remove stack frame */
565 jmp zero,(itmp3) /* jump to new patched code */
567 L_asm_wrapper_patcher_exception:
568 ldq xpc,((5+2+12+27+4)*8+sizestackframeinfo)(sp) /* RA is xpc */
569 lda sp,((6+2+12+27+4)*8+sizestackframeinfo)(sp) /* remove stack frame */
571 br itmp1,L_asm_wrapper_patcher_exception_load_gp
572 L_asm_wrapper_patcher_exception_load_gp:
573 ldgp gp,0(itmp1) /* itmp3 == gp, load the current gp */
575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
577 stq xpc,0*8(sp) /* save return address (xpc) */
580 jsr ra,builtin_asm_get_exceptionptrptr
581 ldq xpc,0*8(sp) /* restore return address (xpc) */
588 ldq xptr,0(v0) /* get the exception pointer */
589 stq zero,0(v0) /* clear the exception pointer */
590 br L_asm_handle_exception/* we have the pv of the calling java func. */
592 .end asm_wrapper_patcher
595 /******************* function asm_initialize_thread_stack **********************
597 * initialized a thread stack *
599 *******************************************************************************/
601 .ent asm_initialize_thread_stack
603 asm_initialize_thread_stack:
624 .end asm_initialize_thread_stack
627 /******************* function asm_perform_threadswitch *************************
629 * void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
631 * performs a threadswitch *
633 *******************************************************************************/
635 .ent asm_perform_threadswitch
637 asm_perform_threadswitch:
678 .end asm_perform_threadswitch
681 /********************* function asm_switchstackandcall *************************
683 * void *asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
686 * Switches to a new stack, calls a function and switches back. *
687 * a0 new stack pointer *
688 * a1 function pointer *
689 * a2 pointer to variable where stack top should be stored *
690 * a3 pointer to user data, is passed to the function *
692 *******************************************************************************/
695 .ent asm_switchstackandcall
697 asm_switchstackandcall:
698 lda a0,-2*8(a0) /* allocate new stack */
699 stq ra,0(a0) /* save return address on new stack */
700 stq sp,1*8(a0) /* save old stack pointer on new stack */
701 stq sp,0(a2) /* save old stack pointer to variable */
702 mov a0,sp /* switch to new stack */
704 mov a1,pv /* load function pointer */
705 mov a3,a0 /* pass pointer */
706 jmp ra,(pv) /* and call function */
708 ldq ra,0(sp) /* load return address */
709 ldq sp,1*8(sp) /* switch to old stack */
711 jmp zero,(ra) /* return */
713 .end asm_switchstackandcall
716 .ent asm_getclassvalues_atomic
718 asm_getclassvalues_atomic:
721 ldl t0,offbaseval(a0)
722 ldl t1,offdiffval(a0)
723 ldl t2,offbaseval(a1)
725 stl t0,offcast_super_baseval(a2)
726 stl t1,offcast_super_diffval(a2)
727 stl t2,offcast_sub_baseval(a2)
730 .end asm_getclassvalues_atomic
735 asm_criticalsections:
736 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
744 /* Disable exec-stacks, required for Gentoo ***********************************/
746 #if defined(__GCC__) && defined(__ELF__)
747 .section .note.GNU-stack,"",@progbits
752 * These are local overrides for various environment variables in Emacs.
753 * Please do not remove this and leave it at the end of the file, where
754 * Emacs will automagically detect them.
755 * ---------------------------------------------------------------------
758 * indent-tabs-mode: t