2020-04-26 23:56:19 -07:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2019 CTCaer
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Armv7tdmi Status register.
|
|
|
|
|
*
|
|
|
|
|
* bit0: Mode 0.
|
|
|
|
|
* bit1: Mode 1.
|
|
|
|
|
* bit2: Mode 2.
|
|
|
|
|
* bit3: Mode 3.
|
|
|
|
|
* bit4: Mode 4.
|
|
|
|
|
* bit5: Thumb state.
|
|
|
|
|
* bit6: FIQ disable.
|
|
|
|
|
* bit7: IRQ disable.
|
|
|
|
|
* bit8-27: Reserved.
|
|
|
|
|
* bit28: Overflow condition.
|
|
|
|
|
* bit29: Carry/Borrow/Extend condition.
|
|
|
|
|
* bit30: Zero condition.
|
|
|
|
|
* bit31: Negative/Less than condition.
|
|
|
|
|
*
|
|
|
|
|
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
|
|
|
|
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
|
|
|
|
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
|
|
|
|
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
|
|
|
|
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
|
|
|
|
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
|
|
|
|
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
|
|
|
|
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define EXCP_EN_ADDR 0x4003FFFC
|
|
|
|
|
#define EXCP_TYPE_ADDR 0x4003FFF8
|
|
|
|
|
#define EXCP_LR_ADDR 0x4003FFF4
|
|
|
|
|
|
|
|
|
|
#define EXCP_VEC_BASE 0x6000F000
|
|
|
|
|
#define EVP_COP_RESET_VECTOR 0x200
|
|
|
|
|
#define EVP_COP_UNDEF_VECTOR 0x204
|
|
|
|
|
#define EVP_COP_SWI_VECTOR 0x208
|
|
|
|
|
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
|
|
|
|
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
|
|
|
|
#define EVP_COP_RSVD_VECTOR 0x214
|
|
|
|
|
#define EVP_COP_IRQ_VECTOR 0x218
|
|
|
|
|
#define EVP_COP_FIQ_VECTOR 0x21C
|
|
|
|
|
|
|
|
|
|
#define MODE_USR 0x10
|
|
|
|
|
#define MODE_FIQ 0x11
|
|
|
|
|
#define MODE_IRQ 0x12
|
|
|
|
|
#define MODE_SVC 0x13
|
|
|
|
|
#define MODE_ABT 0x17
|
|
|
|
|
#define MODE_UDF 0x1B
|
|
|
|
|
#define MODE_SYS 0x1F
|
|
|
|
|
#define MODE_MASK 0x1F
|
|
|
|
|
|
|
|
|
|
#define FIQ 0x40
|
|
|
|
|
#define IRQ 0x80
|
|
|
|
|
|
|
|
|
|
.section .text._irq_setup
|
|
|
|
|
.arm
|
|
|
|
|
|
|
|
|
|
.extern ipl_main
|
|
|
|
|
.type ipl_main, %function
|
|
|
|
|
|
|
|
|
|
.extern svc_handler
|
|
|
|
|
.type svc_handler, %function
|
|
|
|
|
|
|
|
|
|
.extern irq_handler
|
|
|
|
|
.type irq_handler, %function
|
|
|
|
|
|
|
|
|
|
.extern fiq_setup
|
|
|
|
|
.type fiq_setup, %function
|
|
|
|
|
|
|
|
|
|
.extern fiq_handler
|
|
|
|
|
.type fiq_handler, %function
|
|
|
|
|
|
|
|
|
|
.globl _irq_setup
|
|
|
|
|
.type _irq_setup, %function
|
|
|
|
|
_irq_setup:
|
|
|
|
|
MRS R0, CPSR
|
|
|
|
|
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
|
|
|
|
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
|
|
|
|
MSR CPSR, R0
|
|
|
|
|
|
|
|
|
|
/* Setup IRQ stack pointer */
|
|
|
|
|
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
|
|
|
|
LDR SP, =0x40040000
|
|
|
|
|
|
2022-06-29 02:12:03 -07:00
|
|
|
|
/* Setup FIQ stack pointer */
|
|
|
|
|
MSR CPSR, #(MODE_FIQ | IRQ | FIQ) /* FIQ mode, IRQ/FIQ disabled */
|
|
|
|
|
LDR SP, =0x40040000
|
|
|
|
|
|
2020-04-26 23:56:19 -07:00
|
|
|
|
/* Setup SYS stack pointer */
|
|
|
|
|
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
|
|
|
|
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
|
|
|
|
|
|
|
|
|
MOV LR, PC
|
|
|
|
|
BL setup_vectors
|
|
|
|
|
/*BL fiq_setup*/
|
|
|
|
|
|
|
|
|
|
/* Enable interrupts */
|
|
|
|
|
BL irq_enable_cpu_irq_exceptions
|
|
|
|
|
|
|
|
|
|
B ipl_main
|
|
|
|
|
B .
|
|
|
|
|
|
2022-06-29 02:12:03 -07:00
|
|
|
|
.globl excp_reset
|
|
|
|
|
.type excp_reset, %function
|
|
|
|
|
excp_reset:
|
2020-04-26 23:56:19 -07:00
|
|
|
|
LDR R0, =EXCP_EN_ADDR
|
|
|
|
|
LDR R1, =0x30505645 /* EVP0 */
|
|
|
|
|
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
|
|
|
|
LDR R0, =EXCP_LR_ADDR
|
2020-04-29 17:25:22 -07:00
|
|
|
|
MOV R1, LR
|
2020-04-26 23:56:19 -07:00
|
|
|
|
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
|
|
|
|
LDR R0, =__bss_start
|
|
|
|
|
EOR R1, R1, R1
|
|
|
|
|
LDR R2, =__bss_end
|
|
|
|
|
SUB R2, R2, R0
|
|
|
|
|
BL memset
|
|
|
|
|
B _irq_setup
|
|
|
|
|
|
|
|
|
|
_reset_handler:
|
|
|
|
|
LDR R0, =EXCP_TYPE_ADDR
|
|
|
|
|
LDR R1, =0x545352 /* RST */
|
|
|
|
|
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
2022-06-29 02:12:03 -07:00
|
|
|
|
B excp_reset
|
2020-04-26 23:56:19 -07:00
|
|
|
|
|
|
|
|
|
_undefined_handler:
|
|
|
|
|
LDR R0, =EXCP_TYPE_ADDR
|
|
|
|
|
LDR R1, =0x464455 /* UDF */
|
|
|
|
|
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
2022-06-29 02:12:03 -07:00
|
|
|
|
B excp_reset
|
2020-04-26 23:56:19 -07:00
|
|
|
|
|
|
|
|
|
_prefetch_abort_handler:
|
|
|
|
|
LDR R0, =EXCP_TYPE_ADDR
|
|
|
|
|
LDR R1, =0x54424150 /* PABT */
|
|
|
|
|
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
2022-06-29 02:12:03 -07:00
|
|
|
|
B excp_reset
|
2020-04-26 23:56:19 -07:00
|
|
|
|
|
|
|
|
|
_data_abort_handler:
|
|
|
|
|
LDR R0, =EXCP_TYPE_ADDR
|
|
|
|
|
LDR R1, =0x54424144 /* DABT */
|
|
|
|
|
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
2022-06-29 02:12:03 -07:00
|
|
|
|
B excp_reset
|
2020-04-26 23:56:19 -07:00
|
|
|
|
|
|
|
|
|
.globl irq_enable_cpu_irq_exceptions
|
|
|
|
|
.type irq_enable_cpu_irq_exceptions, %function
|
|
|
|
|
irq_enable_cpu_irq_exceptions:
|
|
|
|
|
MRS R12, CPSR
|
|
|
|
|
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
|
|
|
|
MSR CPSR, R12
|
|
|
|
|
BX LR
|
|
|
|
|
|
|
|
|
|
.globl irq_disable_cpu_irq_exceptions
|
|
|
|
|
.type irq_disable_cpu_irq_exceptions, %function
|
|
|
|
|
irq_disable_cpu_irq_exceptions:
|
|
|
|
|
MRS R12, CPSR
|
|
|
|
|
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
|
|
|
|
MSR CPSR, R12
|
|
|
|
|
BX LR
|
|
|
|
|
|
|
|
|
|
_irq_handler:
|
|
|
|
|
MOV R13, R0 /* Save R0 in R13_IRQ */
|
|
|
|
|
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
|
|
|
|
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
|
|
|
|
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
|
|
|
|
|
|
|
|
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
|
|
|
|
STMFD SP!, {R0, R1} /* SPSR and PC */
|
|
|
|
|
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
|
|
|
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
|
|
|
|
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
|
|
|
|
|
|
|
|
|
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
|
|
|
|
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
|
|
|
|
|
|
|
|
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
|
|
|
|
LDR R12, =irq_handler
|
|
|
|
|
MOV LR, PC /* Copy the return address to link register */
|
|
|
|
|
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
|
|
|
|
|
|
|
|
|
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
|
|
|
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
|
|
|
|
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
|
|
|
|
|
|
|
|
|
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
|
|
|
|
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
|
|
|
|
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
|
|
|
|
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
|
|
|
|
|
|
|
|
|
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
|
|
|
|
NOP /* Cant access barked registers immediately */
|
|
|
|
|
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
|
|
|
|
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
|
|
|
|
|
|
|
|
|
_fiq_handler:
|
|
|
|
|
BL fiq_handler
|
|
|
|
|
|
|
|
|
|
setup_vectors:
|
|
|
|
|
/* Setup vectors */
|
|
|
|
|
LDR R0, =EXCP_VEC_BASE
|
|
|
|
|
|
|
|
|
|
LDR R1, =_reset_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_undefined_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_reset_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_prefetch_abort_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_data_abort_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_reset_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_irq_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
|
|
|
|
|
|
|
|
|
LDR R1, =_fiq_handler
|
|
|
|
|
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
|
|
|
|
|
|
|
|
|
BX LR
|