* src/vm/jit/code.c (code_get_stack_frame_size): Implement stack alignment
[cacao.git] / src / vm / jit / powerpc / asmpart.S
index d147388c900b4acb5750c0c82c3551c9f7922c73..ca493baaa21e82a676ddb8f38ec232bb3ce97c35 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/powerpc/asmpart.S - Java-C interface functions for PowerPC
                
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program;  if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Andreas Krall
             Reinhard Grafl
             Stefan Ring
 
    Changes: Christian Thalinger
+                       Edwin Steiner
 
-   $Id: asmpart.S 3925 2005-12-09 00:42:56Z twisti $
+   $Id: asmpart.S 4654 2006-03-19 19:46:11Z edwin $
 
 */
 
 
        .align 2
 
-       .globl asm_calljavafunction
-       .globl asm_calljavafunction_int
 
-       .globl asm_calljavafunction2
-       .globl asm_calljavafunction2int
-       .globl asm_calljavafunction2long
-       .globl asm_calljavafunction2float
-       .globl asm_calljavafunction2double
+/* exported functions and variables *******************************************/
+
+       .globl asm_vm_call_method
+       .globl asm_vm_call_method_int
+       .globl asm_vm_call_method_long
+       .globl asm_vm_call_method_float
+       .globl asm_vm_call_method_double
 
        .globl asm_call_jit_compiler
 
@@ -65,6 +66,9 @@
 
        .globl asm_wrapper_patcher
 
+       .globl asm_replacement_out
+       .globl asm_replacement_in
+
        .globl asm_cacheflush
        .globl asm_initialize_thread_stack
        .globl asm_perform_threadswitch
@@ -73,7 +77,7 @@
        .globl asm_getclassvalues_atomic
 
 
-/********************* function asm_calljavafunction ***************************
+/* asm_vm_call_method **********************************************************
 *                                                                              *
 *   This function calls a Java-method (which possibly needs compilation)       *
 *   with up to 4 address parameters.                                           *
 *                                                                              *
 *******************************************************************************/
                
