Merge branch 'staging/improve_riscv_vector_s_file' into 'master'

RISC-V: Fix vectors.S assembly file indentation and macro usage

See merge request espressif/esp-idf!15927
This commit is contained in:
Zim Kalinowski
2021-11-18 00:50:35 +00:00

View File

@@ -1,16 +1,9 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/interrupt_reg.h" #include "soc/interrupt_reg.h"
#include "riscv/rvruntime-frames.h" #include "riscv/rvruntime-frames.h"
@@ -18,285 +11,274 @@
#include "sdkconfig.h" #include "sdkconfig.h"
.equ SAVE_REGS, 32 .equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4) .equ CONTEXT_SIZE, (SAVE_REGS * 4)
.equ panic_from_exception, xt_unhandled_exception .equ panic_from_exception, xt_unhandled_exception
.equ panic_from_isr, panicHandler .equ panic_from_isr, panicHandler
.macro save_regs /* Macro which first allocates space on the stack to save general
addi sp, sp, -CONTEXT_SIZE * purpose registers, and then save them. GP register is excluded.
sw ra, RV_STK_RA(sp) * The default size allocated on the stack is CONTEXT_SIZE, but it
sw tp, RV_STK_TP(sp) * can be overridden. */
sw t0, RV_STK_T0(sp) .macro save_general_regs cxt_size=CONTEXT_SIZE
sw t1, RV_STK_T1(sp) addi sp, sp, -\cxt_size
sw t2, RV_STK_T2(sp) sw ra, RV_STK_RA(sp)
sw s0, RV_STK_S0(sp) sw tp, RV_STK_TP(sp)
sw s1, RV_STK_S1(sp) sw t0, RV_STK_T0(sp)
sw a0, RV_STK_A0(sp) sw t1, RV_STK_T1(sp)
sw a1, RV_STK_A1(sp) sw t2, RV_STK_T2(sp)
sw a2, RV_STK_A2(sp) sw s0, RV_STK_S0(sp)
sw a3, RV_STK_A3(sp) sw s1, RV_STK_S1(sp)
sw a4, RV_STK_A4(sp) sw a0, RV_STK_A0(sp)
sw a5, RV_STK_A5(sp) sw a1, RV_STK_A1(sp)
sw a6, RV_STK_A6(sp) sw a2, RV_STK_A2(sp)
sw a7, RV_STK_A7(sp) sw a3, RV_STK_A3(sp)
sw s2, RV_STK_S2(sp) sw a4, RV_STK_A4(sp)
sw s3, RV_STK_S3(sp) sw a5, RV_STK_A5(sp)
sw s4, RV_STK_S4(sp) sw a6, RV_STK_A6(sp)
sw s5, RV_STK_S5(sp) sw a7, RV_STK_A7(sp)
sw s6, RV_STK_S6(sp) sw s2, RV_STK_S2(sp)
sw s7, RV_STK_S7(sp) sw s3, RV_STK_S3(sp)
sw s8, RV_STK_S8(sp) sw s4, RV_STK_S4(sp)
sw s9, RV_STK_S9(sp) sw s5, RV_STK_S5(sp)
sw s10, RV_STK_S10(sp) sw s6, RV_STK_S6(sp)
sw s11, RV_STK_S11(sp) sw s7, RV_STK_S7(sp)
sw t3, RV_STK_T3(sp) sw s8, RV_STK_S8(sp)
sw t4, RV_STK_T4(sp) sw s9, RV_STK_S9(sp)
sw t5, RV_STK_T5(sp) sw s10, RV_STK_S10(sp)
sw t6, RV_STK_T6(sp) sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm .endm
.macro save_mepc .macro save_mepc
csrr t0, mepc csrr t0, mepc
sw t0, RV_STK_MEPC(sp) sw t0, RV_STK_MEPC(sp)
.endm .endm
.macro restore_regs /* Restore the general purpose registers (excluding gp) from the context on
lw ra, RV_STK_RA(sp) * the stack. The context is then deallocated. The default size is CONTEXT_SIZE
lw tp, RV_STK_TP(sp) * but it can be overriden. */
lw t0, RV_STK_T0(sp) .macro restore_general_regs cxt_size=CONTEXT_SIZE
lw t1, RV_STK_T1(sp) lw ra, RV_STK_RA(sp)
lw t2, RV_STK_T2(sp) lw tp, RV_STK_TP(sp)
lw s0, RV_STK_S0(sp) lw t0, RV_STK_T0(sp)
lw s1, RV_STK_S1(sp) lw t1, RV_STK_T1(sp)
lw a0, RV_STK_A0(sp) lw t2, RV_STK_T2(sp)
lw a1, RV_STK_A1(sp) lw s0, RV_STK_S0(sp)
lw a2, RV_STK_A2(sp) lw s1, RV_STK_S1(sp)
lw a3, RV_STK_A3(sp) lw a0, RV_STK_A0(sp)
lw a4, RV_STK_A4(sp) lw a1, RV_STK_A1(sp)
lw a5, RV_STK_A5(sp) lw a2, RV_STK_A2(sp)
lw a6, RV_STK_A6(sp) lw a3, RV_STK_A3(sp)
lw a7, RV_STK_A7(sp) lw a4, RV_STK_A4(sp)
lw s2, RV_STK_S2(sp) lw a5, RV_STK_A5(sp)
lw s3, RV_STK_S3(sp) lw a6, RV_STK_A6(sp)
lw s4, RV_STK_S4(sp) lw a7, RV_STK_A7(sp)
lw s5, RV_STK_S5(sp) lw s2, RV_STK_S2(sp)
lw s6, RV_STK_S6(sp) lw s3, RV_STK_S3(sp)
lw s7, RV_STK_S7(sp) lw s4, RV_STK_S4(sp)
lw s8, RV_STK_S8(sp) lw s5, RV_STK_S5(sp)
lw s9, RV_STK_S9(sp) lw s6, RV_STK_S6(sp)
lw s10, RV_STK_S10(sp) lw s7, RV_STK_S7(sp)
lw s11, RV_STK_S11(sp) lw s8, RV_STK_S8(sp)
lw t3, RV_STK_T3(sp) lw s9, RV_STK_S9(sp)
lw t4, RV_STK_T4(sp) lw s10, RV_STK_S10(sp)
lw t5, RV_STK_T5(sp) lw s11, RV_STK_S11(sp)
lw t6, RV_STK_T6(sp) lw t3, RV_STK_T3(sp)
addi sp, sp, CONTEXT_SIZE lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp,sp, \cxt_size
.endm .endm
.macro restore_mepc .macro restore_mepc
lw t0, RV_STK_MEPC(sp) lw t0, RV_STK_MEPC(sp)
csrw mepc, t0 csrw mepc, t0
.endm .endm
.global rtos_int_enter .global rtos_int_enter
.global rtos_int_exit .global rtos_int_exit
.global _global_interrupt_handler .global _global_interrupt_handler
.section .exception_vectors.text .section .exception_vectors.text
/* This is the vector table. MTVEC points here. /* This is the vector table. MTVEC points here.
* *
* Use 4-byte intructions here. 1 instruction = 1 entry of the table. * Use 4-byte intructions here. 1 instruction = 1 entry of the table.
* The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception,
* and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt.
* *
* Note: for our CPU, we need to place this on a 256-byte boundary, as CPU * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU
* only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00).
*/ */
.balign 0x100 .balign 0x100
.global _vector_table .global _vector_table
.type _vector_table, @function .type _vector_table, @function
_vector_table: _vector_table:
.option push .option push
.option norvc .option norvc
j _panic_handler /* exception handler, entry 0 */ j _panic_handler /* exception handler, entry 0 */
.rept (ETS_T1_WDT_INUM - 1) .rept (ETS_T1_WDT_INUM - 1)
j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */ j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */
.endr .endr
j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/ j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/
j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/ j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE #ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
j _panic_handler /* Call panic handler for ETS_MEMPROT_ERR_INUM interrupt (soc-level panic)*/ j _panic_handler /* Call panic handler for ETS_MEMPROT_ERR_INUM interrupt (soc-level panic)*/
.rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM) .rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM)
#else #else
.rept (ETS_MAX_INUM - ETS_CACHEERR_INUM) .rept (ETS_MAX_INUM - ETS_CACHEERR_INUM)
#endif #endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */ j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */
.endr .endr
.option pop .option pop
.size _vector_table, .-_vector_table .size _vector_table, .-_vector_table
/* Exception handler.*/ /* Exception handler.*/
.type _panic_handler, @function .type _panic_handler, @function
_panic_handler: _panic_handler:
addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */ /* Allocate space on the stack and store general purpose registers */
/* save general registers */ save_general_regs RV_STK_FRMSZ
sw ra, RV_STK_RA(sp)
sw gp, RV_STK_GP(sp)
sw tp, RV_STK_TP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp)
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
sw t0, RV_STK_SP(sp)
csrr t0, mepc
sw t0, RV_STK_MEPC(sp)
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
/* Call panic_from_exception(sp) or panic_from_isr(sp) /* As gp register is not saved by the macro, save it here */
* depending on whether we have a pseudo excause or not. sw gp, RV_STK_GP(sp)
* If mcause's highest bit is 1, then an interrupt called this routine,
* so we have a pseudo excause. Else, it is due to a exception, we don't /* Same goes for the SP value before trapping */
* have an pseudo excause */ addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
mv a0, sp
csrr a1, mcause /* Save CSRs */
/* Branches instructions don't accept immediates values, so use t1 to sw t0, RV_STK_SP(sp)
* store our comparator */ csrr t0, mepc
li t0, 0x80000000 sw t0, RV_STK_MEPC(sp)
bgeu a1, t0, _call_panic_handler csrr t0, mstatus
sw a1, RV_STK_MCAUSE(sp) sw t0, RV_STK_MSTATUS(sp)
/* exception_from_panic never returns */ csrr t0, mtvec
j panic_from_exception sw t0, RV_STK_MTVEC(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
/* Call panic_from_exception(sp) or panic_from_isr(sp)
* depending on whether we have a pseudo excause or not.
* If mcause's highest bit is 1, then an interrupt called this routine,
* so we have a pseudo excause. Else, it is due to a exception, we don't
* have an pseudo excause */
mv a0, sp
csrr a1, mcause
/* Branches instructions don't accept immediates values, so use t1 to
* store our comparator */
li t0, 0x80000000
bgeu a1, t0, _call_panic_handler
sw a1, RV_STK_MCAUSE(sp)
/* exception_from_panic never returns */
j panic_from_exception
_call_panic_handler: _call_panic_handler:
/* Remove highest bit from mcause (a1) register and save it in the /* Remove highest bit from mcause (a1) register and save it in the
* structure */ * structure */
not t0, t0 not t0, t0
and a1, a1, t0 and a1, a1, t0
sw a1, RV_STK_MCAUSE(sp) sw a1, RV_STK_MCAUSE(sp)
/* exception_from_isr never returns */ /* exception_from_isr never returns */
j panic_from_isr j panic_from_isr
.size panic_from_isr, .-panic_from_isr .size panic_from_isr, .-panic_from_isr
/* This is the interrupt handler. /* This is the interrupt handler.
* It saves the registers on the stack, * It saves the registers on the stack,
* prepares for interrupt nesting, * prepares for interrupt nesting,
* re-enables the interrupts, * re-enables the interrupts,
* then jumps to the C dispatcher in interrupt.c. * then jumps to the C dispatcher in interrupt.c.
*/ */
.global _interrupt_handler .global _interrupt_handler
.type _interrupt_handler, @function .type _interrupt_handler, @function
_interrupt_handler: _interrupt_handler:
/* entry */ /* Start by saving the general purpose registers and the PC value before
save_regs * the interrupt happened. */
save_mepc save_general_regs
save_mepc
/* Before doing anythig preserve the stack pointer */ /* Before doing anythig preserve the stack pointer */
/* It will be saved in current TCB, if needed */ /* It will be saved in current TCB, if needed */
mv a0, sp mv a0, sp
call rtos_int_enter call rtos_int_enter
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
/* Before dispatch c handler, restore interrupt to enable nested intr */ /* Before dispatch c handler, restore interrupt to enable nested intr */
csrr s1, mcause csrr s1, mcause
csrr s2, mstatus csrr s2, mstatus
/* Save the interrupt threshold level */ /* Save the interrupt threshold level */
la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
lw s3, 0(t0) lw s3, 0(t0)
/* Increase interrupt threshold level */ /* Increase interrupt threshold level */
li t2, 0x7fffffff li t2, 0x7fffffff
and t1, s1, t2 /* t1 = mcause & mask */ and t1, s1, t2 /* t1 = mcause & mask */
slli t1, t1, 2 /* t1 = mcause * 4 */ slli t1, t1, 2 /* t1 = mcause * 4 */
la t2, INTC_INT_PRIO_REG(0) la t2, INTC_INT_PRIO_REG(0)
add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */
lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */
addi t2, t2, 1 /* t2 = t2 +1 */ addi t2, t2, 1 /* t2 = t2 +1 */
sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
fence fence
li t0, 0x8 li t0, 0x8
csrrs t0, mstatus, t0 csrrs t0, mstatus, t0
/* MIE set. Nested interrupts can now occur */
#ifdef CONFIG_PM_TRACE #ifdef CONFIG_PM_TRACE
li a0, 0 /* = ESP_PM_TRACE_IDLE */ li a0, 0 /* = ESP_PM_TRACE_IDLE */
#if SOC_CPU_CORES_NUM == 1 #if SOC_CPU_CORES_NUM == 1
li a1, 0 /* No need to check core ID on single core hardware */ li a1, 0 /* No need to check core ID on single core hardware */
#else #else
csrr a1, mhartid csrr a1, mhartid
#endif #endif
la t0, esp_pm_trace_exit la t0, esp_pm_trace_exit
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif #endif
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
la t0, esp_pm_impl_isr_hook la t0, esp_pm_impl_isr_hook
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif #endif
/* call the C dispatcher */ /* call the C dispatcher */
mv a0, sp /* argument 1, stack pointer */ mv a0, sp /* argument 1, stack pointer */
mv a1, s1 /* argument 2, interrupt number (mcause) */ mv a1, s1 /* argument 2, interrupt number (mcause) */
/* mask off the interrupt flag of mcause */ /* mask off the interrupt flag of mcause */
li t0, 0x7fffffff li t0, 0x7fffffff
and a1, a1, t0 and a1, a1, t0
jal _global_interrupt_handler jal _global_interrupt_handler
/* After dispatch c handler, disable interrupt to make freertos make context switch */ /* After dispatch c handler, disable interrupt to make freertos make context switch */
li t0, 0x8 li t0, 0x8
csrrc t0, mstatus, t0 csrrc t0, mstatus, t0
/* MIE cleared. Nested interrupts are disabled */
/* restore the interrupt threshold level */ /* restore the interrupt threshold level */
la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG
sw s3, 0(t0) sw s3, 0(t0)
fence fence
/* Yield to the next task is needed: */ /* Yield to the next task is needed: */
mv a0, sp mv a0, sp
call rtos_int_exit call rtos_int_exit
/* If this is a non-nested interrupt, context switch called, SP now points to back to task stack. */
/* The next (or current) stack pointer is returned in a0 */ /* The next (or current) stack pointer is returned in a0 */
mv sp, a0 mv sp, a0
/* restore the rest of the registers */ /* restore the rest of the registers */
csrw mcause, s1 csrw mcause, s1
csrw mstatus, s2 csrw mstatus, s2
restore_mepc restore_mepc
restore_regs restore_general_regs
/* exit, this will also re-enable the interrupts */ /* exit, this will also re-enable the interrupts */
mret mret
.size _interrupt_handler, .-_interrupt_handler .size _interrupt_handler, .-_interrupt_handler