All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores
@ 2019-05-14 20:44 Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 1/9] target/xtensa: get rid of centralized SR properties Max Filippov
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Hello,

this series implements options used by the modern xtensa cores: memory
protection unit, block prefetch and exclusive access and adds special
register definitions and IRQ types for a few other options not fully
implemented: ECC/parity, scatter/gather and IDMA.

Max Filippov (9):
  target/xtensa: get rid of centralized SR properties
  target/xtensa: make internal MMU functions static
  target/xtensa: define IDMA and gather/scatter IRQ types
  target/xtensa: add parity/ECC option SRs
  target/xtensa: implement MPU option
  target/xtensa: implement DIWBUI.P opcode
  target/xtensa: implement block prefetch option opcodes
  target/xtensa: update list of exception causes
  target/xtensa: implement exclusive access option

 target/xtensa/cpu.c               |    2 +-
 target/xtensa/cpu.h               |   58 +-
 target/xtensa/helper.c            |    1 +
 target/xtensa/helper.h            |    6 +
 target/xtensa/mmu_helper.c        |  532 ++++++-
 target/xtensa/op_helper.c         |   42 +
 target/xtensa/overlay_tool.h      |   43 +-
 target/xtensa/translate.c         | 2951 ++++++++++++++++++++++++-------------
 tests/tcg/xtensa/test_exclusive.S |   48 +
 9 files changed, 2574 insertions(+), 1109 deletions(-)
 create mode 100644 tests/tcg/xtensa/test_exclusive.S

-- 
2.11.0



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 1/9] target/xtensa: get rid of centralized SR properties
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 2/9] target/xtensa: make internal MMU functions static Max Filippov
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

SR numbers are not unique: different Xtensa options may reuse SR number
for different purposes. Introduce generic rsr/wsr functions and xsr
template and use them instead of centralized SR access functions. Change
prototypes of specific rsr/wsr functions to match XtensaOpcodeOp and use
them instead of centralized SR access functions. Put xtensa option that
introduces SR into the second opcode description parameter and use it to
test for rsr/wsr/xsr opcode validity. Extract SR and UR names for the
xtensa_cpu_dump_state from libisa. Merge SRs and URs in the dump.
Register names of used SR/UR in init_libisa and use these names for TCG
globals referencing these SR/UR.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h       |    1 +
 target/xtensa/helper.c    |    1 +
 target/xtensa/translate.c | 2503 +++++++++++++++++++++++++++------------------
 3 files changed, 1492 insertions(+), 1013 deletions(-)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 5d23e1345be5..539033fccb61 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -589,6 +589,7 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
 #define XTENSA_DEFAULT_CPU_NOMMU_TYPE \
     XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
 
+void xtensa_collect_sr_names(const XtensaConfig *config);
 void xtensa_translate_init(void);
 void **xtensa_get_regfile_by_name(const char *name);
 void xtensa_breakpoint_handler(CPUState *cs);
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 5f37f378a311..ed0108a81209 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -141,6 +141,7 @@ static void init_libisa(XtensaConfig *config)
         }
 #endif
     }
+    xtensa_collect_sr_names(config);
 }
 
 static void xtensa_finalize_config(XtensaConfig *config)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 301c8e31613c..100d6e126590 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -92,128 +92,40 @@ static GHashTable *xtensa_regfile_table;
 
 #include "exec/gen-icount.h"
 
-typedef struct XtensaReg {
-    const char *name;
-    uint64_t opt_bits;
-    enum {
-        SR_R = 1,
-        SR_W = 2,
-        SR_X = 4,
-        SR_RW = 3,
-        SR_RWX = 7,
-    } access;
-} XtensaReg;
-
-#define XTENSA_REG_ACCESS(regname, opt, acc) { \
-        .name = (regname), \
-        .opt_bits = XTENSA_OPTION_BIT(opt), \
-        .access = (acc), \
-    }
+static char *sr_name[256];
+static char *ur_name[256];
 
-#define XTENSA_REG(regname, opt) XTENSA_REG_ACCESS(regname, opt, SR_RWX)
+void xtensa_collect_sr_names(const XtensaConfig *config)
+{
+    xtensa_isa isa = config->isa;
+    int n = xtensa_isa_num_sysregs(isa);
+    int i;
 
-#define XTENSA_REG_BITS_ACCESS(regname, opt, acc) { \
-        .name = (regname), \
-        .opt_bits = (opt), \
-        .access = (acc), \
+    for (i = 0; i < n; ++i) {
+        int sr = xtensa_sysreg_number(isa, i);
+
+        if (sr >= 0 && sr < 256) {
+            const char *name = xtensa_sysreg_name(isa, i);
+            char **pname =
+                (xtensa_sysreg_is_user(isa, i) ? ur_name : sr_name) + sr;
+
+            if (*pname) {
+                if (strstr(*pname, name) == NULL) {
+                    char *new_name =
+                        malloc(strlen(*pname) + strlen(name) + 2);
+
+                    strcpy(new_name, *pname);
+                    strcat(new_name, "/");
+                    strcat(new_name, name);
+                    free(*pname);
+                    *pname = new_name;
+                }
+            } else {
+                *pname = strdup(name);
+            }
+        }
     }
-
-#define XTENSA_REG_BITS(regname, opt) \
-    XTENSA_REG_BITS_ACCESS(regname, opt, SR_RWX)
-
-static const XtensaReg sregnames[256] = {
-    [LBEG] = XTENSA_REG("LBEG", XTENSA_OPTION_LOOP),
-    [LEND] = XTENSA_REG("LEND", XTENSA_OPTION_LOOP),
-    [LCOUNT] = XTENSA_REG("LCOUNT", XTENSA_OPTION_LOOP),
-    [SAR] = XTENSA_REG_BITS("SAR", XTENSA_OPTION_ALL),
-    [BR] = XTENSA_REG("BR", XTENSA_OPTION_BOOLEAN),
-    [LITBASE] = XTENSA_REG("LITBASE", XTENSA_OPTION_EXTENDED_L32R),
-    [SCOMPARE1] = XTENSA_REG("SCOMPARE1", XTENSA_OPTION_CONDITIONAL_STORE),
-    [ACCLO] = XTENSA_REG("ACCLO", XTENSA_OPTION_MAC16),
-    [ACCHI] = XTENSA_REG("ACCHI", XTENSA_OPTION_MAC16),
-    [MR] = XTENSA_REG("MR0", XTENSA_OPTION_MAC16),
-    [MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16),
-    [MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16),
-    [MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16),
-    [PREFCTL] = XTENSA_REG_BITS("PREFCTL", XTENSA_OPTION_ALL),
-    [WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER),
-    [WINDOW_START] = XTENSA_REG("WINDOW_START",
-            XTENSA_OPTION_WINDOWED_REGISTER),
-    [PTEVADDR] = XTENSA_REG("PTEVADDR", XTENSA_OPTION_MMU),
-    [MMID] = XTENSA_REG_BITS("MMID", XTENSA_OPTION_ALL),
-    [RASID] = XTENSA_REG("RASID", XTENSA_OPTION_MMU),
-    [ITLBCFG] = XTENSA_REG("ITLBCFG", XTENSA_OPTION_MMU),
-    [DTLBCFG] = XTENSA_REG("DTLBCFG", XTENSA_OPTION_MMU),
-    [IBREAKENABLE] = XTENSA_REG("IBREAKENABLE", XTENSA_OPTION_DEBUG),
-    [MEMCTL] = XTENSA_REG_BITS("MEMCTL", XTENSA_OPTION_ALL),
-    [CACHEATTR] = XTENSA_REG("CACHEATTR", XTENSA_OPTION_CACHEATTR),
-    [ATOMCTL] = XTENSA_REG("ATOMCTL", XTENSA_OPTION_ATOMCTL),
-    [DDR] = XTENSA_REG("DDR", XTENSA_OPTION_DEBUG),
-    [IBREAKA] = XTENSA_REG("IBREAKA0", XTENSA_OPTION_DEBUG),
-    [IBREAKA + 1] = XTENSA_REG("IBREAKA1", XTENSA_OPTION_DEBUG),
-    [DBREAKA] = XTENSA_REG("DBREAKA0", XTENSA_OPTION_DEBUG),
-    [DBREAKA + 1] = XTENSA_REG("DBREAKA1", XTENSA_OPTION_DEBUG),
-    [DBREAKC] = XTENSA_REG("DBREAKC0", XTENSA_OPTION_DEBUG),
-    [DBREAKC + 1] = XTENSA_REG("DBREAKC1", XTENSA_OPTION_DEBUG),
-    [CONFIGID0] = XTENSA_REG_BITS_ACCESS("CONFIGID0", XTENSA_OPTION_ALL, SR_R),
-    [EPC1] = XTENSA_REG("EPC1", XTENSA_OPTION_EXCEPTION),
-    [EPC1 + 1] = XTENSA_REG("EPC2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPC1 + 2] = XTENSA_REG("EPC3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPC1 + 3] = XTENSA_REG("EPC4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPC1 + 4] = XTENSA_REG("EPC5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPC1 + 5] = XTENSA_REG("EPC6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPC1 + 6] = XTENSA_REG("EPC7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [DEPC] = XTENSA_REG("DEPC", XTENSA_OPTION_EXCEPTION),
-    [EPS2] = XTENSA_REG("EPS2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPS2 + 1] = XTENSA_REG("EPS3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPS2 + 2] = XTENSA_REG("EPS4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPS2 + 3] = XTENSA_REG("EPS5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPS2 + 4] = XTENSA_REG("EPS6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EPS2 + 5] = XTENSA_REG("EPS7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [CONFIGID1] = XTENSA_REG_BITS_ACCESS("CONFIGID1", XTENSA_OPTION_ALL, SR_R),
-    [EXCSAVE1] = XTENSA_REG("EXCSAVE1", XTENSA_OPTION_EXCEPTION),
-    [EXCSAVE1 + 1] = XTENSA_REG("EXCSAVE2",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EXCSAVE1 + 2] = XTENSA_REG("EXCSAVE3",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EXCSAVE1 + 3] = XTENSA_REG("EXCSAVE4",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EXCSAVE1 + 4] = XTENSA_REG("EXCSAVE5",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EXCSAVE1 + 5] = XTENSA_REG("EXCSAVE6",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7",
-            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
-    [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR),
-    [INTSET] = XTENSA_REG_ACCESS("INTSET", XTENSA_OPTION_INTERRUPT, SR_RW),
-    [INTCLEAR] = XTENSA_REG_ACCESS("INTCLEAR", XTENSA_OPTION_INTERRUPT, SR_W),
-    [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT),
-    [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL),
-    [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR),
-    [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION),
-    [DEBUGCAUSE] = XTENSA_REG_ACCESS("DEBUGCAUSE", XTENSA_OPTION_DEBUG, SR_R),
-    [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT),
-    [PRID] = XTENSA_REG_ACCESS("PRID", XTENSA_OPTION_PROCESSOR_ID, SR_R),
-    [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG),
-    [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG),
-    [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION),
-    [CCOMPARE] = XTENSA_REG("CCOMPARE0", XTENSA_OPTION_TIMER_INTERRUPT),
-    [CCOMPARE + 1] = XTENSA_REG("CCOMPARE1",
-            XTENSA_OPTION_TIMER_INTERRUPT),
-    [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2",
-            XTENSA_OPTION_TIMER_INTERRUPT),
-    [MISC] = XTENSA_REG("MISC0", XTENSA_OPTION_MISC_SR),
-    [MISC + 1] = XTENSA_REG("MISC1", XTENSA_OPTION_MISC_SR),
-    [MISC + 2] = XTENSA_REG("MISC2", XTENSA_OPTION_MISC_SR),
-    [MISC + 3] = XTENSA_REG("MISC3", XTENSA_OPTION_MISC_SR),
-};
-
-static const XtensaReg uregnames[256] = {
-    [EXPSTATE] = XTENSA_REG_BITS("EXPSTATE", XTENSA_OPTION_ALL),
-    [THREADPTR] = XTENSA_REG("THREADPTR", XTENSA_OPTION_THREAD_POINTER),
-    [FCR] = XTENSA_REG("FCR", XTENSA_OPTION_FP_COPROCESSOR),
-    [FSR] = XTENSA_REG("FSR", XTENSA_OPTION_FP_COPROCESSOR),
-};
+}
 
 void xtensa_translate_init(void)
 {
@@ -283,18 +195,20 @@ void xtensa_translate_init(void)
     }
 
     for (i = 0; i < 256; ++i) {
-        if (sregnames[i].name) {
+        if (sr_name[i]) {
             cpu_SR[i] = tcg_global_mem_new_i32(cpu_env,
-                    offsetof(CPUXtensaState, sregs[i]),
-                    sregnames[i].name);
+                                               offsetof(CPUXtensaState,
+                                                        sregs[i]),
+                                               sr_name[i]);
         }
     }
 
     for (i = 0; i < 256; ++i) {
-        if (uregnames[i].name) {
+        if (ur_name[i]) {
             cpu_UR[i] = tcg_global_mem_new_i32(cpu_env,
-                    offsetof(CPUXtensaState, uregs[i]),
-                    uregnames[i].name);
+                                               offsetof(CPUXtensaState,
+                                                        uregs[i]),
+                                               ur_name[i]);
         }
     }
 
@@ -536,313 +450,57 @@ static void gen_brcondi(DisasContext *dc, TCGCond cond,
     tcg_temp_free(tmp);
 }
 
-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) {
-            qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not configured\n", sregnames[sr].name);
-        } else {
-            qemu_log_mask(LOG_UNIMP, "SR %d is not implemented\n", sr);
-        }
-        return false;
-    } else if (!(sregnames[sr].access & access)) {
-        static const char * const access_text[] = {
-            [SR_R] = "rsr",
-            [SR_W] = "wsr",
-            [SR_X] = "xsr",
-        };
-        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]);
-        return false;
-    }
-    return true;
-}
-
-#ifndef CONFIG_USER_ONLY
-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();
-    }
-    gen_helper_update_ccount(cpu_env);
-    tcg_gen_mov_i32(d, cpu_SR[sr]);
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_end();
-    }
-}
-
-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);
-}
-#endif
-
-static void gen_rsr(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,
-        [PTEVADDR] = gen_rsr_ptevaddr,
-#endif
-    };
-
-    if (rsr_handler[sr]) {
-        rsr_handler[sr](dc, d, sr);
-    } else {
-        tcg_gen_mov_i32(d, cpu_SR[sr]);
-    }
-}
-
-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) {
-        tcg_gen_discard_i32(dc->sar_m32);
-    }
-    dc->sar_5bit = false;
-    dc->sar_m32_5bit = false;
-}
-
-static void gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], s, 0xffff);
-}
-
-static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
-}
-
-static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
-{
-    tcg_gen_ext8s_i32(cpu_SR[sr], s);
-}
-
-#ifndef CONFIG_USER_ONLY
-static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_mov_i32(cpu_windowbase_next, 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);
-}
-
-static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000);
-}
-
-static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    gen_helper_wsr_rasid(cpu_env, v);
-}
-
-static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
-}
-
-static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    gen_helper_wsr_ibreakenable(cpu_env, v);
-}
-
-static void gen_wsr_memctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    gen_helper_wsr_memctl(cpu_env, v);
-}
-
-static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f);
-}
-
-static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    unsigned id = sr - IBREAKA;
-    TCGv_i32 tmp = tcg_const_i32(id);
-
-    assert(id < dc->config->nibreak);
-    gen_helper_wsr_ibreaka(cpu_env, tmp, v);
-    tcg_temp_free(tmp);
-}
-
-static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    unsigned id = sr - DBREAKA;
-    TCGv_i32 tmp = tcg_const_i32(id);
-
-    assert(id < dc->config->ndbreak);
-    gen_helper_wsr_dbreaka(cpu_env, tmp, v);
-    tcg_temp_free(tmp);
-}
-
-static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    unsigned id = sr - DBREAKC;
-    TCGv_i32 tmp = tcg_const_i32(id);
-
-    assert(id < dc->config->ndbreak);
-    gen_helper_wsr_dbreakc(cpu_env, tmp, v);
-    tcg_temp_free(tmp);
-}
-
-static void gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], v, 0xff);
-}
-
-static void gen_check_interrupts(DisasContext *dc)
-{
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_start();
-    }
-    gen_helper_check_interrupts(cpu_env);
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_end();
-    }
-}
-
-static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+static bool test_ill_sr(DisasContext *dc, const OpcodeArg arg[],
+                        const uint32_t par[])
 {
-    gen_helper_intset(cpu_env, v);
+    return !xtensa_option_enabled(dc->config, par[1]);
 }
 
