Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / entry.S
diff --git a/qemu/roms/SLOF/slof/entry.S b/qemu/roms/SLOF/slof/entry.S
new file mode 100644 (file)
index 0000000..dcff57b
--- /dev/null
@@ -0,0 +1,210 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <macros.h>
+
+#define STACKSIZE 0x2000
+
+       #
+       # The generic exception code.
+       #
+       # Enter with GPR0 = vector, SPRG0 = saved GPR0
+       #
+
+       .section ".entry_text"
+
+the_handler:
+       .quad   handler
+
+eregs:
+       /* the_exception_frame is a C variable which is usually
+        * defined in $(TARG).c
+        * the_exception_frame can be accessed from paflof through
+        * the word eregs
+        * in the case an excpetion is handled paflof will read
+        * from eregs the values of all registers and print them
+        * out in the exception handler */
+       .quad   the_exception_frame
+
+handler:
+       mtsprg 1,1      # SPRG1 = saved GPR1
+       bcl 20,31,$+4
+       mflr 1
+       ld 1,eregs-$+4(1)       # GPR1 = address of register save area
+
+       .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
+               16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+       std \i,\i*8(1)
+       .endr           # save GPR2..GPR31
+
+       li r3, 3        // GPR3 = mode (param_1, param_2)
+       mr 4,0          // GPR4 = vector
+
+       mfsprg 0,0
+       std 0,0(1)      # save GPR0
+       mfsprg 0,1
+       std 0,8(1)      # save GPR1
+
+       cmpwi   r4, 0x900       # Decrementer interrupt
+       bne     0f
+       mfdec   r5              # Save old value of decrementer as reason
+       lis     r0,0x7fff       # Set decrementer to highest value 
+       mtdec   r0
+0:
+       mfcr 0
+       std 0,0x100(1)
+       mfxer 0
+       std 0,0x108(1)
+       mfsprg 0,3      # save lr       
+       std 0,0x110(1)
+       mfsprg 0,2      # save ctr      
+       std 0,0x118(1)
+       mfsrr0 0
+       std 0,0x120(1)
+       mfsrr1 0
+       std 0,0x128(1)
+       mfdar 0
+       std 0,0x130(1)
+       mfdsisr 0
+       std 0,0x138(1)  # save special regs
+
+       bcl     20, 31, over
+base:
+       .align  3
+.the_system_stack:
+       .quad   the_system_stack+STACKSIZE-base
+over:
+       mflr    r2                              /* gpr 2 is the base */
+       ld      r1, .the_system_stack-base(r2)  /* load stack pointer */
+       add     r1, r1, r2                      /* add base */
+       li      r0, 0
+       stdu    r0, -0x10(r1)
+       stdu    r1, -0x100(r1)
+
+       lis 2,engine@ha
+       ld 0,engine@l(2) # set up entry
+       mtsrr0  0
+               
+       ld 2,8+engine@l(2) # set up TOC pointer
+
+       rfid
+#      b .engine       # ...and run!
+
+
+
+       #
+       # Swap non-volatile client interface regs, plus GPR3..GPR7.
+       #
+
+swap_ci_regs:
+       /* save lr */
+       mflr    r0
+       /* let's find out where our client stack is */
+       bcl     20, 31, client_over
+client_base:
+       .align  3
+.the_client_frame:
+       .quad   the_client_frame-client_base
+client_over:
+       mflr    r8                              /* gpr 2 is the client_base */
+       mtlr    r0                              /* restore the original lr */
+       ld      r0, .the_client_frame-client_base(r8)
+       add     r8, r0, r8                      /* add the client_base */
+       /* r8 now contains the address of the_client_frame */
+
+       .irp i, 1,2,3,4,5,6,7, \
+               13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+       ld 0,\i*8(8)
+       std \i,\i*8(8)
+       mr \i,0
+       .endr           # swap GPR1..7, GPR13..31
+
+       ld 0,0x100(8)
+       mfcr 9
+       mtcrf 0xff,0
+       std 9,0x100(8)  # swap CR
+
+       ld 0,0x128(8)
+       mfmsr 9
+       mtmsrd 0
+       sync
+       isync
+       std 9,0x128(8)  # swap MSR
+
+       blr
+
+       #
+       # Entry point for the OF client interface.
+       #
+
+        .globl client_entry_point
+        .section        ".opd","aw"
+        .align 3
+client_entry_point:
+        .quad   .client_entry_point,.TOC.@tocbase,0
+        .previous
+        .type   .client_entry_point,@function
+        .globl  .client_entry_point
+.client_entry_point:
+       mflr 4
+       bl swap_ci_regs # swap regs
+       mtlr 4
+       li 3, 0 # client call
+       blr     
+
+       #
+       # Start the client.
+       #
+
+        .globl call_client
+        .section        ".opd","aw"
+        .align 3
+call_client:
+        .quad   .call_client,.TOC.@tocbase,0
+        .previous
+        .type   .call_client,@function
+        .globl  .call_client
+
+.call_client:  # called with r3 = address, returns r3
+       mflr 4
+       mtctr 3
+       bl swap_ci_regs
+       /* Check if LE loading */
+       cmpwi 0,13,1
+       beq 0f
+       bctrl
+       b 1f
+0:     /* handle LE */
+       mfmsr 13
+       xori  13,13,1
+       mtsrr1 13
+       mfctr 13
+       mr 12,13
+       mtsrr0 13
+       rfid
+#if 0 /* in case we return back, still to be tested */
+       .long 0x05009f42; /* bcl 20,31,$+4   */
+       .long 0xa602c87d; /* mflr r14    */
+       .long 0x1c00ce39; /* addi r14,r14,28   */
+       .long 0xa600e07d; /* mfmsr r15    */
+       .long 0x0100ef69; /* xori r15,r15,1   */
+       .long 0xa603da7d; /* mtsrr0 r14    */
+       .long 0xa603fb7d; /* mtsrr1 r15    */
+       .long 0x2400004c; /* rfid */
+#endif
+1:
+       bl swap_ci_regs
+       mtlr 4
+       li 3, -1 # client app return
+       blr
+
+       .lcomm  the_system_stack, STACKSIZE, 16