rockbox/firmware/target/mips/ingenic_x1000/crt0.S
Aidan MacDonald ca12478df6 x1000: add simple binary header to declare the load address
The header format is basic, a variable length list of values
tagged by 4-byte strings. The main application to to allow a
loader to determine the load address of the binary at runtime
instead of using a hardcoded address. But the header contents
aren't fixed and it could be extended for other purposes too.

Change-Id: If51d85b4c2eb53c919a91b54985b157e8e5c20ef
2022-03-06 23:22:49 +00:00

249 lines
5.6 KiB
ArmAsm

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2021 Aidan MacDonald
*
* 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; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "mips.h"
.text
.extern main
.extern system_early_init
.extern _loadaddress
.global _start
.set push
.set mips32
.set noreorder
.set noat
.section .init.text
_start:
b _realstart
nop
/* Header entries are 4-byte string labels (not null terminated!) followed
* by 4-byte values. Header should begin in the first 128 bytes and should
* be no more than 256 bytes in length. */
_header:
.ascii "BEGINHDR" /* beginning of header */
.ascii "LOAD"
.word _loadaddress
.ascii "ENDH" /* end of header structure */
_realstart:
/* Cache init */
li v0, 0x80000000
ori v1, v0, 0x4000
mtc0 zero, C0_TAGLO
mtc0 zero, C0_TAGHI
_cache_loop:
cache ICIndexStTag, 0(v0)
cache DCIndexStTag, 0(v0)
addiu v0, v0, 32
bne v0, v1, _cache_loop
nop
/* Invalidate BTB */
mfc0 v0, C0_Config, 7
nop
ori v0, v0, 2
mtc0 v0, C0_Config, 7
nop
/* Copy IRAM from BSS to low memory. */
la t0, _iramcopy
la t1, _iramstart
la t2, _iramend
_iram_loop:
lw t3, 0(t0)
addiu t1, 4
addiu t0, 4
bne t1, t2, _iram_loop
sw t3, -4(t1)
/* Clear the BSS segment (needed to zero-initialize C static values) */
la t0, _bssbegin
la t1, _bssend
beq t0, t1, _bss_done
_bss_loop:
addiu t0, 4
bne t0, t1, _bss_loop
sw zero, -4(t0)
_bss_done:
/* Set stack pointer and clear the stack */
la sp, stackend
la t0, stackbegin
li t1, 0xDEADBEEF
_stack_loop:
addiu t0, 4
bne t0, sp, _stack_loop
sw t1, -4(t0)
/* Clear the IRQ stack */
la k0, _irqstackend
la t0, _irqstackbegin
_irqstack_loop:
addiu t0, 4
bne t0, k0, _irqstack_loop
sw t1, -4(t0)
/* Jump to C code */
jal system_early_init
nop
j main
nop
/* Exception entry points */
.section .vectors.1, "ax", %progbits
j tlb_refill_handler
nop
.section .vectors.2, "ax", %progbits
j real_exception_handler
nop
.section .vectors.3, "ax", %progbits
j real_exception_handler
nop
.section .vectors.4, "ax", %progbits
j real_exception_handler
nop
.section .vectors, "ax", %progbits
real_exception_handler:
move k0, sp
la sp, _irqstackend
addiu sp, -0x84
sw k0, 0x80(sp)
sw ra, 0x00(sp)
sw fp, 0x04(sp)
sw gp, 0x08(sp)
sw t9, 0x0c(sp)
sw t8, 0x10(sp)
sw s7, 0x14(sp)
sw s6, 0x18(sp)
sw s5, 0x1c(sp)
sw s4, 0x20(sp)
sw s3, 0x24(sp)
sw s2, 0x28(sp)
sw s1, 0x2c(sp)
sw s0, 0x30(sp)
sw t7, 0x34(sp)
sw t6, 0x38(sp)
sw t5, 0x3c(sp)
sw t4, 0x40(sp)
sw t3, 0x44(sp)
sw t2, 0x48(sp)
sw t1, 0x4c(sp)
sw t0, 0x50(sp)
sw a3, 0x54(sp)
sw a2, 0x58(sp)
sw a1, 0x5c(sp)
sw a0, 0x60(sp)
sw v1, 0x64(sp)
sw v0, 0x68(sp)
sw $1, 0x6c(sp)
mflo k0
nop
sw k0, 0x70(sp)
mfhi k0
nop
sw k0, 0x74(sp)
mfc0 k0, C0_STATUS
nop
nop
nop
sw k0, 0x78(sp)
mfc0 k0, C0_EPC
nop
nop
nop
sw k0, 0x7c(sp)
li k1, M_CauseExcCode
mfc0 a0, C0_CAUSE
and k0, a0, k1
bnez k0, _exception
nop
jal intr_handler
nop
j _exception_return
_exception:
mfc0 a1, C0_EPC
nop
nop
nop
jal exception_handler
move a2, sp
_exception_return:
lw ra, 0x00(sp)
lw fp, 0x04(sp)
lw gp, 0x08(sp)
lw t9, 0x0c(sp)
lw t8, 0x10(sp)
lw s7, 0x14(sp)
lw s6, 0x18(sp)
lw s5, 0x1c(sp)
lw s4, 0x20(sp)
lw s3, 0x24(sp)
lw s2, 0x28(sp)
lw s1, 0x2c(sp)
lw s0, 0x30(sp)
lw t7, 0x34(sp)
lw t6, 0x38(sp)
lw t5, 0x3c(sp)
lw t4, 0x40(sp)
lw t3, 0x44(sp)
lw t2, 0x48(sp)
lw t1, 0x4c(sp)
lw t0, 0x50(sp)
lw a3, 0x54(sp)
lw a2, 0x58(sp)
lw a1, 0x5c(sp)
lw a0, 0x60(sp)
lw v1, 0x64(sp)
lw v0, 0x68(sp)
lw $1, 0x6c(sp)
lw k0, 0x70(sp)
mtlo k0
nop
lw k0, 0x74(sp)
mthi k0
nop
lw k0, 0x78(sp)
mtc0 k0, C0_STATUS
nop
nop
nop
lw k0, 0x7c(sp)
mtc0 k0, C0_EPC
nop
nop
nop
lw sp, 0x80(sp)
eret
nop
.set pop