Initial Esp32c3 Support (#5060)

This commit is contained in:
Me No Dev
2021-04-14 18:10:05 +03:00
committed by GitHub
parent 371f382db7
commit 404a31f445
1929 changed files with 382833 additions and 190 deletions

View File

@ -0,0 +1,27 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#pragma once
enum _panic_reasons {
PANIC_RSN_NONE = 0,
PANIC_RSN_INTWDT_CPU0,
#if SOC_CPU_NUM > 1
PANIC_RSN_INTWDT_CPU1,
#endif
PANIC_RSN_CACHEERR,
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
PANIC_RSN_MEMPROT,
#endif
PANIC_RSN_COUNT
} panic_reasons;

View File

@ -0,0 +1,136 @@
// Copyright (c) 2013, The Regents of the University of California (Regents).
// Copyright (c) 2018-2019, The libfemto authors
// Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD
// All Rights Reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Regents nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
// IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
// OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
// HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
// MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <sys/param.h>
#include "encoding.h"
/********************************************************
Physical Memory Protection (PMP) register fields
(privileged spec)
********************************************************/
/* Value of pmpcfg0 CSR. Note this macro is only needed for calculations like (CSR_PMPCFG0 + 1), which must
still be constant at compile time. Use the assembler name pmpcfg0, pmpcfg1, pmpcfg2, etc. in other cases */
#define CSR_PMPCFG0 0x3A0
/* Value of pmpaddr0 CSR. Note, as above, this macro is only needed for calculations and the assembler names
pmpaddr0, pmpaddr1, pmpaddr2, etc should be used otherwise. */
#define CSR_PMPADDR0 0x3B0
/* Generate the PMP address field value when PMPCFG.A == NAPOT
START & END should be calculated at compile time. The size of the region
(END-START) must be a power of 2 size, and START must be aligned to this
size.
Note: this value must be right-shifted PMP_SHIFT when written to the PMPADDR
register. The PMP_ENTRY_SET macro will do this.
*/
#define PMPADDR_NAPOT(START, END) ({ \
_Static_assert(__builtin_popcount((END)-(START)) == 1, "Size must be a power of 2"); \
_Static_assert((START) % ((END)-(START)) == 0, "Start must be aligned to size"); \
(((START)) | (((END)-(START)-1)>>1)); \
})
#define PMPADDR_ALL 0xFFFFFFFF
/* Set a PMP entry.
- ENTRY is number of the PMP entry to set. This must be a compile-time constant because it's used to
generate specific assembly instructions.
- ADDR is the address to write to the PMPADDRx register. Note this is the unshifted address.
- CFG is the configuration value to write to the correct CFG entry register. Note that
the macro only sets bits in the CFG register, so it sould be zeroed already.
*/
#define PMP_ENTRY_SET(ENTRY, ADDR, CFG) do { \
RV_WRITE_CSR((CSR_PMPADDR0) + (ENTRY), (ADDR) >> (PMP_SHIFT)); \
RV_SET_CSR((CSR_PMPCFG0) + (ENTRY)/4, ((CFG)&0xFF) << (ENTRY%4)*8); \
} while(0)
/********************************************************
Trigger Module register fields (Debug specification)
********************************************************/
/* tcontrol CSRs not recognized by toolchain currently */
#define CSR_TCONTROL 0x7a5
#define CSR_TDATA1 0x7a1
#define TCONTROL_MTE (1<<3) /*R/W, Current M mode trigger enable bit*/
#define TCONTROL_MPTE (1<<7) /*R/W, Previous M mode trigger enable bit*/
#define TDATA1_LOAD (1<<0) /*R/W,Fire trigger on load address match*/
#define TDATA1_STORE (1<<1) /*R/W,Fire trigger on store address mat*/
#define TDATA1_EXECUTE (1<<2) /*R/W,Fire trigger on instruction fetch address match*/
#define TDATA1_USER (1<<3) /*R/W,allow trigger to be fired in user mode*/
#define TDATA1_MACHINE (1<<6) /*R/W,Allow trigger to be fired while hart is executing in machine mode*/
#define TDATA1_MATCH (1<<7)
#define TDATA1_MATCH_V (0xF) /*R/W,Address match type :0 : Exact byte match 1 : NAPOT range match */
#define TDATA1_MATCH_S (7)
/* RISC-V CSR macros
* Adapted from https://github.com/michaeljclark/riscv-probe/blob/master/libfemto/include/arch/riscv/machine.h
*/
#define RV_READ_CONST_CSR(reg) ({ unsigned long __tmp; \
asm ("csrr %0, " _CSR_STRINGIFY(reg) : "=r"(__tmp)); __tmp; })
#define RV_READ_CSR(reg) ({ unsigned long __tmp; \
asm volatile ("csrr %0, " _CSR_STRINGIFY(reg) : "=r"(__tmp)); __tmp; })
#define RV_WRITE_CSR(reg, val) ({ \
asm volatile ("csrw " _CSR_STRINGIFY(reg) ", %0" :: "rK"(val)); })
#define RV_SWAP_CSR(reg, val) ({ unsigned long __tmp; \
asm volatile ("csrrw %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(val)); __tmp; })
/* Note: this uses the atomic read-and-set instruction so possible to read the old CSR value as a result */
#define RV_SET_CSR(reg, bit) ({ unsigned long __tmp; \
asm volatile ("csrrs %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(bit)); __tmp; })
/* Note: this uses the atomic read-and-clear instruction so possible to read the old CSR value as a result */
#define RV_CLEAR_CSR(reg, bit) ({ unsigned long __tmp; \
asm volatile ("csrrc %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(bit)); __tmp; })
#define RV_SET_CSR_FIELD(_r, _f, _v) ({ (RV_WRITE_CSR((_r),((RV_READ_CSR(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S)))));})
#define RV_CLEAR_CSR_FIELD(_r, _f) ({ (RV_WRITE_CSR((_r),(RV_READ_CSR(_r) & ~((_f##_V) << (_f##_S)))));})
#define _CSR_STRINGIFY(REG) #REG /* needed so the 'reg' argument can be a macro or a register name */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,227 @@
/* Copyright (c) 2010-2017, The Regents of the University of California
(Regents). All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Regents nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/* Adapted from https://github.com/riscv/riscv-opcodes/blob/master/encoding.h */
#pragma once
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
#define MSTATUS_HIE 0x00000004
#define MSTATUS_MIE 0x00000008
#define MSTATUS_UPIE 0x00000010
#define MSTATUS_SPIE 0x00000020
#define MSTATUS_HPIE 0x00000040
#define MSTATUS_MPIE 0x00000080
#define MSTATUS_SPP 0x00000100
#define MSTATUS_VS 0x00000600
#define MSTATUS_MPP 0x00001800
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
#define MSTATUS_MPRV 0x00020000
#define MSTATUS_SUM 0x00040000
#define MSTATUS_MXR 0x00080000
#define MSTATUS_TVM 0x00100000
#define MSTATUS_TW 0x00200000
#define MSTATUS_TSR 0x00400000
#define MSTATUS32_SD 0x80000000
#define MSTATUS_UXL 0x0000000300000000
#define MSTATUS_SXL 0x0000000C00000000
#define MSTATUS64_SD 0x8000000000000000
#define SSTATUS_UIE 0x00000001
#define SSTATUS_SIE 0x00000002
#define SSTATUS_UPIE 0x00000010
#define SSTATUS_SPIE 0x00000020
#define SSTATUS_SPP 0x00000100
#define SSTATUS_VS 0x00000600
#define SSTATUS_FS 0x00006000
#define SSTATUS_XS 0x00018000
#define SSTATUS_SUM 0x00040000
#define SSTATUS_MXR 0x00080000
#define SSTATUS32_SD 0x80000000
#define SSTATUS_UXL 0x0000000300000000
#define SSTATUS64_SD 0x8000000000000000
#define USTATUS_UIE 0x00000001
#define USTATUS_UPIE 0x00000010
#define DCSR_XDEBUGVER (3U<<30)
#define DCSR_NDRESET (1<<29)
#define DCSR_FULLRESET (1<<28)
#define DCSR_EBREAKM (1<<15)
#define DCSR_EBREAKH (1<<14)
#define DCSR_EBREAKS (1<<13)
#define DCSR_EBREAKU (1<<12)
#define DCSR_STOPCYCLE (1<<10)
#define DCSR_STOPTIME (1<<9)
#define DCSR_CAUSE (7<<6)
#define DCSR_DEBUGINT (1<<5)
#define DCSR_HALT (1<<3)
#define DCSR_STEP (1<<2)
#define DCSR_PRV (3<<0)
#define DCSR_CAUSE_NONE 0
#define DCSR_CAUSE_SWBP 1
#define DCSR_CAUSE_HWBP 2
#define DCSR_CAUSE_DEBUGINT 3
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
#define DCSR_CAUSE_GROUP 6
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
#define MCONTROL_SELECT (1<<19)
#define MCONTROL_TIMING (1<<18)
#define MCONTROL_ACTION (0x3f<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
#define MCONTROL_H (1<<5)
#define MCONTROL_S (1<<4)
#define MCONTROL_U (1<<3)
#define MCONTROL_EXECUTE (1<<2)
#define MCONTROL_STORE (1<<1)
#define MCONTROL_LOAD (1<<0)
#define MCONTROL_TYPE_NONE 0
#define MCONTROL_TYPE_MATCH 2
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
#define MCONTROL_ACTION_DEBUG_MODE 1
#define MCONTROL_ACTION_TRACE_START 2
#define MCONTROL_ACTION_TRACE_STOP 3
#define MCONTROL_ACTION_TRACE_EMIT 4
#define MCONTROL_MATCH_EQUAL 0
#define MCONTROL_MATCH_NAPOT 1
#define MCONTROL_MATCH_GE 2
#define MCONTROL_MATCH_LT 3
#define MCONTROL_MATCH_MASK_LOW 4
#define MCONTROL_MATCH_MASK_HIGH 5
#define MIP_USIP (1 << IRQ_U_SOFT)
#define MIP_SSIP (1 << IRQ_S_SOFT)
#define MIP_HSIP (1 << IRQ_H_SOFT)
#define MIP_MSIP (1 << IRQ_M_SOFT)
#define MIP_UTIP (1 << IRQ_U_TIMER)
#define MIP_STIP (1 << IRQ_S_TIMER)
#define MIP_HTIP (1 << IRQ_H_TIMER)
#define MIP_MTIP (1 << IRQ_M_TIMER)
#define MIP_UEIP (1 << IRQ_U_EXT)
#define MIP_SEIP (1 << IRQ_S_EXT)
#define MIP_HEIP (1 << IRQ_H_EXT)
#define MIP_MEIP (1 << IRQ_M_EXT)
#define SIP_SSIP MIP_SSIP
#define SIP_STIP MIP_STIP
#define PRV_U 0
#define PRV_S 1
#define PRV_H 2
#define PRV_M 3
#define SATP32_MODE 0x80000000
#define SATP32_ASID 0x7FC00000
#define SATP32_PPN 0x003FFFFF
#define SATP64_MODE 0xF000000000000000
#define SATP64_ASID 0x0FFFF00000000000
#define SATP64_PPN 0x00000FFFFFFFFFFF
#define SATP_MODE_OFF 0
#define SATP_MODE_SV32 1
#define SATP_MODE_SV39 8
#define SATP_MODE_SV48 9
#define SATP_MODE_SV57 10
#define SATP_MODE_SV64 11
#define PMP_R 0x01
#define PMP_W 0x02
#define PMP_X 0x04
#define PMP_A 0x18
#define PMP_L 0x80
#define PMP_SHIFT 2
#define PMP_TOR 0x08
#define PMP_NA4 0x10
#define PMP_NAPOT 0x18
#define IRQ_U_SOFT 0
#define IRQ_S_SOFT 1
#define IRQ_H_SOFT 2
#define IRQ_M_SOFT 3
#define IRQ_U_TIMER 4
#define IRQ_S_TIMER 5
#define IRQ_H_TIMER 6
#define IRQ_M_TIMER 7
#define IRQ_U_EXT 8
#define IRQ_S_EXT 9
#define IRQ_H_EXT 10
#define IRQ_M_EXT 11
#define IRQ_COP 12
#define IRQ_HOST 13
#define DEFAULT_RSTVEC 0x00001000
#define CLINT_BASE 0x02000000
#define CLINT_SIZE 0x000c0000
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
/* page table entry (PTE) fields */
#define PTE_V 0x001 /* Valid */
#define PTE_R 0x002 /* Read */
#define PTE_W 0x004 /* Write */
#define PTE_X 0x008 /* Execute */
#define PTE_U 0x010 /* User */
#define PTE_G 0x020 /* Global */
#define PTE_A 0x040 /* Accessed */
#define PTE_D 0x080 /* Dirty */
#define PTE_SOFT 0x300 /* Reserved for Software */
#define PTE_PPN_SHIFT 10
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
#ifdef __riscv
#if __riscv_xlen == 64
# define MSTATUS_SD MSTATUS64_SD
# define SSTATUS_SD SSTATUS64_SD
# define RISCV_PGLEVEL_BITS 9
# define SATP_MODE SATP64_MODE
#else
# define MSTATUS_SD MSTATUS32_SD
# define SSTATUS_SD SSTATUS32_SD
# define RISCV_PGLEVEL_BITS 10
# define SATP_MODE SATP32_MODE
#endif
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
#endif // __riscv

View File

@ -0,0 +1,34 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Decode the offset value from a RISC-V JAL instruction
* @note This API will abort if the instruction is not JAL formatted.
*
* @param inst_addr Address of JAL instruction
* @return int offset value
*/
int riscv_decode_offset_from_jal_instruction(const intptr_t inst_addr);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,115 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
enum intr_type {
INTR_TYPE_LEVEL = 0,
INTR_TYPE_EDGE
};
/*************************** Software interrupt dispatcher ***************************/
/** Callback type of the interrupt handler */
typedef void (*intr_handler_t)(void*);
/** Set the interrupt handler function for the given CPU interrupt
* @param rv_int_num CPU interrupt number
* @param fn Handler function
* @param arg Handler argument
*/
void intr_handler_set(int rv_int_num, intr_handler_t fn, void* arg);
/** Get the interrupt handler function for the given CPU interrupt
*
*@return interrupt handler registered for a particular interrupt number, or NULL otherwise
*/
intr_handler_t intr_handler_get(int rv_int_num);
/** Get the interrupt handler argument associated with the given CPU interrupt
*
*@return interrupt handler argument for a particular interrupt number, or NULL otherwise
*/
void *intr_handler_get_arg(int rv_int_num);
/*************************** Interrupt matrix ***************************/
/**
* this function will be removed in later, please use `intr_matrix_set` instead
* Route the peripheral interrupt signal to the CPU
* @param periph_intr_source Peripheral interrupt number, one of ETS_XXX_SOURCE
* @param rv_int_num CPU interrupt number
*/
void intr_matrix_route(int periph_intr_source, int rv_int_num);
/*************************** ESP-RV Interrupt Controller ***************************/
/**
* @brief Enable interrupts from interrupt controller.
*
* @param uint32_t unmask, unmask bits for interrupts, each bit for an interrupt
*
* return none
*/
void esprv_intc_int_enable(uint32_t unmask);
/**
* @brief Disable interrupts from interrupt controller.
*
* @param uint32_t mask, mask bits for interrupts, each bit for an interrupt
*
* return none
*/
void esprv_intc_int_disable(uint32_t mask);
/**
* @brief Set interrupt type, level or edge
*
* @param int intr_num, interrupt number
*
* @param enum intr_type type, interrupt type, the level interrupt
can be cleared automatically once the interrupt source cleared, the edge interrupt should be clear by software after handled
*
* return none
*/
void esprv_intc_int_set_type(int intr_num, enum intr_type type);
/**
* Set interrupt priority in the interrupt controller
* @param rv_int_num CPU interrupt number
* @param priority Interrupt priority level, 1 to 7
*/
void esprv_intc_int_set_priority(int rv_int_num, int priority);
/**
* Set interrupt priority threshold.
* Interrupts with priority levels lower than the threshold are masked.
*
* @param priority_threshold Interrupt priority threshold, 0 to 7
*/
void esprv_intc_set_threshold(int priority_threshold);
/**
* @brief Get interrupt unmask
* @param none
* @return uint32_t interrupt unmask
*/
uint32_t esprv_intc_get_interrupt_unmask(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,45 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* Enable CPU interrupt
* @param rv_int_num CPU interrupt number
*/
void riscv_interrupt_enable(int rv_int_num);
/**
* Disable CPU interrupt
* @param rv_int_num CPU interrupt number
*/
void riscv_interrupt_disable(int rv_int_num);
/**
* Globally enable CPU interrupts
*/
void riscv_global_interrupts_enable(void);
/**
* Globally disable CPU interrupts
*/
void riscv_global_interrupts_disable(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,96 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#ifndef __RVRUNTIME_FRAMES_H__
#define __RVRUNTIME_FRAMES_H__
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
#ifdef STRUCT_BEGIN
#undef STRUCT_BEGIN
#undef STRUCT_FIELD
#undef STRUCT_AFIELD
#undef STRUCT_END
#endif
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
#define STRUCT_END(sname) sname##Size:; .popsection
#else
#define STRUCT_BEGIN typedef struct {
#define STRUCT_FIELD(ctype,size,asname,name) ctype name;
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
#define STRUCT_END(sname) } sname;
#endif
/*
-------------------------------------------------------------------------------
INTERRUPT/EXCEPTION STACK FRAME FOR A EXCEPTION OR NESTED INTERRUPT
-------------------------------------------------------------------------------
*/
STRUCT_BEGIN
STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */
STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */
STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */
STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */
STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */
STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */
STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */
STRUCT_FIELD (long, 4, RV_STK_T2, t2)
STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */
STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */
STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */
STRUCT_FIELD (long, 4, RV_STK_A1, a1)
STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */
STRUCT_FIELD (long, 4, RV_STK_A3, a3)
STRUCT_FIELD (long, 4, RV_STK_A4, a4)
STRUCT_FIELD (long, 4, RV_STK_A5, a5)
STRUCT_FIELD (long, 4, RV_STK_A6, a6)
STRUCT_FIELD (long, 4, RV_STK_A7, a7)
STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */
STRUCT_FIELD (long, 4, RV_STK_S3, s3)
STRUCT_FIELD (long, 4, RV_STK_S4, s4)
STRUCT_FIELD (long, 4, RV_STK_S5, s5)
STRUCT_FIELD (long, 4, RV_STK_S6, s6)
STRUCT_FIELD (long, 4, RV_STK_S7, s7)
STRUCT_FIELD (long, 4, RV_STK_S8, s8)
STRUCT_FIELD (long, 4, RV_STK_S9, s9)
STRUCT_FIELD (long, 4, RV_STK_S10, s10)
STRUCT_FIELD (long, 4, RV_STK_S11, s11)
STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */
STRUCT_FIELD (long, 4, RV_STK_T4, t4)
STRUCT_FIELD (long, 4, RV_STK_T5, t5)
STRUCT_FIELD (long, 4, RV_STK_T6, t6)
STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */
STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */
STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */
STRUCT_FIELD (long, 4, RV_STK_MTVAL, mtval) /* Machine Trap Value */
STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID in machine mode */
STRUCT_END(RvExcFrame)
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define RV_STK_SZ1 RvExcFrameSize
#else
#define RV_STK_SZ1 sizeof(RvExcFrame)
#endif
/*
* Exception stack frame size, after align up to 16 bytes boundary
*/
#define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1))
#endif /* #ifndef __RVRUNTIME_FRAMES_H__ */