Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / ppc / qemu / start.S
diff --git a/qemu/roms/openbios/arch/ppc/qemu/start.S b/qemu/roms/openbios/arch/ppc/qemu/start.S
new file mode 100644 (file)
index 0000000..ae2fd53
--- /dev/null
@@ -0,0 +1,729 @@
+/*
+ *   Creation Date: <2001/06/16 21:30:18 samuel>
+ *   Time-stamp: <2003/04/04 16:32:06 samuel>
+ *
+ *     <init.S>
+ *
+ *     Asm glue for ELF images
+ *
+ *   Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation
+ *
+ */
+
+#include "autoconf.h"
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+/************************************************************************/
+/*     Macros                                                          */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v )    .org __vectors + v ; vector__##v: bl trap_error ;
+#define VECTOR( v, dummystr )  .org __vectors + v ; vector__##v
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+/* We're trying to use the same code for the ppc32 and ppc64 handlers here.
+ * On ppc32 we only save/restore the registers, C considers volatile.
+ *
+ * On ppc64 on the other hand, we have to save/restore all registers, because
+ * all OF code is 32 bits, which only saves/restores the low 32 bits of the
+ * registers it clobbers.
+ */
+
+#define EXCEPTION_PREAMBLE_TEMPLATE \
+       mtsprg1 r1 ;                            /* scratch */ \
+       mfcr    r1 ; \
+       mtsprg2 r1 ;                            /* scratch */ \
+       lis     r1, 0x8000 ;                    /* r1=0x80000000 */ \
+       add.    r1,r1,r1 ;                      /* r1=r1+r1 (high 32bit !0) */ \
+       beq     1f; \
+       \
+       mfmsr   r1 ;                            /* unset MSR_SF */ \
+       clrldi  r1,r1,1 ; \
+       mtmsrd  r1 ; \
+1: \
+       mfsprg0 r1 ;                            /* exception stack in sprg0 */ \
+.ifc ULONG_SIZE, 8 ; \
+       addi    r1,r1,-(40 * ULONG_SIZE) ;      /* push exception frame */ \
+.else ; \
+       addi    r1,r1,-(20 * ULONG_SIZE) ;      /* push exception frame */ \
+.endif ; \
+ \
+       stl     r0,(0 * ULONG_SIZE)(r1) ;       /* save r0 */ \
+       mfsprg1 r0 ; \
+       stl     r0,(1 * ULONG_SIZE)(r1) ;       /* save r1 */ \
+       stl     r2,(2 * ULONG_SIZE)(r1) ;       /* save r2 */ \
+       stl     r3,(3 * ULONG_SIZE)(r1) ;       /* save r3 */ \
+       stl     r4,(4 * ULONG_SIZE)(r1) ; \
+       stl     r5,(5 * ULONG_SIZE)(r1) ; \
+       stl     r6,(6 * ULONG_SIZE)(r1) ; \
+       stl     r7,(7 * ULONG_SIZE)(r1) ; \
+       stl     r8,(8 * ULONG_SIZE)(r1) ; \
+       stl     r9,(9 * ULONG_SIZE)(r1) ; \
+       stl     r10,(10 * ULONG_SIZE)(r1) ; \
+       stl     r11,(11 * ULONG_SIZE)(r1) ; \
+       stl     r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+       stl     r13,(17 * ULONG_SIZE)(r1) ; \
+       stl     r14,(18 * ULONG_SIZE)(r1) ; \
+       stl     r15,(19 * ULONG_SIZE)(r1) ; \
+       stl     r16,(20 * ULONG_SIZE)(r1) ; \
+       stl     r17,(21 * ULONG_SIZE)(r1) ; \
+       stl     r18,(22 * ULONG_SIZE)(r1) ; \
+       stl     r19,(23 * ULONG_SIZE)(r1) ; \
+       stl     r20,(24 * ULONG_SIZE)(r1) ; \
+       stl     r21,(25 * ULONG_SIZE)(r1) ; \
+       stl     r22,(26 * ULONG_SIZE)(r1) ; \
+       stl     r23,(27 * ULONG_SIZE)(r1) ; \
+       stl     r24,(28 * ULONG_SIZE)(r1) ; \
+       stl     r25,(29 * ULONG_SIZE)(r1) ; \
+       stl     r26,(30 * ULONG_SIZE)(r1) ; \
+       stl     r27,(31 * ULONG_SIZE)(r1) ; \
+       stl     r28,(32 * ULONG_SIZE)(r1) ; \
+       stl     r29,(33 * ULONG_SIZE)(r1) ; \
+       stl     r30,(34 * ULONG_SIZE)(r1) ; \
+       stl     r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+ \
+       mflr    r0 ; \
+       stl     r0,(13 * ULONG_SIZE)(r1) ; \
+       mfsprg2 r0 ; \
+       stl     r0,(14 * ULONG_SIZE)(r1) ; \
+       mfctr   r0 ; \
+       stl     r0,(15 * ULONG_SIZE)(r1) ; \
+       mfxer   r0 ; \
+       stl     r0,(16 * ULONG_SIZE)(r1) ; \
+ \
+       /* 76(r1) unused */ \
+       addi    r1,r1,-16 ;     /* C ABI uses 0(r1) and 4(r1)... */
+
+#define EXCEPTION_EPILOGUE_TEMPLATE \
+       addi    r1,r1,16 ;                      /* pop ABI frame */ \
+\
+       ll      r0,(13 * ULONG_SIZE)(r1) ; \
+       mtlr    r0 ; \
+       ll      r0,(14 * ULONG_SIZE)(r1) ; \
+       mtcr    r0 ; \
+       ll      r0,(15 * ULONG_SIZE)(r1) ; \
+       mtctr   r0 ; \
+       ll      r0,(16 * ULONG_SIZE)(r1) ; \
+       mtxer   r0 ; \
+\
+       ll      r0,(0 * ULONG_SIZE)(r1) ; \
+       ll      r2,(2 * ULONG_SIZE)(r1) ; \
+       ll      r3,(3 * ULONG_SIZE)(r1) ; \
+       ll      r4,(4 * ULONG_SIZE)(r1) ; \
+       ll      r5,(5 * ULONG_SIZE)(r1) ; \
+       ll      r6,(6 * ULONG_SIZE)(r1) ; \
+       ll      r7,(7 * ULONG_SIZE)(r1) ; \
+       ll      r8,(8 * ULONG_SIZE)(r1) ; \
+       ll      r9,(9 * ULONG_SIZE)(r1) ; \
+       ll      r10,(10 * ULONG_SIZE)(r1) ; \
+       ll      r11,(11 * ULONG_SIZE)(r1) ; \
+       ll      r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+       ll      r13,(17 * ULONG_SIZE)(r1) ; \
+       ll      r14,(18 * ULONG_SIZE)(r1) ; \
+       ll      r15,(19 * ULONG_SIZE)(r1) ; \
+       ll      r16,(20 * ULONG_SIZE)(r1) ; \
+       ll      r17,(21 * ULONG_SIZE)(r1) ; \
+       ll      r18,(22 * ULONG_SIZE)(r1) ; \
+       ll      r19,(23 * ULONG_SIZE)(r1) ; \
+       ll      r20,(24 * ULONG_SIZE)(r1) ; \
+       ll      r21,(25 * ULONG_SIZE)(r1) ; \
+       ll      r22,(26 * ULONG_SIZE)(r1) ; \
+       ll      r23,(27 * ULONG_SIZE)(r1) ; \
+       ll      r24,(28 * ULONG_SIZE)(r1) ; \
+       ll      r25,(29 * ULONG_SIZE)(r1) ; \
+       ll      r26,(30 * ULONG_SIZE)(r1) ; \
+       ll      r27,(31 * ULONG_SIZE)(r1) ; \
+       ll      r28,(32 * ULONG_SIZE)(r1) ; \
+       ll      r29,(33 * ULONG_SIZE)(r1) ; \
+       ll      r30,(34 * ULONG_SIZE)(r1) ; \
+       ll      r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+       ll      r1,(1 * ULONG_SIZE)(r1) ;       /* restore stack at last */ \
+       rfi
+
+// PPC32
+
+#define ULONG_SIZE             4
+#define stl                    stw
+#define ll                     lwz
+
+.macro EXCEPTION_PREAMBLE
+       EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE
+       EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+// PPC64
+
+#define ULONG_SIZE             8
+#define stl                    std
+#define ll                     ld
+
+.macro EXCEPTION_PREAMBLE_64
+       EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE_64
+       EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+
+#else /* !CONFIG_PPC_64BITSUPPORT */
+
+#ifdef __powerpc64__
+
+#define ULONG_SIZE 8
+#define STACKFRAME_MINSIZE 48
+#define stl std
+#define ll  ld
+
+#else
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+#define stl stw
+#define ll  lwz
+
+#endif
+
+.macro EXCEPTION_PREAMBLE
+    mtsprg1 r1 /* scratch */
+    mfsprg0 r1 /* exception stack in sprg0 */
+    addi    r1, r1, -(20 * ULONG_SIZE) /* push exception frame */
+
+    stl     r0,  ( 0 * ULONG_SIZE)(r1) /* save r0 */
+    mfsprg1 r0
+    stl     r0,  ( 1 * ULONG_SIZE)(r1) /* save r1 */
+    stl     r2,  ( 2 * ULONG_SIZE)(r1) /* save r2 */
+    stl     r3,  ( 3 * ULONG_SIZE)(r1) /* save r3 */
+    stl     r4,  ( 4 * ULONG_SIZE)(r1)
+    stl     r5,  ( 5 * ULONG_SIZE)(r1)
+    stl     r6,  ( 6 * ULONG_SIZE)(r1)
+    stl     r7,  ( 7 * ULONG_SIZE)(r1)
+    stl     r8,  ( 8 * ULONG_SIZE)(r1)
+    stl     r9,  ( 9 * ULONG_SIZE)(r1)
+    stl     r10, (10 * ULONG_SIZE)(r1)
+    stl     r11, (11 * ULONG_SIZE)(r1)
+    stl     r12, (12 * ULONG_SIZE)(r1)
+
+    mflr    r0
+    stl     r0,  (13 * ULONG_SIZE)(r1)
+    mfcr    r0
+    stl     r0,  (14 * ULONG_SIZE)(r1)
+    mfctr   r0
+    stl     r0,  (15 * ULONG_SIZE)(r1)
+    mfxer   r0
+    stl     r0,  (16 * ULONG_SIZE)(r1)
+
+    addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */
+.endm
+
+.macro EXCEPTION_EPILOGUE
+    addi r1, r1,  STACKFRAME_MINSIZE /* pop ABI frame */
+
+    ll    r0,  (13 * ULONG_SIZE)(r1)
+    mtlr  r0
+    ll    r0,  (14 * ULONG_SIZE)(r1)
+    mtcr  r0
+    ll    r0,  (15 * ULONG_SIZE)(r1)
+    mtctr r0
+    ll    r0,  (16 * ULONG_SIZE)(r1)
+    mtxer r0
+
+    ll    r0,  ( 0 * ULONG_SIZE)(r1)
+    ll    r2,  ( 2 * ULONG_SIZE)(r1)
+    ll    r3,  ( 3 * ULONG_SIZE)(r1)
+    ll    r4,  ( 4 * ULONG_SIZE)(r1)
+    ll    r5,  ( 5 * ULONG_SIZE)(r1)
+    ll    r6,  ( 6 * ULONG_SIZE)(r1)
+    ll    r7,  ( 7 * ULONG_SIZE)(r1)
+    ll    r8,  ( 8 * ULONG_SIZE)(r1)
+    ll    r9,  ( 9 * ULONG_SIZE)(r1)
+    ll    r10, (10 * ULONG_SIZE)(r1)
+    ll    r11, (11 * ULONG_SIZE)(r1)
+    ll    r12, (12 * ULONG_SIZE)(r1)
+
+    ll    r1,  ( 1 * ULONG_SIZE)(r1) /* restore stack at last */
+    RFI
+.endm
+
+#endif /* !CONFIG_PPC_64BITSUPPORT */
+
+/************************************************************************/
+/*     vectors                                                         */
+/************************************************************************/
+
+        .section .text.vectors, "ax"
+GLOBL(__vectors):
+       nop                     // NULL-jmp trap
+1:     nop                     //
+       b       1b
+
+VECTOR( 0x100, "SRE" ):
+        b       _entry
+
+trap_error:
+       lis     r1, 0x8000                      /* r1=0x80000000 */
+       add.    r1,r1,r1                        /* r1=r1+r1 (high 32bit !0) */
+       beq     1f
+
+       mfmsr   r1                              /* unset MSR_SF */
+       clrldi  r1,r1,1
+       mtmsrd  r1
+1:
+       mflr    r3
+       LOAD_REG_FUNC(r4, unexpected_excep)
+       mtctr r4
+       bctr
+
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+       b       real_dsi
+
+ILLEGAL_VECTOR( 0x380 )
+
+VECTOR( 0x400, "ISI" ):
+       b       real_isi
+
+ILLEGAL_VECTOR( 0x480 )
+
+       ILLEGAL_VECTOR( 0x500 )
+       ILLEGAL_VECTOR( 0x600 )
+       ILLEGAL_VECTOR( 0x700 )
+
+VECTOR( 0x800, "FPU" ):
+       mtsprg1 r3
+       mfsrr1  r3
+       ori     r3,r3,0x2000
+       mtsrr1  r3
+       mfsprg1 r3
+       RFI
+
+ILLEGAL_VECTOR( 0x900 )
+ILLEGAL_VECTOR( 0xa00 )
+ILLEGAL_VECTOR( 0xb00 )
+ILLEGAL_VECTOR( 0xc00 )
+ILLEGAL_VECTOR( 0xd00 )
+ILLEGAL_VECTOR( 0xe00 )
+ILLEGAL_VECTOR( 0xf00 )
+ILLEGAL_VECTOR( 0xf20 )
+ILLEGAL_VECTOR( 0x1000 )
+ILLEGAL_VECTOR( 0x1100 )
+ILLEGAL_VECTOR( 0x1200 )
+ILLEGAL_VECTOR( 0x1300 )
+ILLEGAL_VECTOR( 0x1400 )
+ILLEGAL_VECTOR( 0x1500 )
+ILLEGAL_VECTOR( 0x1600 )
+ILLEGAL_VECTOR( 0x1700 )
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+VECTOR( 0x2000, "DSI_64" ):
+       EXCEPTION_PREAMBLE_64
+       LOAD_REG_IMMEDIATE(r3, dsi_exception)
+       mtctr   r3
+       bctrl
+       EXCEPTION_EPILOGUE_64
+
+VECTOR( 0x2200, "ISI_64" ):
+       EXCEPTION_PREAMBLE_64
+       LOAD_REG_IMMEDIATE(r3, isi_exception)
+       mtctr   r3
+       bctrl
+       EXCEPTION_EPILOGUE_64
+
+#endif
+
+real_dsi:
+       EXCEPTION_PREAMBLE
+       LOAD_REG_FUNC(r3, dsi_exception)
+       mtctr   r3
+       bctrl
+       b exception_return
+
+real_isi:
+       EXCEPTION_PREAMBLE
+       LOAD_REG_FUNC(r3, isi_exception)
+       mtctr   r3
+       bctrl
+       b exception_return
+
+exception_return:
+       EXCEPTION_EPILOGUE
+
+GLOBL(__vectors_end):
+
+/************************************************************************/
+/*     entry                                                           */
+/************************************************************************/
+
+GLOBL(_entry):
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+       li      r0,0
+
+       lis     r3, 0x8000                      /* r1=0x80000000 */
+       add.    r3,r3,r3                        /* r1=r1+r1 (high 32bit !0) */
+       beq     no_64bit                        /* only true when !MSR_SF */
+
+       /* clear MSR, disable MMU, SF */
+       mtmsrd  r0
+       b       real_entry
+
+no_64bit:
+       /* clear MSR, disable MMU */
+       mtmsr   r0
+
+real_entry:
+#endif
+
+       /* copy exception vectors */
+
+       LOAD_REG_IMMEDIATE(r3, __vectors)
+       li      r4,0
+       li      r5,__vectors_end - __vectors + 16
+       rlwinm  r5,r5,0,0,28
+1:     lwz     r6,0(r3)
+       lwz     r7,4(r3)
+       lwz     r8,8(r3)
+       lwz     r9,12(r3)
+       stw     r6,0(r4)
+       stw     r7,4(r4)
+       stw     r8,8(r4)
+       stw     r9,12(r4)
+       dcbst   0,r4
+       sync
+       icbi    0,r4
+       sync
+       addi    r5,r5,-16
+       addi    r3,r3,16
+       addi    r4,r4,16
+       cmpwi   r5,0
+       bgt     1b
+       isync
+
+       bl compute_ramsize
+
+       /* Memory map:
+        *
+        * Top +-------------------------+
+        *     |                         |
+        *     | ROM into RAM (1 MB)     |
+        *     |                         |
+        *     +-------------------------+
+        *     |                         |
+        *     | MMU Hash Table (64 kB)  |
+        *     |                         |
+        *     +-------------------------+
+        *     |                         |
+        *     | Exception Stack (32 kB) |
+        *     |                         |
+        *     +-------------------------+
+        *     |                         |
+        *     | Stack (64 kB)           |
+        *     |                         |
+        *     +-------------------------+
+        *     |                         |
+        *     | Client Stack (64 kB)    |
+        *     |                         |
+        *     +-------------------------+
+        *     |                         |
+        *     | Malloc Zone (2 MiB)     |
+        *     |                         |
+        *     +-------------------------+
+        *     :                         :
+        * Bottom
+        */
+
+       addis   r1, r3, -16             /* ramsize - 1MB */
+
+       /* setup hash table */
+
+       addis   r1, r1, -1              /* - 64 kB */
+       clrrwi  r1, r1, 5*4             /* & ~0xfffff */
+
+       /* setup exception stack */
+
+       mtsprg0 r1
+
+       /* setup stack */
+
+       addi    r1, r1, -32768          /* - 32 kB */
+
+       /* save memory size in stack */
+
+#ifdef __powerpc64__
+       /* set up TOC pointer */
+
+       LOAD_REG_IMMEDIATE(r2, setup_mmu)
+       ld r2, 8(r2)
+#endif
+
+       bl      BRANCH_LABEL(setup_mmu)
+       bl      BRANCH_LABEL(entry)
+1:     nop
+       b       1b
+
+
+       /* According to IEEE 1275, PPC bindings:
+        *
+        *      MSR = FP, ME + (DR|IR)
+        *      r1 = stack (32 K + 32 bytes link area above)
+        *      r5 = client interface handler
+        *      r6 = address of client program arguments (unused)
+        *      r7 = length of client program arguments (unused)
+         *
+         *      Yaboot and Linux use r3 and r4 for initrd address and size
+        */
+        .data
+saved_stack:
+    DATA_LONG(0)
+        .previous
+       /* void call_elf( arg1, arg2, entry ) */
+_GLOBAL(call_elf):
+       mflr    r0
+       PPC_STLU r1, -STACKFRAME_MINSIZE(r1)
+       PPC_STL  r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+       mtlr    r5
+       LOAD_REG_IMMEDIATE(r8, saved_stack)             // save our stack pointer
+       PPC_STL r1,0(r8)
+       mfsdr1  r1
+       addi    r1, r1, -32768          /* - 32 KiB exception stack */
+       addis   r1, r1, -1                      /* - 64 KiB stack */
+       LOAD_REG_IMMEDIATE(r5, of_client_callback)      // r5 = callback
+       li      r6,0                    // r6 = address of client program arguments (unused)
+       li      r7,0                    // r7 = length of client program arguments (unused)
+       li      r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
+       MTMSRD(r0)
+       blrl
+
+#ifdef CONFIG_PPC64
+    /* Restore SF bit */
+    LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR)
+    MTMSRD(r0)
+#endif
+       LOAD_REG_IMMEDIATE(r8, saved_stack)             // restore stack pointer
+       mr      r1,r8
+       PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+       mtlr    r0
+       addi    r1, r1, STACKFRAME_MINSIZE
+       // XXX: should restore r12-r31 etc..
+       // we should not really come here though
+       blr
+
+#ifdef __powerpc64__
+#define STKOFF STACKFRAME_MINSIZE
+#define SAVE_SPACE 320
+#else
+#define STKOFF 8
+#define SAVE_SPACE 144
+#endif
+GLOBL(of_client_callback):
+
+#ifdef CONFIG_PPC64
+    PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1)
+#else
+    PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */
+#endif
+
+       /* save r4 */
+
+    PPC_STL r4, STKOFF(r1)
+
+       /* save lr */
+
+       mflr    r4
+    PPC_STL r4, PPC_LR_STKOFF(r1)
+
+       /* restore OF stack */
+
+       LOAD_REG_IMMEDIATE(r4, saved_stack)
+    PPC_LL  r4, 0(r4)
+
+       PPC_STLU r4,-SAVE_SPACE(r4)
+       PPC_STL r1,(STKOFF)(r4)         // save caller stack
+       mr      r1,r4
+
+    PPC_STL r2,  (STKOFF +  1 * ULONG_SIZE)(r1)
+    PPC_STL r0,  (STKOFF +  2 * ULONG_SIZE)(r1)
+
+       /* save ctr, cr and xer */
+
+       mfctr   r2
+    PPC_STL r2,  (STKOFF +  3 * ULONG_SIZE)(r1)
+       mfcr    r2
+    PPC_STL r2,  (STKOFF +  4 * ULONG_SIZE)(r1)
+       mfxer   r2
+    PPC_STL r2,  (STKOFF +  5 * ULONG_SIZE)(r1)
+
+       /* save r5 - r31 */
+
+    PPC_STL r5,  (STKOFF +  6 * ULONG_SIZE)(r1)
+    PPC_STL r6,  (STKOFF +  7 * ULONG_SIZE)(r1)
+    PPC_STL r7,  (STKOFF +  8 * ULONG_SIZE)(r1)
+    PPC_STL r8,  (STKOFF +  9 * ULONG_SIZE)(r1)
+    PPC_STL r9,  (STKOFF + 10 * ULONG_SIZE)(r1)
+    PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+    PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+    PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+    PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+    PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+    PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+    PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+    PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+    PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+    PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+    PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+    PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+    PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+    PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+    PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+    PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+    PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+    PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+    PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+    PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+    PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+    PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+#ifdef CONFIG_PPC64
+    LOAD_REG_IMMEDIATE(r2, of_client_interface)
+    ld  r2, 8(r2)
+#endif
+    bl BRANCH_LABEL(of_client_interface)
+
+       /* restore r5 - r31 */
+
+    PPC_LL  r5,  (STKOFF +  6 * ULONG_SIZE)(r1)
+    PPC_LL  r6,  (STKOFF +  7 * ULONG_SIZE)(r1)
+    PPC_LL  r7,  (STKOFF +  8 * ULONG_SIZE)(r1)
+    PPC_LL  r8,  (STKOFF +  9 * ULONG_SIZE)(r1)
+    PPC_LL  r9,  (STKOFF + 10 * ULONG_SIZE)(r1)
+    PPC_LL  r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+    PPC_LL  r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+    PPC_LL  r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+    PPC_LL  r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+    PPC_LL  r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+    PPC_LL  r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+    PPC_LL  r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+    PPC_LL  r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+    PPC_LL  r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+    PPC_LL  r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+    PPC_LL  r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+    PPC_LL  r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+    PPC_LL  r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+    PPC_LL  r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+    PPC_LL  r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+    PPC_LL  r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+    PPC_LL  r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+    PPC_LL  r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+    PPC_LL  r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+    PPC_LL  r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+    PPC_LL  r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+    PPC_LL  r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+       /* restore ctr, cr and xer */
+
+    PPC_LL  r2,  (STKOFF +  3 * ULONG_SIZE)(r1)
+       mtctr   r2
+    PPC_LL  r2,  (STKOFF +  4 * ULONG_SIZE)(r1)
+       mtcr    r2
+    PPC_LL  r2,  (STKOFF +  5 * ULONG_SIZE)(r1)
+       mtxer   r2
+
+       /* restore r0 and r2 */
+
+    PPC_LL  r2,  (STKOFF +  1 * ULONG_SIZE)(r1)
+    PPC_LL  r0,  (STKOFF +  2 * ULONG_SIZE)(r1)
+
+       /* restore caller stack */
+
+    PPC_LL  r1,  (STKOFF)(r1)
+
+    PPC_LL  r4, PPC_LR_STKOFF(r1)
+       mtlr    r4
+    PPC_LL  r4, STKOFF(r1)
+    PPC_LL  r1, 0(r1)
+
+       blr
+
+       /* rtas glue (must be reloctable) */
+GLOBL(of_rtas_start):
+       /* r3 = argument buffer, r4 = of_rtas_start */
+       /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
+       blr
+GLOBL(of_rtas_end):
+
+
+#define CACHE_LINE_SIZE         32
+#define LG_CACHE_LINE_SIZE      5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+_GLOBAL(flush_icache_range):
+        li      r5,CACHE_LINE_SIZE-1
+        andc    r3,r3,r5
+        subf    r4,r3,r4
+        add     r4,r4,r5
+        srwi.   r4,r4,LG_CACHE_LINE_SIZE
+        beqlr
+        mtctr   r4
+        mr      r6,r3
+1:      dcbst   0,r3
+        addi    r3,r3,CACHE_LINE_SIZE
+        bdnz    1b
+        sync                            /* wait for dcbst's to get to ram */
+        mtctr   r4
+2:      icbi    0,r6
+        addi    r6,r6,CACHE_LINE_SIZE
+        bdnz    2b
+        sync                            /* additional sync needed on g4 */
+        isync
+        blr
+
+        /* Get RAM size from QEMU configuration device */
+
+#define CFG_ADDR 0xf0000510
+#define FW_CFG_RAM_SIZE         0x03
+
+compute_ramsize:
+        LOAD_REG_IMMEDIATE(r9, CFG_ADDR)
+        li      r0,FW_CFG_RAM_SIZE
+        sth     r0,0(r9)
+        LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2)
+        lbz     r1,0(r9)
+        lbz     r0,0(r9)
+        slwi    r0,r0,8
+        or      r1,r1,r0
+        lbz     r0,0(r9)
+        slwi    r0,r0,16
+        or      r1,r1,r0
+        lbz     r0,0(r9)
+        slwi    r0,r0,24
+        or      r3,r1,r0
+        blr
+
+        /* Hard reset vector */
+       .section .romentry,"ax"
+       bl      _entry