-       .align 2
-
-       .long   0                         /* catch type all                       */
-       .long   calljava_xhandler         /* handler pc                           */
-       .long   calljava_xhandler         /* end pc                               */
-       .long   asm_calljavafunction      /* start pc                             */
-       .long   1                         /* extable size                         */
-       .long   0                         /* line number table start              */
-       .long   0                         /* line number table size               */
-       .long   0                         /* fltsave                              */
-       .long   0                         /* intsave                              */
-       .long   0                         /* isleaf                               */
-       .long   0                         /* IsSync                               */
-       .long   0                         /* frame size                           */
-       .long   0                         /* method pointer (pointer to name)     */
-
-asm_calljavafunction:
-asm_calljavafunction_int:
-       mflr    r0
-       stw     r0,LA_LR_OFFSET(r1)
-       stwu    r1,-40*4(r1)
-
-#if defined(__DARWIN__)
-       stw     itmp1,10*4(sp)            /* register r11 is callee saved         */
-#endif
-       stw     pv,11*4(sp)               /* save PV register                     */
-
-       stw     itmp3,12*4(sp)            /* registers r14-r31 are callee saved   */
-       stfd    ftmp1,14*4(sp)            /* registers f14-f31 are callee saved   */
-       stfd    ftmp2,16*4(sp)
-
-#if defined(__DARWIN__)
-       stw     t1,18*4(r1)
-       stw     t2,19*4(r1)
-       stw     t3,20*4(r1)
-       stw     t4,21*4(r1)
-       stw     t5,22*4(r1)
-       stw     t6,23*4(r1)
-       stw     t7,24*4(r1)
-
-       stfd    ft0,26*4(r1)
-       stfd    ft1,28*4(r1)
-       stfd    ft2,30*4(r1)
-       stfd    ft3,32*4(r1)
-       stfd    ft4,34*4(r1)
-       stfd    ft5,36*4(r1)
-#else
-       SAVE_TEMPORARY_REGISTERS(18)      /* the offset has to be even            */
-#endif
-
-       stw     a0,36(r1)
-       addi    itmp1,r1,36
-       mr      a0,a1
-       mr      a1,a2
-       mr      a2,a3
-       mr      a3,a4
-
-#if defined(__DARWIN__)
-       lis     mptr,ha16(asm_call_jit_compiler)
-       addi    mptr,mptr,lo16(asm_call_jit_compiler)
-#else
-       lis     mptr,asm_call_jit_compiler@ha
-       addi    mptr,mptr,asm_call_jit_compiler@l
-#endif
-       stw     mptr,32(r1)
-       addi    mptr,r1,28
-
-       lwz     pv,4(mptr)
-       mtctr   pv
-       bctrl
-
-1:
-       mflr    itmp1
-#if defined(__DARWIN__)
-       addi    pv,itmp1,lo16(asm_calljavafunction-1b)
-#else
-       addi    pv,itmp1,(asm_calljavafunction-1b)@l
-#endif
-
-L_asm_calljavafunction_return:
-#if defined(__DARWIN__)
-       lwz     itmp1,10*4(sp)            /* register r11 is callee saved         */
-#endif
-       lwz     pv,11*4(sp)               /* save PV register                     */
-
-       lwz     itmp3,12*4(sp)
-       lfd     ftmp1,14*4(sp)            /* registers f14-f31 are callee saved   */
-       lfd     ftmp2,16*4(sp)
-
-#if defined(__DARWIN__)
-       lwz     t1,18*4(r1)
-       lwz     t2,19*4(r1)
-       lwz     t3,20*4(r1)
-       lwz     t4,21*4(r1)
-       lwz     t5,22*4(r1)
-       lwz     t6,23*4(r1)
-       lwz     t7,24*4(r1)
-
-       lfd     ft0,26*4(r1)
-       lfd     ft1,28*4(r1)
-       lfd     ft2,30*4(r1)
-       lfd     ft3,32*4(r1)
-       lfd     ft4,34*4(r1)
-       lfd     ft5,36*4(r1)
-#else
-       RESTORE_TEMPORARY_REGISTERS(18)   /* the offset has to be even            */
-#endif
-
-       lwz     r0,40*4+LA_LR_OFFSET(r1)
-       mtlr    r0
-       addi    r1,r1,40*4
-       blr
-
-calljava_xhandler:
-       mr      a0,itmp1
-       bl      builtin_throw_exception
-       li      v0,0                      /* return NULL                          */
-       b       L_asm_calljavafunction_return
-
-
-
-
        .align 2
 
        .long   0                         /* catch type all                       */
        .long   calljava_xhandler2        /* handler pc                           */
        .long   calljava_xhandler2        /* end pc                               */
-       .long   asm_calljavafunction2     /* start pc                             */
+       .long   L_asm_vm_call_method      /* start pc                             */
        .long   1                         /* extable size                         */
        .long   0                         /* line number table start              */
        .long   0                         /* line number table size               */
@@ -225,11 +107,12 @@ calljava_xhandler:
        .long   0                         /* frame size                           */
        .long   0                         /* method pointer (pointer to name)     */
 
-asm_calljavafunction2:
-asm_calljavafunction2int:
-asm_calljavafunction2long:
-asm_calljavafunction2float:
-asm_calljavafunction2double:
+asm_vm_call_method:
+asm_vm_call_method_int:
+asm_vm_call_method_long:
+asm_vm_call_method_float:
+asm_vm_call_method_double:
+L_asm_vm_call_method:                 /* required for PIC code                */
        mflr    r0
        stw     r0,LA_LR_OFFSET(r1)
        stwu    r1,-40*4(r1)
@@ -262,22 +145,27 @@ asm_calljavafunction2double:
        SAVE_TEMPORARY_REGISTERS(18)      /* the offset has to be even            */
 #endif
 
