/* * 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 . */ /* * 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 /* 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 . _reset: LDR R0, =EXCP_EN_ADDR LDR R1, =0x30505645 /* EVP0 */ STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */ LDR R0, =EXCP_LR_ADDR MOV R1, LR 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 */ B _reset _undefined_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x464455 /* UDF */ STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */ B _reset _prefetch_abort_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x54424150 /* PABT */ STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */ B _reset _data_abort_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x54424144 /* DABT */ STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */ B _reset .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