ca12478df6
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
249 lines
5.6 KiB
ArmAsm
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
|