changeset 78:95ef11e76c5b

src/cs/system/main/gcc: asm code pieced from Citrine
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 20 Jul 2018 06:46:56 +0000
parents 6b6675a07b70
children 621b358b760d
files src/cs/system/main/gcc/exceptions.S src/cs/system/main/gcc/irq_twiddle.S src/cs/system/main/gcc/irqfiq.S src/cs/system/main/gcc/ramvecs.S src/cs/system/main/gcc/vectors.S
diffstat 5 files changed, 207 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/system/main/gcc/exceptions.S	Fri Jul 20 06:46:56 2018 +0000
@@ -0,0 +1,86 @@
+/*
+ * This module contains ARM exception handlers which used to be
+ * in chipsetsw/system/Main/int.s in TI's Leonardo code.
+ */
+
+    .section "except_stack","aw",%nobits
+    .balign  4
+    .space   512
+    .globl   _Except_Stack_SP
+_Except_Stack_SP:
+
+	.text
+	.code	32
+
+@ layout of xdump buffer:
+@ struct xdump_s {
+@     long registers[16] // svc mode registers
+@     long cpsr          // svc mode CPSR
+@     long exception     // magic word + index of vector taken
+@     long stack[20]     // bottom 20 words of usr mode stack
+@ }
+
+	.globl	_arm_undefined
+_arm_undefined:
+	@ store r12 for Xdump_buffer pointer, r11 for index
+	stmfd   r13!,{r11,r12}
+	mov     r11,#1
+	b       save_regs
+
+	.globl	_arm_swi
+_arm_swi:
+	@ store r12 for Xdump_buffer pointer, r11 for index
+	stmfd   r13!,{r11,r12}
+	mov     r11,#2
+	b       save_regs
+
+	.globl	_arm_abort_prefetch
+_arm_abort_prefetch:
+	@ store r12 for Xdump_buffer pointer, r11 for index
+	stmfd   r13!,{r11,r12}
+	mov     r11,#3
+	b       save_regs
+
+	.globl	_arm_abort_data
+_arm_abort_data:
+	@ store r12 for Xdump_buffer pointer, r11 for index
+	stmfd   r13!,{r11,r12}
+	mov     r11,#4
+	b       save_regs
+
+	.globl	_arm_reserved
+_arm_reserved:
+	ldr	r13,=_Except_Stack_SP	@ mode unknown
+	@ store r12 for Xdump_buffer pointer, r11 for index
+	stmfd   r13!,{r11,r12}
+	mov     r11,#5
+	b       save_regs
+
+save_regs:
+        ldr     r12,=xdump_buffer
+        str     r14,[r12,#4*15] @ save r14_abt (original PC) into r15 slot
+
+        stmia   r12,{r0-r10}    @ save unbanked registers (except r11 and r12)
+        ldmfd   r13!,{r0,r1}    @ get original r11 and r12
+        str     r0,[r12,#4*11]  @ save original r11
+        str     r1,[r12,#4*12]  @ save original r12
+        mrs     r0,spsr         @ get original psr
+        str     r0,[r12,#4*16]  @ save original cpsr
+
+        mrs     r1,cpsr         @ save mode psr
+        bic     r2,r1,#0x1f     @ psr with mode bits cleared
+        and     r0,r0,#0x1f     @ get original mode bits
+        add     r0,r0,r2
+
+        msr     cpsr,r0		@ move to pre-exception mode
+        str     r13,[r12,#4*13] @ save original SP
+        str     r14,[r12,#4*14] @ save original LR
+        msr     cpsr,r1 	@ restore mode psr
+
+        @ r11 has original index
+        orr     r10,r11,#0xDE<<24 @ r10 = 0xDEAD0000 + index of vector taken
+        orr     r10,r10,#0xAD<<16
+        str     r10,[r12,#4*17] @ save magic + index
+
+        mov     r0,r11          @ put index into 1st argument
+        b       dar_exception
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/system/main/gcc/irq_twiddle.S	Fri Jul 20 06:46:56 2018 +0000
@@ -0,0 +1,26 @@
+/*
+ * TI's L1 code (and possibly other parts of the software suite) calls
+ * functions named INT_DisableIRQ() and INT_EnableIRQ(); in TI's original
+ * fw they are implemented (in a very ugly manner, as usual) in the
+ * int.s entry point assembly module.  Here we implement the same
+ * functions in a cleaner way.
+ */
+
+#include "asm_defs.h"
+
+	.code 32
+	.text
+
+	.globl	INT_DisableIRQ
+INT_DisableIRQ:
+	mrs	r0, CPSR
+	orr	r0, r0, #LOCKOUT
+	msr	CPSR, r0
+	bx	lr
+
+	.globl	INT_EnableIRQ
+INT_EnableIRQ:
+	mrs	r0, CPSR
+	bic	r0, r0, #LOCKOUT
+	msr	CPSR, r0
+	bx	lr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/system/main/gcc/irqfiq.S	Fri Jul 20 06:46:56 2018 +0000
@@ -0,0 +1,73 @@
+/*
+ * This module contains the assembly shells for IRQ and FIQ, separated
+ * from the architectured vectors only by some simple unconditional
+ * branch instructions.
+ *
+ * Note that TI's way of handling interrupts sacrifices Nucleus' ability
+ * to nest interrupts and minimize the IRQ-disabled window: if my (Falcon's)
+ * understanding is correct, TI's code leaves all further IRQs disabled
+ * for the full execution duration of an IRQ handler.  (IRQ handlers are
+ * really LISRs, but TI's GSM fw does not use Nucleus' LISR framework.)
+ */
+
+	.text
+	.code	32
+
+	.globl	_INT_IRQ
+_INT_IRQ:
+        STMDB   sp!,{r0-r4}                 @ used to be a1-a4
+
+/*
+ * Thanks to TI for discovering and documenting this apparent ARM7TDMI bug:
+
+BUG correction 1st part -------------------
+It looks like there is an issue with ARM7 IRQ masking in the CPSR register
+which leads to crashes in Nucleus+ scheduler.
+Basically the code below  (correct as LOCKOUT = 0xC0) is used in many places by N+ but do not 
+prevent from having an interrupt after the execution of the third line (I mean execution, not 
+fetch).
+        MRS     a1,CPSR                     ; Pickup current CPSR
+        ORR     a1,a1,#LOCKOUT              ; Build interrupt lockout value
+        MSR     CPSR,a1                     ; Lockout interrupts
+       * IRQ INTERRUPT ! *
+       Next instructions...
+
+SW workaround:
+When a task is interrupted at this point an interrupted context is stored on its task and will 
+be resumed later on at the next instruction but to make a long story short it leads to some 
+problem as the OS does not expect to be interrupted there.
+Further testing tends to show that the CPSR *seems* to be loaded with the proper masking value 
+but that the IRQ is still triggered (has been hardwarewise requested during the instruction 
+exectution by the ARM7 core?)
+*/
+
+        MRS     a1,spsr                     @ check for the IRQ bug:
+        TST     a1,#0x80                    @ if the I - flag is set,
+        BNE     IRQBUG                      @ then postpone execution of this IRQ
+/* Bug correction 1st part end --------------- */
+
+        SUB     r4,lr,#4                    @ Save IRQ's lr (return address)
+        BL      TCT_Interrupt_Context_Save  @ Call context save routine
+
+        BL      IQ_IRQ_isr			@ Call  int. service routine
+
+     /* IRQ interrupt processing is complete.  Restore context- Never 
+        returns!  */
+        B       TCT_Interrupt_Context_Restore
+
+/* BUG correction 2nd part  ------------------ */
+IRQBUG: LDMFD  sp!,{r0-r4}                  @ return from interrupt
+        SUBS   pc,r14,#4
+/* BUG correction 2nd part end  -------------- */
+
+	.globl	_INT_FIQ
+_INT_FIQ:
+        STMDB   sp!,{r0-r4}                 @ used to be a1-a4
+        SUB     r4,lr,#4                    @ Save FIQ's lr (return address)
+        BL      TCT_Interrupt_Context_Save  @ Call context save routine
+
+        BL      IQ_FIQ_isr                  @ Call the FIQ ISR
+
+     /* FIQ interrupt processing is complete.  Restore context- Never 
+        returns!  */
+        B       TCT_Interrupt_Context_Restore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/system/main/gcc/ramvecs.S	Fri Jul 20 06:46:56 2018 +0000
@@ -0,0 +1,8 @@
+/*
+ * This assembly module provides the IRAM vectors
+ * to which the internal ROM is going to branch.
+ */
+
+	.section	.ramvecs,"ax",%progbits
+	.code	32
+#include "vectors.S"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/system/main/gcc/vectors.S	Fri Jul 20 06:46:56 2018 +0000
@@ -0,0 +1,14 @@
+/*
+ * These 7 branch instructions, corresponding to ARM exception and interrupt
+ * vectors, will be placed in different sections depending on the flashImage
+ * vs. ramImage configuration and which target we build for; this little
+ * snippet file will be #included where it is needed.
+ */
+
+	b	_arm_undefined
+	b	_arm_swi
+	b	_arm_abort_prefetch
+	b	_arm_abort_data
+	b	_arm_reserved
+	b	_INT_IRQ
+	b	_INT_FIQ