Files
qemu-xteink/target/xtensa/translate_tie_esp32s3.c
T
harshal.patil ba5950398f feat(xtensa/esp32s3): Extend the ESP32-S3's TIE instructions
1. Missing bare ee.vldbc.{8,16,32} instructions - Added 3 opcode table entries with addr_nop and updated translate_vldbc_s3 to handle addr_nop without erroring.
2. Missing ee.st.qacc_{h,l}.{h.32,l.128}.ip store instructions - Added 4 opcode table entries, 2 translate functions, and 2 helper functions (with declarations in helper.h) to implement the QACC store operations as mirrors of the existing load counterparts.
3. ee.src.q incorrect qs1->qs0 copy - The bare ee.src.q qa, qs0, qs1 was incorrectly copying qs1→qs0 after the funnel shift. Per the TRM, only the .qup variant does this copy. Fixed by making the copy conditional on op_type == vmul_qup.
4. Add ee.st.accx.ip to store 40-bit ACCX (zero-extended to 64-bit) to memory, 8-byte aligned.
5. Add ee.ld.ua_state.ip to load 128-bit UA_STATE from memory, 16-byte aligned.
6. Add ee.st.ua_state.ip to store 128-bit UA_STATE to memory, 16-byte aligned.
7. Add ee.ldxq.32: Indexed load: compute address from Q register s16 segment, load 32-bit into Q register segment.
8. Add ee.stxq.32: Indexed store: compute address from Q register s16 segment, store 32-bit from Q register segment.
2026-04-15 14:08:04 +02:00

6198 lines
189 KiB
C

