summaryrefslogtreecommitdiff
path: root/roms/openhackware/src/start.S
diff options
context:
space:
mode:
Diffstat (limited to 'roms/openhackware/src/start.S')
-rw-r--r--roms/openhackware/src/start.S379
1 files changed, 379 insertions, 0 deletions
diff --git a/roms/openhackware/src/start.S b/roms/openhackware/src/start.S
new file mode 100644
index 000000000..471e56fef
--- /dev/null
+++ b/roms/openhackware/src/start.S
@@ -0,0 +1,379 @@
+/*
+ * <start.S>
+ *
+ * BIOS start code for Open Hack'Ware.
+ *
+ * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define ASSEMBLY_CODE
+#include "bios.h"
+
+.section .start, "ax"
+.align 2
+
+.globl _start
+_start:
+ /* Save our stack pointer */
+ lis r11, saved_params@h ;
+ ori r11, r11, saved_params@l ;
+ stw r1, 0(r11) ;
+ /* Fill space from _bss_start to _ram_start with zeroes */
+ lis r11, _bss_start@h ;
+ ori r11, r11, _bss_start@l ;
+ lis r12, _ram_start@h ;
+ ori r12, r12, _ram_start@l ;
+ subf r12, r11, r12 ;
+ srawi r12, r12, 2 ;
+ cmpi 0, r12, 0 ;
+ beq _bss_done ;
+ mtctr r12 ;
+ subi r11, r11, 4 ;
+ li r12, 0 ;
+_bss_loop:
+ stwu r12, 4(r11) ;
+ bdnz _bss_loop ;
+_bss_done:
+ /* Now, we have a real C environment: call main */
+ bl main ;
+ /* If we return, stop */
+.globl bug
+bug:
+ li r0, 0x80 ;
+ mtlr r0 ;
+ blr ;
+_return_loop:
+ b _return_loop ;
+
+.section .data
+.align 2
+saved_params:
+ .long 0x00000000 /* OF stack */
+ .long 0x00000000 /* client stack */
+ .long 0x00000000 /* client link */
+
+.section .text
+.align 2
+
+.globl transfer_handler
+transfer_handler:
+ /* Build a new stack room and launch loaded image
+ * void transfer_handler (void *residual, void *load_addr,
+ * void *OF_entry, void *bootinfos,
+ * void *cmdline, void *unused,
+ * void *nip, void *stack_base);
+ */
+ mfmsr r0 ;
+ mtspr SRR1, r0 ;
+ mtspr SRR0, r9 ;
+ li r0, 0 ;
+ mr r1, r10 ;
+ stw r1, -16(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ /* Skip frame pointer */
+ stwu r0, -8(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ rfi ;
+ /* Should never return, but who knows... */
+ bl bug ;
+
+.globl OF_entry
+OF_entry:
+ /* Save the stack pointer and get our own one */
+ lis r11, saved_params@h ;
+ ori r11, r11, saved_params@l ;
+ mflr r12 ;
+ stw r12, 8(r11) ;
+ stw r1, 4(r11) ;
+ lwz r1, 0(r11) ;
+ bl OF_client_entry ;
+ lis r11, saved_params@h ;
+ ori r11, r11, saved_params@l ;
+ lwz r12, 8(r11) ;
+ mtlr r12 ;
+ lwz r1, 4(r11) ;
+ blr ;
+
+ /* PPC helpers */
+.globl mfmsr
+mfmsr:
+ /* uint32_t mfmsr (void); */
+ mfmsr r3 ;
+ blr ;
+.globl mtmsr
+mtmsr:
+ /* void mtmsr (uint32_t msr); */
+ lis r0, _mtmsr_rfi@h ;
+ ori r0, r0, _mtmsr_rfi@l ;
+ mtspr 26, r0 ;
+ mtspr 27, r3 ;
+ rfi ;
+_mtmsr_rfi:
+ blr ;
+.globl MMU_on
+MMU_on:
+ /* void MMU_on (void); */
+ stwu r1, -16(r1) ;
+ mflr r0 ;
+ stw r0, 20(r1) ;
+ mfmsr r3 ;
+ ori r3, r3, 0x30 ;
+ bl mtmsr ;
+ lwz r0, 20(r1) ;
+ mtlr r0 ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl MMU_off
+MMU_off:
+ /* void MMU_off (void); */
+ stwu r1, -16(r1) ;
+ mflr r0 ;
+ stw r0, 20(r1) ;
+ mfmsr r3 ;
+ andi. r3, r3, 0xFFCF ;
+ bl mtmsr ;
+ lwz r0, 20(r1) ;
+ mtlr r0 ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl mfpvr
+mfpvr:
+ /* uint32_t mfpvr (void); */
+ mfpvr r3 ;
+ blr ;
+
+.globl mftb
+mftb:
+ /* void mftb (uint32_t *tb); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ stw r12, 8(r1) ;
+ /* No need to save lr */
+_tb_loop:
+ mftbu r11 ;
+ mftb r12 ;
+ mftbu r0 ;
+ cmpw r0, r11 ;
+ bne _tb_loop ;
+ stw r11, 0(r3) ;
+ stw r12, 4(r3) ;
+ lwz r12, 8(r1) ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+ /* IO helpers */
+.globl inb
+inb:
+ /* uint32_t inb (uint16_t port); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ lbz r3, 0(r3) ;
+ eieio ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl outb
+outb:
+ /* void outb (uint16_t port, uint32_t val); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ eieio ;
+ stb r4, 0(r3) ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl inw
+inw:
+ /* uint32_t inw (uint16_t port); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ lhbrx r3, 0, r3 ;
+ eieio ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl outw
+outw:
+ /* void outw (uint16_t port, uint32_t val); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ eieio ;
+ sthbrx r4, 0, r3 ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl inl
+inl:
+ /* uint32_t inl (uint16_t port); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ lwbrx r3, 0, r3 ;
+ eieio ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl outl
+outl:
+ /* void outl (uint16_t port, uint32_t val); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ lis r11, isa_io_base@h ;
+ ori r11, r11, isa_io_base@l ;
+ lwz r11, 0(r11) ;
+ add r3, r3, r11 ;
+ eieio ;
+ stwbrx r4, 0, r3 ;
+ lwz r11, 12(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl eieio
+eieio:
+ eieio ;
+ blr ;
+
+ /* Misc helpers */
+.globl ldswap16
+ldswap16:
+ /* uint16_t ldswap16 (uint16_t *addr); */
+ lhbrx r3, 0, r3 ;
+ blr ;
+
+.globl stswap16
+stswap16:
+ /* void stswap16 (void *addr, uint16_t val); */
+ sthbrx r4, 0, r3 ;
+ blr ;
+
+.globl ldswap32
+ldswap32:
+ /* uint32_t ldswap32 (uint32_t *addr); */
+ lwbrx r3, 0, r3 ;
+ blr ;
+
+.globl stswap32
+stswap32:
+ /* void stswap32 (void *addr, uint32_t val); */
+ stwbrx r4, 0, r3 ;
+ blr ;
+
+.globl mul64
+mul64:
+ /* void mul64 (uint32_t *ret, uint32_t a, uint32_t b); */
+ mulhwu r0, r4, r5 ;
+ stw r0, 0(r3) ;
+ mullw r0, r4, r5 ;
+ stw r0, 4(r3) ;
+ blr ;
+
+.globl add64
+add64:
+ /* void add64 (uint32_t *ret, uint32_t *a, uint32_t *b); */
+ stwu r1, -16(r1) ;
+ stw r11, 12(r1) ;
+ stw r12, 8(r1) ;
+ lwz r11, 4(r4) ;
+ lwz r12, 4(r5) ;
+ addc r0, r11, r12 ;
+ stw r0, 4(r3) ;
+ lwz r11, 0(r4) ;
+ lwz r12, 0(r5) ;
+ adde r0, r11, r12 ;
+ stw r0, 0(r3) ;
+ lwz r12, 8(r1) ;
+ lwz r11, 4(r1) ;
+ addi r1, r1, 16 ;
+ blr ;
+
+.globl setjmp
+setjmp:
+ /* int setjmp (jmp_buf env); */
+ /* save gprs */
+ stmw r0, 0(r3) ;
+ /* save lr, ctr, xer and ccr */
+ mflr r0 ;
+ stw r0, 0x80(r3) ;
+ mfctr r0 ;
+ stw r0, 0x84(r3) ;
+ mfxer r0 ;
+ stw r0, 0x88(r3) ;
+ mfcr r0 ;
+ stw r0, 0x8C(r3) ;
+ /* return 0 */
+ li r3, 0 ;
+ blr ;
+
+.globl longjmp
+longjmp:
+ /* void longjmp (jmp_buf env, int val); */
+ /* Let's pretend env is our stack */
+ mr r1, r3 ;
+ /* Be sure we won't return 0 */
+ cmpi 0, r4, 0 ;
+ bne _longjmp_cont ;
+ addi r4, r4, 1 ;
+_longjmp_cont:
+ /* Store return value in jmp_buf */
+ stw r4, 0x0C(r1) ;
+ /* restore lr, ctr, xer and ccr */
+ lwz r0, 0x80(r1) ;
+ mtlr r0 ;
+ lwz r0, 0x84(r1) ;
+ mtctr r0 ;
+ lwz r0, 0x88(r1) ;
+ mtxer r0 ;
+ lwz r0, 0x8C(r1) ;
+ mtcr r0 ;
+ /* Restore r2 to r31 */
+ lmw r2, 0x08(r1) ;
+ /* Restore r0 (could forget it...) */
+ lwz r0, 0x00(r1) ;
+ /* Restore stack */
+ lwz r1, 0x04(r1) ;
+ /* Return */
+ blr ;