You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/05/11 18:07:58 UTC
[incubator-nuttx] branch master updated: tlsr82/tc32: optimize the irq process
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new c39d3fa9e4 tlsr82/tc32: optimize the irq process
c39d3fa9e4 is described below
commit c39d3fa9e48246d0b2385df1585f60d86068f076
Author: wangbowen6 <wa...@xiaomi.com>
AuthorDate: Wed May 11 20:23:23 2022 +0800
tlsr82/tc32: optimize the irq process
1. using armv6-m arm_irq();
2. simplify the interrupt number get process;
3. To improve the performance, move common exception code to ram_code.
Signed-off-by: wangbowen6 <wa...@xiaomi.com>
---
arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S | 170 +--------------
arch/arm/src/tlsr82/tc32/Make.defs | 5 +-
arch/arm/src/tlsr82/tc32/tc32_doirq.c | 164 ++-------------
arch/arm/src/tlsr82/tc32/tc32_exception.S | 231 +++++++++++++++++++++
4 files changed, 253 insertions(+), 317 deletions(-)
diff --git a/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S
index 50656a388f..6a676565bb 100644
--- a/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S
+++ b/arch/arm/src/tlsr82/chip/b87/boot/cstartup_flash.S
@@ -68,11 +68,9 @@
.global __LOAD_DUT
.global __LOAD_FLASH
- .extern g_current_regs
-
__start: @ MUST, referenced by boot.link
- .extern irq_handler
+ .extern tc32_exception
.extern firmwareVersion
@@ -388,176 +386,20 @@ IDLE_STACK:
@ src code for the irq proc part .
__irq:
- /* Save R0 ~ R3, these registers will be used */
+ /* Save R0 ~ R3, these registers will be used before saved */
tpush {r0}
tpush {r1}
tpush {r2}
tpush {r3}
- /* Switch to SVC mode to get the SVC mode SP, then save context
- * into the interrupted task stack.
- */
-
- /* Disable interrupt, because cpu will switch into SVC mode, interrupt
- * nested should be prevented, this is not supported by tc32
- * architecture.
- */
-
- tloadr r0, _REG_IRQ_EN @ disable irq
- tloadrb r1, [r0] @ get irq state in R1
- tmov r2, #0 @ disable irq
- tstorerb r2, [r0] @ disable irq
-
- /* Switch to SVC mode and get the LR and SP in SVC mode */
-
- tloadr r0, _REG_IRQ_EN + 4 @ switch to SVC mode
- tnop
- tmcsr r0 @ switch to SVC mode
- tnop
- tmov r2, r14 @ get SVC mode LR in R2
- tmov r3, r13 @ get SVC mode SP in R3
- tloadr r0, _REG_IRQ_EN + 8 @ return to IRQ mode
- tnop
- tmcsr r0 @ return to IRQ mode
- tnop
-
- /* R0 = the interrupted task SP after context save */
-
- tmov r0, #XCPTCONTEXT_SIZE
- tsub r0, r3, r0
-
- /* Save IRQ_STATE, SVC mode SP and SVC mode LR as PC */
-
- tstorer r1, [r0, #(4 * REG_IRQ_EN)]
- tstorer r3, [r0, #(4 * REG_SP)]
- tstorer r2, [r0, #(4 * REG_PC)]
-
- /* Get SPSR and save as CPSR */
-
- tmrss r1
- tstorer r1, [r0, #(4 * REG_CPSR)]
-
- /* Save IRQ mode LR as LR */
-
- tmov r1, r14
- tstorer r1, [r0, #(4 * REG_LR)]
-
- /* Pop the saved R1 ~ R3 (pushed in beginning of irq),
- * then save R1 ~ R7.
- */
-
- tpop {r3}
- tpop {r2}
- tpop {r1}
- tstorer r1, [r0, #(4 * REG_R1)]
- tstorer r2, [r0, #(4 * REG_R2)]
- tstorer r3, [r0, #(4 * REG_R3)]
- tstorer r4, [r0, #(4 * REG_R4)]
- tstorer r5, [r0, #(4 * REG_R5)]
- tstorer r6, [r0, #(4 * REG_R6)]
- tstorer r7, [r0, #(4 * REG_R7)]
-
- /* Pop R0 and save it */
-
- tpop {r1}
- tstorer r1, [r0, #(4 * REG_R0)]
-
- /* Save R8 ~ R12 */
-
- tmov r1, r8
- tstorer r1, [r0, #(4 * REG_R8)]
- tmov r1, r9
- tstorer r1, [r0, #(4 * REG_R9)]
- tmov r1, r10
- tstorer r1, [r0, #(4 * REG_R10)]
- tmov r1, r11
- tstorer r1, [r0, #(4 * REG_R11)]
- tmov r1, r12
- tstorer r1, [r0, #(4 * REG_R12)]
-
- /* R0 = interrupted task SP after the context save */
-
- tjl irq_handler
-
- /* R0 = interrupted task SP after the context save (no context switch)
- * = next task tcb->regs (with context switch)
- * Restore all the register according to R0
- */
-
- /* Dsiable interrupt to protect the SVC mode */
-
- tloadr r2, _REG_IRQ_EN @ disable irq
- tmov r3, #0 @ disable irq
- tstorerb r3, [r2] @ disable irq
-
- /* Restore SVC mode SP (R13), SVC mode LR (R14, based saved PC)
- * PC is not need to retore */
-
- tloadr r2, [r0, #(4 * REG_SP)]
- tloadr r3, [r0, #(4 * REG_PC)]
-
- tloadr r1, _REG_IRQ_EN + 4 @ switch to SVC mode
- tnop
- tmcsr r1 @ switch to SVC mode
- tnop
- tmov r14, r3 @ restore SVC mode LR
- tmov r13, r2 @ restore SVC mode SP
- tloadr r1, _REG_IRQ_EN + 8 @ return to IRQ mode
- tnop
- tmcsr r1 @ return to IRQ mode
- tnop
-
- /* Restore CPSR to SPSR, IRQ_STATE */
-
- tloadr r2, [r0, #(4 * REG_CPSR)]
- tloadr r3, [r0, #(4 * REG_IRQ_EN)]
-
- tmssr r2 @ restore CPSR to SPSR
-
- tloadr r1, _REG_IRQ_EN @ restore IRQ enable flag
- tstorerb r3, [r1] @ restore IRQ enable flag
-
- /* Restore R8 ~ R12, IRQ mode LR */
-
- tloadr r2, [r0, #(4 * REG_R8)]
- tloadr r3, [r0, #(4 * REG_R9)]
- tloadr r4, [r0, #(4 * REG_R10)]
- tloadr r5, [r0, #(4 * REG_R11)]
- tloadr r6, [r0, #(4 * REG_R12)]
- tloadr r7, [r0, #(4 * REG_LR)]
-
- tmov r8, r2
- tmov r9, r3
- tmov r10, r4
- tmov r11, r5
- tmov r12, r6
- tmov r14, r7
-
- /* Restore R1 ~ R7 */
-
- tloadr r1, [r0, #(4 * REG_R1)]
- tloadr r2, [r0, #(4 * REG_R2)]
- tloadr r3, [r0, #(4 * REG_R3)]
- tloadr r4, [r0, #(4 * REG_R4)]
- tloadr r5, [r0, #(4 * REG_R5)]
- tloadr r6, [r0, #(4 * REG_R6)]
- tloadr r7, [r0, #(4 * REG_R7)]
-
- /* Restore R0 */
-
- tloadr r0, [r0, #(4 * REG_R0)]
-
- /* Return to interrupted task or next task */
+ /* Save LR, LR will change after tjl instruction */
tpush {r14}
- treti {r15}
- .align 4
-_REG_IRQ_EN:
- .word 0x00800643
- .word 0x00000093
- .word 0x00000092
+ /* Call tc32_exception */
+
+ tjl tc32_exception
ASMEND:
.section .bss
diff --git a/arch/arm/src/tlsr82/tc32/Make.defs b/arch/arm/src/tlsr82/tc32/Make.defs
index 5efb136860..bd0cc3c84a 100644
--- a/arch/arm/src/tlsr82/tc32/Make.defs
+++ b/arch/arm/src/tlsr82/tc32/Make.defs
@@ -42,11 +42,12 @@ CMN_CSRCS := $(filter-out $(TC32_CSRCS_FILTER), $(CMN_CSRCS))
# Common files in arch/arm/src/armv6-m
-CMN_CSRCS += arm_sigdeliver.c
+CMN_CSRCS += arm_sigdeliver.c arm_doirq.c
# Common files in arch/arm/src/tlsr82/tc32
-CMN_ASRCS += tc32_fullcontextrestore.S tc32_switchcontext.S tc32_saveusercontext.S
+CMN_ASRCS += tc32_fullcontextrestore.S tc32_switchcontext.S
+CMN_ASRCS += tc32_saveusercontext.S tc32_exception.S
CMN_CSRCS += tc32_doirq.c tc32_initialstate.c tc32_schedulesigaction.c
CMN_CSRCS += tc32_syscall.c tc32_udelay.c
diff --git a/arch/arm/src/tlsr82/tc32/tc32_doirq.c b/arch/arm/src/tlsr82/tc32/tc32_doirq.c
index bbe178da8c..e217eb9041 100644
--- a/arch/arm/src/tlsr82/tc32/tc32_doirq.c
+++ b/arch/arm/src/tlsr82/tc32/tc32_doirq.c
@@ -37,8 +37,6 @@
#include "arm_internal.h"
-#include "group/group.h"
-
#include "hardware/tlsr82_irq.h"
/****************************************************************************
@@ -53,75 +51,10 @@
* Private Data
****************************************************************************/
-static const uint8_t tc32_lowbit_bitmap[] =
-{
- 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 00 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 10 */
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 20 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 30 */
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 40 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 50 */
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 60 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 70 */
- 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 80 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 90 */
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* A0 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* B0 */
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* C0 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* D0 */
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* E0 */
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* F0 */
-};
-
/****************************************************************************
* Private Functions
****************************************************************************/
-/****************************************************************************
- * Name: tc32_ffs
- *
- * Description:
- * This function finds the first bit set (beginning with the least
- * significant bit) in value and return the index of that bit.
- * TC32 archtecture does not support clz instruction.
- *
- * Parameters:
- * uint32_t - value
- *
- * Return Value:
- * [1, 32] - On Success.
- * 0 - No set bit in value (value = 0).
- *
- ****************************************************************************/
-
-static inline int locate_code(".ram_code") tc32_ffs(uint32_t value)
-{
- int ret;
-
- if (value == 0)
- {
- ret = 0;
- }
- else if (value & 0xff)
- {
- ret = (int)tc32_lowbit_bitmap[value & 0xff] + 1;
- }
- else if (value & 0xff00)
- {
- ret = (int)tc32_lowbit_bitmap[(value & 0xff00) >> 8] + 9;
- }
- else if (value & 0xff0000)
- {
- ret = (int)tc32_lowbit_bitmap[(value & 0xff0000) >> 16] + 17;
- }
- else
- {
- ret = (int)tc32_lowbit_bitmap[(value & 0xff000000) >> 24] + 25;
- }
-
- return ret;
-}
-
/****************************************************************************
* Name: tc32_getirq
*
@@ -141,22 +74,17 @@ static inline int locate_code(".ram_code") tc32_ffs(uint32_t value)
static int locate_code(".ram_code") tc32_getirq(void)
{
int irq;
+ uint32_t value;
- /* Only detect the enable interrupt */
-
- irq = tc32_ffs(IRQ_SRC_REG & IRQ_MASK_REG);
+ value = IRQ_SRC_REG & IRQ_MASK_REG;
- if (irq > 0 && irq <= NR_IRQS)
+ if (value == 0)
{
- /* Minus one to obatin the correct irq number */
-
- irq = irq - 1;
+ irq = NR_IRQS;
}
else
{
- /* Invalid irq number */
-
- irq = NR_IRQS;
+ irq = __builtin_ctz(value);
}
return irq;
@@ -166,82 +94,16 @@ static int locate_code(".ram_code") tc32_getirq(void)
* Public Functions
****************************************************************************/
-/**
- * @brief This function serves to handle the interrupt of MCU
- * @param[in] none
- * @return none
- */
+/****************************************************************************
+ * Name: arm_ack_irq
+ *
+ * Description:
+ * Acknowledge the IRQ
+ *
+ ****************************************************************************/
-uint32_t *arm_doirq(int irq, uint32_t *regs)
+void arm_ack_irq(int irq)
{
- board_autoled_on(LED_INIRQ);
-#ifdef CONFIG_SUPPRESS_INTERRUPTS
- PANIC();
-#else
- /* Current regs non-zero indicates that we are processing an interrupt;
- * g_current_regs is also used to manage interrupt level context switches.
- *
- * Nested interrupts are not supported
- */
-
- DEBUGASSERT(CURRENT_REGS == NULL);
- CURRENT_REGS = regs;
-
- /* Disable further occurrences of this interrupt (until the interrupt
- * sources have been clear by the driver).
- */
-
- /* Deliver the IRQ */
-
- irq_dispatch(irq, regs);
-
-#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
- /* Check for a context switch. If a context switch occurred, then
- * g_current_regs will have a different value than it did on entry. If an
- * interrupt level context switch has occurred, then restore the floating
- * point state and the establish the correct address environment before
- * returning from the interrupt.
- */
-
- if (regs != CURRENT_REGS)
- {
-#ifdef CONFIG_ARCH_FPU
- /* Restore floating point registers */
-
- riscv_restorefpu(CURRENT_REGS);
-#endif
-
-#ifdef CONFIG_ARCH_ADDRENV
- /* Make sure that the address environment for the previously
- * running task is closed down gracefully (data caches dump,
- * MMU flushed) and set up the address environment for the new
- * thread at the head of the ready-to-run list.
- */
-
- group_addrenv(NULL);
-#endif
- }
-#endif
-
- /* If a context switch occurred while processing the interrupt then
- * g_current_regs may have change value. If we return any value different
- * from the input regs, then the lower level will know that a context
- * switch occurred during interrupt processing.
- */
-
- regs = (uint32_t *)CURRENT_REGS;
-
- /* Set g_current_regs to NULL to indicate that we are no longer in an
- * interrupt handler.
- */
-
- CURRENT_REGS = NULL;
-
- /* Unmask the last interrupt (global interrupts are still disabled) */
-
-#endif
- board_autoled_off(LED_INIRQ);
- return regs;
}
/****************************************************************************
diff --git a/arch/arm/src/tlsr82/tc32/tc32_exception.S b/arch/arm/src/tlsr82/tc32/tc32_exception.S
new file mode 100644
index 0000000000..1c5249f9d4
--- /dev/null
+++ b/arch/arm/src/tlsr82/tc32/tc32_exception.S
@@ -0,0 +1,231 @@
+/****************************************************************************
+ * arch/arm/src/tlsr82/tc32/tc32_exception.S
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <arch/chip/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+ .file "tc32_exception.S"
+
+/****************************************************************************
+ * Macros
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: tc32_exception
+ *
+ * Description:
+ * TC32 Common exception
+ *
+ ****************************************************************************/
+
+ .align 2
+ .code 16
+ .thumb_func
+ .section .ram_code,"ax"
+ .extern irq_handler
+ .global tc32_exception
+ .type tc32_exception, function
+tc32_exception:
+
+ /* Restore the R14 (LR) saved in __irq */
+
+ tpop {r3}
+ tmov r14, r3
+
+ /* Switch to SVC mode to get the SVC mode SP, then save context
+ * into the interrupted task stack.
+ */
+
+ /* Disable interrupt, because cpu will switch into SVC mode, interrupt
+ * nested should be prevented, this is not supported by tc32
+ * architecture.
+ */
+
+ tloadr r0, _REG_IRQ_EN /* disable irq */
+ tloadrb r1, [r0] /* get irq state in R1 */
+ tmov r2, #0 /* disable irq */
+ tstorerb r2, [r0] /* disable irq */
+
+ /* Switch to SVC mode and get the LR and SP in SVC mode */
+
+ tloadr r0, _REG_IRQ_EN + 4 /* switch to SVC mode */
+ tnop
+ tmcsr r0 /* switch to SVC mode */
+ tnop
+ tmov r2, r14 /* get SVC mode LR in R2 */
+ tmov r3, r13 /* get SVC mode SP in R3 */
+ tloadr r0, _REG_IRQ_EN + 8 /* return to IRQ mode */
+ tnop
+ tmcsr r0 /* return to IRQ mode */
+ tnop
+
+ /* R0 = the interrupted task SP after context save */
+
+ tmov r0, #XCPTCONTEXT_SIZE
+ tsub r0, r3, r0
+
+ /* Save IRQ_STATE, SVC mode SP and SVC mode LR as PC */
+
+ tstorer r1, [r0, #(4 * REG_IRQ_EN)]
+ tstorer r3, [r0, #(4 * REG_SP)]
+ tstorer r2, [r0, #(4 * REG_PC)]
+
+ /* Get SPSR and save as CPSR */
+
+ tmrss r1
+ tstorer r1, [r0, #(4 * REG_CPSR)]
+
+ /* Save IRQ mode LR as LR */
+
+ tmov r1, r14
+ tstorer r1, [r0, #(4 * REG_LR)]
+
+ /* Pop the saved R1 ~ R3 (pushed in beginning of irq),
+ * then save R1 ~ R7.
+ */
+
+ tpop {r3}
+ tpop {r2}
+ tpop {r1}
+ tstorer r1, [r0, #(4 * REG_R1)]
+ tstorer r2, [r0, #(4 * REG_R2)]
+ tstorer r3, [r0, #(4 * REG_R3)]
+ tstorer r4, [r0, #(4 * REG_R4)]
+ tstorer r5, [r0, #(4 * REG_R5)]
+ tstorer r6, [r0, #(4 * REG_R6)]
+ tstorer r7, [r0, #(4 * REG_R7)]
+
+ /* Pop R0 and save it */
+
+ tpop {r1}
+ tstorer r1, [r0, #(4 * REG_R0)]
+
+ /* Save R8 ~ R12 */
+
+ tmov r1, r8
+ tstorer r1, [r0, #(4 * REG_R8)]
+ tmov r1, r9
+ tstorer r1, [r0, #(4 * REG_R9)]
+ tmov r1, r10
+ tstorer r1, [r0, #(4 * REG_R10)]
+ tmov r1, r11
+ tstorer r1, [r0, #(4 * REG_R11)]
+ tmov r1, r12
+ tstorer r1, [r0, #(4 * REG_R12)]
+
+ /* R0 = interrupted task SP after the context save */
+
+ tjl irq_handler
+
+ /* R0 = interrupted task SP after the context save (no context switch)
+ * = next task tcb->regs (with context switch)
+ * Restore all the register according to R0
+ */
+
+ /* Dsiable interrupt to protect the SVC mode */
+
+ tloadr r2, _REG_IRQ_EN /* disable irq */
+ tmov r3, #0 /* disable irq */
+ tstorerb r3, [r2] /* disable irq */
+
+ /* Restore SVC mode SP (R13), SVC mode LR (R14, based saved PC)
+ * PC is not need to retore */
+
+ tloadr r2, [r0, #(4 * REG_SP)]
+ tloadr r3, [r0, #(4 * REG_PC)]
+
+ tloadr r1, _REG_IRQ_EN + 4 /* switch to SVC mode */
+ tnop
+ tmcsr r1 /* switch to SVC mode */
+ tnop
+ tmov r14, r3 /* restore SVC mode LR */
+ tmov r13, r2 /* restore SVC mode SP */
+ tloadr r1, _REG_IRQ_EN + 8 /* return to IRQ mode */
+ tnop
+ tmcsr r1 /* return to IRQ mode */
+ tnop
+
+ /* Restore CPSR to SPSR, IRQ_STATE */
+
+ tloadr r2, [r0, #(4 * REG_CPSR)]
+ tloadr r3, [r0, #(4 * REG_IRQ_EN)]
+
+ tmssr r2 /* restore CPSR to SPSR */
+
+ tloadr r1, _REG_IRQ_EN /* restore IRQ enable flag */
+ tstorerb r3, [r1] /* restore IRQ enable flag */
+
+ /* Restore R8 ~ R12, IRQ mode LR */
+
+ tloadr r2, [r0, #(4 * REG_R8)]
+ tloadr r3, [r0, #(4 * REG_R9)]
+ tloadr r4, [r0, #(4 * REG_R10)]
+ tloadr r5, [r0, #(4 * REG_R11)]
+ tloadr r6, [r0, #(4 * REG_R12)]
+ tloadr r7, [r0, #(4 * REG_LR)]
+
+ tmov r8, r2
+ tmov r9, r3
+ tmov r10, r4
+ tmov r11, r5
+ tmov r12, r6
+ tmov r14, r7
+
+ /* Restore R1 ~ R7 */
+
+ tloadr r1, [r0, #(4 * REG_R1)]
+ tloadr r2, [r0, #(4 * REG_R2)]
+ tloadr r3, [r0, #(4 * REG_R3)]
+ tloadr r4, [r0, #(4 * REG_R4)]
+ tloadr r5, [r0, #(4 * REG_R5)]
+ tloadr r6, [r0, #(4 * REG_R6)]
+ tloadr r7, [r0, #(4 * REG_R7)]
+
+ /* Restore R0 */
+
+ tloadr r0, [r0, #(4 * REG_R0)]
+
+ /* Return to interrupted task or next task */
+
+ tpush {r14}
+ treti {r15}
+
+ .align 4
+_REG_IRQ_EN:
+ .word 0x00800643
+ .word 0x00000093
+ .word 0x00000092
+ .size tc32_exception, .-tc32_exception
+ .end