-static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+static bool test_ill_ccompare(DisasContext *dc, const OpcodeArg arg[],
+                              const uint32_t par[])
 {
-    gen_helper_intclear(cpu_env, v);
-}
+    unsigned n = par[0] - CCOMPARE;
 
-static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_mov_i32(cpu_SR[sr], v);
+    return test_ill_sr(dc, arg, par) || n >= dc->config->nccompare;
 }
 
-static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+static bool test_ill_dbreak(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
 {
-    uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
-        PS_UM | PS_EXCM | PS_INTLEVEL;
+    unsigned n = MAX_NDBREAK;
 
-    if (option_enabled(dc, XTENSA_OPTION_MMU)) {
-        mask |= PS_RING;
-    }
-    tcg_gen_andi_i32(cpu_SR[sr], v, mask);
-}
-
-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();
+    if (par[0] >= DBREAKA && par[0] < DBREAKA + MAX_NDBREAK) {
+        n = par[0] - DBREAKA;
     }
-    gen_helper_wsr_ccount(cpu_env, v);
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_end();
+    if (par[0] >= DBREAKC && par[0] < DBREAKC + MAX_NDBREAK) {
+        n = par[0] - DBREAKC;
     }
+    return test_ill_sr(dc, arg, par) || n >= dc->config->ndbreak;
 }
 
-static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+static bool test_ill_ibreak(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
 {
-    if (dc->icount) {
-        tcg_gen_mov_i32(dc->next_icount, v);
-    } else {
-        tcg_gen_mov_i32(cpu_SR[sr], v);
-    }
-}
+    unsigned n = par[0] - IBREAKA;
 
-static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
-{
-    tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
+    return test_ill_sr(dc, arg, par) || n >= dc->config->nibreak;
 }
 
-static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+static bool test_ill_hpi(DisasContext *dc, const OpcodeArg arg[],
+                         const uint32_t par[])
 {
-    uint32_t id = sr - CCOMPARE;
-    TCGv_i32 tmp = tcg_const_i32(id);
+    unsigned n = MAX_NLEVEL + 1;
 
-    assert(id < dc->config->nccompare);
-    tcg_gen_mov_i32(cpu_SR[sr], v);
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_start();
-    }
-    gen_helper_update_ccompare(cpu_env, tmp);
-    tcg_temp_free(tmp);
-    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-        gen_io_end();
+    if (par[0] >= EXCSAVE1 && par[0] < EXCSAVE1 + MAX_NLEVEL) {
+        n = par[0] - EXCSAVE1 + 1;
     }
-}
-#else
-static void gen_check_interrupts(DisasContext *dc)
-{
-}
-#endif
-
-static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
-{
-    static void (* const wsr_handler[256])(DisasContext *dc,
-                                           uint32_t sr, TCGv_i32 v) = {
-        [SAR] = gen_wsr_sar,
-        [BR] = gen_wsr_br,
-        [LITBASE] = gen_wsr_litbase,
-        [ACCHI] = gen_wsr_acchi,
-#ifndef CONFIG_USER_ONLY
-        [WINDOW_BASE] = gen_wsr_windowbase,
-        [WINDOW_START] = gen_wsr_windowstart,
-        [PTEVADDR] = gen_wsr_ptevaddr,
-        [RASID] = gen_wsr_rasid,
-        [ITLBCFG] = gen_wsr_tlbcfg,
-        [DTLBCFG] = gen_wsr_tlbcfg,
-        [IBREAKENABLE] = gen_wsr_ibreakenable,
-        [MEMCTL] = gen_wsr_memctl,
-        [ATOMCTL] = gen_wsr_atomctl,
-        [IBREAKA] = gen_wsr_ibreaka,
-        [IBREAKA + 1] = gen_wsr_ibreaka,
-        [DBREAKA] = gen_wsr_dbreaka,
-        [DBREAKA + 1] = gen_wsr_dbreaka,
-        [DBREAKC] = gen_wsr_dbreakc,
-        [DBREAKC + 1] = gen_wsr_dbreakc,
-        [CPENABLE] = gen_wsr_cpenable,
-        [INTSET] = gen_wsr_intset,
-        [INTCLEAR] = gen_wsr_intclear,
-        [INTENABLE] = gen_wsr_intenable,
-        [PS] = gen_wsr_ps,
-        [CCOUNT] = gen_wsr_ccount,
-        [ICOUNT] = gen_wsr_icount,
-        [ICOUNTLEVEL] = gen_wsr_icountlevel,
-        [CCOMPARE] = gen_wsr_ccompare,
-        [CCOMPARE + 1] = gen_wsr_ccompare,
-        [CCOMPARE + 2] = gen_wsr_ccompare,
-#endif
-    };
-
-    if (wsr_handler[sr]) {
-        wsr_handler[sr](dc, sr, s);
-    } else {
-        tcg_gen_mov_i32(cpu_SR[sr], s);
+    if (par[0] >= EPC1 && par[0] < EPC1 + MAX_NLEVEL) {
+        n = par[0] - EPC1 + 1;
     }
-}
-
-static void gen_wur(uint32_t ur, TCGv_i32 s)
-{
-    switch (ur) {
-    case FCR:
-        gen_helper_wur_fcr(cpu_env, s);
-        break;
-
-    case FSR:
-        tcg_gen_andi_i32(cpu_UR[ur], s, 0xffffff80);
-        break;
-
-    default:
-        tcg_gen_mov_i32(cpu_UR[ur], s);
-        break;
+    if (par[0] >= EPS2 && par[0] < EPS2 + MAX_NLEVEL - 1) {
+        n = par[0] - EPS2 + 2;
     }
+    return test_ill_sr(dc, arg, par) || n > dc->config->nlevel;
 }
 
 static void gen_load_store_alignment(DisasContext *dc, int shift,
@@ -925,9 +583,17 @@ static int gen_postprocess(DisasContext *dc, int slot)
 {
     uint32_t op_flags = dc->op_flags;
 
+#ifndef CONFIG_USER_ONLY
     if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
-        gen_check_interrupts(dc);
+        if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+            gen_io_start();
+        }
+        gen_helper_check_interrupts(cpu_env);
+        if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+            gen_io_end();
+        }
     }
+#endif
     if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) {
         gen_helper_sync_windowbase(cpu_env);
     }
@@ -1645,24 +1311,20 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
     CPUXtensaState *env = &cpu->env;
+    xtensa_isa isa = env->config->isa;
     int i, j;
 
     qemu_fprintf(f, "PC=%08x\n\n", env->pc);
 
-    for (i = j = 0; i < 256; ++i) {
-        if (xtensa_option_bits_enabled(env->config, sregnames[i].opt_bits)) {
-            qemu_fprintf(f, "%12s=%08x%c",
-                         sregnames[i].name, env->sregs[i],
-                         (j++ % 4) == 3 ? '\n' : ' ');
-        }
-    }
-
-    qemu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
+    for (i = j = 0; i < xtensa_isa_num_sysregs(isa); ++i) {
+        const uint32_t *reg =
+            xtensa_sysreg_is_user(isa, i) ? env->uregs : env->sregs;
+        int regno = xtensa_sysreg_number(isa, i);
 
-    for (i = j = 0; i < 256; ++i) {
-        if (xtensa_option_bits_enabled(env->config, uregnames[i].opt_bits)) {
-            qemu_fprintf(f, "%s=%08x%c",
-                         uregnames[i].name, env->uregs[i],
+        if (regno >= 0) {
+            qemu_fprintf(f, "%12s=%08x%c",
+                         xtensa_sysreg_name(isa, i),
+                         reg[regno],
                          (j++ % 4) == 3 ? '\n' : ' ');
         }
     }
@@ -2472,16 +2134,38 @@ static void translate_rsil(DisasContext *dc, const OpcodeArg arg[],
     tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1].imm);
 }
 
-static bool test_ill_rsr(DisasContext *dc, const OpcodeArg arg[],
-                         const uint32_t par[])
+static void translate_rsr(DisasContext *dc, const OpcodeArg arg[],
+                          const uint32_t par[])
 {
-    return !check_sr(dc, par[0], SR_R);
+    tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
 }
 
-static void translate_rsr(DisasContext *dc, const OpcodeArg arg[],
-                          const uint32_t par[])
+static void translate_rsr_ccount(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+    gen_helper_update_ccount(cpu_env);
+    tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
+#endif
+}
+
+static void translate_rsr_ptevaddr(DisasContext *dc, const OpcodeArg arg[],
+                                   const uint32_t par[])
 {
-    gen_rsr(dc, arg[0].out, par[0]);
+#ifndef CONFIG_USER_ONLY
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    tcg_gen_shri_i32(tmp, cpu_SR[EXCVADDR], 10);
+    tcg_gen_or_i32(tmp, tmp, cpu_SR[PTEVADDR]);
+    tcg_gen_andi_i32(arg[0].out, tmp, 0xfffffffc);
+    tcg_temp_free(tmp);
+#endif
 }
 
 static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
@@ -2503,11 +2187,7 @@ static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
 static void translate_rur(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    if (uregnames[par[0]].name) {
-        tcg_gen_mov_i32(arg[0].out, cpu_UR[par[0]]);
-    } else {
-        qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]);
-    }
+    tcg_gen_mov_i32(arg[0].out, cpu_UR[par[0]]);
 }
 
 static void translate_setb_expstate(DisasContext *dc, const OpcodeArg arg[],
@@ -2778,52 +2458,288 @@ static void translate_wrmsk_expstate(DisasContext *dc, const OpcodeArg arg[],
     tcg_gen_and_i32(cpu_UR[EXPSTATE], arg[0].in, arg[1].in);
 }
 
-static bool test_ill_wsr(DisasContext *dc, const OpcodeArg arg[],
-                         const uint32_t par[])
+static void translate_wsr(DisasContext *dc, const OpcodeArg arg[],
+                          const uint32_t par[])
 {
-    return !check_sr(dc, par[0], SR_W);
+    tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in);
 }
 
-static void translate_wsr(DisasContext *dc, const OpcodeArg arg[],
-                          const uint32_t par[])
+static void translate_wsr_mask(DisasContext *dc, const OpcodeArg arg[],
+                               const uint32_t par[])
 {
-    gen_wsr(dc, par[0], arg[0].in);
+    tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, par[2]);
 }
 
-static void translate_wur(DisasContext *dc, const OpcodeArg arg[],
-                          const uint32_t par[])
+static void translate_wsr_acchi(DisasContext *dc, const OpcodeArg arg[],
+                                const uint32_t par[])
 {
-    if (uregnames[par[0]].name) {
-        gen_wur(par[0], arg[0].in);
-    } else {
-        qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]);
-    }
+    tcg_gen_ext8s_i32(cpu_SR[par[0]], arg[0].in);
 }
 
-static void translate_xor(DisasContext *dc, const OpcodeArg arg[],
-                          const uint32_t par[])
+static void translate_wsr_ccompare(DisasContext *dc, const OpcodeArg arg[],
+                                   const uint32_t par[])
 {
-    tcg_gen_xor_i32(arg[0].out, arg[1].in, arg[2].in);
+#ifndef CONFIG_USER_ONLY
+    uint32_t id = par[0] - CCOMPARE;
+    TCGv_i32 tmp = tcg_const_i32(id);
+
+    assert(id < dc->config->nccompare);
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+    tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in);
+    gen_helper_update_ccompare(cpu_env, tmp);
+    tcg_temp_free(tmp);
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
+#endif
 }
 
