summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/ppc/start.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/ppc/start.S')
-rw-r--r--qemu/roms/openbios/arch/ppc/start.S335
1 files changed, 335 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/ppc/start.S b/qemu/roms/openbios/arch/ppc/start.S
new file mode 100644
index 000000000..40ee08963
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/start.S
@@ -0,0 +1,335 @@
+/*
+ * 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 run inside MOL
+ *
+ * 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 "asm/asmdefs.h"
+#include "asm/processor.h"
+#include "osi.h"
+
+/************************************************************************/
+/* Macros */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ;
+#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
+
+#define EXCEPTION_PREAMBLE \
+ mtsprg1 r1 ; /* scratch */ \
+ mfsprg0 r1 ; /* exception stack in sprg0 */ \
+ addi r1,r1,-80 ; /* push exception frame */ \
+ \
+ stw r0,0(r1) ; /* save r0 */ \
+ mfsprg1 r0 ; \
+ stw r0,4(r1) ; /* save r1 */ \
+ stw r2,8(r1) ; /* save r2 */ \
+ stw r3,12(r1) ; /* save r3 */ \
+ stw r4,16(r1) ; \
+ stw r5,20(r1) ; \
+ stw r6,24(r1) ; \
+ stw r7,28(r1) ; \
+ stw r8,32(r1) ; \
+ stw r9,36(r1) ; \
+ stw r10,40(r1) ; \
+ stw r11,44(r1) ; \
+ stw r12,48(r1) ; \
+ \
+ mflr r0 ; \
+ stw r0,52(r1) ; \
+ mfcr r0 ; \
+ stw r0,56(r1) ; \
+ mfctr r0 ; \
+ stw r0,60(r1) ; \
+ mfxer r0 ; \
+ stw r0,64(r1) ; \
+ \
+ /* 76(r1) unused */ \
+ addi r1,r1,-16 ; /* call conventions uses 0(r1) and 4(r1)... */
+
+
+/************************************************************************/
+/* stack space */
+/************************************************************************/
+
+ .section .bss
+ .balign 32
+ .space 32*1024 // 32 K client stack
+client_stack:
+ .space 128
+
+ .space 64*1024 // 64 K stack
+stack: .space 64
+
+ .space 32*1024 // 32 K exception stack
+estack: .space 128
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+ .text
+GLOBL(_start):
+ li r0,0
+ mtmsr r0
+
+ lis r1,HA(estack)
+ addi r1,r1,LO(estack)
+ mtsprg0 r1 // setup exception stack
+ lis r1,HA(stack)
+ addi r1,r1,LO(stack)
+
+ // copy exception vectors
+ lis r3,HA(__vectors)
+ addi r3,r3,LO(__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 setup_mmu
+ bl 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 = clint interface handler
+ * r6 = address of client program arguments (unused)
+ * r7 = length of client program arguments (unsed)
+ */
+saved_stack:
+ .long 0
+ /* void call_elf( entry ) */
+GLOBL(call_elf):
+ mflr r0
+ stwu r1,-16(r1)
+ stw r0,20(r1)
+ mtlr r3
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // save our stack pointer
+ stw r1,0(r8)
+ lis r1,HA(client_stack)
+ addi r1,r1,LO(client_stack)
+ lis r5,HA(of_client_callback)
+ addi r5,r5,LO(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
+ mtmsr r0
+ blrl
+
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // restore stack pointer
+ mr r1,r8
+ lwz r0,20(r1)
+ mtlr r0
+ addi r1,r1,16
+ // XXX: should restore r12-r31 etc..
+ // we should not really come here though
+ blr
+
+GLOBL(of_client_callback):
+ lis r4,HA(saved_stack)
+ addi r4,r4,LO(saved_stack)
+ lwz r4,0(r4)
+ stwu r4,-32(r4)
+ mflr r5
+ stw r5,32+4(r4)
+ stw r1,8(r4) // save caller stack
+ mr r1,r4
+ stw r2,12(r1)
+ stw r0,16(r1)
+ mfctr r2
+ stw r2,20(r1)
+ mfcr r2
+ stw r2,24(r1)
+ mfxer r2
+ stw r2,28(r1)
+ // do we need to save more registers?
+ bl of_client_interface
+ lwz r4,32+4(r1)
+ mtlr r4
+ lwz r2,20(r1)
+ mtctr r2
+ lwz r2,24(r1)
+ mtcr r2
+ lwz r2,28(r1)
+ mtxer r2
+ lwz r2,12(r1)
+ lwz r0,16(r1)
+ lwz r1,8(r1) // restore caller stack
+ 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?) */
+ mr r6,r3
+ lis r3,HA(OSI_SC_MAGIC_R3)
+ addi r3,r3,LO(OSI_SC_MAGIC_R3)
+ lis r4,HA(OSI_SC_MAGIC_R4)
+ addi r4,r4,LO(OSI_SC_MAGIC_R4)
+ li r5,OSI_OF_RTAS
+ sc
+ blr
+GLOBL(of_rtas_end):
+
+
+ /* used in a hack to the newworld calibration */
+GLOBL(nw_dec_calibration):
+ .long 0
+GLOBL(timer_calib_start):
+ lis r3,HA(nw_dec_calibration)
+ addi r3,r3,LO(nw_dec_calibration)
+ lwz r3,0(r3)
+ blr
+GLOBL(timer_calib_end):
+
+
+/************************************************************************/
+/* vectors */
+/************************************************************************/
+
+GLOBL(__vectors):
+ nop // NULL-jmp trap
+1: nop //
+ b 1b
+
+exception_return:
+ addi r1,r1,16 // pop ABI frame
+
+ lwz r0,52(r1)
+ mtlr r0
+ lwz r0,56(r1)
+ mtcr r0
+ lwz r0,60(r1)
+ mtctr r0
+ lwz r0,64(r1)
+ mtxer r0
+
+ lwz r0,0(r1) // restore r0
+ lwz r2,8(r1) // restore r2
+ lwz r3,12(r1) // restore r3
+ lwz r4,16(r1)
+ lwz r5,20(r1)
+ lwz r6,24(r1)
+ lwz r7,28(r1)
+ lwz r8,32(r1)
+ lwz r9,36(r1)
+ lwz r10,40(r1)
+ lwz r11,44(r1)
+ lwz r12,48(r1)
+ lwz r1,4(r1) // restore r1
+ rfi
+
+trap_error:
+ mflr r3
+ b unexpected_excep
+
+ILLEGAL_VECTOR( 0x100 )
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(dsi_exception)
+ addi r3,r3,LO(dsi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+VECTOR( 0x400, "ISI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(isi_exception)
+ addi r3,r3,LO(isi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+ 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 )
+
+GLOBL(__vectors_end):
+
+
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+GLOBL(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