A switch between esp32 and esp32s2betta added to the ULP build process.

The new bin utils will have extension esp32s2ulp-elf, and they have to be placed to the bin directory.
This commit is contained in:
Dmitry
2019-06-28 15:36:32 +03:00
committed by Dmitry
parent f64ee5aba3
commit 1518c410bc
12 changed files with 552 additions and 26 deletions

View File

@@ -16,6 +16,7 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "soc/soc.h"
#include "ulp_common.h"
@@ -76,15 +77,29 @@ extern "C" {
#define ALU_SEL_MOV 4 /*!< Copy value (immediate to destination register or source register to destination register */
#define ALU_SEL_LSH 5 /*!< Shift left by given number of bits */
#define ALU_SEL_RSH 6 /*!< Shift right by given number of bits */
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
#define ALU_SEL_INC 0 /*!< Stage_cnt = Stage_cnt + Imm */
#define ALU_SEL_DEC 1 /*!< Stage_cnt = Stage_cnt - Imm */
#define ALU_SEL_RST 2 /*!< Stage_cnt = 0 */
#endif
#define OPCODE_BRANCH 8 /*!< Branch instructions */
#define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */
#define BX_JUMP_TYPE_DIRECT 0 /*!< Unconditional jump */
#define BX_JUMP_TYPE_ZERO 1 /*!< Branch if last ALU result is zero */
#define BX_JUMP_TYPE_OVF 2 /*!< Branch if last ALU operation caused and overflow */
#define SUB_OPCODE_B 1 /*!< Branch to a relative offset */
#ifdef CONFIG_IDF_TARGET_ESP32
#define B_CMP_L 0 /*!< Branch if R0 is less than an immediate */
#define B_CMP_GE 1 /*!< Branch if R0 is greater than or equal to an immediate */
#define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */
#define SUB_OPCODE_B 1 /*!< Branch to a relative offset */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
#define B_CMP_L 1 /*!< Branch if R0 is less than an immediate */
#define B_CMP_GE 2 /*!< Branch if R0 is greater than an immediate */
#define B_CMP_EQ 4 /*!< Branch if R0 is equal to an immediate */
#define SUB_OPCODE_BX 1 /*!< Branch to absolute PC (immediate or in register) */
#define SUB_OPCODE_B 0 /*!< Branch to a relative offset base on R0 */
#define SUB_OPCODE_B_STAGE 2 /*!< Branch to a relative offset base on stage reg */
#endif
#define OPCODE_END 9 /*!< Stop executing the program */
#define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */
@@ -99,6 +114,10 @@ extern "C" {
#define OPCODE_MACRO 15 /*!< Not a real opcode. Used to identify labels and branches in the program */
#define SUB_OPCODE_MACRO_LABEL 0 /*!< Label macro */
#define SUB_OPCODE_MACRO_BRANCH 1 /*!< Branch macro */
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
#define OPCODE_SLEEP_WAIT 4
#endif
/**@}*/
/**
@@ -123,6 +142,7 @@ union ulp_insn {
uint32_t opcode : 4; /*!< Opcode (OPCODE_DELAY) */
} delay; /*!< Format of DELAY instruction */
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Register which contains data to store */
uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
@@ -132,7 +152,24 @@ union ulp_insn {
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
} st; /*!< Format of ST instruction */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Data address register number */
uint32_t sreg : 2; /*!< Base address register number */
uint32_t data_label : 2; /*!< Data label */
uint32_t upper : 1; /*!< High and low half-word Select 1: Write high half-word; 0 : write low half-word; */
uint32_t write_way : 2; /*!< Write number Mode 0 : full word write; 1: with data_label; 3: without label; */
uint32_t unused1 : 1; /*!< Unused */
uint32_t offset : 11; /*!< When you select automatic storage, you need to configure the base address offset*/
uint32_t unused2 : 4; /*!< Unused */
uint32_t wr_auto : 1; /*!< Automatic storage selection enabled (burst mode)*/
uint32_t offset_set : 1; /*!< Configure OFFSET enable */
uint32_t manul_en : 1; /*!< Manual storage selection enabled */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
} st; /*!< Format of ST instruction */
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Register where the data should be loaded to */
uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
@@ -141,12 +178,24 @@ union ulp_insn {
uint32_t unused2 : 7; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
} ld; /*!< Format of LD instruction */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Register where the data should be loaded to */
uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
uint32_t unused1 : 6; /*!< Unused */
uint32_t offset : 11; /*!< Offset to add to sreg */
uint32_t unused2 : 6; /*!< Unused */
uint32_t rd_upper: 1;
uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
} ld; /*!< Format of LD instruction */
#endif
struct {
uint32_t unused : 28; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */
} halt; /*!< Format of HALT instruction */
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
@@ -165,7 +214,29 @@ union ulp_insn {
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_B) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
} b; /*!< Format of BRANCH instruction (relative address) */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
uint32_t unused : 8; /*!< Unused */
uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */
uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */
uint32_t unused1 : 1; /*!< Unused */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_BX) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
} bx; /*!< Format of BRANCH instruction (absolute address) */
struct {
uint32_t imm : 15; /*!< Immediate value to compare against */
uint32_t cmp : 3; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_B) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
} b;
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
@@ -175,7 +246,20 @@ union ulp_insn {
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_reg; /*!< Format of ALU instruction (both sources are registers) */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
uint32_t treg : 2; /*!< Register with operand B */
uint32_t unused : 15; /*!< Unused */
uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
uint32_t unused1 : 1; /*!< Unused */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_reg; /*!< Format of ALU instruction (both sources are registers) */
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
@@ -185,6 +269,27 @@ union ulp_insn {
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
uint32_t imm : 16; /*!< Immediate value of operand B */
uint32_t unused : 1; /*!< Unused */
uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
uint32_t unused1 : 1; /*!< Unused */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
struct {
uint32_t unused : 4; /*!< Unused */
uint32_t imm : 16; /*!< Immediate value of operand B */
uint32_t unused1 : 1; /*!< Unused */
uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
uint32_t unused2 : 1; /*!< Unused */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_cnt; /*!< Format of ALU instruction (one source is an immediate) */
#endif
struct {
uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
@@ -203,7 +308,7 @@ union ulp_insn {
uint32_t high : 5; /*!< High bit */
uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
} rd_reg; /*!< Format of RD_REG instruction */
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t dreg : 2; /*!< Register where to store ADC result */
uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
@@ -213,7 +318,17 @@ union ulp_insn {
uint32_t unused2 : 4; /*!< Unused */
uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
} adc; /*!< Format of ADC instruction */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t dreg : 2; /*!< Register where to store ADC result */
uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */
uint32_t hall_phase : 1; /*!< Unused */
uint32_t xpd_hall : 1; /*!< Unused */
uint32_t unused1 : 19; /*!< Unused */
uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
} adc;
#endif
struct {
uint32_t dreg : 2; /*!< Register where to store temperature measurement result */
uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */
@@ -231,7 +346,7 @@ union ulp_insn {
uint32_t rw : 1; /*!< Write (1) or read (0) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */
} i2c; /*!< Format of I2C instruction */
#ifdef CONFIG_IDF_TARGET_ESP32
struct {
uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
uint32_t unused : 24; /*!< Unused */
@@ -245,7 +360,20 @@ union ulp_insn {
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
} sleep; /*!< Format of END instruction with sleep */
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
struct {
uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
uint32_t unused : 25; /*!< Unused */
uint32_t sub_opcode : 2; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
} end;
struct {
uint32_t cycle_sel : 16; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
uint32_t unused : 12; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
} sleep;
#endif
struct {
uint32_t label : 16; /*!< Label number */
uint32_t unused : 8; /*!< Unused */
@@ -373,8 +501,13 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
* ULP program will continue running after this instruction. To stop
* the currently running program, use I_HALT().
*/
#ifdef CONFIG_IDF_TARGET_ESP32
#define I_END() \
I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
#define I_END() \
I_WR_REG_BIT(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
#endif
/**
* Select the time interval used to run ULP program.
*
@@ -390,12 +523,18 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
* By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP
* program timer.
*/
#ifdef CONFIG_IDF_TARGET_ESP32
#define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
.cycle_sel = timer_idx, \
.unused = 0, \
.sub_opcode = SUB_OPCODE_SLEEP, \
.opcode = OPCODE_END } }
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
#define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
.cycle_sel = timer_idx, \
.unused = 0, \
.opcode = OPCODE_SLEEP_WAIT } }
#endif
/**
* Perform temperature sensor measurement and store it into reg_dest.
*
@@ -414,6 +553,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
* adc_idx selects ADC (0 or 1).
* pad_idx selects ADC pad (0 - 7).
*/
#ifdef CONFIG_IDF_TARGET_ESP32
#define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
.dreg = reg_dest, \
.mux = pad_idx + 1, \
@@ -422,6 +562,16 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.cycles = 0, \
.unused2 = 0, \
.opcode = OPCODE_ADC } }
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
#define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
.dreg = reg_dest, \
.mux = pad_idx + 1, \
.sar_sel = adc_idx, \
.hall_phase = 0, \
.xpd_hall = 0, \
.unused1 = 0, \
.opcode = OPCODE_ADC } }
#endif
/**
* Store value from register reg_val into RTC memory.
@@ -435,6 +585,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
*
* RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] }
*/
#ifdef CONFIG_IDF_TARGET_ESP32
#define I_ST(reg_val, reg_addr, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
@@ -443,7 +594,138 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused2 = 0, \
.sub_opcode = SUB_OPCODE_ST, \
.opcode = OPCODE_ST } }
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
/**
* burst Mode: write to consecutive address spaces.
* STW, STC instructions for the Class burst storage instructions for continuous address space write operation;
* Need to be used with the SET_OFFSET instruction, you first need to set the start address offset by SET_OFFSET, SREG is the base address,
* Where STW instruction WORD instruction, each execution time, address offset+1;STC for the half-word operation
* (First write high 16bit current address, the Second Write low 16bit current address), each performed twice, the address offset+1.
* Note: when using STC, you must write a word, that is, a burst operation instruction must be an even number.
*/
#define I_STO(offset_) { .st = { \
.dreg = 0, \
.sreg = 0, \
.data_label = 0, \
.upper = 0, \
.write_way = 0, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
#define I_STW(reg_val, reg_addr) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = 0, \
.upper = 0, \
.write_way = 0, \
.unused1 = 0, \
.offset = 0, \
.unused2 = 0, \
.wr_auto = 1, \
.offset_set = 0, \
.manul_en = 0, \
.opcode = OPCODE_ST } }
#define I_STC(reg_val, reg_addr) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = 0, \
.upper = 0, \
.write_way = 3, \
.unused1 = 0, \
.offset = 0, \
.unused2 = 0, \
.wr_auto = 1, \
.offset_set = 0, \
.manul_en = 0, \
.opcode = OPCODE_ST } }
/**
* Single mode of operation: write to a single address space.
*
* Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
* value of offset_.
*/
/* Mem [ Rsrc1 + offset ]{31:0} = {PC[10:0], 5<>d0,Rdst[15:0]} */
#define I_ST(reg_val, reg_addr, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = 0, \
.upper = 0, \
.write_way = 0, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
/* Mem [ Rsrc1 + offset ]{31:16} = {Rdst[15:0]} */
#define I_STM32U(reg_val, reg_addr, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = 0, \
.upper = 1, \
.write_way = 3, \
.unused1 = 0, \
.offset = offset_, \
.unused1 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
/* Mem [ Rsrc1 + offset ]{15:0} = {Rdst[15:0]} */
#define I_STM32L(reg_val, reg_addr, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = 0, \
.upper = 0, \
.write_way = 3, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
/* Mem [ Rsrc1 + offset ]{31:0} = {data_label[1:0],Rdst[13:0]} */
#define I_STMLBU(reg_val, reg_addr, label, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = label, \
.upper = 1, \
.write_way = 1, \
.unused1 = 0, \
.offset = offset_, \
.unused1 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
/* Mem [ Rsrc1 + offset ]{15:0} = {data_label[1:0],Rdst[13:0]} */
#define I_STMLBL(reg_val, reg_addr, label, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.data_label = label, \
.upper = 0, \
.write_way = 1, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.wr_auto = 0, \
.offset_set = 0, \
.manul_en = 1, \
.opcode = OPCODE_ST } }
#endif
/**
* Load value from RTC memory into reg_dest register.
@@ -451,6 +733,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
* Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
* value of offset_.
*/
#ifdef CONFIG_IDF_TARGET_ESP32
#define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
.dreg = reg_dest, \
.sreg = reg_addr, \
@@ -458,7 +741,16 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.offset = offset_, \
.unused2 = 0, \
.opcode = OPCODE_LD } }
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
#define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
.dreg = reg_dest, \
.sreg = reg_addr, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.rd_upper = 0, \
.opcode = OPCODE_LD } }
#endif
/**
* Branch relative if R0 less than immediate value.
@@ -474,6 +766,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
#ifdef CONFIG_IDF_TARGET_ESP32
/**
* Branch relative if R0 greater or equal than immediate value.
*
@@ -487,7 +780,75 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
#endif
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
/**
* Branch relative if R0 greater than immediate value.
*
* pc_offset is expressed in words, and can be from -127 to 127
* imm_value is a 16-bit value to compare R0 against
*/
#define I_BG(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_GE, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
/**
* Branch relative if R0 equal to immediate value.
*
* pc_offset is expressed in words, and can be from -127 to 127
* imm_value is a 16-bit value to compare R0 against
*/
#define I_BE(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_EQ, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
/*
* Branch to a relative offset base on stage reg
* If stage reg less imm_value, PC will jump pc_offset.
*/
#define I_BRLS(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_L, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B_STAGE, \
.opcode = OPCODE_BRANCH } }
/*
* Branch to a relative offset base on stage reg
* If stage reg greater imm_value, PC will jump pc_offset.
*/
#define I_BRGS(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_GE, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B_STAGE, \
.opcode = OPCODE_BRANCH } }
/*
* Branch to a relative offset base on stage reg
* If stage reg equal to imm_value, PC will jump pc_offset.
*/
#define I_BRES(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_EQ, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B_STAGE, \
.opcode = OPCODE_BRANCH } }
#endif
/**
* Unconditional branch to absolute PC, address in register.
*
@@ -500,6 +861,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_DIRECT, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -514,6 +876,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_DIRECT, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -529,6 +892,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_ZERO, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -543,6 +907,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_ZERO, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -558,6 +923,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_OVF, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -572,6 +938,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_OVF, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
@@ -585,6 +952,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_ADD, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -597,6 +965,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_SUB, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -609,6 +978,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_AND, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -621,6 +991,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_OR, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -633,6 +1004,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = 0, \
.unused = 0, \
.sel = ALU_SEL_MOV, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -645,6 +1017,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_shift, \
.unused = 0, \
.sel = ALU_SEL_LSH, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -658,6 +1031,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.treg = reg_shift, \
.unused = 0, \
.sel = ALU_SEL_RSH, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
@@ -670,6 +1044,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_ADD, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -683,6 +1058,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_SUB, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -695,6 +1071,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_AND, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -707,6 +1084,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_OR, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -719,6 +1097,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_MOV, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -731,6 +1110,7 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_LSH, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
@@ -744,9 +1124,49 @@ static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg) {
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_RSH, \
.unused1 = 0, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
/**
* Increments the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt + Imm
*/
#define I_SINC(imm_) { .alu_cnt = { \
.unused = 0, \
.imm = imm_, \
.unused1 = 0, \
.sel = ALU_SEL_INC, \
.unused2 = 0, \
.sub_opcode = SUB_OPCODE_ALU_CNT, \
.opcode = OPCODE_ALU } }
/**
* Decrements the stage counter for the subscript of the cycle count, Stage_cnt = Stage_cnt - Imm
*/
#define I_SDEC(imm_) { .alu_cnt = { \
.unused = 0, \
.imm = imm_, \
.unused1 = 0, \
.sel = ALU_SEL_DEC, \
.unused2 = 0, \
.sub_opcode = SUB_OPCODE_ALU_CNT, \
.opcode = OPCODE_ALU } }
/**
* Phase counter is reset for the cycle count subscript, Stage_cnt = 0
*/
#define I_SRST() { .alu_cnt = { \
.unused = 0, \
.imm = 0, \
.unused1 = 0, \
.sel = ALU_SEL_RST, \
.unused2 = 0, \
.sub_opcode = SUB_OPCODE_ALU_CNT, \
.opcode = OPCODE_ALU } }
#endif
/**
* Define a label with number label_num.
*