-       stw     r3,36(r1)                 /* save method pointer for compiler     */
-       mr      itmp1,r6                  /* pointer to arg block                 */
+       stw     a0,9*4(r1)                /* save method pointer for compiler     */
+
+       mr      itmp1,r5                  /* pointer to arg block                 */
        mr      itmp2,r4                  /* arg count                            */
 
-       addi    itmp1,itmp1,-sizejniblock /* initialize pointer (smaller code)    */
+       addi    itmp1,itmp1,-sizevmarg    /* initialize pointer (smaller code)    */
        addi    itmp2,itmp2,1             /* initialize argument count            */
        li      r17,0                     /* initialize integer argument counter  */
        li      r18,0                     /* initialize float argument counter    */
 
 L_register_copy:
-       addi    itmp1,itmp1,sizejniblock  /* goto next argument block             */
+       addi    itmp1,itmp1,sizevmarg     /* goto next argument block             */
        addi    itmp2,itmp2,-1            /* argument count - 1                   */
        mr.     itmp2,itmp2
        beq     L_register_copy_done
 
-       lwz     itmp3,offjniitemtype+4(itmp1)
+#if WORDS_BIGENDIAN == 1
+       lwz     itmp3,offvmargtype+4(itmp1)
+#else
+#error XXX
+#endif
        andi.   r0,itmp3,0x0002           /* is this a float/double type?         */
        bne     L_register_handle_float
 
@@ -324,29 +212,30 @@ L_register_handle_float:
 L_register_copy_done:
 
 L_stack_copy_done:
-       addi    itmp1,r1,36
+       lwz     itmp1,9*4(sp)             /* pass method pointer via tmp1         */
+
 #if defined(__DARWIN__)
-       lis     mptr,ha16(asm_call_jit_compiler)
-       addi    mptr,mptr,lo16(asm_call_jit_compiler)
+       lis     mptr,ha16(L_asm_call_jit_compiler)
+       addi    mptr,mptr,lo16(L_asm_call_jit_compiler)
 #else
-       lis     mptr,asm_call_jit_compiler@ha
-       addi    mptr,mptr,asm_call_jit_compiler@l
+       lis     mptr,L_asm_call_jit_compiler@ha
+       addi    mptr,mptr,L_asm_call_jit_compiler@l
 #endif
-       stw     mptr,32(r1)
-       addi    mptr,r1,28
+       stw     mptr,8*4(r1)
+       addi    mptr,r1,7*4
 
-       lwz     pv,4(mptr)
+       lwz     pv,1*4(mptr)
        mtctr   pv
        bctrl
 1:
        mflr    itmp1
 #if defined(__DARWIN__)
-       addi    pv,itmp1,lo16(asm_calljavafunction2-1b)
+       addi    pv,itmp1,lo16(L_asm_vm_call_method-1b)
 #else
-       addi    pv,itmp1,(asm_calljavafunction2-1b)@l
+       addi    pv,itmp1,(L_asm_vm_call_method-1b)@l
 #endif
 
-L_asm_calljavafunction2_return:
+L_asm_vm_call_method_return:
 #if defined(__DARWIN__)
        lwz     itmp1,10*4(sp)            /* register r11 is callee saved         */
 #endif
@@ -384,7 +273,7 @@ calljava_xhandler2:
        mr      r3,itmp1
        bl      builtin_throw_exception
        li      v0,0                      /* return NULL                          */
-       b       L_asm_calljavafunction2_return
+       b       L_asm_vm_call_method_return
 
 
 jumptable_int:
@@ -398,28 +287,28 @@ jumptable_int:
        .long   L_handle_a7
 
 L_handle_a0:
