rockbox/utils/hwstub/stub/atj213x/crt0.S
Amaury Pouly 9bb6050d40 hwstub: rewrite exception catching
Since we can catch exceptions like data aborts on read/write, it takes very
little to also catch exceptions in calls. When extending this with the catching
of illegal instructions, the call instruction now becomes much more robust and
also for address and instruction probing. Since we can catch several types of
exception, rename set_data_abort_jmp to set_exception_jmp. At the same time,
simplify the logic in read/write request handlers. Also fix a bug in ARM
jump code: it was using
  stmia r1, {..., pc}
as if pc would get current pc + 8 but this is actually implementation defined
on older ARMs (typically pc + 12) and deprecated on newer ARMs, so rewrite the
code avoid that. The set_exception_jmp() function now also reports the exception
type.

Change-Id: Icd0dd52d2456b361b27c4776be09c3d13528ed93
2017-01-24 15:34:19 +01:00

295 lines
6.3 KiB
ArmAsm

#include "mips.h"
#include "system.h"
.extern main
.global start
.set mips32r2
.set noreorder
.set noat
.section .init.text,"ax",%progbits
start:
di # disable interrupts
bltzal zero, load_addr # ra = PC + 8, branch not taken
nop
load_addr:
addiu v0, ra, -12 # calc real load address
# account for branch delay slot
# and very first 'di' instruction
core_clk_setup:
la t0, 0xb0010000 # CMU base
li t1, 0x440 # HOSC enable, bypass
sw t1, 0(t0) # CMU_COREPLL
li t1, 0x350 # CORECLKS 24M, CCLKDIV = 1, SCLKDIV = 2,
# PCLKDIV = 4
sw t1, 0x0c(t0) # CMU_BUSCLK
li t1, 0xc6 # HOSC enable, PLL enable, 6*6M = 36M
sw t1, 0(t0) # CMU_COREPLL
nop
nop
nop
nop
nop
nop
nop
nop # arbitrary 300ns delay as there is no
# PLL lock feedback
li t1, 0x390 # CORECLKS COREPLL, CCLKDIV = 1, SCLKDIV = 2,
# PCLKDIV = 4
sw t1, 0x0c(t0) # CMU_BUSCLK
cache_setup:
la t0, 0x80000000 # an idx op should use an unmappable address
ori t1, t0, 0x4000 # 16kB cache
mtc0 zero, C0_TAGLO
mtc0 zero, C0_TAGHI
cache_init_loop:
cache ICIndexStTag, 0(t0) # index store icache tag
cache DCIndexStTag, 0(t0) # index store dcache tag
bne t0, t1, cache_init_loop
addiu t0, t0, 0x10
li t0, 3 # enable cache for kseg0 accesses
mtc0 t0, C0_CONFIG
ehb
la t0, relocstart
la t1, relocend
beq t0, v0, entry_point # no relocation needed
nop
reloc_loop:
lw s0, 0(v0) # src
lw s1, 4(v0)
lw s2, 8(v0)
lw s3, 12(v0)
sw s0, 0(t0) # dst
sw s1, 4(t0)
sw s2, 8(t0)
sw s3, 12(t0)
synci 0(t0) # dcache writeback invalidate
# icache invalidate
addiu t0, t0, 16 # inc dst addr
slt t2, t0, t1
bnez t2, reloc_loop
addiu v0, v0, 16 # inc src addr
entry_point_jump:
la t0, entry_point
sync
jr.hb t0
nop
entry_point:
intc_setup:
li t0, 0xb0020000 # INTC base
lw zero, 4(t0) # INTC_MSK mask all interrupt sources
core_irq_setup:
li t0, 0x00404000 # BEV=1 for C0_EBASE setup, IM6=1, IE=0
mtc0 t0, C0_STATUS
la t0, _irqbase # vectors base address must be 4k aligned
mtc0 t0, C0_EBASE
li t0, 0x00004000
mtc0 t0, C0_STATUS # BEV=0, IM6=1, IE=0
li t1, 0x08800000
mtc0 t1, C0_CAUSE # DC=1, IV=1
mtc0 zero,C0_INTCTL # VS = 0
clear_bss:
la t0, bssbegin
la t1, bssend
beq t0, t1, stack_setup
nop
clear_bss_loop:
sw zero, 0(t0)
bne t0, t1, clear_bss_loop
addiu t0, 4
stack_setup:
la k0, irqstackend
la sp, stackend
la t0, stackbegin
li t1, 0xdeadbeef
stack_munge_loop:
sw t1, 0(t0)
bne t0, sp, stack_munge_loop
addiu t0, 4
# jump to C code with enabled interrupts
la t0, main
jr.hb t0
ei
.extern exception_jmp_ctx_ptr
.global tlb_refill_handler
.section .exception.tlb_refill,"ax",%progbits
tlb_refill_handler:
la k1, exception_jmp_ctx_ptr
lw s0, 0(k1)
lw s1, 4(k1)
lw s2, 8(k1)
lw s3, 12(k1)
lw s4, 16(k1)
lw s5, 20(k1)
lw s6, 24(k1)
lw s7, 28(k1)
lw sp, 32(k1)
lw s8, 36(k1)
lw k1, 40(k1)
mtc0 k1, C0_EPC
ehb
li v0, EXCEPTION_ADDR
eret
nop
.global cache_error_handler
.section .exception.cache_error,"ax",%progbits
cache_error_handler:
la k1, exception_jmp_ctx_ptr
lw s0, 0(k1)
lw s1, 4(k1)
lw s2, 8(k1)
lw s3, 12(k1)
lw s4, 16(k1)
lw s5, 20(k1)
lw s6, 24(k1)
lw s7, 28(k1)
lw sp, 32(k1)
lw s8, 36(k1)
lw k1, 40(k1)
mtc0 k1, C0_EPC
ehb
li v0, EXCEPTION_ADDR
eret
nop
.global general_exception_handler
.section .exception.general_exception,"ax",%progbits
general_exception_handler:
la k1, exception_jmp_ctx_ptr
lw s0, 0(k1)
lw s1, 4(k1)
lw s2, 8(k1)
lw s3, 12(k1)
lw s4, 16(k1)
lw s5, 20(k1)
lw s6, 24(k1)
lw s7, 28(k1)
lw sp, 32(k1)
lw s8, 36(k1)
lw k1, 40(k1)
mtc0 k1, C0_EPC
ehb
li v0, EXCEPTION_UNSP
eret
nop
/* s0-s7 not saved as this are callee saved registers
* CO_STATUS is not saved as nested interrupts are not supported
*
* Separate irqstack is used for context save and irq processing
* k0 holds the address of the top of this stack and k1 is used
* to hold original sp value. Since we do not support nesting
* there is nothing to worry about
*/
.extern INT_UDC
.global irq_handler
.section .exception.irq,"ax",%progbits
irq_handler:
move k1, sp
move sp, k0
addiu sp, sp, -84
/* context save */
sw AT, 0(sp)
sw v0, 4(sp)
sw v1, 8(sp)
sw a0, 12(sp)
sw a1, 16(sp)
sw a2, 20(sp)
sw a3, 24(sp)
sw t0, 28(sp)
sw t1, 32(sp)
sw t2, 36(sp)
sw t3, 40(sp)
sw t4, 44(sp)
sw t5, 48(sp)
sw t6, 52(sp)
sw t7, 56(sp)
sw t8, 60(sp)
sw t9, 64(sp)
sw fp, 68(sp)
sw ra, 72(sp)
mfhi t0
mflo t1
sw t0, 76(sp)
sw t1, 80(sp)
/* handle interrupt */
lui t0, 0xb002 /* INTC base */
lw a0, 0(t0) /* INTC_PD */
lw a1, 4(t0) /* INTC_MSK */
and a0, a0, a1 /* mask */
andi a0, a0, 0x10 /* UDC flag */
beq a0, zero, restore
nop
/* irq dispatch */
la a0, INT_UDC
jalr a0
nop
restore:
/* context restore */
lw t0, 76(sp)
lw t1, 80(sp)
mthi t0
mtlo t1
lw AT, 0(sp)
lw v0, 4(sp)
lw v1, 8(sp)
lw a0, 12(sp)
lw a1, 16(sp)
lw a2, 20(sp)
lw a3, 24(sp)
lw t0, 28(sp)
lw t1, 32(sp)
lw t2, 36(sp)
lw t3, 40(sp)
lw t4, 44(sp)
lw t5, 48(sp)
lw t6, 52(sp)
lw t7, 56(sp)
lw t8, 60(sp)
lw t9, 64(sp)
lw fp, 68(sp)
lw ra, 72(sp)
addiu sp, sp, 84
move sp, k1
eret
nop
.set reorder
.set at