From 0946097051713031db1ff884c67081f291210ee2 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 27 Aug 2018 21:43:43 -0700 Subject: [PATCH 01/15] target/xtensa: extract test for an illegal instruction - TB flags: add XTENSA_TBFLAG_CWOE that corresponds to the architectural CWOE state; - entry: move CWOE check from the helper to the test_ill_entry; - retw: move CWOE check from the helper to the test_ill_retw; - separate instruction disassembly loop and translation loop; save disassembly results in local array; Signed-off-by: Max Filippov --- target/xtensa/cpu.h | 27 ++- target/xtensa/helper.c | 6 + target/xtensa/helper.h | 1 + target/xtensa/op_helper.c | 72 ++++---- target/xtensa/translate.c | 367 ++++++++++++++++++++++++++++++++++---- 5 files changed, 400 insertions(+), 73 deletions(-) diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 1362772617..0a0323f386 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -217,6 +217,7 @@ enum { #define MEMCTL_IL0EN 0x1 #define MAX_INSN_LENGTH 64 +#define MAX_INSN_SLOTS 32 #define MAX_OPCODE_ARGS 16 #define MAX_NAREG 64 #define MAX_NINTERRUPT 32 @@ -347,11 +348,34 @@ typedef struct XtensaMemory { typedef struct DisasContext DisasContext; typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[], const uint32_t par[]); +typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc, + const uint32_t arg[], + const uint32_t par[]); + +enum { + XTENSA_OP_ILL = 0x1, + XTENSA_OP_PRIVILEGED = 0x2, + XTENSA_OP_SYSCALL = 0x4, + XTENSA_OP_DEBUG_BREAK = 0x8, + + XTENSA_OP_OVERFLOW = 0x10, + XTENSA_OP_UNDERFLOW = 0x20, + XTENSA_OP_ALLOCA = 0x40, + XTENSA_OP_COPROCESSOR = 0x80, + + XTENSA_OP_DIVIDE_BY_ZERO = 0x100, + + XTENSA_OP_CHECK_INTERRUPTS = 0x200, + XTENSA_OP_EXIT_TB_M1 = 0x400, + XTENSA_OP_EXIT_TB_0 = 0x800, +}; typedef struct XtensaOpcodeOps { const char *name; XtensaOpcodeOp translate; + XtensaOpcodeBoolTest test_ill; const uint32_t *par; + uint32_t op_flags; } XtensaOpcodeOps; typedef struct XtensaOpcodeTranslators { @@ -661,6 +685,7 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch) #define XTENSA_TBFLAG_WINDOW_MASK 0x18000 #define XTENSA_TBFLAG_WINDOW_SHIFT 15 #define XTENSA_TBFLAG_YIELD 0x20000 +#define XTENSA_TBFLAG_CWOE 0x40000 static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) @@ -698,7 +723,7 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, (env->sregs[WINDOW_BASE] + 1); uint32_t w = ctz32(windowstart | 0x8); - *flags |= w << XTENSA_TBFLAG_WINDOW_SHIFT; + *flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE; } else { *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT; } diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 4fceb4424a..501082f55b 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -57,12 +57,18 @@ static void init_libisa(XtensaConfig *config) { unsigned i, j; unsigned opcodes; + unsigned formats; config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL); assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH); opcodes = xtensa_isa_num_opcodes(config->isa); + formats = xtensa_isa_num_formats(config->isa); config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes); + for (i = 0; i < formats; ++i) { + assert(xtensa_format_num_slots(config->isa, i) <= MAX_INSN_SLOTS); + } + for (i = 0; i < opcodes; ++i) { const char *opc_name = xtensa_opcode_name(config->isa, i); XtensaOpcodeOps *ops = NULL; diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h index 73444ae02c..c1b3bacb4c 100644 --- a/target/xtensa/helper.h +++ b/target/xtensa/helper.h @@ -5,6 +5,7 @@ DEF_HELPER_3(debug_exception, noreturn, env, i32, i32) DEF_HELPER_2(wsr_windowbase, void, env, i32) DEF_HELPER_4(entry, void, env, i32, i32, i32) +DEF_HELPER_2(test_ill_retw, void, env, i32) DEF_HELPER_2(retw, i32, env, i32) DEF_HELPER_2(rotw, void, env, i32) DEF_HELPER_3(window_check, noreturn, env, i32, i32) diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 06fe346f02..f5520659d8 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -253,22 +253,16 @@ void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v) void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) { int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT; - if (s > 3 || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) { - qemu_log_mask(LOG_GUEST_ERROR, "Illegal entry instruction(pc = %08x), PS = %08x\n", - pc, env->sregs[PS]); - HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE); - } else { - uint32_t windowstart = xtensa_replicate_windowstart(env) >> - (env->sregs[WINDOW_BASE] + 1); + uint32_t windowstart = xtensa_replicate_windowstart(env) >> + (env->sregs[WINDOW_BASE] + 1); - if (windowstart & ((1 << callinc) - 1)) { - HELPER(window_check)(env, pc, callinc); - } - env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm; - xtensa_rotate_window(env, callinc); - env->sregs[WINDOW_START] |= - windowstart_bit(env->sregs[WINDOW_BASE], env); + if (windowstart & ((1 << callinc) - 1)) { + HELPER(window_check)(env, pc, callinc); } + env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm; + xtensa_rotate_window(env, callinc); + env->sregs[WINDOW_START] |= + windowstart_bit(env->sregs[WINDOW_BASE], env); } void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w) @@ -298,13 +292,12 @@ void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w) } } -uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) +void HELPER(test_ill_retw)(CPUXtensaState *env, uint32_t pc) { int n = (env->regs[0] >> 30) & 0x3; int m = 0; uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); uint32_t windowstart = env->sregs[WINDOW_START]; - uint32_t ret_pc = 0; if (windowstart & windowstart_bit(windowbase - 1, env)) { m = 1; @@ -314,33 +307,38 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) m = 3; } - if (n == 0 || (m != 0 && m != n) || - ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) { + if (n == 0 || (m != 0 && m != n)) { qemu_log_mask(LOG_GUEST_ERROR, "Illegal retw instruction(pc = %08x), " "PS = %08x, m = %d, n = %d\n", pc, env->sregs[PS], m, n); HELPER(exception_cause)(env, pc, ILLEGAL_INSTRUCTION_CAUSE); + } +} + +uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) +{ + int n = (env->regs[0] >> 30) & 0x3; + uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); + uint32_t windowstart = env->sregs[WINDOW_START]; + uint32_t ret_pc = 0; + + ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); + + xtensa_rotate_window(env, -n); + if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { + env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env); } else { - int owb = windowbase; + /* window underflow */ + env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | + (windowbase << PS_OWB_SHIFT) | PS_EXCM; + env->sregs[EPC1] = env->pc = pc; - ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); - - xtensa_rotate_window(env, -n); - if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { - env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env); - } else { - /* window underflow */ - env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | - (windowbase << PS_OWB_SHIFT) | PS_EXCM; - env->sregs[EPC1] = env->pc = pc; - - if (n == 1) { - HELPER(exception)(env, EXC_WINDOW_UNDERFLOW4); - } else if (n == 2) { - HELPER(exception)(env, EXC_WINDOW_UNDERFLOW8); - } else if (n == 3) { - HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12); - } + if (n == 1) { + HELPER(exception)(env, EXC_WINDOW_UNDERFLOW4); + } else if (n == 2) { + HELPER(exception)(env, EXC_WINDOW_UNDERFLOW8); + } else if (n == 3) { + HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12); } } return ret_pc; diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index c626583cd9..9cfb33fc00 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -62,6 +62,7 @@ struct DisasContext { TCGv_i32 sar_m32; unsigned window; + bool cwoe; bool debug; bool icount; @@ -469,7 +470,7 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond, tcg_temp_free(tmp); } -static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) +static bool check_sr(DisasContext *dc, uint32_t sr, unsigned access) { if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) { if (sregnames[sr].name) { @@ -477,7 +478,6 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) } else { qemu_log_mask(LOG_UNIMP, "SR %d is not implemented\n", sr); } - gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return false; } else if (!(sregnames[sr].access & access)) { static const char * const access_text[] = { @@ -488,7 +488,6 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) assert(access < ARRAY_SIZE(access_text) && access_text[access]); qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not available for %s\n", sregnames[sr].name, access_text[access]); - gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return false; } return true; @@ -954,6 +953,12 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) xtensa_format fmt; int slot, slots; unsigned i; + uint32_t op_flags = 0; + struct { + XtensaOpcodeOps *ops; + uint32_t arg[MAX_OPCODE_ARGS]; + uint32_t raw_arg[MAX_OPCODE_ARGS]; + } slot_prop[MAX_INSN_SLOTS]; if (len == XTENSA_UNDEFINED) { qemu_log_mask(LOG_GUEST_ERROR, @@ -987,8 +992,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) for (slot = 0; slot < slots; ++slot) { xtensa_opcode opc; int opnd, vopnd, opnds; - uint32_t raw_arg[MAX_OPCODE_ARGS]; - uint32_t arg[MAX_OPCODE_ARGS]; + uint32_t *raw_arg = slot_prop[slot].raw_arg; + uint32_t *arg = slot_prop[slot].arg; XtensaOpcodeOps *ops; dc->raw_arg = raw_arg; @@ -1020,16 +1025,29 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } } ops = dc->config->opcode_ops[opc]; + slot_prop[slot].ops = ops; + if (ops) { - ops->translate(dc, arg, ops->par); + op_flags |= ops->op_flags; } else { - qemu_log_mask(LOG_GUEST_ERROR, + qemu_log_mask(LOG_UNIMP, "unimplemented opcode '%s' in slot %d (pc = %08x)\n", xtensa_opcode_name(isa, opc), slot, dc->pc); + op_flags |= XTENSA_OP_ILL; + } + if ((op_flags & XTENSA_OP_ILL) || + (ops && ops->test_ill && ops->test_ill(dc, arg, ops->par))) { gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return; } } + + for (slot = 0; slot < slots; ++slot) { + XtensaOpcodeOps *ops = slot_prop[slot].ops; + + dc->raw_arg = slot_prop[slot].raw_arg; + ops->translate(dc, slot_prop[slot].arg, ops->par); + } if (dc->base.is_jmp == DISAS_NEXT) { gen_check_loop_end(dc, 0); } @@ -1074,6 +1092,7 @@ static void xtensa_tr_init_disas_context(DisasContextBase *dcbase, XTENSA_TBFLAG_CPENABLE_SHIFT; dc->window = ((tb_flags & XTENSA_TBFLAG_WINDOW_MASK) >> XTENSA_TBFLAG_WINDOW_SHIFT); + dc->cwoe = tb_flags & XTENSA_TBFLAG_CWOE; if (dc->config->isa) { dc->insnbuf = xtensa_insnbuf_alloc(dc->config->isa); @@ -1590,6 +1609,18 @@ static void translate_depbits(DisasContext *dc, const uint32_t arg[], } } +static bool test_ill_entry(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + if (arg[0] > 3 || !dc->cwoe) { + qemu_log_mask(LOG_GUEST_ERROR, + "Illegal entry instruction(pc = %08x)\n", dc->pc); + return true; + } else { + return false; + } +} + static void translate_entry(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -1650,12 +1681,6 @@ static void translate_itlb(DisasContext *dc, const uint32_t arg[], } } -static void translate_ill(DisasContext *dc, const uint32_t arg[], - const uint32_t par[]) -{ - gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); -} - static void translate_j(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -2124,6 +2149,22 @@ static void translate_ret(DisasContext *dc, const uint32_t arg[], gen_jump(dc, cpu_R[0]); } +static bool test_ill_retw(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + if (!dc->cwoe) { + qemu_log_mask(LOG_GUEST_ERROR, + "Illegal retw instruction(pc = %08x)\n", dc->pc); + return true; + } else { + TCGv_i32 tmp = tcg_const_i32(dc->pc); + + gen_helper_test_ill_retw(cpu_env, tmp); + tcg_temp_free(tmp); + return false; + } +} + static void translate_retw(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -2211,11 +2252,16 @@ static void translate_rsil(DisasContext *dc, const uint32_t arg[], } } +static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + return !check_sr(dc, par[0], SR_R); +} + static void translate_rsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_sr(dc, par[0], SR_R) && - (par[0] < 64 || gen_check_privilege(dc)) && + if ((par[0] < 64 || gen_check_privilege(dc)) && gen_window_check1(dc, arg[0])) { if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { gen_jumpi_check_loop_end(dc, 0); @@ -2337,20 +2383,28 @@ static void translate_sext(DisasContext *dc, const uint32_t arg[], } } +static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ +#ifdef CONFIG_USER_ONLY + bool ill = true; +#else + bool ill = !semihosting_enabled(); +#endif + if (ill) { + qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); + } + return ill; +} + static void translate_simcall(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { #ifndef CONFIG_USER_ONLY - if (semihosting_enabled()) { - if (gen_check_privilege(dc)) { - gen_helper_simcall(cpu_env); - } - } else -#endif - { - qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); - gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); + if (gen_check_privilege(dc)) { + gen_helper_simcall(cpu_env); } +#endif } /* @@ -2570,11 +2624,16 @@ static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[], } } +static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + return !check_sr(dc, par[0], SR_W); +} + static void translate_wsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_sr(dc, par[0], SR_W) && - (par[0] < 64 || gen_check_privilege(dc)) && + if ((par[0] < 64 || gen_check_privilege(dc)) && gen_window_check1(dc, arg[0])) { gen_wsr(dc, par[0], cpu_R[arg[0]]); } @@ -2600,11 +2659,16 @@ static void translate_xor(DisasContext *dc, const uint32_t arg[], } } +static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + return !check_sr(dc, par[0], SR_X); +} + static void translate_xsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_sr(dc, par[0], SR_X) && - (par[0] < 64 || gen_check_privilege(dc)) && + if ((par[0] < 64 || gen_check_privilege(dc)) && gen_window_check1(dc, arg[0])) { TCGv_i32 tmp = tcg_temp_new_i32(); bool rsr_end, wsr_end; @@ -2897,6 +2961,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "entry", .translate = translate_entry, + .test_ill = test_ill_entry, }, { .name = "esync", .translate = translate_nop, @@ -2911,10 +2976,10 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_memw, }, { .name = "hwwdtlba", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "hwwitlba", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "idtlb", .translate = translate_itlb, @@ -2941,10 +3006,10 @@ static const XtensaOpcodeOps core_ops[] = { .par = (const uint32_t[]){true, false}, }, { .name = "ill", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "ill.n", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "ipf", .translate = translate_icache, @@ -3002,7 +3067,7 @@ static const XtensaOpcodeOps core_ops[] = { .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4}, }, { .name = "ldpte", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "loop", .translate = translate_loop, @@ -3417,18 +3482,20 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "retw", .translate = translate_retw, + .test_ill = test_ill_retw, }, { .name = "retw.n", .translate = translate_retw, + .test_ill = test_ill_retw, }, { .name = "rfdd", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "rfde", .translate = translate_rfde, }, { .name = "rfdo", - .translate = translate_ill, + .op_flags = XTENSA_OP_ILL, }, { .name = "rfe", .translate = translate_rfe, @@ -3460,306 +3527,382 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsr.176", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){176}, }, { .name = "rsr.208", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){208}, }, { .name = "rsr.acchi", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ACCHI}, }, { .name = "rsr.acclo", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ACCLO}, }, { .name = "rsr.atomctl", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ATOMCTL}, }, { .name = "rsr.br", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){BR}, }, { .name = "rsr.cacheattr", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CACHEATTR}, }, { .name = "rsr.ccompare0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE}, }, { .name = "rsr.ccompare1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 1}, }, { .name = "rsr.ccompare2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 2}, }, { .name = "rsr.ccount", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOUNT}, }, { .name = "rsr.configid0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID0}, }, { .name = "rsr.configid1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID1}, }, { .name = "rsr.cpenable", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){CPENABLE}, }, { .name = "rsr.dbreaka0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA}, }, { .name = "rsr.dbreaka1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA + 1}, }, { .name = "rsr.dbreakc0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC}, }, { .name = "rsr.dbreakc1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC + 1}, }, { .name = "rsr.ddr", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DDR}, }, { .name = "rsr.debugcause", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEBUGCAUSE}, }, { .name = "rsr.depc", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEPC}, }, { .name = "rsr.dtlbcfg", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){DTLBCFG}, }, { .name = "rsr.epc1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1}, }, { .name = "rsr.epc2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 1}, }, { .name = "rsr.epc3", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 2}, }, { .name = "rsr.epc4", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 3}, }, { .name = "rsr.epc5", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 4}, }, { .name = "rsr.epc6", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 5}, }, { .name = "rsr.epc7", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 6}, }, { .name = "rsr.eps2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2}, }, { .name = "rsr.eps3", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 1}, }, { .name = "rsr.eps4", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 2}, }, { .name = "rsr.eps5", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 3}, }, { .name = "rsr.eps6", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 4}, }, { .name = "rsr.eps7", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 5}, }, { .name = "rsr.exccause", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCCAUSE}, }, { .name = "rsr.excsave1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1}, }, { .name = "rsr.excsave2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, }, { .name = "rsr.excsave3", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, }, { .name = "rsr.excsave4", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, }, { .name = "rsr.excsave5", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, }, { .name = "rsr.excsave6", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, }, { .name = "rsr.excsave7", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, }, { .name = "rsr.excvaddr", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCVADDR}, }, { .name = "rsr.ibreaka0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA}, }, { .name = "rsr.ibreaka1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA + 1}, }, { .name = "rsr.ibreakenable", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKENABLE}, }, { .name = "rsr.icount", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNT}, }, { .name = "rsr.icountlevel", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNTLEVEL}, }, { .name = "rsr.intclear", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTCLEAR}, }, { .name = "rsr.intenable", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTENABLE}, }, { .name = "rsr.interrupt", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, }, { .name = "rsr.intset", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, }, { .name = "rsr.itlbcfg", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){ITLBCFG}, }, { .name = "rsr.lbeg", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){LBEG}, }, { .name = "rsr.lcount", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){LCOUNT}, }, { .name = "rsr.lend", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){LEND}, }, { .name = "rsr.litbase", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){LITBASE}, }, { .name = "rsr.m0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR}, }, { .name = "rsr.m1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 1}, }, { .name = "rsr.m2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 2}, }, { .name = "rsr.m3", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 3}, }, { .name = "rsr.memctl", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MEMCTL}, }, { .name = "rsr.misc0", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC}, }, { .name = "rsr.misc1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 1}, }, { .name = "rsr.misc2", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 2}, }, { .name = "rsr.misc3", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 3}, }, { .name = "rsr.prid", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){PRID}, }, { .name = "rsr.ps", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){PS}, }, { .name = "rsr.ptevaddr", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){PTEVADDR}, }, { .name = "rsr.rasid", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){RASID}, }, { .name = "rsr.sar", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){SAR}, }, { .name = "rsr.scompare1", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){SCOMPARE1}, }, { .name = "rsr.vecbase", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){VECBASE}, }, { .name = "rsr.windowbase", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_BASE}, }, { .name = "rsr.windowstart", .translate = translate_rsr, + .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_START}, }, { .name = "rsync", @@ -3827,6 +3970,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "simcall", .translate = translate_simcall, + .test_ill = test_ill_simcall, }, { .name = "sll", .translate = translate_sll, @@ -3917,310 +4061,387 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "wsr.176", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){176}, }, { .name = "wsr.208", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){208}, }, { .name = "wsr.acchi", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ACCHI}, }, { .name = "wsr.acclo", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ACCLO}, }, { .name = "wsr.atomctl", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ATOMCTL}, }, { .name = "wsr.br", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){BR}, }, { .name = "wsr.cacheattr", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CACHEATTR}, }, { .name = "wsr.ccompare0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE}, }, { .name = "wsr.ccompare1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 1}, }, { .name = "wsr.ccompare2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 2}, }, { .name = "wsr.ccount", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOUNT}, }, { .name = "wsr.configid0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID0}, }, { .name = "wsr.configid1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID1}, }, { .name = "wsr.cpenable", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){CPENABLE}, }, { .name = "wsr.dbreaka0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA}, }, { .name = "wsr.dbreaka1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA + 1}, }, { .name = "wsr.dbreakc0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC}, }, { .name = "wsr.dbreakc1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC + 1}, }, { .name = "wsr.ddr", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DDR}, }, { .name = "wsr.debugcause", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEBUGCAUSE}, }, { .name = "wsr.depc", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEPC}, }, { .name = "wsr.dtlbcfg", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){DTLBCFG}, }, { .name = "wsr.epc1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1}, }, { .name = "wsr.epc2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 1}, }, { .name = "wsr.epc3", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 2}, }, { .name = "wsr.epc4", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 3}, }, { .name = "wsr.epc5", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 4}, }, { .name = "wsr.epc6", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 5}, }, { .name = "wsr.epc7", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 6}, }, { .name = "wsr.eps2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2}, }, { .name = "wsr.eps3", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 1}, }, { .name = "wsr.eps4", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 2}, }, { .name = "wsr.eps5", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 3}, }, { .name = "wsr.eps6", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 4}, }, { .name = "wsr.eps7", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 5}, }, { .name = "wsr.exccause", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCCAUSE}, }, { .name = "wsr.excsave1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1}, }, { .name = "wsr.excsave2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, }, { .name = "wsr.excsave3", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, }, { .name = "wsr.excsave4", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, }, { .name = "wsr.excsave5", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, }, { .name = "wsr.excsave6", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, }, { .name = "wsr.excsave7", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, }, { .name = "wsr.excvaddr", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCVADDR}, }, { .name = "wsr.ibreaka0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA}, }, { .name = "wsr.ibreaka1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA + 1}, }, { .name = "wsr.ibreakenable", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKENABLE}, }, { .name = "wsr.icount", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNT}, }, { .name = "wsr.icountlevel", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNTLEVEL}, }, { .name = "wsr.intclear", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTCLEAR}, }, { .name = "wsr.intenable", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTENABLE}, }, { .name = "wsr.interrupt", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, }, { .name = "wsr.intset", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, }, { .name = "wsr.itlbcfg", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){ITLBCFG}, }, { .name = "wsr.lbeg", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){LBEG}, }, { .name = "wsr.lcount", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){LCOUNT}, }, { .name = "wsr.lend", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){LEND}, }, { .name = "wsr.litbase", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){LITBASE}, }, { .name = "wsr.m0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR}, }, { .name = "wsr.m1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 1}, }, { .name = "wsr.m2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 2}, }, { .name = "wsr.m3", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 3}, }, { .name = "wsr.memctl", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MEMCTL}, }, { .name = "wsr.misc0", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC}, }, { .name = "wsr.misc1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 1}, }, { .name = "wsr.misc2", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 2}, }, { .name = "wsr.misc3", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 3}, }, { .name = "wsr.mmid", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){MMID}, }, { .name = "wsr.prid", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){PRID}, }, { .name = "wsr.ps", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){PS}, }, { .name = "wsr.ptevaddr", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){PTEVADDR}, }, { .name = "wsr.rasid", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){RASID}, }, { .name = "wsr.sar", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){SAR}, }, { .name = "wsr.scompare1", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){SCOMPARE1}, }, { .name = "wsr.vecbase", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){VECBASE}, }, { .name = "wsr.windowbase", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_BASE}, }, { .name = "wsr.windowstart", .translate = translate_wsr, + .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_START}, }, { .name = "wur.expstate", @@ -4248,306 +4469,382 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "xsr.176", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){176}, }, { .name = "xsr.208", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){208}, }, { .name = "xsr.acchi", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ACCHI}, }, { .name = "xsr.acclo", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ACCLO}, }, { .name = "xsr.atomctl", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ATOMCTL}, }, { .name = "xsr.br", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){BR}, }, { .name = "xsr.cacheattr", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CACHEATTR}, }, { .name = "xsr.ccompare0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE}, }, { .name = "xsr.ccompare1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 1}, }, { .name = "xsr.ccompare2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 2}, }, { .name = "xsr.ccount", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOUNT}, }, { .name = "xsr.configid0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID0}, }, { .name = "xsr.configid1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID1}, }, { .name = "xsr.cpenable", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){CPENABLE}, }, { .name = "xsr.dbreaka0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA}, }, { .name = "xsr.dbreaka1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA + 1}, }, { .name = "xsr.dbreakc0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC}, }, { .name = "xsr.dbreakc1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC + 1}, }, { .name = "xsr.ddr", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DDR}, }, { .name = "xsr.debugcause", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEBUGCAUSE}, }, { .name = "xsr.depc", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEPC}, }, { .name = "xsr.dtlbcfg", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){DTLBCFG}, }, { .name = "xsr.epc1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1}, }, { .name = "xsr.epc2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 1}, }, { .name = "xsr.epc3", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 2}, }, { .name = "xsr.epc4", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 3}, }, { .name = "xsr.epc5", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 4}, }, { .name = "xsr.epc6", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 5}, }, { .name = "xsr.epc7", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 6}, }, { .name = "xsr.eps2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2}, }, { .name = "xsr.eps3", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 1}, }, { .name = "xsr.eps4", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 2}, }, { .name = "xsr.eps5", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 3}, }, { .name = "xsr.eps6", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 4}, }, { .name = "xsr.eps7", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 5}, }, { .name = "xsr.exccause", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCCAUSE}, }, { .name = "xsr.excsave1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1}, }, { .name = "xsr.excsave2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, }, { .name = "xsr.excsave3", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, }, { .name = "xsr.excsave4", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, }, { .name = "xsr.excsave5", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, }, { .name = "xsr.excsave6", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, }, { .name = "xsr.excsave7", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, }, { .name = "xsr.excvaddr", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCVADDR}, }, { .name = "xsr.ibreaka0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA}, }, { .name = "xsr.ibreaka1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA + 1}, }, { .name = "xsr.ibreakenable", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKENABLE}, }, { .name = "xsr.icount", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNT}, }, { .name = "xsr.icountlevel", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNTLEVEL}, }, { .name = "xsr.intclear", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTCLEAR}, }, { .name = "xsr.intenable", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTENABLE}, }, { .name = "xsr.interrupt", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, }, { .name = "xsr.intset", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, }, { .name = "xsr.itlbcfg", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){ITLBCFG}, }, { .name = "xsr.lbeg", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){LBEG}, }, { .name = "xsr.lcount", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){LCOUNT}, }, { .name = "xsr.lend", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){LEND}, }, { .name = "xsr.litbase", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){LITBASE}, }, { .name = "xsr.m0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR}, }, { .name = "xsr.m1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 1}, }, { .name = "xsr.m2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 2}, }, { .name = "xsr.m3", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 3}, }, { .name = "xsr.memctl", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MEMCTL}, }, { .name = "xsr.misc0", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC}, }, { .name = "xsr.misc1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 1}, }, { .name = "xsr.misc2", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 2}, }, { .name = "xsr.misc3", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 3}, }, { .name = "xsr.prid", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){PRID}, }, { .name = "xsr.ps", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){PS}, }, { .name = "xsr.ptevaddr", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){PTEVADDR}, }, { .name = "xsr.rasid", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){RASID}, }, { .name = "xsr.sar", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){SAR}, }, { .name = "xsr.scompare1", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){SCOMPARE1}, }, { .name = "xsr.vecbase", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){VECBASE}, }, { .name = "xsr.windowbase", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_BASE}, }, { .name = "xsr.windowstart", .translate = translate_xsr, + .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_START}, }, }; From 21a2dad5c40d9f1b3f82e73c9fcc35166ef4d57c Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 27 Aug 2018 22:17:50 -0700 Subject: [PATCH 02/15] target/xtensa: extract test for privileged instruction - mark privileged instructions; - put single privileged instruction check after disassembly loop; - translate_[di]cache: drop parameter 0, shift parameters one down; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 389 +++++++++++++++++++++++++++++--------- 1 file changed, 295 insertions(+), 94 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 9cfb33fc00..6b5edfd0c2 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1042,6 +1042,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } } + if ((op_flags & XTENSA_OP_PRIVILEGED) && + !gen_check_privilege(dc)) { + return; + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -1584,12 +1589,11 @@ static void translate_const16(DisasContext *dc, const uint32_t arg[], } } -/* par[0]: privileged, par[1]: check memory access */ +/* par[0]: check memory access */ static void translate_dcache(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if ((!par[0] || gen_check_privilege(dc)) && - gen_window_check1(dc, arg[0]) && par[1]) { + if (gen_window_check1(dc, arg[0]) && par[0]) { TCGv_i32 addr = tcg_temp_new_i32(); TCGv_i32 res = tcg_temp_new_i32(); @@ -1648,12 +1652,11 @@ static void translate_extui(DisasContext *dc, const uint32_t arg[], } } -/* par[0]: privileged, par[1]: check memory access */ +/* par[0]: check memory access */ static void translate_icache(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if ((!par[0] || gen_check_privilege(dc)) && - gen_window_check1(dc, arg[0]) && par[1]) { + if (gen_window_check1(dc, arg[0]) && par[0]) { #ifndef CONFIG_USER_ONLY TCGv_i32 addr = tcg_temp_new_i32(); @@ -1668,8 +1671,7 @@ static void translate_icache(DisasContext *dc, const uint32_t arg[], static void translate_itlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check1(dc, arg[0])) { + if (gen_window_check1(dc, arg[0])) { #ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); @@ -1698,8 +1700,7 @@ static void translate_jx(DisasContext *dc, const uint32_t arg[], static void translate_l32e(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); @@ -2061,8 +2062,7 @@ static void translate_or(DisasContext *dc, const uint32_t arg[], static void translate_ptlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { #ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); @@ -2137,8 +2137,7 @@ static void translate_read_impwire(DisasContext *dc, const uint32_t arg[], static void translate_rer(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]); } } @@ -2177,73 +2176,62 @@ static void translate_retw(DisasContext *dc, const uint32_t arg[], static void translate_rfde(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { - gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]); - } + gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]); } static void translate_rfe(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { - tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); - gen_check_interrupts(dc); - gen_jump(dc, cpu_SR[EPC1]); - } + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); + gen_check_interrupts(dc); + gen_jump(dc, cpu_SR[EPC1]); } static void translate_rfi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { - tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]); - gen_check_interrupts(dc); - gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]); - } + tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]); + gen_check_interrupts(dc); + gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]); } static void translate_rfw(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { - TCGv_i32 tmp = tcg_const_i32(1); + TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); - tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]); + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); + tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]); - if (par[0]) { - tcg_gen_andc_i32(cpu_SR[WINDOW_START], - cpu_SR[WINDOW_START], tmp); - } else { - tcg_gen_or_i32(cpu_SR[WINDOW_START], - cpu_SR[WINDOW_START], tmp); - } - - gen_helper_restore_owb(cpu_env); - gen_check_interrupts(dc); - gen_jump(dc, cpu_SR[EPC1]); - - tcg_temp_free(tmp); + if (par[0]) { + tcg_gen_andc_i32(cpu_SR[WINDOW_START], + cpu_SR[WINDOW_START], tmp); + } else { + tcg_gen_or_i32(cpu_SR[WINDOW_START], + cpu_SR[WINDOW_START], tmp); } + + gen_helper_restore_owb(cpu_env); + gen_check_interrupts(dc); + gen_jump(dc, cpu_SR[EPC1]); + + tcg_temp_free(tmp); } static void translate_rotw(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { - TCGv_i32 tmp = tcg_const_i32(arg[0]); - gen_helper_rotw(cpu_env, tmp); - tcg_temp_free(tmp); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); - } + TCGv_i32 tmp = tcg_const_i32(arg[0]); + gen_helper_rotw(cpu_env, tmp); + tcg_temp_free(tmp); + /* This can change tb->flags, so exit tb */ + gen_jumpi_check_loop_end(dc, -1); } static void translate_rsil(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check1(dc, arg[0])) { + if (gen_window_check1(dc, arg[0])) { tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]); tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); @@ -2261,8 +2249,7 @@ static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], static void translate_rsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if ((par[0] < 64 || gen_check_privilege(dc)) && - gen_window_check1(dc, arg[0])) { + if (gen_window_check1(dc, arg[0])) { if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { gen_jumpi_check_loop_end(dc, 0); } @@ -2272,21 +2259,20 @@ static void translate_rsr(DisasContext *dc, const uint32_t arg[], static void translate_rtlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { +#ifndef CONFIG_USER_ONLY static void (* const helper[])(TCGv_i32 r, TCGv_env env, TCGv_i32 a1, TCGv_i32 a2) = { -#ifndef CONFIG_USER_ONLY gen_helper_rtlb0, gen_helper_rtlb1, -#endif }; - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { TCGv_i32 dtlb = tcg_const_i32(par[0]); helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); tcg_temp_free(dtlb); } +#endif } static void translate_rur(DisasContext *dc, const uint32_t arg[], @@ -2343,8 +2329,7 @@ static void translate_s32c1i(DisasContext *dc, const uint32_t arg[], static void translate_s32e(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); @@ -2401,9 +2386,7 @@ static void translate_simcall(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { #ifndef CONFIG_USER_ONLY - if (gen_check_privilege(dc)) { - gen_helper_simcall(cpu_env); - } + gen_helper_simcall(cpu_env); #endif } @@ -2583,18 +2566,15 @@ static void translate_syscall(DisasContext *dc, const uint32_t arg[], static void translate_waiti(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc)) { #ifndef CONFIG_USER_ONLY - gen_waiti(dc, arg[0]); + gen_waiti(dc, arg[0]); #endif - } } static void translate_wtlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { #ifndef CONFIG_USER_ONLY TCGv_i32 dtlb = tcg_const_i32(par[0]); @@ -2609,8 +2589,7 @@ static void translate_wtlb(DisasContext *dc, const uint32_t arg[], static void translate_wer(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_privilege(dc) && - gen_window_check2(dc, arg[0], arg[1])) { + if (gen_window_check2(dc, arg[0], arg[1])) { gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]); } } @@ -2633,8 +2612,7 @@ static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[], static void translate_wsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if ((par[0] < 64 || gen_check_privilege(dc)) && - gen_window_check1(dc, arg[0])) { + if (gen_window_check1(dc, arg[0])) { gen_wsr(dc, par[0], cpu_R[arg[0]]); } } @@ -2668,8 +2646,7 @@ static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[], static void translate_xsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if ((par[0] < 64 || gen_check_privilege(dc)) && - gen_window_check1(dc, arg[0])) { + if (gen_window_check1(dc, arg[0])) { TCGv_i32 tmp = tcg_temp_new_i32(); bool rsr_end, wsr_end; @@ -2906,55 +2883,62 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "dhi", .translate = translate_dcache, - .par = (const uint32_t[]){true, true}, + .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "dhu", .translate = translate_dcache, - .par = (const uint32_t[]){true, true}, + .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "dhwb", .translate = translate_dcache, - .par = (const uint32_t[]){false, true}, + .par = (const uint32_t[]){true}, }, { .name = "dhwbi", .translate = translate_dcache, - .par = (const uint32_t[]){false, true}, + .par = (const uint32_t[]){true}, }, { .name = "dii", .translate = translate_dcache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "diu", .translate = translate_dcache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "diwb", .translate = translate_dcache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "diwbi", .translate = translate_dcache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "dpfl", .translate = translate_dcache, - .par = (const uint32_t[]){true, true}, + .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "dpfr", .translate = translate_dcache, - .par = (const uint32_t[]){false, false}, + .par = (const uint32_t[]){false}, }, { .name = "dpfro", .translate = translate_dcache, - .par = (const uint32_t[]){false, false}, + .par = (const uint32_t[]){false}, }, { .name = "dpfw", .translate = translate_dcache, - .par = (const uint32_t[]){false, false}, + .par = (const uint32_t[]){false}, }, { .name = "dpfwo", .translate = translate_dcache, - .par = (const uint32_t[]){false, false}, + .par = (const uint32_t[]){false}, }, { .name = "dsync", .translate = translate_nop, @@ -2984,26 +2968,31 @@ static const XtensaOpcodeOps core_ops[] = { .name = "idtlb", .translate = translate_itlb, .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "ihi", .translate = translate_icache, - .par = (const uint32_t[]){false, true}, + .par = (const uint32_t[]){true}, }, { .name = "ihu", .translate = translate_icache, - .par = (const uint32_t[]){true, true}, + .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "iii", .translate = translate_icache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "iitlb", .translate = translate_itlb, .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "iiu", .translate = translate_icache, - .par = (const uint32_t[]){true, false}, + .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "ill", .op_flags = XTENSA_OP_ILL, @@ -3013,11 +3002,12 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "ipf", .translate = translate_icache, - .par = (const uint32_t[]){false, false}, + .par = (const uint32_t[]){false}, }, { .name = "ipfl", .translate = translate_icache, - .par = (const uint32_t[]){true, true}, + .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "isync", .translate = translate_nop, @@ -3042,6 +3032,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "l32e", .translate = translate_l32e, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "l32i", .translate = translate_ldst, @@ -3439,10 +3430,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "pdtlb", .translate = translate_ptlb, .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "pitlb", .translate = translate_ptlb, .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "quos", .translate = translate_quos, @@ -3455,10 +3448,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "rdtlb0", .translate = translate_rtlb, .par = (const uint32_t[]){true, 0}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rdtlb1", .translate = translate_rtlb, .par = (const uint32_t[]){true, 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "read_impwire", .translate = translate_read_impwire, @@ -3473,6 +3468,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rer", .translate = translate_rer, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "ret", .translate = translate_ret, @@ -3493,47 +3489,58 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rfde", .translate = translate_rfde, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rfdo", .op_flags = XTENSA_OP_ILL, }, { .name = "rfe", .translate = translate_rfe, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rfi", .translate = translate_rfi, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rfwo", .translate = translate_rfw, .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rfwu", .translate = translate_rfw, .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "ritlb0", .translate = translate_rtlb, .par = (const uint32_t[]){false, 0}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "ritlb1", .translate = translate_rtlb, .par = (const uint32_t[]){false, 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rotw", .translate = translate_rotw, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsil", .translate = translate_rsil, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.176", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){176}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.208", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){208}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.acchi", .translate = translate_rsr, @@ -3549,6 +3556,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ATOMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.br", .translate = translate_rsr, @@ -3559,241 +3567,289 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CACHEATTR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ccompare0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ccompare1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ccompare2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ccount", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.configid0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID0}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.configid1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.cpenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CPENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.dbreaka0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.dbreaka1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.dbreakc0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.dbreakc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.debugcause", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEBUGCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.depc", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEPC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.dtlbcfg", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DTLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.epc7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.eps7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.exccause", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excsave7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.excvaddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ibreaka0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ibreaka1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ibreakenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.icount", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.icountlevel", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNTLEVEL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.intclear", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTCLEAR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.intenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.interrupt", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.intset", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.itlbcfg", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ITLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.lbeg", .translate = translate_rsr, @@ -3839,46 +3895,55 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MEMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.misc0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.misc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.misc2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.misc3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.prid", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PRID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ps", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PS}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.ptevaddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PTEVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.rasid", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){RASID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.sar", .translate = translate_rsr, @@ -3894,16 +3959,19 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){VECBASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.windowbase", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_BASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsr.windowstart", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_START}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "rsync", .translate = translate_nop, @@ -3933,6 +4001,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "s32e", .translate = translate_s32e, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "s32i", .translate = translate_ldst, @@ -3971,6 +4040,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "simcall", .translate = translate_simcall, .test_ill = test_ill_simcall, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "sll", .translate = translate_sll, @@ -4044,17 +4114,21 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "waiti", .translate = translate_waiti, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wdtlb", .translate = translate_wtlb, .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wer", .translate = translate_wer, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "witlb", .translate = translate_wtlb, .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wrmsk_expstate", .translate = translate_wrmsk_expstate, @@ -4063,11 +4137,13 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){176}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.208", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){208}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.acchi", .translate = translate_wsr, @@ -4083,6 +4159,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ATOMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.br", .translate = translate_wsr, @@ -4093,241 +4170,289 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CACHEATTR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ccompare0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ccompare1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ccompare2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ccount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.configid0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID0}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.configid1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.cpenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CPENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.dbreaka0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.dbreaka1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.dbreakc0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.dbreakc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.debugcause", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEBUGCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.depc", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEPC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.dtlbcfg", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DTLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.epc7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.eps7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.exccause", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excsave7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.excvaddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ibreaka0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ibreaka1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ibreakenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.icount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.icountlevel", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNTLEVEL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.intclear", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTCLEAR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.intenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.interrupt", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.intset", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.itlbcfg", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ITLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.lbeg", .translate = translate_wsr, @@ -4373,51 +4498,61 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MEMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.misc0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.misc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.misc2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.misc3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.mmid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MMID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.prid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PRID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ps", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PS}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.ptevaddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PTEVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.rasid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){RASID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.sar", .translate = translate_wsr, @@ -4433,16 +4568,19 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){VECBASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.windowbase", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_BASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wsr.windowstart", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_START}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "wur.expstate", .translate = translate_wur, @@ -4471,11 +4609,13 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){176}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.208", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){208}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.acchi", .translate = translate_xsr, @@ -4491,6 +4631,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ATOMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.br", .translate = translate_xsr, @@ -4501,241 +4642,289 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CACHEATTR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ccompare0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ccompare1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ccompare2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ccount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.configid0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID0}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.configid1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.cpenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CPENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.dbreaka0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.dbreaka1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.dbreakc0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.dbreakc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.debugcause", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEBUGCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.depc", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEPC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.dtlbcfg", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DTLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.epc7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.eps7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.exccause", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCCAUSE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excsave7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.excvaddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ibreaka0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ibreaka1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ibreakenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.icount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNT}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.icountlevel", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNTLEVEL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.intclear", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTCLEAR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.intenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTENABLE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.interrupt", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.intset", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.itlbcfg", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ITLBCFG}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.lbeg", .translate = translate_xsr, @@ -4781,46 +4970,55 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MEMCTL}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.misc0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.misc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 1}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.misc2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 2}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.misc3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 3}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.prid", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PRID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ps", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PS}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.ptevaddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PTEVADDR}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.rasid", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){RASID}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.sar", .translate = translate_xsr, @@ -4836,16 +5034,19 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){VECBASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.windowbase", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_BASE}, + .op_flags = XTENSA_OP_PRIVILEGED, }, { .name = "xsr.windowstart", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_START}, + .op_flags = XTENSA_OP_PRIVILEGED, }, }; From 4c6ec5f3cd88cb27a4e40a480b34e433a725dc05 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 27 Aug 2018 22:18:48 -0700 Subject: [PATCH 03/15] target/xtensa: extract test for syscall instruction - mark syscall instruction; - put syscall exception check right after privileged exception check; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 6b5edfd0c2..69d3c583e8 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1047,6 +1047,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; } + if (op_flags & XTENSA_OP_SYSCALL) { + gen_exception_cause(dc, SYSCALL_CAUSE); + return; + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -2557,12 +2562,6 @@ static void translate_subx(DisasContext *dc, const uint32_t arg[], } } -static void translate_syscall(DisasContext *dc, const uint32_t arg[], - const uint32_t par[]) -{ - gen_exception_cause(dc, SYSCALL_CAUSE); -} - static void translate_waiti(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -4094,7 +4093,7 @@ static const XtensaOpcodeOps core_ops[] = { .par = (const uint32_t[]){3}, }, { .name = "syscall", - .translate = translate_syscall, + .op_flags = XTENSA_OP_SYSCALL, }, { .name = "umul.aa.hh", .translate = translate_mac16, From 15477819427f5d2f0eddd4daba4159dee5f3b2ec Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 28 Aug 2018 14:52:27 -0700 Subject: [PATCH 04/15] target/xtensa: extract test for debug exception - mark break and break.n instructions; - collect debug cause bits from parameter 0 of instructions marked for debug exception; - put debug exception check right after syscall check; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 69d3c583e8..570d4a39e2 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -959,6 +959,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) uint32_t arg[MAX_OPCODE_ARGS]; uint32_t raw_arg[MAX_OPCODE_ARGS]; } slot_prop[MAX_INSN_SLOTS]; + uint32_t debug_cause = 0; if (len == XTENSA_UNDEFINED) { qemu_log_mask(LOG_GUEST_ERROR, @@ -1040,6 +1041,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return; } + if (ops->op_flags & XTENSA_OP_DEBUG_BREAK) { + debug_cause |= ops->par[0]; + } } if ((op_flags & XTENSA_OP_PRIVILEGED) && @@ -1052,6 +1056,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; } + if ((op_flags & XTENSA_OP_DEBUG_BREAK) && dc->debug) { + gen_debug_exception(dc, debug_cause); + return; + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -1515,14 +1524,6 @@ static void translate_bp(DisasContext *dc, const uint32_t arg[], tcg_temp_free(tmp); } -static void translate_break(DisasContext *dc, const uint32_t arg[], - const uint32_t par[]) -{ - if (dc->debug) { - gen_debug_exception(dc, par[0]); - } -} - static void translate_call0(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -2827,12 +2828,14 @@ static const XtensaOpcodeOps core_ops[] = { .par = (const uint32_t[]){TCG_COND_EQ}, }, { .name = "break", - .translate = translate_break, + .translate = translate_nop, .par = (const uint32_t[]){DEBUGCAUSE_BI}, + .op_flags = XTENSA_OP_DEBUG_BREAK, }, { .name = "break.n", - .translate = translate_break, + .translate = translate_nop, .par = (const uint32_t[]){DEBUGCAUSE_BN}, + .op_flags = XTENSA_OP_DEBUG_BREAK, }, { .name = "bt", .translate = translate_bp, From 6416d16f7544c53ccb6ce7d74e8f01f502b558d3 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 29 Aug 2018 10:37:29 -0700 Subject: [PATCH 05/15] target/xtensa: extract test for window overflow exception - add ps.callinc to the TB flags, that allows testing all instructions for window overflow statically; - drop gen_window_check* functions; replace them with get_window_check that accepts bitmask of used registers; - add XtensaOpcodeOps::test_overflow that returns bitmask of implicitly used registers; use it for entry and call{,x}{4,8,12}; - drop window overflow test from the entry helper; - drop parameter 0 from translate_[di]cache and use translate_nop for d/i cache opcodes that don't need memory accessibility check; - add bitmask XtensaOpcodeOps::windowed_register_op that marks opcode arguments that refer to windowed registers; - translate windowed_register_op mask to a mask of actually used registers in the disassembly loop; - add check for window overflow right after the check for debug exception; Signed-off-by: Max Filippov --- target/xtensa/cpu.h | 9 + target/xtensa/op_helper.c | 5 - target/xtensa/translate.c | 1464 ++++++++++++++++++++++--------------- 3 files changed, 890 insertions(+), 588 deletions(-) diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 0a0323f386..be234958a2 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -351,6 +351,9 @@ typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[], typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc, const uint32_t arg[], const uint32_t par[]); +typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc, + const uint32_t arg[], + const uint32_t par[]); enum { XTENSA_OP_ILL = 0x1, @@ -374,8 +377,10 @@ typedef struct XtensaOpcodeOps { const char *name; XtensaOpcodeOp translate; XtensaOpcodeBoolTest test_ill; + XtensaOpcodeUintTest test_overflow; const uint32_t *par; uint32_t op_flags; + uint32_t windowed_register_op; } XtensaOpcodeOps; typedef struct XtensaOpcodeTranslators { @@ -686,6 +691,8 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch) #define XTENSA_TBFLAG_WINDOW_SHIFT 15 #define XTENSA_TBFLAG_YIELD 0x20000 #define XTENSA_TBFLAG_CWOE 0x40000 +#define XTENSA_TBFLAG_CALLINC_MASK 0x180000 +#define XTENSA_TBFLAG_CALLINC_SHIFT 19 static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) @@ -724,6 +731,8 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, uint32_t w = ctz32(windowstart | 0x8); *flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE; + *flags |= extract32(env->sregs[PS], PS_CALLINC_SHIFT, + PS_CALLINC_LEN) << XTENSA_TBFLAG_CALLINC_SHIFT; } else { *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT; } diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index f5520659d8..68052851af 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -253,12 +253,7 @@ void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v) void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm) { int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT; - uint32_t windowstart = xtensa_replicate_windowstart(env) >> - (env->sregs[WINDOW_BASE] + 1); - if (windowstart & ((1 << callinc) - 1)) { - HELPER(window_check)(env, pc, callinc); - } env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm; xtensa_rotate_window(env, callinc); env->sregs[WINDOW_START] |= diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 570d4a39e2..83e107a2ac 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -62,6 +62,7 @@ struct DisasContext { TCGv_i32 sar_m32; unsigned window; + unsigned callinc; bool cwoe; bool debug; @@ -904,11 +905,13 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4) } #endif -static bool gen_window_check1(DisasContext *dc, unsigned r1) +static bool gen_window_check(DisasContext *dc, uint32_t mask) { - if (r1 / 4 > dc->window) { + unsigned r = 31 - clz32(mask); + + if (r / 4 > dc->window) { TCGv_i32 pc = tcg_const_i32(dc->pc); - TCGv_i32 w = tcg_const_i32(r1 / 4); + TCGv_i32 w = tcg_const_i32(r / 4); gen_helper_window_check(cpu_env, pc, w); dc->base.is_jmp = DISAS_NORETURN; @@ -917,17 +920,6 @@ static bool gen_window_check1(DisasContext *dc, unsigned r1) return true; } -static bool gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2) -{ - return gen_window_check1(dc, r1 > r2 ? r1 : r2); -} - -static bool gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2, - unsigned r3) -{ - return gen_window_check2(dc, r1, r2 > r3 ? r2 : r3); -} - static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned) { TCGv_i32 m = tcg_temp_new_i32(); @@ -960,6 +952,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) uint32_t raw_arg[MAX_OPCODE_ARGS]; } slot_prop[MAX_INSN_SLOTS]; uint32_t debug_cause = 0; + uint32_t windowed_register = 0; if (len == XTENSA_UNDEFINED) { qemu_log_mask(LOG_GUEST_ERROR, @@ -1044,6 +1037,19 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (ops->op_flags & XTENSA_OP_DEBUG_BREAK) { debug_cause |= ops->par[0]; } + if (ops->test_overflow) { + windowed_register |= ops->test_overflow(dc, arg, ops->par); + } + if (ops->windowed_register_op) { + uint32_t reg_opnd = ops->windowed_register_op; + + while (reg_opnd) { + unsigned i = ctz32(reg_opnd); + + windowed_register |= 1 << arg[i]; + reg_opnd ^= 1 << i; + } + } } if ((op_flags & XTENSA_OP_PRIVILEGED) && @@ -1061,6 +1067,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; } + if (windowed_register && !gen_window_check(dc, windowed_register)) { + return; + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -1112,6 +1122,8 @@ static void xtensa_tr_init_disas_context(DisasContextBase *dcbase, dc->window = ((tb_flags & XTENSA_TBFLAG_WINDOW_MASK) >> XTENSA_TBFLAG_WINDOW_SHIFT); dc->cwoe = tb_flags & XTENSA_TBFLAG_CWOE; + dc->callinc = ((tb_flags & XTENSA_TBFLAG_CALLINC_MASK) >> + XTENSA_TBFLAG_CALLINC_SHIFT); if (dc->config->isa) { dc->insnbuf = xtensa_insnbuf_alloc(dc->config->isa); @@ -1333,43 +1345,35 @@ xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t, static void translate_abs(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 zero = tcg_const_i32(0); - TCGv_i32 neg = tcg_temp_new_i32(); + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 neg = tcg_temp_new_i32(); - tcg_gen_neg_i32(neg, cpu_R[arg[1]]); - tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]], - cpu_R[arg[1]], zero, cpu_R[arg[1]], neg); - tcg_temp_free(neg); - tcg_temp_free(zero); - } + tcg_gen_neg_i32(neg, cpu_R[arg[1]]); + tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]], + cpu_R[arg[1]], zero, cpu_R[arg[1]], neg); + tcg_temp_free(neg); + tcg_temp_free(zero); } static void translate_add(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_addi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); - } + tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); } static void translate_addx(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); - tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); + tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); + tcg_temp_free(tmp); } static void translate_all(DisasContext *dc, const uint32_t arg[], @@ -1395,93 +1399,77 @@ static void translate_all(DisasContext *dc, const uint32_t arg[], static void translate_and(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_ball(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); - gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); + gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]); + tcg_temp_free(tmp); } static void translate_bany(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); - gen_brcondi(dc, par[0], tmp, 0, arg[2]); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); + gen_brcondi(dc, par[0], tmp, 0, arg[2]); + tcg_temp_free(tmp); } static void translate_b(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); - } + gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); } static void translate_bb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { #ifdef TARGET_WORDS_BIGENDIAN - TCGv_i32 bit = tcg_const_i32(0x80000000u); + TCGv_i32 bit = tcg_const_i32(0x80000000u); #else - TCGv_i32 bit = tcg_const_i32(0x00000001u); + TCGv_i32 bit = tcg_const_i32(0x00000001u); #endif - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f); + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f); #ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_shr_i32(bit, bit, tmp); + tcg_gen_shr_i32(bit, bit, tmp); #else - tcg_gen_shl_i32(bit, bit, tmp); + tcg_gen_shl_i32(bit, bit, tmp); #endif - tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit); - gen_brcondi(dc, par[0], tmp, 0, arg[2]); - tcg_temp_free(tmp); - tcg_temp_free(bit); - } + tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit); + gen_brcondi(dc, par[0], tmp, 0, arg[2]); + tcg_temp_free(tmp); + tcg_temp_free(bit); } static void translate_bbi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); #ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]); + tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]); #else - tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]); + tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]); #endif - gen_brcondi(dc, par[0], tmp, 0, arg[2]); - tcg_temp_free(tmp); - } + gen_brcondi(dc, par[0], tmp, 0, arg[2]); + tcg_temp_free(tmp); } static void translate_bi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]); - } + gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]); } static void translate_bz(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]); - } + gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]); } enum { @@ -1531,50 +1519,48 @@ static void translate_call0(DisasContext *dc, const uint32_t arg[], gen_jumpi(dc, arg[0], 0); } +static uint32_t test_overflow_callw(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + return 1 << (par[0] * 4); +} + static void translate_callw(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, par[0] << 2)) { - gen_callwi(dc, par[0], arg[0], 0); - } + gen_callwi(dc, par[0], arg[0], 0); } static void translate_callx0(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); - tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next); - gen_jump(dc, tmp); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); + tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next); + gen_jump(dc, tmp); + tcg_temp_free(tmp); } static void translate_callxw(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], par[0] << 2)) { - TCGv_i32 tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); - gen_callw(dc, par[0], tmp); - tcg_temp_free(tmp); - } + tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); + gen_callw(dc, par[0], tmp); + tcg_temp_free(tmp); } static void translate_clamps(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]); - TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1); + TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]); + TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1); - tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]); - tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2); - tcg_temp_free(tmp1); - tcg_temp_free(tmp2); - } + tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]); + tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2); + tcg_temp_free(tmp1); + tcg_temp_free(tmp2); } static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[], @@ -1587,36 +1573,29 @@ static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[], static void translate_const16(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 c = tcg_const_i32(arg[1]); + TCGv_i32 c = tcg_const_i32(arg[1]); - tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16); - tcg_temp_free(c); - } + tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16); + tcg_temp_free(c); } -/* par[0]: check memory access */ static void translate_dcache(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0]) && par[0]) { - TCGv_i32 addr = tcg_temp_new_i32(); - TCGv_i32 res = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 res = tcg_temp_new_i32(); - tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); - tcg_gen_qemu_ld8u(res, addr, dc->cring); - tcg_temp_free(addr); - tcg_temp_free(res); - } + tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); + tcg_gen_qemu_ld8u(res, addr, dc->cring); + tcg_temp_free(addr); + tcg_temp_free(res); } static void translate_depbits(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]], - arg[2], arg[3]); - } + tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]], + arg[2], arg[3]); } static bool test_ill_entry(DisasContext *dc, const uint32_t arg[], @@ -1631,6 +1610,12 @@ static bool test_ill_entry(DisasContext *dc, const uint32_t arg[], } } +static uint32_t test_overflow_entry(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + return 1 << (dc->callinc * 4); +} + static void translate_entry(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -1648,45 +1633,38 @@ static void translate_entry(DisasContext *dc, const uint32_t arg[], static void translate_extui(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - int maskimm = (1 << arg[3]) - 1; + int maskimm = (1 << arg[3]) - 1; - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]); - tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]); + tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm); + tcg_temp_free(tmp); } -/* par[0]: check memory access */ static void translate_icache(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0]) && par[0]) { #ifndef CONFIG_USER_ONLY - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_movi_i32(cpu_pc, dc->pc); - tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); - gen_helper_itlb_hit_test(cpu_env, addr); - tcg_temp_free(addr); + tcg_gen_movi_i32(cpu_pc, dc->pc); + tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); + gen_helper_itlb_hit_test(cpu_env, addr); + tcg_temp_free(addr); #endif - } } static void translate_itlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { #ifndef CONFIG_USER_ONLY - TCGv_i32 dtlb = tcg_const_i32(par[0]); + TCGv_i32 dtlb = tcg_const_i32(par[0]); - gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb); - /* This could change memory mapping, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); - tcg_temp_free(dtlb); + gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb); + /* This could change memory mapping, so exit tb */ + gen_jumpi_check_loop_end(dc, -1); + tcg_temp_free(dtlb); #endif - } } static void translate_j(DisasContext *dc, const uint32_t arg[], @@ -1698,87 +1676,77 @@ static void translate_j(DisasContext *dc, const uint32_t arg[], static void translate_jx(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_jump(dc, cpu_R[arg[0]]); - } + gen_jump(dc, cpu_R[arg[0]]); } static void translate_l32e(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); - gen_load_store_alignment(dc, 2, addr, false); - tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); - tcg_temp_free(addr); - } + tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); + gen_load_store_alignment(dc, 2, addr, false); + tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); + tcg_temp_free(addr); } static void translate_ldst(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); - if (par[0] & MO_SIZE) { - gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]); - } - if (par[2]) { - if (par[1]) { - tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL); - } - tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); - } else { - tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); - if (par[1]) { - tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL); - } - } - tcg_temp_free(addr); + tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); + if (par[0] & MO_SIZE) { + gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]); } + if (par[2]) { + if (par[1]) { + tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL); + } + tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); + } else { + tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); + if (par[1]) { + tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL); + } + } + tcg_temp_free(addr); } static void translate_l32r(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp; + TCGv_i32 tmp; - if (dc->base.tb->flags & XTENSA_TBFLAG_LITBASE) { - tmp = tcg_const_i32(dc->raw_arg[1] - 1); - tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp); - } else { - tmp = tcg_const_i32(arg[1]); - } - tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring); - tcg_temp_free(tmp); + if (dc->base.tb->flags & XTENSA_TBFLAG_LITBASE) { + tmp = tcg_const_i32(dc->raw_arg[1] - 1); + tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp); + } else { + tmp = tcg_const_i32(arg[1]); } + tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring); + tcg_temp_free(tmp); } static void translate_loop(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - uint32_t lend = arg[1]; - TCGv_i32 tmp = tcg_const_i32(lend); + uint32_t lend = arg[1]; + TCGv_i32 tmp = tcg_const_i32(lend); - tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1); - tcg_gen_movi_i32(cpu_SR[LBEG], dc->base.pc_next); - gen_helper_wsr_lend(cpu_env, tmp); - tcg_temp_free(tmp); + tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1); + tcg_gen_movi_i32(cpu_SR[LBEG], dc->base.pc_next); + gen_helper_wsr_lend(cpu_env, tmp); + tcg_temp_free(tmp); - if (par[0] != TCG_COND_NEVER) { - TCGLabel *label = gen_new_label(); - tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label); - gen_jumpi(dc, lend, 1); - gen_set_label(label); - } - - gen_jumpi(dc, dc->base.pc_next, 0); + if (par[0] != TCG_COND_NEVER) { + TCGLabel *label = gen_new_label(); + tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label); + gen_jumpi(dc, lend, 1); + gen_set_label(label); } + + gen_jumpi(dc, dc->base.pc_next, 0); } enum { @@ -1818,78 +1786,60 @@ static void translate_mac16(DisasContext *dc, const uint32_t arg[], unsigned half = par[2]; uint32_t ld_offset = par[3]; unsigned off = ld_offset ? 2 : 0; - uint32_t ar[3] = {0}; - unsigned n_ar = 0; - - if (op != MAC16_NONE) { - if (!is_m1_sr) { - ar[n_ar++] = arg[off]; - } - if (!is_m2_sr) { - ar[n_ar++] = arg[off + 1]; - } - } + TCGv_i32 vaddr = tcg_temp_new_i32(); + TCGv_i32 mem32 = tcg_temp_new_i32(); if (ld_offset) { - ar[n_ar++] = arg[1]; + tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset); + gen_load_store_alignment(dc, 2, vaddr, false); + tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring); } + if (op != MAC16_NONE) { + TCGv_i32 m1 = gen_mac16_m(is_m1_sr ? + cpu_SR[MR + arg[off]] : + cpu_R[arg[off]], + half & MAC16_HX, op == MAC16_UMUL); + TCGv_i32 m2 = gen_mac16_m(is_m2_sr ? + cpu_SR[MR + arg[off + 1]] : + cpu_R[arg[off + 1]], + half & MAC16_XH, op == MAC16_UMUL); - if (gen_window_check3(dc, ar[0], ar[1], ar[2])) { - TCGv_i32 vaddr = tcg_temp_new_i32(); - TCGv_i32 mem32 = tcg_temp_new_i32(); - - if (ld_offset) { - tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset); - gen_load_store_alignment(dc, 2, vaddr, false); - tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring); - } - if (op != MAC16_NONE) { - TCGv_i32 m1 = gen_mac16_m(is_m1_sr ? - cpu_SR[MR + arg[off]] : - cpu_R[arg[off]], - half & MAC16_HX, op == MAC16_UMUL); - TCGv_i32 m2 = gen_mac16_m(is_m2_sr ? - cpu_SR[MR + arg[off + 1]] : - cpu_R[arg[off + 1]], - half & MAC16_XH, op == MAC16_UMUL); - - if (op == MAC16_MUL || op == MAC16_UMUL) { - tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2); - if (op == MAC16_UMUL) { - tcg_gen_movi_i32(cpu_SR[ACCHI], 0); - } else { - tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31); - } + if (op == MAC16_MUL || op == MAC16_UMUL) { + tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2); + if (op == MAC16_UMUL) { + tcg_gen_movi_i32(cpu_SR[ACCHI], 0); } else { - TCGv_i32 lo = tcg_temp_new_i32(); - TCGv_i32 hi = tcg_temp_new_i32(); - - tcg_gen_mul_i32(lo, m1, m2); - tcg_gen_sari_i32(hi, lo, 31); - if (op == MAC16_MULA) { - tcg_gen_add2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], - cpu_SR[ACCLO], cpu_SR[ACCHI], - lo, hi); - } else { - tcg_gen_sub2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], - cpu_SR[ACCLO], cpu_SR[ACCHI], - lo, hi); - } - tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]); - - tcg_temp_free_i32(lo); - tcg_temp_free_i32(hi); + tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31); } - tcg_temp_free(m1); - tcg_temp_free(m2); + } else { + TCGv_i32 lo = tcg_temp_new_i32(); + TCGv_i32 hi = tcg_temp_new_i32(); + + tcg_gen_mul_i32(lo, m1, m2); + tcg_gen_sari_i32(hi, lo, 31); + if (op == MAC16_MULA) { + tcg_gen_add2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], + cpu_SR[ACCLO], cpu_SR[ACCHI], + lo, hi); + } else { + tcg_gen_sub2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], + cpu_SR[ACCLO], cpu_SR[ACCHI], + lo, hi); + } + tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]); + + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); } - if (ld_offset) { - tcg_gen_mov_i32(cpu_R[arg[1]], vaddr); - tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32); - } - tcg_temp_free(vaddr); - tcg_temp_free(mem32); + tcg_temp_free(m1); + tcg_temp_free(m2); } + if (ld_offset) { + tcg_gen_mov_i32(cpu_R[arg[1]], vaddr); + tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32); + } + tcg_temp_free(vaddr); + tcg_temp_free(mem32); } static void translate_memw(DisasContext *dc, const uint32_t arg[], @@ -1901,139 +1851,113 @@ static void translate_memw(DisasContext *dc, const uint32_t arg[], static void translate_smin(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_umin(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_smax(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_umax(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_mov(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - } + tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); } static void translate_movcond(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 zero = tcg_const_i32(0); - tcg_gen_movcond_i32(par[0], cpu_R[arg[0]], - cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]); - tcg_temp_free(zero); - } + tcg_gen_movcond_i32(par[0], cpu_R[arg[0]], + cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]); + tcg_temp_free(zero); } static void translate_movi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]); - } + tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]); } static void translate_movp(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 zero = tcg_const_i32(0); - TCGv_i32 tmp = tcg_temp_new_i32(); + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); - tcg_gen_movcond_i32(par[0], - cpu_R[arg[0]], tmp, zero, - cpu_R[arg[1]], cpu_R[arg[0]]); - tcg_temp_free(tmp); - tcg_temp_free(zero); - } + tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); + tcg_gen_movcond_i32(par[0], + cpu_R[arg[0]], tmp, zero, + cpu_R[arg[1]], cpu_R[arg[0]]); + tcg_temp_free(tmp); + tcg_temp_free(zero); } static void translate_movsp(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 pc = tcg_const_i32(dc->pc); - gen_helper_movsp(cpu_env, pc); - tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - tcg_temp_free(pc); - } + TCGv_i32 pc = tcg_const_i32(dc->pc); + gen_helper_movsp(cpu_env, pc); + tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); + tcg_temp_free(pc); } static void translate_mul16(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i32 v1 = tcg_temp_new_i32(); - TCGv_i32 v2 = tcg_temp_new_i32(); + TCGv_i32 v1 = tcg_temp_new_i32(); + TCGv_i32 v2 = tcg_temp_new_i32(); - if (par[0]) { - tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]); - tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]); - } else { - tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]); - tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]); - } - tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2); - tcg_temp_free(v2); - tcg_temp_free(v1); + if (par[0]) { + tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]); + tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]); + } else { + tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]); + tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]); } + tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2); + tcg_temp_free(v2); + tcg_temp_free(v1); } static void translate_mull(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_mulh(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i32 lo = tcg_temp_new(); + TCGv_i32 lo = tcg_temp_new(); - if (par[0]) { - tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } else { - tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } - tcg_temp_free(lo); + if (par[0]) { + tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); + } else { + tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } + tcg_temp_free(lo); } static void translate_neg(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - } + tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]); } static void translate_nop(DisasContext *dc, const uint32_t arg[], @@ -2044,39 +1968,31 @@ static void translate_nop(DisasContext *dc, const uint32_t arg[], static void translate_nsa(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - } + tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]); } static void translate_nsau(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32); - } + tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32); } static void translate_or(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_ptlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { #ifndef CONFIG_USER_ONLY - TCGv_i32 dtlb = tcg_const_i32(par[0]); + TCGv_i32 dtlb = tcg_const_i32(par[0]); - tcg_gen_movi_i32(cpu_pc, dc->pc); - gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); - tcg_temp_free(dtlb); + tcg_gen_movi_i32(cpu_pc, dc->pc); + gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); + tcg_temp_free(dtlb); #endif - } } static void gen_zero_check(DisasContext *dc, const uint32_t arg[]) @@ -2091,61 +2007,53 @@ static void gen_zero_check(DisasContext *dc, const uint32_t arg[]) static void translate_quos(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGLabel *label1 = gen_new_label(); - TCGLabel *label2 = gen_new_label(); + TCGLabel *label1 = gen_new_label(); + TCGLabel *label2 = gen_new_label(); - gen_zero_check(dc, arg); + gen_zero_check(dc, arg); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000, - label1); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff, - label1); - tcg_gen_movi_i32(cpu_R[arg[0]], - par[0] ? 0x80000000 : 0); - tcg_gen_br(label2); - gen_set_label(label1); - if (par[0]) { - tcg_gen_div_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } else { - tcg_gen_rem_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } - gen_set_label(label2); + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000, + label1); + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff, + label1); + tcg_gen_movi_i32(cpu_R[arg[0]], + par[0] ? 0x80000000 : 0); + tcg_gen_br(label2); + gen_set_label(label1); + if (par[0]) { + tcg_gen_div_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); + } else { + tcg_gen_rem_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); } + gen_set_label(label2); } static void translate_quou(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - gen_zero_check(dc, arg); - if (par[0]) { - tcg_gen_divu_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } else { - tcg_gen_remu_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } + gen_zero_check(dc, arg); + if (par[0]) { + tcg_gen_divu_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); + } else { + tcg_gen_remu_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); } } static void translate_read_impwire(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - /* TODO: GPIO32 may be a part of coprocessor */ - tcg_gen_movi_i32(cpu_R[arg[0]], 0); - } + /* TODO: GPIO32 may be a part of coprocessor */ + tcg_gen_movi_i32(cpu_R[arg[0]], 0); } static void translate_rer(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]); - } + gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]); } static void translate_ret(DisasContext *dc, const uint32_t arg[], @@ -2237,13 +2145,11 @@ static void translate_rotw(DisasContext *dc, const uint32_t arg[], static void translate_rsil(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]); - tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); - tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); - gen_check_interrupts(dc); - gen_jumpi_check_loop_end(dc, 0); - } + tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]); + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); + tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); + gen_check_interrupts(dc); + gen_jumpi_check_loop_end(dc, 0); } static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], @@ -2255,10 +2161,8 @@ static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], static void translate_rsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { - gen_jumpi_check_loop_end(dc, 0); - } + if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { + gen_jumpi_check_loop_end(dc, 0); } } @@ -2271,25 +2175,20 @@ static void translate_rtlb(DisasContext *dc, const uint32_t arg[], gen_helper_rtlb0, gen_helper_rtlb1, }; + TCGv_i32 dtlb = tcg_const_i32(par[0]); - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 dtlb = tcg_const_i32(par[0]); - - helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); - tcg_temp_free(dtlb); - } + helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); + tcg_temp_free(dtlb); #endif } static void translate_rur(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - if (uregnames[par[0]].name) { - tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]); - } else { - qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]); - } + if (uregnames[par[0]].name) { + tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]); + } else { + qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]); } } @@ -2317,60 +2216,52 @@ static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr) static void translate_s32c1i(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 tmp = tcg_temp_local_new_i32(); - TCGv_i32 addr = tcg_temp_local_new_i32(); + TCGv_i32 tmp = tcg_temp_local_new_i32(); + TCGv_i32 addr = tcg_temp_local_new_i32(); - tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); - tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); - gen_load_store_alignment(dc, 2, addr, true); - gen_check_atomctl(dc, addr); - tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1], - tmp, dc->cring, MO_TEUL); - tcg_temp_free(addr); - tcg_temp_free(tmp); - } + tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); + tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); + gen_load_store_alignment(dc, 2, addr, true); + gen_check_atomctl(dc, addr); + tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1], + tmp, dc->cring, MO_TEUL); + tcg_temp_free(addr); + tcg_temp_free(tmp); } static void translate_s32e(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); - gen_load_store_alignment(dc, 2, addr, false); - tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); - tcg_temp_free(addr); - } + tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); + gen_load_store_alignment(dc, 2, addr, false); + tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); + tcg_temp_free(addr); } static void translate_salt(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_setcond_i32(par[0], - cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_setcond_i32(par[0], + cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_sext(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - int shift = 31 - arg[2]; + int shift = 31 - arg[2]; - if (shift == 24) { - tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - } else if (shift == 16) { - tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - } else { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift); - tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift); - tcg_temp_free(tmp); - } + if (shift == 24) { + tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); + } else if (shift == 16) { + tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); + } else { + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift); + tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift); + tcg_temp_free(tmp); } } @@ -2414,76 +2305,64 @@ static void translate_simcall(DisasContext *dc, const uint32_t arg[], static void translate_sll(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - if (dc->sar_m32_5bit) { - tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32); - } else { - TCGv_i64 v = tcg_temp_new_i64(); - TCGv_i32 s = tcg_const_i32(32); - tcg_gen_sub_i32(s, s, cpu_SR[SAR]); - tcg_gen_andi_i32(s, s, 0x3f); - tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); - gen_shift_reg(shl, s); - tcg_temp_free(s); - } + if (dc->sar_m32_5bit) { + tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32); + } else { + TCGv_i64 v = tcg_temp_new_i64(); + TCGv_i32 s = tcg_const_i32(32); + tcg_gen_sub_i32(s, s, cpu_SR[SAR]); + tcg_gen_andi_i32(s, s, 0x3f); + tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); + gen_shift_reg(shl, s); + tcg_temp_free(s); } } static void translate_slli(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - if (arg[2] == 32) { - qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n", - arg[0], arg[1]); - } - tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f); + if (arg[2] == 32) { + qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n", + arg[0], arg[1]); } + tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f); } static void translate_sra(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - if (dc->sar_m32_5bit) { - tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); - } else { - TCGv_i64 v = tcg_temp_new_i64(); - tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]); - gen_shift(sar); - } + if (dc->sar_m32_5bit) { + tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); + } else { + TCGv_i64 v = tcg_temp_new_i64(); + tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]); + gen_shift(sar); } } static void translate_srai(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); - } + tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); } static void translate_src(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i64 v = tcg_temp_new_i64(); - tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]); - gen_shift(shr); - } + TCGv_i64 v = tcg_temp_new_i64(); + tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]); + gen_shift(shr); } static void translate_srl(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - if (dc->sar_m32_5bit) { - tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); - } else { - TCGv_i64 v = tcg_temp_new_i64(); - tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); - gen_shift(shr); - } + if (dc->sar_m32_5bit) { + tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); + } else { + TCGv_i64 v = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); + gen_shift(shr); } } @@ -2493,31 +2372,25 @@ static void translate_srl(DisasContext *dc, const uint32_t arg[], static void translate_srli(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); - } + tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); } static void translate_ssa8b(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); - gen_left_shift_sar(dc, tmp); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); + gen_left_shift_sar(dc, tmp); + tcg_temp_free(tmp); } static void translate_ssa8l(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); - gen_right_shift_sar(dc, tmp); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); + gen_right_shift_sar(dc, tmp); + tcg_temp_free(tmp); } static void translate_ssai(DisasContext *dc, const uint32_t arg[], @@ -2531,36 +2404,28 @@ static void translate_ssai(DisasContext *dc, const uint32_t arg[], static void translate_ssl(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_left_shift_sar(dc, cpu_R[arg[0]]); - } + gen_left_shift_sar(dc, cpu_R[arg[0]]); } static void translate_ssr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_right_shift_sar(dc, cpu_R[arg[0]]); - } + gen_right_shift_sar(dc, cpu_R[arg[0]]); } static void translate_sub(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_subx(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); - tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); - tcg_temp_free(tmp); - } + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); + tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); + tcg_temp_free(tmp); } static void translate_waiti(DisasContext *dc, const uint32_t arg[], @@ -2574,33 +2439,27 @@ static void translate_waiti(DisasContext *dc, const uint32_t arg[], static void translate_wtlb(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { #ifndef CONFIG_USER_ONLY - TCGv_i32 dtlb = tcg_const_i32(par[0]); + TCGv_i32 dtlb = tcg_const_i32(par[0]); - gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb); - /* This could change memory mapping, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); - tcg_temp_free(dtlb); + gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb); + /* This could change memory mapping, so exit tb */ + gen_jumpi_check_loop_end(dc, -1); + tcg_temp_free(dtlb); #endif - } } static void translate_wer(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]); - } + gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]); } static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[0], arg[1])) { - /* TODO: GPIO32 may be a part of coprocessor */ - tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]); - } + /* TODO: GPIO32 may be a part of coprocessor */ + tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]); } static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[], @@ -2612,29 +2471,23 @@ static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[], static void translate_wsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - gen_wsr(dc, par[0], cpu_R[arg[0]]); - } + gen_wsr(dc, par[0], cpu_R[arg[0]]); } static void translate_wur(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - if (uregnames[par[0]].name) { - gen_wur(par[0], cpu_R[arg[0]]); - } else { - qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]); - } + if (uregnames[par[0]].name) { + gen_wur(par[0], cpu_R[arg[0]]); + } else { + qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]); } } static void translate_xor(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { - tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); } static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[], @@ -2646,17 +2499,15 @@ static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[], static void translate_xsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0])) { - TCGv_i32 tmp = tcg_temp_new_i32(); - bool rsr_end, wsr_end; + TCGv_i32 tmp = tcg_temp_new_i32(); + bool rsr_end, wsr_end; - tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); - rsr_end = gen_rsr(dc, cpu_R[arg[0]], par[0]); - wsr_end = gen_wsr(dc, par[0], tmp); - tcg_temp_free(tmp); - if (rsr_end && !wsr_end) { - gen_jumpi_check_loop_end(dc, 0); - } + tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); + rsr_end = gen_rsr(dc, cpu_R[arg[0]], par[0]); + wsr_end = gen_wsr(dc, par[0], tmp); + tcg_temp_free(tmp); + if (rsr_end && !wsr_end) { + gen_jumpi_check_loop_end(dc, 0); } } @@ -2664,33 +2515,42 @@ static const XtensaOpcodeOps core_ops[] = { { .name = "abs", .translate = translate_abs, + .windowed_register_op = 0x3, }, { .name = "add", .translate = translate_add, + .windowed_register_op = 0x7, }, { .name = "add.n", .translate = translate_add, + .windowed_register_op = 0x7, }, { .name = "addi", .translate = translate_addi, + .windowed_register_op = 0x3, }, { .name = "addi.n", .translate = translate_addi, + .windowed_register_op = 0x3, }, { .name = "addmi", .translate = translate_addi, + .windowed_register_op = 0x3, }, { .name = "addx2", .translate = translate_addx, .par = (const uint32_t[]){1}, + .windowed_register_op = 0x7, }, { .name = "addx4", .translate = translate_addx, .par = (const uint32_t[]){2}, + .windowed_register_op = 0x7, }, { .name = "addx8", .translate = translate_addx, .par = (const uint32_t[]){3}, + .windowed_register_op = 0x7, }, { .name = "all4", .translate = translate_all, @@ -2702,6 +2562,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "and", .translate = translate_and, + .windowed_register_op = 0x7, }, { .name = "andb", .translate = translate_boolean, @@ -2722,42 +2583,52 @@ static const XtensaOpcodeOps core_ops[] = { .name = "ball", .translate = translate_ball, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x3, }, { .name = "bany", .translate = translate_bany, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x3, }, { .name = "bbc", .translate = translate_bb, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x3, }, { .name = "bbci", .translate = translate_bbi, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x1, }, { .name = "bbs", .translate = translate_bb, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x3, }, { .name = "bbsi", .translate = translate_bbi, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x1, }, { .name = "beq", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x3, }, { .name = "beqi", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x1, }, { .name = "beqz", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x1, }, { .name = "beqz.n", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x1, }, { .name = "bf", .translate = translate_bp, @@ -2766,66 +2637,82 @@ static const XtensaOpcodeOps core_ops[] = { .name = "bge", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_GE}, + .windowed_register_op = 0x3, }, { .name = "bgei", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_GE}, + .windowed_register_op = 0x1, }, { .name = "bgeu", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_GEU}, + .windowed_register_op = 0x3, }, { .name = "bgeui", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_GEU}, + .windowed_register_op = 0x1, }, { .name = "bgez", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_GE}, + .windowed_register_op = 0x1, }, { .name = "blt", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x3, }, { .name = "blti", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x1, }, { .name = "bltu", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_LTU}, + .windowed_register_op = 0x3, }, { .name = "bltui", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_LTU}, + .windowed_register_op = 0x1, }, { .name = "bltz", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x1, }, { .name = "bnall", .translate = translate_ball, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x3, }, { .name = "bne", .translate = translate_b, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x3, }, { .name = "bnei", .translate = translate_bi, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x1, }, { .name = "bnez", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x1, }, { .name = "bnez.n", .translate = translate_bz, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x1, }, { .name = "bnone", .translate = translate_bany, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x3, }, { .name = "break", .translate = translate_nop, @@ -2846,101 +2733,114 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "call12", .translate = translate_callw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){3}, }, { .name = "call4", .translate = translate_callw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){1}, }, { .name = "call8", .translate = translate_callw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){2}, }, { .name = "callx0", .translate = translate_callx0, + .windowed_register_op = 0x1, }, { .name = "callx12", .translate = translate_callxw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){3}, + .windowed_register_op = 0x1, }, { .name = "callx4", .translate = translate_callxw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){1}, + .windowed_register_op = 0x1, }, { .name = "callx8", .translate = translate_callxw, + .test_overflow = test_overflow_callw, .par = (const uint32_t[]){2}, + .windowed_register_op = 0x1, }, { .name = "clamps", .translate = translate_clamps, + .windowed_register_op = 0x3, }, { .name = "clrb_expstate", .translate = translate_clrb_expstate, }, { .name = "const16", .translate = translate_const16, + .windowed_register_op = 0x1, }, { .name = "depbits", .translate = translate_depbits, + .windowed_register_op = 0x3, }, { .name = "dhi", .translate = translate_dcache, - .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "dhu", .translate = translate_dcache, - .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "dhwb", .translate = translate_dcache, - .par = (const uint32_t[]){true}, + .windowed_register_op = 0x1, }, { .name = "dhwbi", .translate = translate_dcache, - .par = (const uint32_t[]){true}, + .windowed_register_op = 0x1, }, { .name = "dii", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "diu", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "diwb", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "diwbi", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "dpfl", .translate = translate_dcache, - .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "dpfr", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, + .windowed_register_op = 0x1, }, { .name = "dpfro", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, + .windowed_register_op = 0x1, }, { .name = "dpfw", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, + .windowed_register_op = 0x1, }, { .name = "dpfwo", - .translate = translate_dcache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, + .windowed_register_op = 0x1, }, { .name = "dsync", .translate = translate_nop, @@ -2948,6 +2848,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "entry", .translate = translate_entry, .test_ill = test_ill_entry, + .test_overflow = test_overflow_entry, }, { .name = "esync", .translate = translate_nop, @@ -2957,6 +2858,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "extui", .translate = translate_extui, + .windowed_register_op = 0x3, }, { .name = "extw", .translate = translate_memw, @@ -2971,30 +2873,32 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_itlb, .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "ihi", .translate = translate_icache, - .par = (const uint32_t[]){true}, + .windowed_register_op = 0x1, }, { .name = "ihu", .translate = translate_icache, - .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "iii", - .translate = translate_icache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "iitlb", .translate = translate_itlb, .par = (const uint32_t[]){false}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "iiu", - .translate = translate_icache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "ill", .op_flags = XTENSA_OP_ILL, @@ -3003,13 +2907,13 @@ static const XtensaOpcodeOps core_ops[] = { .op_flags = XTENSA_OP_ILL, }, { .name = "ipf", - .translate = translate_icache, - .par = (const uint32_t[]){false}, + .translate = translate_nop, + .windowed_register_op = 0x1, }, { .name = "ipfl", .translate = translate_icache, - .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "isync", .translate = translate_nop, @@ -3019,45 +2923,56 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "jx", .translate = translate_jx, + .windowed_register_op = 0x1, }, { .name = "l16si", .translate = translate_ldst, .par = (const uint32_t[]){MO_TESW, false, false}, + .windowed_register_op = 0x3, }, { .name = "l16ui", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUW, false, false}, + .windowed_register_op = 0x3, }, { .name = "l32ai", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, true, false}, + .windowed_register_op = 0x3, }, { .name = "l32e", .translate = translate_l32e, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "l32i", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, false, false}, + .windowed_register_op = 0x3, }, { .name = "l32i.n", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, false, false}, + .windowed_register_op = 0x3, }, { .name = "l32r", .translate = translate_l32r, + .windowed_register_op = 0x1, }, { .name = "l8ui", .translate = translate_ldst, .par = (const uint32_t[]){MO_UB, false, false}, + .windowed_register_op = 0x3, }, { .name = "lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_NONE, 0, 0, -4}, + .windowed_register_op = 0x2, }, { .name = "ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4}, + .windowed_register_op = 0x2, }, { .name = "ldpte", .op_flags = XTENSA_OP_ILL, @@ -3065,116 +2980,146 @@ static const XtensaOpcodeOps core_ops[] = { .name = "loop", .translate = translate_loop, .par = (const uint32_t[]){TCG_COND_NEVER}, + .windowed_register_op = 0x1, }, { .name = "loopgtz", .translate = translate_loop, .par = (const uint32_t[]){TCG_COND_GT}, + .windowed_register_op = 0x1, }, { .name = "loopnez", .translate = translate_loop, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x1, }, { .name = "max", .translate = translate_smax, + .windowed_register_op = 0x7, }, { .name = "maxu", .translate = translate_umax, + .windowed_register_op = 0x7, }, { .name = "memw", .translate = translate_memw, }, { .name = "min", .translate = translate_smin, + .windowed_register_op = 0x7, }, { .name = "minu", .translate = translate_umin, + .windowed_register_op = 0x7, }, { .name = "mov", .translate = translate_mov, + .windowed_register_op = 0x3, }, { .name = "mov.n", .translate = translate_mov, + .windowed_register_op = 0x3, }, { .name = "moveqz", .translate = translate_movcond, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x7, }, { .name = "movf", .translate = translate_movp, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x3, }, { .name = "movgez", .translate = translate_movcond, .par = (const uint32_t[]){TCG_COND_GE}, + .windowed_register_op = 0x7, }, { .name = "movi", .translate = translate_movi, + .windowed_register_op = 0x1, }, { .name = "movi.n", .translate = translate_movi, + .windowed_register_op = 0x1, }, { .name = "movltz", .translate = translate_movcond, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x7, }, { .name = "movnez", .translate = translate_movcond, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x7, }, { .name = "movsp", .translate = translate_movsp, + .windowed_register_op = 0x3, }, { .name = "movt", .translate = translate_movp, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x3, }, { .name = "mul.aa.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HH, 0}, + .windowed_register_op = 0x3, }, { .name = "mul.aa.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HL, 0}, + .windowed_register_op = 0x3, }, { .name = "mul.aa.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LH, 0}, + .windowed_register_op = 0x3, }, { .name = "mul.aa.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LL, 0}, + .windowed_register_op = 0x3, }, { .name = "mul.ad.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HH, 0}, + .windowed_register_op = 0x1, }, { .name = "mul.ad.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HL, 0}, + .windowed_register_op = 0x1, }, { .name = "mul.ad.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LH, 0}, + .windowed_register_op = 0x1, }, { .name = "mul.ad.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LL, 0}, + .windowed_register_op = 0x1, }, { .name = "mul.da.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HH, 0}, + .windowed_register_op = 0x2, }, { .name = "mul.da.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HL, 0}, + .windowed_register_op = 0x2, }, { .name = "mul.da.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LH, 0}, + .windowed_register_op = 0x2, }, { .name = "mul.da.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LL, 0}, + .windowed_register_op = 0x2, }, { .name = "mul.dd.hh", .translate = translate_mac16, @@ -3195,90 +3140,112 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mul16s", .translate = translate_mul16, .par = (const uint32_t[]){true}, + .windowed_register_op = 0x7, }, { .name = "mul16u", .translate = translate_mul16, .par = (const uint32_t[]){false}, + .windowed_register_op = 0x7, }, { .name = "mula.aa.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HH, 0}, + .windowed_register_op = 0x3, }, { .name = "mula.aa.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HL, 0}, + .windowed_register_op = 0x3, }, { .name = "mula.aa.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LH, 0}, + .windowed_register_op = 0x3, }, { .name = "mula.aa.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LL, 0}, + .windowed_register_op = 0x3, }, { .name = "mula.ad.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HH, 0}, + .windowed_register_op = 0x1, }, { .name = "mula.ad.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HL, 0}, + .windowed_register_op = 0x1, }, { .name = "mula.ad.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LH, 0}, + .windowed_register_op = 0x1, }, { .name = "mula.ad.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LL, 0}, + .windowed_register_op = 0x1, }, { .name = "mula.da.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 0}, + .windowed_register_op = 0x2, }, { .name = "mula.da.hh.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, -4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.hh.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 0}, + .windowed_register_op = 0x2, }, { .name = "mula.da.hl.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, -4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.hl.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 0}, + .windowed_register_op = 0x2, }, { .name = "mula.da.lh.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, -4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.lh.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 0}, + .windowed_register_op = 0x2, }, { .name = "mula.da.ll.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, -4}, + .windowed_register_op = 0xa, }, { .name = "mula.da.ll.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 4}, + .windowed_register_op = 0xa, }, { .name = "mula.dd.hh", .translate = translate_mac16, @@ -3287,10 +3254,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mula.dd.hh.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, -4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.hh.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.hl", .translate = translate_mac16, @@ -3299,10 +3268,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mula.dd.hl.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, -4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.hl.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.lh", .translate = translate_mac16, @@ -3311,10 +3282,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mula.dd.lh.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, -4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.lh.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.ll", .translate = translate_mac16, @@ -3323,61 +3296,76 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mula.dd.ll.lddec", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, -4}, + .windowed_register_op = 0x2, }, { .name = "mula.dd.ll.ldinc", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 4}, + .windowed_register_op = 0x2, }, { .name = "mull", .translate = translate_mull, + .windowed_register_op = 0x7, }, { .name = "muls.aa.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HH, 0}, + .windowed_register_op = 0x3, }, { .name = "muls.aa.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HL, 0}, + .windowed_register_op = 0x3, }, { .name = "muls.aa.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LH, 0}, + .windowed_register_op = 0x3, }, { .name = "muls.aa.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LL, 0}, + .windowed_register_op = 0x3, }, { .name = "muls.ad.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HH, 0}, + .windowed_register_op = 0x1, }, { .name = "muls.ad.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HL, 0}, + .windowed_register_op = 0x1, }, { .name = "muls.ad.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LH, 0}, + .windowed_register_op = 0x1, }, { .name = "muls.ad.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LL, 0}, + .windowed_register_op = 0x1, }, { .name = "muls.da.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HH, 0}, + .windowed_register_op = 0x2, }, { .name = "muls.da.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HL, 0}, + .windowed_register_op = 0x2, }, { .name = "muls.da.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LH, 0}, + .windowed_register_op = 0x2, }, { .name = "muls.da.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LL, 0}, + .windowed_register_op = 0x2, }, { .name = "muls.dd.hh", .translate = translate_mac16, @@ -3398,13 +3386,16 @@ static const XtensaOpcodeOps core_ops[] = { .name = "mulsh", .translate = translate_mulh, .par = (const uint32_t[]){true}, + .windowed_register_op = 0x7, }, { .name = "muluh", .translate = translate_mulh, .par = (const uint32_t[]){false}, + .windowed_register_op = 0x7, }, { .name = "neg", .translate = translate_neg, + .windowed_register_op = 0x3, }, { .name = "nop", .translate = translate_nop, @@ -3414,12 +3405,15 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "nsa", .translate = translate_nsa, + .windowed_register_op = 0x3, }, { .name = "nsau", .translate = translate_nsau, + .windowed_register_op = 0x3, }, { .name = "or", .translate = translate_or, + .windowed_register_op = 0x7, }, { .name = "orb", .translate = translate_boolean, @@ -3433,44 +3427,54 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_ptlb, .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "pitlb", .translate = translate_ptlb, .par = (const uint32_t[]){false}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "quos", .translate = translate_quos, .par = (const uint32_t[]){true}, + .windowed_register_op = 0x7, }, { .name = "quou", .translate = translate_quou, .par = (const uint32_t[]){true}, + .windowed_register_op = 0x7, }, { .name = "rdtlb0", .translate = translate_rtlb, .par = (const uint32_t[]){true, 0}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "rdtlb1", .translate = translate_rtlb, .par = (const uint32_t[]){true, 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "read_impwire", .translate = translate_read_impwire, + .windowed_register_op = 0x1, }, { .name = "rems", .translate = translate_quos, .par = (const uint32_t[]){false}, + .windowed_register_op = 0x7, }, { .name = "remu", .translate = translate_quou, .par = (const uint32_t[]){false}, + .windowed_register_op = 0x7, }, { .name = "rer", .translate = translate_rer, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "ret", .translate = translate_ret, @@ -3518,11 +3522,13 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rtlb, .par = (const uint32_t[]){false, 0}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "ritlb1", .translate = translate_rtlb, .par = (const uint32_t[]){false, 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "rotw", .translate = translate_rotw, @@ -3531,449 +3537,526 @@ static const XtensaOpcodeOps core_ops[] = { .name = "rsil", .translate = translate_rsil, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.176", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){176}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.208", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){208}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.acchi", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ACCHI}, + .windowed_register_op = 0x1, }, { .name = "rsr.acclo", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ACCLO}, + .windowed_register_op = 0x1, }, { .name = "rsr.atomctl", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ATOMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.br", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){BR}, + .windowed_register_op = 0x1, }, { .name = "rsr.cacheattr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CACHEATTR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ccompare0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ccompare1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ccompare2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOMPARE + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ccount", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.configid0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID0}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.configid1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CONFIGID1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.cpenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CPENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.dbreaka0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.dbreaka1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.dbreakc0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.dbreakc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DBREAKC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.debugcause", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEBUGCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.depc", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DEPC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.dtlbcfg", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){DTLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.epc7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPC1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.eps7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EPS2 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.exccause", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave4", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave5", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave6", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excsave7", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.excvaddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){EXCVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ibreaka0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ibreaka1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ibreakenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){IBREAKENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.icount", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.icountlevel", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ICOUNTLEVEL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.intclear", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTCLEAR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.intenable", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.interrupt", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.intset", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.itlbcfg", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){ITLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.lbeg", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){LBEG}, + .windowed_register_op = 0x1, }, { .name = "rsr.lcount", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){LCOUNT}, + .windowed_register_op = 0x1, }, { .name = "rsr.lend", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){LEND}, + .windowed_register_op = 0x1, }, { .name = "rsr.litbase", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){LITBASE}, + .windowed_register_op = 0x1, }, { .name = "rsr.m0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR}, + .windowed_register_op = 0x1, }, { .name = "rsr.m1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 1}, + .windowed_register_op = 0x1, }, { .name = "rsr.m2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 2}, + .windowed_register_op = 0x1, }, { .name = "rsr.m3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MR + 3}, + .windowed_register_op = 0x1, }, { .name = "rsr.memctl", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MEMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.misc0", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.misc1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.misc2", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.misc3", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){MISC + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.prid", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PRID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ps", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PS}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.ptevaddr", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){PTEVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.rasid", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){RASID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.sar", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){SAR}, + .windowed_register_op = 0x1, }, { .name = "rsr.scompare1", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){SCOMPARE1}, + .windowed_register_op = 0x1, }, { .name = "rsr.vecbase", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){VECBASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.windowbase", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_BASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsr.windowstart", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){WINDOW_START}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "rsync", .translate = translate_nop, @@ -3981,63 +4064,78 @@ static const XtensaOpcodeOps core_ops[] = { .name = "rur.expstate", .translate = translate_rur, .par = (const uint32_t[]){EXPSTATE}, + .windowed_register_op = 0x1, }, { .name = "rur.fcr", .translate = translate_rur, .par = (const uint32_t[]){FCR}, + .windowed_register_op = 0x1, }, { .name = "rur.fsr", .translate = translate_rur, .par = (const uint32_t[]){FSR}, + .windowed_register_op = 0x1, }, { .name = "rur.threadptr", .translate = translate_rur, .par = (const uint32_t[]){THREADPTR}, + .windowed_register_op = 0x1, }, { .name = "s16i", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUW, false, true}, + .windowed_register_op = 0x3, }, { .name = "s32c1i", .translate = translate_s32c1i, + .windowed_register_op = 0x3, }, { .name = "s32e", .translate = translate_s32e, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "s32i", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, false, true}, + .windowed_register_op = 0x3, }, { .name = "s32i.n", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, false, true}, + .windowed_register_op = 0x3, }, { .name = "s32nb", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, false, true}, + .windowed_register_op = 0x3, }, { .name = "s32ri", .translate = translate_ldst, .par = (const uint32_t[]){MO_TEUL, true, true}, + .windowed_register_op = 0x3, }, { .name = "s8i", .translate = translate_ldst, .par = (const uint32_t[]){MO_UB, false, true}, + .windowed_register_op = 0x3, }, { .name = "salt", .translate = translate_salt, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x7, }, { .name = "saltu", .translate = translate_salt, .par = (const uint32_t[]){TCG_COND_LTU}, + .windowed_register_op = 0x7, }, { .name = "setb_expstate", .translate = translate_setb_expstate, }, { .name = "sext", .translate = translate_sext, + .windowed_register_op = 0x3, }, { .name = "simcall", .translate = translate_simcall, @@ -4046,54 +4144,69 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "sll", .translate = translate_sll, + .windowed_register_op = 0x3, }, { .name = "slli", .translate = translate_slli, + .windowed_register_op = 0x3, }, { .name = "sra", .translate = translate_sra, + .windowed_register_op = 0x3, }, { .name = "srai", .translate = translate_srai, + .windowed_register_op = 0x3, }, { .name = "src", .translate = translate_src, + .windowed_register_op = 0x7, }, { .name = "srl", .translate = translate_srl, + .windowed_register_op = 0x3, }, { .name = "srli", .translate = translate_srli, + .windowed_register_op = 0x3, }, { .name = "ssa8b", .translate = translate_ssa8b, + .windowed_register_op = 0x1, }, { .name = "ssa8l", .translate = translate_ssa8l, + .windowed_register_op = 0x1, }, { .name = "ssai", .translate = translate_ssai, }, { .name = "ssl", .translate = translate_ssl, + .windowed_register_op = 0x1, }, { .name = "ssr", .translate = translate_ssr, + .windowed_register_op = 0x1, }, { .name = "sub", .translate = translate_sub, + .windowed_register_op = 0x7, }, { .name = "subx2", .translate = translate_subx, .par = (const uint32_t[]){1}, + .windowed_register_op = 0x7, }, { .name = "subx4", .translate = translate_subx, .par = (const uint32_t[]){2}, + .windowed_register_op = 0x7, }, { .name = "subx8", .translate = translate_subx, .par = (const uint32_t[]){3}, + .windowed_register_op = 0x7, }, { .name = "syscall", .op_flags = XTENSA_OP_SYSCALL, @@ -4101,18 +4214,22 @@ static const XtensaOpcodeOps core_ops[] = { .name = "umul.aa.hh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HH, 0}, + .windowed_register_op = 0x3, }, { .name = "umul.aa.hl", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HL, 0}, + .windowed_register_op = 0x3, }, { .name = "umul.aa.lh", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LH, 0}, + .windowed_register_op = 0x3, }, { .name = "umul.aa.ll", .translate = translate_mac16, .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LL, 0}, + .windowed_register_op = 0x3, }, { .name = "waiti", .translate = translate_waiti, @@ -4122,486 +4239,572 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wtlb, .par = (const uint32_t[]){true}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "wer", .translate = translate_wer, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "witlb", .translate = translate_wtlb, .par = (const uint32_t[]){false}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x3, }, { .name = "wrmsk_expstate", .translate = translate_wrmsk_expstate, + .windowed_register_op = 0x3, }, { .name = "wsr.176", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){176}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.208", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){208}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.acchi", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ACCHI}, + .windowed_register_op = 0x1, }, { .name = "wsr.acclo", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ACCLO}, + .windowed_register_op = 0x1, }, { .name = "wsr.atomctl", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ATOMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.br", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){BR}, + .windowed_register_op = 0x1, }, { .name = "wsr.cacheattr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CACHEATTR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ccompare0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ccompare1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ccompare2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ccount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.configid0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID0}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.configid1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CONFIGID1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.cpenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CPENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.dbreaka0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.dbreaka1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.dbreakc0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.dbreakc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DBREAKC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.debugcause", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEBUGCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.depc", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DEPC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.dtlbcfg", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){DTLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.epc7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPC1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.eps7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EPS2 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.exccause", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave4", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave5", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave6", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excsave7", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.excvaddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){EXCVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ibreaka0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ibreaka1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ibreakenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.icount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.icountlevel", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNTLEVEL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.intclear", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTCLEAR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.intenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.interrupt", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.intset", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.itlbcfg", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ITLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.lbeg", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LBEG}, + .windowed_register_op = 0x1, }, { .name = "wsr.lcount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LCOUNT}, + .windowed_register_op = 0x1, }, { .name = "wsr.lend", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LEND}, + .windowed_register_op = 0x1, }, { .name = "wsr.litbase", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LITBASE}, + .windowed_register_op = 0x1, }, { .name = "wsr.m0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR}, + .windowed_register_op = 0x1, }, { .name = "wsr.m1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 1}, + .windowed_register_op = 0x1, }, { .name = "wsr.m2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 2}, + .windowed_register_op = 0x1, }, { .name = "wsr.m3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MR + 3}, + .windowed_register_op = 0x1, }, { .name = "wsr.memctl", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MEMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.misc0", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.misc1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.misc2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.misc3", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MISC + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.mmid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){MMID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.prid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PRID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ps", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PS}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.ptevaddr", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PTEVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.rasid", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){RASID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.sar", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){SAR}, + .windowed_register_op = 0x1, }, { .name = "wsr.scompare1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){SCOMPARE1}, + .windowed_register_op = 0x1, }, { .name = "wsr.vecbase", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){VECBASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.windowbase", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_BASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wsr.windowstart", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_START}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "wur.expstate", .translate = translate_wur, .par = (const uint32_t[]){EXPSTATE}, + .windowed_register_op = 0x1, }, { .name = "wur.fcr", .translate = translate_wur, .par = (const uint32_t[]){FCR}, + .windowed_register_op = 0x1, }, { .name = "wur.fsr", .translate = translate_wur, .par = (const uint32_t[]){FSR}, + .windowed_register_op = 0x1, }, { .name = "wur.threadptr", .translate = translate_wur, .par = (const uint32_t[]){THREADPTR}, + .windowed_register_op = 0x1, }, { .name = "xor", .translate = translate_xor, + .windowed_register_op = 0x7, }, { .name = "xorb", .translate = translate_boolean, @@ -4612,443 +4815,519 @@ static const XtensaOpcodeOps core_ops[] = { .test_ill = test_ill_xsr, .par = (const uint32_t[]){176}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.208", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){208}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.acchi", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ACCHI}, + .windowed_register_op = 0x1, }, { .name = "xsr.acclo", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ACCLO}, + .windowed_register_op = 0x1, }, { .name = "xsr.atomctl", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ATOMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.br", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){BR}, + .windowed_register_op = 0x1, }, { .name = "xsr.cacheattr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CACHEATTR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ccompare0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ccompare1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ccompare2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ccount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.configid0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID0}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.configid1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CONFIGID1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.cpenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CPENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.dbreaka0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.dbreaka1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.dbreakc0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.dbreakc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DBREAKC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.debugcause", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEBUGCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.depc", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DEPC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.dtlbcfg", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){DTLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.epc7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPC1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.eps7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EPS2 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.exccause", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCCAUSE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave4", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave5", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 4}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave6", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 5}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excsave7", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCSAVE1 + 6}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.excvaddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){EXCVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ibreaka0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ibreaka1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ibreakenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.icount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNT}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.icountlevel", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNTLEVEL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.intclear", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTCLEAR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.intenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTENABLE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.interrupt", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.intset", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.itlbcfg", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ITLBCFG}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.lbeg", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LBEG}, + .windowed_register_op = 0x1, }, { .name = "xsr.lcount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LCOUNT}, + .windowed_register_op = 0x1, }, { .name = "xsr.lend", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LEND}, + .windowed_register_op = 0x1, }, { .name = "xsr.litbase", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LITBASE}, + .windowed_register_op = 0x1, }, { .name = "xsr.m0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR}, + .windowed_register_op = 0x1, }, { .name = "xsr.m1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 1}, + .windowed_register_op = 0x1, }, { .name = "xsr.m2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 2}, + .windowed_register_op = 0x1, }, { .name = "xsr.m3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MR + 3}, + .windowed_register_op = 0x1, }, { .name = "xsr.memctl", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MEMCTL}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.misc0", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.misc1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 1}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.misc2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 2}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.misc3", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){MISC + 3}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.prid", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PRID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ps", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PS}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.ptevaddr", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PTEVADDR}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.rasid", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){RASID}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.sar", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){SAR}, + .windowed_register_op = 0x1, }, { .name = "xsr.scompare1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){SCOMPARE1}, + .windowed_register_op = 0x1, }, { .name = "xsr.vecbase", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){VECBASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.windowbase", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_BASE}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, { .name = "xsr.windowstart", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_START}, .op_flags = XTENSA_OP_PRIVILEGED, + .windowed_register_op = 0x1, }, }; @@ -5110,7 +5389,7 @@ static void translate_compare_s(DisasContext *dc, const uint32_t arg[], static void translate_float_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[1]) && gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { TCGv_i32 scale = tcg_const_i32(-arg[2]); if (par[0]) { @@ -5125,7 +5404,7 @@ static void translate_float_s(DisasContext *dc, const uint32_t arg[], static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0]) && gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { TCGv_i32 rounding_mode = tcg_const_i32(par[0]); TCGv_i32 scale = tcg_const_i32(arg[2]); @@ -5144,7 +5423,7 @@ static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[], static void translate_ldsti(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[1]) && gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); @@ -5164,7 +5443,7 @@ static void translate_ldsti(DisasContext *dc, const uint32_t arg[], static void translate_ldstx(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check2(dc, arg[1], arg[2]) && gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]); @@ -5201,7 +5480,7 @@ static void translate_mov_s(DisasContext *dc, const uint32_t arg[], static void translate_movcond_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[2]) && gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { TCGv_i32 zero = tcg_const_i32(0); tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]], @@ -5256,8 +5535,7 @@ static void translate_neg_s(DisasContext *dc, const uint32_t arg[], static void translate_rfr_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[0]) && - gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]); } } @@ -5274,8 +5552,7 @@ static void translate_sub_s(DisasContext *dc, const uint32_t arg[], static void translate_wfr_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_window_check1(dc, arg[1]) && - gen_check_cpenable(dc, 0)) { + if (gen_check_cpenable(dc, 0)) { tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]); } } @@ -5291,30 +5568,37 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "ceil.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_up, false}, + .windowed_register_op = 0x1, }, { .name = "float.s", .translate = translate_float_s, .par = (const uint32_t[]){false}, + .windowed_register_op = 0x2, }, { .name = "floor.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_down, false}, + .windowed_register_op = 0x1, }, { .name = "lsi", .translate = translate_ldsti, .par = (const uint32_t[]){false, false}, + .windowed_register_op = 0x2, }, { .name = "lsiu", .translate = translate_ldsti, .par = (const uint32_t[]){false, true}, + .windowed_register_op = 0x2, }, { .name = "lsx", .translate = translate_ldstx, .par = (const uint32_t[]){false, false}, + .windowed_register_op = 0x6, }, { .name = "lsxu", .translate = translate_ldstx, .par = (const uint32_t[]){false, true}, + .windowed_register_op = 0x6, }, { .name = "madd.s", .translate = translate_madd_s, @@ -5325,6 +5609,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "moveqz.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_EQ}, + .windowed_register_op = 0x4, }, { .name = "movf.s", .translate = translate_movp_s, @@ -5333,14 +5618,17 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "movgez.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_GE}, + .windowed_register_op = 0x4, }, { .name = "movltz.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_LT}, + .windowed_register_op = 0x4, }, { .name = "movnez.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_NE}, + .windowed_register_op = 0x4, }, { .name = "movt.s", .translate = translate_movp_s, @@ -5369,26 +5657,32 @@ static const XtensaOpcodeOps fpu2000_ops[] = { }, { .name = "rfr", .translate = translate_rfr_s, + .windowed_register_op = 0x1, }, { .name = "round.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_nearest_even, false}, + .windowed_register_op = 0x1, }, { .name = "ssi", .translate = translate_ldsti, .par = (const uint32_t[]){true, false}, + .windowed_register_op = 0x2, }, { .name = "ssiu", .translate = translate_ldsti, .par = (const uint32_t[]){true, true}, + .windowed_register_op = 0x2, }, { .name = "ssx", .translate = translate_ldstx, .par = (const uint32_t[]){true, false}, + .windowed_register_op = 0x6, }, { .name = "ssxu", .translate = translate_ldstx, .par = (const uint32_t[]){true, true}, + .windowed_register_op = 0x6, }, { .name = "sub.s", .translate = translate_sub_s, @@ -5396,6 +5690,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "trunc.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_to_zero, false}, + .windowed_register_op = 0x1, }, { .name = "ueq.s", .translate = translate_compare_s, @@ -5404,6 +5699,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "ufloat.s", .translate = translate_float_s, .par = (const uint32_t[]){true}, + .windowed_register_op = 0x2, }, { .name = "ule.s", .translate = translate_compare_s, @@ -5420,9 +5716,11 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .name = "utrunc.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_to_zero, true}, + .windowed_register_op = 0x1, }, { .name = "wfr", .translate = translate_wfr_s, + .windowed_register_op = 0x2, }, }; From f473019a97d7c890ddb816367dc9f89fdfefa22e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 30 Aug 2018 17:55:33 -0700 Subject: [PATCH 06/15] target/xtensa: extract test for window underflow exception - mark retw and retw.n instructions; - extract window inderflow test from retw helper; - put underflow exception check generation right after the overflow check; Signed-off-by: Max Filippov --- target/xtensa/helper.h | 1 + target/xtensa/op_helper.c | 24 +++++++++++++++--------- target/xtensa/translate.c | 9 +++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h index c1b3bacb4c..10153c2453 100644 --- a/target/xtensa/helper.h +++ b/target/xtensa/helper.h @@ -6,6 +6,7 @@ DEF_HELPER_3(debug_exception, noreturn, env, i32, i32) DEF_HELPER_2(wsr_windowbase, void, env, i32) DEF_HELPER_4(entry, void, env, i32, i32, i32) DEF_HELPER_2(test_ill_retw, void, env, i32) +DEF_HELPER_2(test_underflow_retw, void, env, i32) DEF_HELPER_2(retw, i32, env, i32) DEF_HELPER_2(rotw, void, env, i32) DEF_HELPER_3(window_check, noreturn, env, i32, i32) diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 68052851af..e4b42ab3e5 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -310,19 +310,15 @@ void HELPER(test_ill_retw)(CPUXtensaState *env, uint32_t pc) } } -uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) +void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc) { int n = (env->regs[0] >> 30) & 0x3; - uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); - uint32_t windowstart = env->sregs[WINDOW_START]; - uint32_t ret_pc = 0; - ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); + if (!(env->sregs[WINDOW_START] & + windowstart_bit(env->sregs[WINDOW_BASE] - n, env))) { + uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); - xtensa_rotate_window(env, -n); - if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { - env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env); - } else { + xtensa_rotate_window(env, -n); /* window underflow */ env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | (windowbase << PS_OWB_SHIFT) | PS_EXCM; @@ -336,6 +332,16 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12); } } +} + +uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc) +{ + int n = (env->regs[0] >> 30) & 0x3; + uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); + uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); + + xtensa_rotate_window(env, -n); + env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env); return ret_pc; } diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 83e107a2ac..187de7467f 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1071,6 +1071,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; } + if (op_flags & XTENSA_OP_UNDERFLOW) { + TCGv_i32 tmp = tcg_const_i32(dc->pc); + + gen_helper_test_underflow_retw(cpu_env, tmp); + tcg_temp_free(tmp); + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -3485,10 +3492,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "retw", .translate = translate_retw, .test_ill = test_ill_retw, + .op_flags = XTENSA_OP_UNDERFLOW, }, { .name = "retw.n", .translate = translate_retw, .test_ill = test_ill_retw, + .op_flags = XTENSA_OP_UNDERFLOW, }, { .name = "rfdd", .op_flags = XTENSA_OP_ILL, From 90d6494d130afa6de932fb1fa2eed8296d702836 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 30 Aug 2018 18:21:22 -0700 Subject: [PATCH 07/15] target/xtensa: extract test for alloca exception - mark movsp instruction; - put test for alloca exception right after the test for window underflow; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 187de7467f..12c54b674e 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1078,6 +1078,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) tcg_temp_free(tmp); } + if (op_flags & XTENSA_OP_ALLOCA) { + TCGv_i32 tmp = tcg_const_i32(dc->pc); + + gen_helper_movsp(cpu_env, tmp); + tcg_temp_free(tmp); + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -1918,10 +1925,7 @@ static void translate_movp(DisasContext *dc, const uint32_t arg[], static void translate_movsp(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - TCGv_i32 pc = tcg_const_i32(dc->pc); - gen_helper_movsp(cpu_env, pc); tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); - tcg_temp_free(pc); } static void translate_mul16(DisasContext *dc, const uint32_t arg[], @@ -3062,6 +3066,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "movsp", .translate = translate_movsp, .windowed_register_op = 0x3, + .op_flags = XTENSA_OP_ALLOCA, }, { .name = "movt", .translate = translate_movp, From 582fef0f47876da8968ac8d867922e040a02ebae Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Aug 2018 13:57:08 -0700 Subject: [PATCH 08/15] target/xtensa: extract test for cpdisabled exception - add XtensaOpcodeOps::coprocessor with bitmask of coprocessors used by the instruction; - replace coprocessor id parameter of gen_check_cpenable with the bitmask of used coprocessors; - collect coprocessor IDs used by an instruction in the disassembly loop; - put test for coprocessor disabled exception after the alloca test; Signed-off-by: Max Filippov --- target/xtensa/cpu.h | 1 + target/xtensa/translate.c | 230 ++++++++++++++++++++------------------ 2 files changed, 123 insertions(+), 108 deletions(-) diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index be234958a2..34e5ccd9f1 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -381,6 +381,7 @@ typedef struct XtensaOpcodeOps { const uint32_t *par; uint32_t op_flags; uint32_t windowed_register_op; + uint32_t coprocessor; } XtensaOpcodeOps; typedef struct XtensaOpcodeTranslators { diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 12c54b674e..e4f3101bda 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -351,11 +351,12 @@ static bool gen_check_privilege(DisasContext *dc) return false; } -static bool gen_check_cpenable(DisasContext *dc, unsigned cp) +static bool gen_check_cpenable(DisasContext *dc, uint32_t cp_mask) { - if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) && - !(dc->cpenable & (1 << cp))) { - gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp); + cp_mask &= ~dc->cpenable; + + if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) && cp_mask) { + gen_exception_cause(dc, COPROCESSOR0_DISABLED + ctz32(cp_mask)); dc->base.is_jmp = DISAS_NORETURN; return false; } @@ -953,6 +954,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } slot_prop[MAX_INSN_SLOTS]; uint32_t debug_cause = 0; uint32_t windowed_register = 0; + uint32_t coprocessor = 0; if (len == XTENSA_UNDEFINED) { qemu_log_mask(LOG_GUEST_ERROR, @@ -1050,6 +1052,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) reg_opnd ^= 1 << i; } } + coprocessor |= ops->coprocessor; } if ((op_flags & XTENSA_OP_PRIVILEGED) && @@ -1085,6 +1088,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) tcg_temp_free(tmp); } + if (coprocessor && !gen_check_cpenable(dc, coprocessor)) { + return; + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -4084,11 +4091,13 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rur, .par = (const uint32_t[]){FCR}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "rur.fsr", .translate = translate_rur, .par = (const uint32_t[]){FSR}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "rur.threadptr", .translate = translate_rur, @@ -4805,11 +4814,13 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wur, .par = (const uint32_t[]){FCR}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "wur.fsr", .translate = translate_wur, .par = (const uint32_t[]){FSR}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "wur.threadptr", .translate = translate_wur, @@ -5354,18 +5365,14 @@ const XtensaOpcodeTranslators xtensa_core_opcodes = { static void translate_abs_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); - } + gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); } static void translate_add_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_add_s(cpu_FR[arg[0]], cpu_env, - cpu_FR[arg[1]], cpu_FR[arg[2]]); - } + gen_helper_add_s(cpu_FR[arg[0]], cpu_env, + cpu_FR[arg[1]], cpu_FR[arg[2]]); } enum { @@ -5391,350 +5398,357 @@ static void translate_compare_s(DisasContext *dc, const uint32_t arg[], [COMPARE_OLE] = gen_helper_ole_s, [COMPARE_ULE] = gen_helper_ule_s, }; + TCGv_i32 bit = tcg_const_i32(1 << arg[0]); - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 bit = tcg_const_i32(1 << arg[0]); - - helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]); - tcg_temp_free(bit); - } + helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]); + tcg_temp_free(bit); } static void translate_float_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 scale = tcg_const_i32(-arg[2]); + TCGv_i32 scale = tcg_const_i32(-arg[2]); - if (par[0]) { - gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); - } else { - gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); - } - tcg_temp_free(scale); + if (par[0]) { + gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); + } else { + gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); } + tcg_temp_free(scale); } static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 rounding_mode = tcg_const_i32(par[0]); - TCGv_i32 scale = tcg_const_i32(arg[2]); + TCGv_i32 rounding_mode = tcg_const_i32(par[0]); + TCGv_i32 scale = tcg_const_i32(arg[2]); - if (par[1]) { - gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]], - rounding_mode, scale); - } else { - gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]], - rounding_mode, scale); - } - tcg_temp_free(rounding_mode); - tcg_temp_free(scale); + if (par[1]) { + gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]], + rounding_mode, scale); + } else { + gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]], + rounding_mode, scale); } + tcg_temp_free(rounding_mode); + tcg_temp_free(scale); } static void translate_ldsti(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); - gen_load_store_alignment(dc, 2, addr, false); - if (par[0]) { - tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); - } else { - tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); - } - if (par[1]) { - tcg_gen_mov_i32(cpu_R[arg[1]], addr); - } - tcg_temp_free(addr); + tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); + gen_load_store_alignment(dc, 2, addr, false); + if (par[0]) { + tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); + } else { + tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); } + if (par[1]) { + tcg_gen_mov_i32(cpu_R[arg[1]], addr); + } + tcg_temp_free(addr); } static void translate_ldstx(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 addr = tcg_temp_new_i32(); + TCGv_i32 addr = tcg_temp_new_i32(); - tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]); - gen_load_store_alignment(dc, 2, addr, false); - if (par[0]) { - tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); - } else { - tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); - } - if (par[1]) { - tcg_gen_mov_i32(cpu_R[arg[1]], addr); - } - tcg_temp_free(addr); + tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]); + gen_load_store_alignment(dc, 2, addr, false); + if (par[0]) { + tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); + } else { + tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); } + if (par[1]) { + tcg_gen_mov_i32(cpu_R[arg[1]], addr); + } + tcg_temp_free(addr); } static void translate_madd_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_madd_s(cpu_FR[arg[0]], cpu_env, - cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); - } + gen_helper_madd_s(cpu_FR[arg[0]], cpu_env, + cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); } static void translate_mov_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]); - } + tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]); } static void translate_movcond_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 zero = tcg_const_i32(0); - tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]], - cpu_R[arg[2]], zero, - cpu_FR[arg[1]], cpu_FR[arg[0]]); - tcg_temp_free(zero); - } + tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]], + cpu_R[arg[2]], zero, + cpu_FR[arg[1]], cpu_FR[arg[0]]); + tcg_temp_free(zero); } static void translate_movp_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - TCGv_i32 zero = tcg_const_i32(0); - TCGv_i32 tmp = tcg_temp_new_i32(); + TCGv_i32 zero = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); - tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); - tcg_gen_movcond_i32(par[0], - cpu_FR[arg[0]], tmp, zero, - cpu_FR[arg[1]], cpu_FR[arg[0]]); - tcg_temp_free(tmp); - tcg_temp_free(zero); - } + tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); + tcg_gen_movcond_i32(par[0], + cpu_FR[arg[0]], tmp, zero, + cpu_FR[arg[1]], cpu_FR[arg[0]]); + tcg_temp_free(tmp); + tcg_temp_free(zero); } static void translate_mul_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_mul_s(cpu_FR[arg[0]], cpu_env, - cpu_FR[arg[1]], cpu_FR[arg[2]]); - } + gen_helper_mul_s(cpu_FR[arg[0]], cpu_env, + cpu_FR[arg[1]], cpu_FR[arg[2]]); } static void translate_msub_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_msub_s(cpu_FR[arg[0]], cpu_env, - cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); - } + gen_helper_msub_s(cpu_FR[arg[0]], cpu_env, + cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); } static void translate_neg_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); - } + gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); } static void translate_rfr_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]); - } + tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]); } static void translate_sub_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - gen_helper_sub_s(cpu_FR[arg[0]], cpu_env, - cpu_FR[arg[1]], cpu_FR[arg[2]]); - } + gen_helper_sub_s(cpu_FR[arg[0]], cpu_env, + cpu_FR[arg[1]], cpu_FR[arg[2]]); } static void translate_wfr_s(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_check_cpenable(dc, 0)) { - tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]); - } + tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]); } static const XtensaOpcodeOps fpu2000_ops[] = { { .name = "abs.s", .translate = translate_abs_s, + .coprocessor = 0x1, }, { .name = "add.s", .translate = translate_add_s, + .coprocessor = 0x1, }, { .name = "ceil.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_up, false}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "float.s", .translate = translate_float_s, .par = (const uint32_t[]){false}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "floor.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_down, false}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "lsi", .translate = translate_ldsti, .par = (const uint32_t[]){false, false}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "lsiu", .translate = translate_ldsti, .par = (const uint32_t[]){false, true}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "lsx", .translate = translate_ldstx, .par = (const uint32_t[]){false, false}, .windowed_register_op = 0x6, + .coprocessor = 0x1, }, { .name = "lsxu", .translate = translate_ldstx, .par = (const uint32_t[]){false, true}, .windowed_register_op = 0x6, + .coprocessor = 0x1, }, { .name = "madd.s", .translate = translate_madd_s, + .coprocessor = 0x1, }, { .name = "mov.s", .translate = translate_mov_s, + .coprocessor = 0x1, }, { .name = "moveqz.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_EQ}, .windowed_register_op = 0x4, + .coprocessor = 0x1, }, { .name = "movf.s", .translate = translate_movp_s, .par = (const uint32_t[]){TCG_COND_EQ}, + .coprocessor = 0x1, }, { .name = "movgez.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_GE}, .windowed_register_op = 0x4, + .coprocessor = 0x1, }, { .name = "movltz.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_LT}, .windowed_register_op = 0x4, + .coprocessor = 0x1, }, { .name = "movnez.s", .translate = translate_movcond_s, .par = (const uint32_t[]){TCG_COND_NE}, .windowed_register_op = 0x4, + .coprocessor = 0x1, }, { .name = "movt.s", .translate = translate_movp_s, .par = (const uint32_t[]){TCG_COND_NE}, + .coprocessor = 0x1, }, { .name = "msub.s", .translate = translate_msub_s, + .coprocessor = 0x1, }, { .name = "mul.s", .translate = translate_mul_s, + .coprocessor = 0x1, }, { .name = "neg.s", .translate = translate_neg_s, + .coprocessor = 0x1, }, { .name = "oeq.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_OEQ}, + .coprocessor = 0x1, }, { .name = "ole.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_OLE}, + .coprocessor = 0x1, }, { .name = "olt.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_OLT}, + .coprocessor = 0x1, }, { .name = "rfr", .translate = translate_rfr_s, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "round.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_nearest_even, false}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "ssi", .translate = translate_ldsti, .par = (const uint32_t[]){true, false}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "ssiu", .translate = translate_ldsti, .par = (const uint32_t[]){true, true}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "ssx", .translate = translate_ldstx, .par = (const uint32_t[]){true, false}, .windowed_register_op = 0x6, + .coprocessor = 0x1, }, { .name = "ssxu", .translate = translate_ldstx, .par = (const uint32_t[]){true, true}, .windowed_register_op = 0x6, + .coprocessor = 0x1, }, { .name = "sub.s", .translate = translate_sub_s, + .coprocessor = 0x1, }, { .name = "trunc.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_to_zero, false}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "ueq.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_UEQ}, + .coprocessor = 0x1, }, { .name = "ufloat.s", .translate = translate_float_s, .par = (const uint32_t[]){true}, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, { .name = "ule.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_ULE}, + .coprocessor = 0x1, }, { .name = "ult.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_ULT}, + .coprocessor = 0x1, }, { .name = "un.s", .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_UN}, + .coprocessor = 0x1, }, { .name = "utrunc.s", .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_to_zero, true}, .windowed_register_op = 0x1, + .coprocessor = 0x1, }, { .name = "wfr", .translate = translate_wfr_s, .windowed_register_op = 0x2, + .coprocessor = 0x1, }, }; From 4a038955dadd063b17c1d67bc2811707cfa56719 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Aug 2018 21:26:54 -0700 Subject: [PATCH 09/15] target/xtensa: extract test for division by zero - mark quos/quou/rems/remu instructions; - drop parameter 0 from the translate_quou and split translate_remu from it; - put test for division by zero exception right after the coprocessor exception test; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 53 +++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index e4f3101bda..29a536436d 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -933,6 +933,15 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned) return m; } +static void gen_zero_check(DisasContext *dc, const uint32_t arg[]) +{ + TCGLabel *label = gen_new_label(); + + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label); + gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE); + gen_set_label(label); +} + static inline unsigned xtensa_op0_insn_len(DisasContext *dc, uint8_t op0) { return xtensa_isa_length_from_chars(dc->config->isa, &op0); @@ -1092,6 +1101,14 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; } + if (op_flags & XTENSA_OP_DIVIDE_BY_ZERO) { + for (slot = 0; slot < slots; ++slot) { + if (slot_prop[slot].ops->op_flags & XTENSA_OP_DIVIDE_BY_ZERO) { + gen_zero_check(dc, slot_prop[slot].arg); + } + } + } + for (slot = 0; slot < slots; ++slot) { XtensaOpcodeOps *ops = slot_prop[slot].ops; @@ -2013,23 +2030,12 @@ static void translate_ptlb(DisasContext *dc, const uint32_t arg[], #endif } -static void gen_zero_check(DisasContext *dc, const uint32_t arg[]) -{ - TCGLabel *label = gen_new_label(); - - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label); - gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE); - gen_set_label(label); -} - static void translate_quos(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { TCGLabel *label1 = gen_new_label(); TCGLabel *label2 = gen_new_label(); - gen_zero_check(dc, arg); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000, label1); tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff, @@ -2051,14 +2057,8 @@ static void translate_quos(DisasContext *dc, const uint32_t arg[], static void translate_quou(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - gen_zero_check(dc, arg); - if (par[0]) { - tcg_gen_divu_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } else { - tcg_gen_remu_i32(cpu_R[arg[0]], - cpu_R[arg[1]], cpu_R[arg[2]]); - } + tcg_gen_divu_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); } static void translate_read_impwire(DisasContext *dc, const uint32_t arg[], @@ -2068,6 +2068,13 @@ static void translate_read_impwire(DisasContext *dc, const uint32_t arg[], tcg_gen_movi_i32(cpu_R[arg[0]], 0); } +static void translate_remu(DisasContext *dc, const uint32_t arg[], + const uint32_t par[]) +{ + tcg_gen_remu_i32(cpu_R[arg[0]], + cpu_R[arg[1]], cpu_R[arg[2]]); +} + static void translate_rer(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { @@ -3457,11 +3464,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "quos", .translate = translate_quos, .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_DIVIDE_BY_ZERO, .windowed_register_op = 0x7, }, { .name = "quou", .translate = translate_quou, - .par = (const uint32_t[]){true}, + .op_flags = XTENSA_OP_DIVIDE_BY_ZERO, .windowed_register_op = 0x7, }, { .name = "rdtlb0", @@ -3483,11 +3491,12 @@ static const XtensaOpcodeOps core_ops[] = { .name = "rems", .translate = translate_quos, .par = (const uint32_t[]){false}, + .op_flags = XTENSA_OP_DIVIDE_BY_ZERO, .windowed_register_op = 0x7, }, { .name = "remu", - .translate = translate_quou, - .par = (const uint32_t[]){false}, + .translate = translate_remu, + .op_flags = XTENSA_OP_DIVIDE_BY_ZERO, .windowed_register_op = 0x7, }, { .name = "rer", From 226444a8444b7b3269442505026c78766a6870db Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 1 Sep 2018 00:47:55 -0700 Subject: [PATCH 10/15] target/xtensa: extract unconditional TB termination - mark all instructions that exit TB and require dynamic search for the next TB; - put TB termination right after the instruction translation loop; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 67 ++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 29a536436d..c55447db36 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -572,8 +572,6 @@ static bool gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s) static bool gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s) { tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -587,16 +585,12 @@ static bool gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s) static bool gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_windowbase(cpu_env, v); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } static bool gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -609,8 +603,6 @@ static bool gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_rasid(cpu_env, v); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -680,8 +672,6 @@ static bool gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0xff); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -738,8 +728,6 @@ static bool gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) } tcg_gen_andi_i32(cpu_SR[sr], v, mask); gen_check_interrupts(dc); - /* This can change mmu index and tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -770,8 +758,6 @@ static bool gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0xf); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); return true; } @@ -1115,6 +1101,14 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) dc->raw_arg = slot_prop[slot].raw_arg; ops->translate(dc, slot_prop[slot].arg, ops->par); } + + if (dc->base.is_jmp == DISAS_NEXT) { + if (op_flags & XTENSA_OP_EXIT_TB_M1) { + /* Change in mmu index, memory mapping or tb->flags; exit tb */ + gen_jumpi_check_loop_end(dc, -1); + } + } + if (dc->base.is_jmp == DISAS_NEXT) { gen_check_loop_end(dc, 0); } @@ -1664,8 +1658,6 @@ static void translate_entry(DisasContext *dc, const uint32_t arg[], tcg_temp_free(imm); tcg_temp_free(s); tcg_temp_free(pc); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); } static void translate_extui(DisasContext *dc, const uint32_t arg[], @@ -1699,8 +1691,6 @@ static void translate_itlb(DisasContext *dc, const uint32_t arg[], TCGv_i32 dtlb = tcg_const_i32(par[0]); gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb); - /* This could change memory mapping, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); tcg_temp_free(dtlb); #endif } @@ -2163,8 +2153,6 @@ static void translate_rotw(DisasContext *dc, const uint32_t arg[], TCGv_i32 tmp = tcg_const_i32(arg[0]); gen_helper_rotw(cpu_env, tmp); tcg_temp_free(tmp); - /* This can change tb->flags, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); } static void translate_rsil(DisasContext *dc, const uint32_t arg[], @@ -2468,8 +2456,6 @@ static void translate_wtlb(DisasContext *dc, const uint32_t arg[], TCGv_i32 dtlb = tcg_const_i32(par[0]); gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb); - /* This could change memory mapping, so exit tb */ - gen_jumpi_check_loop_end(dc, -1); tcg_temp_free(dtlb); #endif } @@ -2874,6 +2860,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_entry, .test_ill = test_ill_entry, .test_overflow = test_overflow_entry, + .op_flags = XTENSA_OP_EXIT_TB_M1, }, { .name = "esync", .translate = translate_nop, @@ -2897,7 +2884,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "idtlb", .translate = translate_itlb, .par = (const uint32_t[]){true}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "ihi", @@ -2917,7 +2904,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "iitlb", .translate = translate_itlb, .par = (const uint32_t[]){false}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "iiu", @@ -3562,7 +3549,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rotw", .translate = translate_rotw, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, }, { .name = "rsil", .translate = translate_rsil, @@ -4270,7 +4257,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "wdtlb", .translate = translate_wtlb, .par = (const uint32_t[]){true}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x3, }, { .name = "wer", @@ -4281,7 +4268,7 @@ static const XtensaOpcodeOps core_ops[] = { .name = "witlb", .translate = translate_wtlb, .par = (const uint32_t[]){false}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x3, }, { .name = "wrmsk_expstate", @@ -4380,7 +4367,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CPENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.dbreaka0", @@ -4625,7 +4612,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){ICOUNTLEVEL}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.intclear", @@ -4685,6 +4672,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LITBASE}, + .op_flags = XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.m0", @@ -4764,7 +4752,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PS}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.ptevaddr", @@ -4778,7 +4766,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){RASID}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.sar", @@ -4804,14 +4792,14 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_BASE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wsr.windowstart", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){WINDOW_START}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "wur.expstate", @@ -4936,7 +4924,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CPENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.dbreaka0", @@ -5181,7 +5169,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){ICOUNTLEVEL}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.intclear", @@ -5241,6 +5229,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LITBASE}, + .op_flags = XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.m0", @@ -5313,7 +5302,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PS}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.ptevaddr", @@ -5327,7 +5316,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){RASID}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.sar", @@ -5353,14 +5342,14 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_BASE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, { .name = "xsr.windowstart", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){WINDOW_START}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, .windowed_register_op = 0x1, }, }; From 9dccbd1c69fd928a8eafbb171374029967143673 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 1 Sep 2018 21:48:59 -0700 Subject: [PATCH 11/15] target/xtensa: change SR number checks to assertions Opcode decoding with libisa takes care about range of valid group SRs, like CCOMPARE, IBREAKA, DBREAKA or DBREAKC. Turn range checks in wsr implementations into assertions. Signed-off-by: Max Filippov --- target/xtensa/translate.c | 65 +++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index c55447db36..cb72669704 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -634,38 +634,34 @@ static bool gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - IBREAKA; + TCGv_i32 tmp = tcg_const_i32(id); - if (id < dc->config->nibreak) { - TCGv_i32 tmp = tcg_const_i32(id); - gen_helper_wsr_ibreaka(cpu_env, tmp, v); - tcg_temp_free(tmp); - gen_jumpi_check_loop_end(dc, 0); - return true; - } - return false; + assert(id < dc->config->nibreak); + gen_helper_wsr_ibreaka(cpu_env, tmp, v); + tcg_temp_free(tmp); + gen_jumpi_check_loop_end(dc, 0); + return true; } static bool gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - DBREAKA; + TCGv_i32 tmp = tcg_const_i32(id); - if (id < dc->config->ndbreak) { - TCGv_i32 tmp = tcg_const_i32(id); - gen_helper_wsr_dbreaka(cpu_env, tmp, v); - tcg_temp_free(tmp); - } + assert(id < dc->config->ndbreak); + gen_helper_wsr_dbreaka(cpu_env, tmp, v); + tcg_temp_free(tmp); return false; } static bool gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - DBREAKC; + TCGv_i32 tmp = tcg_const_i32(id); - if (id < dc->config->ndbreak) { - TCGv_i32 tmp = tcg_const_i32(id); - gen_helper_wsr_dbreakc(cpu_env, tmp, v); - tcg_temp_free(tmp); - } + assert(id < dc->config->ndbreak); + gen_helper_wsr_dbreakc(cpu_env, tmp, v); + tcg_temp_free(tmp); return false; } @@ -764,26 +760,23 @@ static bool gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) { uint32_t id = sr - CCOMPARE; - bool ret = false; + uint32_t int_bit = 1 << dc->config->timerint[id]; + TCGv_i32 tmp = tcg_const_i32(id); - if (id < dc->config->nccompare) { - uint32_t int_bit = 1 << dc->config->timerint[id]; - TCGv_i32 tmp = tcg_const_i32(id); - - tcg_gen_mov_i32(cpu_SR[sr], v); - tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit); - if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { - gen_io_start(); - } - gen_helper_update_ccompare(cpu_env, tmp); - if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { - gen_io_end(); - gen_jumpi_check_loop_end(dc, 0); - ret = true; - } - tcg_temp_free(tmp); + assert(id < dc->config->nccompare); + tcg_gen_mov_i32(cpu_SR[sr], v); + tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit); + if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); } - return ret; + gen_helper_update_ccompare(cpu_env, tmp); + tcg_temp_free(tmp); + if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { + gen_io_end(); + gen_jumpi_check_loop_end(dc, 0); + return true; + } + return false; } #else static void gen_check_interrupts(DisasContext *dc) From 06ec08a0be86c249163284dbb5e9f4828155fa83 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 1 Sep 2018 21:56:21 -0700 Subject: [PATCH 12/15] target/xtensa: always end TB on CCOUNT access/CCOMPARE write Currently we only end TB in icount mode, because access to CCOUNT or write to CCOMPARE are IO operations. Simplify the behaviour a bit and end TB unconditionally. Signed-off-by: Max Filippov --- target/xtensa/translate.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index cb72669704..7995a4d4ea 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -505,9 +505,8 @@ static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) tcg_gen_mov_i32(d, cpu_SR[sr]); if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - return true; } - return false; + return true; } static bool gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr) @@ -735,10 +734,9 @@ static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) gen_helper_wsr_ccount(cpu_env, v); if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - gen_jumpi_check_loop_end(dc, 0); - return true; } - return false; + gen_jumpi_check_loop_end(dc, 0); + return true; } static bool gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v) @@ -773,10 +771,9 @@ static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) tcg_temp_free(tmp); if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - gen_jumpi_check_loop_end(dc, 0); - return true; } - return false; + gen_jumpi_check_loop_end(dc, 0); + return true; } #else static void gen_check_interrupts(DisasContext *dc) From bf525107749a9ea78e6ecdc3d98f34e82c8d8881 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 1 Sep 2018 00:47:55 -0700 Subject: [PATCH 13/15] target/xtensa: extract unconditional TB termination via slot 0 - mark instructions that require TB termination via slot 0; - put TB termination right after the instruction translation loop, if termination w/o TB linking wasn't requested; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 83 +++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 7995a4d4ea..c9ccfabca4 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -540,14 +540,12 @@ static bool gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) static bool gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s) { gen_helper_wsr_lbeg(cpu_env, s); - gen_jumpi_check_loop_end(dc, 0); return false; } static bool gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s) { gen_helper_wsr_lend(cpu_env, s); - gen_jumpi_check_loop_end(dc, 0); return false; } @@ -614,7 +612,6 @@ static bool gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v) static bool gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_ibreakenable(cpu_env, v); - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -638,7 +635,6 @@ static bool gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) assert(id < dc->config->nibreak); gen_helper_wsr_ibreaka(cpu_env, tmp, v); tcg_temp_free(tmp); - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -686,7 +682,6 @@ static bool gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) tcg_gen_andi_i32(cpu_SR[sr], v, dc->config->inttype_mask[INTTYPE_SOFTWARE]); gen_check_interrupts(dc); - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -701,7 +696,6 @@ static bool gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp); tcg_temp_free(tmp); gen_check_interrupts(dc); - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -709,7 +703,6 @@ static bool gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_mov_i32(cpu_SR[sr], v); gen_check_interrupts(dc); - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -735,7 +728,6 @@ static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - gen_jumpi_check_loop_end(dc, 0); return true; } @@ -772,7 +764,6 @@ static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - gen_jumpi_check_loop_end(dc, 0); return true; } #else @@ -878,7 +869,6 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4) } tcg_temp_free(pc); tcg_temp_free(intlevel); - gen_jumpi_check_loop_end(dc, 0); } #endif @@ -1096,6 +1086,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (op_flags & XTENSA_OP_EXIT_TB_M1) { /* Change in mmu index, memory mapping or tb->flags; exit tb */ gen_jumpi_check_loop_end(dc, -1); + } else if (op_flags & XTENSA_OP_EXIT_TB_0) { + gen_jumpi_check_loop_end(dc, 0); } } @@ -2152,7 +2144,6 @@ static void translate_rsil(DisasContext *dc, const uint32_t arg[], tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); gen_check_interrupts(dc); - gen_jumpi_check_loop_end(dc, 0); } static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], @@ -2164,9 +2155,7 @@ static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], static void translate_rsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { - if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { - gen_jumpi_check_loop_end(dc, 0); - } + gen_rsr(dc, cpu_R[arg[0]], par[0]); } static void translate_rtlb(DisasContext *dc, const uint32_t arg[], @@ -2501,15 +2490,11 @@ static void translate_xsr(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { TCGv_i32 tmp = tcg_temp_new_i32(); - bool rsr_end, wsr_end; tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); - rsr_end = gen_rsr(dc, cpu_R[arg[0]], par[0]); - wsr_end = gen_wsr(dc, par[0], tmp); + gen_rsr(dc, cpu_R[arg[0]], par[0]); + gen_wsr(dc, par[0], tmp); tcg_temp_free(tmp); - if (rsr_end && !wsr_end) { - gen_jumpi_check_loop_end(dc, 0); - } } static const XtensaOpcodeOps core_ops[] = { @@ -3543,7 +3528,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsil", .translate = translate_rsil, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "rsr.176", @@ -3617,7 +3602,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){CCOUNT}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "rsr.configid0", @@ -3904,14 +3889,14 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "rsr.intset", .translate = translate_rsr, .test_ill = test_ill_rsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "rsr.itlbcfg", @@ -4242,7 +4227,7 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "waiti", .translate = translate_waiti, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, }, { .name = "wdtlb", .translate = translate_wtlb, @@ -4315,28 +4300,28 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.ccompare1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 1}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.ccompare2", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOMPARE + 2}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.ccount", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){CCOUNT}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.configid0", @@ -4574,21 +4559,21 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.ibreaka1", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKA + 1}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.ibreakenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){IBREAKENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.icount", @@ -4609,28 +4594,28 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTCLEAR}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.intenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.interrupt", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.intset", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.itlbcfg", @@ -4644,6 +4629,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LBEG}, + .op_flags = XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.lcount", @@ -4656,6 +4642,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){LEND}, + .op_flags = XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "wsr.litbase", @@ -4872,28 +4859,28 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.ccompare1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 1}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.ccompare2", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOMPARE + 2}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.ccount", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){CCOUNT}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.configid0", @@ -5131,21 +5118,21 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.ibreaka1", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKA + 1}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.ibreakenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){IBREAKENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.icount", @@ -5166,28 +5153,28 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTCLEAR}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.intenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.interrupt", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.intset", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.itlbcfg", @@ -5201,6 +5188,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LBEG}, + .op_flags = XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.lcount", @@ -5213,6 +5201,7 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){LEND}, + .op_flags = XTENSA_OP_EXIT_TB_0, .windowed_register_op = 0x1, }, { .name = "xsr.litbase", From c7159acbbeff32501cb54e52478f2621cfa008db Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 1 Sep 2018 19:47:26 -0700 Subject: [PATCH 14/15] target/xtensa: make rsr/wsr helpers return void Now that all logic for TB termination is extracted from rsr/wsr their return value is not used and may be dropped. Signed-off-by: Max Filippov --- target/xtensa/translate.c | 102 ++++++++++++++------------------------ 1 file changed, 36 insertions(+), 66 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index c9ccfabca4..4268a17f86 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -496,7 +496,7 @@ static bool check_sr(DisasContext *dc, uint32_t sr, unsigned access) } #ifndef CONFIG_USER_ONLY -static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) +static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) { if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_start(); @@ -506,22 +506,20 @@ static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - return true; } -static bool gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr) +static void gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr) { tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10); tcg_gen_or_i32(d, d, cpu_SR[sr]); tcg_gen_andi_i32(d, d, 0xfffffffc); - return false; } #endif -static bool gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) +static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) { - static bool (* const rsr_handler[256])(DisasContext *dc, - TCGv_i32 d, uint32_t sr) = { + static void (* const rsr_handler[256])(DisasContext *dc, + TCGv_i32 d, uint32_t sr) = { #ifndef CONFIG_USER_ONLY [CCOUNT] = gen_rsr_ccount, [INTSET] = gen_rsr_ccount, @@ -530,26 +528,23 @@ static bool gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) }; if (rsr_handler[sr]) { - return rsr_handler[sr](dc, d, sr); + rsr_handler[sr](dc, d, sr); } else { tcg_gen_mov_i32(d, cpu_SR[sr]); - return false; } } -static bool gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s) { gen_helper_wsr_lbeg(cpu_env, s); - return false; } -static bool gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s) { gen_helper_wsr_lend(cpu_env, s); - return false; } -static bool gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s) { tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f); if (dc->sar_m32_5bit) { @@ -557,77 +552,65 @@ static bool gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s) } dc->sar_5bit = false; dc->sar_m32_5bit = false; - return false; } -static bool gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s) { tcg_gen_andi_i32(cpu_SR[sr], s, 0xffff); - return false; } -static bool gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s) { tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001); - return true; } -static bool gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s) { tcg_gen_ext8s_i32(cpu_SR[sr], s); - return false; } #ifndef CONFIG_USER_ONLY -static bool gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_windowbase(cpu_env, v); - return true; } -static bool gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1); - return true; } -static bool gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000); - return false; } -static bool gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_rasid(cpu_env, v); - return true; } -static bool gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000); - return false; } -static bool gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_ibreakenable(cpu_env, v); - return true; } -static bool gen_wsr_memctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_memctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) { gen_helper_wsr_memctl(cpu_env, v); - return false; } -static bool gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f); - return false; } -static bool gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - IBREAKA; TCGv_i32 tmp = tcg_const_i32(id); @@ -635,10 +618,9 @@ static bool gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) assert(id < dc->config->nibreak); gen_helper_wsr_ibreaka(cpu_env, tmp, v); tcg_temp_free(tmp); - return true; } -static bool gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - DBREAKA; TCGv_i32 tmp = tcg_const_i32(id); @@ -646,10 +628,9 @@ static bool gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) assert(id < dc->config->ndbreak); gen_helper_wsr_dbreaka(cpu_env, tmp, v); tcg_temp_free(tmp); - return false; } -static bool gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - DBREAKC; TCGv_i32 tmp = tcg_const_i32(id); @@ -657,13 +638,11 @@ static bool gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) assert(id < dc->config->ndbreak); gen_helper_wsr_dbreakc(cpu_env, tmp, v); tcg_temp_free(tmp); - return false; } -static bool gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0xff); - return true; } static void gen_check_interrupts(DisasContext *dc) @@ -677,15 +656,14 @@ static void gen_check_interrupts(DisasContext *dc) } } -static bool gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, dc->config->inttype_mask[INTTYPE_SOFTWARE]); gen_check_interrupts(dc); - return true; } -static bool gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) { TCGv_i32 tmp = tcg_temp_new_i32(); @@ -696,17 +674,15 @@ static bool gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp); tcg_temp_free(tmp); gen_check_interrupts(dc); - return true; } -static bool gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_mov_i32(cpu_SR[sr], v); gen_check_interrupts(dc); - return true; } -static bool gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) { uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB | PS_UM | PS_EXCM | PS_INTLEVEL; @@ -716,10 +692,9 @@ static bool gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) } tcg_gen_andi_i32(cpu_SR[sr], v, mask); gen_check_interrupts(dc); - return true; } -static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) { if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_start(); @@ -728,26 +703,23 @@ static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - return true; } -static bool gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v) { if (dc->icount) { tcg_gen_mov_i32(dc->next_icount, v); } else { tcg_gen_mov_i32(cpu_SR[sr], v); } - return false; } -static bool gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, 0xf); - return true; } -static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) +static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) { uint32_t id = sr - CCOMPARE; uint32_t int_bit = 1 << dc->config->timerint[id]; @@ -764,7 +736,6 @@ static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - return true; } #else static void gen_check_interrupts(DisasContext *dc) @@ -772,10 +743,10 @@ static void gen_check_interrupts(DisasContext *dc) } #endif -static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) +static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) { - static bool (* const wsr_handler[256])(DisasContext *dc, - uint32_t sr, TCGv_i32 v) = { + static void (* const wsr_handler[256])(DisasContext *dc, + uint32_t sr, TCGv_i32 v) = { [LBEG] = gen_wsr_lbeg, [LEND] = gen_wsr_lend, [SAR] = gen_wsr_sar, @@ -813,10 +784,9 @@ static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) }; if (wsr_handler[sr]) { - return wsr_handler[sr](dc, sr, s); + wsr_handler[sr](dc, sr, s); } else { tcg_gen_mov_i32(cpu_SR[sr], s); - return false; } } From d74624e59a6087ccf233843b936aedc9f8a8050a Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 2 Sep 2018 02:07:30 -0700 Subject: [PATCH 15/15] target/xtensa: extract gen_check_interrupts call - mark instructions that affect active IRQ level; - put call for gen_check_interrupts right after the instruction translation; when FLIX is enabled it will need to appear before other exits from the TB as well; Signed-off-by: Max Filippov --- target/xtensa/translate.c | 80 ++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 4268a17f86..46e1338448 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -660,7 +660,6 @@ static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_andi_i32(cpu_SR[sr], v, dc->config->inttype_mask[INTTYPE_SOFTWARE]); - gen_check_interrupts(dc); } static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) @@ -673,13 +672,11 @@ static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) dc->config->inttype_mask[INTTYPE_SOFTWARE]); tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp); tcg_temp_free(tmp); - gen_check_interrupts(dc); } static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) { tcg_gen_mov_i32(cpu_SR[sr], v); - gen_check_interrupts(dc); } static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) @@ -691,7 +688,6 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) mask |= PS_RING; } tcg_gen_andi_i32(cpu_SR[sr], v, mask); - gen_check_interrupts(dc); } static void gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) @@ -1053,6 +1049,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } if (dc->base.is_jmp == DISAS_NEXT) { + if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) { + gen_check_interrupts(dc); + } + if (op_flags & XTENSA_OP_EXIT_TB_M1) { /* Change in mmu index, memory mapping or tb->flags; exit tb */ gen_jumpi_check_loop_end(dc, -1); @@ -2064,7 +2064,6 @@ static void translate_rfe(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); - gen_check_interrupts(dc); gen_jump(dc, cpu_SR[EPC1]); } @@ -2072,7 +2071,6 @@ static void translate_rfi(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]); - gen_check_interrupts(dc); gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]); } @@ -2092,11 +2090,9 @@ static void translate_rfw(DisasContext *dc, const uint32_t arg[], cpu_SR[WINDOW_START], tmp); } - gen_helper_restore_owb(cpu_env); - gen_check_interrupts(dc); - gen_jump(dc, cpu_SR[EPC1]); - tcg_temp_free(tmp); + gen_helper_restore_owb(cpu_env); + gen_jump(dc, cpu_SR[EPC1]); } static void translate_rotw(DisasContext *dc, const uint32_t arg[], @@ -2113,7 +2109,6 @@ static void translate_rsil(DisasContext *dc, const uint32_t arg[], tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]); tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); - gen_check_interrupts(dc); } static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[], @@ -3464,21 +3459,21 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rfe", .translate = translate_rfe, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_CHECK_INTERRUPTS, }, { .name = "rfi", .translate = translate_rfi, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_CHECK_INTERRUPTS, }, { .name = "rfwo", .translate = translate_rfw, .par = (const uint32_t[]){true}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_CHECK_INTERRUPTS, }, { .name = "rfwu", .translate = translate_rfw, .par = (const uint32_t[]){false}, - .op_flags = XTENSA_OP_PRIVILEGED, + .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_CHECK_INTERRUPTS, }, { .name = "ritlb0", .translate = translate_rtlb, @@ -3498,7 +3493,10 @@ static const XtensaOpcodeOps core_ops[] = { }, { .name = "rsil", .translate = translate_rsil, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "rsr.176", @@ -4564,28 +4562,40 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTCLEAR}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "wsr.intenable", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "wsr.interrupt", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "wsr.intset", .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "wsr.itlbcfg", @@ -4699,7 +4709,10 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_wsr, .test_ill = test_ill_wsr, .par = (const uint32_t[]){PS}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_M1 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "wsr.ptevaddr", @@ -5123,28 +5136,40 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTCLEAR}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "xsr.intenable", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTENABLE}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "xsr.interrupt", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "xsr.intset", .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){INTSET}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_0 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "xsr.itlbcfg", @@ -5251,7 +5276,10 @@ static const XtensaOpcodeOps core_ops[] = { .translate = translate_xsr, .test_ill = test_ill_xsr, .par = (const uint32_t[]){PS}, - .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1, + .op_flags = + XTENSA_OP_PRIVILEGED | + XTENSA_OP_EXIT_TB_M1 | + XTENSA_OP_CHECK_INTERRUPTS, .windowed_register_op = 0x1, }, { .name = "xsr.ptevaddr",