-       lwz     a0,offjniitem+4(itmp1)
+       lwz     a0,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a1:
-       lwz     a1,offjniitem+4(itmp1)
+       lwz     a1,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a2:
-       lwz     a2,offjniitem+4(itmp1)
+       lwz     a2,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a3:
-       lwz     a3,offjniitem+4(itmp1)
+       lwz     a3,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a4:
-       lwz     a4,offjniitem+4(itmp1)
+       lwz     a4,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a5:
-       lwz     a5,offjniitem+4(itmp1)
+       lwz     a5,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a6:
-       lwz     a6,offjniitem+4(itmp1)
+       lwz     a6,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a7:
-       lwz     a7,offjniitem+4(itmp1)
+       lwz     a7,offvmargdata+4(itmp1)
        b       L_register_copy
 
 
@@ -440,20 +329,20 @@ jumptable_long:
 #endif
 
 L_handle_a0_a1:
-       lwz     a0,offjniitem+0(itmp1)
-       lwz     a1,offjniitem+4(itmp1)
+       lwz     a0,offvmargdata+0(itmp1)
+       lwz     a1,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a2_a3:
-       lwz     a2,offjniitem+0(itmp1)
-       lwz     a3,offjniitem+4(itmp1)
+       lwz     a2,offvmargdata+0(itmp1)
+       lwz     a3,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a4_a5:
-       lwz     a4,offjniitem+0(itmp1)
-       lwz     a5,offjniitem+4(itmp1)
+       lwz     a4,offvmargdata+0(itmp1)
+       lwz     a5,offvmargdata+4(itmp1)
        b       L_register_copy
 L_handle_a6_a7:
-       lwz     a6,offjniitem+0(itmp1)
-       lwz     a7,offjniitem+4(itmp1)
+       lwz     a6,offvmargdata+0(itmp1)
+       lwz     a7,offvmargdata+4(itmp1)
        b       L_register_copy
 
 
@@ -464,6 +353,7 @@ L_handle_a6_a7:
 *******************************************************************************/
 
 asm_call_jit_compiler:
+L_asm_call_jit_compiler:                /* required for PIC code              */
        mflr    r0
        stw     r0,LA_LR_OFFSET(r1)         /* save return address                */
        stwu    r1,-((LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 3*4)+sizestackframeinfo)(r1)
@@ -523,8 +413,7 @@ noregchange:
        mr      a4,a3                       /* xpc is equal to ra                 */
        bl      stacktrace_create_extern_stackframeinfo
 
-       lwz     itmp1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 1*4)(r1)
-       lwz     a0,0(itmp1)
+       lwz     a0,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8 + 1*4)(r1)
        bl      jit_compile                 /* compile the Java method            */
        mr      pv,r3                       /* move address to pv register        */
 
@@ -598,7 +487,7 @@ L_asm_call_jit_compiler_exception:
 
        mflr    xpc
        addi    xpc,xpc,-4
-       b       asm_handle_nat_exception
+       b       L_asm_handle_nat_exception
 
 
 /********************* function asm_handle_exception ***************************
@@ -614,6 +503,7 @@ L_asm_call_jit_compiler_exception:
 *******************************************************************************/
                
 asm_handle_nat_exception:
+L_asm_handle_nat_exception:             /* required for PIC code              */
        mflr    r9
        lwz     itmp3,4(r9)
        extsh   itmp3,itmp3
@@ -621,12 +511,13 @@ asm_handle_nat_exception:
        lwz     itmp3,8(r9)
        srwi    itmp3,itmp3,16
        cmpwi   itmp3,0x3dad
-       bne     asm_handle_exception
+       bne     L_asm_handle_exception
        lwz     itmp3,8(r9)
        slwi    itmp3,itmp3,16
        add     pv,pv,itmp3
 
 asm_handle_exception:
+L_asm_handle_exception:                 /* required for PIC code              */
        addi    sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
 
 #if defined(__DARWIN__)
@@ -957,8 +848,223 @@ L_asm_wrapper_patcher_exception:
        lwz     xptr,0(v0)            /* get the exception pointer                */
        li      itmp3,0
        stw     itmp3,0(v0)           /* clear the exception pointer              */
-       b       asm_handle_exception
+       b       L_asm_handle_exception
+
 