#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "disas/disas.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-temp-internal.h"
#include "qemu/log.h"
#include "qemu/qemu-print.h"
#include "exec/cpu_ldst.h"
#include "semihosting/semihost.h"
#include "exec/translator.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "exec/log.h"
#include "translate.h"
#include "cpu_esp32s3.h"
typedef enum Addr_Update
{
addr_nop,
addr_inc16,
addr_dec16,
addr_ip,
addr_xp,
addr_ldbc_inc1,
} Addr_Update;
typedef enum vldbc_type
{
vldbc_8,
vldbc_16,
vldbc_32,
} vldbc_type;
typedef enum ldqa_type
{
ldqa_u8,
ldqa_s8,
ldqa_u16,
ldqa_s16,
ldqa_u32,
ldqa_s32,
} ldqa_type;
typedef enum vmul_type
{
vmul_nop,
vmul_s8,
vmul_u8,
vmul_s16,
vmul_u16,
vmul_s8xs8,
vmul_s8lx16,
vmul_s8hx16,
vmul_s32,
vmul_qup,
}vmul_type;
typedef enum ee_ldst_type
{
ee_load_op,
ee_store_op,
} ee_ldst_type;
typedef enum cmul_type
{
cmul_sel0,
cmul_sel1,
cmul_sel2,
cmul_sel3,
}cmul_type;
typedef enum wrur_type
{
wrur_accx_0,
wrur_accx_1,
wrur_qacc_h_0,
wrur_qacc_h_1,
wrur_qacc_h_2,
wrur_qacc_h_3,
wrur_qacc_h_4,
wrur_qacc_l_0,
wrur_qacc_l_1,
wrur_qacc_l_2,
wrur_qacc_l_3,
wrur_qacc_l_4,
wrur_gpio_out,
wrur_sar_byte,
wrur_fft_bit_width,
wrur_ua_state_0,
wrur_ua_state_1,
wrur_ua_state_2,
wrur_ua_state_3,
} wrur_type;
typedef enum ee_zero_type
{
ee_zero_qacc,
ee_zero_accx,
ee_zero_qx,
}ee_zero_type;
typedef enum ee_movi_type
{
ee_movi_a,
ee_movi_q,
}ee_movi_type;
typedef enum ee_vcmp_type
{
ee_vcmp_eq,
ee_vcmp_lt,
ee_vcmp_gt,
}ee_vcmp_type;
typedef enum ee_bw_logic_type
{
bw_logic_or,
bw_logic_and,
bw_logic_xor,
bw_logic_not,
bw_shift_left,
bw_shift_right,
}ee_bw_logic_type;
typedef enum gpio_type
{
gpio_mask,
gpio_set,
gpio_clr,
gpio_in,
} gpio_type;
typedef struct QACC_reg_s
{
union
{
int32_t s20[8];
uint32_t u20[8];
uint8_t u20_8[32];
};
union
{
int64_t s40[4];
uint64_t u40[4];
uint8_t u40_8[32];
};
} QACC_reg;
typedef enum ee_arithmetic_type
{
ee_add_op,
ee_sub_op,
}ee_arithmetic_type;
extern TCGv_i32 cpu_SR[256];
static void load_qacc(uint8_t* src, QACC_reg* dest);
static void save_qacc20(QACC_reg* src, uint8_t* dest);
static void save_qacc40(QACC_reg* src, uint8_t* dest);
static void load_qacc(uint8_t* src, QACC_reg* dest)
{
for (int i=0 ; i< 4 ; i++)
{
dest->s20[0 + i*2] = ((((uint32_t)src[2 + i*5]) << 16) |(((uint32_t)src[1 + i*5]) << 8) | ((uint32_t)src[0 + i*5])) << 12;
dest->s20[0 + i*2] = dest->s20[0 + i*2] >> 12;
dest->s20[1 + i*2] = ((((uint32_t)src[4 + i*5]) << 12) |(((uint32_t)src[3 + i*5]) << 4) | ((uint32_t)src[2 + i*5] >> 4)) << 12;
dest->s20[1 + i*2] = dest->s20[1 + i*2] >> 12;
}
for (int i=0 ; i< 4 ; i++)
{
dest->s40[i] = ((((uint64_t)src[4 + i*5]) << 32) | (((uint64_t)src[3 + i*5]) << 24)| (((uint64_t)src[2 + i*5]) << 16)| (((uint64_t)src[1 + i*5]) << 8) | ((uint64_t)src[0 + i*5])) << 24;
dest->s40[i] = dest->s40[i] >> 24;
}
}
static void save_qacc20(QACC_reg* src, uint8_t* dest)
{
for (int i = 0; i < 4; i++)
{
dest[0 + i*5] = (uint8_t)((src->u20[0 + i*2]) & 0xff);
dest[1 + i*5] = (uint8_t)((src->u20[0 + i*2]>>8) & 0xff);
dest[2 + i*5] = (uint8_t)(((src->u20[0 + i*2]>>16) & 0xf) | ((src->u20[1 + i*2]<<4) & 0xf0));
dest[3 + i*5] = (uint8_t)((src->u20[1 + i*2]>>4) & 0xff);
dest[4 + i*5] = (uint8_t)((src->u20[1 + i*2]>>12) & 0xff);
}
}
static void save_qacc40(QACC_reg* src, uint8_t* dest)
{
for (int i = 0; i < 4; i++)
{
uint8_t* src_ptr = (uint8_t*)&src->u40[i];
for (int m = 0; m < 5; m++)
{
dest[i*5 + m] = src_ptr[m];
}
}
}
static inline esp_qreg_t *cpu_vec_ptr(CPUXtensaState *env, int i)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return &tie->Q[i];
}
static inline uint8_t *cpu_sar_ptr(CPUXtensaState *env)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return &tie->SAR_BYTE;
}
static inline ACCQ_reg *cpu_qacc_ptr(CPUXtensaState *env, int a_b)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return &tie->ACCQ[a_b];
}
void HELPER(vld_64_s3)(CPUXtensaState *env, uint32_t vec, uint64_t data, uint32_t low_high)
{
esp_qreg_t *avr = cpu_vec_ptr(env, vec);
avr->u64[low_high] = data;
return;
}
void HELPER(ldqa_64_s3)(CPUXtensaState *env, uint32_t data_type, uint64_t data, uint32_t low_high)
{
ACCQ_reg *qacc = cpu_qacc_ptr(env, low_high);
if(ldqa_u8 == (ldqa_type)data_type)
{
uint8_t* data_ptr = (uint8_t*)&data;
QACC_reg q_reg;
for (int i=0 ; i< 8 ; i++)
{
q_reg.u20[i] = (uint32_t)data_ptr[i];
}
save_qacc20(&q_reg, qacc->u8);
} else if(ldqa_s8 == (ldqa_type)data_type)
{
int8_t* data_ptr = (int8_t*)&data;
QACC_reg q_reg;
for (int i=0 ; i< 8 ; i++)
{
q_reg.s20[i] = (int32_t)data_ptr[i];
}
save_qacc20(&q_reg, qacc->u8);
} else if(ldqa_u16 == (ldqa_type)data_type)
{
uint16_t* data_ptr = (uint16_t*)&data;
QACC_reg q_reg;
for (int i=0 ; i< 4 ; i++)
{
q_reg.u40[i] = (uint32_t)data_ptr[i];
}
save_qacc40(&q_reg, qacc->u8);
} else if(ldqa_s16 == (ldqa_type)data_type)
{
int16_t* data_ptr = (int16_t*)&data;
QACC_reg q_reg;
for (int i=0 ; i< 4 ; i++)
{
q_reg.s40[i] = (int32_t)data_ptr[i];
}
save_qacc40(&q_reg, qacc->u8);
}
return;
}
void HELPER(set_sar_byte_s3)(CPUXtensaState *env, uint32_t sar)
{
uint8_t* sar_ptr = cpu_sar_ptr(env);
*sar_ptr = sar;
return;
}
void HELPER(vldhbc_16_s3)(CPUXtensaState *env, uint32_t vec, uint64_t data)
{
esp_qreg_t *avr = cpu_vec_ptr(env, vec);
uint16_t* data16 = (uint16_t*)&data;
for (int i = 0; i < 4; i++)
{
avr->u16[i*2 + 0] = data16[i];
avr->u16[i*2 + 1] = data16[i];
}
return;
}
void HELPER(vldbc_s3)(CPUXtensaState *env, uint32_t vec, uint32_t data, uint32_t bc_bits)
{
esp_qreg_t *avr = cpu_vec_ptr(env, vec);
if (vldbc_8 == bc_bits)
{
for (int i=0 ; i< 16 ; i++)
{
avr->u8[i] = data&0xff;
}
} else if (vldbc_16 == bc_bits)
{
for (int i=0 ; i< 8 ; i++)
{
avr->u16[i] = data&0xffff;
}
} else if (vldbc_32 == bc_bits)
{
for (int i=0 ; i< 4 ; i++)
{
avr->u32[i] = data;
}
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension! \n");
}
return;
}
uint64_t HELPER(vst_64_s3)(CPUXtensaState *env, uint32_t vec, uint32_t low_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = tie->Q[vec].u64[low_high];
return result;
}
/// @brief This function used to dump the code from QEMU
void HELPER(dump_all_s3)(CPUXtensaState *env)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
printf("Dump TIE: \n");
for (int i = 0; i < 8; i++)
{
printf("Q[%i]: ", i);
esp_qreg_t *avr = cpu_vec_ptr(env, i);
for (int m = 0; m < 16; m++)
{
printf("%2.2x ", avr->u8[m]);
}
printf("\n");
/* code */
}
QACC_reg q_req_l;
QACC_reg q_req_h;
load_qacc(tie->ACCQ[0].u8, &q_req_l);
load_qacc(tie->ACCQ[1].u8, &q_req_h);
printf("QACC_L: ");
for (int i = 0; i < 20; i++)
{
printf("%2.2x ", tie->ACCQ[0].u8[i]);
}
printf("\n");
printf("QACC_H: ");
for (int i = 0; i < 20; i++)
{
printf("%2.2x ", tie->ACCQ[1].u8[i]);
}
printf("\n");
for (int i = 0; i < 8; i++)
{
printf("QACC_L S20[%i] %8.8x\n", i, q_req_l.s20[i]);
}
for (int i = 0; i < 8; i++)
{
printf("QACC_H S20[%i] %8.8x\n", i+8, q_req_h.s20[i]);
}
for (int i = 0; i < 4; i++)
{
printf("QACC_L S40[%i] %16.16" PRIx64 "\n", i, q_req_l.s40[i]);
}
for (int i = 0; i < 4; i++)
{
printf("QACC_H S40[%i] %16.16" PRIx64 "\n", i+4, q_req_h.s40[i]);
}
printf("ACCX = %16.16" PRIx64 "\n", tie->ACCX);
printf("SAR_BYTE = %i\n", tie->SAR_BYTE);
printf("\n");
return;
}
static void translate_zero(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
// Example, how to call dump for all registers
// Dump all
// translate_dump_all_s3(dc,arg,par);
// Clear acc:
TCGv_i32 index;
index = tcg_constant_i32(par[0]);
if ((ee_zero_qacc == (ee_zero_type)par[0]) || (ee_zero_accx == (ee_zero_type)par[0]))
{
TCGv_i32 dummy = tcg_constant_i32(0);
gen_helper_zero_s3(tcg_env, index, dummy);
tcg_temp_free_i32(dummy);
} else
{
TCGv_i32 qr_index = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_zero_s3(tcg_env, index, qr_index);
tcg_temp_free_i32(qr_index);
}
tcg_temp_free_i32(index);
}
void HELPER(zero_s3)(CPUXtensaState *env, uint32_t data, uint32_t index)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if ((ee_zero_type)data == ee_zero_qacc)
{
for (int i = 0; i < 20; i++)
{
tie->ACCQ[0].u8[i] = 0;
tie->ACCQ[1].u8[i] = 0;
}
} else if ((ee_zero_type)data == ee_zero_accx)
{
tie->ACCX = 0;
} else if ((ee_zero_type)data == ee_zero_qx)
{
tie->Q[index].u64[0] = 0;
tie->Q[index].u64[1] = 0;
}
}
void HELPER(wur_s3)(CPUXtensaState *env, uint32_t data, uint32_t wrur_reg)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
switch ((wrur_type)wrur_reg)
{
case wrur_accx_0:
((uint32_t*)(&tie->ACCX))[0] = data;
tie->ACCX &= 0x000000ffffffffff;
break;
case wrur_accx_1:
((uint32_t*)(&tie->ACCX))[1] = data;
tie->ACCX &= 0x000000ffffffffff;
break;
case wrur_qacc_l_0:
case wrur_qacc_l_1:
case wrur_qacc_l_2:
case wrur_qacc_l_3:
case wrur_qacc_l_4:
{
uint8_t* data_ptr = (uint8_t*)&data;
int index = wrur_reg - wrur_qacc_l_0;
for (int i = 0; i < 4; i++)
{
tie->ACCQ[0].u8[i + 4*index] = data_ptr[i];
}
}
break;
case wrur_qacc_h_0:
case wrur_qacc_h_1:
case wrur_qacc_h_2:
case wrur_qacc_h_3:
case wrur_qacc_h_4:
{
uint8_t* data_ptr = (uint8_t*)&data;
int index = wrur_reg - wrur_qacc_h_0;
for (int i = 0; i < 4; i++)
{
tie->ACCQ[1].u8[i + 4*index] = data_ptr[i];
}
}
break;
case wrur_gpio_out:
tie->gpio_out = data;
break;
case wrur_sar_byte:
tie->SAR_BYTE = data;
break;
case wrur_fft_bit_width:
tie->fft_width = data;
break;
case wrur_ua_state_0:
case wrur_ua_state_1:
case wrur_ua_state_2:
case wrur_ua_state_3:
{
int index = wrur_reg - wrur_ua_state_0;
tie->UA_STATE.u32[index] = data;
}
break;
default:
break;
}
return;
}
static void translate_wur(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 wur_addr = tcg_constant_i32(par[0]);
gen_helper_wur_s3(tcg_env, arg[0].in, wur_addr);
tcg_temp_free_i32(wur_addr);
}
uint32_t HELPER(rur_s3)(CPUXtensaState *env, uint32_t wrur_reg)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint32_t result = 0;
switch ((wrur_type)wrur_reg)
{
case wrur_accx_0:
result = ((uint32_t*)(&tie->ACCX))[0];
break;
case wrur_accx_1:
result = ((uint32_t*)(&tie->ACCX))[1];
break;
case wrur_qacc_l_0:
case wrur_qacc_l_1:
case wrur_qacc_l_2:
case wrur_qacc_l_3:
case wrur_qacc_l_4:
{
uint8_t* data_ptr = (uint8_t*)&result;
int index = wrur_reg - wrur_qacc_l_0;
for (int i = 0; i < 4; i++)
{
data_ptr[i] = tie->ACCQ[0].u8[i + 4*index];
}
}
break;
case wrur_qacc_h_0:
case wrur_qacc_h_1:
case wrur_qacc_h_2:
case wrur_qacc_h_3:
case wrur_qacc_h_4:
{
uint8_t* data_ptr = (uint8_t*)&result;
int index = wrur_reg - wrur_qacc_h_0;
for (int i = 0; i < 4; i++)
{
data_ptr[i] = tie->ACCQ[1].u8[i + 4*index];
}
}
break;
case wrur_gpio_out:
result = tie->gpio_out;
break;
case wrur_sar_byte:
result = tie->SAR_BYTE;
break;
case wrur_fft_bit_width:
result = tie->fft_width;
break;
case wrur_ua_state_0:
case wrur_ua_state_1:
case wrur_ua_state_2:
case wrur_ua_state_3:
{
int index = wrur_reg - wrur_ua_state_0;
result = tie->UA_STATE.u32[index];
}
break;
default:
break;
}
return result;
}
static void translate_rur(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 rur_addr = tcg_constant_i32(par[0]);
gen_helper_rur_s3( arg[0].out, tcg_env, rur_addr);
tcg_temp_free_i32(rur_addr);
}
static void translate_vld_64_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(par[1]);
gen_helper_vld_64_s3(tcg_env, index, data, low_high);
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
static void translate_vldhbc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i< 2 ; i++)
{
TCGv_i32 addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[i].imm);
gen_helper_vldhbc_16_s3(tcg_env, index, data);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
}
tcg_gen_addi_i32(arg[2].out, arg[2].in, 16);
}
static void translate_vldbc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
MemOp mop = MO_8;
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 ldbc_type = tcg_constant_i32(par[1]);
TCGv_i32 addr = tcg_temp_new_i32();
if (vldbc_8 == par[1])
{
tcg_gen_andi_i32(addr, arg[1].in, 0xffffffff);
mop = gen_load_store_alignment(dc, MO_8 | MO_TE, addr);
} else if (vldbc_16 == par[1])
{
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffffe);
mop = gen_load_store_alignment(dc, MO_16 | MO_TE, addr);
} else if (vldbc_32 == par[1])
{
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffffc);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
TCGv_i32 data = tcg_temp_new_i32();
// Read data from memory
tcg_gen_qemu_ld_i32(data, addr, dc->cring, mop);
gen_helper_vldbc_s3(tcg_env, index, data, ldbc_type);
tcg_temp_free_i32(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else if (par[0] ==addr_ldbc_inc1)
{
if (vldbc_8 == par[1]) tcg_gen_addi_i32(arg[1].out, arg[1].in, 1);
if (vldbc_16 == par[1]) tcg_gen_addi_i32(arg[1].out, arg[1].in, 2);
} else if (par[0] != addr_nop)
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_vst_64_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(par[1]);
gen_helper_vst_64_s3(data, tcg_env, index, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_vld_128_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vld_64_s3(tcg_env, index, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_ld_qr_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, arg[2].imm);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vld_64_s3(tcg_env, index, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
}
static void translate_ld_usar_128_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vld_64_s3(tcg_env, index, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
TCGv_i32 sar = tcg_temp_new_i32();
tcg_gen_andi_i32(sar, arg[1].in, 0xf);
gen_helper_set_sar_byte_s3(tcg_env, sar);
tcg_temp_free_i32(sar);
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_ldqa_128_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 data_type;
data_type = tcg_constant_i32((uint32_t)par[1]);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_ldqa_64_s3(tcg_env, data_type, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(data_type);
tcg_temp_free_i32(low_high);
}
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[0].out, arg[0].in, arg[1].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_vst_128_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vst_64_s3(data, tcg_env, index, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
if (par[0] == addr_ip)
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
} else if (par[0] == addr_xp)
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
} else
{
qemu_log_mask(LOG_GUEST_ERROR, "unknown instruction extension (pc = %08x)\n", dc->pc);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
}
}
static void translate_st_qr_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, arg[2].imm);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vst_64_s3(data, tcg_env, index, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
}
void HELPER(mv_qr_s3)(CPUXtensaState *env, uint32_t qv, uint32_t qx)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
for (int i = 0; i < 16; i++)
{
tie->Q[qv].u8[i] = tie->Q[qx].u8[i];
}
}
static void translate_mv_qr_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qv = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[1].imm);
gen_helper_mv_qr_s3(tcg_env, qv, qx);
tcg_temp_free_i32(qv);
tcg_temp_free_i32(qx);
}
uint64_t HELPER(fft_vst_64_s3)(CPUXtensaState *env, uint32_t qv, uint32_t sar2, uint32_t low_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int32_t* prt_result = (int32_t*)&result;
if (0 == low_high)
{
prt_result[0] = tie->Q[qv].u32[3] >> sar2;
prt_result[1] = tie->Q[qv].u32[2] >> sar2;
} else
{
prt_result[0] = tie->Q[qv].u32[1] >> sar2;
prt_result[1] = tie->Q[qv].u32[0] >> sar2;
}
return result;
}
static void translate_fft_vst_decp_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 addr_low;
TCGv_i32 addr_high;
MemOp mop_low;
MemOp mop_high;
addr_low = tcg_temp_new_i32();
addr_high = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr_low, arg[1].in, 0xfffffff0);
tcg_gen_andi_i32(addr_high, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr_high, addr_high, 8);
mop_low = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_low);
mop_high = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_high);
TCGv_i64 data_low = tcg_temp_new_i64();
TCGv_i64 data_high = tcg_temp_new_i64();
// Read data from memory
TCGv_i32 qv = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 sar2 = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 low_high = tcg_constant_i32(0);
gen_helper_fft_vst_64_s3(data_low, tcg_env, qv, sar2, low_high);
low_high = tcg_constant_i32(1);
gen_helper_fft_vst_64_s3(data_high, tcg_env, qv, sar2, low_high);
tcg_gen_qemu_st_i64(data_low, addr_low, dc->cring, mop_low);
tcg_gen_qemu_st_i64(data_high, addr_high, dc->cring, mop_high);
tcg_temp_free_i64(data_low);
tcg_temp_free_i32(addr_low);
tcg_temp_free_i64(data_high);
tcg_temp_free_i32(addr_high);
tcg_temp_free_i32(qv);
tcg_temp_free_i32(low_high);
tcg_gen_subi_i32(arg[1].out, arg[1].in, 16);
}
static void translate_ldf_128_ip(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[4];
for (int i = 0; i < 4; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[4].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_o1(arg, arg32, 3 - i);
tcg_gen_qemu_ld_tl(arg32[3 - i].out, addr, dc->cring, mop);
put_f32_o1(arg, arg32, 3 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_addi_i32(arg[4].out, arg[4].in, arg[5].imm);
}
static void translate_stf_128_ip(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[4];
for (int i = 0; i < 4; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[4].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_i1(arg, arg32, 3 - i);
tcg_gen_qemu_st_tl(arg32[3 - i].in, addr, dc->cring, mop);
put_f32_i1(arg, arg32, 3 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_addi_i32(arg[4].out, arg[4].in, arg[5].imm);
}
static void translate_ldf_64_ip(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[2];
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 64 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff8);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_o1(arg, arg32, 1 - i);
tcg_gen_qemu_ld_tl(arg32[1 - i].out, addr, dc->cring, mop);
put_f32_o1(arg, arg32, 1 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_addi_i32(arg[2].out, arg[2].in, arg[3].imm);
}
static void translate_stf_64_ip(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[2];
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 64 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff8);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_i1(arg, arg32, 1 - i);
tcg_gen_qemu_st_tl(arg32[1 - i].in, addr, dc->cring, mop);
put_f32_i1(arg, arg32, 1 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_addi_i32(arg[2].out, arg[2].in, arg[3].imm);
}
static void translate_ldf_128_xp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
OpcodeArg arg32[4];
for (int i = 0; i < 4; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[4].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_o1(arg, arg32, 3 - i);
tcg_gen_qemu_ld_tl(arg32[3 - i].out, addr, dc->cring, mop);
put_f32_o1(arg, arg32, 3 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_add_i32(arg[4].out, arg[4].in, arg[5].in);
}
static void translate_stf_128_xp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[4];
for (int i = 0; i < 4; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[4].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_i1(arg, arg32, 3 - i);
tcg_gen_qemu_st_tl(arg32[3 - i].in, addr, dc->cring, mop);
put_f32_i1(arg, arg32, 3 - i);
tcg_temp_free_i32(addr);
}
tcg_gen_add_i32(arg[4].out, arg[4].in, arg[5].in);
}
static void translate_ldf_64_xp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[2];
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 64 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff8);
tcg_gen_addi_i32(addr, addr, i*4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_o1(arg, arg32, 1-i);
tcg_gen_qemu_ld_tl(arg32[1-i].out, addr, dc->cring, mop);
put_f32_o1(arg, arg32, 1-i);
tcg_temp_free_i32(addr);
}
tcg_gen_add_i32(arg[2].out, arg[2].in, arg[3].in);
}
static void translate_stf_64_xp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
OpcodeArg arg32[2];
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 64 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff8);
tcg_gen_addi_i32(addr, addr, i*4);
mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
get_f32_i1(arg, arg32, 1-i);
tcg_gen_qemu_st_tl(arg32[1-i].in, addr, dc->cring, mop);
put_f32_i1(arg, arg32, 1-i);
tcg_temp_free_i32(addr);
}
tcg_gen_add_i32(arg[2].out, arg[2].in, arg[3].in);
}
void HELPER(mov_qacc_s3)(CPUXtensaState *env, uint32_t data_type, uint32_t qr_index)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if(ldqa_u8 == (ldqa_type)data_type)
{
ACCQ_reg *qacc_l = cpu_qacc_ptr(env, 0);
ACCQ_reg *qacc_h = cpu_qacc_ptr(env, 1);
QACC_reg q_reg_l;
QACC_reg q_reg_h;
for (int i=0 ; i< 8 ; i++)
{
q_reg_l.u20[i] = (uint32_t)tie->Q[qr_index].u8[i];
q_reg_h.u20[i] = (uint32_t)tie->Q[qr_index].u8[i+8];
}
save_qacc20(&q_reg_l, qacc_l->u8);
save_qacc20(&q_reg_h, qacc_h->u8);
} else if(ldqa_s8 == (ldqa_type)data_type)
{
ACCQ_reg *qacc_l = cpu_qacc_ptr(env, 0);
ACCQ_reg *qacc_h = cpu_qacc_ptr(env, 1);
QACC_reg q_reg_l;
QACC_reg q_reg_h;
for (int i=0 ; i< 8 ; i++)
{
q_reg_l.s20[i] = (int32_t)tie->Q[qr_index].s8[i];
q_reg_h.s20[i] = (int32_t)tie->Q[qr_index].s8[i+8];
}
save_qacc20(&q_reg_l, qacc_l->u8);
save_qacc20(&q_reg_h, qacc_h->u8);
} else if(ldqa_u16 == (ldqa_type)data_type)
{
ACCQ_reg *qacc_l = cpu_qacc_ptr(env, 0);
ACCQ_reg *qacc_h = cpu_qacc_ptr(env, 1);
QACC_reg q_reg_l;
QACC_reg q_reg_h;
for (int i=0 ; i< 4 ; i++)
{
q_reg_l.u40[i] = (uint64_t)tie->Q[qr_index].u16[i];
q_reg_h.u40[i] = (uint64_t)tie->Q[qr_index].u16[i+4];
}
save_qacc40(&q_reg_l, qacc_l->u8);
save_qacc40(&q_reg_h, qacc_h->u8);
} else if(ldqa_s16 == (ldqa_type)data_type)
{
ACCQ_reg *qacc_l = cpu_qacc_ptr(env, 0);
ACCQ_reg *qacc_h = cpu_qacc_ptr(env, 1);
QACC_reg q_reg_l;
QACC_reg q_reg_h;
for (int i=0 ; i< 4 ; i++)
{
q_reg_l.s40[i] = (int64_t)tie->Q[qr_index].s16[i];
q_reg_h.s40[i] = (int64_t)tie->Q[qr_index].s16[i+4];
}
save_qacc40(&q_reg_l, qacc_l->u8);
save_qacc40(&q_reg_h, qacc_h->u8);
}
return;
}
static void translate_mov_qacc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 data_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 qr_index = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_mov_qacc_s3(tcg_env, data_type, qr_index);
tcg_temp_free_i32(qr_index);
tcg_temp_free_i32(data_type);
}
void HELPER(movi_q_s3)(CPUXtensaState *env, uint32_t qr_index, uint32_t sel, uint32_t data)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
tie->Q[qr_index].u32[sel] = data;
}
uint32_t HELPER(movi_a_s3)(CPUXtensaState *env, uint32_t qr_index, uint32_t sel)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint32_t result = tie->Q[qr_index].u32[sel];
return result;
}
static void translate_movi_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qr_index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 sel = tcg_constant_i32((uint32_t)arg[2].imm);
if (ee_movi_a == (ee_movi_type)par[0])
{
gen_helper_movi_a_s3(arg[1].out, tcg_env, qr_index, sel);
} else if (ee_movi_q == (ee_movi_type)par[0])
{
gen_helper_movi_q_s3(tcg_env, qr_index, sel, arg[1].in);
}
tcg_temp_free_i32(qr_index);
tcg_temp_free_i32(sel);
}
void HELPER(vzip_s3)(CPUXtensaState *env, uint32_t qs0, uint32_t qs1, uint32_t width)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
Q_reg q_copy[2];
Q_reg* q0 = &tie->Q[qs0];
Q_reg* q1 = &tie->Q[qs1];
q_copy[0].u64[0] = q0->u64[0];
q_copy[0].u64[1] = q0->u64[1];
q_copy[1].u64[0] = q1->u64[0];
q_copy[1].u64[1] = q1->u64[1];
if (vldbc_8 == (vldbc_type)width)
{
for (int i=0 ; i< 8 ; i++)
{
q0->u8[i*2 + 0] = q_copy[0].u8[i];
q0->u8[i*2 + 1] = q_copy[1].u8[i];
q1->u8[i*2 + 0] = q_copy[0].u8[i + 8];
q1->u8[i*2 + 1] = q_copy[1].u8[i + 8];
}
} else if (vldbc_16 == (vldbc_type)width)
{
for (int i=0 ; i< 4 ; i++)
{
q0->u16[i*2 + 0] = q_copy[0].u16[i];
q0->u16[i*2 + 1] = q_copy[1].u16[i];
q1->u16[i*2 + 0] = q_copy[0].u16[i + 4];
q1->u16[i*2 + 1] = q_copy[1].u16[i + 4];
}
} else if (vldbc_32 == (vldbc_type)width)
{
for (int i=0 ; i< 2 ; i++)
{
q0->u32[i*2 + 0] = q_copy[0].u32[i];
q0->u32[i*2 + 1] = q_copy[1].u32[i];
q1->u32[i*2 + 0] = q_copy[0].u32[i + 2];
q1->u32[i*2 + 1] = q_copy[1].u32[i + 2];
}
}
}
void HELPER(vunzip_s3)(CPUXtensaState *env, uint32_t qs0, uint32_t qs1, uint32_t width)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
Q_reg q_copy[2];
Q_reg* q0 = &tie->Q[qs0];
Q_reg* q1 = &tie->Q[qs1];
q_copy[0].u64[0] = q0->u64[0];
q_copy[0].u64[1] = q0->u64[1];
q_copy[1].u64[0] = q1->u64[0];
q_copy[1].u64[1] = q1->u64[1];
if (vldbc_8 == (vldbc_type)width)
{
for (int i=0 ; i< 8 ; i++)
{
q0->u8[i] = q_copy[0].u8[i*2 + 0];
q0->u8[i + 8] = q_copy[1].u8[i*2 + 0];
q1->u8[i] = q_copy[0].u8[i*2 + 1];
q1->u8[i + 8] = q_copy[1].u8[i*2 + 1];
}
} else if (vldbc_16 == (vldbc_type)width)
{
for (int i=0 ; i< 4 ; i++)
{
q0->u16[i] = q_copy[0].u16[i*2 + 0];
q0->u16[i + 4] = q_copy[1].u16[i*2 + 0];
q1->u16[i] = q_copy[0].u16[i*2 + 1];
q1->u16[i + 4] = q_copy[1].u16[i*2 + 1];
}
} else if (vldbc_32 == (vldbc_type)width)
{
for (int i=0 ; i< 2 ; i++)
{
q0->u32[i] = q_copy[0].u32[i*2 + 0];
q0->u32[i + 2] = q_copy[1].u32[i*2 + 0];
q1->u32[i] = q_copy[0].u32[i*2 + 1];
q1->u32[i + 2] = q_copy[1].u32[i*2 + 1];
}
}
}
static void translate_zip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 width = tcg_constant_i32((uint32_t)par[1]);
if (0 == par[0]) // zip operation
{
gen_helper_vzip_s3(tcg_env, qs0, qs1, width);
} else // unzip operation
{
gen_helper_vunzip_s3(tcg_env, qs0, qs1, width);
}
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
tcg_temp_free_i32(width);
}
void HELPER(vadds_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (ldqa_s8 == (ldqa_type)op_type)
{
for (int i = 0; i < 16; i++)
{
int16_t result = (int16_t)tie->Q[qx].s8[i] + (int16_t)tie->Q[qy].s8[i];
if (result > 0x7f) result = 0x7f;
if (result < -0x7f) result = -0x7f;
tie->Q[qz].s8[i] = result;
}
} else if (ldqa_s16 == (ldqa_type)op_type)
{
for (int i = 0; i < 8; i++)
{
int32_t result = (int32_t)tie->Q[qx].s16[i] + (int32_t)tie->Q[qy].s16[i];
if (result > 0x7fff) result = 0x7fff;
if (result < -0x7fff) result = -0x7fff;
tie->Q[qz].s16[i] = result;
}
} else if (ldqa_s32 == (ldqa_type)op_type)
{
for (int i = 0; i < 4; i++)
{
int64_t result = (int64_t)tie->Q[qx].s32[i] + (int64_t)tie->Q[qy].s32[i];
if (result > 0x7fffffff) result = 0x7fffffff;
if (result < -0x7fffffff) result = -0x7fffffff;
tie->Q[qz].s32[i] = result;
}
} else if (ldqa_u8 == (ldqa_type)op_type)
{
for (int i = 0; i < 16; i++)
{
uint16_t result = (uint16_t)tie->Q[qx].u8[i] + (uint16_t)tie->Q[qy].u8[i];
if (result > 0xff) result = 0xff;
tie->Q[qz].u8[i] = result;
}
} else if (ldqa_u16 == (ldqa_type)op_type)
{
for (int i = 0; i < 8; i++)
{
uint32_t result = (uint32_t)tie->Q[qx].u16[i] + (uint32_t)tie->Q[qy].u16[i];
if (result > 0xffff) result = 0xffff;
tie->Q[qz].u16[i] = result;
}
} else if (ldqa_u32 == (ldqa_type)op_type)
{
for (int i = 0; i < 4; i++)
{
uint64_t result = (uint64_t)tie->Q[qx].u32[i] + (uint64_t)tie->Q[qy].u32[i];
if (result > 0xffffffff) result = 0xffffffff;
tie->Q[qz].u32[i] = result;
}
}
}
void HELPER(vsubs_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (ldqa_s8 == (ldqa_type)op_type)
{
for (int i = 0; i < 16; i++)
{
int16_t result = (int16_t)tie->Q[qx].s8[i] - (int16_t)tie->Q[qy].s8[i];
if (result > 0x7f) result = 0x7f;
if (result < -0x7f) result = -0x7f;
tie->Q[qz].s8[i] = result;
}
} else if (ldqa_s16 == (ldqa_type)op_type)
{
for (int i = 0; i < 8; i++)
{
int32_t result = (int32_t)tie->Q[qx].s16[i] - (int32_t)tie->Q[qy].s16[i];
if (result > 0x7fff) result = 0x7fff;
if (result < -0x7fff) result = -0x7fff;
tie->Q[qz].s16[i] = result;
}
} else if (ldqa_s32 == (ldqa_type)op_type)
{
for (int i = 0; i < 4; i++)
{
int64_t result = (int64_t)tie->Q[qx].s32[i] - (int64_t)tie->Q[qy].s32[i];
if (result > 0x7fffffff) result = 0x7fffffff;
if (result < -0x7fffffff) result = -0x7fffffff;
tie->Q[qz].s32[i] = result;
}
} else if (ldqa_u8 == (ldqa_type)op_type)
{
for (int i = 0; i < 16; i++)
{
uint16_t result = (uint16_t)tie->Q[qx].u8[i] - (uint16_t)tie->Q[qy].u8[i];
if (result > 0xff) result = 0xff;
tie->Q[qz].u8[i] = result;
}
} else if (ldqa_u16 == (ldqa_type)op_type)
{
for (int i = 0; i < 8; i++)
{
uint32_t result = (uint32_t)tie->Q[qx].u16[i] - (uint32_t)tie->Q[qy].u16[i];
if (result > 0xffff) result = 0xffff;
tie->Q[qz].u16[i] = result;
}
} else if (ldqa_u32 == (ldqa_type)op_type)
{
for (int i = 0; i < 4; i++)
{
uint64_t result = (uint64_t)tie->Q[qx].u32[i] - (uint64_t)tie->Q[qy].u32[i];
if (result > 0xffffffff) result = 0xffffffff;
tie->Q[qz].u32[i] = result;
}
}
}
static void store_qreg_to_memory(DisasContext *dc, const OpcodeArg arg[])
{
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vst_64_s3(data, tcg_env, index, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
}
static void load_qreg_from_memory(DisasContext *dc, const OpcodeArg arg[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index;
index = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_vld_64_s3(tcg_env, index, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
tcg_temp_free_i32(low_high);
}
}
// par[0..2] = ldqa_s8, addr_nop, ee_load_op
// Addr_Update
// ee_ldst_type
static void translate_vadds_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
// First, we have to store the register to the memory
int start_index = 0;
if (addr_inc16 == (Addr_Update)par[1])
{
start_index = 2;
if (ee_store_op == (ee_ldst_type)par[2])
{
store_qreg_to_memory(dc, arg);
}
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
if (ee_add_op == (ee_arithmetic_type)par[3])
{
gen_helper_vadds_s3(tcg_env, qz, qx, qy, op_type);
} else if (ee_sub_op == (ee_arithmetic_type)par[3])
{
gen_helper_vsubs_s3(tcg_env, qz, qx, qy, op_type);
}
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if (addr_inc16 == (Addr_Update)par[1])
{
if (ee_load_op == (ee_ldst_type)par[2])
{
// Store
load_qreg_from_memory(dc, arg);
}
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(vmul_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t sar, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (vmul_s8 == (vmul_type)op_type)
{
for (size_t i = 0; i < 16; i++)
{
int16_t result = ((int16_t)tie->Q[qx].s8[i] * (int16_t)tie->Q[qy].s8[i]) >> sar;
tie->Q[qz].s8[i] = (int8_t)result;
}
} else if (vmul_u8 == (vmul_type)op_type)
{
for (size_t i = 0; i < 16; i++)
{
uint16_t result = ((uint16_t)tie->Q[qx].u8[i] * (uint16_t)tie->Q[qy].u8[i]) >> sar;
tie->Q[qz].u8[i] = (uint8_t)result;
}
} else if (vmul_s16 == (vmul_type)op_type)
{
for (size_t i = 0; i < 8; i++)
{
int32_t result = ((int32_t)tie->Q[qx].s16[i] * (int32_t)tie->Q[qy].s16[i]) >> sar;
tie->Q[qz].s16[i] = (int16_t)result;
}
} else if (vmul_u16 == (vmul_type)op_type)
{
for (size_t i = 0; i < 8; i++)
{
uint32_t result = ((uint32_t)tie->Q[qx].u16[i] * (uint32_t)tie->Q[qy].u16[i]) >> sar;
tie->Q[qz].u16[i] = (uint32_t)result;
}
}
}
static void translate_vmul_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_inc16 == (Addr_Update)par[1])
{
start_index = 2;
if (ee_store_op == (ee_ldst_type)par[2])
{
store_qreg_to_memory(dc, arg);
}
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
if (dc->sar_m32_5bit)
{
gen_helper_vmul_s3(tcg_env, qz, qx, qy, dc->sar_m32, op_type);
} else
{
gen_helper_vmul_s3(tcg_env, qz, qx, qy, cpu_SR[SAR], op_type);
}
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if (addr_inc16 == (Addr_Update)par[1])
{
if (ee_load_op == (ee_ldst_type)par[2])
{
// Store
load_qreg_from_memory(dc, arg);
}
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(cmul_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t sar, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int32_t result = 0;
if (0 == op_type)
{
result = (((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]) - ((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1])) >> sar;
tie->Q[qz].s16[0] = result;
result = (((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]) + ((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0])) >> sar;
tie->Q[qz].s16[1] = result;
result = (((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]) - ((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3])) >> sar;
tie->Q[qz].s16[2] = result;
result = (((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]) + ((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2])) >> sar;
tie->Q[qz].s16[3] = result;
} else if (1 == op_type)
{
result = (((int32_t)tie->Q[qx].s16[0 + 4])*((int32_t)tie->Q[qy].s16[0 + 4]) - ((int32_t)tie->Q[qx].s16[1 + 4])*((int32_t)tie->Q[qy].s16[1 + 4])) >> sar;
tie->Q[qz].s16[0 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[0 + 4])*((int32_t)tie->Q[qy].s16[1 + 4]) + ((int32_t)tie->Q[qx].s16[1 + 4])*((int32_t)tie->Q[qy].s16[0 + 4])) >> sar;
tie->Q[qz].s16[1 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[2 + 4])*((int32_t)tie->Q[qy].s16[2 + 4]) - ((int32_t)tie->Q[qx].s16[3 + 4])*((int32_t)tie->Q[qy].s16[3 + 4])) >> sar;
tie->Q[qz].s16[2 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[2 + 4])*((int32_t)tie->Q[qy].s16[3 + 4]) + ((int32_t)tie->Q[qx].s16[3 + 4])*((int32_t)tie->Q[qy].s16[2 + 4])) >> sar;
tie->Q[qz].s16[3 + 4] = result;
} else if (2 == op_type)
{
result = (((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]) + ((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1])) >> sar;
tie->Q[qz].s16[0] = result;
result = (((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]) - ((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0])) >> sar;
tie->Q[qz].s16[1] = result;
result = (((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]) + ((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3])) >> sar;
tie->Q[qz].s16[2] = result;
result = (((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]) - ((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2])) >> sar;
tie->Q[qz].s16[3] = result;
} else if (3 == op_type)
{
result = (((int32_t)tie->Q[qx].s16[0 + 4])*((int32_t)tie->Q[qy].s16[0 + 4]) + ((int32_t)tie->Q[qx].s16[1 + 4])*((int32_t)tie->Q[qy].s16[1 + 4])) >> sar;
tie->Q[qz].s16[0 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[0 + 4])*((int32_t)tie->Q[qy].s16[1 + 4]) - ((int32_t)tie->Q[qx].s16[1 + 4])*((int32_t)tie->Q[qy].s16[0 + 4])) >> sar;
tie->Q[qz].s16[1 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[2 + 4])*((int32_t)tie->Q[qy].s16[2 + 4]) + ((int32_t)tie->Q[qx].s16[3 + 4])*((int32_t)tie->Q[qy].s16[3 + 4])) >> sar;
tie->Q[qz].s16[2 + 4] = result;
result = (((int32_t)tie->Q[qx].s16[2 + 4])*((int32_t)tie->Q[qy].s16[3 + 4]) - ((int32_t)tie->Q[qx].s16[3 + 4])*((int32_t)tie->Q[qy].s16[2 + 4])) >> sar;
tie->Q[qz].s16[3 + 4] = result;
}
}
static void translate_cmul_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
if ((addr_inc16 == (Addr_Update)par[0]) && (ee_store_op == (ee_ldst_type)par[1]))
{
store_qreg_to_memory(dc, arg);
}
int start_index = 0;
if (addr_nop == (Addr_Update)par[0])
{
start_index = 0;
} else
{
start_index = 2;
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)arg[start_index + 3].imm);
if (dc->sar_m32_5bit)
{
gen_helper_cmul_s3(tcg_env, qz, qx, qy, dc->sar_m32, op_type);
}
else
{
gen_helper_cmul_s3(tcg_env, qz, qx, qy, cpu_SR[SAR], op_type);
}
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if ((addr_inc16 == (Addr_Update)par[0]) && (ee_load_op == (ee_ldst_type)par[1]))
{
// Store
load_qreg_from_memory(dc, arg);
}
if (addr_inc16 == (Addr_Update)par[0])
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(vmulas_accx_s3)(CPUXtensaState *env, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (vmul_s8 == (vmul_type)op_type)
{
for (size_t i = 0; i < 16; i++)
{
tie->ACCX += (int16_t)tie->Q[qx].s8[i] * (int16_t)tie->Q[qy].s8[i];
}
if (tie->ACCX > 0x7fffffffff)
{
tie->ACCX = 0x7fffffffff;
}
if (tie->ACCX < -0x7fffffffff)
{
tie->ACCX = -0x7fffffffff;
}
} else if (vmul_u8 == (vmul_type)op_type)
{
for (size_t i = 0; i < 16; i++)
{
tie->ACCX += (uint16_t)tie->Q[qx].u8[i] * (uint16_t)tie->Q[qy].u8[i];
}
if (tie->ACCX > 0xffffffffff)
{
tie->ACCX = 0xffffffffff;
}
if (tie->ACCX < 0)
{
tie->ACCX = 0;
}
} else if (vmul_s16 == (vmul_type)op_type)
{
for (size_t i = 0; i < 8; i++)
{
tie->ACCX += (int32_t)tie->Q[qx].s16[i] * (int32_t)tie->Q[qy].s16[i];
}
if (tie->ACCX > 0x7fffffffff)
{
tie->ACCX = 0x7fffffffff;
}
if (tie->ACCX < -0x7fffffffff)
{
tie->ACCX = -0x7fffffffff;
}
} else if (vmul_u16 == (vmul_type)op_type)
{
for (size_t i = 0; i < 8; i++)
{
tie->ACCX += (uint32_t)tie->Q[qx].u16[i] * (uint32_t)tie->Q[qy].u16[i];
}
if (tie->ACCX > 0xffffffffff)
{
tie->ACCX = 0xffffffffff;
}
if (tie->ACCX < 0)
{
tie->ACCX = 0;
}
}
}
static void translate_vmulas_accx_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_nop == (Addr_Update)par[1])
{
start_index = 0;
} else
{
start_index = 3;
}
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vmulas_accx_s3(tcg_env, qx, qy, op_type);
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if (addr_nop != (Addr_Update)par[1])
{
load_qreg_from_memory(dc, arg);
}
if (addr_ip == (Addr_Update)par[1])
{
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
}
if (addr_xp == (Addr_Update)par[1])
{
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
}
if (par[2] == vmul_qup)
{
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[start_index + 3].imm);
gen_helper_vmulas_qup_s3(tcg_env, qs0, qs1);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
}
}
void HELPER(vmulas_qacc_s3)(CPUXtensaState *env, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
QACC_reg q_req_l;
QACC_reg q_req_h;
load_qacc(tie->ACCQ[0].u8, &q_req_l);
load_qacc(tie->ACCQ[1].u8, &q_req_h);
if (vmul_s8 == (vmul_type)op_type)
{
for (int i = 0; i < 8; i++)
{
q_req_l.s20[i] += (int32_t)tie->Q[qx].s8[i]*(int32_t)tie->Q[qy].s8[i];
if (q_req_l.s20[i] > 0x7ffff) q_req_l.s20[i] = 0x7ffff;
if (q_req_l.s20[i] < -0x7ffff) q_req_l.s20[i] = -0x7ffff;
q_req_h.s20[i] += (int32_t)tie->Q[qx].s8[i + 8]*(int32_t)tie->Q[qy].s8[i + 8];
if (q_req_h.s20[i] > 0x7ffff) q_req_h.s20[i] = 0x7ffff;
if (q_req_h.s20[i] < -0x7ffff) q_req_h.s20[i] = -0x7ffff;
}
save_qacc20(&q_req_l, tie->ACCQ[0].u8);
save_qacc20(&q_req_h, tie->ACCQ[1].u8);
} else if (vmul_u8 == (vmul_type)op_type)
{
for (int i = 0; i < 8; i++)
{
q_req_l.u20[i] += (uint32_t)tie->Q[qx].u8[i]*(uint32_t)tie->Q[qy].u8[i];
if (q_req_l.u20[i] > 0xfffff) q_req_l.u20[i] = -0xfffff;
q_req_h.u20[i] += (uint32_t)tie->Q[qx].u8[i + 8]*(uint32_t)tie->Q[qy].u8[i + 8];
if (q_req_h.u20[i] > 0xfffff) q_req_h.u20[i] = -0xfffff;
}
save_qacc20(&q_req_l, tie->ACCQ[0].u8);
save_qacc20(&q_req_h, tie->ACCQ[1].u8);
} else if (vmul_s16 == (vmul_type)op_type)
{
for (int i = 0; i < 4; i++)
{
q_req_l.s40[i] += (int64_t)tie->Q[qx].s16[i]*(int64_t)tie->Q[qy].s16[i];
if (q_req_l.s40[i] > 0x7fffffffff) q_req_l.s40[i] = 0x7fffffffff;
if (q_req_l.s40[i] < -0x7fffffffff) q_req_l.s40[i] = -0x7fffffffff;
q_req_h.s40[i] += (int64_t)tie->Q[qx].s16[i + 4]*(int64_t)tie->Q[qy].s16[i + 4];
if (q_req_h.s40[i] > 0x7fffffffff) q_req_h.s40[i] = 0x7fffffffff;
if (q_req_h.s40[i] < -0x7fffffffff) q_req_h.s40[i] = -0x7fffffffff;
}
save_qacc40(&q_req_l, tie->ACCQ[0].u8);
save_qacc40(&q_req_h, tie->ACCQ[1].u8);
} else if (vmul_u16 == (vmul_type)op_type)
{
for (int i = 0; i < 4; i++)
{
q_req_l.u40[i] += (int64_t)tie->Q[qx].u16[i]*(int64_t)tie->Q[qy].u16[i];
if (q_req_l.u40[i] > 0xffffffffff) q_req_l.u40[i] = 0xffffffffff;
q_req_h.u40[i] += (int64_t)tie->Q[qx].u16[i + 4]*(int64_t)tie->Q[qy].u16[i + 4];
if (q_req_h.u40[i] > 0xffffffffff) q_req_h.u40[i] = 0xffffffffff;
}
save_qacc40(&q_req_l, tie->ACCQ[0].u8);
save_qacc40(&q_req_h, tie->ACCQ[1].u8);
}
}
void HELPER(vmulas_qup_s3)(CPUXtensaState *env, uint32_t qs0, uint32_t qs1)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int shift = tie->SAR_BYTE;
for (int i=0 ; i< (16-shift) ; i++)
{
tie->Q[qs0].u8[i] = tie->Q[qs0].u8[i + shift];
}
for (int i= 16-shift ; i< 16 ; i++)
{
tie->Q[qs0].u8[i] = tie->Q[qs1].u8[i - (16 - shift)];
}
}
static void translate_vmulas_qacc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_nop == (Addr_Update)par[1])
{
start_index = 0;
} else if (addr_ldbc_inc1 == (Addr_Update)par[1])
{
start_index = 2;
}else
{
start_index = 3;
}
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vmulas_qacc_s3(tcg_env, qx, qy, op_type);
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if (addr_ldbc_inc1 == (Addr_Update)par[1])
{
if ((par[0] == vmul_s8) || (par[0] == vmul_u8))
{
const uint32_t* par_ldbc = (const uint32_t[]){addr_ldbc_inc1, vldbc_8};
translate_vldbc_s3(dc, arg, par_ldbc);
}
if ((par[0] == vmul_s16) || (par[0] == vmul_u16))
{
const uint32_t* par_ldbc = (const uint32_t[]){addr_ldbc_inc1, vldbc_16};
translate_vldbc_s3(dc, arg, par_ldbc);
}
}
if (addr_ip == (Addr_Update)par[1])
{
load_qreg_from_memory(dc, arg);
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
}
if (addr_xp == (Addr_Update)par[1])
{
load_qreg_from_memory(dc, arg);
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
}
if (par[2] == vmul_qup)
{
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[start_index + 3].imm);
gen_helper_vmulas_qup_s3(tcg_env, qs0, qs1);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
}
}
void HELPER(vsmulas_s3)(CPUXtensaState *env, uint32_t qx, uint32_t qy, uint32_t op_type, uint32_t sel)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
QACC_reg q_req_l;
QACC_reg q_req_h;
load_qacc(tie->ACCQ[0].u8, &q_req_l);
load_qacc(tie->ACCQ[1].u8, &q_req_h);
if (op_type == vmul_s8)
{
int32_t tmp_s = tie->Q[qy].s8[sel];
for (int i=0 ; i< 8 ; i++)
{
q_req_l.s20[i] += (int32_t)tie->Q[qx].s8[i] * tmp_s;
if (q_req_l.s20[i] > 0x7ffff) q_req_l.s20[i] = 0x7ffff;
if (q_req_l.s20[i] < -0x7ffff) q_req_l.s20[i] = -0x7ffff;
q_req_h.s20[i] += (int32_t)tie->Q[qx].s8[i + 8] * tmp_s;
if (q_req_h.s20[i] > 0x7ffff) q_req_h.s20[i] = 0x7ffff;
if (q_req_h.s20[i] < -0x7ffff) q_req_h.s20[i] = -0x7ffff;
}
save_qacc20(&q_req_l, tie->ACCQ[0].u8);
save_qacc20(&q_req_h, tie->ACCQ[1].u8);
} else if (op_type == vmul_s16)
{
int32_t tmp_s = tie->Q[qy].s16[sel];
for (int i=0 ; i< 4 ; i++)
{
q_req_l.s40[i] += (int32_t)tie->Q[qx].s16[i] * tmp_s;
if (q_req_l.s40[i] > 0x7fffffffff) q_req_l.s40[i] = 0x7fffffffff;
if (q_req_l.s40[i] < -0x7fffffffff) q_req_l.s40[i] = -0x7fffffffff;
q_req_h.s40[i] += (int32_t)tie->Q[qx].s16[i + 4] * tmp_s;
if (q_req_h.s40[i] > 0x7fffffffff) q_req_h.s40[i] = 0x7fffffffff;
if (q_req_h.s40[i] < -0x7fffffffff) q_req_h.s40[i] = -0x7fffffffff;
}
save_qacc40(&q_req_l, tie->ACCQ[0].u8);
save_qacc40(&q_req_h, tie->ACCQ[1].u8);
}
}
static void translate_vsmulas_qacc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_nop == (Addr_Update)par[1])
{
start_index = 0;
}
if (addr_inc16 == (Addr_Update)par[1])
{
start_index = 2;
}
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 op_sel = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
gen_helper_vsmulas_s3(tcg_env, qx, qy, op_type, op_sel);
tcg_temp_free_i32(op_sel);
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
if (addr_inc16 == (Addr_Update)par[1])
{
load_qreg_from_memory(dc, arg);
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(srcmb_qacc_s3)(CPUXtensaState *env, uint32_t qu, uint32_t a0, uint32_t op_type, uint32_t sel)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
QACC_reg q_req_l;
QACC_reg q_req_h;
load_qacc(tie->ACCQ[0].u8, &q_req_l);
load_qacc(tie->ACCQ[1].u8, &q_req_h);
if (vmul_s8 == op_type)
{
for (int i=0 ; i< 8 ; i++)
{
q_req_l.s20[i] = q_req_l.s20[i] >> a0;
q_req_h.s20[i] = q_req_h.s20[i] >> a0;
tie->Q[qu].s8[i] = q_req_l.s20[i];
tie->Q[qu].s8[i + 8] = q_req_h.s20[i];
if (q_req_l.s20[i] > 0x7f)
{
tie->Q[qu].s8[i] = 0x7f;
}
if (q_req_l.s20[i] < -0x7f)
{
tie->Q[qu].s8[i] = 0x80;
}
if (q_req_h.s20[i] > 0x7f)
{
tie->Q[qu].s8[i + 8] = 0x7f;
}
if (q_req_h.s20[i] < -0x7f)
{
tie->Q[qu].s8[i + 8] = 0x80;
}
}
save_qacc20(&q_req_l, tie->ACCQ[0].u8);
save_qacc20(&q_req_h, tie->ACCQ[1].u8);
} else if (vmul_s16 == op_type)
{
for (int i=0 ; i< 4 ; i++)
{
q_req_l.s40[i] = q_req_l.s40[i] >> a0;
q_req_h.s40[i] = q_req_h.s40[i] >> a0;
tie->Q[qu].s16[i] = q_req_l.s40[i];
tie->Q[qu].s16[i + 4] = q_req_h.s40[i];
if (q_req_l.s40[i] > 0x7fff)
{
tie->Q[qu].s16[i] = 0x7fff;
}
if (q_req_l.s40[i] < -0x7fff)
{
tie->Q[qu].s16[i] = 0x8000;
}
if (q_req_h.s40[i] > 0x7fff)
{
tie->Q[qu].s16[i + 4] = 0x7fff;
}
if (q_req_h.s40[i] < -0x7fff)
{
tie->Q[qu].s16[i + 4] = 0x8000;
}
}
save_qacc40(&q_req_l, tie->ACCQ[0].u8);
save_qacc40(&q_req_h, tie->ACCQ[1].u8);
}
}
static void translate_srcmb_qacc_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qu = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 op_sel = tcg_constant_i32((uint32_t)arg[2].imm);
gen_helper_srcmb_qacc_s3(tcg_env, qu, arg[1].in, op_type, op_sel);
tcg_temp_free_i32(qu);
tcg_temp_free_i32(op_sel);
tcg_temp_free_i32(op_type);
}
void HELPER(vrelu_s3)(CPUXtensaState *env, uint32_t qs, uint32_t ax, uint32_t ay, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int32_t* pax = (int32_t*)&ax;
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qs].s8[i] <= 0)
{
int16_t m_result = ((int16_t)tie->Q[qs].s8[i]*(int16_t)(*pax))>>ay;
tie->Q[qs].s8[i] = (int8_t)m_result;
} else
{
tie->Q[qs].s8[i] = tie->Q[qs].s8[i];
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qs].s16[i] <= 0)
{
int32_t m_result = ((int32_t)tie->Q[qs].s16[i]*(*pax))>>ay;
tie->Q[qs].s16[i] = (int16_t)m_result;
} else
{
tie->Q[qs].s16[i] = tie->Q[qs].s16[i];
}
}
}
}
static void translate_vrelu_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qs = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vrelu_s3(tcg_env, qs, arg[1].in, arg[2].in, op_type);
tcg_temp_free_i32(qs);
tcg_temp_free_i32(op_type);
}
void HELPER(vprelu_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t ay, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] <= 0)
{
int16_t m_result = ((int16_t)tie->Q[qx].s8[i]*(int16_t)tie->Q[qy].s8[i])>>ay;
tie->Q[qz].s8[i] = (int8_t)m_result;
} else
{
tie->Q[qz].s8[i] = tie->Q[qx].s8[i];
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] <= 0)
{
int32_t m_result = ((int32_t)tie->Q[qx].s16[i]*(int32_t)tie->Q[qy].s16[i])>>ay;
tie->Q[qz].s16[i] = (int16_t)m_result;
} else
{
tie->Q[qz].s16[i] = tie->Q[qx].s16[i];
}
}
}
}
static void translate_vprelu_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vprelu_s3(tcg_env, qz, qx, qy, arg[3].in, op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(op_type);
}
void HELPER(vmax_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] >= tie->Q[qy].s8[i])
{
tie->Q[qz].s8[i] = tie->Q[qx].s8[i];
} else
{
tie->Q[qz].s8[i] = tie->Q[qy].s8[i];
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] >= tie->Q[qy].s16[i])
{
tie->Q[qz].s16[i] = tie->Q[qx].s16[i];
} else
{
tie->Q[qz].s16[i] = tie->Q[qy].s16[i];
}
}
} else if (vmul_s32 == op_type)
{
for (int i = 0; i < 4; i++)
{
if (tie->Q[qx].s32[i] >= tie->Q[qy].s32[i])
{
tie->Q[qz].s32[i] = tie->Q[qx].s32[i];
} else
{
tie->Q[qz].s32[i] = tie->Q[qy].s32[i];
}
}
}
}
static void translate_vmax_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_inc16 == par[1])
{
start_index = 2;
if (ee_store_op == (ee_ldst_type)par[2])
{
store_qreg_to_memory(dc, arg);
}
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vmax_s3(tcg_env, qz, qx, qy, op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(op_type);
if (addr_inc16 == (Addr_Update)par[1])
{
if (ee_load_op == (ee_ldst_type)par[2])
{
// Load
load_qreg_from_memory(dc, arg);
}
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(vmin_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] <= tie->Q[qy].s8[i])
{
tie->Q[qz].s8[i] = tie->Q[qx].s8[i];
} else
{
tie->Q[qz].s8[i] = tie->Q[qy].s8[i];
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] <= tie->Q[qy].s16[i])
{
tie->Q[qz].s16[i] = tie->Q[qx].s16[i];
} else
{
tie->Q[qz].s16[i] = tie->Q[qy].s16[i];
}
}
} else if (vmul_s32 == op_type)
{
for (int i = 0; i < 4; i++)
{
if (tie->Q[qx].s32[i] <= tie->Q[qy].s32[i])
{
tie->Q[qz].s32[i] = tie->Q[qx].s32[i];
} else
{
tie->Q[qz].s32[i] = tie->Q[qy].s32[i];
}
}
}
}
static void translate_vmin_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int start_index = 0;
if (addr_inc16 == par[1])
{
start_index = 2;
if (ee_store_op == (ee_ldst_type)par[2])
{
store_qreg_to_memory(dc, arg);
}
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[start_index + 0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[start_index + 1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[start_index + 2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_vmin_s3(tcg_env, qz, qx, qy, op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(op_type);
if (addr_inc16 == (Addr_Update)par[1])
{
if (ee_load_op == (ee_ldst_type)par[2])
{
// Load
load_qreg_from_memory(dc, arg);
}
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
}
void HELPER(vcmp_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type, uint32_t op_sel)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (ee_vcmp_eq == op_sel)
{
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] == tie->Q[qy].s8[i])
{
tie->Q[qz].u8[i] = 0xff;
} else
{
tie->Q[qz].u8[i] = 0;
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] == tie->Q[qy].s16[i])
{
tie->Q[qz].u16[i] = 0xffff;
} else
{
tie->Q[qz].u16[i] = 0;
}
}
} else if (vmul_s32 == op_type)
{
for (int i = 0; i < 4; i++)
{
if (tie->Q[qx].s32[i] == tie->Q[qy].s32[i])
{
tie->Q[qz].u32[i] = 0xffffffff;
} else
{
tie->Q[qz].u32[i] = 0;
}
}
}
} else if (ee_vcmp_lt == op_sel)
{
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] < tie->Q[qy].s8[i])
{
tie->Q[qz].u8[i] = 0xff;
} else
{
tie->Q[qz].u8[i] = 0;
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] < tie->Q[qy].s16[i])
{
tie->Q[qz].u16[i] = 0xffff;
} else
{
tie->Q[qz].u16[i] = 0;
}
}
} else if (vmul_s32 == op_type)
{
for (int i = 0; i < 4; i++)
{
if (tie->Q[qx].s32[i] < tie->Q[qy].s32[i])
{
tie->Q[qz].u32[i] = 0xffffffff;
} else
{
tie->Q[qz].u32[i] = 0;
}
}
}
} else if (ee_vcmp_gt == op_sel)
{
if (vmul_s8 == op_type)
{
for (int i = 0; i < 16; i++)
{
if (tie->Q[qx].s8[i] > tie->Q[qy].s8[i])
{
tie->Q[qz].u8[i] = 0xff;
} else
{
tie->Q[qz].u8[i] = 0;
}
}
} else if (vmul_s16 == op_type)
{
for (int i = 0; i < 8; i++)
{
if (tie->Q[qx].s16[i] > tie->Q[qy].s16[i])
{
tie->Q[qz].u16[i] = 0xffff;
} else
{
tie->Q[qz].u16[i] = 0;
}
}
} else if (vmul_s32 == op_type)
{
for (int i = 0; i < 4; i++)
{
if (tie->Q[qx].s32[i] > tie->Q[qy].s32[i])
{
tie->Q[qz].u32[i] = 0xffffffff;
} else
{
tie->Q[qz].u32[i] = 0;
}
}
}
}
}
static void translate_vcmp_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 op_sel = tcg_constant_i32((uint32_t)par[1]);
gen_helper_vcmp_s3(tcg_env, qz, qx, qy, op_type, op_sel);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(op_sel);
}
void HELPER(bw_logic_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (bw_logic_or == op_type)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qz].u8[i] = tie->Q[qx].u8[i]|tie->Q[qy].u8[i];
}
}
else if (bw_logic_and == op_type)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qz].u8[i] = tie->Q[qx].u8[i]&tie->Q[qy].u8[i];
}
} else if (bw_logic_xor == op_type)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qz].u8[i] = tie->Q[qx].u8[i]^tie->Q[qy].u8[i];
}
} else if (bw_logic_not == op_type)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qz].u8[i] = ~tie->Q[qx].u8[i];
}
}
}
static void translate_bw_logic_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
int y_index = 2;
if (par[0] == bw_logic_not)
{
y_index = 1;
}
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[y_index].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_bw_logic_s3(tcg_env, qz, qx, qy, op_type);
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(op_type);
}
void HELPER(sxci_2q_s3)(CPUXtensaState *env, uint32_t qs0, uint32_t qs1, uint32_t sar, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int shift = sar + 1;
uint8_t temp_arr[32];
for (int i = 0; i < 16; i++)
{
temp_arr[i] = tie->Q[qs0].u8[i];
temp_arr[i+16] = tie->Q[qs1].u8[i];
}
if (bw_shift_left == op_type)
{
for (int i = 0; i < shift; i++)
{
tie->Q[qs0].u8[i] = 0;
}
for (int i = shift; i < 16; i++)
{
tie->Q[qs0].u8[i] = temp_arr[i - shift];
}
for (int i = 0; i < 16; i++)
{
tie->Q[qs1].u8[i] = temp_arr[16 - shift + i];
}
} else if (bw_shift_right == op_type)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qs0].u8[i] = temp_arr[i + shift];;
}
for (int i = 0; i < (16 - shift); i++)
{
tie->Q[qs1].u8[i] = temp_arr[i + shift + 16];
}
for (int i = (16 - shift); i < 16; i++)
{
tie->Q[qs1].u8[i] = 0;
}
}
}
static void translate_sxci_2q_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 sar = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_sxci_2q_s3(tcg_env, qs0, qs1, sar, op_type);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
tcg_temp_free_i32(sar);
tcg_temp_free_i32(op_type);
}
static void translate_sxcxxp_2q_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
gen_helper_sxci_2q_s3(tcg_env, qs0, qs1, arg[2].in, op_type);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
tcg_temp_free_i32(op_type);
tcg_gen_add_i32(arg[2].out, arg[2].in, arg[3].in);
}
uint64_t HELPER(srcq_64_rd_s3)(CPUXtensaState *env, uint32_t qs0, uint32_t qs1, uint32_t low_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = tie->Q[qs0].u64[low_high];
int shift = tie->SAR_BYTE;
uint8_t temp_arr[32];
for (int i = 0; i < 16; i++)
{
temp_arr[i] = tie->Q[qs0].u8[i];
temp_arr[i+16] = tie->Q[qs1].u8[i];
}
if (0 == low_high)
{
memcpy(&result, &temp_arr[shift], 8);
} else if (1 == low_high)
{
memcpy(&result, &temp_arr[shift + 8], 8);
}
return result;
}
static void translate_srcq_128_st_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[2].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_srcq_64_rd_s3(data, tcg_env, qs0, qs1, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
tcg_temp_free_i32(low_high);
}
tcg_gen_addi_i32(arg[2].out, arg[2].in, 16);
}
void HELPER(vsx32_s3)(CPUXtensaState *env, uint32_t qa, uint32_t qs, uint32_t sar, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
if (bw_shift_right == op_type)
{
for (int i = 0; i < 4; i++)
{
tie->Q[qa].s32[i] = tie->Q[qs].s32[i] >> sar;
}
}
if (bw_shift_left == op_type)
{
for (int i = 0; i < 4; i++)
{
tie->Q[qa].s32[i] = tie->Q[qs].s32[i] << sar;
}
}
}
static void translate_vsx32_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qa = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
if (dc->sar_m32_5bit)
{
gen_helper_vsx32_s3(tcg_env, qa, qs, dc->sar_m32, op_type);
}
else
{
gen_helper_vsx32_s3(tcg_env, qa, qs, cpu_SR[SAR], op_type);
}
tcg_temp_free_i32(qa);
tcg_temp_free_i32(qs);
tcg_temp_free_i32(op_type);
}
void HELPER(src_q_s3)(CPUXtensaState *env, uint32_t qa, uint32_t qs0, uint32_t qs1, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int sar_value = tie->SAR_BYTE;
/* Need a temp copy since qa may alias qs0 or qs1 */
Q_reg tmp;
for (int i = 0; i < (16 - sar_value); i++)
{
tmp.u8[i] = tie->Q[qs0].u8[i + sar_value];
}
for (int i = 0; i < sar_value; i++)
{
tmp.u8[16 - sar_value + i] = tie->Q[qs1].u8[i];
}
tie->Q[qa].u64[0] = tmp.u64[0];
tie->Q[qa].u64[1] = tmp.u64[1];
/* QUP variant: also copy qs1 → qs0 */
if (op_type == vmul_qup)
{
for (int i = 0; i < 16; i++)
{
tie->Q[qs0].u8[i] = tie->Q[qs1].u8[i];
}
}
}
static void translate_src_q_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
if (addr_nop == (Addr_Update)par[0])
{
TCGv_i32 qa = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[1]);
gen_helper_src_q_s3(tcg_env, qa, qs0, qs1, op_type);
tcg_temp_free_i32(qa);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
tcg_temp_free_i32(op_type);
} else
{
TCGv_i32 qs0 = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 qs1 = tcg_constant_i32((uint32_t)arg[4].imm);
gen_helper_vmulas_qup_s3(tcg_env, qs0, qs1);
tcg_temp_free_i32(qs0);
tcg_temp_free_i32(qs1);
if (addr_ip == (Addr_Update)par[0])
{
load_qreg_from_memory(dc, arg);
tcg_gen_addi_i32(arg[1].out, arg[1].in, arg[2].imm);
}
if (addr_xp == (Addr_Update)par[0])
{
load_qreg_from_memory(dc, arg);
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
}
}
}
uint64_t HELPER(r2bf_st_low_s3)(CPUXtensaState *env, uint32_t qa0, uint32_t qx, uint32_t qy, uint32_t sar4)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
for (int i = 0; i < 8; i++)
{
tie->Q[qa0].s16[i] = tie->Q[qx].s16[i] - tie->Q[qy].s16[i];
}
for (int i=0; i< 4 ; i++)
{
int32_t temp = (tie->Q[qx].s16[i] + tie->Q[qy].s16[i]) >> sar4;
ptr_result[i] = temp;
}
return result;
}
uint64_t HELPER(r2bf_st_high_s3)(CPUXtensaState *env, uint32_t qa0, uint32_t qx, uint32_t qy, uint32_t sar4)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
for (int i=0; i< 4 ; i++)
{
int32_t temp = (tie->Q[qx].s16[i + 4] + tie->Q[qy].s16[i + 4]) >> sar4;
ptr_result[i] = temp;
}
return result;
}
static void translate_r2bf_st_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qa0 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 sar4 = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 addr_low;
TCGv_i32 addr_high;
MemOp mop;
addr_low = tcg_temp_new_i32();
addr_high = tcg_temp_new_i32();
// We have to align to 128 bit memory
// Load low addr
tcg_gen_andi_i32(addr_low, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_low, addr_low, 0);
// Load high addr
tcg_gen_andi_i32(addr_high, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_high, addr_high, 8);
TCGv_i64 data_low = tcg_temp_new_i64();
TCGv_i64 data_high = tcg_temp_new_i64();
gen_helper_r2bf_st_low_s3(data_low, tcg_env, qa0, qx, qy, sar4);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_low);
tcg_gen_qemu_st_i64(data_low, addr_low, dc->cring, mop);
gen_helper_r2bf_st_high_s3(data_high, tcg_env, qa0, qx, qy, sar4);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_high);
tcg_gen_qemu_st_i64(data_high, addr_high, dc->cring, mop);
tcg_gen_addi_i32(arg[3].out, arg[3].in, 16);
tcg_temp_free_i64(data_low);
tcg_temp_free_i64(data_high);
tcg_temp_free_i32(addr_low);
tcg_temp_free_i32(addr_high);
tcg_temp_free_i32(qa0);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(sar4);
}
void HELPER(r2bf_s3)(CPUXtensaState *env, uint32_t qa0, uint32_t qa1, uint32_t qx, uint32_t qy, uint32_t sel2)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int16_t op_a[8];
int16_t op_b[8];
for (int i = 0; i < 8; i++)
{
op_a[i] = 0;
op_b[i] = 0;
}
if (sel2 == 0)
{
op_a[0] = tie->Q[qx].s16[0];
op_a[1] = tie->Q[qx].s16[1];
op_a[2] = tie->Q[qx].s16[2];
op_a[3] = tie->Q[qx].s16[3];
op_a[4] = tie->Q[qy].s16[0];
op_a[5] = tie->Q[qy].s16[1];
op_a[6] = tie->Q[qy].s16[2];
op_a[7] = tie->Q[qy].s16[3];
op_b[0] = tie->Q[qx].s16[4];
op_b[1] = tie->Q[qx].s16[5];
op_b[2] = tie->Q[qx].s16[6];
op_b[3] = tie->Q[qx].s16[7];
op_b[4] = tie->Q[qy].s16[4];
op_b[5] = tie->Q[qy].s16[5];
op_b[6] = tie->Q[qy].s16[6];
op_b[7] = tie->Q[qy].s16[7];
}
if (sel2 == 1)
{
op_a[0] = tie->Q[qx].s16[0];
op_a[1] = tie->Q[qx].s16[1];
op_a[2] = tie->Q[qx].s16[4];
op_a[3] = tie->Q[qx].s16[5];
op_a[4] = tie->Q[qy].s16[0];
op_a[5] = tie->Q[qy].s16[1];
op_a[6] = tie->Q[qy].s16[4];
op_a[7] = tie->Q[qy].s16[5];
op_b[0] = tie->Q[qx].s16[2];
op_b[1] = tie->Q[qx].s16[3];
op_b[2] = tie->Q[qx].s16[6];
op_b[3] = tie->Q[qx].s16[7];
op_b[4] = tie->Q[qy].s16[2];
op_b[5] = tie->Q[qy].s16[3];
op_b[6] = tie->Q[qy].s16[6];
op_b[7] = tie->Q[qy].s16[7];
}
tie->Q[qa0].s16[0] = op_a[0] + op_b[0];
tie->Q[qa0].s16[1] = op_a[1] + op_b[1];
tie->Q[qa0].s16[2] = op_a[2] + op_b[2];
tie->Q[qa0].s16[3] = op_a[3] + op_b[3];
tie->Q[qa0].s16[4] = op_a[0] - op_b[0];
tie->Q[qa0].s16[5] = op_a[1] - op_b[1];
tie->Q[qa0].s16[6] = op_a[2] - op_b[2];
tie->Q[qa0].s16[7] = op_a[3] - op_b[3];
tie->Q[qa1].s16[0] = op_a[4] + op_b[4];
tie->Q[qa1].s16[1] = op_a[5] + op_b[5];
tie->Q[qa1].s16[2] = op_a[6] + op_b[6];
tie->Q[qa1].s16[3] = op_a[7] + op_b[7];
tie->Q[qa1].s16[4] = op_a[4] - op_b[4];
tie->Q[qa1].s16[5] = op_a[5] - op_b[5];
tie->Q[qa1].s16[6] = op_a[6] - op_b[6];
tie->Q[qa1].s16[7] = op_a[7] - op_b[7];
}
static void translate_r2bf_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qa0 = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qa1 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 sel2 = tcg_constant_i32((uint32_t)arg[4].imm);
gen_helper_r2bf_s3(tcg_env, qa0, qa1, qx, qy, sel2);
tcg_temp_free_i32(qa0);
tcg_temp_free_i32(qa1);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(sel2);
}
void HELPER(fft_cmul_ld_s3)(CPUXtensaState *env, uint32_t qz, uint32_t qx, uint32_t qy, uint32_t sel8, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int64_t temp;
if (0 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1]);
tie->Q[qz].s16[0] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]);
tie->Q[qz].s16[1] = temp >> sar;
}
if (1 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1]);
tie->Q[qz].s16[0] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]);
tie->Q[qz].s16[1] = temp >> sar;
}
if (2 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3]);
tie->Q[qz].s16[2] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]);
tie->Q[qz].s16[3] = temp >> sar;
}
if (3 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3]);
tie->Q[qz].s16[2] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]);
tie->Q[qz].s16[3] = temp >> sar;
}
if (4 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[4]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[5]);
tie->Q[qz].s16[4] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[4]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[5]);
tie->Q[qz].s16[5] = temp >> sar;
}
if (5 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[4]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[5]);
tie->Q[qz].s16[4] = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[4]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[5]);
tie->Q[qz].s16[5] = temp >> sar;
}
}
static void translate_fft_cmul_ld_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 sel8 = tcg_constant_i32((uint32_t)arg[6].imm);
if (dc->sar_m32_5bit)
{
gen_helper_fft_cmul_ld_s3(tcg_env, qz, qx, qy, sel8, dc->sar_m32);
} else
{
gen_helper_fft_cmul_ld_s3(tcg_env, qz, qx, qy, sel8, cpu_SR[SAR]);
}
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(sel8);
// Update memory
load_qreg_from_memory(dc, arg);
tcg_gen_add_i32(arg[1].out, arg[1].in, arg[2].in);
}
// EE.FFT.CMUL.S16.ST.XP qx, qy, qv, as, ad, sel8, upd4, sar4,
uint64_t HELPER(fft_cmul_st_low_s3)(CPUXtensaState *env, uint32_t qx, uint32_t qy, uint32_t qv, uint32_t sel8, uint32_t upd4, uint32_t sar4, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* prt_result = (int16_t*)&result;
if (0 == upd4)
{
prt_result[0] = tie->Q[qv].s16[0];
prt_result[1] = tie->Q[qv].s16[1];
prt_result[2] = tie->Q[qv].s16[2];
prt_result[3] = tie->Q[qv].s16[3];
}
if (1 == upd4)
{
prt_result[0] = tie->Q[qx].s16[0]>>sar4;
prt_result[1] = tie->Q[qx].s16[1]>>sar4;
prt_result[2] = tie->Q[qx].s16[2]>>sar4;
prt_result[3] = tie->Q[qx].s16[3]>>sar4;
}
if (2 == upd4)
{
prt_result[0] = tie->Q[qx].s16[0]>>sar4;
prt_result[1] = tie->Q[qx].s16[1]>>sar4;
prt_result[2] = tie->Q[qv].s16[4];
prt_result[3] = tie->Q[qv].s16[5];
}
return result;
}
uint64_t HELPER(fft_cmul_st_high_s3)(CPUXtensaState *env, uint32_t qx, uint32_t qy, uint32_t qv, uint32_t sel8, uint32_t upd4, uint32_t sar4, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* prt_result = (int16_t*)&result;
int16_t temp0 = 0;
int16_t temp1 = 0;
int64_t temp = 0;
if (0 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]);
temp1 = temp >> sar;
}
if (1 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[0]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[1]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[1])*((int32_t)tie->Q[qy].s16[0]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[0])*((int32_t)tie->Q[qy].s16[1]);
temp1 = temp >> sar;
}
if (2 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]);
temp1 = temp >> sar;
}
if (3 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[2]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[3]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[3])*((int32_t)tie->Q[qy].s16[2]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[2])*((int32_t)tie->Q[qy].s16[3]);
temp1 = temp >> sar;
}
if (4 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[4]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[5]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[4]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[5]);
temp1 = temp >> sar;
}
if (5 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[4]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[5]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[5])*((int32_t)tie->Q[qy].s16[4]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[4])*((int32_t)tie->Q[qy].s16[5]);
temp1 = temp >> sar;
}
if (6 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[6])*((int32_t)tie->Q[qy].s16[6]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[7])*((int32_t)tie->Q[qy].s16[7]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[7])*((int32_t)tie->Q[qy].s16[6]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[6])*((int32_t)tie->Q[qy].s16[7]);
temp1 = temp >> sar;
}
if (7 == sel8)
{
temp = (int64_t)((int32_t)tie->Q[qx].s16[6])*((int32_t)tie->Q[qy].s16[6]);
temp -= (int64_t)((int32_t)tie->Q[qx].s16[7])*((int32_t)tie->Q[qy].s16[7]);
temp0 = temp >> sar;
temp = (int64_t)((int32_t)tie->Q[qx].s16[7])*((int32_t)tie->Q[qy].s16[6]);
temp += (int64_t)((int32_t)tie->Q[qx].s16[6])*((int32_t)tie->Q[qy].s16[7]);
temp1 = temp >> sar;
}
if (0 == upd4)
{
prt_result[0] = tie->Q[qv].s16[4];
prt_result[1] = tie->Q[qv].s16[5];
prt_result[2] = temp0;
prt_result[3] = temp1;
}
if (1 == upd4)
{
prt_result[0] = tie->Q[qv].s16[4];
prt_result[1] = tie->Q[qv].s16[5];
prt_result[2] = temp0;
prt_result[3] = temp1;
}
if (2 == upd4)
{
prt_result[0] = tie->Q[qx].s16[2]>>sar4;
prt_result[1] = tie->Q[qx].s16[3]>>sar4;
prt_result[2] = temp0;
prt_result[3] = temp1;
}
return result;
}
static void translate_fft_cmul_st_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qv = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 sel8 = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 upd4 = tcg_constant_i32((uint32_t)arg[6].imm);
TCGv_i32 sar4 = tcg_constant_i32((uint32_t)arg[7].imm);
TCGv_i32 addr_low;
TCGv_i32 addr_high;
MemOp mop;
addr_low = tcg_temp_new_i32();
addr_high = tcg_temp_new_i32();
// We have to align to 128 bit memory
// Load low addr
tcg_gen_andi_i32(addr_low, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_low, addr_low, 0);
// Load high addr
tcg_gen_andi_i32(addr_high, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_high, addr_high, 8);
TCGv_i64 data_low = tcg_temp_new_i64();
TCGv_i64 data_high = tcg_temp_new_i64();
if (dc->sar_m32_5bit)
{
gen_helper_fft_cmul_st_low_s3(data_low, tcg_env, qx, qy, qv, sel8, upd4, sar4, dc->sar_m32);
} else
{
gen_helper_fft_cmul_st_low_s3(data_low, tcg_env, qx, qy, qv, sel8, upd4, sar4, cpu_SR[SAR]);
}
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_low);
tcg_gen_qemu_st_i64(data_low, addr_low, dc->cring, mop);
if (dc->sar_m32_5bit)
{
gen_helper_fft_cmul_st_high_s3(data_high, tcg_env, qx, qy, qv, sel8, upd4, sar4, dc->sar_m32);
} else
{
gen_helper_fft_cmul_st_high_s3(data_high, tcg_env, qx, qy, qv, sel8, upd4, sar4, cpu_SR[SAR]);
}
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_high);
tcg_gen_qemu_st_i64(data_high, addr_high, dc->cring, mop);
tcg_temp_free_i64(data_low);
tcg_temp_free_i64(data_high);
tcg_temp_free_i32(addr_low);
tcg_temp_free_i32(addr_high);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(qv);
tcg_temp_free_i32(sar4);
tcg_gen_add_i32(arg[3].out, arg[3].in, arg[4].in);
}
static uint16_t reverse(uint16_t x, int order)
{
uint16_t result = 0;
for (int i = 0; i < order; i++)
{
if (x&(1<<i))
{
result |= 1<<(order - i - 1);
}
}
return result;
}
void HELPER(bitrev_s3)(CPUXtensaState *env, uint32_t qa, uint32_t as)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
for (int i = 0; i < 8; i++)
{
tie->Q[qa].u16[i] = as + i;
int16_t rev = reverse( as + i, tie->fft_width);
if (rev > tie->Q[qa].u16[i]) tie->Q[qa].u16[i] = rev;
}
}
static void translate_bitrev_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qa = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_bitrev_s3(tcg_env, qa, arg[1].in);
tcg_temp_free_i32(qa);
tcg_gen_addi_i32(arg[1].out, arg[1].in, 8);
}
void HELPER(fft_ams_s16)(CPUXtensaState *env, uint32_t qz, uint32_t qz1, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sel2, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int16_t temp0 = tie->Q[qx].s16[2] + tie->Q[qy].s16[2];
int16_t temp1 = tie->Q[qx].s16[3] - tie->Q[qy].s16[3];
int16_t temp2 = 0;
int16_t temp3 = 0;
if (0 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[2] - tie->Q[qy].s16[2])*(int32_t)tie->Q[qm].s16[2]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[3] + tie->Q[qy].s16[3])*(int32_t)tie->Q[qm].s16[3]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[2] - tie->Q[qy].s16[2])*(int32_t)tie->Q[qm].s16[3]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[3] + tie->Q[qy].s16[3])*(int32_t)tie->Q[qm].s16[2]);
temp3 = temp >> sar;
}
if (1 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[3] + tie->Q[qy].s16[3])*(int32_t)tie->Q[qm].s16[3]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[2] - tie->Q[qy].s16[2])*(int32_t)tie->Q[qm].s16[2]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[3] + tie->Q[qy].s16[3])*(int32_t)tie->Q[qm].s16[2]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[2] - tie->Q[qy].s16[2])*(int32_t)tie->Q[qm].s16[3]);
temp3 = temp >> sar;
}
tie->Q[qz].s16[2] = temp0 + temp2;
tie->Q[qz].s16[3] = temp1 + temp3;
tie->Q[qz1].s16[2] = temp0 - temp2;
tie->Q[qz1].s16[3] = temp3 - temp1;
}
static void translate_fft_ams_s16_ld_incp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 qz1 = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 qm = tcg_constant_i32((uint32_t)arg[6].imm);
TCGv_i32 sel2 = tcg_constant_i32((uint32_t)arg[7].imm);
if (dc->sar_m32_5bit)
{
gen_helper_fft_ams_s16(tcg_env, qz, qz1, qx, qy, qm, sel2, dc->sar_m32);
} else
{
gen_helper_fft_ams_s16(tcg_env, qz, qz1, qx, qy, qm, sel2, cpu_SR[SAR]);
}
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qz1);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(qm);
tcg_temp_free_i32(sel2);
// Load from memory
load_qreg_from_memory(dc, arg);
// incp
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
uint64_t HELPER(fft_ams_st_0_s16_low)(CPUXtensaState *env, uint32_t qv, uint32_t qz1, uint32_t as0, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
int16_t* ptr_as = (int16_t*)&as0;
ptr_result[0] =ptr_as[0]>>1;
ptr_result[1] =ptr_as[1]>>1;
ptr_result[2] = tie->Q[qv].s16[0] >> 1;
ptr_result[3] = tie->Q[qv].s16[1] >> 1;
return result;
}
uint64_t HELPER(fft_ams_st_0_s16_high)(CPUXtensaState *env, uint32_t qv, uint32_t qz1, uint32_t as0, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
ptr_result[0] = tie->Q[qv].s16[2] >> 1;
ptr_result[1] = tie->Q[qv].s16[3] >> 1;
ptr_result[2] = tie->Q[qv].s16[4] >> 1;
ptr_result[3] = tie->Q[qv].s16[5] >> 1;
int16_t temp0 = tie->Q[qx].s16[6] + tie->Q[qy].s16[6];
int16_t temp1 = tie->Q[qx].s16[7] - tie->Q[qy].s16[7];
int16_t temp2 = 0;
int16_t temp3 = 0;
int16_t temp4 = 0;
int16_t temp5 = 0;
int64_t temp;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[6] - tie->Q[qy].s16[6])*(int32_t)tie->Q[qm].s16[6]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[7] + tie->Q[qy].s16[7])*(int32_t)tie->Q[qm].s16[7]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[6] - tie->Q[qy].s16[6])*(int32_t)tie->Q[qm].s16[7]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[7] + tie->Q[qy].s16[7])*(int32_t)tie->Q[qm].s16[6]);
temp3 = temp >> sar;
temp4 = temp1 + temp3;
temp5 = temp0 + temp2;
tie->Q[qz1].s16[6] = temp0 - temp2;
tie->Q[qz1].s16[7] = temp3 - temp1;
tie->temp_asm[1] = temp4;
tie->temp_asm[0] = temp5;
return result;
}
uint64_t HELPER(fft_ams_st_1_s16_low)(CPUXtensaState *env, uint32_t qv, uint32_t qz1, uint32_t as0, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
int16_t* ptr_as = (int16_t*)&as0;
ptr_result[0] =ptr_as[0];
ptr_result[1] =ptr_as[1];
ptr_result[2] = tie->Q[qv].s16[0];
ptr_result[3] = tie->Q[qv].s16[1];
return result;
}
uint64_t HELPER(fft_ams_st_1_s16_high)(CPUXtensaState *env, uint32_t qv, uint32_t qz1, uint32_t as0, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint64_t result = 0;
int16_t* ptr_result = (int16_t*)&result;
ptr_result[0] = tie->Q[qv].s16[2];
ptr_result[1] = tie->Q[qv].s16[3];
ptr_result[2] = tie->Q[qv].s16[4];
ptr_result[3] = tie->Q[qv].s16[5];
int16_t temp0 = tie->Q[qx].s16[6] + tie->Q[qy].s16[6];
int16_t temp1 = tie->Q[qx].s16[7] - tie->Q[qy].s16[7];
int16_t temp2 = 0;
int16_t temp3 = 0;
int16_t temp4 = 0;
int16_t temp5 = 0;
int64_t temp;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[7] + tie->Q[qy].s16[7])*(int32_t)tie->Q[qm].s16[7]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[6] - tie->Q[qy].s16[6])*(int32_t)tie->Q[qm].s16[6]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[7] + tie->Q[qy].s16[7])*(int32_t)tie->Q[qm].s16[6]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[6] - tie->Q[qy].s16[6])*(int32_t)tie->Q[qm].s16[7]);
temp3 = temp >> sar;
temp4 = temp1 + temp3;
temp5 = temp0 + temp2;
tie->Q[qz1].s16[6] = temp0 - temp2;
tie->Q[qz1].s16[7] = temp3 - temp1;
tie->temp_asm[1] = temp4;
tie->temp_asm[0] = temp5;
return result;
}
uint32_t HELPER(fft_ams_st_s16_at)(CPUXtensaState *env)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint32_t result = 0;
memcpy(&result, tie->temp_asm, sizeof(uint32_t));
return result;
}
static void translate_fft_ams_s16_st_incp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qv = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 qz1 = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 qm = tcg_constant_i32((uint32_t)arg[6].imm);
TCGv_i64 data_low = tcg_temp_new_i64();
TCGv_i64 data_high = tcg_temp_new_i64();
if ((uint32_t)arg[7].imm == 0)
{
if (dc->sar_m32_5bit)
{
gen_helper_fft_ams_st_0_s16_low(data_low, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, dc->sar_m32);
gen_helper_fft_ams_st_0_s16_high(data_high, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, dc->sar_m32);
} else
{
gen_helper_fft_ams_st_0_s16_low(data_low, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, cpu_SR[SAR]);
gen_helper_fft_ams_st_0_s16_high(data_high, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, cpu_SR[SAR]);
}
} else
{
if (dc->sar_m32_5bit)
{
gen_helper_fft_ams_st_1_s16_low(data_low, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, dc->sar_m32);
gen_helper_fft_ams_st_1_s16_high(data_high, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, dc->sar_m32);
} else
{
gen_helper_fft_ams_st_1_s16_low(data_low, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, cpu_SR[SAR]);
gen_helper_fft_ams_st_1_s16_high(data_high, tcg_env, qv, qz1, arg[2].in, qx, qy, qm, cpu_SR[SAR]);
}
}
tcg_temp_free_i32(qv);
tcg_temp_free_i32(qz1);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(qm);
TCGv_i32 addr_low;
TCGv_i32 addr_high;
MemOp mop;
addr_low = tcg_temp_new_i32();
addr_high = tcg_temp_new_i32();
// We have to align to 128 bit memory
// Load low addr
tcg_gen_andi_i32(addr_low, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_low, addr_low, 0);
// Load high addr
tcg_gen_andi_i32(addr_high, arg[3].in, 0xfffffff0);
tcg_gen_addi_i32(addr_high, addr_high, 8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_low);
tcg_gen_qemu_st_i64(data_low, addr_low, dc->cring, mop);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_high);
tcg_gen_qemu_st_i64(data_high, addr_high, dc->cring, mop);
tcg_temp_free_i64(data_low);
tcg_temp_free_i64(data_high);
// Load from memory
TCGv_i32 data_as = tcg_temp_new_i32();
gen_helper_fft_ams_st_s16_at(data_as, tcg_env);
tcg_gen_mov_i32(arg[2].out, data_as);
tcg_temp_free_i32(data_as);
// incp
tcg_gen_addi_i32(arg[3].out, arg[3].in, 16);
}
void HELPER(fft_ams_s16_uqup)(CPUXtensaState *env, uint32_t qz, uint32_t qz1, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sel2, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int16_t temp0 = tie->Q[qx].s16[0] + tie->Q[qy].s16[0];
int16_t temp1 = tie->Q[qx].s16[1] - tie->Q[qy].s16[1];
int16_t temp2 = 0;
int16_t temp3 = 0;
if (0 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[0] - tie->Q[qy].s16[0])*(int32_t)tie->Q[qm].s16[0]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[1] + tie->Q[qy].s16[1])*(int32_t)tie->Q[qm].s16[1]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[0] - tie->Q[qy].s16[0])*(int32_t)tie->Q[qm].s16[1]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[1] + tie->Q[qy].s16[1])*(int32_t)tie->Q[qm].s16[0]);
temp3 = temp >> sar;
}
if (1 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[1] + tie->Q[qy].s16[1])*(int32_t)tie->Q[qm].s16[1]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[0] - tie->Q[qy].s16[0])*(int32_t)tie->Q[qm].s16[0]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[1] + tie->Q[qy].s16[1])*(int32_t)tie->Q[qm].s16[0]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[0] - tie->Q[qy].s16[0])*(int32_t)tie->Q[qm].s16[1]);
temp3 = temp >> sar;
}
tie->Q[qz].s16[0] = temp0 + temp2;
tie->Q[qz].s16[1] = temp1 + temp3;
tie->Q[qz1].s16[0] = temp0 - temp2;
tie->Q[qz1].s16[1] = temp3 - temp1;
}
void HELPER(fft_ams_s16_ld_incp_uaup)(CPUXtensaState *env, uint32_t qu, uint64_t data_low, uint64_t data_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint8_t inData[32];
memcpy(&inData[0], tie->UA_STATE.u8, 16);
memcpy(&inData[16], &data_low, 8);
memcpy(&inData[16 + 8], &data_high, 8);
int shift = tie->SAR_BYTE;
for (int i=0 ; i< 16; i++)
{
tie->Q[qu].u8[i] = inData[i + shift];
}
memcpy(tie->UA_STATE.u8, &inData[16], 16);
}
static void translate_fft_ams_s16_ld_incp_uaup(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 qz1 = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 qm = tcg_constant_i32((uint32_t)arg[6].imm);
TCGv_i32 sel2 = tcg_constant_i32((uint32_t)arg[7].imm);
if (dc->sar_m32_5bit)
{
gen_helper_fft_ams_s16_uqup(tcg_env, qz, qz1, qx, qy, qm, sel2, dc->sar_m32);
} else
{
gen_helper_fft_ams_s16_uqup(tcg_env, qz, qz1, qx, qy, qm, sel2, cpu_SR[SAR]);
}
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qz1);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(qm);
tcg_temp_free_i32(sel2);
// Load q and ua_state from memory
{
TCGv_i32 addr_low = tcg_temp_new_i32();
TCGv_i32 addr_high = tcg_temp_new_i32();
MemOp mop_low;
MemOp mop_high;
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr_low, arg[1].in, 0xfffffff0);
tcg_gen_andi_i32(addr_high, arg[1].in, 0xfffffff0);
tcg_gen_addi_i32(addr_high, addr_high, 8);
mop_low = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_low);
mop_high = gen_load_store_alignment(dc, MO_64 | MO_TE, addr_high);
// Read data from memory
TCGv_i64 data_low = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(data_low, addr_low, dc->cring, mop_low);
TCGv_i64 data_high = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(data_high, addr_high, dc->cring, mop_high);
TCGv_i32 qu = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_fft_ams_s16_ld_incp_uaup(tcg_env, qu, data_low, data_high);
tcg_temp_free_i32(addr_low);
tcg_temp_free_i32(addr_high);
tcg_temp_free_i64(data_low);
tcg_temp_free_i64(data_high);
tcg_temp_free_i32(qu);
}
// incp
tcg_gen_addi_i32(arg[1].out, arg[1].in, 16);
}
void HELPER(fft_ams_s16_decp)(CPUXtensaState *env, uint32_t qz, uint32_t qz1, uint32_t qx, uint32_t qy, uint32_t qm, uint32_t sel2, uint32_t sar)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int16_t temp0 = tie->Q[qx].s16[4] + tie->Q[qy].s16[4];
int16_t temp1 = tie->Q[qx].s16[5] - tie->Q[qy].s16[5];
int16_t temp2 = 0;
int16_t temp3 = 0;
if (0 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[4] - tie->Q[qy].s16[4])*(int32_t)tie->Q[qm].s16[4]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[5] + tie->Q[qy].s16[5])*(int32_t)tie->Q[qm].s16[5]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[4] - tie->Q[qy].s16[4])*(int32_t)tie->Q[qm].s16[5]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[5] + tie->Q[qy].s16[5])*(int32_t)tie->Q[qm].s16[4]);
temp3 = temp >> sar;
}
if (1 == sel2)
{
int64_t temp = (int64_t)((int32_t)(tie->Q[qx].s16[5] + tie->Q[qy].s16[5])*(int32_t)tie->Q[qm].s16[5]);
temp += (int64_t)((int32_t)(tie->Q[qx].s16[4] - tie->Q[qy].s16[4])*(int32_t)tie->Q[qm].s16[4]);
temp2 = temp >> sar;
temp = (int64_t)((int32_t)(tie->Q[qx].s16[5] + tie->Q[qy].s16[5])*(int32_t)tie->Q[qm].s16[4]);
temp -= (int64_t)((int32_t)(tie->Q[qx].s16[4] - tie->Q[qy].s16[4])*(int32_t)tie->Q[qm].s16[5]);
temp3 = temp >> sar;
}
tie->Q[qz].s16[4] = temp0 + temp2;
tie->Q[qz].s16[5] = temp1 + temp3;
tie->Q[qz1].s16[4] = temp0 - temp2;
tie->Q[qz1].s16[5] = temp3 - temp1;
}
void HELPER(fft_ams_s16_exchange_q)(CPUXtensaState *env, uint32_t qu)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int32_t temp;
temp = tie->Q[qu].s32[0];
tie->Q[qu].s32[0] = tie->Q[qu].s32[3];
tie->Q[qu].s32[3] = temp;
temp = tie->Q[qu].s32[1];
tie->Q[qu].s32[1] = tie->Q[qu].s32[2];
tie->Q[qu].s32[2] = temp;
}
static void translate_fft_ams_s16_ld_decp(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 qz = tcg_constant_i32((uint32_t)arg[2].imm);
TCGv_i32 qz1 = tcg_constant_i32((uint32_t)arg[3].imm);
TCGv_i32 qx = tcg_constant_i32((uint32_t)arg[4].imm);
TCGv_i32 qy = tcg_constant_i32((uint32_t)arg[5].imm);
TCGv_i32 qm = tcg_constant_i32((uint32_t)arg[6].imm);
TCGv_i32 sel2 = tcg_constant_i32((uint32_t)arg[7].imm);
if (dc->sar_m32_5bit)
{
gen_helper_fft_ams_s16_decp(tcg_env, qz, qz1, qx, qy, qm, sel2, dc->sar_m32);
} else
{
gen_helper_fft_ams_s16_decp(tcg_env, qz, qz1, qx, qy, qm, sel2, cpu_SR[SAR]);
}
tcg_temp_free_i32(qz);
tcg_temp_free_i32(qz1);
tcg_temp_free_i32(qx);
tcg_temp_free_i32(qy);
tcg_temp_free_i32(qm);
tcg_temp_free_i32(sel2);
// Load from memory
load_qreg_from_memory(dc, arg);
TCGv_i32 qu = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_fft_ams_s16_exchange_q(tcg_env, qu);
tcg_temp_free_i32(qu);
// incp
tcg_gen_subi_i32(arg[1].out, arg[1].in, 16);
}
uint32_t HELPER(wr_mask_gpio_out_s3)(CPUXtensaState *env, uint32_t as, uint32_t ax, uint32_t op_type)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint32_t result = 0;
if (gpio_mask == op_type)
{
tie->gpio_out = (tie->gpio_out &~ax) | (as & ax);
}
if (gpio_set == op_type)
{
tie->gpio_out = (tie->gpio_out | as);
}
if (gpio_clr == op_type)
{
tie->gpio_out = (tie->gpio_out & ~as);
}
if (gpio_in == op_type)
{
result = tie->gpio_out;
}
return result;
}
static void translate_wr_mask_gpio_out_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 data = tcg_temp_new_i32();
if (gpio_mask == (uint32_t)par[0])
{
gen_helper_wr_mask_gpio_out_s3(data, tcg_env, arg[0].in, arg[1].in, op_type);
} else if ((gpio_set == (uint32_t)par[0]) | (gpio_clr == (uint32_t)par[0]))
{
TCGv_i32 as = tcg_constant_i32((uint32_t)arg[0].imm);
gen_helper_wr_mask_gpio_out_s3(data, tcg_env, as, op_type, op_type);
tcg_temp_free_i32(as);
} else
{
gen_helper_wr_mask_gpio_out_s3(data, tcg_env, op_type, op_type, op_type);
tcg_gen_mov_i32(arg[0].out, data);
}
tcg_temp_free_i32(op_type);
tcg_temp_free_i32(data);
}
void HELPER(ld_accx_s3)(CPUXtensaState *env, uint64_t data)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
tie->ACCX = data & 0x000000ffffffffff;
return;
}
static void translate_ld_accx_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
// We have to align to 64 bit memory
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
gen_helper_ld_accx_s3(tcg_env, data);
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
}
uint32_t HELPER(srs_accx_s3)(CPUXtensaState *env, uint32_t shift)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
uint32_t result = 0;
// tie->ACCX = (tie->ACCX&0x000000ffffffffff) >> shift;
tie->ACCX = tie->ACCX >> shift;
result = (uint32_t)tie->ACCX;
// printf("srs_accx_s3 = %i\n", result);
return result;
}
static void translate_srs_accx_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 shift = tcg_temp_new_i32();
tcg_gen_andi_i32(shift, arg[1].in, 0x3f);
gen_helper_srs_accx_s3(arg[0].out, tcg_env, shift);
tcg_temp_free_i32(shift);
}
static void translate_ld_qacc_x_h_32_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 addr = tcg_temp_new_i32();
// We have to align to 32 bit memory
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffffc);
MemOp mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
TCGv_i32 data = tcg_temp_new_i32();
// Read data from memory
tcg_gen_qemu_ld_i32(data, addr, dc->cring, mop);
gen_helper_ld_qacc_x_h_32_ip_s3(tcg_env, data, op_type);
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i32(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(op_type);
}
void HELPER(ld_qacc_x_h_32_ip_s3)(CPUXtensaState *env, uint32_t data, uint32_t op_type)
{
// printf("ld_qacc_x_h_32_ip_s3 data = %8.8x, type = %i\n", data, op_type);
ACCQ_reg *qacc = cpu_qacc_ptr(env, 1);
if (op_type == wrur_qacc_l_0)
{
qacc = cpu_qacc_ptr(env, 0);
}
uint8_t* data_ptr = (uint8_t*)&data;
qacc->u8[16] = data_ptr[0];
qacc->u8[17] = data_ptr[1];
qacc->u8[18] = data_ptr[2];
qacc->u8[19] = data_ptr[3];
}
void HELPER(ld_qacc_x_l_128_ip_s3)(CPUXtensaState *env, uint32_t op_type, uint32_t index, uint64_t data)
{
ACCQ_reg *qacc = cpu_qacc_ptr(env, 1);
if (op_type == wrur_qacc_l_0)
{
qacc = cpu_qacc_ptr(env, 0);
}
uint8_t* data_ptr = (uint8_t*)&data;
for (int i=0 ; i< 8 ; i++)
{
qacc->u8[i + index*8] = data_ptr[i];
}
}
/* Store upper 32 bits of QACC_H or QACC_L to memory */
uint32_t HELPER(st_qacc_x_h_32_ip_s3)(CPUXtensaState *env, uint32_t op_type)
{
ACCQ_reg *qacc = cpu_qacc_ptr(env, 1);
if (op_type == wrur_qacc_l_0)
{
qacc = cpu_qacc_ptr(env, 0);
}
uint32_t data;
uint8_t* data_ptr = (uint8_t*)&data;
data_ptr[0] = qacc->u8[16];
data_ptr[1] = qacc->u8[17];
data_ptr[2] = qacc->u8[18];
data_ptr[3] = qacc->u8[19];
return data;
}
/* Store lower 128 bits of QACC_H or QACC_L to memory (64-bit chunk) */
uint64_t HELPER(st_qacc_x_l_128_ip_s3)(CPUXtensaState *env, uint32_t op_type, uint32_t index)
{
ACCQ_reg *qacc = cpu_qacc_ptr(env, 1);
if (op_type == wrur_qacc_l_0)
{
qacc = cpu_qacc_ptr(env, 0);
}
uint64_t data;
uint8_t* data_ptr = (uint8_t*)&data;
for (int i = 0; i < 8; i++)
{
data_ptr[i] = qacc->u8[i + index * 8];
}
return data;
}
static void translate_st_qacc_x_h_32_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
TCGv_i32 addr = tcg_temp_new_i32();
// Align to 32 bit
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffffc);
MemOp mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
TCGv_i32 data = tcg_temp_new_i32();
gen_helper_st_qacc_x_h_32_ip_s3(data, tcg_env, op_type);
tcg_gen_qemu_st_i32(data, addr, dc->cring, mop);
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i32(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(op_type);
}
static void translate_st_qacc_x_l_128_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// Align to 128 bit
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
TCGv_i32 index = tcg_constant_i32(i);
gen_helper_st_qacc_x_l_128_ip_s3(data, tcg_env, op_type, index);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
}
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i32(op_type);
}
static void translate_ld_qacc_x_l_128_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 op_type = tcg_constant_i32((uint32_t)par[0]);
for (int i=0 ; i < 2 ; i++)
{
TCGv_i32 addr;
MemOp mop;
addr = tcg_temp_new_i32();
// We have to align to 128 bit memory
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i*8);
mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
// Read data from memory
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 index = tcg_constant_i32(i);
gen_helper_ld_qacc_x_l_128_ip_s3(tcg_env, op_type, index, data);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(index);
}
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i32(op_type);
}
/* EE.ST.ACCX.IP: store ACCX (40-bit, zero-extended to 64-bit) to memory */
uint64_t HELPER(st_accx_s3)(CPUXtensaState *env)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return (uint64_t)(tie->ACCX & 0x000000ffffffffffULL);
}
static void translate_st_accx_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
/* Align to 8 bytes */
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
gen_helper_st_accx_s3(data, tcg_env);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
}
/* EE.LD.UA_STATE.IP: load 128-bit UA_STATE from memory */
void HELPER(ld_ua_state_s3)(CPUXtensaState *env, uint64_t data, uint32_t low_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
tie->UA_STATE.u64[low_high] = data;
}
static void translate_ld_ua_state_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr = tcg_temp_new_i32();
/* Align to 16 bytes */
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(data, addr, dc->cring, mop);
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_ld_ua_state_s3(tcg_env, data, low_high);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(low_high);
}
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
}
/* EE.ST.UA_STATE.IP: store 128-bit UA_STATE to memory */
uint64_t HELPER(st_ua_state_s3)(CPUXtensaState *env, uint32_t low_high)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return tie->UA_STATE.u64[low_high];
}
static void translate_st_ua_state_ip_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
for (int i = 0; i < 2; i++)
{
TCGv_i32 addr = tcg_temp_new_i32();
/* Align to 16 bytes */
tcg_gen_andi_i32(addr, arg[0].in, 0xfffffff0);
tcg_gen_addi_i32(addr, addr, i * 8);
MemOp mop = gen_load_store_alignment(dc, MO_64 | MO_TE, addr);
TCGv_i64 data = tcg_temp_new_i64();
TCGv_i32 low_high = tcg_constant_i32(i);
gen_helper_st_ua_state_s3(data, tcg_env, low_high);
tcg_gen_qemu_st_i64(data, addr, dc->cring, mop);
tcg_temp_free_i64(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(low_high);
}
tcg_gen_addi_i32(arg[0].out, arg[0].in, arg[1].imm);
}
/* EE.LDXQ.32: indexed load 32-bit into Q register segment */
void HELPER(ldxq_32_s3)(CPUXtensaState *env, uint32_t qu, uint32_t sel4, uint32_t data)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
tie->Q[qu].u32[sel4] = data;
}
static void translate_ldxq_32_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
/* EE.LDXQ.32 qu, qs, as, sel4, sel8 */
/* arg[0]=qu, arg[1]=qs, arg[2]=as, arg[3]=sel4(imm), arg[4]=sel8(imm) */
uint32_t sel8 = (uint32_t)arg[4].imm;
uint32_t sel4 = (uint32_t)arg[3].imm;
/* Compute address: as + sign_extend(qs.s16[sel8]) * 4 - 4, aligned to 4 */
TCGv_i32 qs_idx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 sel8_val = tcg_constant_i32(sel8);
TCGv_i32 offset = tcg_temp_new_i32();
gen_helper_ldstxq_addr_s3(offset, tcg_env, qs_idx, sel8_val);
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_add_i32(addr, arg[2].in, offset);
tcg_gen_andi_i32(addr, addr, 0xfffffffc);
MemOp mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
TCGv_i32 data = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(data, addr, dc->cring, mop);
TCGv_i32 qu_idx = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 sel4_val = tcg_constant_i32(sel4);
gen_helper_ldxq_32_s3(tcg_env, qu_idx, sel4_val, data);
tcg_temp_free_i32(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(offset);
tcg_temp_free_i32(qs_idx);
tcg_temp_free_i32(sel8_val);
tcg_temp_free_i32(qu_idx);
tcg_temp_free_i32(sel4_val);
}
/* EE.STXQ.32: indexed store 32-bit from Q register segment */
uint32_t HELPER(stxq_32_s3)(CPUXtensaState *env, uint32_t qv, uint32_t sel4)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
return tie->Q[qv].u32[sel4];
}
/* Helper to compute address offset: sign_extend(qs.s16[sel8]) * 4 - 4 */
uint32_t HELPER(ldstxq_addr_s3)(CPUXtensaState *env, uint32_t qs, uint32_t sel8)
{
CPUXtensaEsp32s3State* tie = (CPUXtensaEsp32s3State*)(env->ext);
int32_t offset = (int32_t)tie->Q[qs].s16[sel8];
return offset * 4 - 4;
}
static void translate_stxq_32_s3(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[])
{
/* EE.STXQ.32 qv, qs, as, sel4, sel8 */
/* arg[0]=qv, arg[1]=qs, arg[2]=as, arg[3]=sel4(imm), arg[4]=sel8(imm) */
uint32_t sel8 = (uint32_t)arg[4].imm;
uint32_t sel4 = (uint32_t)arg[3].imm;
/* Get data to store */
TCGv_i32 qv_idx = tcg_constant_i32((uint32_t)arg[0].imm);
TCGv_i32 sel4_val = tcg_constant_i32(sel4);
TCGv_i32 data = tcg_temp_new_i32();
gen_helper_stxq_32_s3(data, tcg_env, qv_idx, sel4_val);
/* Compute address: as + sign_extend(qs.s16[sel8]) * 4 - 4, aligned to 4 */
TCGv_i32 qs_idx = tcg_constant_i32((uint32_t)arg[1].imm);
TCGv_i32 sel8_val = tcg_constant_i32(sel8);
TCGv_i32 offset = tcg_temp_new_i32();
gen_helper_ldstxq_addr_s3(offset, tcg_env, qs_idx, sel8_val);
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_add_i32(addr, arg[2].in, offset);
tcg_gen_andi_i32(addr, addr, 0xfffffffc);
MemOp mop = gen_load_store_alignment(dc, MO_32 | MO_TE, addr);
tcg_gen_qemu_st_i32(data, addr, dc->cring, mop);
tcg_temp_free_i32(data);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(offset);
tcg_temp_free_i32(qv_idx);
tcg_temp_free_i32(sel4_val);
tcg_temp_free_i32(qs_idx);
tcg_temp_free_i32(sel8_val);
}
static const XtensaOpcodeOps tie_ops[] = {
// VLD.L/H.64.ip/xp
{
.name = "ee.vld.l.64.ip",
.translate = translate_vld_64_s3,
.par = (const uint32_t[]){addr_ip, false},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vld.h.64.ip",
.translate = translate_vld_64_s3,
.par = (const uint32_t[]){addr_ip, true},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vld.l.64.xp",
.translate = translate_vld_64_s3,
.par = (const uint32_t[]){addr_xp, false},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vld.h.64.xp",
.translate = translate_vld_64_s3,
.par = (const uint32_t[]){addr_xp, true},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VLD 128 bit
{
.name = "ee.vld.128.ip",
.translate = translate_vld_128_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vld.128.xp",
.translate = translate_vld_128_s3,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// LD.USAR.128
{
.name = "ee.ld.128.usar.ip",
.translate = translate_ld_usar_128_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ld.128.usar.xp",
.translate = translate_ld_usar_128_s3,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// LDQA.[U/S].[8/16].[IP/XP]
{
.name = "ee.ldqa.u8.128.ip",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_ip, ldqa_u8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.u16.128.ip",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_ip, ldqa_u16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.s8.128.ip",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_ip, ldqa_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.s16.128.ip",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_ip, ldqa_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.u8.128.xp",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_xp, ldqa_u8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.u16.128.xp",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_xp, ldqa_u16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.s8.128.xp",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_xp, ldqa_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ldqa.s16.128.xp",
.translate = translate_ldqa_128_s3,
.par = (const uint32_t[]){addr_xp, ldqa_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VLDBC 8/16/32 bit (bare, no address update)
{
.name = "ee.vldbc.8",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_nop, vldbc_8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.16",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_nop, vldbc_16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.32",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_nop, vldbc_32},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VLDBC 8/16/32 bit (with address post-update)
{
.name = "ee.vldbc.8.ip",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_ip, vldbc_8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.8.xp",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_xp, vldbc_8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.16.ip",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_ip, vldbc_16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.16.xp",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_xp, vldbc_16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.32.ip",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_ip, vldbc_32},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vldbc.32.xp",
.translate = translate_vldbc_s3,
.par = (const uint32_t[]){addr_xp, vldbc_32},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// vldhbc:
{
.name = "ee.vldhbc.16.incp",
.translate = translate_vldhbc_s3,
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// store operations:
{
.name = "ee.vst.l.64.ip",
.translate = translate_vst_64_s3,
.par = (const uint32_t[]){addr_ip, false},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vst.h.64.ip",
.translate = translate_vst_64_s3,
.par = (const uint32_t[]){addr_ip, true},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vst.l.64.xp",
.translate = translate_vst_64_s3,
.par = (const uint32_t[]){addr_xp, false},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vst.h.64.xp",
.translate = translate_vst_64_s3,
.par = (const uint32_t[]){addr_xp, true},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vst.128.ip",
.translate = translate_vst_128_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vst.128.xp",
.translate = translate_vst_128_s3,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// LDF/STF operations:
{
.name = "ee.ldf.128.ip",
.translate = translate_ldf_128_ip,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.stf.128.ip",
.translate = translate_stf_128_ip,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.ldf.64.ip",
.translate = translate_ldf_64_ip,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.stf.64.ip",
.translate = translate_stf_64_ip,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.ldf.128.xp",
.translate = translate_ldf_128_xp,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.stf.128.xp",
.translate = translate_stf_128_xp,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.ldf.64.xp",
.translate = translate_ldf_64_xp,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.stf.64.xp",
.translate = translate_stf_64_xp,
.par = (const uint32_t[]){addr_xp},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
// Set to zero or dump
{
.name = "ee.zero.qacc",
.translate = translate_zero,
.par = (const uint32_t[]){ee_zero_qacc},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.zero.accx",
.translate = translate_zero,
.par = (const uint32_t[]){ee_zero_accx},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.zero.q",
.translate = translate_zero,
.par = (const uint32_t[]){ee_zero_qx},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// WUR operations
{
.name = "wur.accx_0",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_accx_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.accx_1",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_accx_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_l_0",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_l_1",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_l_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_l_2",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_l_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_l_3",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_l_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_l_4",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_l_4},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_h_0",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_h_1",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_h_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_h_2",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_h_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_h_3",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_h_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.qacc_h_4",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_qacc_h_4},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.gpio_out",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_gpio_out},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.sar_byte",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_sar_byte},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.fft_bit_width",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_fft_bit_width},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.ua_state_0",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_ua_state_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.ua_state_1",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_ua_state_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.ua_state_2",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_ua_state_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "wur.ua_state_3",
.translate = translate_wur,
.par = (const uint32_t[]){wrur_ua_state_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// RUR operations
{
.name = "rur.accx_0",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_accx_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.accx_1",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_accx_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_l_0",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_l_1",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_l_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_l_2",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_l_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_l_3",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_l_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_l_4",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_l_4},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_h_0",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_h_1",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_h_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_h_2",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_h_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_h_3",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_h_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.qacc_h_4",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_qacc_h_4},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.gpio_out",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_gpio_out},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.sar_byte",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_sar_byte},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.fft_bit_width",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_fft_bit_width},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.ua_state_0",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_ua_state_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.ua_state_1",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_ua_state_1},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.ua_state_2",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_ua_state_2},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "rur.ua_state_3",
.translate = translate_rur,
.par = (const uint32_t[]){wrur_ua_state_3},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Data exchange:
// ee.mov.[u/s][8/16].qacc qx
{
.name = "ee.mov.u8.qacc",
.translate = translate_mov_qacc_s3,
.par = (const uint32_t[]){ldqa_u8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.mov.s8.qacc",
.translate = translate_mov_qacc_s3,
.par = (const uint32_t[]){ldqa_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.mov.u16.qacc",
.translate = translate_mov_qacc_s3,
.par = (const uint32_t[]){ldqa_u16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.mov.s16.qacc",
.translate = translate_mov_qacc_s3,
.par = (const uint32_t[]){ldqa_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// movi.a/q
{
.name = "ee.movi.32.a",
.translate = translate_movi_s3,
.par = (const uint32_t[]){ee_movi_a},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.movi.32.q",
.translate = translate_movi_s3,
.par = (const uint32_t[]){ee_movi_q},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// vzip/vunzip
{
.name = "ee.vzip.8",
.translate = translate_zip_s3,
.par = (const uint32_t[]){0, vldbc_8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vzip.16",
.translate = translate_zip_s3,
.par = (const uint32_t[]){0, vldbc_16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vzip.32",
.translate = translate_zip_s3,
.par = (const uint32_t[]){0, vldbc_32},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vunzip.8",
.translate = translate_zip_s3,
.par = (const uint32_t[]){1, vldbc_8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vunzip.16",
.translate = translate_zip_s3,
.par = (const uint32_t[]){1, vldbc_16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vunzip.32",
.translate = translate_zip_s3,
.par = (const uint32_t[]){1, vldbc_32},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Arithmetic instructions...
// VADDS ...
// VADDS.s[8/16/32] qz,qx,qy
{
.name = "ee.vadds.s8",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_nop, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s16",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_nop, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s32",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_nop, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VADDS.s[8/16/32].LD.INCP qz,qx,qy
{
.name = "ee.vadds.s8.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_inc16, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s16.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_inc16, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s32.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_inc16, ee_load_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VADDS.s[8/16/32].ST.INCP qz,qx,qy
{
.name = "ee.vadds.s8.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_inc16, ee_store_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s16.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_inc16, ee_store_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vadds.s32.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_inc16, ee_store_op, ee_add_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VSUBS ...
// VSUBS.s[8/16/32] qz,qx,qy
{
.name = "ee.vsubs.s8",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_nop, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s16",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_nop, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s32",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_nop, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VSUBS.s[8/16/32].LD.INCP qz,qx,qy
{
.name = "ee.vsubs.s8.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_inc16, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s16.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_inc16, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s32.ld.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_inc16, ee_load_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VSUBS.s[8/16/32].ST.INCP qz,qx,qy
{
.name = "ee.vsubs.s8.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s8, addr_inc16, ee_store_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s16.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s16, addr_inc16, ee_store_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsubs.s32.st.incp",
.translate = translate_vadds_s3,
.par = (const uint32_t[]){ldqa_s32, addr_inc16, ee_store_op, ee_sub_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VMUL
{
.name = "ee.vmul.s8",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.s16",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u8",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u8, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u16",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u16, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Load: ee.vmul.xx.ld.incp
{
.name = "ee.vmul.s8.ld.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.s16.ld.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u8.ld.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u8, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u16.ld.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u16, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Store: ee.vmul.xx.st.incp
{
.name = "ee.vmul.s8.st.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.s16.st.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u8.st.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u8, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmul.u16.st.incp",
.translate = translate_vmul_s3,
.par = (const uint32_t[]){vmul_u16, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// CMUL
// ee.cmul.s16 qz, qx, qy, sel4
{
.name = "ee.cmul.s16",
.translate = translate_cmul_s3,
.par = (const uint32_t[]){addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.cmul.s16.ld.incp",
.translate = translate_cmul_s3,
.par = (const uint32_t[]){addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.cmul.s16.st.incp",
.translate = translate_cmul_s3,
.par = (const uint32_t[]){addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Multiply and accumulate
// EE.VMULAS.[U/S][8/16].ACCX qx, qy
{
.name = "ee.vmulas.s8.accx",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.accx",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u8, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.accx",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.accx",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u16, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].ACCX.LD.IP qu, as, imm16, qx, qy
{
.name = "ee.vmulas.s8.accx.ld.ip",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s8, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.accx.ld.ip",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u8, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.accx.ld.ip",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s16, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.accx.ld.ip",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u16, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].ACCX.LD.xP qu, as, ad, qx, qy
{
.name = "ee.vmulas.s8.accx.ld.xp",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s8, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.accx.ld.xp",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u8, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.accx.ld.xp",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s16, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.accx.ld.xp",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u16, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].ACCX.LD.IP.qup qu, as, imm16, qx, qy, qs0, qs1
{
.name = "ee.vmulas.s8.accx.ld.ip.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s8, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.accx.ld.ip.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u8, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.accx.ld.ip.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s16, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.accx.ld.ip.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u16, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].ACCX.LD.xP.qup qu, as, ad, qx, qy , qs0, qs1
{
.name = "ee.vmulas.s8.accx.ld.xp.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s8, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.accx.ld.xp.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u8, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.accx.ld.xp.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_s16, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.accx.ld.xp.qup",
.translate = translate_vmulas_accx_s3,
.par = (const uint32_t[]){vmul_u16, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC qx, qy
{
.name = "ee.vmulas.s8.qacc",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.LD.IP qu, as, imm16, qx, qy
{
.name = "ee.vmulas.s8.qacc.ld.ip",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ld.ip",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ld.ip",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ld.ip",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.LD.xP qu, as, ad, qx, qy
{
.name = "ee.vmulas.s8.qacc.ld.xp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ld.xp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ld.xp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ld.xp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.ldbc.incp qu, as, qx, qy
{
.name = "ee.vmulas.s8.qacc.ldbc.incp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_ldbc_inc1, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ldbc.incp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_ldbc_inc1, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ldbc.incp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_ldbc_inc1, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ldbc.incp",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_ldbc_inc1, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.ldbc.incp.qup qu, as, qx, qy, qs0, qs1
{
.name = "ee.vmulas.s8.qacc.ldbc.incp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_ldbc_inc1, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ldbc.incp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_ldbc_inc1, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ldbc.incp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_ldbc_inc1, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ldbc.incp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_ldbc_inc1, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.LD.IP.QUP qu, as, imm16, qx, qy, qs0, qs1
{
.name = "ee.vmulas.s8.qacc.ld.ip.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ld.ip.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ld.ip.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ld.ip.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_ip, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMULAS.[U/S][8/16].QACC.LD.XP.QUP qu, as, ad, qx, qy, qs0, qs1
{
.name = "ee.vmulas.s8.qacc.ld.xp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u8.qacc.ld.xp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u8, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.s16.qacc.ld.xp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmulas.u16.qacc.ld.xp.qup",
.translate = translate_vmulas_qacc_s3,
.par = (const uint32_t[]){vmul_u16, addr_xp, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ee.vsmulas.s[8/16].qacc
{
.name = "ee.vsmulas.s8.qacc",
.translate = translate_vsmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsmulas.s16.qacc",
.translate = translate_vsmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ee.vsmulas.s[8/16].qacc.ld.incp
{
.name = "ee.vsmulas.s8.qacc.ld.incp",
.translate = translate_vsmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vsmulas.s16.qacc.ld.incp",
.translate = translate_vsmulas_qacc_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Others..
// EE.SRCMB.S[8/16].QACC qu, as, sel2
{
.name = "ee.srcmb.s8.qacc",
.translate = translate_srcmb_qacc_s3,
.par = (const uint32_t[]){vmul_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.srcmb.s16.qacc",
.translate = translate_srcmb_qacc_s3,
.par = (const uint32_t[]){vmul_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VRELU.S[8/16] qs, ax, ay
{
.name = "ee.vrelu.s8",
.translate = translate_vrelu_s3,
.par = (const uint32_t[]){vmul_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vrelu.s16",
.translate = translate_vrelu_s3,
.par = (const uint32_t[]){vmul_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VPRELU.S[8/16] qz, qx, qy, ay
{
.name = "ee.vprelu.s8",
.translate = translate_vprelu_s3,
.par = (const uint32_t[]){vmul_s8},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vprelu.s16",
.translate = translate_vprelu_s3,
.par = (const uint32_t[]){vmul_s16},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Comparison...
// EE.VMAX.[S8/S16/S32] qa, qx, qy
{
.name = "ee.vmax.s8",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s16",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s32",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s32, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMAX.[S8/S16/S32].LD.INCP qu, as, qa, qx, qy
{
.name = "ee.vmax.s8.ld.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s16.ld.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s32.ld.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s32, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMAX.[S8/S16/S32].ST.INCP qu, as, qa, qx, qy
{
.name = "ee.vmax.s8.st.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s16.st.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmax.s32.st.incp",
.translate = translate_vmax_s3,
.par = (const uint32_t[]){vmul_s32, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Min operations
// EE.VMIN.[S8/S16/S32] qa, qx, qy
{
.name = "ee.vmin.s8",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s8, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s16",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s16, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s32",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s32, addr_nop, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMIN.[S8/S16/S32].LD.INCP qu, as, qa, qx, qy
{
.name = "ee.vmin.s8.ld.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s16.ld.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s32.ld.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s32, addr_inc16, ee_load_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VMIN.[S8/S16/S32].ST.INCP qv, as, qa, qx, qy
{
.name = "ee.vmin.s8.st.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s8, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s16.st.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s16, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vmin.s32.st.incp",
.translate = translate_vmin_s3,
.par = (const uint32_t[]){vmul_s32, addr_inc16, ee_store_op},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// VCMP...
// EE.VCMP.EQ.[S8/S16/S32] qa, qx, qy
{
.name = "ee.vcmp.eq.s8",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s8, ee_vcmp_eq},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.eq.s16",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s16, ee_vcmp_eq},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.eq.s32",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s32, ee_vcmp_eq},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VCMP.LT.[S8/S16/S32] qa, qx, qy
{
.name = "ee.vcmp.lt.s8",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s8, ee_vcmp_lt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.lt.s16",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s16, ee_vcmp_lt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.lt.s32",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s32, ee_vcmp_lt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VCMP.GT.[S8/S16/S32] qa, qx, qy
{
.name = "ee.vcmp.gt.s8",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s8, ee_vcmp_gt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.gt.s16",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s16, ee_vcmp_gt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.vcmp.gt.s32",
.translate = translate_vcmp_s3,
.par = (const uint32_t[]){vmul_s32, ee_vcmp_gt},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Bitwise logical
// EE.ORQ qa, qx, qy
{
.name = "ee.orq",
.translate = translate_bw_logic_s3,
.par = (const uint32_t[]){bw_logic_or},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.XORQ qa, qx, qy
{
.name = "ee.xorq",
.translate = translate_bw_logic_s3,
.par = (const uint32_t[]){bw_logic_xor},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.ANDQ qa, qx, qy
{
.name = "ee.andq",
.translate = translate_bw_logic_s3,
.par = (const uint32_t[]){bw_logic_and},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.NOTQ qa, qx
{
.name = "ee.notq",
.translate = translate_bw_logic_s3,
.par = (const uint32_t[]){bw_logic_not},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Shift
// EE.SRC.Q qa, qs0, qs1
{
.name = "ee.src.q",
.translate = translate_src_q_s3,
.par = (const uint32_t[]){addr_nop, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRC.Q.QUP qa, qs0, qs1
{
.name = "ee.src.q.qup",
.translate = translate_src_q_s3,
.par = (const uint32_t[]){addr_nop, vmul_qup},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRC.Q.LD.XP qu, as, ad, qs0, qs1
{
.name = "ee.src.q.ld.xp",
.translate = translate_src_q_s3,
.par = (const uint32_t[]){addr_xp, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRC.Q.LD.IP qu, as, imm16, qs0, qs1
{
.name = "ee.src.q.ld.ip",
.translate = translate_src_q_s3,
.par = (const uint32_t[]){addr_ip, vmul_nop},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SLCI.2Q qs1, qs0, sar16
{
.name = "ee.slci.2q",
.translate = translate_sxci_2q_s3,
.par = (const uint32_t[]){bw_shift_left},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRCI.2Q qs1, qs0, sar16
{
.name = "ee.srci.2q",
.translate = translate_sxci_2q_s3,
.par = (const uint32_t[]){bw_shift_right},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SLCXXP.2Q qs1, qs0, as, ad
{
.name = "ee.slcxxp.2q",
.translate = translate_sxcxxp_2q_s3,
.par = (const uint32_t[]){bw_shift_left},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRCXXP.2Q qs1, qs0, as, ad
{
.name = "ee.srcxxp.2q",
.translate = translate_sxcxxp_2q_s3,
.par = (const uint32_t[]){bw_shift_right},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SRCQ.128.ST.INCP qs0, qs1, as
{
.name = "ee.srcq.128.st.incp",
.translate = translate_srcq_128_st_s3,
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VSR.32 qa, qs
{
.name = "ee.vsr.32",
.translate = translate_vsx32_s3,
.par = (const uint32_t[]){bw_shift_right},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.VSL.32 qa, qs
{
.name = "ee.vsl.32",
.translate = translate_vsx32_s3,
.par = (const uint32_t[]){bw_shift_left},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// FFT
// Butterfly operation
// EE.FFT.R2BF.S16.ST.INCP qa0, qx, qy, as, sar4
{
.name = "ee.fft.r2bf.s16.st.incp",
.translate = translate_r2bf_st_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.R2BF.S16 qa0, qa1, qx, qy, sel2
{
.name = "ee.fft.r2bf.s16",
.translate = translate_r2bf_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.CMUL.S16.LD.XP qu, as, ad, qz, qx, qy, sel8
{
.name = "ee.fft.cmul.s16.ld.xp",
.translate = translate_fft_cmul_ld_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.CMUL.S16.ST.XP qx, qy, qv, as, ad, sel8, upd4, sar4
{
.name = "ee.fft.cmul.s16.st.xp",
.translate = translate_fft_cmul_st_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// Bit reverse
// EE.BITREV qa, as
{
.name = "ee.bitrev",
.translate = translate_bitrev_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// FFTR
// EE.FFT.AMS.S16.LD.INCP qu, as, qz, qz1, qx, qy, qm, sel2
{
.name = "ee.fft.ams.s16.ld.incp",
.translate = translate_fft_ams_s16_ld_incp,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.AMS.S16.ST.INCP qv, qz1, as0, as, qx, qy, qm, sel2
{
.name = "ee.fft.ams.s16.st.incp",
.translate = translate_fft_ams_s16_st_incp,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.AMS.S16.LD.INCP.UAUP qu, as, qz, qz1, qx, qy, qm, sel2
{
.name = "ee.fft.ams.s16.ld.incp.uaup",
.translate = translate_fft_ams_s16_ld_incp_uaup,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.AMS.S16.LD.R32.DECP qu, as, qz, qz1, qx, qy, qm, sel2
{
.name = "ee.fft.ams.s16.ld.r32.decp",
.translate = translate_fft_ams_s16_ld_decp,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.FFT.VST.R32.DECP qv, as, sar2
{
.name = "ee.fft.vst.r32.decp",
.translate = translate_fft_vst_decp_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// GPIO
// EE.WR_MASK_GPIO_OUT
{
.name = "ee.wr_mask_gpio_out",
.translate = translate_wr_mask_gpio_out_s3,
.par = (const uint32_t[]){gpio_mask},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.SET_BIT_GPIO_OUT
{
.name = "ee.set_bit_gpio_out",
.translate = translate_wr_mask_gpio_out_s3,
.par = (const uint32_t[]){gpio_set},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.CLR_BIT_GPIO_OUT
{
.name = "ee.clr_bit_gpio_out",
.translate = translate_wr_mask_gpio_out_s3,
.par = (const uint32_t[]){gpio_clr},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// EE.GET_GPIO_IN
{
.name = "ee.get_gpio_in",
.translate = translate_wr_mask_gpio_out_s3,
.par = (const uint32_t[]){gpio_in},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ld.qr
{
.name = "ld.qr",
.translate = translate_ld_qr_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// st.qr
{
.name = "st.qr",
.translate = translate_st_qr_s3,
.par = (const uint32_t[]){addr_ip},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// mv.qr
{
.name = "mv.qr",
.translate = translate_mv_qr_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ee.ld.accx.ip
{
.name = "ee.ld.accx.ip",
.translate = translate_ld_accx_ip_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ee.ld.accx.ip
{
.name = "ee.srs.accx",
.translate = translate_srs_accx_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// ld.qacc_x.h.32.ip
{
.name = "ee.ld.qacc_h.h.32.ip",
.translate = translate_ld_qacc_x_h_32_ip_s3,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ld.qacc_l.h.32.ip",
.translate = translate_ld_qacc_x_h_32_ip_s3,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ld.qacc_h.l.128.ip",
.translate = translate_ld_qacc_x_l_128_ip_s3,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.ld.qacc_l.l.128.ip",
.translate = translate_ld_qacc_x_l_128_ip_s3,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
// st.qacc_x.h.32.ip / st.qacc_x.l.128.ip
{
.name = "ee.st.qacc_h.h.32.ip",
.translate = translate_st_qacc_x_h_32_ip_s3,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.st.qacc_l.h.32.ip",
.translate = translate_st_qacc_x_h_32_ip_s3,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.st.qacc_h.l.128.ip",
.translate = translate_st_qacc_x_l_128_ip_s3,
.par = (const uint32_t[]){wrur_qacc_h_0},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
{
.name = "ee.st.qacc_l.l.128.ip",
.translate = translate_st_qacc_x_l_128_ip_s3,
.par = (const uint32_t[]){wrur_qacc_l_0},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
// ee.st.accx.ip
{
.name = "ee.st.accx.ip",
.translate = translate_st_accx_ip_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
// ee.ld.ua_state.ip / ee.st.ua_state.ip
{
.name = "ee.ld.ua_state.ip",
.translate = translate_ld_ua_state_ip_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.st.ua_state.ip",
.translate = translate_st_ua_state_ip_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
// ee.ldxq.32 / ee.stxq.32
{
.name = "ee.ldxq.32",
.translate = translate_ldxq_32_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x0,
},
{
.name = "ee.stxq.32",
.translate = translate_stxq_32_s3,
.par = (const uint32_t[]){},
.op_flags = XTENSA_OP_STORE,
.coprocessor = 0x0,
},
};
const XtensaOpcodeTranslators xtensa_tie_opcodes = {
.num_opcodes = ARRAY_SIZE(tie_ops),
.opcode = tie_ops,
};