/*1* Copyright (c) 2019 CTCaer2*3* This program is free software; you can redistribute it and/or modify it4* under the terms and conditions of the GNU General Public License,5* version 2, as published by the Free Software Foundation.6*7* This program is distributed in the hope it will be useful, but WITHOUT8* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or9* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for10* more details.11*12* You should have received a copy of the GNU General Public License13* along with this program. If not, see <http://www.gnu.org/licenses/>.14*/1516/*17* Armv7tdmi Status register.18*19* bit0: Mode 0.20* bit1: Mode 1.21* bit2: Mode 2.22* bit3: Mode 3.23* bit4: Mode 4.24* bit5: Thumb state.25* bit6: FIQ disable.26* bit7: IRQ disable.27* bit8-27: Reserved.28* bit28: Overflow condition.29* bit29: Carry/Borrow/Extend condition.30* bit30: Zero condition.31* bit31: Negative/Less than condition.32*33* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers34* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR35* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq36* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq37* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc38* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt39* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und40* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR41*/4243#define EXCP_EN_ADDR 0x4003FFFC44#define EXCP_TYPE_ADDR 0x4003FFF845#define EXCP_LR_ADDR 0x4003FFF44647#define EXCP_VEC_BASE 0x6000F00048#define EVP_COP_RESET_VECTOR 0x20049#define EVP_COP_UNDEF_VECTOR 0x20450#define EVP_COP_SWI_VECTOR 0x20851#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C52#define EVP_COP_DATA_ABORT_VECTOR 0x21053#define EVP_COP_RSVD_VECTOR 0x21454#define EVP_COP_IRQ_VECTOR 0x21855#define EVP_COP_FIQ_VECTOR 0x21C5657#define MODE_USR 0x1058#define MODE_FIQ 0x1159#define MODE_IRQ 0x1260#define MODE_SVC 0x1361#define MODE_ABT 0x1762#define MODE_UDF 0x1B63#define MODE_SYS 0x1F64#define MODE_MASK 0x1F6566#define FIQ 0x4067#define IRQ 0x806869.section .text._irq_setup70.arm7172.extern ipl_main73.type ipl_main, %function7475.extern svc_handler76.type svc_handler, %function7778.extern irq_handler79.type irq_handler, %function8081.extern fiq_setup82.type fiq_setup, %function8384.extern fiq_handler85.type fiq_handler, %function8687.globl _irq_setup88.type _irq_setup, %function89_irq_setup:90MRS R0, CPSR91BIC R0, R0, #MODE_MASK /* Clear mode bits */92ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */93MSR CPSR, R09495/* Setup IRQ stack pointer */96MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */97LDR SP, =0x400400009899/* Setup FIQ stack pointer */100MSR CPSR, #(MODE_FIQ | IRQ | FIQ) /* FIQ mode, IRQ/FIQ disabled */101LDR SP, =0x40040000102103/* Setup SYS stack pointer */104MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */105LDR SP, =0x4003FF00 /* Will be changed later to DRAM */106107MOV LR, PC108BL setup_vectors109/*BL fiq_setup*/110111/* Enable interrupts */112BL irq_enable_cpu_irq_exceptions113114B ipl_main115B .116117.globl excp_reset118.type excp_reset, %function119excp_reset:120LDR R0, =EXCP_EN_ADDR121LDR R1, =0x30505645 /* EVP0 */122STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */123LDR R0, =EXCP_LR_ADDR124MOV R1, LR125STR R1, [R0] /* Save LR in EXCP_LR_ADDR */126LDR R0, =__bss_start127EOR R1, R1, R1128LDR R2, =__bss_end129SUB R2, R2, R0130BL memset131B _irq_setup132133_reset_handler:134LDR R0, =EXCP_TYPE_ADDR135LDR R1, =0x545352 /* RST */136STR R1, [R0] /* RST in EXCP_TYPE_ADDR */137B excp_reset138139_undefined_handler:140LDR R0, =EXCP_TYPE_ADDR141LDR R1, =0x464455 /* UDF */142STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */143B excp_reset144145_prefetch_abort_handler:146LDR R0, =EXCP_TYPE_ADDR147LDR R1, =0x54424150 /* PABT */148STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */149B excp_reset150151_data_abort_handler:152LDR R0, =EXCP_TYPE_ADDR153LDR R1, =0x54424144 /* DABT */154STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */155B excp_reset156157.globl irq_enable_cpu_irq_exceptions158.type irq_enable_cpu_irq_exceptions, %function159irq_enable_cpu_irq_exceptions:160MRS R12, CPSR161BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */162MSR CPSR, R12163BX LR164165.globl irq_disable_cpu_irq_exceptions166.type irq_disable_cpu_irq_exceptions, %function167irq_disable_cpu_irq_exceptions:168MRS R12, CPSR169ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */170MSR CPSR, R12171BX LR172173_irq_handler:174MOV R13, R0 /* Save R0 in R13_IRQ */175SUB R0, LR, #4 /* Put return address in R0_SYS */176MOV LR, R1 /* Save R1 in R14_IRQ (LR) */177MRS R1, SPSR /* Put the SPSR in R1_SYS */178179MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */180STMFD SP!, {R0, R1} /* SPSR and PC */181STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */182MOV R0, SP /* Make SP_SYS visible to IRQ mode */183SUB SP, SP, #8 /* Make room for stacking R0 and R1 */184185MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */186STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */187188MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */189LDR R12, =irq_handler190MOV LR, PC /* Copy the return address to link register */191BX R12 /* Call the C IRQ handler (ARM/THUMB) */192193MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */194MOV R0, SP /* Make SP_SYS visible to IRQ mode */195ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */196197MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */198MOV SP, R0 /* Copy SP_SYS to SP_IRQ */199LDR R0, [SP, #28] /* Load the saved SPSR from the stack */200MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */201202LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */203NOP /* Cant access barked registers immediately */204LDR LR, [SP, #24] /* Load return address from the SYS stack */205MOVS PC, LR /* Return restoring CPSR from SPSR */206207_fiq_handler:208BL fiq_handler209210setup_vectors:211/* Setup vectors */212LDR R0, =EXCP_VEC_BASE213214LDR R1, =_reset_handler215STR R1, [R0, #EVP_COP_RESET_VECTOR]216217LDR R1, =_undefined_handler218STR R1, [R0, #EVP_COP_UNDEF_VECTOR]219220LDR R1, =_reset_handler221STR R1, [R0, #EVP_COP_SWI_VECTOR]222223LDR R1, =_prefetch_abort_handler224STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]225226LDR R1, =_data_abort_handler227STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]228229LDR R1, =_reset_handler230STR R1, [R0, #EVP_COP_RSVD_VECTOR]231232LDR R1, =_irq_handler233STR R1, [R0, #EVP_COP_IRQ_VECTOR]234235LDR R1, =_fiq_handler236STR R1, [R0, #EVP_COP_FIQ_VECTOR]237238BX LR239240241