-static bool test_ill_xsr(DisasContext *dc, const OpcodeArg arg[],
-                         const uint32_t par[])
+static void translate_wsr_ccount(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
 {
-    return !check_sr(dc, par[0], SR_X);
+#ifndef CONFIG_USER_ONLY
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+    gen_helper_wsr_ccount(cpu_env, arg[0].in);
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
+#endif
 }
 
-static void translate_xsr(DisasContext *dc, const OpcodeArg arg[],
-                          const uint32_t par[])
+static void translate_wsr_dbreaka(DisasContext *dc, const OpcodeArg arg[],
+                                  const uint32_t par[])
 {
-    TCGv_i32 tmp = tcg_temp_new_i32();
+#ifndef CONFIG_USER_ONLY
+    unsigned id = par[0] - DBREAKA;
+    TCGv_i32 tmp = tcg_const_i32(id);
 
-    tcg_gen_mov_i32(tmp, arg[0].in);
-    gen_rsr(dc, arg[0].out, par[0]);
-    gen_wsr(dc, par[0], tmp);
+    assert(id < dc->config->ndbreak);
+    gen_helper_wsr_dbreaka(cpu_env, tmp, arg[0].in);
     tcg_temp_free(tmp);
+#endif
 }
 
-static const XtensaOpcodeOps core_ops[] = {
+static void translate_wsr_dbreakc(DisasContext *dc, const OpcodeArg arg[],
+                                  const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    unsigned id = par[0] - DBREAKC;
+    TCGv_i32 tmp = tcg_const_i32(id);
+
+    assert(id < dc->config->ndbreak);
+    gen_helper_wsr_dbreakc(cpu_env, tmp, arg[0].in);
+    tcg_temp_free(tmp);
+#endif
+}
+
+static void translate_wsr_ibreaka(DisasContext *dc, const OpcodeArg arg[],
+                                  const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    unsigned id = par[0] - IBREAKA;
+    TCGv_i32 tmp = tcg_const_i32(id);
+
+    assert(id < dc->config->nibreak);
+    gen_helper_wsr_ibreaka(cpu_env, tmp, arg[0].in);
+    tcg_temp_free(tmp);
+#endif
+}
+
+static void translate_wsr_ibreakenable(DisasContext *dc, const OpcodeArg arg[],
+                                       const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_wsr_ibreakenable(cpu_env, arg[0].in);
+#endif
+}
+
+static void translate_wsr_icount(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    if (dc->icount) {
+        tcg_gen_mov_i32(dc->next_icount, arg[0].in);
+    } else {
+        tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in);
+    }
+#endif
+}
+
+static void translate_wsr_intclear(DisasContext *dc, const OpcodeArg arg[],
+                                   const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_intclear(cpu_env, arg[0].in);
+#endif
+}
+
+static void translate_wsr_intset(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_intset(cpu_env, arg[0].in);
+#endif
+}
+
+static void translate_wsr_memctl(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_wsr_memctl(cpu_env, arg[0].in);
+#endif
+}
+
+static void translate_wsr_ps(DisasContext *dc, const OpcodeArg arg[],
+                             const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
+        PS_UM | PS_EXCM | PS_INTLEVEL;
+
+    if (option_enabled(dc, XTENSA_OPTION_MMU)) {
+        mask |= PS_RING;
+    }
+    tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, mask);
+#endif
+}
+
+static void translate_wsr_rasid(DisasContext *dc, const OpcodeArg arg[],
+                                const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_wsr_rasid(cpu_env, arg[0].in);
+#endif
+}
+
+static void translate_wsr_sar(DisasContext *dc, const OpcodeArg arg[],
+                              const uint32_t par[])
+{
+    tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, 0x3f);
+    if (dc->sar_m32_5bit) {
+        tcg_gen_discard_i32(dc->sar_m32);
+    }
+    dc->sar_5bit = false;
+    dc->sar_m32_5bit = false;
+}
+
+static void translate_wsr_windowbase(DisasContext *dc, const OpcodeArg arg[],
+                                     const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    tcg_gen_mov_i32(cpu_windowbase_next, arg[0].in);
+#endif
+}
+
+static void translate_wsr_windowstart(DisasContext *dc, const OpcodeArg arg[],
+                                      const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in,
+                     (1 << dc->config->nareg / 4) - 1);
+#endif
+}
+
+static void translate_wur(DisasContext *dc, const OpcodeArg arg[],
+                          const uint32_t par[])
+{
+    tcg_gen_mov_i32(cpu_UR[par[0]], arg[0].in);
+}
+
+static void translate_wur_fcr(DisasContext *dc, const OpcodeArg arg[],
+                              const uint32_t par[])
+{
+    gen_helper_wur_fcr(cpu_env, arg[0].in);
+}
+
+static void translate_wur_fsr(DisasContext *dc, const OpcodeArg arg[],
+                              const uint32_t par[])
+{
+    tcg_gen_andi_i32(cpu_UR[par[0]], arg[0].in, 0xffffff80);
+}
+
+static void translate_xor(DisasContext *dc, const OpcodeArg arg[],
+                          const uint32_t par[])
+{
+    tcg_gen_xor_i32(arg[0].out, arg[1].in, arg[2].in);
+}
+
+static void translate_xsr(DisasContext *dc, const OpcodeArg arg[],
+                          const uint32_t par[])
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    tcg_gen_mov_i32(tmp, arg[0].in);
+    tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
+    tcg_gen_mov_i32(cpu_SR[par[0]], tmp);
+    tcg_temp_free(tmp);
+}
+
+static void translate_xsr_mask(DisasContext *dc, const OpcodeArg arg[],
+                               const uint32_t par[])
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    tcg_gen_mov_i32(tmp, arg[0].in);
+    tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
+    tcg_gen_andi_i32(cpu_SR[par[0]], tmp, par[2]);
+    tcg_temp_free(tmp);
+}
+
+static void translate_xsr_ccount(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_start();
+    }
+
+    gen_helper_update_ccount(cpu_env);
+    tcg_gen_mov_i32(tmp, cpu_SR[par[0]]);
+    gen_helper_wsr_ccount(cpu_env, arg[0].in);
+    tcg_gen_mov_i32(arg[0].out, tmp);
+    tcg_temp_free(tmp);
+
+    if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
+        gen_io_end();
+    }
+#endif
+}
+
+#define gen_translate_xsr(name) \
+    static void translate_xsr_##name(DisasContext *dc, const OpcodeArg arg[], \
+                                     const uint32_t par[]) \
+{ \
+    TCGv_i32 tmp = tcg_temp_new_i32(); \
+ \
+    tcg_gen_mov_i32(tmp, cpu_SR[par[0]]); \
+    translate_wsr_##name(dc, arg, par); \
+    tcg_gen_mov_i32(arg[0].out, tmp); \
+    tcg_temp_free(tmp); \
+}
+
+gen_translate_xsr(acchi)
+gen_translate_xsr(ccompare)
+gen_translate_xsr(dbreaka)
+gen_translate_xsr(dbreakc)
+gen_translate_xsr(ibreaka)
+gen_translate_xsr(ibreakenable)
+gen_translate_xsr(icount)
+gen_translate_xsr(memctl)
+gen_translate_xsr(ps)
+gen_translate_xsr(rasid)
+gen_translate_xsr(sar)
+gen_translate_xsr(windowbase)
+gen_translate_xsr(windowstart)
+
+#undef gen_translate_xsr
+
+static const XtensaOpcodeOps core_ops[] = {
     {
         .name = "abs",
         .translate = translate_abs,
@@ -3766,450 +3682,653 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .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,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ACCHI},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCHI,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.acclo",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ACCLO},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCLO,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.atomctl",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ATOMCTL},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ATOMCTL,
+            XTENSA_OPTION_ATOMCTL,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.br",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){BR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            BR,
+            XTENSA_OPTION_BOOLEAN,
+        },
     }, {
         .name = "rsr.cacheattr",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){CACHEATTR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEATTR,
+            XTENSA_OPTION_CACHEATTR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ccompare0",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){CCOMPARE},
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ccompare1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){CCOMPARE + 1},
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 1,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ccompare2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){CCOMPARE + 2},
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 2,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ccount",
-        .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){CCOUNT},
+        .translate = translate_rsr_ccount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CCOUNT,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .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},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CPENABLE,
+            XTENSA_OPTION_COPROCESSOR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.dbreaka0",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DBREAKA},
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.dbreaka1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DBREAKA + 1},
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.dbreakc0",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DBREAKC},
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.dbreakc1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DBREAKC + 1},
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ddr",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DDR,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.debugcause",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DEBUGCAUSE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DEBUGCAUSE,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.depc",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DEPC},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DEPC,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.dtlbcfg",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){DTLBCFG},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DTLBCFG,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EPC1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc3",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc4",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc5",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc6",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.epc7",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPC1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps3",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps4",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps5",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps6",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.eps7",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EPS2 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.exccause",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCCAUSE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCCAUSE,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCSAVE1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave3",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave4",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave5",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave6",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excsave7",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.excvaddr",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){EXCVADDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCVADDR,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ibreaka0",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){IBREAKA},
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ibreaka1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){IBREAKA + 1},
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ibreakenable",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){IBREAKENABLE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            IBREAKENABLE,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.icount",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ICOUNT},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNT,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.icountlevel",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ICOUNTLEVEL},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNTLEVEL,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.intclear",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){INTCLEAR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTCLEAR,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.intenable",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){INTENABLE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTENABLE,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.interrupt",
-        .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){INTSET},
+        .translate = translate_rsr_ccount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTSET,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "rsr.intset",
-        .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){INTSET},
+        .translate = translate_rsr_ccount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTSET,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "rsr.itlbcfg",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){ITLBCFG},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ITLBCFG,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.lbeg",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){LBEG},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LBEG,
+            XTENSA_OPTION_LOOP,
+        },
     }, {
         .name = "rsr.lcount",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){LCOUNT},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LCOUNT,
+            XTENSA_OPTION_LOOP,
+        },
     }, {
         .name = "rsr.lend",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){LEND},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LEND,
+            XTENSA_OPTION_LOOP,
+        },
     }, {
         .name = "rsr.litbase",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){LITBASE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LITBASE,
+            XTENSA_OPTION_EXTENDED_L32R,
+        },
     }, {
         .name = "rsr.m0",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.m1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MR + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 1,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.m2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MR + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 2,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.m3",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MR + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 3,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "rsr.memctl",
         .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},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.misc1",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MISC + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 1,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.misc2",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MISC + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 2,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.misc3",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){MISC + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 3,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.prefctl",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){PREFCTL},
     }, {
         .name = "rsr.prid",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){PRID},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PRID,
+            XTENSA_OPTION_PROCESSOR_ID,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ps",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){PS},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PS,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.ptevaddr",
-        .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){PTEVADDR},
+        .translate = translate_rsr_ptevaddr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PTEVADDR,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.rasid",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){RASID},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            RASID,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .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},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            SCOMPARE1,
+            XTENSA_OPTION_CONDITIONAL_STORE,
+        },
     }, {
         .name = "rsr.vecbase",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){VECBASE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            VECBASE,
+            XTENSA_OPTION_RELOCATABLE_VECTOR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.windowbase",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){WINDOW_BASE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_BASE,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsr.windowstart",
         .translate = translate_rsr,
-        .test_ill = test_ill_rsr,
-        .par = (const uint32_t[]){WINDOW_START},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_START,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "rsync",
@@ -4374,300 +4493,425 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_wrmsk_expstate,
     }, {
         .name = "wsr.176",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){176},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.208",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){208},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.acchi",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ACCHI},
+        .translate = translate_wsr_acchi,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCHI,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.acclo",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ACCLO},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCLO,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.atomctl",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ATOMCTL},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ATOMCTL,
+            XTENSA_OPTION_ATOMCTL,
+            0x3f,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.br",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){BR},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            BR,
+            XTENSA_OPTION_BOOLEAN,
+            0xffff,
+        },
     }, {
         .name = "wsr.cacheattr",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CACHEATTR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEATTR,
+            XTENSA_OPTION_CACHEATTR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.ccompare0",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CCOMPARE},
+        .translate = translate_wsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.ccompare1",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CCOMPARE + 1},
+        .translate = translate_wsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 1,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.ccompare2",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CCOMPARE + 2},
+        .translate = translate_wsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 2,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.ccount",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CCOUNT},
+        .translate = translate_wsr_ccount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CCOUNT,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.configid0",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CONFIGID0},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.configid1",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CONFIGID1},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.cpenable",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){CPENABLE},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CPENABLE,
+            XTENSA_OPTION_COPROCESSOR,
+            0xff,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.dbreaka0",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DBREAKA},
+        .translate = translate_wsr_dbreaka,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.dbreaka1",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DBREAKA + 1},
+        .translate = translate_wsr_dbreaka,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.dbreakc0",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DBREAKC},
+        .translate = translate_wsr_dbreakc,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.dbreakc1",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DBREAKC + 1},
+        .translate = translate_wsr_dbreakc,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.ddr",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DDR,
+            XTENSA_OPTION_DEBUG,
+        },
         .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,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.depc",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DEPC},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DEPC,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.dtlbcfg",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){DTLBCFG},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DTLBCFG,
+            XTENSA_OPTION_MMU,
+            0x01130000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc1",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EPC1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc2",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc3",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc4",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc5",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc6",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.epc7",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPC1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps2",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps3",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps4",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps5",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps6",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.eps7",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EPS2 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.exccause",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCCAUSE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCCAUSE,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave1",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCSAVE1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave2",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave3",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave4",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave5",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave6",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excsave7",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.excvaddr",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){EXCVADDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCVADDR,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.ibreaka0",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){IBREAKA},
+        .translate = translate_wsr_ibreaka,
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.ibreaka1",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){IBREAKA + 1},
+        .translate = translate_wsr_ibreaka,
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.ibreakenable",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){IBREAKENABLE},
+        .translate = translate_wsr_ibreakenable,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            IBREAKENABLE,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "wsr.icount",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ICOUNT},
+        .translate = translate_wsr_icount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNT,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.icountlevel",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ICOUNTLEVEL},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNTLEVEL,
+            XTENSA_OPTION_DEBUG,
+            0xf,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.intclear",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){INTCLEAR},
+        .translate = translate_wsr_intclear,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTCLEAR,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
@@ -4675,8 +4919,11 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "wsr.intenable",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){INTENABLE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTENABLE,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
@@ -4684,167 +4931,233 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "wsr.interrupt",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){INTSET},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTSET,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
     }, {
         .name = "wsr.intset",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){INTSET},
+        .translate = translate_wsr_intset,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTSET,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
     }, {
         .name = "wsr.itlbcfg",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){ITLBCFG},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ITLBCFG,
+            XTENSA_OPTION_MMU,
+            0x01130000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.lbeg",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){LBEG},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LBEG,
+            XTENSA_OPTION_LOOP,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.lcount",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){LCOUNT},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LCOUNT,
+            XTENSA_OPTION_LOOP,
+        },
     }, {
         .name = "wsr.lend",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){LEND},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LEND,
+            XTENSA_OPTION_LOOP,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.litbase",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){LITBASE},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LITBASE,
+            XTENSA_OPTION_EXTENDED_L32R,
+            0xfffff001,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.m0",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.m1",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MR + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 1,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.m2",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MR + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 2,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.m3",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MR + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 3,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "wsr.memctl",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
+        .translate = translate_wsr_memctl,
         .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},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.misc1",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MISC + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 1,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.misc2",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MISC + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 2,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.misc3",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MISC + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 3,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.mmid",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){MMID},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MMID,
+            XTENSA_OPTION_TRACE_PORT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.prefctl",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){PREFCTL},
     }, {
         .name = "wsr.prid",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){PRID},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "wsr.ps",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){PS},
+        .translate = translate_wsr_ps,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PS,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_CHECK_INTERRUPTS,
     }, {
         .name = "wsr.ptevaddr",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){PTEVADDR},
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PTEVADDR,
+            XTENSA_OPTION_MMU,
+            0xffc00000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.rasid",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){RASID},
+        .translate = translate_wsr_rasid,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            RASID,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wsr.sar",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
+        .translate = translate_wsr_sar,
         .par = (const uint32_t[]){SAR},
     }, {
         .name = "wsr.scompare1",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){SCOMPARE1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            SCOMPARE1,
+            XTENSA_OPTION_CONDITIONAL_STORE,
+        },
     }, {
         .name = "wsr.vecbase",
         .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){VECBASE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            VECBASE,
+            XTENSA_OPTION_RELOCATABLE_VECTOR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "wsr.windowbase",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){WINDOW_BASE},
+        .translate = translate_wsr_windowbase,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_BASE,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_SYNC_REGISTER_WINDOW,
     }, {
         .name = "wsr.windowstart",
-        .translate = translate_wsr,
-        .test_ill = test_ill_wsr,
-        .par = (const uint32_t[]){WINDOW_START},
+        .translate = translate_wsr_windowstart,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_START,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "wur.expstate",
@@ -4852,12 +5165,12 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){EXPSTATE},
     }, {
         .name = "wur.fcr",
-        .translate = translate_wur,
+        .translate = translate_wur_fcr,
         .par = (const uint32_t[]){FCR},
         .coprocessor = 0x1,
     }, {
         .name = "wur.fsr",
-        .translate = translate_wur,
+        .translate = translate_wur_fsr,
         .par = (const uint32_t[]){FSR},
         .coprocessor = 0x1,
     }, {
@@ -4873,471 +5186,635 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){BOOLEAN_XOR},
     }, {
         .name = "xsr.176",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){176},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.208",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){208},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.acchi",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ACCHI},
+        .translate = translate_xsr_acchi,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCHI,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.acclo",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ACCLO},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ACCLO,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.atomctl",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ATOMCTL},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ATOMCTL,
+            XTENSA_OPTION_ATOMCTL,
+            0x3f,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.br",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){BR},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            BR,
+            XTENSA_OPTION_BOOLEAN,
+            0xffff,
+        },
     }, {
         .name = "xsr.cacheattr",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CACHEATTR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEATTR,
+            XTENSA_OPTION_CACHEATTR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.ccompare0",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CCOMPARE},
+        .translate = translate_xsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.ccompare1",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CCOMPARE + 1},
+        .translate = translate_xsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 1,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.ccompare2",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CCOMPARE + 2},
+        .translate = translate_xsr_ccompare,
+        .test_ill = test_ill_ccompare,
+        .par = (const uint32_t[]){
+            CCOMPARE + 2,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.ccount",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CCOUNT},
+        .translate = translate_xsr_ccount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CCOUNT,
+            XTENSA_OPTION_TIMER_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.configid0",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CONFIGID0},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.configid1",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CONFIGID1},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.cpenable",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){CPENABLE},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CPENABLE,
+            XTENSA_OPTION_COPROCESSOR,
+            0xff,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.dbreaka0",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DBREAKA},
+        .translate = translate_xsr_dbreaka,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.dbreaka1",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DBREAKA + 1},
+        .translate = translate_xsr_dbreaka,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.dbreakc0",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DBREAKC},
+        .translate = translate_xsr_dbreakc,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.dbreakc1",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DBREAKC + 1},
+        .translate = translate_xsr_dbreakc,
+        .test_ill = test_ill_dbreak,
+        .par = (const uint32_t[]){
+            DBREAKC + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.ddr",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DDR,
+            XTENSA_OPTION_DEBUG,
+        },
         .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,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.depc",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DEPC},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DEPC,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.dtlbcfg",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){DTLBCFG},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            DTLBCFG,
+            XTENSA_OPTION_MMU,
+            0x01130000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc1",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EPC1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc2",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc3",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc4",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc5",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc6",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.epc7",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPC1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPC1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps2",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps3",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps4",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps5",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps6",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.eps7",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EPS2 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EPS2 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.exccause",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCCAUSE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCCAUSE,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave1",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCSAVE1,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave2",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 1},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 1,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave3",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 2},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 2,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave4",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 3},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 3,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave5",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 4},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 4,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave6",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 5},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 5,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excsave7",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCSAVE1 + 6},
+        .test_ill = test_ill_hpi,
+        .par = (const uint32_t[]){
+            EXCSAVE1 + 6,
+            XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.excvaddr",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){EXCVADDR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            EXCVADDR,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.ibreaka0",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){IBREAKA},
+        .translate = translate_xsr_ibreaka,
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.ibreaka1",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){IBREAKA + 1},
+        .translate = translate_xsr_ibreaka,
+        .test_ill = test_ill_ibreak,
+        .par = (const uint32_t[]){
+            IBREAKA + 1,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.ibreakenable",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){IBREAKENABLE},
+        .translate = translate_xsr_ibreakenable,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            IBREAKENABLE,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
     }, {
         .name = "xsr.icount",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ICOUNT},
+        .translate = translate_xsr_icount,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNT,
+            XTENSA_OPTION_DEBUG,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.icountlevel",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ICOUNTLEVEL},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ICOUNTLEVEL,
+            XTENSA_OPTION_DEBUG,
+            0xf,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.intclear",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){INTCLEAR},
-        .op_flags =
-            XTENSA_OP_PRIVILEGED |
-            XTENSA_OP_EXIT_TB_0 |
-            XTENSA_OP_CHECK_INTERRUPTS,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.intenable",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){INTENABLE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            INTENABLE,
+            XTENSA_OPTION_INTERRUPT,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
     }, {
         .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 |
-            XTENSA_OP_CHECK_INTERRUPTS,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .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 |
-            XTENSA_OP_CHECK_INTERRUPTS,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.itlbcfg",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){ITLBCFG},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            ITLBCFG,
+            XTENSA_OPTION_MMU,
+            0x01130000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.lbeg",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){LBEG},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LBEG,
+            XTENSA_OPTION_LOOP,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.lcount",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){LCOUNT},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LCOUNT,
+            XTENSA_OPTION_LOOP,
+        },
     }, {
         .name = "xsr.lend",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){LEND},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LEND,
+            XTENSA_OPTION_LOOP,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.litbase",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){LITBASE},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            LITBASE,
+            XTENSA_OPTION_EXTENDED_L32R,
+            0xfffff001,
+        },
         .op_flags = XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.m0",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MR},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.m1",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MR + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 1,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.m2",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MR + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 2,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.m3",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MR + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MR + 3,
+            XTENSA_OPTION_MAC16,
+        },
     }, {
         .name = "xsr.memctl",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
+        .translate = translate_xsr_memctl,
         .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},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.misc1",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MISC + 1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 1,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.misc2",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MISC + 2},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 2,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.misc3",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){MISC + 3},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MISC + 3,
+            XTENSA_OPTION_MISC_SR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.prefctl",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){PREFCTL},
     }, {
         .name = "xsr.prid",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){PRID},
-        .op_flags = XTENSA_OP_PRIVILEGED,
+        .op_flags = XTENSA_OP_ILL,
     }, {
         .name = "xsr.ps",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){PS},
+        .translate = translate_xsr_ps,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PS,
+            XTENSA_OPTION_EXCEPTION,
+        },
         .op_flags =
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_CHECK_INTERRUPTS,
     }, {
         .name = "xsr.ptevaddr",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){PTEVADDR},
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            PTEVADDR,
+            XTENSA_OPTION_MMU,
+            0xffc00000,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.rasid",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){RASID},
+        .translate = translate_xsr_rasid,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            RASID,
+            XTENSA_OPTION_MMU,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
         .name = "xsr.sar",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
+        .translate = translate_xsr_sar,
         .par = (const uint32_t[]){SAR},
     }, {
         .name = "xsr.scompare1",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){SCOMPARE1},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            SCOMPARE1,
+            XTENSA_OPTION_CONDITIONAL_STORE,
+        },
     }, {
         .name = "xsr.vecbase",
         .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){VECBASE},
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            VECBASE,
+            XTENSA_OPTION_RELOCATABLE_VECTOR,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
         .name = "xsr.windowbase",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){WINDOW_BASE},
+        .translate = translate_xsr_windowbase,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_BASE,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_SYNC_REGISTER_WINDOW,
     }, {
         .name = "xsr.windowstart",
-        .translate = translate_xsr,
-        .test_ill = test_ill_xsr,
-        .par = (const uint32_t[]){WINDOW_START},
+        .translate = translate_xsr_windowstart,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            WINDOW_START,
+            XTENSA_OPTION_WINDOWED_REGISTER,
+        },
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     },
 };
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 2/9] target/xtensa: make internal MMU functions static
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 1/9] target/xtensa: get rid of centralized SR properties Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 3/9] target/xtensa: define IDMA and gather/scatter IRQ types Max Filippov
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Remove declarations of the internal mmu_helper functions from the cpu.h,
make these functions static and shuffle them.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h        |  19 ------
 target/xtensa/mmu_helper.c | 163 ++++++++++++++++++++++++---------------------
 2 files changed, 87 insertions(+), 95 deletions(-)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 539033fccb61..502d41688365 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -658,17 +658,6 @@ static inline int xtensa_get_cring(const CPUXtensaState *env)
 }
 
 #ifndef CONFIG_USER_ONLY
-uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env,
-                                  bool dtlb, uint32_t way);
-void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
-        uint32_t *vpn, uint32_t wi, uint32_t *ei);
-int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
-        uint32_t *pwi, uint32_t *pei, uint8_t *pring);
-void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
-        xtensa_tlb_entry *entry, bool dtlb,
-        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
-void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
-        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
@@ -679,14 +668,6 @@ static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env)
 {
     return env->system_er;
 }
-
-static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
-        bool dtlb, unsigned wi, unsigned ei)
-{
-    return dtlb ?
-        env->dtlb[wi] + ei :
-        env->itlb[wi] + ei;
-}
 #endif
 
 static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c
index 79a10da2310e..465cfbf61359 100644
--- a/target/xtensa/mmu_helper.c
+++ b/target/xtensa/mmu_helper.c
@@ -78,8 +78,8 @@ static uint32_t get_page_size(const CPUXtensaState *env,
 /*!
  * Get bit mask for the virtual address bits translated by the TLB way
  */
-uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env,
-                                  bool dtlb, uint32_t way)
+static uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env,
+                                         bool dtlb, uint32_t way)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
         bool varway56 = dtlb ?
@@ -145,8 +145,9 @@ static uint32_t get_vpn_mask(const CPUXtensaState *env, bool dtlb, uint32_t way)
  * Split virtual address into VPN (with index) and entry index
  * for the given TLB way
  */
-void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
-        uint32_t *vpn, uint32_t wi, uint32_t *ei)
+static void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v,
+                                     bool dtlb, uint32_t *vpn,
+                                     uint32_t wi, uint32_t *ei)
 {
     bool varway56 = dtlb ?
         env->config->dtlb.varway56 :
@@ -213,6 +214,14 @@ static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
     }
 }
 
+static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb,
+                                              unsigned wi, unsigned ei)
+{
+    return dtlb ?
+        env->dtlb[wi] + ei :
+        env->itlb[wi] + ei;
+}
+
 static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
         uint32_t v, bool dtlb, uint32_t *pwi)
 {
@@ -227,65 +236,10 @@ static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
     return xtensa_tlb_get_entry(env, dtlb, wi, ei);
 }
 
-uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
-{
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
-        uint32_t wi;
-        const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
-        return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
-    } else {
-        return v & REGION_PAGE_MASK;
-    }
-}
-
-uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
-{
-    const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
-    return entry->paddr | entry->attr;
-}
-
-void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
-{
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
-        uint32_t wi;
-        xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
-        if (entry->variable && entry->asid) {
-            tlb_flush_page(CPU(xtensa_env_get_cpu(env)), entry->vaddr);
-            entry->asid = 0;
-        }
-    }
-}
-
-uint32_t HELPER(ptlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
-{
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
-        uint32_t wi;
-        uint32_t ei;
-        uint8_t ring;
-        int res = xtensa_tlb_lookup(env, v, dtlb, &wi, &ei, &ring);
-
-        switch (res) {
-        case 0:
-            if (ring >= xtensa_get_ring(env)) {
-                return (v & 0xfffff000) | wi | (dtlb ? 0x10 : 0x8);
-            }
-            break;
-
-        case INST_TLB_MULTI_HIT_CAUSE:
-        case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
-            HELPER(exception_cause_vaddr)(env, env->pc, res, v);
-            break;
-        }
-        return 0;
-    } else {
-        return (v & REGION_PAGE_MASK) | 0x1;
-    }
-}
-
-void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
-                              xtensa_tlb_entry *entry, bool dtlb,
-                              unsigned wi, unsigned ei, uint32_t vpn,
-                              uint32_t pte)
+static void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
+                                     xtensa_tlb_entry *entry, bool dtlb,
+                                     unsigned wi, unsigned ei, uint32_t vpn,
+                                     uint32_t pte)
 {
     entry->vaddr = vpn;
     entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi);
@@ -293,8 +247,9 @@ void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
     entry->attr = pte & 0xf;
 }
 
-void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
-                          unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte)
+static void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
+                                 unsigned wi, unsigned ei,
+                                 uint32_t vpn, uint32_t pte)
 {
     XtensaCPU *cpu = xtensa_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
@@ -322,15 +277,6 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
     }
 }
 
-void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
-{
-    uint32_t vpn;
-    uint32_t wi;
-    uint32_t ei;
-    split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
-    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
-}
-
 hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
@@ -462,8 +408,9 @@ static unsigned get_ring(const CPUXtensaState *env, uint8_t asid)
  * \param pring: [out] access ring
  * \return 0 if ok, exception cause code otherwise
  */
-int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
-                      uint32_t *pwi, uint32_t *pei, uint8_t *pring)
+static int xtensa_tlb_lookup(const CPUXtensaState *env,
+                             uint32_t addr, bool dtlb,
+                             uint32_t *pwi, uint32_t *pei, uint8_t *pring)
 {
     const xtensa_tlb *tlb = dtlb ?
         &env->config->dtlb : &env->config->itlb;
@@ -495,6 +442,70 @@ int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
         (dtlb ? LOAD_STORE_TLB_MISS_CAUSE : INST_TLB_MISS_CAUSE);
 }
 
+uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
+        return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
+    } else {
+        return v & REGION_PAGE_MASK;
+    }
+}
+
+uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+{
+    const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
+    return entry->paddr | entry->attr;
+}
+
+void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
+        if (entry->variable && entry->asid) {
+            tlb_flush_page(CPU(xtensa_env_get_cpu(env)), entry->vaddr);
+            entry->asid = 0;
+        }
+    }
+}
+
+uint32_t HELPER(ptlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
+{
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+        uint32_t wi;
+        uint32_t ei;
+        uint8_t ring;
+        int res = xtensa_tlb_lookup(env, v, dtlb, &wi, &ei, &ring);
+
+        switch (res) {
+        case 0:
+            if (ring >= xtensa_get_ring(env)) {
+                return (v & 0xfffff000) | wi | (dtlb ? 0x10 : 0x8);
+            }
+            break;
+
+        case INST_TLB_MULTI_HIT_CAUSE:
+        case LOAD_STORE_TLB_MULTI_HIT_CAUSE:
+            HELPER(exception_cause_vaddr)(env, env->pc, res, v);
+            break;
+        }
+        return 0;
+    } else {
+        return (v & REGION_PAGE_MASK) | 0x1;
+    }
+}
+
+void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
+{
+    uint32_t vpn;
+    uint32_t wi;
+    uint32_t ei;
+    split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
+    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
+}
+
 /*!
  * Convert MMU ATTR to PAGE_{READ,WRITE,EXEC} mask.
  * See ISA, 4.6.5.10
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 3/9] target/xtensa: define IDMA and gather/scatter IRQ types
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 1/9] target/xtensa: get rid of centralized SR properties Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 2/9] target/xtensa: make internal MMU functions static Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 4/9] target/xtensa: add parity/ECC option SRs Max Filippov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

IDMA and scatter/gather features introduced new IRQ types that
overlay_tool.h need to initialize Xtensa configuration.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h          | 3 +++
 target/xtensa/overlay_tool.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 502d41688365..d4258fcc6199 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -298,6 +298,9 @@ typedef enum {
     INTTYPE_DEBUG,
     INTTYPE_WRITE_ERR,
     INTTYPE_PROFILING,
+    INTTYPE_IDMA_DONE,
+    INTTYPE_IDMA_ERR,
+    INTTYPE_GS_ERR,
     INTTYPE_MAX
 } interrupt_type;
 
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index ea07576bc921..8b380ce5e329 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -200,6 +200,9 @@
 #define XTHAL_INTTYPE_TBD2 INTTYPE_WRITE_ERR
 #define XTHAL_INTTYPE_WRITE_ERROR INTTYPE_WRITE_ERR
 #define XTHAL_INTTYPE_PROFILING INTTYPE_PROFILING
+#define XTHAL_INTTYPE_IDMA_DONE INTTYPE_IDMA_DONE
+#define XTHAL_INTTYPE_IDMA_ERR INTTYPE_IDMA_ERR
+#define XTHAL_INTTYPE_GS_ERR INTTYPE_GS_ERR
 
 
 #define INTERRUPT(i) { \
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 4/9] target/xtensa: add parity/ECC option SRs
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (2 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 3/9] target/xtensa: define IDMA and gather/scatter IRQ types Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 5/9] target/xtensa: implement MPU option Max Filippov
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Add SRs and rsr/wsr/xsr opcodes defined by the parity/ECC xtensa option.
The implementation is trivial since we don't emulate parity/ECC yet.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h          |   6 ++
 target/xtensa/overlay_tool.h |   2 +
 target/xtensa/translate.c    | 162 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index d4258fcc6199..74ee7d125360 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -144,6 +144,12 @@ enum {
     CACHEATTR = 98,
     ATOMCTL = 99,
     DDR = 104,
+    MEPC = 106,
+    MEPS = 107,
+    MESAVE = 108,
+    MESR = 109,
+    MECR = 110,
+    MEVADDR = 111,
     IBREAKA = 128,
     DBREAKA = 144,
     DBREAKC = 160,
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index 8b380ce5e329..ffaab4b094cc 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -112,6 +112,8 @@
     XCHAL_OPTION(XCHAL_DCACHE_LINE_LOCKABLE, \
             XTENSA_OPTION_DCACHE_INDEX_LOCK) | \
     XCHAL_OPTION(XCHAL_UNALIGNED_LOAD_HW, XTENSA_OPTION_HW_ALIGNMENT) | \
+    XCHAL_OPTION(XCHAL_HAVE_MEM_ECC_PARITY, \
+                 XTENSA_OPTION_MEMORY_ECC_PARITY) | \
     /* Memory protection and translation */ \
     XCHAL_OPTION(XCHAL_HAVE_MIMIC_CACHEATTR, \
             XTENSA_OPTION_REGION_PROTECTION) | \
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 100d6e126590..63a90fdd17dc 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -4216,6 +4216,60 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "rsr.mecr",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MECR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.mepc",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPC,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.meps",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPS,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.mesave",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESAVE,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.mesr",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.mevaddr",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "rsr.misc0",
         .translate = translate_rsr,
         .test_ill = test_ill_sr,
@@ -5036,6 +5090,60 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "wsr.mecr",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MECR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "wsr.mepc",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPC,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "wsr.meps",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPS,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "wsr.mesave",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESAVE,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "wsr.mesr",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "wsr.mevaddr",
+        .translate = translate_wsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "wsr.misc0",
         .translate = translate_wsr,
         .test_ill = test_ill_sr,
@@ -5702,6 +5810,60 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "xsr.mecr",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MECR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "xsr.mepc",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPC,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "xsr.meps",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MEPS,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "xsr.mesave",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESAVE,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "xsr.mesr",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "xsr.mevaddr",
+        .translate = translate_xsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MESR,
+            XTENSA_OPTION_MEMORY_ECC_PARITY,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "xsr.misc0",
         .translate = translate_xsr,
         .test_ill = test_ill_sr,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 5/9] target/xtensa: implement MPU option
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (3 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 4/9] target/xtensa: add parity/ECC option SRs Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 6/9] target/xtensa: implement DIWBUI.P opcode Max Filippov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

The Memory Protection Unit Option (MPU) is a combined instruction and
data memory protection unit with more protection flexibility than the
Region Protection Option or the Region Translation Option but without
any translation capability. It does no demand paging and does not
reference a memory-based page table.

Add memory protection unit option, internal state, SRs and opcodes.
Implement MPU entries dumping in dump_mmu.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.c          |   1 -
 target/xtensa/cpu.h          |  17 ++
 target/xtensa/helper.h       |   5 +
 target/xtensa/mmu_helper.c   | 369 +++++++++++++++++++++++++++++++++++++++++++
 target/xtensa/overlay_tool.h |  29 ++++
 target/xtensa/translate.c    | 146 +++++++++++++++++
 6 files changed, 566 insertions(+), 1 deletion(-)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index a54dbe42602d..4215a1881ec7 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -78,7 +78,6 @@ static void xtensa_cpu_reset(CPUState *s)
     env->sregs[VECBASE] = env->config->vecbase;
     env->sregs[IBREAKENABLE] = 0;
     env->sregs[MEMCTL] = MEMCTL_IL0EN & env->config->memctl_mask;
-    env->sregs[CACHEATTR] = 0x22222222;
     env->sregs[ATOMCTL] = xtensa_option_enabled(env->config,
             XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
     env->sregs[CONFIGID0] = env->config->configid[0];
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 74ee7d125360..d6e6bf6ca183 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -99,6 +99,7 @@ enum {
     /* Memory protection and translation */
     XTENSA_OPTION_REGION_PROTECTION,
     XTENSA_OPTION_REGION_TRANSLATION,
+    XTENSA_OPTION_MPU,
     XTENSA_OPTION_MMU,
     XTENSA_OPTION_CACHEATTR,
 
@@ -137,11 +138,15 @@ enum {
     PTEVADDR = 83,
     MMID = 89,
     RASID = 90,
+    MPUENB = 90,
     ITLBCFG = 91,
     DTLBCFG = 92,
+    MPUCFG = 92,
+    ERACCESS = 95,
     IBREAKENABLE = 96,
     MEMCTL = 97,
     CACHEATTR = 98,
+    CACHEADRDIS = 98,
     ATOMCTL = 99,
     DDR = 104,
     MEPC = 106,
@@ -234,6 +239,7 @@ enum {
 #define MAX_TLB_WAY_SIZE 8
 #define MAX_NDBREAK 2
 #define MAX_NMEMORY 4
+#define MAX_MPU_FOREGROUND_SEGMENTS 32
 
 #define REGION_PAGE_MASK 0xe0000000
 
@@ -327,6 +333,11 @@ typedef struct xtensa_tlb {
     unsigned nrefillentries;
 } xtensa_tlb;
 
+typedef struct xtensa_mpu_entry {
+    uint32_t vaddr;
+    uint32_t attr;
+} xtensa_mpu_entry;
+
 typedef struct XtensaGdbReg {
     int targno;
     unsigned flags;
@@ -477,6 +488,11 @@ struct XtensaConfig {
 
     xtensa_tlb itlb;
     xtensa_tlb dtlb;
+
+    uint32_t mpu_align;
+    unsigned n_mpu_fg_segments;
+    unsigned n_mpu_bg_segments;
+    const xtensa_mpu_entry *mpu_bg;
 };
 
 typedef struct XtensaConfigList {
@@ -513,6 +529,7 @@ typedef struct CPUXtensaState {
 #ifndef CONFIG_USER_ONLY
     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
     xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
+    xtensa_mpu_entry mpu_fg[MAX_MPU_FOREGROUND_SEGMENTS];
     unsigned autorefill_idx;
     bool runstall;
     AddressSpace *address_space_er;
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index 0b9ec670c86e..9216bee57e9a 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -33,6 +33,11 @@ DEF_HELPER_FLAGS_3(rtlb1, TCG_CALL_NO_RWG_SE, i32, env, i32, i32)
 DEF_HELPER_3(itlb, void, env, i32, i32)
 DEF_HELPER_3(ptlb, i32, env, i32, i32)
 DEF_HELPER_4(wtlb, void, env, i32, i32, i32)
+DEF_HELPER_2(wsr_mpuenb, void, env, i32)
+DEF_HELPER_3(wptlb, void, env, i32, i32)
+DEF_HELPER_FLAGS_2(rptlb0, TCG_CALL_NO_RWG_SE, i32, env, i32)
+DEF_HELPER_FLAGS_2(rptlb1, TCG_CALL_NO_RWG_SE, i32, env, i32)
+DEF_HELPER_2(pptlb, i32, env, i32)
 
 DEF_HELPER_2(wsr_ibreakenable, void, env, i32)
 DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32)
diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c
index 465cfbf61359..cab39f687a21 100644
--- a/target/xtensa/mmu_helper.c
+++ b/target/xtensa/mmu_helper.c
@@ -35,6 +35,31 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 
+#define XTENSA_MPU_SEGMENT_MASK 0x0000001f
+#define XTENSA_MPU_ACC_RIGHTS_MASK 0x00000f00
+#define XTENSA_MPU_ACC_RIGHTS_SHIFT 8
+#define XTENSA_MPU_MEM_TYPE_MASK 0x001ff000
+#define XTENSA_MPU_MEM_TYPE_SHIFT 12
+#define XTENSA_MPU_ATTR_MASK 0x001fff00
+
+#define XTENSA_MPU_PROBE_B 0x40000000
+#define XTENSA_MPU_PROBE_V 0x80000000
+
+#define XTENSA_MPU_SYSTEM_TYPE_DEVICE 0x0001
+#define XTENSA_MPU_SYSTEM_TYPE_NC     0x0002
+#define XTENSA_MPU_SYSTEM_TYPE_C      0x0003
+#define XTENSA_MPU_SYSTEM_TYPE_MASK   0x0003
+
+#define XTENSA_MPU_TYPE_SYS_C     0x0010
+#define XTENSA_MPU_TYPE_SYS_W     0x0020
+#define XTENSA_MPU_TYPE_SYS_R     0x0040
+#define XTENSA_MPU_TYPE_CPU_C     0x0100
+#define XTENSA_MPU_TYPE_CPU_W     0x0200
+#define XTENSA_MPU_TYPE_CPU_R     0x0400
+#define XTENSA_MPU_TYPE_CPU_CACHE 0x0800
+#define XTENSA_MPU_TYPE_B         0x1000
+#define XTENSA_MPU_TYPE_INT       0x2000
+
 void HELPER(itlb_hit_test)(CPUXtensaState *env, uint32_t vaddr)
 {
     /*
@@ -382,7 +407,20 @@ void reset_mmu(CPUXtensaState *env)
         reset_tlb_mmu_all_ways(env, &env->config->dtlb, env->dtlb);
         reset_tlb_mmu_ways56(env, &env->config->itlb, env->itlb);
         reset_tlb_mmu_ways56(env, &env->config->dtlb, env->dtlb);
+    } else if (xtensa_option_enabled(env->config, XTENSA_OPTION_MPU)) {
+        unsigned i;
+
+        env->sregs[MPUENB] = 0;
+        env->sregs[MPUCFG] = env->config->n_mpu_fg_segments;
+        env->sregs[CACHEADRDIS] = 0;
+        assert(env->config->n_mpu_bg_segments > 0 &&
+               env->config->mpu_bg[0].vaddr == 0);
+        for (i = 1; i < env->config->n_mpu_bg_segments; ++i) {
+            assert(env->config->mpu_bg[i].vaddr >=
+                   env->config->mpu_bg[i - 1].vaddr);
+        }
     } else {
+        env->sregs[CACHEATTR] = 0x22222222;
         reset_tlb_region_way0(env, env->itlb);
         reset_tlb_region_way0(env, env->dtlb);
     }
@@ -579,6 +617,149 @@ static unsigned cacheattr_attr_to_access(uint32_t attr)
     return access[attr & 0xf];
 }
 
+struct attr_pattern {
+    uint32_t mask;
+    uint32_t value;
+};
+
+static int attr_pattern_match(uint32_t attr,
+                              const struct attr_pattern *pattern,
+                              size_t n)
+{
+    size_t i;
+
+    for (i = 0; i < n; ++i) {
+        if ((attr & pattern[i].mask) == pattern[i].value) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static unsigned mpu_attr_to_cpu_cache(uint32_t attr)
+{
+    static const struct attr_pattern cpu_c[] = {
+        { .mask = 0x18f, .value = 0x089 },
+        { .mask = 0x188, .value = 0x080 },
+        { .mask = 0x180, .value = 0x180 },
+    };
+
+    unsigned type = 0;
+
+    if (attr_pattern_match(attr, cpu_c, ARRAY_SIZE(cpu_c))) {
+        type |= XTENSA_MPU_TYPE_CPU_CACHE;
+        if (attr & 0x10) {
+            type |= XTENSA_MPU_TYPE_CPU_C;
+        }
+        if (attr & 0x20) {
+            type |= XTENSA_MPU_TYPE_CPU_W;
+        }
+        if (attr & 0x40) {
+            type |= XTENSA_MPU_TYPE_CPU_R;
+        }
+    }
+    return type;
+}
+
+static unsigned mpu_attr_to_type(uint32_t attr)
+{
+    static const struct attr_pattern device_type[] = {
+        { .mask = 0x1f6, .value = 0x000 },
+        { .mask = 0x1f6, .value = 0x006 },
+    };
+    static const struct attr_pattern sys_nc_type[] = {
+        { .mask = 0x1fe, .value = 0x018 },
+        { .mask = 0x1fe, .value = 0x01e },
+        { .mask = 0x18f, .value = 0x089 },
+    };
+    static const struct attr_pattern sys_c_type[] = {
+        { .mask = 0x1f8, .value = 0x010 },
+        { .mask = 0x188, .value = 0x080 },
+        { .mask = 0x1f0, .value = 0x030 },
+        { .mask = 0x180, .value = 0x180 },
+    };
+    static const struct attr_pattern b[] = {
+        { .mask = 0x1f7, .value = 0x001 },
+        { .mask = 0x1f7, .value = 0x007 },
+        { .mask = 0x1ff, .value = 0x019 },
+        { .mask = 0x1ff, .value = 0x01f },
+    };
+
+    unsigned type = 0;
+
+    attr = (attr & XTENSA_MPU_MEM_TYPE_MASK) >> XTENSA_MPU_MEM_TYPE_SHIFT;
+    if (attr_pattern_match(attr, device_type, ARRAY_SIZE(device_type))) {
+        type |= XTENSA_MPU_SYSTEM_TYPE_DEVICE;
+        if (attr & 0x80) {
+            type |= XTENSA_MPU_TYPE_INT;
+        }
+    }
+    if (attr_pattern_match(attr, sys_nc_type, ARRAY_SIZE(sys_nc_type))) {
+        type |= XTENSA_MPU_SYSTEM_TYPE_NC;
+    }
+    if (attr_pattern_match(attr, sys_c_type, ARRAY_SIZE(sys_c_type))) {
+        type |= XTENSA_MPU_SYSTEM_TYPE_C;
+        if (attr & 0x1) {
+            type |= XTENSA_MPU_TYPE_SYS_C;
+        }
+        if (attr & 0x2) {
+            type |= XTENSA_MPU_TYPE_SYS_W;
+        }
+        if (attr & 0x4) {
+            type |= XTENSA_MPU_TYPE_SYS_R;
+        }
+    }
+    if (attr_pattern_match(attr, b, ARRAY_SIZE(b))) {
+        type |= XTENSA_MPU_TYPE_B;
+    }
+    type |= mpu_attr_to_cpu_cache(attr);
+
+    return type;
+}
+
+static unsigned mpu_attr_to_access(uint32_t attr, unsigned ring)
+{
+    static const unsigned access[2][16] = {
+        [0] = {
+             [4] = PAGE_READ,
+             [5] = PAGE_READ              | PAGE_EXEC,
+             [6] = PAGE_READ | PAGE_WRITE,
+             [7] = PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+             [8] =             PAGE_WRITE,
+             [9] = PAGE_READ | PAGE_WRITE,
+            [10] = PAGE_READ | PAGE_WRITE,
+            [11] = PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+            [12] = PAGE_READ,
+            [13] = PAGE_READ              | PAGE_EXEC,
+            [14] = PAGE_READ | PAGE_WRITE,
+            [15] = PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+        },
+        [1] = {
+             [8] =             PAGE_WRITE,
+             [9] = PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+            [10] = PAGE_READ,
+            [11] = PAGE_READ              | PAGE_EXEC,
+            [12] = PAGE_READ,
+            [13] = PAGE_READ              | PAGE_EXEC,
+            [14] = PAGE_READ | PAGE_WRITE,
+            [15] = PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+        },
+    };
+    unsigned rv;
+    unsigned type;
+
+    type = mpu_attr_to_cpu_cache(attr);
+    rv = access[ring != 0][(attr & XTENSA_MPU_ACC_RIGHTS_MASK) >>
+        XTENSA_MPU_ACC_RIGHTS_SHIFT];
+
+    if (type & XTENSA_MPU_TYPE_CPU_CACHE) {
+        rv |= (type & XTENSA_MPU_TYPE_CPU_C) ? PAGE_CACHE_WB : PAGE_CACHE_WT;
+    } else {
+        rv |= PAGE_CACHE_BYPASS;
+    }
+    return rv;
+}
+
 static bool is_access_granted(unsigned access, int is_write)
 {
     switch (is_write) {
@@ -723,6 +904,129 @@ static int get_physical_addr_region(CPUXtensaState *env,
     return 0;
 }
 
+static int xtensa_mpu_lookup(const xtensa_mpu_entry *entry, unsigned n,
+                             uint32_t vaddr, unsigned *segment)
+{
+    unsigned nhits = 0;
+    unsigned i;
+
+    for (i = 0; i < n; ++i) {
+        if (vaddr >= entry[i].vaddr &&
+            (i == n - 1 || vaddr < entry[i + 1].vaddr)) {
+            if (nhits++) {
+                break;
+            }
+            *segment = i;
+        }
+    }
+    return nhits;
+}
+
+void HELPER(wsr_mpuenb)(CPUXtensaState *env, uint32_t v)
+{
+    XtensaCPU *cpu = xtensa_env_get_cpu(env);
+
+    v &= (2u << (env->config->n_mpu_fg_segments - 1)) - 1;
+
+    if (v != env->sregs[MPUENB]) {
+        env->sregs[MPUENB] = v;
+        tlb_flush(CPU(cpu));
+    }
+}
+
+void HELPER(wptlb)(CPUXtensaState *env, uint32_t p, uint32_t v)
+{
+    unsigned segment = p & XTENSA_MPU_SEGMENT_MASK;
+
+    if (segment < env->config->n_mpu_fg_segments) {
+        env->mpu_fg[segment].vaddr = v & -env->config->mpu_align;
+        env->mpu_fg[segment].attr = p & XTENSA_MPU_ATTR_MASK;
+        env->sregs[MPUENB] = deposit32(env->sregs[MPUENB], segment, 1, v);
+        tlb_flush(CPU(xtensa_env_get_cpu(env)));
+    }
+}
+
+uint32_t HELPER(rptlb0)(CPUXtensaState *env, uint32_t s)
+{
+    unsigned segment = s & XTENSA_MPU_SEGMENT_MASK;
+
+    if (segment < env->config->n_mpu_fg_segments) {
+        return env->mpu_fg[segment].vaddr |
+            extract32(env->sregs[MPUENB], segment, 1);
+    } else {
+        return 0;
+    }
+}
+
+uint32_t HELPER(rptlb1)(CPUXtensaState *env, uint32_t s)
+{
+    unsigned segment = s & XTENSA_MPU_SEGMENT_MASK;
+
+    if (segment < env->config->n_mpu_fg_segments) {
+        return env->mpu_fg[segment].attr;
+    } else {
+        return 0;
+    }
+}
+
+uint32_t HELPER(pptlb)(CPUXtensaState *env, uint32_t v)
+{
+    unsigned nhits;
+    unsigned segment = XTENSA_MPU_PROBE_B;
+    unsigned bg_segment;
+
+    nhits = xtensa_mpu_lookup(env->mpu_fg, env->config->n_mpu_fg_segments,
+                              v, &segment);
+    if (nhits > 1) {
+        HELPER(exception_cause_vaddr)(env, env->pc,
+                                      LOAD_STORE_TLB_MULTI_HIT_CAUSE, v);
+    } else if (nhits == 1 && (env->sregs[MPUENB] & (1u << segment))) {
+        return env->mpu_fg[segment].attr | segment | XTENSA_MPU_PROBE_V;
+    } else {
+        xtensa_mpu_lookup(env->config->mpu_bg,
+                          env->config->n_mpu_bg_segments,
+                          v, &bg_segment);
+        return env->config->mpu_bg[bg_segment].attr | segment;
+    }
+}
+
+static int get_physical_addr_mpu(CPUXtensaState *env,
+                                 uint32_t vaddr, int is_write, int mmu_idx,
+                                 uint32_t *paddr, uint32_t *page_size,
+                                 unsigned *access)
+{
+    unsigned nhits;
+    unsigned segment;
+    uint32_t attr;
+
+    nhits = xtensa_mpu_lookup(env->mpu_fg, env->config->n_mpu_fg_segments,
+                              vaddr, &segment);
+    if (nhits > 1) {
+        return is_write < 2 ?
+            LOAD_STORE_TLB_MULTI_HIT_CAUSE :
+            INST_TLB_MULTI_HIT_CAUSE;
+    } else if (nhits == 1 && (env->sregs[MPUENB] & (1u << segment))) {
+        attr = env->mpu_fg[segment].attr;
+    } else {
+        xtensa_mpu_lookup(env->config->mpu_bg,
+                          env->config->n_mpu_bg_segments,
+                          vaddr, &segment);
+        attr = env->config->mpu_bg[segment].attr;
+    }
+
+    *access = mpu_attr_to_access(attr, mmu_idx);
+    if (!is_access_granted(*access, is_write)) {
+        return is_write < 2 ?
+            (is_write ?
+             STORE_PROHIBITED_CAUSE :
+             LOAD_PROHIBITED_CAUSE) :
+            INST_FETCH_PROHIBITED_CAUSE;
+    }
+    *paddr = vaddr;
+    *page_size = env->config->mpu_align;
+    return 0;
+}
+
 /*!
  * Convert virtual address to physical addr.
  * MMU may issue pagewalk and change xtensa autorefill TLB way entry.
@@ -743,6 +1047,9 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
                 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) {
         return get_physical_addr_region(env, vaddr, is_write, mmu_idx,
                                         paddr, page_size, access);
+    } else if (xtensa_option_enabled(env->config, XTENSA_OPTION_MPU)) {
+        return get_physical_addr_mpu(env, vaddr, is_write, mmu_idx,
+                                     paddr, page_size, access);
     } else {
         *paddr = vaddr;
         *page_size = TARGET_PAGE_SIZE;
@@ -810,6 +1117,63 @@ static void dump_tlb(CPUXtensaState *env, bool dtlb)
     }
 }
 
+static void dump_mpu(CPUXtensaState *env,
+                     const xtensa_mpu_entry *entry, unsigned n)
+{
+    unsigned i;
+
+    qemu_printf("\t%s  Vaddr       Attr        Ring0  Ring1  System Type    CPU cache\n"
+                "\t%s  ----------  ----------  -----  -----  -------------  ---------\n",
+                env ? "En" : "  ",
+                env ? "--" : "  ");
+
+    for (i = 0; i < n; ++i) {
+        uint32_t attr = entry[i].attr;
+        unsigned access0 = mpu_attr_to_access(attr, 0);
+        unsigned access1 = mpu_attr_to_access(attr, 1);
+        unsigned type = mpu_attr_to_type(attr);
+        char cpu_cache = (type & XTENSA_MPU_TYPE_CPU_CACHE) ? '-' : ' ';
+
+        qemu_printf("\t %c  0x%08x  0x%08x   %c%c%c    %c%c%c   ",
+                    env ?
+                    ((env->sregs[MPUENB] & (1u << i)) ? '+' : '-') : ' ',
+                    entry[i].vaddr, attr,
+                    (access0 & PAGE_READ) ? 'R' : '-',
+                    (access0 & PAGE_WRITE) ? 'W' : '-',
+                    (access0 & PAGE_EXEC) ? 'X' : '-',
+                    (access1 & PAGE_READ) ? 'R' : '-',
+                    (access1 & PAGE_WRITE) ? 'W' : '-',
+                    (access1 & PAGE_EXEC) ? 'X' : '-');
+
+        switch (type & XTENSA_MPU_SYSTEM_TYPE_MASK) {
+        case XTENSA_MPU_SYSTEM_TYPE_DEVICE:
+            qemu_printf("Device %cB %3s\n",
+                        (type & XTENSA_MPU_TYPE_B) ? ' ' : 'n',
+                        (type & XTENSA_MPU_TYPE_INT) ? "int" : "");
+            break;
+        case XTENSA_MPU_SYSTEM_TYPE_NC:
+            qemu_printf("Sys NC %cB      %c%c%c\n",
+                        (type & XTENSA_MPU_TYPE_B) ? ' ' : 'n',
+                        (type & XTENSA_MPU_TYPE_CPU_R) ? 'r' : cpu_cache,
+                        (type & XTENSA_MPU_TYPE_CPU_W) ? 'w' : cpu_cache,
+                        (type & XTENSA_MPU_TYPE_CPU_C) ? 'c' : cpu_cache);
+            break;
+        case XTENSA_MPU_SYSTEM_TYPE_C:
+            qemu_printf("Sys  C %c%c%c     %c%c%c\n",
+                        (type & XTENSA_MPU_TYPE_SYS_R) ? 'R' : '-',
+                        (type & XTENSA_MPU_TYPE_SYS_W) ? 'W' : '-',
+                        (type & XTENSA_MPU_TYPE_SYS_C) ? 'C' : '-',
+                        (type & XTENSA_MPU_TYPE_CPU_R) ? 'r' : cpu_cache,
+                        (type & XTENSA_MPU_TYPE_CPU_W) ? 'w' : cpu_cache,
+                        (type & XTENSA_MPU_TYPE_CPU_C) ? 'c' : cpu_cache);
+            break;
+        default:
+            qemu_printf("Unknown\n");
+            break;
+        }
+    }
+}
+
 void dump_mmu(CPUXtensaState *env)
 {
     if (xtensa_option_bits_enabled(env->config,
@@ -821,6 +1185,11 @@ void dump_mmu(CPUXtensaState *env)
         dump_tlb(env, false);
         qemu_printf("\nDTLB:\n");
         dump_tlb(env, true);
+    } else if (xtensa_option_enabled(env->config, XTENSA_OPTION_MPU)) {
+        qemu_printf("Foreground map:\n");
+        dump_mpu(env, env->mpu_fg, env->config->n_mpu_fg_segments);
+        qemu_printf("\nBackground map:\n");
+        dump_mpu(NULL, env->config->mpu_bg, env->config->n_mpu_bg_segments);
     } else {
         qemu_printf("No TLB for this CPU core\n");
     }
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index ffaab4b094cc..b61c92539861 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -72,6 +72,10 @@
 #define XCHAL_HAVE_EXTERN_REGS 0
 #endif
 
+#ifndef XCHAL_HAVE_MPU
+#define XCHAL_HAVE_MPU 0
+#endif
+
 #define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
 
 #define XTENSA_OPTIONS ( \
@@ -119,6 +123,7 @@
             XTENSA_OPTION_REGION_PROTECTION) | \
     XCHAL_OPTION(XCHAL_HAVE_XLT_CACHEATTR, \
             XTENSA_OPTION_REGION_TRANSLATION) | \
+    XCHAL_OPTION(XCHAL_HAVE_MPU, XTENSA_OPTION_MPU) | \
     XCHAL_OPTION(XCHAL_HAVE_PTP_MMU, XTENSA_OPTION_MMU) | \
     XCHAL_OPTION(XCHAL_HAVE_CACHEATTR, XTENSA_OPTION_CACHEATTR) | \
     /* Other, TODO */ \
@@ -361,6 +366,30 @@
 #define XCHAL_SYSRAM0_SIZE  0x04000000
 #endif
 
+#elif XCHAL_HAVE_MPU
+
+#ifndef XTENSA_MPU_BG_MAP
+#define XTENSA_MPU_BG_MAP (xtensa_mpu_entry []){\
+    { .vaddr = 0, .attr = 0x00006700, }, \
+}
+#endif
+
+#define TLB_SECTION \
+    .mpu_align = XCHAL_MPU_ALIGN, \
+    .n_mpu_fg_segments = XCHAL_MPU_ENTRIES, \
+    .n_mpu_bg_segments = 1, \
+    .mpu_bg = XTENSA_MPU_BG_MAP
+
+#ifndef XCHAL_SYSROM0_PADDR
+#define XCHAL_SYSROM0_PADDR 0x50000000
+#define XCHAL_SYSROM0_SIZE  0x04000000
+#endif
+
+#ifndef XCHAL_SYSRAM0_PADDR
+#define XCHAL_SYSRAM0_PADDR 0x60000000
+#define XCHAL_SYSRAM0_SIZE  0x04000000
+#endif
+
 #else
 
 #ifndef XCHAL_SYSROM0_PADDR
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 63a90fdd17dc..782f2ec62099 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -1992,6 +1992,15 @@ static void translate_ptlb(DisasContext *dc, const OpcodeArg arg[],
 #endif
 }
 
+static void translate_pptlb(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    tcg_gen_movi_i32(cpu_pc, dc->pc);
+    gen_helper_pptlb(arg[0].out, cpu_env, arg[1].in);
+#endif
+}
+
 static void translate_quos(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
@@ -2184,6 +2193,22 @@ static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
 #endif
 }
 
+static void translate_rptlb0(DisasContext *dc, const OpcodeArg arg[],
+                             const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_rptlb0(arg[0].out, cpu_env, arg[1].in);
+#endif
+}
+
+static void translate_rptlb1(DisasContext *dc, const OpcodeArg arg[],
+                             const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_rptlb1(arg[0].out, cpu_env, arg[1].in);
+#endif
+}
+
 static void translate_rur(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
@@ -2445,6 +2470,14 @@ static void translate_wtlb(DisasContext *dc, const OpcodeArg arg[],
 #endif
 }
 
+static void translate_wptlb(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_wptlb(cpu_env, arg[0].in, arg[1].in);
+#endif
+}
+
 static void translate_wer(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
@@ -2593,6 +2626,14 @@ static void translate_wsr_memctl(DisasContext *dc, const OpcodeArg arg[],
 #endif
 }
 
+static void translate_wsr_mpuenb(DisasContext *dc, const OpcodeArg arg[],
+                                 const uint32_t par[])
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_wsr_mpuenb(cpu_env, arg[0].in);
+#endif
+}
+
 static void translate_wsr_ps(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
@@ -2731,6 +2772,7 @@ gen_translate_xsr(ibreaka)
 gen_translate_xsr(ibreakenable)
 gen_translate_xsr(icount)
 gen_translate_xsr(memctl)
+gen_translate_xsr(mpuenb)
 gen_translate_xsr(ps)
 gen_translate_xsr(rasid)
 gen_translate_xsr(sar)
@@ -3581,6 +3623,10 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "pptlb",
+        .translate = translate_pptlb,
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "quos",
         .translate = translate_quos,
         .par = (const uint32_t[]){true},
@@ -3667,6 +3713,14 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){false, 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "rptlb0",
+        .translate = translate_rptlb0,
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rptlb1",
+        .translate = translate_rptlb1,
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "rotw",
         .translate = translate_rotw,
         .op_flags = XTENSA_OP_PRIVILEGED |
@@ -3723,6 +3777,15 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OPTION_BOOLEAN,
         },
     }, {
+        .name = "rsr.cacheadrdis",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEADRDIS,
+            XTENSA_OPTION_MPU,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "rsr.cacheattr",
         .translate = translate_rsr,
         .test_ill = test_ill_sr,
@@ -3976,6 +4039,11 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "rsr.eraccess",
+        .translate = translate_rsr,
+        .par = (const uint32_t[]){ERACCESS},
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "rsr.exccause",
         .translate = translate_rsr,
         .test_ill = test_ill_sr,
@@ -4306,6 +4374,24 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "rsr.mpucfg",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MPUCFG,
+            XTENSA_OPTION_MPU,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
+        .name = "rsr.mpuenb",
+        .translate = translate_rsr,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MPUENB,
+            XTENSA_OPTION_MPU,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "rsr.prefctl",
         .translate = translate_rsr,
         .par = (const uint32_t[]){PREFCTL},
@@ -4543,6 +4629,10 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
     }, {
+        .name = "wptlb",
+        .translate = translate_wptlb,
+        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+    }, {
         .name = "wrmsk_expstate",
         .translate = translate_wrmsk_expstate,
     }, {
@@ -4587,6 +4677,16 @@ static const XtensaOpcodeOps core_ops[] = {
             0xffff,
         },
     }, {
+        .name = "wsr.cacheadrdis",
+        .translate = translate_wsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEADRDIS,
+            XTENSA_OPTION_MPU,
+            0xff,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "wsr.cacheattr",
         .translate = translate_wsr,
         .test_ill = test_ill_sr,
@@ -4832,6 +4932,15 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "wsr.eraccess",
+        .translate = translate_wsr_mask,
+        .par = (const uint32_t[]){
+            ERACCESS,
+            0,
+            0xffff,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "wsr.exccause",
         .translate = translate_wsr,
         .test_ill = test_ill_sr,
@@ -5189,6 +5298,15 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "wsr.mpuenb",
+        .translate = translate_wsr_mpuenb,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MPUENB,
+            XTENSA_OPTION_MPU,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+    }, {
         .name = "wsr.prefctl",
         .translate = translate_wsr,
         .par = (const uint32_t[]){PREFCTL},
@@ -5334,6 +5452,16 @@ static const XtensaOpcodeOps core_ops[] = {
             0xffff,
         },
     }, {
+        .name = "xsr.cacheadrdis",
+        .translate = translate_xsr_mask,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            CACHEADRDIS,
+            XTENSA_OPTION_MPU,
+            0xff,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "xsr.cacheattr",
         .translate = translate_xsr,
         .test_ill = test_ill_sr,
@@ -5579,6 +5707,15 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "xsr.eraccess",
+        .translate = translate_xsr_mask,
+        .par = (const uint32_t[]){
+            ERACCESS,
+            0,
+            0xffff,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "xsr.exccause",
         .translate = translate_xsr,
         .test_ill = test_ill_sr,
@@ -5900,6 +6037,15 @@ static const XtensaOpcodeOps core_ops[] = {
         },
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "xsr.mpuenb",
+        .translate = translate_xsr_mpuenb,
+        .test_ill = test_ill_sr,
+        .par = (const uint32_t[]){
+            MPUENB,
+            XTENSA_OPTION_MPU,
+        },
+        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+    }, {
         .name = "xsr.prefctl",
         .translate = translate_xsr,
         .par = (const uint32_t[]){PREFCTL},
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 6/9] target/xtensa: implement DIWBUI.P opcode
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (4 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 5/9] target/xtensa: implement MPU option Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes Max Filippov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

This is a recent addition to the set of data cache opcodes.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h          |  1 +
 target/xtensa/overlay_tool.h |  1 +
 target/xtensa/translate.c    | 10 ++++++++++
 3 files changed, 12 insertions(+)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index d6e6bf6ca183..ba4ef2b6a729 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -466,6 +466,7 @@ struct XtensaConfig {
 
     unsigned icache_ways;
     unsigned dcache_ways;
+    unsigned dcache_line_bytes;
     uint32_t memctl_mask;
 
     XtensaMemory instrom;
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index b61c92539861..4925b21f0edf 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -425,6 +425,7 @@
 #define CACHE_SECTION \
     .icache_ways = XCHAL_ICACHE_WAYS, \
     .dcache_ways = XCHAL_DCACHE_WAYS, \
+    .dcache_line_bytes = XCHAL_DCACHE_LINESIZE, \
     .memctl_mask = \
         (XCHAL_ICACHE_SIZE ? MEMCTL_IUSEWAYS_MASK : 0) | \
         (XCHAL_DCACHE_SIZE ? \
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 782f2ec62099..24eb70d619d5 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -1620,6 +1620,12 @@ static void translate_depbits(DisasContext *dc, const OpcodeArg arg[],
                         arg[2].imm, arg[3].imm);
 }
 
+static void translate_diwbuip(DisasContext *dc, const OpcodeArg arg[],
+                              const uint32_t par[])
+{
+    tcg_gen_addi_i32(arg[0].out, arg[0].in, dc->config->dcache_line_bytes);
+}
+
 static bool test_ill_entry(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
@@ -3098,6 +3104,10 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "diwbui.p",
+        .translate = translate_diwbuip,
+        .op_flags = XTENSA_OP_PRIVILEGED,
+    }, {
         .name = "dpfl",
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (5 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 6/9] target/xtensa: implement DIWBUI.P opcode Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-15  6:46   ` Philippe Mathieu-Daudé
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 8/9] target/xtensa: update list of exception causes Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 9/9] target/xtensa: implement exclusive access option Max Filippov
  8 siblings, 1 reply; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Block prefetch option adds a bunch of non-privileged opcodes that may be
implemented as nops since QEMU doesn't model caches.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/translate.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 24eb70d619d5..356eb9948701 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -3078,6 +3078,9 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "dhi.b",
+        .translate = translate_nop,
+    }, {
         .name = "dhu",
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
@@ -3085,9 +3088,15 @@ static const XtensaOpcodeOps core_ops[] = {
         .name = "dhwb",
         .translate = translate_dcache,
     }, {
+        .name = "dhwb.b",
+        .translate = translate_nop,
+    }, {
         .name = "dhwbi",
         .translate = translate_dcache,
     }, {
+        .name = "dhwbi.b",
+        .translate = translate_nop,
+    }, {
         .name = "dii",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
@@ -3112,15 +3121,33 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "dpfm.b",
+        .translate = translate_nop,
+    }, {
+        .name = "dpfm.bf",
+        .translate = translate_nop,
+    }, {
         .name = "dpfr",
         .translate = translate_nop,
     }, {
+        .name = "dpfr.b",
+        .translate = translate_nop,
+    }, {
+        .name = "dpfr.bf",
+        .translate = translate_nop,
+    }, {
         .name = "dpfro",
         .translate = translate_nop,
     }, {
         .name = "dpfw",
         .translate = translate_nop,
     }, {
+        .name = "dpfw.b",
+        .translate = translate_nop,
+    }, {
+        .name = "dpfw.bf",
+        .translate = translate_nop,
+    }, {
         .name = "dpfwo",
         .translate = translate_nop,
     }, {
@@ -3628,6 +3655,21 @@ static const XtensaOpcodeOps core_ops[] = {
         .par = (const uint32_t[]){true},
         .op_flags = XTENSA_OP_PRIVILEGED,
     }, {
+        .name = "pfend.a",
+        .translate = translate_nop,
+    }, {
+        .name = "pfend.o",
+        .translate = translate_nop,
+    }, {
+        .name = "pfnxt.f",
+        .translate = translate_nop,
+    }, {
+        .name = "pfwait.a",
+        .translate = translate_nop,
+    }, {
+        .name = "pfwait.o",
+        .translate = translate_nop,
+    }, {
         .name = "pitlb",
         .translate = translate_ptlb,
         .par = (const uint32_t[]){false},
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 8/9] target/xtensa: update list of exception causes
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (6 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 9/9] target/xtensa: implement exclusive access option Max Filippov
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

Add XEA2 exception cause codes defined in recent Xtensa ISA releases.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index ba4ef2b6a729..8301923e4c4a 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -280,14 +280,15 @@ enum {
     LEVEL1_INTERRUPT_CAUSE,
     ALLOCA_CAUSE,
     INTEGER_DIVIDE_BY_ZERO_CAUSE,
-    PRIVILEGED_CAUSE = 8,
+    PC_VALUE_ERROR_CAUSE,
+    PRIVILEGED_CAUSE,
     LOAD_STORE_ALIGNMENT_CAUSE,
-
-    INSTR_PIF_DATA_ERROR_CAUSE = 12,
+    EXTERNAL_REG_PRIVILEGE_CAUSE,
+    EXCLUSIVE_ERROR_CAUSE,
+    INSTR_PIF_DATA_ERROR_CAUSE,
     LOAD_STORE_PIF_DATA_ERROR_CAUSE,
     INSTR_PIF_ADDR_ERROR_CAUSE,
     LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
-
     INST_TLB_MISS_CAUSE,
     INST_TLB_MULTI_HIT_CAUSE,
     INST_FETCH_PRIVILEGE_CAUSE,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH 9/9] target/xtensa: implement exclusive access option
  2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
                   ` (7 preceding siblings ...)
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 8/9] target/xtensa: update list of exception causes Max Filippov
@ 2019-05-14 20:44 ` Max Filippov
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2019-05-14 20:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Max Filippov

The Exclusive Instructions provide a general-purpose mechanism for
atomic updates of memory-based synchronization variables that can be
used for exclusion algorithms.

Use cmpxchg-based implementation that is sufficient for the typical use
of exclusive access in atomic operations.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target/xtensa/cpu.c               |   1 +
 target/xtensa/cpu.h               |   2 +
 target/xtensa/helper.h            |   1 +
 target/xtensa/op_helper.c         |  42 ++++++++++++++++
 target/xtensa/overlay_tool.h      |   8 ++-
 target/xtensa/translate.c         | 100 ++++++++++++++++++++++++++++++++++++++
 tests/tcg/xtensa/test_exclusive.S |  48 ++++++++++++++++++
 7 files changed, 200 insertions(+), 2 deletions(-)
 create mode 100644 tests/tcg/xtensa/test_exclusive.S

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 4215a1881ec7..54c834228a91 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -82,6 +82,7 @@ static void xtensa_cpu_reset(CPUState *s)
             XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15;
     env->sregs[CONFIGID0] = env->config->configid[0];
     env->sregs[CONFIGID1] = env->config->configid[1];
+    env->exclusive_addr = -1;
 
 #ifndef CONFIG_USER_ONLY
     reset_mmu(env);
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 8301923e4c4a..28a6fb4d796d 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -527,6 +527,8 @@ typedef struct CPUXtensaState {
     } fregs[16];
     float_status fp_status;
     uint32_t windowbase_next;
+    uint32_t exclusive_addr;
+    uint32_t exclusive_val;
 
 #ifndef CONFIG_USER_ONLY
     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index 9216bee57e9a..8532de0b35f5 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -24,6 +24,7 @@ DEF_HELPER_1(check_interrupts, void, env)
 DEF_HELPER_2(intset, void, env, i32)
 DEF_HELPER_2(intclear, void, env, i32)
 DEF_HELPER_3(check_atomctl, void, env, i32, i32)
+DEF_HELPER_4(check_exclusive, void, env, i32, i32, i32)
 DEF_HELPER_2(wsr_memctl, void, env, i32)
 
 DEF_HELPER_2(itlb_hit_test, void, env, i32)
diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c
index 04971b044fac..09f4962d008a 100644
--- a/target/xtensa/op_helper.c
+++ b/target/xtensa/op_helper.c
@@ -130,6 +130,48 @@ void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
     }
 }
 
+void HELPER(check_exclusive)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr,
+                             uint32_t is_write)
+{
+    uint32_t paddr, page_size, access;
+    uint32_t atomctl = env->sregs[ATOMCTL];
+    int rc = xtensa_get_physical_addr(env, true, vaddr, is_write,
+                                      xtensa_get_cring(env), &paddr,
+                                      &page_size, &access);
+
+    if (rc) {
+        HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
+    }
+
+    /* When data cache is not configured use ATOMCTL bypass field. */
+    if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
+        access = PAGE_CACHE_BYPASS;
+    }
+
+    switch (access & PAGE_CACHE_MASK) {
+    case PAGE_CACHE_WB:
+        atomctl >>= 2;
+        /* fall through */
+    case PAGE_CACHE_WT:
+        atomctl >>= 2;
+        /* fall through */
+    case PAGE_CACHE_BYPASS:
+        if ((atomctl & 0x3) == 0) {
+            HELPER(exception_cause_vaddr)(env, pc,
+                                          EXCLUSIVE_ERROR_CAUSE, vaddr);
+        }
+        break;
+
+    case PAGE_CACHE_ISOLATE:
+        HELPER(exception_cause_vaddr)(env, pc,
+                LOAD_STORE_ERROR_CAUSE, vaddr);
+        break;
+
+    default:
+        break;
+    }
+}
+
 void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v)
 {
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) {
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index 4925b21f0edf..f0cc33adfe05 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -76,6 +76,10 @@
 #define XCHAL_HAVE_MPU 0
 #endif
 
+#ifndef XCHAL_HAVE_EXCLUSIVE
+#define XCHAL_HAVE_EXCLUSIVE 0
+#endif
+
 #define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
 
 #define XTENSA_OPTIONS ( \
@@ -96,8 +100,8 @@
     XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \
     XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \
     XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \
-    XCHAL_OPTION(XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000, \
-        XTENSA_OPTION_ATOMCTL) | \
+    XCHAL_OPTION(((XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000) || \
+                  XCHAL_HAVE_EXCLUSIVE), XTENSA_OPTION_ATOMCTL) | \
     XCHAL_OPTION(XCHAL_HAVE_DEPBITS, XTENSA_OPTION_DEPBITS) | \
     /* Interrupts and exceptions */ \
     XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 356eb9948701..158a600b4293 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -87,6 +87,8 @@ static TCGv_i32 cpu_BR8[2];
 static TCGv_i32 cpu_SR[256];
 static TCGv_i32 cpu_UR[256];
 static TCGv_i32 cpu_windowbase_next;
+static TCGv_i32 cpu_exclusive_addr;
+static TCGv_i32 cpu_exclusive_val;
 
 static GHashTable *xtensa_regfile_table;
 
@@ -216,6 +218,14 @@ void xtensa_translate_init(void)
         tcg_global_mem_new_i32(cpu_env,
                                offsetof(CPUXtensaState, windowbase_next),
                                "windowbase_next");
+    cpu_exclusive_addr =
+        tcg_global_mem_new_i32(cpu_env,
+                               offsetof(CPUXtensaState, exclusive_addr),
+                               "exclusive_addr");
+    cpu_exclusive_val =
+        tcg_global_mem_new_i32(cpu_env,
+                               offsetof(CPUXtensaState, exclusive_val),
+                               "exclusive_val");
 }
 
 void **xtensa_get_regfile_by_name(const char *name)
@@ -1592,6 +1602,12 @@ static void translate_clrb_expstate(DisasContext *dc, const OpcodeArg arg[],
     tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0].imm));
 }
 
+static void translate_clrex(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+}
+
 static void translate_const16(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
@@ -1667,6 +1683,17 @@ static void translate_extui(DisasContext *dc, const OpcodeArg arg[],
     tcg_temp_free(tmp);
 }
 
+static void translate_getex(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+
+    tcg_gen_extract_i32(tmp, cpu_SR[ATOMCTL], 8, 1);
+    tcg_gen_deposit_i32(cpu_SR[ATOMCTL], cpu_SR[ATOMCTL], arg[0].in, 8, 1);
+    tcg_gen_mov_i32(arg[0].out, tmp);
+    tcg_temp_free(tmp);
+}
+
 static void translate_icache(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
@@ -1714,6 +1741,38 @@ static void translate_l32e(DisasContext *dc, const OpcodeArg arg[],
     tcg_temp_free(addr);
 }
 
+#ifdef CONFIG_USER_ONLY
+static void gen_check_exclusive(DisasContext *dc, TCGv_i32 addr, bool is_write)
+{
+}
+#else
+static void gen_check_exclusive(DisasContext *dc, TCGv_i32 addr, bool is_write)
+{
+    if (!option_enabled(dc, XTENSA_OPTION_MPU)) {
+        TCGv_i32 tpc = tcg_const_i32(dc->pc);
+        TCGv_i32 write = tcg_const_i32(is_write);
+
+        gen_helper_check_exclusive(cpu_env, tpc, addr, write);
+        tcg_temp_free(tpc);
+        tcg_temp_free(write);
+    }
+}
+#endif
+
+static void translate_l32ex(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+    TCGv_i32 addr = tcg_temp_new_i32();
+
+    tcg_gen_mov_i32(addr, arg[1].in);
+    gen_load_store_alignment(dc, 2, addr, true);
+    gen_check_exclusive(dc, addr, false);
+    tcg_gen_qemu_ld_i32(arg[0].out, addr, dc->ring, MO_TEUL);
+    tcg_gen_mov_i32(cpu_exclusive_addr, addr);
+    tcg_gen_mov_i32(cpu_exclusive_val, arg[0].out);
+    tcg_temp_free(addr);
+}
+
 static void translate_ldst(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
@@ -2269,6 +2328,33 @@ static void translate_s32e(DisasContext *dc, const OpcodeArg arg[],
     tcg_temp_free(addr);
 }
 
+static void translate_s32ex(DisasContext *dc, const OpcodeArg arg[],
+                            const uint32_t par[])
+{
+    TCGv_i32 prev = tcg_temp_new_i32();
+    TCGv_i32 addr = tcg_temp_local_new_i32();
+    TCGv_i32 res = tcg_temp_local_new_i32();
+    TCGLabel *label = gen_new_label();
+
+    tcg_gen_movi_i32(res, 0);
+    tcg_gen_mov_i32(addr, arg[1].in);
+    gen_load_store_alignment(dc, 2, addr, true);
+    tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, label);
+    gen_check_exclusive(dc, addr, true);
+    tcg_gen_atomic_cmpxchg_i32(prev, cpu_exclusive_addr, cpu_exclusive_val,
+                               arg[0].in, dc->cring, MO_TEUL);
+    tcg_gen_setcond_i32(TCG_COND_EQ, res, prev, cpu_exclusive_val);
+    tcg_gen_movcond_i32(TCG_COND_EQ, cpu_exclusive_val,
+                        prev, cpu_exclusive_val, prev, cpu_exclusive_val);
+    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+    gen_set_label(label);
+    tcg_gen_extract_i32(arg[0].out, cpu_SR[ATOMCTL], 8, 1);
+    tcg_gen_deposit_i32(cpu_SR[ATOMCTL], cpu_SR[ATOMCTL], res, 8, 1);
+    tcg_temp_free(prev);
+    tcg_temp_free(addr);
+    tcg_temp_free(res);
+}
+
 static void translate_salt(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
@@ -3068,6 +3154,9 @@ static const XtensaOpcodeOps core_ops[] = {
         .name = "clrb_expstate",
         .translate = translate_clrb_expstate,
     }, {
+        .name = "clrex",
+        .translate = translate_clrex,
+    }, {
         .name = "const16",
         .translate = translate_const16,
     }, {
@@ -3173,6 +3262,9 @@ static const XtensaOpcodeOps core_ops[] = {
         .name = "extw",
         .translate = translate_memw,
     }, {
+        .name = "getex",
+        .translate = translate_getex,
+    }, {
         .name = "hwwdtlba",
         .op_flags = XTENSA_OP_ILL,
     }, {
@@ -3244,6 +3336,10 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_l32e,
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_LOAD,
     }, {
+        .name = "l32ex",
+        .translate = translate_l32ex,
+        .op_flags = XTENSA_OP_LOAD,
+    }, {
         .name = (const char * const[]) {
             "l32i", "l32i.n", NULL,
         },
@@ -4557,6 +4653,10 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_s32e,
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_STORE,
     }, {
+        .name = "s32ex",
+        .translate = translate_s32ex,
+        .op_flags = XTENSA_OP_LOAD | XTENSA_OP_STORE,
+    }, {
         .name = (const char * const[]) {
             "s32i", "s32i.n", "s32nb", NULL,
         },
diff --git a/tests/tcg/xtensa/test_exclusive.S b/tests/tcg/xtensa/test_exclusive.S
new file mode 100644
index 000000000000..7757a552ea00
--- /dev/null
+++ b/tests/tcg/xtensa/test_exclusive.S
@@ -0,0 +1,48 @@
+#include "macros.inc"
+
+test_suite exclusive
+
+#if XCHAL_HAVE_EXCLUSIVE
+
+test exclusive_nowrite
+    movi    a2, 0x29
+    wsr     a2, atomctl
+    clrex
+    movi    a2, 1f
+    movi    a3, 1
+    s32ex   a3, a2
+    getex   a3
+    assert  eqi, a3, 0
+    l32i    a3, a2, 0
+    assert  eqi, a3, 3
+
+.data
+.align 4
+1:
+    .word   3
+.text
+test_end
+
+test exclusive_write
+    movi    a2, 0x29
+    wsr     a2, atomctl
+    movi    a2, 1f
+    l32ex   a3, a2
+    assert  eqi, a3, 3
+    movi    a3, 2
+    s32ex   a3, a2
+    getex   a3
+    assert  eqi, a3, 1
+    l32i    a3, a2, 0
+    assert  eqi, a3, 2
+
+.data
+.align 4
+1:
+    .word   3
+.text
+test_end
+
+#endif
+
+test_suite_end
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes
  2019-05-14 20:44 ` [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes Max Filippov
@ 2019-05-15  6:46   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-05-15  6:46 UTC (permalink / raw)
  To: Max Filippov, qemu-devel

On 5/14/19 10:44 PM, Max Filippov wrote:
> Block prefetch option adds a bunch of non-privileged opcodes that may be
> implemented as nops since QEMU doesn't model caches.
> 
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  target/xtensa/translate.c | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
> index 24eb70d619d5..356eb9948701 100644
> --- a/target/xtensa/translate.c
> +++ b/target/xtensa/translate.c
> @@ -3078,6 +3078,9 @@ static const XtensaOpcodeOps core_ops[] = {
>          .translate = translate_dcache,
>          .op_flags = XTENSA_OP_PRIVILEGED,
>      }, {
> +        .name = "dhi.b",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dhu",
>          .translate = translate_dcache,
>          .op_flags = XTENSA_OP_PRIVILEGED,
> @@ -3085,9 +3088,15 @@ static const XtensaOpcodeOps core_ops[] = {
>          .name = "dhwb",
>          .translate = translate_dcache,
>      }, {
> +        .name = "dhwb.b",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dhwbi",
>          .translate = translate_dcache,
>      }, {
> +        .name = "dhwbi.b",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dii",
>          .translate = translate_nop,
>          .op_flags = XTENSA_OP_PRIVILEGED,
> @@ -3112,15 +3121,33 @@ static const XtensaOpcodeOps core_ops[] = {
>          .translate = translate_dcache,
>          .op_flags = XTENSA_OP_PRIVILEGED,
>      }, {
> +        .name = "dpfm.b",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "dpfm.bf",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dpfr",
>          .translate = translate_nop,
>      }, {
> +        .name = "dpfr.b",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "dpfr.bf",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dpfro",
>          .translate = translate_nop,
>      }, {
>          .name = "dpfw",
>          .translate = translate_nop,
>      }, {
> +        .name = "dpfw.b",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "dpfw.bf",
> +        .translate = translate_nop,
> +    }, {
>          .name = "dpfwo",
>          .translate = translate_nop,
>      }, {
> @@ -3628,6 +3655,21 @@ static const XtensaOpcodeOps core_ops[] = {
>          .par = (const uint32_t[]){true},
>          .op_flags = XTENSA_OP_PRIVILEGED,
>      }, {
> +        .name = "pfend.a",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "pfend.o",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "pfnxt.f",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "pfwait.a",
> +        .translate = translate_nop,
> +    }, {
> +        .name = "pfwait.o",
> +        .translate = translate_nop,
> +    }, {
>          .name = "pitlb",
>          .translate = translate_ptlb,
>          .par = (const uint32_t[]){false},
> 

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-05-15  6:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-14 20:44 [Qemu-devel] [PATCH 0/9] target/xtensa: implement options for modern cores Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 1/9] target/xtensa: get rid of centralized SR properties Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 2/9] target/xtensa: make internal MMU functions static Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 3/9] target/xtensa: define IDMA and gather/scatter IRQ types Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 4/9] target/xtensa: add parity/ECC option SRs Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 5/9] target/xtensa: implement MPU option Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 6/9] target/xtensa: implement DIWBUI.P opcode Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 7/9] target/xtensa: implement block prefetch option opcodes Max Filippov
2019-05-15  6:46   ` Philippe Mathieu-Daudé
2019-05-14 20:44 ` [Qemu-devel] [PATCH 8/9] target/xtensa: update list of exception causes Max Filippov
2019-05-14 20:44 ` [Qemu-devel] [PATCH 9/9] target/xtensa: implement exclusive access option Max Filippov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.