diff options
Diffstat (limited to 'qemu/roms/openbios/arch/ppc/start.S')
-rw-r--r-- | qemu/roms/openbios/arch/ppc/start.S | 335 |
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 |