+/* asm_replacement_out *********************************************************
+
+   This code is jumped to from the replacement-out stubs that are executed
+   when a thread reaches an activated replacement point.
+
+   The purpose of asm_replacement_out is to read out the parts of the
+   execution state that cannot be accessed from C code, store this state,
+   and then call the C function replace_me.
+
+   Stack layout:
+      16                start of stack inside method to replace
+      0   rplpoint *    info on the replacement point that was reached
+
+   NOTE: itmp3 has been clobbered by the replacement-out stub!
+
+*******************************************************************************/
+
+/* some room to accomodate changes of the stack frame size during replacement */
+       /* XXX we should find a cleaner solution here */
+#define REPLACEMENT_ROOM  512
+
+asm_replacement_out:
+    /* create stack frame */
+       addi    sp,sp,-(sizeexecutionstate + REPLACEMENT_ROOM) /* XXX align */
+
+       /* save link register */
+       mflr    r16
+
+       /* save registers in execution state */
+       stw     r0 ,( 0*8+offes_intregs)(sp)
+       stw     r1 ,( 1*8+offes_intregs)(sp)
+       stw     r2 ,( 2*8+offes_intregs)(sp)
+       stw     r3 ,( 3*8+offes_intregs)(sp)
+       stw     r4 ,( 4*8+offes_intregs)(sp)
+       stw     r5 ,( 5*8+offes_intregs)(sp)
+       stw     r6 ,( 6*8+offes_intregs)(sp)
+       stw     r7 ,( 7*8+offes_intregs)(sp)
+       stw     r8 ,( 8*8+offes_intregs)(sp)
+       stw     r9 ,( 9*8+offes_intregs)(sp)
+       stw     r10,(10*8+offes_intregs)(sp)
+       stw     r11,(11*8+offes_intregs)(sp)
+       stw     r12,(12*8+offes_intregs)(sp)
+       stw     r13,(13*8+offes_intregs)(sp)
+       stw     r14,(14*8+offes_intregs)(sp)
+       stw     r15,(15*8+offes_intregs)(sp)
+       stw     r16,(16*8+offes_intregs)(sp) /* link register */
+       stw     r17,(17*8+offes_intregs)(sp)
+       stw     r18,(18*8+offes_intregs)(sp)
+       stw     r19,(19*8+offes_intregs)(sp)
+       stw     r20,(20*8+offes_intregs)(sp)
+       stw     r21,(21*8+offes_intregs)(sp)
+       stw     r22,(22*8+offes_intregs)(sp)
+       stw     r23,(23*8+offes_intregs)(sp)
+       stw     r24,(24*8+offes_intregs)(sp)
+       stw     r25,(25*8+offes_intregs)(sp)
+       stw     r26,(26*8+offes_intregs)(sp)
+       stw     r27,(27*8+offes_intregs)(sp)
+       stw     r28,(28*8+offes_intregs)(sp)
+       stw     r29,(29*8+offes_intregs)(sp)
+       stw     r30,(30*8+offes_intregs)(sp)
+       stw     r31,(31*8+offes_intregs)(sp)
+       
+       stfd    fr0 ,( 0*8+offes_fltregs)(sp)
+       stfd    fr1 ,( 1*8+offes_fltregs)(sp)
+       stfd    fr2 ,( 2*8+offes_fltregs)(sp)
+       stfd    fr3 ,( 3*8+offes_fltregs)(sp)
+       stfd    fr4 ,( 4*8+offes_fltregs)(sp)
+       stfd    fr5 ,( 5*8+offes_fltregs)(sp)
+       stfd    fr6 ,( 6*8+offes_fltregs)(sp)
+       stfd    fr7 ,( 7*8+offes_fltregs)(sp)
+       stfd    fr8 ,( 8*8+offes_fltregs)(sp)
+       stfd    fr9 ,( 9*8+offes_fltregs)(sp)
+       stfd    fr10,(10*8+offes_fltregs)(sp)
+       stfd    fr11,(11*8+offes_fltregs)(sp)
+       stfd    fr12,(12*8+offes_fltregs)(sp)
+       stfd    fr13,(13*8+offes_fltregs)(sp)
+       stfd    fr14,(14*8+offes_fltregs)(sp)
+       stfd    fr15,(15*8+offes_fltregs)(sp)
+       stfd    fr16,(16*8+offes_fltregs)(sp)
+       stfd    fr17,(17*8+offes_fltregs)(sp)
+       stfd    fr18,(18*8+offes_fltregs)(sp)
+       stfd    fr19,(19*8+offes_fltregs)(sp)
+       stfd    fr20,(20*8+offes_fltregs)(sp)
+       stfd    fr21,(21*8+offes_fltregs)(sp)
+       stfd    fr22,(22*8+offes_fltregs)(sp)
+       stfd    fr23,(23*8+offes_fltregs)(sp)
+       stfd    fr24,(24*8+offes_fltregs)(sp)
+       stfd    fr25,(25*8+offes_fltregs)(sp)
+       stfd    fr26,(26*8+offes_fltregs)(sp)
+       stfd    fr27,(27*8+offes_fltregs)(sp)
+       stfd    fr28,(28*8+offes_fltregs)(sp)
+       stfd    fr29,(29*8+offes_fltregs)(sp)
+       stfd    fr30,(30*8+offes_fltregs)(sp)
+       stfd    fr31,(31*8+offes_fltregs)(sp)
+       
+       /* calculate sp of method */
+       addi    itmp1,sp,(sizeexecutionstate + REPLACEMENT_ROOM + 4*4)
+       stw     itmp1,(offes_sp)(sp)
+
+       /* store pv */
+       stw     pv,(offes_pv)(sp)
+
+       /* call replace_me */
+       lwz     a0,-(4*4)(itmp1)            /* arg0: rplpoint *                   */
+    mr      a1,sp                       /* arg1: execution state              */
+       addi    sp,sp,-(LA_SIZE_ALIGNED)
+    b       replace_me                  /* call C function replace_me         */
+
+/* asm_replacement_in **********************************************************
+
+   This code writes the given execution state and jumps to the replacement
+   code.
+
+   This function never returns!
+
+   NOTE: itmp3 is not restored!
+
+   C prototype:
+      void asm_replacement_in(executionstate *es);
+
+*******************************************************************************/
+
+asm_replacement_in:
+       /* a0 == executionstate *es */
+
+       /* set new sp and pv */
+       lwz     sp,(offes_sp)(a0)
+       lwz     pv,(offes_pv)(a0)
+       
+       /* copy registers from execution state */
+       lwz     r0 ,( 0*8+offes_intregs)(a0)
+       /* r1 is sp                       */
+       /* r2 is reserved                 */
+       /* a0 is loaded below             */
+       lwz     r4 ,( 4*8+offes_intregs)(a0)
+       lwz     r5 ,( 5*8+offes_intregs)(a0)
+       lwz     r6 ,( 6*8+offes_intregs)(a0)
+       lwz     r7 ,( 7*8+offes_intregs)(a0)
+       lwz     r8 ,( 8*8+offes_intregs)(a0)
+       lwz     r9 ,( 9*8+offes_intregs)(a0)
+       lwz     r10,(10*8+offes_intregs)(a0)
+       lwz     r11,(11*8+offes_intregs)(a0)
+       lwz     r12,(12*8+offes_intregs)(a0)
+       /* r13 is pv                      */
+       lwz     r14,(14*8+offes_intregs)(a0)
+       lwz     r15,(15*8+offes_intregs)(a0)
+       lwz     r16,(16*8+offes_intregs)(a0) /* link register */
+       lwz     r17,(17*8+offes_intregs)(a0)
+       lwz     r18,(18*8+offes_intregs)(a0)
+       lwz     r19,(19*8+offes_intregs)(a0)
+       lwz     r20,(20*8+offes_intregs)(a0)
+       lwz     r21,(21*8+offes_intregs)(a0)
+       lwz     r22,(22*8+offes_intregs)(a0)
+       lwz     r23,(23*8+offes_intregs)(a0)
+       lwz     r24,(24*8+offes_intregs)(a0)
+       lwz     r25,(25*8+offes_intregs)(a0)
+       lwz     r26,(26*8+offes_intregs)(a0)
+       lwz     r27,(27*8+offes_intregs)(a0)
+       lwz     r28,(28*8+offes_intregs)(a0)
+       lwz     r29,(29*8+offes_intregs)(a0)
+       lwz     r30,(30*8+offes_intregs)(a0)
+       lwz     r31,(31*8+offes_intregs)(a0)
+       
+       lfd     fr0 ,( 0*8+offes_fltregs)(a0)
+       lfd     fr1 ,( 1*8+offes_fltregs)(a0)
+       lfd     fr2 ,( 2*8+offes_fltregs)(a0)
+       lfd     fr3 ,( 3*8+offes_fltregs)(a0)
+       lfd     fr4 ,( 4*8+offes_fltregs)(a0)
+       lfd     fr5 ,( 5*8+offes_fltregs)(a0)
+       lfd     fr6 ,( 6*8+offes_fltregs)(a0)
+       lfd     fr7 ,( 7*8+offes_fltregs)(a0)
+       lfd     fr8 ,( 8*8+offes_fltregs)(a0)
+       lfd     fr9 ,( 9*8+offes_fltregs)(a0)
+       lfd     fr10,(10*8+offes_fltregs)(a0)
+       lfd     fr11,(11*8+offes_fltregs)(a0)
+       lfd     fr12,(12*8+offes_fltregs)(a0)
+       lfd     fr13,(13*8+offes_fltregs)(a0)
+       lfd     fr14,(14*8+offes_fltregs)(a0)
+       lfd     fr15,(15*8+offes_fltregs)(a0)
+       lfd     fr16,(16*8+offes_fltregs)(a0)
+       lfd     fr17,(17*8+offes_fltregs)(a0)
+       lfd     fr18,(18*8+offes_fltregs)(a0)
+       lfd     fr19,(19*8+offes_fltregs)(a0)
+       lfd     fr20,(20*8+offes_fltregs)(a0)
+       lfd     fr21,(21*8+offes_fltregs)(a0)
+       lfd     fr22,(22*8+offes_fltregs)(a0)
+       lfd     fr23,(23*8+offes_fltregs)(a0)
+       lfd     fr24,(24*8+offes_fltregs)(a0)
+       lfd     fr25,(25*8+offes_fltregs)(a0)
+       lfd     fr26,(26*8+offes_fltregs)(a0)
+       lfd     fr27,(27*8+offes_fltregs)(a0)
+       lfd     fr28,(28*8+offes_fltregs)(a0)
+       lfd     fr29,(29*8+offes_fltregs)(a0)
+       lfd     fr30,(30*8+offes_fltregs)(a0)
+       lfd     fr31,(31*8+offes_fltregs)(a0)
+
+       /* restore link register */
+
+       mtlr    r16
+       
+       /* load new pc */
+
+       lwz     itmp3,offes_pc(a0)
+
+       /* load a0 */
+       
+       lwz     a0,(3*8+offes_intregs)(a0)
+
+       /* jump to new code */
+
+       mtctr   itmp3
+       bctr
+
+/*********************************************************************/
 
 asm_cacheflush:
        add     r4,r3,r4
@@ -1183,6 +1289,13 @@ asm_criticalsections:
        .long 0
 
 
+/* Disable exec-stacks, required for Gentoo ***********************************/
+
+#if defined(__GCC__) && defined(__ELF__)
+       .section .note.GNU-stack,"",@progbits
+#endif
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -1194,4 +1307,5 @@ asm_criticalsections:
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */