summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/slof/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/slof/entry.S')
-rw-r--r--qemu/roms/SLOF/slof/entry.S210
1 files changed, 210 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/slof/entry.S b/qemu/roms/SLOF/slof/entry.S
new file mode 100644
index 000000000..dcff57ba0
--- /dev/null
+++ b/qemu/roms/SLOF/slof/entry.S
@@ -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