summary refs log tree commit diff stats
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/arm/arm-powerctl.c56
-rw-r--r--target/arm/arm-powerctl.h16
-rw-r--r--target/arm/cpu.c34
-rw-r--r--target/arm/cpu.h138
-rw-r--r--target/arm/cpu64.c8
-rw-r--r--target/arm/helper-a64.c30
-rw-r--r--target/arm/helper-a64.h3
-rw-r--r--target/arm/helper.c90
-rw-r--r--target/arm/helper.h17
-rw-r--r--target/arm/internals.h15
-rw-r--r--target/arm/kvm.c10
-rw-r--r--target/arm/kvm32.c23
-rw-r--r--target/arm/kvm64.c2
-rw-r--r--target/arm/kvm_arm.h13
-rw-r--r--target/arm/machine.c2
-rw-r--r--target/arm/op_helper.c47
-rw-r--r--target/arm/translate-a64.c521
-rw-r--r--target/arm/translate.c215
-rw-r--r--target/arm/translate.h34
-rw-r--r--target/arm/vec_helper.c148
-rw-r--r--target/arm/vfp_helper.c96
-rw-r--r--target/mips/translate.c43
-rw-r--r--target/ppc/cpu-qom.h5
-rw-r--r--target/ppc/cpu.h33
-rw-r--r--target/ppc/excp_helper.c164
-rw-r--r--target/ppc/helper.h1
-rw-r--r--target/ppc/helper_regs.h27
-rw-r--r--target/ppc/misc_helper.c15
-rw-r--r--target/ppc/mmu-book3s-v3.c29
-rw-r--r--target/ppc/mmu-book3s-v3.h78
-rw-r--r--target/ppc/mmu-hash32.c6
-rw-r--r--target/ppc/mmu-hash64.c39
-rw-r--r--target/ppc/mmu-hash64.h22
-rw-r--r--target/ppc/mmu-radix64.c95
-rw-r--r--target/ppc/mmu-radix64.h4
-rw-r--r--target/ppc/mmu_helper.c9
-rw-r--r--target/ppc/translate.c28
-rw-r--r--target/ppc/translate_init.inc.c41
-rw-r--r--target/s390x/cc_helper.c8
-rw-r--r--target/s390x/excp_helper.c46
-rw-r--r--target/s390x/fpu_helper.c541
-rw-r--r--target/s390x/gen-features.c5
-rw-r--r--target/s390x/helper.c40
-rw-r--r--target/s390x/helper.h9
-rw-r--r--target/s390x/insn-data.def16
-rw-r--r--target/s390x/insn-format.def2
-rw-r--r--target/s390x/internal.h14
-rw-r--r--target/s390x/translate.c409
-rw-r--r--target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c1322
-rw-r--r--target/xtensa/cpu.h40
-rw-r--r--target/xtensa/helper.c94
-rw-r--r--target/xtensa/helper.h5
-rwxr-xr-xtarget/xtensa/import_core.sh2
-rw-r--r--target/xtensa/overlay_tool.h1
-rw-r--r--target/xtensa/translate.c2114
-rw-r--r--target/xtensa/win_helper.c22
56 files changed, 4297 insertions, 2550 deletions
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index f9de5164e5..f77a950db6 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -228,6 +228,62 @@ int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id,
     return QEMU_ARM_POWERCTL_RET_SUCCESS;
 }
 
+static void arm_set_cpu_on_and_reset_async_work(CPUState *target_cpu_state,
+                                                run_on_cpu_data data)
+{
+    ARMCPU *target_cpu = ARM_CPU(target_cpu_state);
+
+    /* Initialize the cpu we are turning on */
+    cpu_reset(target_cpu_state);
+    target_cpu_state->halted = 0;
+
+    /* Finally set the power status */
+    assert(qemu_mutex_iothread_locked());
+    target_cpu->power_state = PSCI_ON;
+}
+
+int arm_set_cpu_on_and_reset(uint64_t cpuid)
+{
+    CPUState *target_cpu_state;
+    ARMCPU *target_cpu;
+
+    assert(qemu_mutex_iothread_locked());
+
+    /* Retrieve the cpu we are powering up */
+    target_cpu_state = arm_get_cpu_by_id(cpuid);
+    if (!target_cpu_state) {
+        /* The cpu was not found */
+        return QEMU_ARM_POWERCTL_INVALID_PARAM;
+    }
+
+    target_cpu = ARM_CPU(target_cpu_state);
+    if (target_cpu->power_state == PSCI_ON) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "[ARM]%s: CPU %" PRId64 " is already on\n",
+                      __func__, cpuid);
+        return QEMU_ARM_POWERCTL_ALREADY_ON;
+    }
+
+    /*
+     * If another CPU has powered the target on we are in the state
+     * ON_PENDING and additional attempts to power on the CPU should
+     * fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI
+     * spec)
+     */
+    if (target_cpu->power_state == PSCI_ON_PENDING) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "[ARM]%s: CPU %" PRId64 " is already powering on\n",
+                      __func__, cpuid);
+        return QEMU_ARM_POWERCTL_ON_PENDING;
+    }
+
+    async_run_on_cpu(target_cpu_state, arm_set_cpu_on_and_reset_async_work,
+                     RUN_ON_CPU_NULL);
+
+    /* We are good to go */
+    return QEMU_ARM_POWERCTL_RET_SUCCESS;
+}
+
 static void arm_set_cpu_off_async_work(CPUState *target_cpu_state,
                                        run_on_cpu_data data)
 {
diff --git a/target/arm/arm-powerctl.h b/target/arm/arm-powerctl.h
index 04353923c0..37c8a04f0a 100644
--- a/target/arm/arm-powerctl.h
+++ b/target/arm/arm-powerctl.h
@@ -74,4 +74,20 @@ int arm_set_cpu_off(uint64_t cpuid);
  */
 int arm_reset_cpu(uint64_t cpuid);
 
+/*
+ * arm_set_cpu_on_and_reset:
+ * @cpuid: the id of the CPU we want to star
+ *
+ * Start the cpu designated by @cpuid and put it through its normal
+ * CPU reset process. The CPU will start in the way it is architected
+ * to start after a power-on reset.
+ *
+ * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success.
+ * QEMU_ARM_POWERCTL_INVALID_PARAM if there is no CPU with that ID.
+ * QEMU_ARM_POWERCTL_ALREADY_ON if the CPU is already on.
+ * QEMU_ARM_POWERCTL_ON_PENDING if the CPU is already partway through
+ * powering on.
+ */
+int arm_set_cpu_on_and_reset(uint64_t cpuid);
+
 #endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8ea6569088..96f0ff0ec7 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -22,6 +22,7 @@
 #include "target/arm/idau.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "cpu.h"
 #include "internals.h"
 #include "qemu-common.h"
@@ -771,9 +772,21 @@ static Property arm_cpu_pmsav7_dregion_property =
                                            pmsav7_dregion,
                                            qdev_prop_uint32, uint32_t);
 
-/* M profile: initial value of the Secure VTOR */
-static Property arm_cpu_initsvtor_property =
-            DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
+static void arm_get_init_svtor(Object *obj, Visitor *v, const char *name,
+                               void *opaque, Error **errp)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
+
+static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
+                               void *opaque, Error **errp)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
 
 void arm_cpu_post_init(Object *obj)
 {
@@ -845,8 +858,14 @@ void arm_cpu_post_init(Object *obj)
                                  qdev_prop_allow_set_link_before_realize,
                                  OBJ_PROP_LINK_STRONG,
                                  &error_abort);
-        qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
-                                 &error_abort);
+        /*
+         * M profile: initial value of the Secure VTOR. We can't just use
+         * a simple DEFINE_PROP_UINT32 for this because we want to permit
+         * the property to be set after realize.
+         */
+        object_property_add(obj, "init-svtor", "uint32",
+                            arm_get_init_svtor, arm_set_init_svtor,
+                            NULL, NULL, &error_abort);
     }
 
     qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
@@ -995,7 +1014,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     }
     if (arm_feature(env, ARM_FEATURE_VFP4)) {
         set_feature(env, ARM_FEATURE_VFP3);
-        set_feature(env, ARM_FEATURE_VFP_FP16);
     }
     if (arm_feature(env, ARM_FEATURE_VFP3)) {
         set_feature(env, ARM_FEATURE_VFP);
@@ -1656,7 +1674,6 @@ static void cortex_a9_initfn(Object *obj)
     cpu->dtb_compatible = "arm,cortex-a9";
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_VFP3);
-    set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
     set_feature(&cpu->env, ARM_FEATURE_NEON);
     set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
     set_feature(&cpu->env, ARM_FEATURE_EL3);
@@ -2003,6 +2020,9 @@ static void arm_max_initfn(Object *obj)
             t = cpu->isar.id_isar6;
             t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
             t = FIELD_DP32(t, ID_ISAR6, DP, 1);
+            t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
+            t = FIELD_DP32(t, ID_ISAR6, SB, 1);
+            t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
             cpu->isar.id_isar6 = t;
 
             t = cpu->id_mmfr4;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1eea1a408b..5f23c62132 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1060,7 +1060,8 @@ void pmu_init(ARMCPU *cpu);
 #define SCTLR_R       (1U << 9) /* up to v6; RAZ in v7 */
 #define SCTLR_UMA     (1U << 9) /* v8 onward, AArch64 only */
 #define SCTLR_F       (1U << 10) /* up to v6 */
-#define SCTLR_SW      (1U << 10) /* v7, RES0 in v8 */
+#define SCTLR_SW      (1U << 10) /* v7 */
+#define SCTLR_EnRCTX  (1U << 10) /* in v8.0-PredInv */
 #define SCTLR_Z       (1U << 11) /* in v7, RES1 in v8 */
 #define SCTLR_EOS     (1U << 11) /* v8.5-ExS */
 #define SCTLR_I       (1U << 12)
@@ -1730,6 +1731,27 @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
 FIELD(ID_DFR0, PERFMON, 24, 4)
 FIELD(ID_DFR0, TRACEFILT, 28, 4)
 
+FIELD(MVFR0, SIMDREG, 0, 4)
+FIELD(MVFR0, FPSP, 4, 4)
+FIELD(MVFR0, FPDP, 8, 4)
+FIELD(MVFR0, FPTRAP, 12, 4)
+FIELD(MVFR0, FPDIVIDE, 16, 4)
+FIELD(MVFR0, FPSQRT, 20, 4)
+FIELD(MVFR0, FPSHVEC, 24, 4)
+FIELD(MVFR0, FPROUND, 28, 4)
+
+FIELD(MVFR1, FPFTZ, 0, 4)
+FIELD(MVFR1, FPDNAN, 4, 4)
+FIELD(MVFR1, SIMDLS, 8, 4)
+FIELD(MVFR1, SIMDINT, 12, 4)
+FIELD(MVFR1, SIMDSP, 16, 4)
+FIELD(MVFR1, SIMDHP, 20, 4)
+FIELD(MVFR1, FPHP, 24, 4)
+FIELD(MVFR1, SIMDFMAC, 28, 4)
+
+FIELD(MVFR2, SIMDMISC, 0, 4)
+FIELD(MVFR2, FPMISC, 4, 4)
+
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
 
 /* If adding a feature bit which corresponds to a Linux ELF
@@ -1747,7 +1769,6 @@ enum arm_features {
     ARM_FEATURE_THUMB2,
     ARM_FEATURE_PMSA,   /* no MMU; may have Memory Protection Unit */
     ARM_FEATURE_VFP3,
-    ARM_FEATURE_VFP_FP16,
     ARM_FEATURE_NEON,
     ARM_FEATURE_M, /* Microcontroller profile.  */
     ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling.  */
@@ -2538,25 +2559,18 @@ bool write_list_to_cpustate(ARMCPU *cpu);
 /**
  * write_cpustate_to_list:
  * @cpu: ARMCPU
- * @kvm_sync: true if this is for syncing back to KVM
  *
  * For each register listed in the ARMCPU cpreg_indexes list, write
  * its value from the ARMCPUState structure into the cpreg_values list.
  * This is used to copy info from TCG's working data structures into
  * KVM or for outbound migration.
  *
- * @kvm_sync is true if we are doing this in order to sync the
- * register state back to KVM. In this case we will only update
- * values in the list if the previous list->cpustate sync actually
- * successfully wrote the CPU state. Otherwise we will keep the value
- * that is in the list.
- *
  * Returns: true if all register values were read correctly,
  * false if some register was unknown or could not be read.
  * Note that we do not stop early on failure -- we will attempt
  * reading all registers in the list.
  */
-bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
+bool write_cpustate_to_list(ARMCPU *cpu);
 
 #define ARM_CPUID_TI915T      0x54029152
 #define ARM_CPUID_TI925T      0x54029252
@@ -3029,11 +3043,20 @@ static inline bool arm_sctlr_b(CPUARMState *env)
         (env->cp15.sctlr_el[1] & SCTLR_B) != 0;
 }
 
+static inline uint64_t arm_sctlr(CPUARMState *env, int el)
+{
+    if (el == 0) {
+        /* FIXME: ARMv8.1-VHE S2 translation regime.  */
+        return env->cp15.sctlr_el[1];
+    } else {
+        return env->cp15.sctlr_el[el];
+    }
+}
+
+
 /* Return true if the processor is in big-endian mode. */
 static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
 {
-    int cur_el;
-
     /* In 32bit endianness is determined by looking at CPSR's E bit */
     if (!is_a64(env)) {
         return
@@ -3052,15 +3075,12 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
             arm_sctlr_b(env) ||
 #endif
                 ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
-    }
-
-    cur_el = arm_current_el(env);
+    } else {
+        int cur_el = arm_current_el(env);
+        uint64_t sctlr = arm_sctlr(env, cur_el);
 
-    if (cur_el == 0) {
-        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
+        return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0;
     }
-
-    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
 }
 
 #include "exec/cpu-all.h"
@@ -3283,6 +3303,21 @@ static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
     return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
 }
 
+static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
+{
+    return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
+}
+
+static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
+{
+    return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
+}
+
+static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
+{
+    return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
+}
+
 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
 {
     /*
@@ -3294,6 +3329,41 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
 }
 
 /*
+ * We always set the FP and SIMD FP16 fields to indicate identical
+ * levels of support (assuming SIMD is implemented at all), so
+ * we only need one set of accessors.
+ */
+static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0;
+}
+
+static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1;
+}
+
+static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1;
+}
+
+static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2;
+}
+
+static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3;
+}
+
+static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
+}
+
+/*
  * 64-bit feature tests via id registers.
  */
 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
@@ -3356,6 +3426,21 @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
 }
 
+static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
+}
+
+static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
+}
+
+static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
+}
+
 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
@@ -3381,6 +3466,21 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
              FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
 }
 
+static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
+}
+
+static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
+}
+
+static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
+}
+
 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
 {
     /* We always set the AdvSIMD and FP fields identically wrt FP16.  */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 69e4134f79..228906f267 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -308,6 +308,8 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
+        t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
+        t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
         cpu->isar.id_aa64isar0 = t;
 
         t = cpu->isar.id_aa64isar1;
@@ -317,6 +319,9 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
         t = FIELD_DP64(t, ID_AA64ISAR1, GPA, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
+        t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
+        t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
+        t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
         cpu->isar.id_aa64isar1 = t;
 
         t = cpu->isar.id_aa64pfr0;
@@ -347,6 +352,9 @@ static void aarch64_max_initfn(Object *obj)
         u = cpu->isar.id_isar6;
         u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
         u = FIELD_DP32(u, ID_ISAR6, DP, 1);
+        u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
+        u = FIELD_DP32(u, ID_ISAR6, SB, 1);
+        u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
         cpu->isar.id_isar6 = u;
 
         /*
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 70850e564d..796ef34b55 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -61,6 +61,36 @@ uint64_t HELPER(rbit64)(uint64_t x)
     return revbit64(x);
 }
 
+void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
+{
+    update_spsel(env, imm);
+}
+
+static void daif_check(CPUARMState *env, uint32_t op,
+                       uint32_t imm, uintptr_t ra)
+{
+    /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set.  */
+    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
+        raise_exception_ra(env, EXCP_UDEF,
+                           syn_aa64_sysregtrap(0, extract32(op, 0, 3),
+                                               extract32(op, 3, 3), 4,
+                                               imm, 0x1f, 0),
+                           exception_target_el(env), ra);
+    }
+}
+
+void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
+{
+    daif_check(env, 0x1e, imm, GETPC());
+    env->daif |= (imm << 6) & PSTATE_DAIF;
+}
+
+void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
+{
+    daif_check(env, 0x1f, imm, GETPC());
+    env->daif &= ~((imm << 6) & PSTATE_DAIF);
+}
+
 /* Convert a softfloat float_relation_ (as returned by
  * the float*_compare functions) to the correct ARM
  * NZCV flag state.
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index aff8d6c9f3..a915c1247f 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -19,6 +19,9 @@
 DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
 DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_2(msr_i_spsel, void, env, i32)
+DEF_HELPER_2(msr_i_daifset, void, env, i32)
+DEF_HELPER_2(msr_i_daifclear, void, env, i32)
 DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
 DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
 DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index fbaa801cea..2607d39ad1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -265,7 +265,7 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
     return true;
 }
 
-bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
+bool write_cpustate_to_list(ARMCPU *cpu)
 {
     /* Write the coprocessor state from cpu->env to the (index,value) list. */
     int i;
@@ -274,7 +274,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
     for (i = 0; i < cpu->cpreg_array_len; i++) {
         uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
         const ARMCPRegInfo *ri;
-        uint64_t newval;
 
         ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
         if (!ri) {
@@ -284,29 +283,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
         if (ri->type & ARM_CP_NO_RAW) {
             continue;
         }
-
-        newval = read_raw_cp_reg(&cpu->env, ri);
-        if (kvm_sync) {
-            /*
-             * Only sync if the previous list->cpustate sync succeeded.
-             * Rather than tracking the success/failure state for every
-             * item in the list, we just recheck "does the raw write we must
-             * have made in write_list_to_cpustate() read back OK" here.
-             */
-            uint64_t oldval = cpu->cpreg_values[i];
-
-            if (oldval == newval) {
-                continue;
-            }
-
-            write_raw_cp_reg(&cpu->env, ri, oldval);
-            if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
-                continue;
-            }
-
-            write_raw_cp_reg(&cpu->env, ri, newval);
-        }
-        cpu->cpreg_values[i] = newval;
+        cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
     }
     return ok;
 }
@@ -5742,6 +5719,50 @@ static const ARMCPRegInfo pauth_reginfo[] = {
 };
 #endif
 
+static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
+                                     bool isread)
+{
+    int el = arm_current_el(env);
+
+    if (el == 0) {
+        uint64_t sctlr = arm_sctlr(env, el);
+        if (!(sctlr & SCTLR_EnRCTX)) {
+            return CP_ACCESS_TRAP;
+        }
+    } else if (el == 1) {
+        uint64_t hcr = arm_hcr_el2_eff(env);
+        if (hcr & HCR_NV) {
+            return CP_ACCESS_TRAP_EL2;
+        }
+    }
+    return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo predinv_reginfo[] = {
+    { .name = "CFP_RCTX", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 4,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    { .name = "DVP_RCTX", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 5,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    { .name = "CPP_RCTX", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 7,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    /*
+     * Note the AArch32 opcodes have a different OPC1.
+     */
+    { .name = "CFPRCTX", .state = ARM_CP_STATE_AA32,
+      .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 4,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    { .name = "DVPRCTX", .state = ARM_CP_STATE_AA32,
+      .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 5,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    { .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
+      .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
+      .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+    REGINFO_SENTINEL
+};
+
 void register_cp_regs_for_features(ARMCPU *cpu)
 {
     /* Register all the coprocessor registers based on feature bits */
@@ -6641,6 +6662,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, pauth_reginfo);
     }
 #endif
+
+    /*
+     * While all v8.0 cpus support aarch64, QEMU does have configurations
+     * that do not set ID_AA64ISAR1, e.g. user-only qemu-arm -cpu max,
+     * which will set ID_ISAR6.
+     */
+    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
+        ? cpu_isar_feature(aa64_predinv, cpu)
+        : cpu_isar_feature(aa32_predinv, cpu)) {
+        define_arm_cp_regs(cpu, predinv_reginfo);
+    }
 }
 
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
@@ -12877,12 +12909,8 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
             flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
         }
 
-        if (current_el == 0) {
-            /* FIXME: ARMv8.1-VHE S2 translation regime.  */
-            sctlr = env->cp15.sctlr_el[1];
-        } else {
-            sctlr = env->cp15.sctlr_el[current_el];
-        }
+        sctlr = arm_sctlr(env, current_el);
+
         if (cpu_isar_feature(aa64_pauth, cpu)) {
             /*
              * In order to save space in flags, we record only whether
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 747cb64d29..a09566f795 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -77,9 +77,6 @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr)
 DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
 DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
 
-DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
-DEF_HELPER_1(clear_pstate_ss, void, env)
-
 DEF_HELPER_2(get_r13_banked, i32, env, i32)
 DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
 
@@ -677,6 +674,20 @@ DEF_HELPER_FLAGS_5(gvec_sqsub_s, TCG_CALL_NO_RWG,
 DEF_HELPER_FLAGS_5(gvec_sqsub_d, TCG_CALL_NO_RWG,
                    void, ptr, ptr, ptr, ptr, i32)
 
+DEF_HELPER_FLAGS_5(gvec_fmlal_a32, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_a64, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a32, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a64, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_2(frint32_s, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
+DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
+
 #ifdef TARGET_AARCH64
 #include "helper-a64.h"
 #include "helper-sve.h"
diff --git a/target/arm/internals.h b/target/arm/internals.h
index a4bd1becb7..587a1ddf58 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -968,4 +968,19 @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
 ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
                                    ARMMMUIdx mmu_idx, bool data);
 
+static inline int exception_target_el(CPUARMState *env)
+{
+    int target_el = MAX(1, arm_current_el(env));
+
+    /*
+     * No such thing as secure EL1 if EL3 is aarch32,
+     * so update the target EL to EL3 in this case.
+     */
+    if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
+        target_el = 3;
+    }
+
+    return target_el;
+}
+
 #endif
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index e00ccf9c98..79a79f0190 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -18,6 +18,7 @@
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
 #include "kvm_arm.h"
 #include "cpu.h"
 #include "trace.h"
@@ -162,6 +163,15 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
     env->features = arm_host_cpu_features.features;
 }
 
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+{
+    KVMState *s = KVM_STATE(ms->accelerator);
+    int ret;
+
+    ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
+    return ret > 0 ? ret : 40;
+}
+
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
     /* For ARM interrupt delivery is always asynchronous,
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index a75e04cc8f..50327989dc 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -125,9 +125,6 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     if (extract32(id_pfr0, 12, 4) == 1) {
         set_feature(&features, ARM_FEATURE_THUMB2EE);
     }
-    if (extract32(ahcf->isar.mvfr1, 20, 4) == 1) {
-        set_feature(&features, ARM_FEATURE_VFP_FP16);
-    }
     if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
         set_feature(&features, ARM_FEATURE_NEON);
     }
@@ -387,8 +384,24 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
-    write_cpustate_to_list(cpu, true);
-
+    /* Note that we do not call write_cpustate_to_list()
+     * here, so we are only writing the tuple list back to
+     * KVM. This is safe because nothing can change the
+     * CPUARMState cp15 fields (in particular gdb accesses cannot)
+     * and so there are no changes to sync. In fact syncing would
+     * be wrong at this point: for a constant register where TCG and
+     * KVM disagree about its value, the preceding write_list_to_cpustate()
+     * would not have had any effect on the CPUARMState value (since the
+     * register is read-only), and a write_cpustate_to_list() here would
+     * then try to write the TCG value back into KVM -- this would either
+     * fail or incorrectly change the value the guest sees.
+     *
+     * If we ever want to allow the user to modify cp15 registers via
+     * the gdb stub, we would need to be more clever here (for instance
+     * tracking the set of registers kvm_arch_get_registers() successfully
+     * managed to update the CPUARMState with, and only allowing those
+     * to be written back up into the kernel).
+     */
     if (!write_list_to_kvmstate(cpu, level)) {
         return EINVAL;
     }
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index e3ba149248..089af9c5f0 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -838,8 +838,6 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
-    write_cpustate_to_list(cpu, true);
-
     if (!write_list_to_kvmstate(cpu, level)) {
         return EINVAL;
     }
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 6393455b1d..2a07333c61 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -208,6 +208,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
 void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
 
 /**
+ * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
+ * IPA address space supported by KVM
+ *
+ * @ms: Machine state handle
+ */
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
+
+/**
  * kvm_arm_sync_mpstate_to_kvm
  * @cpu: ARMCPU
  *
@@ -239,6 +247,11 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
     cpu->host_cpu_probe_failed = true;
 }
 
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+{
+    return -ENOENT;
+}
+
 static inline int kvm_arm_vgic_probe(void)
 {
     return 0;
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 124192bfc2..b292549614 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -630,7 +630,7 @@ static int cpu_pre_save(void *opaque)
             abort();
         }
     } else {
-        if (!write_cpustate_to_list(cpu, false)) {
+        if (!write_cpustate_to_list(cpu)) {
             /* This should never fail. */
             abort();
         }
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index c998eadfaa..8698b4dc83 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -68,20 +68,6 @@ void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
     cpu_loop_exit_restore(cs, ra);
 }
 
-static int exception_target_el(CPUARMState *env)
-{
-    int target_el = MAX(1, arm_current_el(env));
-
-    /* No such thing as secure EL1 if EL3 is aarch32, so update the target EL
-     * to EL3 in this case.
-     */
-    if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
-        target_el = 3;
-    }
-
-    return target_el;
-}
-
 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
                           uint32_t maxindex)
 {
@@ -875,39 +861,6 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
     return res;
 }
 
-void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
-{
-    /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set.
-     * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
-     * to catch that case at translate time.
-     */
-    if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
-        uint32_t syndrome = syn_aa64_sysregtrap(0, extract32(op, 0, 3),
-                                                extract32(op, 3, 3), 4,
-                                                imm, 0x1f, 0);
-        raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
-    }
-
-    switch (op) {
-    case 0x05: /* SPSel */
-        update_spsel(env, imm);
-        break;
-    case 0x1e: /* DAIFSet */
-        env->daif |= (imm << 6) & PSTATE_DAIF;
-        break;
-    case 0x1f: /* DAIFClear */
-        env->daif &= ~((imm << 6) & PSTATE_DAIF);
-        break;
-    default:
-        g_assert_not_reached();
-    }
-}
-
-void HELPER(clear_pstate_ss)(CPUARMState *env)
-{
-    env->pstate &= ~PSTATE_SS;
-}
-
 void HELPER(pre_hvc)(CPUARMState *env)
 {
     ARMCPU *cpu = arm_env_get_cpu(env);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c56e878787..1959046343 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -421,17 +421,6 @@ static void gen_exception_bkpt_insn(DisasContext *s, int offset,
     s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_ss_advance(DisasContext *s)
-{
-    /* If the singlestep state is Active-not-pending, advance to
-     * Active-pending.
-     */
-    if (s->ss_active) {
-        s->pstate_ss = 0;
-        gen_helper_clear_pstate_ss(cpu_env);
-    }
-}
-
 static void gen_step_complete_exception(DisasContext *s)
 {
     /* We just completed step of an insn. Move from Active-not-pending
@@ -1637,39 +1626,128 @@ static void handle_sync(DisasContext *s, uint32_t insn,
         reset_btype(s);
         gen_goto_tb(s, 0, s->pc);
         return;
+
+    case 7: /* SB */
+        if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
+            goto do_unallocated;
+        }
+        /*
+         * TODO: There is no speculation barrier opcode for TCG;
+         * MB and end the TB instead.
+         */
+        tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+        gen_goto_tb(s, 0, s->pc);
+        return;
+
     default:
+    do_unallocated:
         unallocated_encoding(s);
         return;
     }
 }
 
+static void gen_xaflag(void)
+{
+    TCGv_i32 z = tcg_temp_new_i32();
+
+    tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
+
+    /*
+     * (!C & !Z) << 31
+     * (!(C | Z)) << 31
+     * ~((C | Z) << 31)
+     * ~-(C | Z)
+     * (C | Z) - 1
+     */
+    tcg_gen_or_i32(cpu_NF, cpu_CF, z);
+    tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
+
+    /* !(Z & C) */
+    tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
+    tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
+
+    /* (!C & Z) << 31 -> -(Z & ~C) */
+    tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
+    tcg_gen_neg_i32(cpu_VF, cpu_VF);
+
+    /* C | Z */
+    tcg_gen_or_i32(cpu_CF, cpu_CF, z);
+
+    tcg_temp_free_i32(z);
+}
+
+static void gen_axflag(void)
+{
+    tcg_gen_sari_i32(cpu_VF, cpu_VF, 31);         /* V ? -1 : 0 */
+    tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF);     /* C & !V */
+
+    /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
+    tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
+
+    tcg_gen_movi_i32(cpu_NF, 0);
+    tcg_gen_movi_i32(cpu_VF, 0);
+}
+
 /* MSR (immediate) - move immediate to processor state field */
 static void handle_msr_i(DisasContext *s, uint32_t insn,
                          unsigned int op1, unsigned int op2, unsigned int crm)
 {
+    TCGv_i32 t1;
     int op = op1 << 3 | op2;
+
+    /* End the TB by default, chaining is ok.  */
+    s->base.is_jmp = DISAS_TOO_MANY;
+
     switch (op) {
+    case 0x00: /* CFINV */
+        if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+            goto do_unallocated;
+        }
+        tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
+        s->base.is_jmp = DISAS_NEXT;
+        break;
+
+    case 0x01: /* XAFlag */
+        if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+            goto do_unallocated;
+        }
+        gen_xaflag();
+        s->base.is_jmp = DISAS_NEXT;
+        break;
+
+    case 0x02: /* AXFlag */
+        if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+            goto do_unallocated;
+        }
+        gen_axflag();
+        s->base.is_jmp = DISAS_NEXT;
+        break;
+
     case 0x05: /* SPSel */
         if (s->current_el == 0) {
-            unallocated_encoding(s);
-            return;
+            goto do_unallocated;
         }
-        /* fall through */
+        t1 = tcg_const_i32(crm & PSTATE_SP);
+        gen_helper_msr_i_spsel(cpu_env, t1);
+        tcg_temp_free_i32(t1);
+        break;
+
     case 0x1e: /* DAIFSet */
+        t1 = tcg_const_i32(crm);
+        gen_helper_msr_i_daifset(cpu_env, t1);
+        tcg_temp_free_i32(t1);
+        break;
+
     case 0x1f: /* DAIFClear */
-    {
-        TCGv_i32 tcg_imm = tcg_const_i32(crm);
-        TCGv_i32 tcg_op = tcg_const_i32(op);
-        gen_a64_set_pc_im(s->pc - 4);
-        gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
-        tcg_temp_free_i32(tcg_imm);
-        tcg_temp_free_i32(tcg_op);
+        t1 = tcg_const_i32(crm);
+        gen_helper_msr_i_daifclear(cpu_env, t1);
+        tcg_temp_free_i32(t1);
         /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs.  */
-        gen_a64_set_pc_im(s->pc);
-        s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
+        s->base.is_jmp = DISAS_UPDATE;
         break;
-    }
+
     default:
+    do_unallocated:
         unallocated_encoding(s);
         return;
     }
@@ -1698,7 +1776,6 @@ static void gen_get_nzcv(TCGv_i64 tcg_rt)
 }
 
 static void gen_set_nzcv(TCGv_i64 tcg_rt)
-
 {
     TCGv_i32 nzcv = tcg_temp_new_i32();
 
@@ -4482,11 +4559,10 @@ static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
 }
 
 /* Add/subtract (with carry)
- *  31 30 29 28 27 26 25 24 23 22 21  20  16  15   10  9    5 4   0
- * +--+--+--+------------------------+------+---------+------+-----+
- * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | opcode2 |  Rn  |  Rd |
- * +--+--+--+------------------------+------+---------+------+-----+
- *                                            [000000]
+ *  31 30 29 28 27 26 25 24 23 22 21  20  16  15       10  9    5 4   0
+ * +--+--+--+------------------------+------+-------------+------+-----+
+ * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | 0 0 0 0 0 0 |  Rn  |  Rd |
+ * +--+--+--+------------------------+------+-------------+------+-----+
  */
 
 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
@@ -4494,11 +4570,6 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
     unsigned int sf, op, setflags, rm, rn, rd;
     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
 
-    if (extract32(insn, 10, 6) != 0) {
-        unallocated_encoding(s);
-        return;
-    }
-
     sf = extract32(insn, 31, 1);
     op = extract32(insn, 30, 1);
     setflags = extract32(insn, 29, 1);
@@ -4523,6 +4594,84 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
     }
 }
 
+/*
+ * Rotate right into flags
+ *  31 30 29                21       15          10      5  4      0
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 |  imm6  | 0 0 0 0 1 |  Rn  |o2| mask |
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ */
+static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
+{
+    int mask = extract32(insn, 0, 4);
+    int o2 = extract32(insn, 4, 1);
+    int rn = extract32(insn, 5, 5);
+    int imm6 = extract32(insn, 15, 6);
+    int sf_op_s = extract32(insn, 29, 3);
+    TCGv_i64 tcg_rn;
+    TCGv_i32 nzcv;
+
+    if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_rn = read_cpu_reg(s, rn, 1);
+    tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
+
+    nzcv = tcg_temp_new_i32();
+    tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
+
+    if (mask & 8) { /* N */
+        tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
+    }
+    if (mask & 4) { /* Z */
+        tcg_gen_not_i32(cpu_ZF, nzcv);
+        tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
+    }
+    if (mask & 2) { /* C */
+        tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
+    }
+    if (mask & 1) { /* V */
+        tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
+    }
+
+    tcg_temp_free_i32(nzcv);
+}
+
+/*
+ * Evaluate into flags
+ *  31 30 29                21        15   14        10      5  4      0
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 |  Rn  |o3| mask |
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ */
+static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
+{
+    int o3_mask = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int o2 = extract32(insn, 15, 6);
+    int sz = extract32(insn, 14, 1);
+    int sf_op_s = extract32(insn, 29, 3);
+    TCGv_i32 tmp;
+    int shift;
+
+    if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
+        !dc_isar_feature(aa64_condm_4, s)) {
+        unallocated_encoding(s);
+        return;
+    }
+    shift = sz ? 16 : 24;  /* SETF16 or SETF8 */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
+    tcg_gen_shli_i32(cpu_NF, tmp, shift);
+    tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
+    tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+    tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
+    tcg_temp_free_i32(tmp);
+}
+
 /* Conditional compare (immediate / register)
  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
@@ -5152,47 +5301,81 @@ static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Data processing - register */
+/*
+ * Data processing - register
+ *  31  30 29  28      25    21  20  16      10         0
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ * |  |op0|  |op1| 1 0 1 | op2 |       |  op3  |         |
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ */
 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
 {
-    switch (extract32(insn, 24, 5)) {
-    case 0x0a: /* Logical (shifted register) */
-        disas_logic_reg(s, insn);
-        break;
-    case 0x0b: /* Add/subtract */
-        if (insn & (1 << 21)) { /* (extended register) */
-            disas_add_sub_ext_reg(s, insn);
+    int op0 = extract32(insn, 30, 1);
+    int op1 = extract32(insn, 28, 1);
+    int op2 = extract32(insn, 21, 4);
+    int op3 = extract32(insn, 10, 6);
+
+    if (!op1) {
+        if (op2 & 8) {
+            if (op2 & 1) {
+                /* Add/sub (extended register) */
+                disas_add_sub_ext_reg(s, insn);
+            } else {
+                /* Add/sub (shifted register) */
+                disas_add_sub_reg(s, insn);
+            }
         } else {
-            disas_add_sub_reg(s, insn);
+            /* Logical (shifted register) */
+            disas_logic_reg(s, insn);
         }
-        break;
-    case 0x1b: /* Data-processing (3 source) */
-        disas_data_proc_3src(s, insn);
-        break;
-    case 0x1a:
-        switch (extract32(insn, 21, 3)) {
-        case 0x0: /* Add/subtract (with carry) */
+        return;
+    }
+
+    switch (op2) {
+    case 0x0:
+        switch (op3) {
+        case 0x00: /* Add/subtract (with carry) */
             disas_adc_sbc(s, insn);
             break;
-        case 0x2: /* Conditional compare */
-            disas_cc(s, insn); /* both imm and reg forms */
-            break;
-        case 0x4: /* Conditional select */
-            disas_cond_select(s, insn);
+
+        case 0x01: /* Rotate right into flags */
+        case 0x21:
+            disas_rotate_right_into_flags(s, insn);
             break;
-        case 0x6: /* Data-processing */
-            if (insn & (1 << 30)) { /* (1 source) */
-                disas_data_proc_1src(s, insn);
-            } else {            /* (2 source) */
-                disas_data_proc_2src(s, insn);
-            }
+
+        case 0x02: /* Evaluate into flags */
+        case 0x12:
+        case 0x22:
+        case 0x32:
+            disas_evaluate_into_flags(s, insn);
             break;
+
         default:
-            unallocated_encoding(s);
-            break;
+            goto do_unallocated;
         }
         break;
+
+    case 0x2: /* Conditional compare */
+        disas_cc(s, insn); /* both imm and reg forms */
+        break;
+
+    case 0x4: /* Conditional select */
+        disas_cond_select(s, insn);
+        break;
+
+    case 0x6: /* Data-processing */
+        if (op0) {    /* (1 source) */
+            disas_data_proc_1src(s, insn);
+        } else {      /* (2 source) */
+            disas_data_proc_2src(s, insn);
+        }
+        break;
+    case 0x8 ... 0xf: /* (3 source) */
+        disas_data_proc_3src(s, insn);
+        break;
+
     default:
+    do_unallocated:
         unallocated_encoding(s);
         break;
     }
@@ -5505,55 +5688,73 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
 /* Floating-point data-processing (1 source) - single precision */
 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
 {
+    void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
+    TCGv_i32 tcg_op, tcg_res;
     TCGv_ptr fpst;
-    TCGv_i32 tcg_op;
-    TCGv_i32 tcg_res;
+    int rmode = -1;
 
-    fpst = get_fpstatus_ptr(false);
     tcg_op = read_fp_sreg(s, rn);
     tcg_res = tcg_temp_new_i32();
 
     switch (opcode) {
     case 0x0: /* FMOV */
         tcg_gen_mov_i32(tcg_res, tcg_op);
-        break;
+        goto done;
     case 0x1: /* FABS */
         gen_helper_vfp_abss(tcg_res, tcg_op);
-        break;
+        goto done;
     case 0x2: /* FNEG */
         gen_helper_vfp_negs(tcg_res, tcg_op);
-        break;
+        goto done;
     case 0x3: /* FSQRT */
         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
-        break;
+        goto done;
     case 0x8: /* FRINTN */
     case 0x9: /* FRINTP */
     case 0xa: /* FRINTM */
     case 0xb: /* FRINTZ */
     case 0xc: /* FRINTA */
-    {
-        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
-
-        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
-        gen_helper_rints(tcg_res, tcg_op, fpst);
-
-        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
-        tcg_temp_free_i32(tcg_rmode);
+        rmode = arm_rmode_to_sf(opcode & 7);
+        gen_fpst = gen_helper_rints;
         break;
-    }
     case 0xe: /* FRINTX */
-        gen_helper_rints_exact(tcg_res, tcg_op, fpst);
+        gen_fpst = gen_helper_rints_exact;
         break;
     case 0xf: /* FRINTI */
-        gen_helper_rints(tcg_res, tcg_op, fpst);
+        gen_fpst = gen_helper_rints;
+        break;
+    case 0x10: /* FRINT32Z */
+        rmode = float_round_to_zero;
+        gen_fpst = gen_helper_frint32_s;
+        break;
+    case 0x11: /* FRINT32X */
+        gen_fpst = gen_helper_frint32_s;
+        break;
+    case 0x12: /* FRINT64Z */
+        rmode = float_round_to_zero;
+        gen_fpst = gen_helper_frint64_s;
+        break;
+    case 0x13: /* FRINT64X */
+        gen_fpst = gen_helper_frint64_s;
         break;
     default:
-        abort();
+        g_assert_not_reached();
     }
 
-    write_fp_sreg(s, rd, tcg_res);
-
+    fpst = get_fpstatus_ptr(false);
+    if (rmode >= 0) {
+        TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+        gen_fpst(tcg_res, tcg_op, fpst);
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+        tcg_temp_free_i32(tcg_rmode);
+    } else {
+        gen_fpst(tcg_res, tcg_op, fpst);
+    }
     tcg_temp_free_ptr(fpst);
+
+ done:
+    write_fp_sreg(s, rd, tcg_res);
     tcg_temp_free_i32(tcg_op);
     tcg_temp_free_i32(tcg_res);
 }
@@ -5561,9 +5762,10 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
 /* Floating-point data-processing (1 source) - double precision */
 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
 {
+    void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
+    TCGv_i64 tcg_op, tcg_res;
     TCGv_ptr fpst;
-    TCGv_i64 tcg_op;
-    TCGv_i64 tcg_res;
+    int rmode = -1;
 
     switch (opcode) {
     case 0x0: /* FMOV */
@@ -5571,48 +5773,65 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
         return;
     }
 
-    fpst = get_fpstatus_ptr(false);
     tcg_op = read_fp_dreg(s, rn);
     tcg_res = tcg_temp_new_i64();
 
     switch (opcode) {
     case 0x1: /* FABS */
         gen_helper_vfp_absd(tcg_res, tcg_op);
-        break;
+        goto done;
     case 0x2: /* FNEG */
         gen_helper_vfp_negd(tcg_res, tcg_op);
-        break;
+        goto done;
     case 0x3: /* FSQRT */
         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
-        break;
+        goto done;
     case 0x8: /* FRINTN */
     case 0x9: /* FRINTP */
     case 0xa: /* FRINTM */
     case 0xb: /* FRINTZ */
     case 0xc: /* FRINTA */
-    {
-        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
-
-        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
-        gen_helper_rintd(tcg_res, tcg_op, fpst);
-
-        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
-        tcg_temp_free_i32(tcg_rmode);
+        rmode = arm_rmode_to_sf(opcode & 7);
+        gen_fpst = gen_helper_rintd;
         break;
-    }
     case 0xe: /* FRINTX */
-        gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
+        gen_fpst = gen_helper_rintd_exact;
         break;
     case 0xf: /* FRINTI */
-        gen_helper_rintd(tcg_res, tcg_op, fpst);
+        gen_fpst = gen_helper_rintd;
+        break;
+    case 0x10: /* FRINT32Z */
+        rmode = float_round_to_zero;
+        gen_fpst = gen_helper_frint32_d;
+        break;
+    case 0x11: /* FRINT32X */
+        gen_fpst = gen_helper_frint32_d;
+        break;
+    case 0x12: /* FRINT64Z */
+        rmode = float_round_to_zero;
+        gen_fpst = gen_helper_frint64_d;
+        break;
+    case 0x13: /* FRINT64X */
+        gen_fpst = gen_helper_frint64_d;
         break;
     default:
-        abort();
+        g_assert_not_reached();
     }
 
-    write_fp_dreg(s, rd, tcg_res);
-
+    fpst = get_fpstatus_ptr(false);
+    if (rmode >= 0) {
+        TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+        gen_fpst(tcg_res, tcg_op, fpst);
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+        tcg_temp_free_i32(tcg_rmode);
+    } else {
+        gen_fpst(tcg_res, tcg_op, fpst);
+    }
     tcg_temp_free_ptr(fpst);
+
+ done:
+    write_fp_dreg(s, rd, tcg_res);
     tcg_temp_free_i64(tcg_op);
     tcg_temp_free_i64(tcg_res);
 }
@@ -5731,6 +5950,13 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
         break;
     }
+
+    case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
+        if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
+            unallocated_encoding(s);
+            return;
+        }
+        /* fall through */
     case 0x0 ... 0x3:
     case 0x8 ... 0xc:
     case 0xe ... 0xf:
@@ -5740,14 +5966,12 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
             if (!fp_access_check(s)) {
                 return;
             }
-
             handle_fp_1src_single(s, opcode, rd, rn);
             break;
         case 1:
             if (!fp_access_check(s)) {
                 return;
             }
-
             handle_fp_1src_double(s, opcode, rd, rn);
             break;
         case 3:
@@ -5759,13 +5983,13 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
             if (!fp_access_check(s)) {
                 return;
             }
-
             handle_fp_1src_half(s, opcode, rd, rn);
             break;
         default:
             unallocated_encoding(s);
         }
         break;
+
     default:
         unallocated_encoding(s);
         break;
@@ -9293,6 +9517,14 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u,
     case 0x59: /* FRINTX */
         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
         break;
+    case 0x1e: /* FRINT32Z */
+    case 0x5e: /* FRINT32X */
+        gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
+        break;
+    case 0x1f: /* FRINT64Z */
+    case 0x5f: /* FRINT64X */
+        gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
+        break;
     default:
         g_assert_not_reached();
     }
@@ -10917,9 +11149,29 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
         if (!fp_access_check(s)) {
             return;
         }
-
         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
         return;
+
+    case 0x1d: /* FMLAL  */
+    case 0x3d: /* FMLSL  */
+    case 0x59: /* FMLAL2 */
+    case 0x79: /* FMLSL2 */
+        if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
+            unallocated_encoding(s);
+            return;
+        }
+        if (fp_access_check(s)) {
+            int is_s = extract32(insn, 23, 1);
+            int is_2 = extract32(insn, 29, 1);
+            int data = (is_2 << 1) | is_s;
+            tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+                               vec_full_reg_offset(s, rn),
+                               vec_full_reg_offset(s, rm), cpu_env,
+                               is_q ? 16 : 8, vec_full_reg_size(s),
+                               data, gen_helper_gvec_fmlal_a64);
+        }
+        return;
+
     default:
         unallocated_encoding(s);
         return;
@@ -11923,8 +12175,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
         }
         break;
     case 0xc ... 0xf:
-    case 0x16 ... 0x1d:
-    case 0x1f:
+    case 0x16 ... 0x1f:
     {
         /* Floating point: U, size[1] and opcode indicate operation;
          * size[0] indicates single or double precision.
@@ -12067,6 +12318,19 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
             }
             need_fpstatus = true;
             break;
+        case 0x1e: /* FRINT32Z */
+        case 0x1f: /* FRINT64Z */
+            need_rmode = true;
+            rmode = FPROUNDING_ZERO;
+            /* fall through */
+        case 0x5e: /* FRINT32X */
+        case 0x5f: /* FRINT64X */
+            need_fpstatus = true;
+            if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
+                unallocated_encoding(s);
+                return;
+            }
+            break;
         default:
             unallocated_encoding(s);
             return;
@@ -12232,6 +12496,14 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
                 case 0x7c: /* URSQRTE */
                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
                     break;
+                case 0x1e: /* FRINT32Z */
+                case 0x5e: /* FRINT32X */
+                    gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
+                    break;
+                case 0x1f: /* FRINT64Z */
+                case 0x5f: /* FRINT64X */
+                    gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
+                    break;
                 default:
                     g_assert_not_reached();
                 }
@@ -12739,6 +13011,17 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
         }
         is_fp = 2;
         break;
+    case 0x00: /* FMLAL */
+    case 0x04: /* FMLSL */
+    case 0x18: /* FMLAL2 */
+    case 0x1c: /* FMLSL2 */
+        if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
+            unallocated_encoding(s);
+            return;
+        }
+        size = MO_16;
+        /* is_fp, but we pass cpu_env not fp_status.  */
+        break;
     default:
         unallocated_encoding(s);
         return;
@@ -12849,6 +13132,22 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
             tcg_temp_free_ptr(fpst);
         }
         return;
+
+    case 0x00: /* FMLAL */
+    case 0x04: /* FMLSL */
+    case 0x18: /* FMLAL2 */
+    case 0x1c: /* FMLSL2 */
+        {
+            int is_s = extract32(opcode, 2, 1);
+            int is_2 = u;
+            int data = (index << 2) | (is_2 << 1) | is_s;
+            tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+                               vec_full_reg_offset(s, rn),
+                               vec_full_reg_offset(s, rm), cpu_env,
+                               is_q ? 16 : 8, vec_full_reg_size(s),
+                               data, gen_helper_gvec_fmlal_idx_a64);
+        }
+        return;
     }
 
     if (size == 3) {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c1175798ac..d408e4d7ef 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -298,17 +298,6 @@ static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
     tcg_temp_free_i32(tcg_excp);
 }
 
-static void gen_ss_advance(DisasContext *s)
-{
-    /* If the singlestep state is Active-not-pending, advance to
-     * Active-pending.
-     */
-    if (s->ss_active) {
-        s->pstate_ss = 0;
-        gen_helper_clear_pstate_ss(cpu_env);
-    }
-}
-
 static void gen_step_complete_exception(DisasContext *s)
 {
     /* We just completed step of an insn. Move from Active-not-pending
@@ -3357,14 +3346,10 @@ static const uint8_t fp_decode_rm[] = {
     FPROUNDING_NEGINF,
 };
 
-static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
+static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
 {
     uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
 
-    if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
-        return 1;
-    }
-
     if (dp) {
         VFP_DREG_D(rd, insn);
         VFP_DREG_N(rn, insn);
@@ -3375,15 +3360,18 @@ static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
         rm = VFP_SREG_M(insn);
     }
 
-    if ((insn & 0x0f800e50) == 0x0e000a00) {
+    if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
         return handle_vsel(insn, rd, rn, rm, dp);
-    } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
+    } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
+               dc_isar_feature(aa32_vminmaxnm, s)) {
         return handle_vminmaxnm(insn, rd, rn, rm, dp);
-    } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
+    } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
+               dc_isar_feature(aa32_vrint, s)) {
         /* VRINTA, VRINTN, VRINTP, VRINTM */
         int rounding = fp_decode_rm[extract32(insn, 16, 2)];
         return handle_vrint(insn, rd, rm, dp, rounding);
-    } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
+    } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
+               dc_isar_feature(aa32_vcvt_dr, s)) {
         /* VCVTA, VCVTN, VCVTP, VCVTM */
         int rounding = fp_decode_rm[extract32(insn, 16, 2)];
         return handle_vcvt(insn, rd, rm, dp, rounding);
@@ -3427,10 +3415,12 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
     }
 
     if (extract32(insn, 28, 4) == 0xf) {
-        /* Encodings with T=1 (Thumb) or unconditional (ARM):
-         * only used in v8 and above.
+        /*
+         * Encodings with T=1 (Thumb) or unconditional (ARM):
+         * only used for the "miscellaneous VFP features" added in v8A
+         * and v7M (and gated on the MVFR2.FPMisc field).
          */
-        return disas_vfp_v8_insn(s, insn);
+        return disas_vfp_misc_insn(s, insn);
     }
 
     dp = ((insn & 0xf00) == 0xb00);
@@ -3663,17 +3653,27 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
                      * UNPREDICTABLE if bit 8 is set prior to ARMv8
                      * (we choose to UNDEF)
                      */
-                    if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
-                        !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
-                        return 1;
+                    if (dp) {
+                        if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+                            return 1;
+                        }
+                    } else {
+                        if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+                            return 1;
+                        }
                     }
                     rm_is_dp = false;
                     break;
                 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
                 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
-                    if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
-                        !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
-                        return 1;
+                    if (dp) {
+                        if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+                            return 1;
+                        }
+                    } else {
+                        if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+                            return 1;
+                        }
                     }
                     rd_is_dp = false;
                     break;
@@ -7876,7 +7876,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                     TCGv_ptr fpst;
                     TCGv_i32 ahp;
 
-                    if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+                    if (!dc_isar_feature(aa32_fp16_spconv, s) ||
                         q || (rm & 1)) {
                         return 1;
                     }
@@ -7908,7 +7908,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
                 {
                     TCGv_ptr fpst;
                     TCGv_i32 ahp;
-                    if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+                    if (!dc_isar_feature(aa32_fp16_spconv, s) ||
                         q || (rd & 1)) {
                         return 1;
                     }
@@ -8372,15 +8372,9 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
     gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
     int rd, rn, rm, opr_sz;
     int data = 0;
-    bool q;
-
-    q = extract32(insn, 6, 1);
-    VFP_DREG_D(rd, insn);
-    VFP_DREG_N(rn, insn);
-    VFP_DREG_M(rm, insn);
-    if ((rd | rn | rm) & q) {
-        return 1;
-    }
+    int off_rn, off_rm;
+    bool is_long = false, q = extract32(insn, 6, 1);
+    bool ptr_is_env = false;
 
     if ((insn & 0xfe200f10) == 0xfc200800) {
         /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
@@ -8407,10 +8401,39 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
             return 1;
         }
         fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
+    } else if ((insn & 0xff300f10) == 0xfc200810) {
+        /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
+        int is_s = extract32(insn, 23, 1);
+        if (!dc_isar_feature(aa32_fhm, s)) {
+            return 1;
+        }
+        is_long = true;
+        data = is_s; /* is_2 == 0 */
+        fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
+        ptr_is_env = true;
     } else {
         return 1;
     }
 
+    VFP_DREG_D(rd, insn);
+    if (rd & q) {
+        return 1;
+    }
+    if (q || !is_long) {
+        VFP_DREG_N(rn, insn);
+        VFP_DREG_M(rm, insn);
+        if ((rn | rm) & q & !is_long) {
+            return 1;
+        }
+        off_rn = vfp_reg_offset(1, rn);
+        off_rm = vfp_reg_offset(1, rm);
+    } else {
+        rn = VFP_SREG_N(insn);
+        rm = VFP_SREG_M(insn);
+        off_rn = vfp_reg_offset(0, rn);
+        off_rm = vfp_reg_offset(0, rm);
+    }
+
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
                            syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
@@ -8422,16 +8445,19 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
 
     opr_sz = (1 + q) * 8;
     if (fn_gvec_ptr) {
-        TCGv_ptr fpst = get_fpstatus_ptr(1);
-        tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
-                           vfp_reg_offset(1, rn),
-                           vfp_reg_offset(1, rm), fpst,
+        TCGv_ptr ptr;
+        if (ptr_is_env) {
+            ptr = cpu_env;
+        } else {
+            ptr = get_fpstatus_ptr(1);
+        }
+        tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
                            opr_sz, opr_sz, data, fn_gvec_ptr);
-        tcg_temp_free_ptr(fpst);
+        if (!ptr_is_env) {
+            tcg_temp_free_ptr(ptr);
+        }
     } else {
-        tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
-                           vfp_reg_offset(1, rn),
-                           vfp_reg_offset(1, rm),
+        tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
                            opr_sz, opr_sz, data, fn_gvec);
     }
     return 0;
@@ -8450,14 +8476,9 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
     gen_helper_gvec_3 *fn_gvec = NULL;
     gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
     int rd, rn, rm, opr_sz, data;
-    bool q;
-
-    q = extract32(insn, 6, 1);
-    VFP_DREG_D(rd, insn);
-    VFP_DREG_N(rn, insn);
-    if ((rd | rn) & q) {
-        return 1;
-    }
+    int off_rn, off_rm;
+    bool is_long = false, q = extract32(insn, 6, 1);
+    bool ptr_is_env = false;
 
     if ((insn & 0xff000f10) == 0xfe000800) {
         /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
@@ -8486,6 +8507,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
     } else if ((insn & 0xffb00f00) == 0xfe200d00) {
         /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
         int u = extract32(insn, 4, 1);
+
         if (!dc_isar_feature(aa32_dp, s)) {
             return 1;
         }
@@ -8493,10 +8515,48 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
         /* rm is just Vm, and index is M.  */
         data = extract32(insn, 5, 1); /* index */
         rm = extract32(insn, 0, 4);
+    } else if ((insn & 0xffa00f10) == 0xfe000810) {
+        /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
+        int is_s = extract32(insn, 20, 1);
+        int vm20 = extract32(insn, 0, 3);
+        int vm3 = extract32(insn, 3, 1);
+        int m = extract32(insn, 5, 1);
+        int index;
+
+        if (!dc_isar_feature(aa32_fhm, s)) {
+            return 1;
+        }
+        if (q) {
+            rm = vm20;
+            index = m * 2 + vm3;
+        } else {
+            rm = vm20 * 2 + m;
+            index = vm3;
+        }
+        is_long = true;
+        data = (index << 2) | is_s; /* is_2 == 0 */
+        fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
+        ptr_is_env = true;
     } else {
         return 1;
     }
 
+    VFP_DREG_D(rd, insn);
+    if (rd & q) {
+        return 1;
+    }
+    if (q || !is_long) {
+        VFP_DREG_N(rn, insn);
+        if (rn & q & !is_long) {
+            return 1;
+        }
+        off_rn = vfp_reg_offset(1, rn);
+        off_rm = vfp_reg_offset(1, rm);
+    } else {
+        rn = VFP_SREG_N(insn);
+        off_rn = vfp_reg_offset(0, rn);
+        off_rm = vfp_reg_offset(0, rm);
+    }
     if (s->fp_excp_el) {
         gen_exception_insn(s, 4, EXCP_UDEF,
                            syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
@@ -8508,16 +8568,19 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
 
     opr_sz = (1 + q) * 8;
     if (fn_gvec_ptr) {
-        TCGv_ptr fpst = get_fpstatus_ptr(1);
-        tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
-                           vfp_reg_offset(1, rn),
-                           vfp_reg_offset(1, rm), fpst,
+        TCGv_ptr ptr;
+        if (ptr_is_env) {
+            ptr = cpu_env;
+        } else {
+            ptr = get_fpstatus_ptr(1);
+        }
+        tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
                            opr_sz, opr_sz, data, fn_gvec_ptr);
-        tcg_temp_free_ptr(fpst);
+        if (!ptr_is_env) {
+            tcg_temp_free_ptr(ptr);
+        }
     } else {
-        tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
-                           vfp_reg_offset(1, rn),
-                           vfp_reg_offset(1, rm),
+        tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
                            opr_sz, opr_sz, data, fn_gvec);
     }
     return 0;
@@ -9208,6 +9271,17 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                  */
                 gen_goto_tb(s, 0, s->pc & ~1);
                 return;
+            case 7: /* sb */
+                if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
+                    goto illegal_op;
+                }
+                /*
+                 * TODO: There is no speculation barrier opcode
+                 * for TCG; MB and end the TB instead.
+                 */
+                tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+                gen_goto_tb(s, 0, s->pc & ~1);
+                return;
             default:
                 goto illegal_op;
             }
@@ -10538,7 +10612,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                             } else if (i == rn) {
                                 loaded_var = tmp;
                                 loaded_base = 1;
-                            } else if (rn == 15 && exc_return) {
+                            } else if (i == 15 && exc_return) {
                                 store_pc_exc_ret(s, tmp);
                             } else {
                                 store_reg_from_load(s, i, tmp);
@@ -11826,6 +11900,17 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
                              */
                             gen_goto_tb(s, 0, s->pc & ~1);
                             break;
+                        case 7: /* sb */
+                            if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
+                                goto illegal_op;
+                            }
+                            /*
+                             * TODO: There is no speculation barrier opcode
+                             * for TCG; MB and end the TB instead.
+                             */
+                            tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+                            gen_goto_tb(s, 0, s->pc & ~1);
+                            break;
                         default:
                             goto illegal_op;
                         }
diff --git a/target/arm/translate.h b/target/arm/translate.h
index f25fe75685..912cc2a4a5 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -202,6 +202,40 @@ static inline TCGv_i32 get_ahp_flag(void)
     return ret;
 }
 
+/* Set bits within PSTATE.  */
+static inline void set_pstate_bits(uint32_t bits)
+{
+    TCGv_i32 p = tcg_temp_new_i32();
+
+    tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
+
+    tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+    tcg_gen_ori_i32(p, p, bits);
+    tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+    tcg_temp_free_i32(p);
+}
+
+/* Clear bits within PSTATE.  */
+static inline void clear_pstate_bits(uint32_t bits)
+{
+    TCGv_i32 p = tcg_temp_new_i32();
+
+    tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
+
+    tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+    tcg_gen_andi_i32(p, p, ~bits);
+    tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+    tcg_temp_free_i32(p);
+}
+
+/* If the singlestep state is Active-not-pending, advance to Active-pending. */
+static inline void gen_ss_advance(DisasContext *s)
+{
+    if (s->ss_active) {
+        s->pstate_ss = 0;
+        clear_pstate_bits(PSTATE_SS);
+    }
+}
 
 /* Vector operations shared between ARM and AArch64.  */
 extern const GVecGen3 bsl_op;
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
index dfc635cf9a..dedef62403 100644
--- a/target/arm/vec_helper.c
+++ b/target/arm/vec_helper.c
@@ -898,3 +898,151 @@ void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn,
     }
     clear_tail(d, oprsz, simd_maxsz(desc));
 }
+
+/*
+ * Convert float16 to float32, raising no exceptions and
+ * preserving exceptional values, including SNaN.
+ * This is effectively an unpack+repack operation.
+ */
+static float32 float16_to_float32_by_bits(uint32_t f16, bool fz16)
+{
+    const int f16_bias = 15;
+    const int f32_bias = 127;
+    uint32_t sign = extract32(f16, 15, 1);
+    uint32_t exp = extract32(f16, 10, 5);
+    uint32_t frac = extract32(f16, 0, 10);
+
+    if (exp == 0x1f) {
+        /* Inf or NaN */
+        exp = 0xff;
+    } else if (exp == 0) {
+        /* Zero or denormal.  */
+        if (frac != 0) {
+            if (fz16) {
+                frac = 0;
+            } else {
+                /*
+                 * Denormal; these are all normal float32.
+                 * Shift the fraction so that the msb is at bit 11,
+                 * then remove bit 11 as the implicit bit of the
+                 * normalized float32.  Note that we still go through
+                 * the shift for normal numbers below, to put the
+                 * float32 fraction at the right place.
+                 */
+                int shift = clz32(frac) - 21;
+                frac = (frac << shift) & 0x3ff;
+                exp = f32_bias - f16_bias - shift + 1;
+            }
+        }
+    } else {
+        /* Normal number; adjust the bias.  */
+        exp += f32_bias - f16_bias;
+    }
+    sign <<= 31;
+    exp <<= 23;
+    frac <<= 23 - 10;
+
+    return sign | exp | frac;
+}
+
+static uint64_t load4_f16(uint64_t *ptr, int is_q, int is_2)
+{
+    /*
+     * Branchless load of u32[0], u64[0], u32[1], or u64[1].
+     * Load the 2nd qword iff is_q & is_2.
+     * Shift to the 2nd dword iff !is_q & is_2.
+     * For !is_q & !is_2, the upper bits of the result are garbage.
+     */
+    return ptr[is_q & is_2] >> ((is_2 & ~is_q) << 5);
+}
+
+/*
+ * Note that FMLAL requires oprsz == 8 or oprsz == 16,
+ * as there is not yet SVE versions that might use blocking.
+ */
+
+static void do_fmlal(float32 *d, void *vn, void *vm, float_status *fpst,
+                     uint32_t desc, bool fz16)
+{
+    intptr_t i, oprsz = simd_oprsz(desc);
+    int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+    int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+    int is_q = oprsz == 16;
+    uint64_t n_4, m_4;
+
+    /* Pre-load all of the f16 data, avoiding overlap issues.  */
+    n_4 = load4_f16(vn, is_q, is_2);
+    m_4 = load4_f16(vm, is_q, is_2);
+
+    /* Negate all inputs for FMLSL at once.  */
+    if (is_s) {
+        n_4 ^= 0x8000800080008000ull;
+    }
+
+    for (i = 0; i < oprsz / 4; i++) {
+        float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+        float32 m_1 = float16_to_float32_by_bits(m_4 >> (i * 16), fz16);
+        d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+    }
+    clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_a32)(void *vd, void *vn, void *vm,
+                            void *venv, uint32_t desc)
+{
+    CPUARMState *env = venv;
+    do_fmlal(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+             get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_a64)(void *vd, void *vn, void *vm,
+                            void *venv, uint32_t desc)
+{
+    CPUARMState *env = venv;
+    do_fmlal(vd, vn, vm, &env->vfp.fp_status, desc,
+             get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+static void do_fmlal_idx(float32 *d, void *vn, void *vm, float_status *fpst,
+                         uint32_t desc, bool fz16)
+{
+    intptr_t i, oprsz = simd_oprsz(desc);
+    int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+    int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+    int index = extract32(desc, SIMD_DATA_SHIFT + 2, 3);
+    int is_q = oprsz == 16;
+    uint64_t n_4;
+    float32 m_1;
+
+    /* Pre-load all of the f16 data, avoiding overlap issues.  */
+    n_4 = load4_f16(vn, is_q, is_2);
+
+    /* Negate all inputs for FMLSL at once.  */
+    if (is_s) {
+        n_4 ^= 0x8000800080008000ull;
+    }
+
+    m_1 = float16_to_float32_by_bits(((float16 *)vm)[H2(index)], fz16);
+
+    for (i = 0; i < oprsz / 4; i++) {
+        float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+        d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+    }
+    clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_idx_a32)(void *vd, void *vn, void *vm,
+                                void *venv, uint32_t desc)
+{
+    CPUARMState *env = venv;
+    do_fmlal_idx(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+                 get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm,
+                                void *venv, uint32_t desc)
+{
+    CPUARMState *env = venv;
+    do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc,
+                 get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
index cc7f9f5cb1..2468fc1629 100644
--- a/target/arm/vfp_helper.c
+++ b/target/arm/vfp_helper.c
@@ -1174,3 +1174,99 @@ uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
 
     return result;
 }
+
+/* Round a float32 to an integer that fits in int32_t or int64_t.  */
+static float32 frint_s(float32 f, float_status *fpst, int intsize)
+{
+    int old_flags = get_float_exception_flags(fpst);
+    uint32_t exp = extract32(f, 23, 8);
+
+    if (unlikely(exp == 0xff)) {
+        /* NaN or Inf.  */
+        goto overflow;
+    }
+
+    /* Round and re-extract the exponent.  */
+    f = float32_round_to_int(f, fpst);
+    exp = extract32(f, 23, 8);
+
+    /* Validate the range of the result.  */
+    if (exp < 126 + intsize) {
+        /* abs(F) <= INT{N}_MAX */
+        return f;
+    }
+    if (exp == 126 + intsize) {
+        uint32_t sign = extract32(f, 31, 1);
+        uint32_t frac = extract32(f, 0, 23);
+        if (sign && frac == 0) {
+            /* F == INT{N}_MIN */
+            return f;
+        }
+    }
+
+ overflow:
+    /*
+     * Raise Invalid and return INT{N}_MIN as a float.  Revert any
+     * inexact exception float32_round_to_int may have raised.
+     */
+    set_float_exception_flags(old_flags | float_flag_invalid, fpst);
+    return (0x100u + 126u + intsize) << 23;
+}
+
+float32 HELPER(frint32_s)(float32 f, void *fpst)
+{
+    return frint_s(f, fpst, 32);
+}
+
+float32 HELPER(frint64_s)(float32 f, void *fpst)
+{
+    return frint_s(f, fpst, 64);
+}
+
+/* Round a float64 to an integer that fits in int32_t or int64_t.  */
+static float64 frint_d(float64 f, float_status *fpst, int intsize)
+{
+    int old_flags = get_float_exception_flags(fpst);
+    uint32_t exp = extract64(f, 52, 11);
+
+    if (unlikely(exp == 0x7ff)) {
+        /* NaN or Inf.  */
+        goto overflow;
+    }
+
+    /* Round and re-extract the exponent.  */
+    f = float64_round_to_int(f, fpst);
+    exp = extract64(f, 52, 11);
+
+    /* Validate the range of the result.  */
+    if (exp < 1022 + intsize) {
+        /* abs(F) <= INT{N}_MAX */
+        return f;
+    }
+    if (exp == 1022 + intsize) {
+        uint64_t sign = extract64(f, 63, 1);
+        uint64_t frac = extract64(f, 0, 52);
+        if (sign && frac == 0) {
+            /* F == INT{N}_MIN */
+            return f;
+        }
+    }
+
+ overflow:
+    /*
+     * Raise Invalid and return INT{N}_MIN as a float.  Revert any
+     * inexact exception float64_round_to_int may have raised.
+     */
+    set_float_exception_flags(old_flags | float_flag_invalid, fpst);
+    return (uint64_t)(0x800 + 1022 + intsize) << 52;
+}
+
+float64 HELPER(frint32_d)(float64 f, void *fpst)
+{
+    return frint_d(f, fpst, 32);
+}
+
+float64 HELPER(frint64_d)(float64 f, void *fpst)
+{
+    return frint_d(f, fpst, 64);
+}
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 3b170208c3..364bd6dc4f 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -4362,6 +4362,7 @@ static void gen_shift(DisasContext *ctx, uint32_t opc,
     tcg_temp_free(t1);
 }
 
+#if defined(TARGET_MIPS64)
 /* Copy GPR to and from TX79 HI1/LO1 register. */
 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
 {
@@ -4397,6 +4398,7 @@ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
         break;
     }
 }
+#endif
 
 /* Arithmetic on HI/LO registers */
 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
@@ -4746,6 +4748,7 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
     tcg_temp_free(t1);
 }
 
+#if defined(TARGET_MIPS64)
 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
 {
     TCGv t0, t1;
@@ -4802,6 +4805,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
     tcg_temp_free(t0);
     tcg_temp_free(t1);
 }
+#endif
 
 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
                        int acc, int rs, int rt)
@@ -24324,6 +24328,29 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
 }
 
 
+#if defined(TARGET_MIPS64)
+
+/*
+ *
+ *           MMI (MultiMedia Interface) ASE instructions
+ *           ===========================================
+ */
+
+/*
+ *          MMI instructions category: data communication
+ *          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *   PCPYH    PEXCH    PEXTLB   PINTH    PPACB    PEXT5    PREVH
+ *   PCPYLD   PEXCW    PEXTLH   PINTEH   PPACH    PPAC5    PROT3W
+ *   PCPYUD   PEXEH    PEXTLW            PPACW
+ *            PEXEW    PEXTUB
+ *                     PEXTUH
+ *                     PEXTUW
+ */
+
+#endif
+
+
 #if !defined(TARGET_MIPS64)
 
 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
@@ -27247,6 +27274,9 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
     }
 }
 
+
+#if defined(TARGET_MIPS64)
+
 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
 {
     uint32_t opc = MASK_MMI0(ctx->opcode);
@@ -27491,6 +27521,8 @@ static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
     gen_mmi_sq(ctx, base, rt, offset);
 }
 
+#endif
+
 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
 {
     int rs, rt, rd, sa;
@@ -28796,10 +28828,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         decode_opc_special(env, ctx);
         break;
     case OPC_SPECIAL2:
+#if defined(TARGET_MIPS64)
         if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
             decode_mmi(env, ctx);
-#if !defined(TARGET_MIPS64)
-        } else if (ctx->insn_flags & ASE_MXU) {
+#else
+        if (ctx->insn_flags & ASE_MXU) {
             decode_opc_mxu(env, ctx);
 #endif
         } else {
@@ -28807,11 +28840,15 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         }
         break;
     case OPC_SPECIAL3:
+#if defined(TARGET_MIPS64)
         if (ctx->insn_flags & INSN_R5900) {
             decode_mmi_sq(env, ctx);    /* MMI_OPC_SQ */
         } else {
             decode_opc_special3(env, ctx);
         }
+#else
+        decode_opc_special3(env, ctx);
+#endif
         break;
     case OPC_REGIMM:
         op1 = MASK_REGIMM(ctx->opcode);
@@ -29483,7 +29520,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         break;
     case OPC_MSA: /* OPC_MDMX */
         if (ctx->insn_flags & INSN_R5900) {
+#if defined(TARGET_MIPS64)
             gen_mmi_lq(env, ctx);    /* MMI_OPC_LQ */
+#endif
         } else {
             /* MDMX: Not implemented. */
             gen_msa(env, ctx);
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 3130802304..ae51fe754e 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -113,6 +113,8 @@ enum powerpc_excp_t {
     POWERPC_EXCP_POWER7,
     /* POWER8 exception model           */
     POWERPC_EXCP_POWER8,
+    /* POWER9 exception model           */
+    POWERPC_EXCP_POWER9,
 };
 
 /*****************************************************************************/
@@ -122,6 +124,7 @@ typedef enum {
     PPC_PM_NAP,
     PPC_PM_SLEEP,
     PPC_PM_RVWINKLE,
+    PPC_PM_STOP,
 } powerpc_pm_insn_t;
 
 /*****************************************************************************/
@@ -139,6 +142,8 @@ enum powerpc_input_t {
     PPC_FLAGS_INPUT_970,
     /* PowerPC POWER7 bus               */
     PPC_FLAGS_INPUT_POWER7,
+    /* PowerPC POWER9 bus               */
+    PPC_FLAGS_INPUT_POWER9,
     /* PowerPC 401 bus                  */
     PPC_FLAGS_INPUT_401,
     /* Freescale RCPU bus               */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 325ebbeb98..26604ddf98 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -160,8 +160,10 @@ enum {
     /* Server doorbell variants */
     POWERPC_EXCP_SDOOR    = 99,
     POWERPC_EXCP_SDOOR_HV = 100,
+    /* ISA 3.00 additions */
+    POWERPC_EXCP_HVIRT    = 101,
     /* EOL                                                                   */
-    POWERPC_EXCP_NB       = 101,
+    POWERPC_EXCP_NB       = 102,
     /* QEMU exceptions: used internally during code translation              */
     POWERPC_EXCP_STOP         = 0x200, /* stop translation                   */
     POWERPC_EXCP_BRANCH       = 0x201, /* branch instruction                 */
@@ -318,6 +320,10 @@ struct ppc_slb_t {
 #define SEGMENT_SHIFT_1T        40
 #define SEGMENT_MASK_1T         (~((1ULL << SEGMENT_SHIFT_1T) - 1))
 
+typedef struct ppc_v3_pate_t {
+    uint64_t dw0;
+    uint64_t dw1;
+} ppc_v3_pate_t;
 
 /*****************************************************************************/
 /* Machine state register bits definition                                    */
@@ -386,6 +392,7 @@ struct ppc_slb_t {
 #define LPCR_AIL          (3ull << LPCR_AIL_SHIFT)
 #define LPCR_UPRT         PPC_BIT(41) /* Use Process Table */
 #define LPCR_EVIRT        PPC_BIT(42) /* Enhanced Virtualisation */
+#define LPCR_HR           PPC_BIT(43) /* Host Radix */
 #define LPCR_ONL          PPC_BIT(45)
 #define LPCR_LD           PPC_BIT(46) /* Large Decrementer */
 #define LPCR_P7_PECE0     PPC_BIT(49)
@@ -414,6 +421,10 @@ struct ppc_slb_t {
 #define LPCR_HVICE        PPC_BIT(62) /* HV Virtualisation Int Enable */
 #define LPCR_HDICE        PPC_BIT(63)
 
+/* PSSCR bits */
+#define PSSCR_ESL         PPC_BIT(42) /* Enable State Loss */
+#define PSSCR_EC          PPC_BIT(43) /* Exit Criterion */
+
 #define msr_sf   ((env->msr >> MSR_SF)   & 1)
 #define msr_isf  ((env->msr >> MSR_ISF)  & 1)
 #define msr_shv  ((env->msr >> MSR_SHV)  & 1)
@@ -1110,11 +1121,13 @@ struct CPUPPCState {
      * instructions and SPRs are diallowed if MSR:HV is 0
      */
     bool has_hv_mode;
-    /* On P7/P8, set when in PM state, we need to handle resume
-     * in a special way (such as routing some resume causes to
-     * 0x100), so flag this here.
+
+    /*
+     * On P7/P8/P9, set when in PM state, we need to handle resume in
+     * a special way (such as routing some resume causes to 0x100, ie,
+     * sreset), so flag this here.
      */
-    bool in_pm_state;
+    bool resume_as_sreset;
 #endif
 
     /* Those resources are used only during code translation */
@@ -1239,7 +1252,7 @@ struct PPCVirtualHypervisorClass {
                         hwaddr ptex, int n);
     void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
                        uint64_t pte0, uint64_t pte1);
-    uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp);
+    void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry);
     target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp);
 };
 
@@ -2319,6 +2332,13 @@ enum {
      * them */
     POWER7_INPUT_NB,
 };
+
+enum {
+    /* POWER9 input pins */
+    POWER9_INPUT_INT        = 0,
+    POWER9_INPUT_HINT       = 1,
+    POWER9_INPUT_NB,
+};
 #endif
 
 /* Hardware exceptions definitions */
@@ -2343,6 +2363,7 @@ enum {
     PPC_INTERRUPT_PERFM,          /* Performance monitor interrupt        */
     PPC_INTERRUPT_HMI,            /* Hypervisor Maintainance interrupt    */
     PPC_INTERRUPT_HDOORBELL,      /* Hypervisor Doorbell interrupt        */
+    PPC_INTERRUPT_HVIRT,          /* Hypervisor virtualization interrupt  */
 };
 
 /* Processor Compatibility mask (PCR) */
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 751d759fcc..39bedbb11d 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -65,6 +65,49 @@ static inline void dump_syscall(CPUPPCState *env)
                   ppc_dump_gpr(env, 6), env->nip);
 }
 
+static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
+                                target_ulong *msr)
+{
+    /* We no longer are in a PM state */
+    env->resume_as_sreset = false;
+
+    /* Pretend to be returning from doze always as we don't lose state */
+    *msr |= (0x1ull << (63 - 47));
+
+    /* Machine checks are sent normally */
+    if (excp == POWERPC_EXCP_MCHECK) {
+        return excp;
+    }
+    switch (excp) {
+    case POWERPC_EXCP_RESET:
+        *msr |= 0x4ull << (63 - 45);
+        break;
+    case POWERPC_EXCP_EXTERNAL:
+        *msr |= 0x8ull << (63 - 45);
+        break;
+    case POWERPC_EXCP_DECR:
+        *msr |= 0x6ull << (63 - 45);
+        break;
+    case POWERPC_EXCP_SDOOR:
+        *msr |= 0x5ull << (63 - 45);
+        break;
+    case POWERPC_EXCP_SDOOR_HV:
+        *msr |= 0x3ull << (63 - 45);
+        break;
+    case POWERPC_EXCP_HV_MAINT:
+        *msr |= 0xaull << (63 - 45);
+        break;
+    case POWERPC_EXCP_HVIRT:
+        *msr |= 0x9ull << (63 - 45);
+        break;
+    default:
+        cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
+                  excp);
+    }
+    return POWERPC_EXCP_RESET;
+}
+
+
 /* Note that this function should be greatly optimized
  * when called with a constant excp, from ppc_hw_interrupt
  */
@@ -97,47 +140,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     asrr0 = -1;
     asrr1 = -1;
 
-    /* check for special resume at 0x100 from doze/nap/sleep/winkle on P7/P8 */
-    if (env->in_pm_state) {
-        env->in_pm_state = false;
-
-        /* Pretend to be returning from doze always as we don't lose state */
-        msr |= (0x1ull << (63 - 47));
-
-        /* Non-machine check are routed to 0x100 with a wakeup cause
-         * encoded in SRR1
-         */
-        if (excp != POWERPC_EXCP_MCHECK) {
-            switch (excp) {
-            case POWERPC_EXCP_RESET:
-                msr |= 0x4ull << (63 - 45);
-                break;
-            case POWERPC_EXCP_EXTERNAL:
-                msr |= 0x8ull << (63 - 45);
-                break;
-            case POWERPC_EXCP_DECR:
-                msr |= 0x6ull << (63 - 45);
-                break;
-            case POWERPC_EXCP_SDOOR:
-                msr |= 0x5ull << (63 - 45);
-                break;
-            case POWERPC_EXCP_SDOOR_HV:
-                msr |= 0x3ull << (63 - 45);
-                break;
-            case POWERPC_EXCP_HV_MAINT:
-                msr |= 0xaull << (63 - 45);
-                break;
-            default:
-                cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
-                          excp);
-            }
-            excp = POWERPC_EXCP_RESET;
-        }
+    /*
+     * check for special resume at 0x100 from doze/nap/sleep/winkle on
+     * P7/P8/P9
+     */
+    if (env->resume_as_sreset) {
+        excp = powerpc_reset_wakeup(cs, env, excp, &msr);
     }
 
     /* Exception targetting modifiers
      *
-     * LPES0 is supported on POWER7/8
+     * LPES0 is supported on POWER7/8/9
      * LPES1 is not supported (old iSeries mode)
      *
      * On anything else, we behave as if LPES0 is 1
@@ -148,9 +161,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
      */
 #if defined(TARGET_PPC64)
     if (excp_model == POWERPC_EXCP_POWER7 ||
-        excp_model == POWERPC_EXCP_POWER8) {
+        excp_model == POWERPC_EXCP_POWER8 ||
+        excp_model == POWERPC_EXCP_POWER9) {
         lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
-        if (excp_model == POWERPC_EXCP_POWER8) {
+        if (excp_model != POWERPC_EXCP_POWER7) {
             ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
         } else {
             ail = 0;
@@ -416,6 +430,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
     case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
     case POWERPC_EXCP_HV_EMU:
+    case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
         srr0 = SPR_HSRR0;
         srr1 = SPR_HSRR1;
         new_msr |= (target_ulong)MSR_HVB;
@@ -652,7 +667,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
         }
     } else if (excp_model == POWERPC_EXCP_POWER8) {
         if (new_msr & MSR_HVB) {
-            if (env->spr[SPR_HID0] & (HID0_HILE | HID0_POWER9_HILE)) {
+            if (env->spr[SPR_HID0] & HID0_HILE) {
+                new_msr |= (target_ulong)1 << MSR_LE;
+            }
+        } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
+            new_msr |= (target_ulong)1 << MSR_LE;
+        }
+    } else if (excp_model == POWERPC_EXCP_POWER9) {
+        if (new_msr & MSR_HVB) {
+            if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
                 new_msr |= (target_ulong)1 << MSR_LE;
             }
         } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
@@ -748,6 +771,7 @@ void ppc_cpu_do_interrupt(CPUState *cs)
 static void ppc_hw_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    bool async_deliver;
 
     /* External reset */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
@@ -769,21 +793,44 @@ static void ppc_hw_interrupt(CPUPPCState *env)
         return;
     }
 #endif
+
+    /*
+     * For interrupts that gate on MSR:EE, we need to do something a
+     * bit more subtle, as we need to let them through even when EE is
+     * clear when coming out of some power management states (in order
+     * for them to become a 0x100).
+     */
+    async_deliver = (msr_ee != 0) || env->resume_as_sreset;
+
     /* Hypervisor decrementer exception */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
         /* LPCR will be clear when not supported so this will work */
         bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
-        if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+        if ((async_deliver || msr_hv == 0) && hdice) {
             /* HDEC clears on delivery */
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
             return;
         }
     }
-    /* Extermal interrupt can ignore MSR:EE under some circumstances */
+
+    /* Hypervisor virtualization interrupt */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
+        /* LPCR will be clear when not supported so this will work */
+        bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
+        if ((async_deliver || msr_hv == 0) && hvice) {
+            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
+            return;
+        }
+    }
+
+    /* External interrupt can ignore MSR:EE under some circumstances */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
         bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
-        if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
+        bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+        /* HEIC blocks delivery to the hypervisor */
+        if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
+            (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
             return;
         }
@@ -795,7 +842,7 @@ static void ppc_hw_interrupt(CPUPPCState *env)
             return;
         }
     }
-    if (msr_ee != 0) {
+    if (async_deliver != 0) {
         /* Watchdog timer on embedded PowerPC */
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
@@ -849,6 +896,22 @@ static void ppc_hw_interrupt(CPUPPCState *env)
             return;
         }
     }
+
+    if (env->resume_as_sreset) {
+        /*
+         * This is a bug ! It means that has_work took us out of halt without
+         * anything to deliver while in a PM state that requires getting
+         * out via a 0x100
+         *
+         * This means we will incorrectly execute past the power management
+         * instruction instead of triggering a reset.
+         *
+         * It generally means a discrepancy between the wakup conditions in the
+         * processor has_work implementation and the logic in this function.
+         */
+        cpu_abort(CPU(ppc_env_get_cpu(env)),
+                  "Wakeup from PM state but interrupt Undelivered");
+    }
 }
 
 void ppc_cpu_do_system_reset(CPUState *cs)
@@ -943,22 +1006,15 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
 
     cs = CPU(ppc_env_get_cpu(env));
     cs->halted = 1;
-    env->in_pm_state = true;
 
     /* The architecture specifies that HDEC interrupts are
      * discarded in PM states
      */
     env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
 
-    /* Technically, nap doesn't set EE, but if we don't set it
-     * then ppc_hw_interrupt() won't deliver. We could add some
-     * other tests there based on LPCR but it's simpler to just
-     * whack EE in. It will be cleared by the 0x100 at wakeup
-     * anyway. It will still be observable by the guest in SRR1
-     * but this doesn't seem to be a problem.
-     */
-    env->msr |= (1ull << MSR_EE);
-    raise_exception(env, EXCP_HLT);
+    /* Condition for waking up at 0x100 */
+    env->resume_as_sreset = (insn != PPC_PM_STOP) ||
+        (env->spr[SPR_PSSCR] & PSSCR_EC);
 }
 #endif /* defined(TARGET_PPC64) */
 
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 18910d18a4..638a6e99c4 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -689,6 +689,7 @@ DEF_HELPER_2(store_ptcr, void, env, tl)
 #endif
 DEF_HELPER_2(store_sdr1, void, env, tl)
 DEF_HELPER_2(store_pidr, void, env, tl)
+DEF_HELPER_2(store_lpidr, void, env, tl)
 DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl)
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 5efd18049e..a2205e1044 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -174,26 +174,19 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
 static inline void check_tlb_flush(CPUPPCState *env, bool global)
 {
     CPUState *cs = CPU(ppc_env_get_cpu(env));
-    if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
-        tlb_flush(cs);
-        env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
-    }
 
-    /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
-     * TLB invalidation instructions.
-     */
+    /* Handle global flushes first */
     if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
-        CPUState *other_cs;
-        CPU_FOREACH(other_cs) {
-            if (other_cs != cs) {
-                PowerPCCPU *cpu = POWERPC_CPU(other_cs);
-                CPUPPCState *other_env = &cpu->env;
-
-                other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
-                tlb_flush(other_cs);
-            }
-        }
         env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
+        env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+        tlb_flush_all_cpus_synced(cs);
+        return;
+    }
+
+    /* Then handle local ones */
+    if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
+        env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+        tlb_flush(cs);
     }
 }
 #else
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index b884930096..c65d1ade15 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -117,6 +117,21 @@ void helper_store_pidr(CPUPPCState *env, target_ulong val)
     tlb_flush(CPU(cpu));
 }
 
+void helper_store_lpidr(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->spr[SPR_LPIDR] = val;
+
+    /*
+     * We need to flush the TLB on LPID changes as we only tag HV vs
+     * guest in TCG TLB. Also the quadrants means the HV will
+     * potentially access and cache entries for the current LPID as
+     * well.
+     */
+    tlb_flush(CPU(cpu));
+}
+
 void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
 {
     target_ulong hid0;
diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
index b60df4408f..32b8c166b5 100644
--- a/target/ppc/mmu-book3s-v3.c
+++ b/target/ppc/mmu-book3s-v3.c
@@ -26,9 +26,36 @@
 int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
                               int mmu_idx)
 {
-    if (ppc64_radix_guest(cpu)) { /* Guest uses radix */
+    if (ppc64_v3_radix(cpu)) { /* Guest uses radix */
         return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
     } else { /* Guest uses hash */
         return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
     }
 }
+
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr)
+{
+    if (ppc64_v3_radix(cpu)) {
+        return ppc_radix64_get_phys_page_debug(cpu, eaddr);
+    } else {
+        return ppc_hash64_get_phys_page_debug(cpu, eaddr);
+    }
+}
+
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
+{
+    uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
+    uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
+
+    /* Calculate number of entries */
+    pats = 1ull << (pats + 12 - 4);
+    if (pats <= lpid) {
+        return false;
+    }
+
+    /* Grab entry */
+    patb += 16 * lpid;
+    entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
+    entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
+    return true;
+}
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index fdf80987d7..ee8288e32d 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -17,8 +17,10 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef MMU_H
-#define MMU_H
+#ifndef MMU_BOOOK3S_V3_H
+#define MMU_BOOOK3S_V3_H
+
+#include "mmu-hash64.h"
 
 #ifndef CONFIG_USER_ONLY
 
@@ -29,7 +31,16 @@
 #define PTCR_PATS               0x000000000000001FULL /* Partition Table Size */
 
 /* Partition Table Entry Fields */
-#define PATBE1_GR 0x8000000000000000
+#define PATE0_HR 0x8000000000000000
+
+/*
+ * WARNING: This field doesn't actually exist in the final version of
+ * the architecture and is unused by hardware. However, qemu uses it
+ * as an indication of a radix guest in the pseudo-PATB entry that it
+ * maintains for SPAPR guests and in the migration stream, so we need
+ * to keep it around
+ */
+#define PATE1_GR 0x8000000000000000
 
 /* Process Table Entry */
 struct prtb_entry {
@@ -43,19 +54,68 @@ static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu)
     return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
 }
 
-static inline bool ppc64_radix_guest(PowerPCCPU *cpu)
-{
-    PPCVirtualHypervisorClass *vhc =
-        PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
+                       ppc_v3_pate_t *entry);
 
-    return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR);
+/*
+ * The LPCR:HR bit is a shortcut that avoids having to
+ * dig out the partition table in the fast path. This is
+ * also how the HW uses it.
+ */
+static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
+{
+    return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
 }
 
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr);
+
 int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
                               int mmu_idx);
 
+static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
+{
+    uint64_t base;
+
+    if (cpu->vhyp) {
+        return 0;
+    }
+    if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+        ppc_v3_pate_t pate;
+
+        if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+            return 0;
+        }
+        base = pate.dw0;
+    } else {
+        base = cpu->env.spr[SPR_SDR1];
+    }
+    return base & SDR_64_HTABORG;
+}
+
+static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
+{
+    uint64_t base;
+
+    if (cpu->vhyp) {
+        PPCVirtualHypervisorClass *vhc =
+            PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+        return vhc->hpt_mask(cpu->vhyp);
+    }
+    if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+        ppc_v3_pate_t pate;
+
+        if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+            return 0;
+        }
+        base = pate.dw0;
+    } else {
+        base = cpu->env.spr[SPR_SDR1];
+    }
+    return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
+}
+
 #endif /* TARGET_PPC64 */
 
 #endif /* CONFIG_USER_ONLY */
 
-#endif /* MMU_H */
+#endif /* MMU_BOOOK3S_V3_H */
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 03ae3c1279..e8562a7c87 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -319,6 +319,12 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
 
     for (i = 0; i < HPTES_PER_GROUP; i++) {
         pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
+        /*
+         * pte0 contains the valid bit and must be read before pte1,
+         * otherwise we might see an old pte1 with a new valid bit and
+         * thus an inconsistent hpte value
+         */
+        smp_rmb();
         pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
 
         if ((pte0 & HPTE32_V_VALID)
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 276d9015e7..c431303eff 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -417,7 +417,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
                                              hwaddr ptex, int n)
 {
     hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
-    hwaddr base = ppc_hash64_hpt_base(cpu);
+    hwaddr base;
     hwaddr plen = n * HASH_PTE_SIZE_64;
     const ppc_hash_pte64_t *hptes;
 
@@ -426,6 +426,7 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
             PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
         return vhc->map_hptes(cpu->vhyp, ptex, n);
     }
+    base = ppc_hash64_hpt_base(cpu);
 
     if (!base) {
         return NULL;
@@ -490,6 +491,18 @@ static unsigned hpte_page_shift(const PPCHash64SegmentPageSizes *sps,
     return 0; /* Bad page size encoding */
 }
 
+static void ppc64_v3_new_to_old_hpte(target_ulong *pte0, target_ulong *pte1)
+{
+    /* Insert B into pte0 */
+    *pte0 = (*pte0 & HPTE64_V_COMMON_BITS) |
+            ((*pte1 & HPTE64_R_3_0_SSIZE_MASK) <<
+             (HPTE64_V_SSIZE_SHIFT - HPTE64_R_3_0_SSIZE_SHIFT));
+
+    /* Remove B from pte1 */
+    *pte1 = *pte1 & ~HPTE64_R_3_0_SSIZE_MASK;
+}
+
+
 static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
                                      const PPCHash64SegmentPageSizes *sps,
                                      target_ulong ptem,
@@ -507,8 +520,19 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
     }
     for (i = 0; i < HPTES_PER_GROUP; i++) {
         pte0 = ppc_hash64_hpte0(cpu, pteg, i);
+        /*
+         * pte0 contains the valid bit and must be read before pte1,
+         * otherwise we might see an old pte1 with a new valid bit and
+         * thus an inconsistent hpte value
+         */
+        smp_rmb();
         pte1 = ppc_hash64_hpte1(cpu, pteg, i);
 
+        /* Convert format if necessary */
+        if (cpu->env.mmu_model == POWERPC_MMU_3_00 && !cpu->vhyp) {
+            ppc64_v3_new_to_old_hpte(&pte0, &pte1);
+        }
+
         /* This compares V, B, H (secondary) and the AVPN */
         if (HPTE64_V_COMPARE(pte0, ptem)) {
             *pshift = hpte_page_shift(sps, pte0, pte1);
@@ -918,7 +942,7 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
 void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
                            uint64_t pte0, uint64_t pte1)
 {
-    hwaddr base = ppc_hash64_hpt_base(cpu);
+    hwaddr base;
     hwaddr offset = ptex * HASH_PTE_SIZE_64;
 
     if (cpu->vhyp) {
@@ -927,6 +951,7 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
         vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
         return;
     }
+    base = ppc_hash64_hpt_base(cpu);
 
     stq_phys(CPU(cpu)->as, base + offset, pte0);
     stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
@@ -1084,10 +1109,18 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
     case POWERPC_MMU_3_00: /* P9 */
         lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
                       (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
-                      LPCR_UPRT | LPCR_EVIRT | LPCR_ONL |
+                      LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR |
                       (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
                       LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
                       LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
+        /*
+         * If we have a virtual hypervisor, we need to bring back RMLS. It
+         * doesn't exist on an actual P9 but that's all we know how to
+         * configure with softmmu at the moment
+         */
+        if (cpu->vhyp) {
+            lpcr |= (val & LPCR_RMLS);
+        }
         break;
     default:
         ;
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index f11efc9cbc..6b555b7220 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -63,6 +63,7 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
 #define SDR_64_HTABORG         0x0FFFFFFFFFFC0000ULL
 #define SDR_64_HTABSIZE        0x000000000000001FULL
 
+#define PATE0_HTABORG           0x0FFFFFFFFFFC0000ULL
 #define HPTES_PER_GROUP         8
 #define HASH_PTE_SIZE_64        16
 #define HASH_PTEG_SIZE_64       (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
@@ -102,23 +103,10 @@ void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
 #define HPTE64_V_1TB_SEG        0x4000000000000000ULL
 #define HPTE64_V_VRMA_MASK      0x4001ffffff000000ULL
 
-static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
-{
-    if (cpu->vhyp) {
-        return 0;
-    }
-    return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
-}
-
-static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
-{
-    if (cpu->vhyp) {
-        PPCVirtualHypervisorClass *vhc =
-            PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
-        return vhc->hpt_mask(cpu->vhyp);
-    }
-    return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1;
-}
+/* Format changes for ARCH v3 */
+#define HPTE64_V_COMMON_BITS    0x000fffffffffffffULL
+#define HPTE64_R_3_0_SSIZE_SHIFT 58
+#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT)
 
 struct ppc_hash_pte64 {
     uint64_t pte0, pte1;
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index ab76cbc835..ca1fb2673f 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -31,10 +31,26 @@
 static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
                                                  uint64_t *lpid, uint64_t *pid)
 {
-    /* We don't have HV support yet and shouldn't get here with it set anyway */
-    assert(!msr_hv);
-
-    if (!msr_hv) { /* !MSR[HV] -> Guest */
+    if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
+        switch (eaddr & R_EADDR_QUADRANT) {
+        case R_EADDR_QUADRANT0:
+            *lpid = 0;
+            *pid = env->spr[SPR_BOOKS_PID];
+            break;
+        case R_EADDR_QUADRANT1:
+            *lpid = env->spr[SPR_LPIDR];
+            *pid = env->spr[SPR_BOOKS_PID];
+            break;
+        case R_EADDR_QUADRANT2:
+            *lpid = env->spr[SPR_LPIDR];
+            *pid = 0;
+            break;
+        case R_EADDR_QUADRANT3:
+            *lpid = 0;
+            *pid = 0;
+            break;
+        }
+    } else {  /* !MSR[HV] -> Guest */
         switch (eaddr & R_EADDR_QUADRANT) {
         case R_EADDR_QUADRANT0: /* Guest application */
             *lpid = env->spr[SPR_LPIDR];
@@ -186,20 +202,32 @@ static uint64_t ppc_radix64_walk_tree(PowerPCCPU *cpu, vaddr eaddr,
                                  raddr, psize, fault_cause, pte_addr);
 }
 
+static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate)
+{
+    CPUPPCState *env = &cpu->env;
+
+    if (!(pate->dw0 & PATE0_HR)) {
+        return false;
+    }
+    if (lpid == 0 && !msr_hv) {
+        return false;
+    }
+    /* More checks ... */
+    return true;
+}
+
 int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
                                  int mmu_idx)
 {
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
-    PPCVirtualHypervisorClass *vhc =
-        PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+    PPCVirtualHypervisorClass *vhc;
     hwaddr raddr, pte_addr;
-    uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+    uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
     int page_size, prot, fault_cause = 0;
+    ppc_v3_pate_t pate;
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
-    assert(!msr_hv); /* For now there is no Radix PowerNV Support */
-    assert(cpu->vhyp);
     assert(ppc64_use_proc_tbl(cpu));
 
     /* Real Mode Access */
@@ -220,17 +248,33 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
     }
 
     /* Get Process Table */
-    patbe = vhc->get_patbe(cpu->vhyp);
+    if (cpu->vhyp) {
+        vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+        vhc->get_pate(cpu->vhyp, &pate);
+    } else {
+        if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+            ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
+            return 1;
+        }
+        if (!validate_pate(cpu, lpid, &pate)) {
+            ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
+        }
+        /* We don't support guest mode yet */
+        if (lpid != 0) {
+            error_report("PowerNV guest support Unimplemented");
+            exit(1);
+       }
+    }
 
     /* Index Process Table by PID to Find Corresponding Process Table Entry */
     offset = pid * sizeof(struct prtb_entry);
-    size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+    size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
     if (offset >= size) {
         /* offset exceeds size of the process table */
         ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
         return 1;
     }
-    prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+    prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
 
     /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
     page_size = PRTBE_R_GET_RTS(prtbe0);
@@ -255,11 +299,11 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
 {
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
-    PPCVirtualHypervisorClass *vhc =
-        PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+    PPCVirtualHypervisorClass *vhc;
     hwaddr raddr, pte_addr;
-    uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+    uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
     int page_size, fault_cause = 0;
+    ppc_v3_pate_t pate;
 
     /* Handle Real Mode */
     if (msr_dr == 0) {
@@ -273,16 +317,31 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
     }
 
     /* Get Process Table */
-    patbe = vhc->get_patbe(cpu->vhyp);
+    if (cpu->vhyp) {
+        vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+        vhc->get_pate(cpu->vhyp, &pate);
+    } else {
+        if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+            return -1;
+        }
+        if (!validate_pate(cpu, lpid, &pate)) {
+            return -1;
+        }
+        /* We don't support guest mode yet */
+        if (lpid != 0) {
+            error_report("PowerNV guest support Unimplemented");
+            exit(1);
+       }
+    }
 
     /* Index Process Table by PID to Find Corresponding Process Table Entry */
     offset = pid * sizeof(struct prtb_entry);
-    size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+    size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
     if (offset >= size) {
         /* offset exceeds size of the process table */
         return -1;
     }
-    prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+    prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
 
     /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
     page_size = PRTBE_R_GET_RTS(prtbe0);
diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h
index 0ecf063a17..96228546aa 100644
--- a/target/ppc/mmu-radix64.h
+++ b/target/ppc/mmu-radix64.h
@@ -12,8 +12,8 @@
 #define R_EADDR_QUADRANT3       0xC000000000000000
 
 /* Radix Partition Table Entry Fields */
-#define PATBE1_R_PRTB           0x0FFFFFFFFFFFF000
-#define PATBE1_R_PRTS           0x000000000000001F
+#define PATE1_R_PRTB           0x0FFFFFFFFFFFF000
+#define PATE1_R_PRTS           0x000000000000001F
 
 /* Radix Process Table Entry Fields */
 #define PRTBE_R_GET_RTS(rts) \
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index bcf19da61d..4a6be4d63b 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1342,7 +1342,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
         dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
         break;
     case POWERPC_MMU_3_00:
-        if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
+        if (ppc64_v3_radix(ppc_env_get_cpu(env))) {
             /* TODO - Unsupported */
         } else {
             dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
@@ -1489,12 +1489,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     case POWERPC_MMU_2_07:
         return ppc_hash64_get_phys_page_debug(cpu, addr);
     case POWERPC_MMU_3_00:
-        if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
-            return ppc_radix64_get_phys_page_debug(cpu, addr);
-        } else {
-            return ppc_hash64_get_phys_page_debug(cpu, addr);
-        }
-        break;
+        return ppc64_v3_get_phys_page_debug(cpu, addr);
 #endif
 
     case POWERPC_MMU_32B:
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index f4d70e725a..819221f246 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3566,7 +3566,8 @@ static void gen_doze(DisasContext *ctx)
     t = tcg_const_i32(PPC_PM_DOZE);
     gen_helper_pminsn(cpu_env, t);
     tcg_temp_free_i32(t);
-    gen_stop_exception(ctx);
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -3581,13 +3582,25 @@ static void gen_nap(DisasContext *ctx)
     t = tcg_const_i32(PPC_PM_NAP);
     gen_helper_pminsn(cpu_env, t);
     tcg_temp_free_i32(t);
-    gen_stop_exception(ctx);
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
 static void gen_stop(DisasContext *ctx)
 {
-    gen_nap(ctx);
+#if defined(CONFIG_USER_ONLY)
+    GEN_PRIV;
+#else
+    TCGv_i32 t;
+
+    CHK_HV;
+    t = tcg_const_i32(PPC_PM_STOP);
+    gen_helper_pminsn(cpu_env, t);
+    tcg_temp_free_i32(t);
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
+#endif /* defined(CONFIG_USER_ONLY) */
 }
 
 static void gen_sleep(DisasContext *ctx)
@@ -3601,7 +3614,8 @@ static void gen_sleep(DisasContext *ctx)
     t = tcg_const_i32(PPC_PM_SLEEP);
     gen_helper_pminsn(cpu_env, t);
     tcg_temp_free_i32(t);
-    gen_stop_exception(ctx);
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -3616,7 +3630,8 @@ static void gen_rvwinkle(DisasContext *ctx)
     t = tcg_const_i32(PPC_PM_RVWINKLE);
     gen_helper_pminsn(cpu_env, t);
     tcg_temp_free_i32(t);
-    gen_stop_exception(ctx);
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 #endif /* #if defined(TARGET_PPC64) */
@@ -7466,7 +7481,8 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
 #if defined(TARGET_PPC64)
     if (env->excp_model == POWERPC_EXCP_POWER7 ||
-        env->excp_model == POWERPC_EXCP_POWER8) {
+        env->excp_model == POWERPC_EXCP_POWER8 ||
+        env->excp_model == POWERPC_EXCP_POWER9)  {
         cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
                     env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
     }
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index d884906004..58542c0fe0 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -408,6 +408,11 @@ static void spr_write_pidr(DisasContext *ctx, int sprn, int gprn)
     gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]);
 }
 
+static void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn)
+{
+    gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]);
+}
+
 static void spr_read_hior(DisasContext *ctx, int gprn, int sprn)
 {
     tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
@@ -3313,6 +3318,15 @@ static void init_excp_POWER8(CPUPPCState *env)
 #endif
 }
 
+static void init_excp_POWER9(CPUPPCState *env)
+{
+    init_excp_POWER8(env);
+
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_HVIRT]    = 0x00000EA0;
+#endif
+}
+
 #endif
 
 /*****************************************************************************/
@@ -7876,7 +7890,7 @@ static void gen_spr_book3s_ids(CPUPPCState *env)
     spr_register_hv(env, SPR_LPIDR, "LPIDR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_lpidr,
                  0x00000000);
     spr_register_hv(env, SPR_HFSCR, "HFSCR",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -8783,8 +8797,8 @@ static void init_proc_POWER9(CPUPPCState *env)
     env->icache_line_size = 128;
 
     /* Allocate hardware IRQ controller */
-    init_excp_POWER8(env);
-    ppcPOWER7_irq_init(ppc_env_get_cpu(env));
+    init_excp_POWER9(env);
+    ppcPOWER9_irq_init(ppc_env_get_cpu(env));
 }
 
 static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr)
@@ -8801,13 +8815,23 @@ static bool cpu_has_work_POWER9(CPUState *cs)
     CPUPPCState *env = &cpu->env;
 
     if (cs->halted) {
+        uint64_t psscr = env->spr[SPR_PSSCR];
+
         if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
             return false;
         }
+
+        /* If EC is clear, just return true on any pending interrupt */
+        if (!(psscr & PSSCR_EC)) {
+            return true;
+        }
         /* External Exception */
         if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
             (env->spr[SPR_LPCR] & LPCR_EEE)) {
-            return true;
+            bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+            if (heic == 0 || !msr_hv || msr_pr) {
+                return true;
+            }
         }
         /* Decrementer Exception */
         if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) &&
@@ -8829,6 +8853,11 @@ static bool cpu_has_work_POWER9(CPUState *cs)
             (env->spr[SPR_LPCR] & LPCR_HDEE)) {
             return true;
         }
+        /* Hypervisor virtualization exception */
+        if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) &&
+            (env->spr[SPR_LPCR] & LPCR_HVEE)) {
+            return true;
+        }
         if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) {
             return true;
         }
@@ -8898,8 +8927,8 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
     pcc->hash64_opts = &ppc_hash64_opts_POWER7;
     pcc->radix_page_info = &POWER9_radix_page_info;
 #endif
-    pcc->excp_model = POWERPC_EXCP_POWER8;
-    pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
+    pcc->excp_model = POWERPC_EXCP_POWER9;
+    pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
     pcc->bfd_mach = bfd_mach_ppc64;
     pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
                  POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c
index 307ad61aee..0e467bf2b6 100644
--- a/target/s390x/cc_helper.c
+++ b/target/s390x/cc_helper.c
@@ -397,6 +397,11 @@ static uint32_t cc_calc_flogr(uint64_t dst)
     return dst ? 2 : 0;
 }
 
+static uint32_t cc_calc_lcbb(uint64_t dst)
+{
+    return dst == 16 ? 0 : 3;
+}
+
 static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                   uint64_t src, uint64_t dst, uint64_t vr)
 {
@@ -506,6 +511,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
     case CC_OP_FLOGR:
         r = cc_calc_flogr(dst);
         break;
+    case CC_OP_LCBB:
+        r = cc_calc_lcbb(dst);
+        break;
 
     case CC_OP_NZ_F32:
         r = set_cc_nz_f32(dst);
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index a758649f47..f84bfb1284 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -347,10 +347,41 @@ static void do_io_interrupt(CPUS390XState *env)
     load_psw(env, mask, addr);
 }
 
+typedef struct MchkExtSaveArea {
+    uint64_t    vregs[32][2];                     /* 0x0000 */
+    uint8_t     pad_0x0200[0x0400 - 0x0200];      /* 0x0200 */
+} MchkExtSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
+
+static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
+{
+    hwaddr len = sizeof(MchkExtSaveArea);
+    MchkExtSaveArea *sa;
+    int i;
+
+    sa = cpu_physical_memory_map(mcesao, &len, 1);
+    if (!sa) {
+        return -EFAULT;
+    }
+    if (len != sizeof(MchkExtSaveArea)) {
+        cpu_physical_memory_unmap(sa, len, 1, 0);
+        return -EFAULT;
+    }
+
+    for (i = 0; i < 32; i++) {
+        sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0].ll);
+        sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1].ll);
+    }
+
+    cpu_physical_memory_unmap(sa, len, 1, len);
+    return 0;
+}
+
 static void do_mchk_interrupt(CPUS390XState *env)
 {
     QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
-    uint64_t mask, addr;
+    uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
+    uint64_t mask, addr, mcesao = 0;
     LowCore *lowcore;
     int i;
 
@@ -362,6 +393,17 @@ static void do_mchk_interrupt(CPUS390XState *env)
 
     lowcore = cpu_map_lowcore(env);
 
+    /* extended save area */
+    if (mcic & MCIC_VB_VR) {
+        /* length and alignment is 1024 bytes */
+        mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
+    }
+
+    /* try to store vector registers */
+    if (!mcesao || mchk_store_vregs(env, mcesao)) {
+        mcic &= ~MCIC_VB_VR;
+    }
+
     /* we are always in z/Architecture mode */
     lowcore->ar_access_id = 1;
 
@@ -377,7 +419,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
     lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
     lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
 
-    lowcore->mcic = cpu_to_be64(s390_build_validity_mcic() | MCIC_SC_CP);
+    lowcore->mcic = cpu_to_be64(mcic);
     lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
     lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
     mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e921172bc4..1be68bafea 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -36,13 +36,21 @@
 
 #define RET128(F) (env->retxl = F.low, F.high)
 
-#define convert_bit(mask, from, to) \
-    (to < from                      \
-     ? (mask / (from / to)) & to    \
-     : (mask & from) * (to / from))
+uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
+{
+    uint8_t s390_exc = 0;
+
+    s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0;
+    s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
+    s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
+    s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
+    s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
+
+    return s390_exc;
+}
 
 /* Should be called after any operation that may raise IEEE exceptions.  */
-static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr)
 {
     unsigned s390_exc, qemu_exc;
 
@@ -53,22 +61,54 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
         return;
     }
     env->fpu_status.float_exception_flags = 0;
+    s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
+
+    /*
+     * IEEE-Underflow exception recognition exists if a tininess condition
+     * (underflow) exists and
+     * - The mask bit in the FPC is zero and the result is inexact
+     * - The mask bit in the FPC is one
+     * So tininess conditions that are not inexact don't trigger any
+     * underflow action in case the mask bit is not one.
+     */
+    if (!(s390_exc & S390_IEEE_MASK_INEXACT) &&
+        !((env->fpc >> 24) & S390_IEEE_MASK_UNDERFLOW)) {
+        s390_exc &= ~S390_IEEE_MASK_UNDERFLOW;
+    }
 
-    /* Convert softfloat exception bits to s390 exception bits.  */
-    s390_exc = 0;
-    s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
-    s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
-    s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
-    s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
-    s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
-
-    /* Install the exceptions that we raised.  */
-    env->fpc |= s390_exc << 16;
+    /*
+     * FIXME:
+     * 1. Right now, all inexact conditions are inidicated as
+     *    "truncated" (0) and never as "incremented" (1) in the DXC.
+     * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
+     *    are completing, meaning the target register has to be written!
+     *    This, however will mean that we have to write the register before
+     *    triggering the trap - impossible right now.
+     */
+
+    /*
+     * invalid/divbyzero cannot coexist with other conditions.
+     * overflow/underflow however can coexist with inexact, we have to
+     * handle it separatly.
+     */
+    if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
+        if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+            /* trap condition - inexact reported along */
+            tcg_s390_data_exception(env, s390_exc, retaddr);
+        }
+        /* nontrap condition - inexact handled differently */
+        env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
+    }
 
-    /* Send signals for enabled exceptions.  */
-    s390_exc &= env->fpc >> 24;
-    if (s390_exc) {
-        tcg_s390_data_exception(env, s390_exc, retaddr);
+    /* inexact handling */
+    if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
+        /* trap condition - overflow/underflow _not_ reported along */
+        if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+            tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
+                                    retaddr);
+        }
+        /* nontrap condition */
+        env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
     }
 }
 
@@ -130,11 +170,22 @@ uint32_t set_cc_nz_f128(float128 v)
     }
 }
 
+static inline uint8_t round_from_m34(uint32_t m34)
+{
+    return extract32(m34, 0, 4);
+}
+
+static inline bool xxc_from_m34(uint32_t m34)
+{
+    /* XxC is bit 1 of m4 */
+    return extract32(m34, 4 + 3 - 1, 1);
+}
+
 /* 32-bit FP addition */
 uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_add(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -142,7 +193,7 @@ uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_add(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -153,7 +204,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_add(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -161,7 +212,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_sub(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -169,7 +220,7 @@ uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_sub(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -180,7 +231,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_sub(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -188,7 +239,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_div(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -196,7 +247,7 @@ uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_div(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -207,7 +258,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_div(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -215,7 +266,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_mul(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -223,7 +274,7 @@ uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_mul(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -232,7 +283,7 @@ uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float32_to_float64(f2, &env->fpu_status);
     ret = float64_mul(f1, ret, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -243,7 +294,7 @@ uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_mul(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -253,7 +304,7 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 {
     float128 ret = float64_to_float128(f2, &env->fpu_status);
     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -261,15 +312,19 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 {
     float64 ret = float32_to_float64(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 64-bit float */
-uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
@@ -277,7 +332,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float64_to_float128(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -285,23 +340,30 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float32_to_float128(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
 /* convert 64-bit float to 32-bit float */
-uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float64_to_float32(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit float */
-uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
@@ -309,7 +371,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -317,7 +379,7 @@ uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -328,21 +390,28 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     int cmp = float128_compare_quiet(make_float128(ah, al),
                                      make_float128(bh, bl),
                                      &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
-static int swap_round_mode(CPUS390XState *env, int m3)
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
 {
     int ret = env->fpu_status.float_rounding_mode;
+
     switch (m3) {
     case 0:
         /* current mode */
         break;
     case 1:
-        /* biased round no nearest */
+        /* round to nearest with ties away from 0 */
+        set_float_rounding_mode(float_round_ties_away, &env->fpu_status);
+        break;
+    case 3:
+        /* round to prepare for shorter precision */
+        set_float_rounding_mode(float_round_to_odd, &env->fpu_status);
+        break;
     case 4:
-        /* round to nearest */
+        /* round to nearest with ties to even */
         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
         break;
     case 5:
@@ -357,226 +426,251 @@ static int swap_round_mode(CPUS390XState *env, int m3)
         /* round to -inf */
         set_float_rounding_mode(float_round_down, &env->fpu_status);
         break;
+    default:
+        g_assert_not_reached();
     }
     return ret;
 }
 
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
+{
+    set_float_rounding_mode(old_mode, &env->fpu_status);
+}
+
 /* convert 64-bit int to 32-bit float */
-uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = int64_to_float32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit int to 64-bit float */
-uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = int64_to_float64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit int to 128-bit float */
-uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = int64_to_float128(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
 /* convert 64-bit uint to 32-bit float */
-uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = uint64_to_float32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit uint to 64-bit float */
-uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = uint64_to_float64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit uint to 128-bit float */
-uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = uint64_to_float128(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
 /* convert 32-bit float to 64-bit int */
-uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int64_t ret = float32_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 64-bit int */
-uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int64_t ret = float64_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 64-bit int */
-uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 v2 = make_float128(h, l);
     int64_t ret = float128_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 32-bit int */
-uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int32_t ret = float32_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 32-bit int */
-uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int32_t ret = float64_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit int */
-uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 v2 = make_float128(h, l);
     int32_t ret = float128_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 64-bit uint */
-uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint64_t ret;
+
     v2 = float32_to_float64(v2, &env->fpu_status);
     ret = float64_to_uint64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 64-bit uint */
-uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 64-bit uint */
-uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
-    float128 v2 = make_float128(h, l);
-    /* ??? Not 100% correct.  */
-    uint64_t ret = float128_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
+    uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 32-bit uint */
-uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 32-bit uint */
-uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit uint */
-uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
-    float128 v2 = make_float128(h, l);
-    /* Not 100% correct.  */
-    uint32_t ret = float128_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
+    uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 32-bit */
-uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float32_round_to_int(f2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 64-bit */
-uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = float64_round_to_int(f2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 128-bit */
-uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
+uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = float128_round_to_int(make_float128(ah, al),
                                          &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
@@ -584,7 +678,7 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
 uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float32_compare(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -592,7 +686,7 @@ uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float64_compare(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -603,7 +697,7 @@ uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     int cmp = float128_compare(make_float128(ah, al),
                                make_float128(bh, bl),
                                &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -612,7 +706,7 @@ uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
 {
     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -621,7 +715,7 @@ uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
 {
     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -631,7 +725,7 @@ uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
 {
     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
                                  &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -641,78 +735,63 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
 {
     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
                                  &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
+/* The rightmost bit has the number 11. */
+static inline uint16_t dcmask(int bit, bool neg)
+{
+    return 1 << (11 - bit - neg);
+}
+
+#define DEF_FLOAT_DCMASK(_TYPE) \
+static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)       \
+{                                                                  \
+    const bool neg = _TYPE##_is_neg(f1);                           \
+                                                                   \
+    /* Sorted by most common cases - only one class is possible */ \
+    if (_TYPE##_is_normal(f1)) {                                   \
+        return dcmask(2, neg);                                     \
+    } else if (_TYPE##_is_zero(f1)) {                              \
+        return dcmask(0, neg);                                     \
+    } else if (_TYPE##_is_denormal(f1)) {                          \
+        return dcmask(4, neg);                                     \
+    } else if (_TYPE##_is_infinity(f1)) {                          \
+        return dcmask(6, neg);                                     \
+    } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
+        return dcmask(8, neg);                                     \
+    }                                                              \
+    /* signaling nan, as last remaining case */                    \
+    return dcmask(10, neg);                                        \
+}
+DEF_FLOAT_DCMASK(float32)
+DEF_FLOAT_DCMASK(float64)
+DEF_FLOAT_DCMASK(float128)
+
 /* test data class 32-bit */
 uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
 {
-    float32 v1 = f1;
-    int neg = float32_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float32_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+    return (m2 & float32_dcmask(env, f1)) != 0;
 }
 
 /* test data class 64-bit */
 uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
 {
-    int neg = float64_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float64_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+    return (m2 & float64_dcmask(env, v1)) != 0;
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
-                      uint64_t al, uint64_t m2)
-{
-    float128 v1 = make_float128(ah, al);
-    int neg = float128_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
+{
+    return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
 }
 
 /* square root 32-bit */
 uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
 {
     float32 ret = float32_sqrt(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -720,7 +799,7 @@ uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
 {
     float64 ret = float64_sqrt(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -728,44 +807,84 @@ uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
-static const int fpc_to_rnd[4] = {
+static const int fpc_to_rnd[8] = {
     float_round_nearest_even,
     float_round_to_zero,
     float_round_up,
-    float_round_down
+    float_round_down,
+    -1,
+    -1,
+    -1,
+    float_round_to_odd,
 };
 
 /* set fpc */
 void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
 {
+    if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+        (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
+
     /* Install everything in the main FPC.  */
     env->fpc = fpc;
 
     /* Install the rounding mode in the shadow fpu_status.  */
-    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
 }
 
 /* set fpc and signal */
-void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
 {
     uint32_t signalling = env->fpc;
-    uint32_t source = val;
     uint32_t s390_exc;
 
-    /* The contents of the source operand are placed in the FPC register;
-       then the flags in the FPC register are set to the logical OR of the
-       signalling flags and the source flags.  */
-    env->fpc = source | (signalling & 0x00ff0000);
-    set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+    if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+        (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
 
-    /* If any signalling flag is 1 and the corresponding source mask
-       is also 1, a simulated-iee-exception trap occurs.  */
-    s390_exc = (signalling >> 16) & (source >> 24);
+    /*
+     * FPC is set to the FPC operand with a bitwise OR of the signalling
+     * flags.
+     */
+    env->fpc = fpc | (signalling & 0x00ff0000);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
+
+    /*
+     * If any signaling flag is enabled in the new FPC mask, a
+     * simulated-iee-exception exception occurs.
+     */
+    s390_exc = (signalling >> 16) & (fpc >> 24);
     if (s390_exc) {
+        if (s390_exc & S390_IEEE_MASK_INVALID) {
+            s390_exc = S390_IEEE_MASK_INVALID;
+        } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
+            s390_exc = S390_IEEE_MASK_DIVBYZERO;
+        } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
+            s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
+        } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
+            s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
+        } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
+            s390_exc = S390_IEEE_MASK_INEXACT;
+        } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
+            s390_exc = S390_IEEE_MASK_QUANTUM;
+        }
         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
     }
 }
+
+/* set bfp rounding mode */
+void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
+{
+    if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
+
+    env->fpc = deposit32(env->fpc, 0, 3, rnd);
+    set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
+}
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
index 44eca45474..e4739a6b9f 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -601,6 +601,11 @@ static uint16_t qemu_V3_1[] = {
 };
 
 static uint16_t qemu_LATEST[] = {
+    /*
+     * Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not
+     * implemented yet).
+     */
+    S390_FEAT_FLOATING_POINT_EXT,
     S390_FEAT_ZPCI,
 };
 
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 3d74836a83..8e9573221c 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -211,7 +211,7 @@ void s390_cpu_recompute_watchpoints(CPUState *cs)
     }
 }
 
-struct sigp_save_area {
+typedef struct SigpSaveArea {
     uint64_t    fprs[16];                       /* 0x0000 */
     uint64_t    grs[16];                        /* 0x0080 */
     PSW         psw;                            /* 0x0100 */
@@ -225,13 +225,13 @@ struct sigp_save_area {
     uint8_t     pad_0x0138[0x0140 - 0x0138];    /* 0x0138 */
     uint32_t    ars[16];                        /* 0x0140 */
     uint64_t    crs[16];                        /* 0x0384 */
-};
-QEMU_BUILD_BUG_ON(sizeof(struct sigp_save_area) != 512);
+} SigpSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512);
 
 int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
 {
     static const uint8_t ar_id = 1;
-    struct sigp_save_area *sa;
+    SigpSaveArea *sa;
     hwaddr len = sizeof(*sa);
     int i;
 
@@ -272,32 +272,43 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
     return 0;
 }
 
-#define ADTL_GS_OFFSET   1024 /* offset of GS data in adtl save area */
+typedef struct SigpAdtlSaveArea {
+    uint64_t    vregs[32][2];                     /* 0x0000 */
+    uint8_t     pad_0x0200[0x0400 - 0x0200];      /* 0x0200 */
+    uint64_t    gscb[4];                          /* 0x0400 */
+    uint8_t     pad_0x0420[0x1000 - 0x0420];      /* 0x0420 */
+} SigpAdtlSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096);
+
 #define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */
 int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len)
 {
+    SigpAdtlSaveArea *sa;
     hwaddr save = len;
-    void *mem;
+    int i;
 
-    mem = cpu_physical_memory_map(addr, &save, 1);
-    if (!mem) {
+    sa = cpu_physical_memory_map(addr, &save, 1);
+    if (!sa) {
         return -EFAULT;
     }
     if (save != len) {
-        cpu_physical_memory_unmap(mem, len, 1, 0);
+        cpu_physical_memory_unmap(sa, len, 1, 0);
         return -EFAULT;
     }
 
-    /* FIXME: as soon as TCG supports these features, convert cpu->be */
     if (s390_has_feat(S390_FEAT_VECTOR)) {
-        memcpy(mem, &cpu->env.vregs, 512);
+        for (i = 0; i < 32; i++) {
+            sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0].ll);
+            sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1].ll);
+        }
     }
     if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) {
-        memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32);
+        for (i = 0; i < 4; i++) {
+            sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]);
+        }
     }
 
-    cpu_physical_memory_unmap(mem, len, 1, len);
-
+    cpu_physical_memory_unmap(sa, len, 1, len);
     return 0;
 }
 #endif /* CONFIG_USER_ONLY */
@@ -406,6 +417,7 @@ const char *cc_name(enum cc_op cc_op)
         [CC_OP_SLA_32]    = "CC_OP_SLA_32",
         [CC_OP_SLA_64]    = "CC_OP_SLA_64",
         [CC_OP_FLOGR]     = "CC_OP_FLOGR",
+        [CC_OP_LCBB]      = "CC_OP_LCBB",
     };
 
     return cc_names[cc_op];
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 6260b50496..bb659257f6 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -53,11 +53,11 @@ DEF_HELPER_FLAGS_3(mdb, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_4(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
 DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
 DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(ledb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(lexb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
@@ -104,8 +104,9 @@ DEF_HELPER_4(trtr, i32, env, i32, i64, i64)
 DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
+DEF_HELPER_FLAGS_2(srnm, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_2(stfle, i32, env, i64)
 DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 61582372ab..61b750a855 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -479,6 +479,8 @@
     F(0xb313, LCDBR,   RRE,   Z,   0, f2, new, f1, negf64, f64, IF_BFP)
     F(0xb343, LCXBR,   RRE,   Z,   x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
     F(0xb373, LCDFR,   RRE,   FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
+/* LOAD COUNT TO BLOCK BOUNDARY */
+    C(0xe727, LCBB,    RXE,   V,   la2, 0, r1, 0, lcbb, 0)
 /* LOAD HALFWORD */
     C(0xb927, LHR,     RRE,   EI,  0, r2_16s, 0, r1_32, mov2, 0)
     C(0xb907, LGHR,    RRE,   EI,  0, r2_16s, 0, r1, mov2, 0)
@@ -598,10 +600,12 @@
     F(0xed04, LDEB,    RXE,   Z,   0, m2_32u, new, f1, ldeb, 0, IF_BFP)
     F(0xed05, LXDB,    RXE,   Z,   0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
     F(0xed06, LXEB,    RXE,   Z,   0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
+    F(0xb324, LDER,    RXE,   Z,   0, e2, new, f1, lde, 0, IF_AFP1)
+    F(0xed24, LDE,     RXE,   Z,   0, m2_32u, new, f1, lde, 0, IF_AFP1)
 /* LOAD ROUNDED */
-    F(0xb344, LEDBR,   RRE,   Z,   0, f2, new, e1, ledb, 0, IF_BFP)
-    F(0xb345, LDXBR,   RRE,   Z,   x2h, x2l, new, f1, ldxb, 0, IF_BFP)
-    F(0xb346, LEXBR,   RRE,   Z,   x2h, x2l, new, e1, lexb, 0, IF_BFP)
+    F(0xb344, LEDBR,   RRF_e, Z,   0, f2, new, e1, ledb, 0, IF_BFP)
+    F(0xb345, LDXBR,   RRF_e, Z,   x2h, x2l, new, f1, ldxb, 0, IF_BFP)
+    F(0xb346, LEXBR,   RRF_e, Z,   x2h, x2l, new, e1, lexb, 0, IF_BFP)
 
 /* LOAD MULTIPLE */
     C(0x9800, LM,      RS_a,  Z,   0, a2, 0, 0, lm32, 0)
@@ -759,10 +763,10 @@
 /* SET FPC AND SIGNAL */
     F(0xb385, SFASR,   RRE,   IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
 /* SET BFP ROUNDING MODE */
-    F(0xb299, SRNM,    S,     Z,   0, 0, 0, 0, srnm, 0, IF_BFP)
-    F(0xb2b8, SRNMB,   S,     FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
+    F(0xb299, SRNM,    S,     Z,   la2, 0, 0, 0, srnm, 0, IF_BFP)
+    F(0xb2b8, SRNMB,   S,     FPE, la2, 0, 0, 0, srnmb, 0, IF_BFP)
 /* SET DFP ROUNDING MODE */
-    F(0xb2b9, SRNMT,   S,     DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
+    F(0xb2b9, SRNMT,   S,     DFPR, la2, 0, 0, 0, srnmt, 0, IF_DFP)
 /* SET PROGRAM MASK */
     C(0x0400, SPM,     RR_a,  Z,   r1, 0, 0, 0, spm, 0)
 
diff --git a/target/s390x/insn-format.def b/target/s390x/insn-format.def
index a412d90fb7..4297ff4165 100644
--- a/target/s390x/insn-format.def
+++ b/target/s390x/insn-format.def
@@ -36,7 +36,7 @@ F3(RSY_a, R(1, 8),     BDL(2),      R(3,12))
 F3(RSY_b, R(1, 8),     BDL(2),      M(3,12))
 F2(RX_a,  R(1, 8),     BXD(2))
 F2(RX_b,  M(1, 8),     BXD(2))
-F2(RXE,   R(1, 8),     BXD(2))
+F3(RXE,   R(1, 8),     BXD(2),      M(3,32))
 F3(RXF,   R(1,32),     BXD(2),      R(3, 8))
 F2(RXY_a, R(1, 8),     BXDL(2))
 F2(RXY_b, M(1, 8),     BXDL(2))
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index f2a771e2b4..7baf0e2404 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -101,7 +101,9 @@ typedef struct LowCore {
     /* whether the kernel died with panic() or not */
     uint32_t        panic_magic;              /* 0xe00 */
 
-    uint8_t         pad13[0x11b8 - 0xe04];    /* 0xe04 */
+    uint8_t         pad13[0x11b0 - 0xe04];    /* 0xe04 */
+
+    uint64_t        mcesad;                    /* 0x11B0 */
 
     /* 64 bit extparam used for pfault, diag 250 etc  */
     uint64_t        ext_params2;               /* 0x11B8 */
@@ -234,6 +236,7 @@ enum cc_op {
     CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
     CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
     CC_OP_FLOGR,                /* find leftmost one */
+    CC_OP_LCBB,                 /* load count to block boundary */
     CC_OP_MAX
 };
 
@@ -308,6 +311,15 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 uint32_t set_cc_nz_f128(float128 v);
+#define S390_IEEE_MASK_INVALID   0x80
+#define S390_IEEE_MASK_DIVBYZERO 0x40
+#define S390_IEEE_MASK_OVERFLOW  0x20
+#define S390_IEEE_MASK_UNDERFLOW 0x10
+#define S390_IEEE_MASK_INEXACT   0x08
+#define S390_IEEE_MASK_QUANTUM   0x04
+uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
 
 
 /* gdbstub.c */
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 19072efec6..41fb466bb4 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -145,12 +145,18 @@ void s390x_translate_init(void)
     }
 }
 
-static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
+static inline int vec_full_reg_offset(uint8_t reg)
 {
-    const uint8_t es = 1 << size;
-    int offs = enr * es;
-
     g_assert(reg < 32);
+    return offsetof(CPUS390XState, vregs[reg][0].d);
+}
+
+static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es)
+{
+    /* Convert element size (es) - e.g. MO_8 - to bytes */
+    const uint8_t bytes = 1 << es;
+    int offs = enr * bytes;
+
     /*
      * vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte
      * of the 16 byte vector, on both, little and big endian systems.
@@ -173,11 +179,11 @@ static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
      * the two 8 byte elements have to be loaded separately. Let's force all
      * 16 byte operations to handle it in a special way.
      */
-    g_assert(size <= MO_64);
+    g_assert(es <= MO_64);
 #ifndef HOST_WORDS_BIGENDIAN
-    offs ^= (8 - es);
+    offs ^= (8 - bytes);
 #endif
-    return offs + offsetof(CPUS390XState, vregs[reg][0].d);
+    return offs + vec_full_reg_offset(reg);
 }
 
 static inline int freg64_offset(uint8_t reg)
@@ -376,32 +382,43 @@ static inline void gen_trap(DisasContext *s)
     gen_data_exception(0xff);
 }
 
+static void gen_addi_and_wrap_i64(DisasContext *s, TCGv_i64 dst, TCGv_i64 src,
+                                  int64_t imm)
+{
+    tcg_gen_addi_i64(dst, src, imm);
+    if (!(s->base.tb->flags & FLAG_MASK_64)) {
+        if (s->base.tb->flags & FLAG_MASK_32) {
+            tcg_gen_andi_i64(dst, dst, 0x7fffffff);
+        } else {
+            tcg_gen_andi_i64(dst, dst, 0x00ffffff);
+        }
+    }
+}
+
 static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
 {
     TCGv_i64 tmp = tcg_temp_new_i64();
-    bool need_31 = !(s->base.tb->flags & FLAG_MASK_64);
-
-    /* Note that d2 is limited to 20 bits, signed.  If we crop negative
-       displacements early we create larger immedate addends.  */
 
-    /* Note that addi optimizes the imm==0 case.  */
+    /*
+     * Note that d2 is limited to 20 bits, signed.  If we crop negative
+     * displacements early we create larger immedate addends.
+     */
     if (b2 && x2) {
         tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
-        tcg_gen_addi_i64(tmp, tmp, d2);
+        gen_addi_and_wrap_i64(s, tmp, tmp, d2);
     } else if (b2) {
-        tcg_gen_addi_i64(tmp, regs[b2], d2);
+        gen_addi_and_wrap_i64(s, tmp, regs[b2], d2);
     } else if (x2) {
-        tcg_gen_addi_i64(tmp, regs[x2], d2);
-    } else {
-        if (need_31) {
-            d2 &= 0x7fffffff;
-            need_31 = false;
+        gen_addi_and_wrap_i64(s, tmp, regs[x2], d2);
+    } else if (!(s->base.tb->flags & FLAG_MASK_64)) {
+        if (s->base.tb->flags & FLAG_MASK_32) {
+            tcg_gen_movi_i64(tmp, d2 & 0x7fffffff);
+        } else {
+            tcg_gen_movi_i64(tmp, d2 & 0x00ffffff);
         }
+    } else {
         tcg_gen_movi_i64(tmp, d2);
     }
-    if (need_31) {
-        tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
-    }
 
     return tmp;
 }
@@ -540,6 +557,7 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_NZ_F32:
     case CC_OP_NZ_F64:
     case CC_OP_FLOGR:
+    case CC_OP_LCBB:
         /* 1 argument */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
         break;
@@ -1758,160 +1776,257 @@ static DisasJumpType op_cxb(DisasContext *s, DisasOps *o)
     return DISAS_NEXT;
 }
 
+static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe,
+                                   bool m4_with_fpe)
+{
+    const bool fpe = s390_has_feat(S390_FEAT_FLOATING_POINT_EXT);
+    uint8_t m3 = get_field(s->fields, m3);
+    uint8_t m4 = get_field(s->fields, m4);
+
+    /* m3 field was introduced with FPE */
+    if (!fpe && m3_with_fpe) {
+        m3 = 0;
+    }
+    /* m4 field was introduced with FPE */
+    if (!fpe && m4_with_fpe) {
+        m4 = 0;
+    }
+
+    /* Check for valid rounding modes. Mode 3 was introduced later. */
+    if (m3 == 2 || m3 > 7 || (!fpe && m3 == 3)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return NULL;
+    }
+
+    return tcg_const_i32(deposit32(m3, 4, 4, m4));
+}
+
 static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cegb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cegb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cegb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cdgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cxgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return_low128(o->out2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_celgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_celgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_celgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cdlgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cxlgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return_low128(o->out2);
     return DISAS_NEXT;
 }
@@ -2390,26 +2505,38 @@ static DisasJumpType op_ex(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_fieb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fieb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fieb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_fidb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fidb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fidb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_fixb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m34);
     return_low128(o->out2);
-    tcg_temp_free_i32(m3);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
@@ -2678,19 +2805,37 @@ static DisasJumpType op_ldeb(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_ledb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_ledb(o->out, cpu_env, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_ledb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_lexb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
@@ -2708,6 +2853,12 @@ static DisasJumpType op_lxeb(DisasContext *s, DisasOps *o)
     return DISAS_NEXT;
 }
 
+static DisasJumpType op_lde(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_shli_i64(o->out, o->in2, 32);
+    return DISAS_NEXT;
+}
+
 static DisasJumpType op_llgt(DisasContext *s, DisasOps *o)
 {
     tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
@@ -3119,6 +3270,23 @@ static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o)
     return DISAS_NEXT;
 }
 
+static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o)
+{
+    const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
+
+    if (get_field(s->fields, m3) > 6) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tcg_gen_ori_i64(o->addr1, o->addr1, -block_size);
+    tcg_gen_neg_i64(o->addr1, o->addr1);
+    tcg_gen_movi_i64(o->out, 16);
+    tcg_gen_umin_i64(o->out, o->out, o->addr1);
+    gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out);
+    return DISAS_NEXT;
+}
+
 static DisasJumpType op_mov2(DisasContext *s, DisasOps *o)
 {
     o->out = o->in2;
@@ -3955,41 +4123,33 @@ static DisasJumpType op_sfas(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_srnm(DisasContext *s, DisasOps *o)
 {
-    int b2 = get_field(s->fields, b2);
-    int d2 = get_field(s->fields, d2);
-    TCGv_i64 t1 = tcg_temp_new_i64();
-    TCGv_i64 t2 = tcg_temp_new_i64();
-    int mask, pos, len;
+    /* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0x3ull);
+    gen_helper_srnm(cpu_env, o->addr1);
+    return DISAS_NEXT;
+}
 
-    switch (s->fields->op2) {
-    case 0x99: /* SRNM */
-        pos = 0, len = 2;
-        break;
-    case 0xb8: /* SRNMB */
-        pos = 0, len = 3;
-        break;
-    case 0xb9: /* SRNMT */
-        pos = 4, len = 3;
-        break;
-    default:
-        tcg_abort();
-    }
-    mask = (1 << len) - 1;
+static DisasJumpType op_srnmb(DisasContext *s, DisasOps *o)
+{
+    /* Bits 0-55 are are ignored. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0xffull);
+    gen_helper_srnm(cpu_env, o->addr1);
+    return DISAS_NEXT;
+}
 
-    /* Insert the value into the appropriate field of the FPC.  */
-    if (b2 == 0) {
-        tcg_gen_movi_i64(t1, d2 & mask);
-    } else {
-        tcg_gen_addi_i64(t1, regs[b2], d2);
-        tcg_gen_andi_i64(t1, t1, mask);
-    }
-    tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
-    tcg_gen_deposit_i64(t2, t2, t1, pos, len);
-    tcg_temp_free_i64(t1);
+static DisasJumpType op_srnmt(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
 
-    /* Then install the new FPC to set the rounding mode in fpu_status.  */
-    gen_helper_sfpc(cpu_env, t2);
-    tcg_temp_free_i64(t2);
+    /* Bits other than 61-63 are ignored. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0x7ull);
+
+    /* No need to call a helper, we don't implement dfp */
+    tcg_gen_ld32u_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+    tcg_gen_deposit_i64(tmp, tmp, o->addr1, 4, 3);
+    tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+
+    tcg_temp_free_i64(tmp);
     return DISAS_NEXT;
 }
 
@@ -5908,6 +6068,7 @@ enum DisasInsnEnum {
 #define FAC_ECT         S390_FEAT_EXTRACT_CPU_TIME
 #define FAC_PCI         S390_FEAT_ZPCI /* z/PCI facility */
 #define FAC_AIS         S390_FEAT_ADAPTER_INT_SUPPRESSION
+#define FAC_V           S390_FEAT_VECTOR /* vector facility */
 
 static const DisasInsn insn_info[] = {
 #include "insn-data.def"
@@ -6091,7 +6252,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
     const DisasInsn *insn;
     DisasJumpType ret = DISAS_NEXT;
     DisasFields f;
-    DisasOps o;
+    DisasOps o = {};
 
     /* Search for the insn in the table.  */
     insn = extract_insn(env, s, &f);
@@ -6161,12 +6322,6 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
     /* Set up the strutures we use to communicate with the helpers. */
     s->insn = insn;
     s->fields = &f;
-    o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
-    o.out = NULL;
-    o.out2 = NULL;
-    o.in1 = NULL;
-    o.in2 = NULL;
-    o.addr1 = NULL;
 
     /* Implement the instruction.  */
     if (insn->help_in1) {
diff --git a/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c b/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
index ef70f80f1d..687631b8fb 100644
--- a/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
+++ b/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
@@ -24159,2627 +24159,2627 @@ Opcode_ae_sbf_Slot_inst_encode (xtensa_insnbuf slotbuf)
   slotbuf[0] = 0xe7d014;
 }
 
-xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = {
   Opcode_excw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = {
   Opcode_rfe_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = {
   Opcode_rfde_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = {
   Opcode_syscall_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = {
   Opcode_simcall_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = {
   Opcode_call12_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = {
   Opcode_call8_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = {
   Opcode_call4_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = {
   Opcode_callx12_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = {
   Opcode_callx8_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = {
   Opcode_callx4_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = {
   Opcode_entry_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = {
   Opcode_movsp_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = {
   Opcode_rotw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = {
   Opcode_retw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = {
   0, 0, Opcode_retw_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = {
   Opcode_rfwo_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = {
   Opcode_rfwu_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = {
   Opcode_l32e_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = {
   Opcode_s32e_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = {
   Opcode_rsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = {
   Opcode_wsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = {
   Opcode_xsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = {
   Opcode_rsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = {
   Opcode_wsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = {
   Opcode_xsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = {
   0, Opcode_add_n_Slot_inst16a_encode, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = {
   0, Opcode_addi_n_Slot_inst16a_encode, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = {
   0, 0, Opcode_beqz_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = {
   0, 0, Opcode_bnez_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = {
   0, 0, Opcode_ill_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = {
   0, Opcode_l32i_n_Slot_inst16a_encode, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = {
   0, 0, Opcode_mov_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = {
   0, 0, Opcode_movi_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = {
   0, 0, Opcode_nop_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = {
   0, 0, Opcode_ret_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = {
   0, Opcode_s32i_n_Slot_inst16a_encode, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = {
   Opcode_rur_threadptr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = {
   Opcode_wur_threadptr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = {
   Opcode_addi_Slot_inst_encode, 0, 0, 0, Opcode_addi_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = {
   Opcode_addmi_Slot_inst_encode, 0, 0, 0, Opcode_addmi_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_add_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_add_encode_fns[] = {
   Opcode_add_Slot_inst_encode, 0, 0, 0, Opcode_add_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = {
   Opcode_sub_Slot_inst_encode, 0, 0, 0, Opcode_sub_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = {
   Opcode_addx2_Slot_inst_encode, 0, 0, 0, Opcode_addx2_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = {
   Opcode_addx4_Slot_inst_encode, 0, 0, 0, Opcode_addx4_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = {
   Opcode_addx8_Slot_inst_encode, 0, 0, 0, Opcode_addx8_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = {
   Opcode_subx2_Slot_inst_encode, 0, 0, 0, Opcode_subx2_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = {
   Opcode_subx4_Slot_inst_encode, 0, 0, 0, Opcode_subx4_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = {
   Opcode_subx8_Slot_inst_encode, 0, 0, 0, Opcode_subx8_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_and_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_and_encode_fns[] = {
   Opcode_and_Slot_inst_encode, 0, 0, 0, Opcode_and_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_or_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_or_encode_fns[] = {
   Opcode_or_Slot_inst_encode, 0, 0, 0, Opcode_or_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = {
   Opcode_xor_Slot_inst_encode, 0, 0, 0, Opcode_xor_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = {
   Opcode_beqi_Slot_inst_encode, 0, 0, 0, Opcode_beqi_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = {
   Opcode_bnei_Slot_inst_encode, 0, 0, 0, Opcode_bnei_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = {
   Opcode_bgei_Slot_inst_encode, 0, 0, 0, Opcode_bgei_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = {
   Opcode_blti_Slot_inst_encode, 0, 0, 0, Opcode_blti_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = {
   Opcode_bbci_Slot_inst_encode, 0, 0, 0, Opcode_bbci_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = {
   Opcode_bbsi_Slot_inst_encode, 0, 0, 0, Opcode_bbsi_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = {
   Opcode_bgeui_Slot_inst_encode, 0, 0, 0, Opcode_bgeui_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = {
   Opcode_bltui_Slot_inst_encode, 0, 0, 0, Opcode_bltui_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = {
   Opcode_beq_Slot_inst_encode, 0, 0, 0, Opcode_beq_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = {
   Opcode_bne_Slot_inst_encode, 0, 0, 0, Opcode_bne_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = {
   Opcode_bge_Slot_inst_encode, 0, 0, 0, Opcode_bge_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = {
   Opcode_blt_Slot_inst_encode, 0, 0, 0, Opcode_blt_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = {
   Opcode_bgeu_Slot_inst_encode, 0, 0, 0, Opcode_bgeu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = {
   Opcode_bltu_Slot_inst_encode, 0, 0, 0, Opcode_bltu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = {
   Opcode_bany_Slot_inst_encode, 0, 0, 0, Opcode_bany_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = {
   Opcode_bnone_Slot_inst_encode, 0, 0, 0, Opcode_bnone_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = {
   Opcode_ball_Slot_inst_encode, 0, 0, 0, Opcode_ball_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = {
   Opcode_bnall_Slot_inst_encode, 0, 0, 0, Opcode_bnall_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = {
   Opcode_bbc_Slot_inst_encode, 0, 0, 0, Opcode_bbc_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = {
   Opcode_bbs_Slot_inst_encode, 0, 0, 0, Opcode_bbs_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = {
   Opcode_beqz_Slot_inst_encode, 0, 0, 0, Opcode_beqz_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = {
   Opcode_bnez_Slot_inst_encode, 0, 0, 0, Opcode_bnez_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = {
   Opcode_bgez_Slot_inst_encode, 0, 0, 0, Opcode_bgez_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = {
   Opcode_bltz_Slot_inst_encode, 0, 0, 0, Opcode_bltz_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = {
   Opcode_call0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = {
   Opcode_callx0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = {
   Opcode_extui_Slot_inst_encode, 0, 0, 0, Opcode_extui_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = {
   Opcode_ill_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_j_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_j_encode_fns[] = {
   Opcode_j_Slot_inst_encode, 0, 0, 0, Opcode_j_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = {
   Opcode_jx_Slot_inst_encode, 0, 0, 0, Opcode_jx_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = {
   Opcode_l16ui_Slot_inst_encode, 0, 0, 0, Opcode_l16ui_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = {
   Opcode_l16si_Slot_inst_encode, 0, 0, 0, Opcode_l16si_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = {
   Opcode_l32i_Slot_inst_encode, 0, 0, 0, Opcode_l32i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = {
   Opcode_l32r_Slot_inst_encode, 0, 0, 0, Opcode_l32r_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = {
   Opcode_l8ui_Slot_inst_encode, 0, 0, 0, Opcode_l8ui_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = {
   Opcode_loop_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = {
   Opcode_loopnez_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = {
   Opcode_loopgtz_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = {
   Opcode_movi_Slot_inst_encode, 0, 0, 0, Opcode_movi_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = {
   Opcode_moveqz_Slot_inst_encode, 0, 0, 0, Opcode_moveqz_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = {
   Opcode_movnez_Slot_inst_encode, 0, 0, 0, Opcode_movnez_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = {
   Opcode_movltz_Slot_inst_encode, 0, 0, 0, Opcode_movltz_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = {
   Opcode_movgez_Slot_inst_encode, 0, 0, 0, Opcode_movgez_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = {
   Opcode_neg_Slot_inst_encode, 0, 0, 0, Opcode_neg_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = {
   Opcode_abs_Slot_inst_encode, 0, 0, 0, Opcode_abs_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = {
   Opcode_nop_Slot_inst_encode, 0, 0, Opcode_nop_Slot_ae_slot1_encode, Opcode_nop_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = {
   Opcode_ret_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = {
   Opcode_s16i_Slot_inst_encode, 0, 0, 0, Opcode_s16i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = {
   Opcode_s32i_Slot_inst_encode, 0, 0, 0, Opcode_s32i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = {
   Opcode_s8i_Slot_inst_encode, 0, 0, 0, Opcode_s8i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = {
   Opcode_ssr_Slot_inst_encode, 0, 0, 0, Opcode_ssr_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = {
   Opcode_ssl_Slot_inst_encode, 0, 0, 0, Opcode_ssl_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = {
   Opcode_ssa8l_Slot_inst_encode, 0, 0, 0, Opcode_ssa8l_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = {
   Opcode_ssa8b_Slot_inst_encode, 0, 0, 0, Opcode_ssa8b_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = {
   Opcode_ssai_Slot_inst_encode, 0, 0, 0, Opcode_ssai_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = {
   Opcode_sll_Slot_inst_encode, 0, 0, 0, Opcode_sll_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_src_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_src_encode_fns[] = {
   Opcode_src_Slot_inst_encode, 0, 0, 0, Opcode_src_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = {
   Opcode_srl_Slot_inst_encode, 0, 0, 0, Opcode_srl_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = {
   Opcode_sra_Slot_inst_encode, 0, 0, 0, Opcode_sra_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = {
   Opcode_slli_Slot_inst_encode, 0, 0, 0, Opcode_slli_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = {
   Opcode_srai_Slot_inst_encode, 0, 0, 0, Opcode_srai_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = {
   Opcode_srli_Slot_inst_encode, 0, 0, 0, Opcode_srli_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = {
   Opcode_memw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = {
   Opcode_extw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = {
   Opcode_isync_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = {
   Opcode_rsync_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = {
   Opcode_esync_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = {
   Opcode_dsync_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = {
   Opcode_rsil_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = {
   Opcode_rsr_lend_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = {
   Opcode_wsr_lend_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = {
   Opcode_xsr_lend_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = {
   Opcode_rsr_lcount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = {
   Opcode_wsr_lcount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = {
   Opcode_xsr_lcount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = {
   Opcode_rsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = {
   Opcode_wsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = {
   Opcode_xsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = {
   Opcode_rsr_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = {
   Opcode_wsr_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = {
   Opcode_xsr_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = {
   Opcode_rsr_litbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = {
   Opcode_wsr_litbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = {
   Opcode_xsr_litbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_176_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_176_encode_fns[] = {
   Opcode_rsr_176_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_176_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_176_encode_fns[] = {
   Opcode_wsr_176_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_208_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_208_encode_fns[] = {
   Opcode_rsr_208_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = {
   Opcode_rsr_ps_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = {
   Opcode_wsr_ps_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = {
   Opcode_xsr_ps_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = {
   Opcode_rsr_epc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = {
   Opcode_wsr_epc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = {
   Opcode_xsr_epc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = {
   Opcode_rsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = {
   Opcode_wsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = {
   Opcode_xsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = {
   Opcode_rsr_epc2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = {
   Opcode_wsr_epc2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = {
   Opcode_xsr_epc2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = {
   Opcode_rsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = {
   Opcode_wsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = {
   Opcode_xsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = {
   Opcode_rsr_eps2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = {
   Opcode_wsr_eps2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = {
   Opcode_xsr_eps2_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = {
   Opcode_rsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = {
   Opcode_wsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = {
   Opcode_xsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = {
   Opcode_rsr_depc_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = {
   Opcode_wsr_depc_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = {
   Opcode_xsr_depc_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = {
   Opcode_rsr_exccause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = {
   Opcode_wsr_exccause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = {
   Opcode_xsr_exccause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = {
   Opcode_rsr_misc0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = {
   Opcode_wsr_misc0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = {
   Opcode_xsr_misc0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = {
   Opcode_rsr_misc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = {
   Opcode_wsr_misc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = {
   Opcode_xsr_misc1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = {
   Opcode_rsr_prid_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = {
   Opcode_rsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = {
   Opcode_wsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = {
   Opcode_xsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = {
   Opcode_mul16u_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = {
   Opcode_mul16s_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = {
   Opcode_mull_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = {
   Opcode_rfi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = {
   Opcode_waiti_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = {
   Opcode_rsr_interrupt_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = {
   Opcode_wsr_intset_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = {
   Opcode_wsr_intclear_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = {
   Opcode_rsr_intenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = {
   Opcode_wsr_intenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = {
   Opcode_xsr_intenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_break_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_break_encode_fns[] = {
   Opcode_break_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = {
   0, 0, Opcode_break_n_Slot_inst16b_encode, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = {
   Opcode_rsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = {
   Opcode_wsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = {
   Opcode_xsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = {
   Opcode_rsr_icount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = {
   Opcode_wsr_icount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = {
   Opcode_xsr_icount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = {
   Opcode_rsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = {
   Opcode_wsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = {
   Opcode_xsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = {
   Opcode_rsr_ddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = {
   Opcode_wsr_ddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = {
   Opcode_xsr_ddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = {
   Opcode_rfdo_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = {
   Opcode_rfdd_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = {
   Opcode_andb_Slot_inst_encode, 0, 0, 0, Opcode_andb_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = {
   Opcode_andbc_Slot_inst_encode, 0, 0, 0, Opcode_andbc_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = {
   Opcode_orb_Slot_inst_encode, 0, 0, 0, Opcode_orb_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = {
   Opcode_orbc_Slot_inst_encode, 0, 0, 0, Opcode_orbc_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = {
   Opcode_xorb_Slot_inst_encode, 0, 0, 0, Opcode_xorb_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = {
   Opcode_any4_Slot_inst_encode, 0, 0, 0, Opcode_any4_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = {
   Opcode_all4_Slot_inst_encode, 0, 0, 0, Opcode_all4_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = {
   Opcode_any8_Slot_inst_encode, 0, 0, 0, Opcode_any8_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = {
   Opcode_all8_Slot_inst_encode, 0, 0, 0, Opcode_all8_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = {
   Opcode_bf_Slot_inst_encode, 0, 0, 0, Opcode_bf_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = {
   Opcode_bt_Slot_inst_encode, 0, 0, 0, Opcode_bt_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = {
   Opcode_movf_Slot_inst_encode, 0, 0, 0, Opcode_movf_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = {
   Opcode_movt_Slot_inst_encode, 0, 0, 0, Opcode_movt_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = {
   Opcode_rsr_br_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = {
   Opcode_wsr_br_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = {
   Opcode_xsr_br_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = {
   Opcode_rsr_ccount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = {
   Opcode_wsr_ccount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = {
   Opcode_xsr_ccount_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = {
   Opcode_rsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = {
   Opcode_wsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = {
   Opcode_xsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = {
   Opcode_rsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = {
   Opcode_wsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = {
   Opcode_xsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = {
   Opcode_ipf_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = {
   Opcode_ihi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = {
   Opcode_iii_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = {
   Opcode_lict_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = {
   Opcode_licw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = {
   Opcode_sict_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = {
   Opcode_sicw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = {
   Opcode_dhwb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = {
   Opcode_dhwbi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = {
   Opcode_diwb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = {
   Opcode_diwbi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = {
   Opcode_dhi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = {
   Opcode_dii_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = {
   Opcode_dpfr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = {
   Opcode_dpfw_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = {
   Opcode_dpfro_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = {
   Opcode_dpfwo_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = {
   Opcode_sdct_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = {
   Opcode_ldct_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ptevaddr_encode_fns[] = {
   Opcode_wsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ptevaddr_encode_fns[] = {
   Opcode_rsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ptevaddr_encode_fns[] = {
   Opcode_xsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_rasid_encode_fns[] = {
   Opcode_rsr_rasid_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_rasid_encode_fns[] = {
   Opcode_wsr_rasid_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_rasid_encode_fns[] = {
   Opcode_xsr_rasid_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_itlbcfg_encode_fns[] = {
   Opcode_rsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_itlbcfg_encode_fns[] = {
   Opcode_wsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_itlbcfg_encode_fns[] = {
   Opcode_xsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_dtlbcfg_encode_fns[] = {
   Opcode_rsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_dtlbcfg_encode_fns[] = {
   Opcode_wsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_dtlbcfg_encode_fns[] = {
   Opcode_xsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = {
   Opcode_idtlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = {
   Opcode_pdtlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = {
   Opcode_rdtlb0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = {
   Opcode_rdtlb1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = {
   Opcode_wdtlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = {
   Opcode_iitlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = {
   Opcode_pitlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = {
   Opcode_ritlb0_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = {
   Opcode_ritlb1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = {
   Opcode_witlb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ldpte_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ldpte_encode_fns[] = {
   Opcode_ldpte_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_hwwitlba_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_hwwitlba_encode_fns[] = {
   Opcode_hwwitlba_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_hwwdtlba_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_hwwdtlba_encode_fns[] = {
   Opcode_hwwdtlba_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = {
   Opcode_rsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = {
   Opcode_wsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = {
   Opcode_xsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = {
   Opcode_clamps_Slot_inst_encode, 0, 0, 0, Opcode_clamps_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_min_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_min_encode_fns[] = {
   Opcode_min_Slot_inst_encode, 0, 0, 0, Opcode_min_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_max_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_max_encode_fns[] = {
   Opcode_max_Slot_inst_encode, 0, 0, 0, Opcode_max_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = {
   Opcode_minu_Slot_inst_encode, 0, 0, 0, Opcode_minu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = {
   Opcode_maxu_Slot_inst_encode, 0, 0, 0, Opcode_maxu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = {
   Opcode_nsa_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = {
   Opcode_nsau_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = {
   Opcode_sext_Slot_inst_encode, 0, 0, 0, Opcode_sext_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = {
   Opcode_l32ai_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = {
   Opcode_s32ri_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = {
   Opcode_s32c1i_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = {
   Opcode_rsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = {
   Opcode_wsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = {
   Opcode_xsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = {
   Opcode_rsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = {
   Opcode_wsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = {
   Opcode_xsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = {
   Opcode_rer_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = {
   Opcode_wer_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_ovf_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_ovf_sar_encode_fns[] = {
   Opcode_rur_ae_ovf_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_ovf_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_ovf_sar_encode_fns[] = {
   Opcode_wur_ae_ovf_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_bithead_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bithead_encode_fns[] = {
   Opcode_rur_ae_bithead_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_bithead_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bithead_encode_fns[] = {
   Opcode_wur_ae_bithead_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_ts_fts_bu_bp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_ts_fts_bu_bp_encode_fns[] = {
   Opcode_rur_ae_ts_fts_bu_bp_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_ts_fts_bu_bp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_ts_fts_bu_bp_encode_fns[] = {
   Opcode_wur_ae_ts_fts_bu_bp_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_sd_no_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_sd_no_encode_fns[] = {
   Opcode_rur_ae_sd_no_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_sd_no_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_sd_no_encode_fns[] = {
   Opcode_wur_ae_sd_no_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_overflow_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_overflow_encode_fns[] = {
   Opcode_rur_ae_overflow_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_overflow_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_overflow_encode_fns[] = {
   Opcode_wur_ae_overflow_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_sar_encode_fns[] = {
   Opcode_rur_ae_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_sar_encode_fns[] = {
   Opcode_wur_ae_sar_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_bitptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bitptr_encode_fns[] = {
   Opcode_rur_ae_bitptr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_bitptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bitptr_encode_fns[] = {
   Opcode_wur_ae_bitptr_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_bitsused_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bitsused_encode_fns[] = {
   Opcode_rur_ae_bitsused_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_bitsused_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bitsused_encode_fns[] = {
   Opcode_wur_ae_bitsused_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_tablesize_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_tablesize_encode_fns[] = {
   Opcode_rur_ae_tablesize_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_tablesize_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_tablesize_encode_fns[] = {
   Opcode_wur_ae_tablesize_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_first_ts_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_first_ts_encode_fns[] = {
   Opcode_rur_ae_first_ts_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_first_ts_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_first_ts_encode_fns[] = {
   Opcode_wur_ae_first_ts_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_nextoffset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_nextoffset_encode_fns[] = {
   Opcode_rur_ae_nextoffset_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_nextoffset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_nextoffset_encode_fns[] = {
   Opcode_wur_ae_nextoffset_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_rur_ae_searchdone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_searchdone_encode_fns[] = {
   Opcode_rur_ae_searchdone_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_wur_ae_searchdone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_searchdone_encode_fns[] = {
   Opcode_wur_ae_searchdone_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_i_encode_fns[] = {
   Opcode_ae_lp16f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_iu_encode_fns[] = {
   Opcode_ae_lp16f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_x_encode_fns[] = {
   Opcode_ae_lp16f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_xu_encode_fns[] = {
   Opcode_ae_lp16f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_i_encode_fns[] = {
   Opcode_ae_lp24_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_iu_encode_fns[] = {
   Opcode_ae_lp24_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_x_encode_fns[] = {
   Opcode_ae_lp24_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_xu_encode_fns[] = {
   Opcode_ae_lp24_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_i_encode_fns[] = {
   Opcode_ae_lp24f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_iu_encode_fns[] = {
   Opcode_ae_lp24f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_x_encode_fns[] = {
   Opcode_ae_lp24f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_xu_encode_fns[] = {
   Opcode_ae_lp24f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_i_encode_fns[] = {
   Opcode_ae_lp16x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_iu_encode_fns[] = {
   Opcode_ae_lp16x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_x_encode_fns[] = {
   Opcode_ae_lp16x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_xu_encode_fns[] = {
   Opcode_ae_lp16x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_i_encode_fns[] = {
   Opcode_ae_lp24x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_iu_encode_fns[] = {
   Opcode_ae_lp24x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_x_encode_fns[] = {
   Opcode_ae_lp24x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_xu_encode_fns[] = {
   Opcode_ae_lp24x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_i_encode_fns[] = {
   Opcode_ae_lp24x2_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_iu_encode_fns[] = {
   Opcode_ae_lp24x2_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_x_encode_fns[] = {
   Opcode_ae_lp24x2_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_xu_encode_fns[] = {
   Opcode_ae_lp24x2_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_i_encode_fns[] = {
   Opcode_ae_sp16x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_iu_encode_fns[] = {
   Opcode_ae_sp16x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_x_encode_fns[] = {
   Opcode_ae_sp16x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_xu_encode_fns[] = {
   Opcode_ae_sp16x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_i_encode_fns[] = {
   Opcode_ae_sp24x2s_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_iu_encode_fns[] = {
   Opcode_ae_sp24x2s_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_x_encode_fns[] = {
   Opcode_ae_sp24x2s_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_xu_encode_fns[] = {
   Opcode_ae_sp24x2s_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_i_encode_fns[] = {
   Opcode_ae_sp24x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_iu_encode_fns[] = {
   Opcode_ae_sp24x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_x_encode_fns[] = {
   Opcode_ae_sp24x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_xu_encode_fns[] = {
   Opcode_ae_sp24x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_i_encode_fns[] = {
   Opcode_ae_sp16f_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_iu_encode_fns[] = {
   Opcode_ae_sp16f_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_x_encode_fns[] = {
   Opcode_ae_sp16f_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_xu_encode_fns[] = {
   Opcode_ae_sp16f_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_i_encode_fns[] = {
   Opcode_ae_sp24s_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_iu_encode_fns[] = {
   Opcode_ae_sp24s_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_x_encode_fns[] = {
   Opcode_ae_sp24s_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_xu_encode_fns[] = {
   Opcode_ae_sp24s_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_i_encode_fns[] = {
   Opcode_ae_sp24f_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_iu_encode_fns[] = {
   Opcode_ae_sp24f_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_x_encode_fns[] = {
   Opcode_ae_sp24f_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_xu_encode_fns[] = {
   Opcode_ae_sp24f_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq56_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_i_encode_fns[] = {
   Opcode_ae_lq56_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq56_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_iu_encode_fns[] = {
   Opcode_ae_lq56_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq56_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_x_encode_fns[] = {
   Opcode_ae_lq56_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq56_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_xu_encode_fns[] = {
   Opcode_ae_lq56_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq32f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_i_encode_fns[] = {
   Opcode_ae_lq32f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq32f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_iu_encode_fns[] = {
   Opcode_ae_lq32f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq32f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_x_encode_fns[] = {
   Opcode_ae_lq32f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lq32f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_xu_encode_fns[] = {
   Opcode_ae_lq32f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq56s_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_i_encode_fns[] = {
   Opcode_ae_sq56s_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq56s_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_iu_encode_fns[] = {
   Opcode_ae_sq56s_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq56s_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_x_encode_fns[] = {
   Opcode_ae_sq56s_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq56s_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_xu_encode_fns[] = {
   Opcode_ae_sq56s_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq32f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_i_encode_fns[] = {
   Opcode_ae_sq32f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_i_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq32f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_iu_encode_fns[] = {
   Opcode_ae_sq32f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_iu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq32f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_x_encode_fns[] = {
   Opcode_ae_sq32f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_x_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sq32f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_xu_encode_fns[] = {
   Opcode_ae_sq32f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_xu_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_zerop48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_zerop48_encode_fns[] = {
   0, 0, 0, Opcode_ae_zerop48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movp48_encode_fns[] = {
   Opcode_ae_movp48_Slot_inst_encode, 0, 0, Opcode_ae_movp48_Slot_ae_slot1_encode, Opcode_ae_movp48_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_selp24_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_selp24_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_selp24_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_selp24_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_selp24_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_selp24_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_selp24_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_selp24_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movtp24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtp24x2_encode_fns[] = {
   0, 0, 0, Opcode_ae_movtp24x2_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movfp24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfp24x2_encode_fns[] = {
   0, 0, 0, Opcode_ae_movfp24x2_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movtp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_movtp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movfp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_movfp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movpa24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movpa24x2_encode_fns[] = {
   Opcode_ae_movpa24x2_Slot_inst_encode, 0, 0, 0, Opcode_ae_movpa24x2_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_truncp24a32x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp24a32x2_encode_fns[] = {
   Opcode_ae_truncp24a32x2_Slot_inst_encode, 0, 0, 0, Opcode_ae_truncp24a32x2_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvta32p24_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvta32p24_l_encode_fns[] = {
   Opcode_ae_cvta32p24_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvta32p24_l_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvta32p24_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvta32p24_h_encode_fns[] = {
   Opcode_ae_cvta32p24_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvta32p24_h_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_ll_encode_fns[] = {
   Opcode_ae_cvtp24a16x2_ll_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_ll_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_lh_encode_fns[] = {
   Opcode_ae_cvtp24a16x2_lh_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_lh_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hl_encode_fns[] = {
   Opcode_ae_cvtp24a16x2_hl_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_hl_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hh_encode_fns[] = {
   Opcode_ae_cvtp24a16x2_hh_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_hh_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_truncp24q48x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp24q48x2_encode_fns[] = {
   0, 0, 0, Opcode_ae_truncp24q48x2_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_truncp16_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp16_encode_fns[] = {
   0, 0, 0, Opcode_ae_truncp16_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp24q48sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp24q48sym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp24q48sym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp24q48asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp24q48asym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp24q48asym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp16q48sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16q48sym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp16q48sym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp16q48asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16q48asym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp16q48asym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp16sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16sym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp16sym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsp16asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16asym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsp16asym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_zeroq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_zeroq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_zeroq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movq56_encode_fns[] = {
   Opcode_ae_movq56_Slot_inst_encode, 0, 0, Opcode_ae_movq56_Slot_ae_slot1_encode, Opcode_ae_movq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movtq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtq56_encode_fns[] = {
   Opcode_ae_movtq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_movtq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movfq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfq56_encode_fns[] = {
   Opcode_ae_movfq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_movfq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtq48a32s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48a32s_encode_fns[] = {
   Opcode_ae_cvtq48a32s_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtq48a32s_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_cvtq48p24s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_cvtq48p24s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_satq48s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_satq48s_encode_fns[] = {
   0, 0, 0, Opcode_ae_satq48s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_truncq32_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncq32_encode_fns[] = {
   0, 0, 0, Opcode_ae_truncq32_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsq32sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsq32sym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsq32sym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_roundsq32asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsq32asym_encode_fns[] = {
   0, 0, 0, Opcode_ae_roundsq32asym_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_trunca32q48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca32q48_encode_fns[] = {
   Opcode_ae_trunca32q48_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca32q48_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movap24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movap24s_l_encode_fns[] = {
   Opcode_ae_movap24s_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_movap24s_l_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_movap24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movap24s_h_encode_fns[] = {
   Opcode_ae_movap24s_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_movap24s_h_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_l_encode_fns[] = {
   Opcode_ae_trunca16p24s_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca16p24s_l_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_h_encode_fns[] = {
   Opcode_ae_trunca16p24s_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca16p24s_h_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_addp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_addp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_subp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_subp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_negp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_negp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_absp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_absp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_absp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_maxp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_maxp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_minp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_minp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_maxbp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxbp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_maxbp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_minbp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minbp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_minbp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_addsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addsp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_addsp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_subsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subsp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_subsp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_negsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negsp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_negsp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_abssp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_abssp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_abssp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_andp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_andp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_andp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_nandp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nandp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_nandp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_orp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_orp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_orp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_xorp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_xorp48_encode_fns[] = {
   0, 0, 0, Opcode_ae_xorp48_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_ltp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_ltp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_ltp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lep24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lep24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_lep24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_eqp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_eqp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_eqp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_addq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_addq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_subq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_subq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_negq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_negq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_absq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_absq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_absq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_maxq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_maxq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_minq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_minq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_maxbq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxbq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_maxbq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_minbq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minbq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_minbq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_addsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addsq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_addsq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_subsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subsq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_subsq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_negsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negsq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_negsq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_abssq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_abssq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_abssq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_andq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_andq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_andq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_nandq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nandq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_nandq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_orq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_orq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_orq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_xorq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_xorq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_xorq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllip24_encode_fns[] = {
   0, 0, 0, Opcode_ae_sllip24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srlip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlip24_encode_fns[] = {
   0, 0, 0, Opcode_ae_srlip24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sraip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraip24_encode_fns[] = {
   0, 0, 0, Opcode_ae_sraip24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllsp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllsp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_sllsp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srlsp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlsp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_srlsp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srasp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srasp24_encode_fns[] = {
   0, 0, 0, Opcode_ae_srasp24_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllisp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllisp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_sllisp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllssp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllssp24s_encode_fns[] = {
   0, 0, 0, Opcode_ae_sllssp24s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_slliq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_slliq56_encode_fns[] = {
   Opcode_ae_slliq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_slliq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srliq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srliq56_encode_fns[] = {
   Opcode_ae_srliq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srliq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sraiq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraiq56_encode_fns[] = {
   Opcode_ae_sraiq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sraiq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllsq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllsq56_encode_fns[] = {
   Opcode_ae_sllsq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllsq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srlsq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlsq56_encode_fns[] = {
   Opcode_ae_srlsq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srlsq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srasq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srasq56_encode_fns[] = {
   Opcode_ae_srasq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srasq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllaq56_encode_fns[] = {
   Opcode_ae_sllaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllaq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_srlaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlaq56_encode_fns[] = {
   Opcode_ae_srlaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srlaq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sraaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraaq56_encode_fns[] = {
   Opcode_ae_sraaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sraaq56_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllisq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllisq56s_encode_fns[] = {
   Opcode_ae_sllisq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllisq56s_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllssq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllssq56s_encode_fns[] = {
   Opcode_ae_sllssq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllssq56s_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sllasq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllasq56s_encode_fns[] = {
   Opcode_ae_sllasq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllasq56s_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_ltq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_ltq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_ltq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_leq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_leq56s_encode_fns[] = {
   0, 0, 0, Opcode_ae_leq56s_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_eqq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_eqq56_encode_fns[] = {
   0, 0, 0, Opcode_ae_eqq56_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_nsaq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nsaq56s_encode_fns[] = {
   Opcode_ae_nsaq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_nsaq56s_Slot_ae_slot0_encode
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfs32p16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfp24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulp24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfs32p16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfp24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulp24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfs32p16s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfp24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulp24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfs32p16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfp24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulp24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs32p16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafp24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulap24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs32p16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafp24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulap24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs32p16s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafp24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulap24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs32p16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafp24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulap24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs32p16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfp24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsp24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs32p16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfp24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsp24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs32p16s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfp24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsp24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs32p16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfp24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsp24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs56p24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulas56p24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs56p24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulas56p24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs56p24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulas56p24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafs56p24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulas56p24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs56p24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulss56p24s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs56p24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulss56p24s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs56p24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hl_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulss56p24s_hl_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfs56p24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulss56p24s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulfq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulafq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsfq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsq32sp16s_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsq32sp16s_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_l_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsq32sp16u_l_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_h_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsq32sp16u_h_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaaq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsaq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16s_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16u_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16s_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_hh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16u_hh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16s_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfq32sp16u_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaap24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaafp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzaap24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasfp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzasp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsap24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsafp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzsap24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssfp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulzssp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaafp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaap24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaafp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulaap24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulasfp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulasp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulasfp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulasp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsafp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsap24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsafp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulsap24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulssfp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hh_ll_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulssp24s_hh_ll_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulssfp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hl_lh_encode_fns[] = {
   0, 0, 0, Opcode_ae_mulssp24s_hl_lh_Slot_ae_slot1_encode, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sha32_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sha32_encode_fns[] = {
   Opcode_ae_sha32_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vldl32t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl32t_encode_fns[] = {
   Opcode_ae_vldl32t_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vldl16t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl16t_encode_fns[] = {
   Opcode_ae_vldl16t_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vldl16c_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl16c_encode_fns[] = {
   Opcode_ae_vldl16c_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vldsht_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldsht_encode_fns[] = {
   Opcode_ae_vldsht_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lb_encode_fns[] = {
   Opcode_ae_lb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbi_encode_fns[] = {
   Opcode_ae_lbi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lbk_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbk_encode_fns[] = {
   Opcode_ae_lbk_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_lbki_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbki_encode_fns[] = {
   Opcode_ae_lbki_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_db_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_db_encode_fns[] = {
   Opcode_ae_db_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_dbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_dbi_encode_fns[] = {
   Opcode_ae_dbi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vlel32t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vlel32t_encode_fns[] = {
   Opcode_ae_vlel32t_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vlel16t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vlel16t_encode_fns[] = {
   Opcode_ae_vlel16t_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sb_encode_fns[] = {
   Opcode_ae_sb_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sbi_encode_fns[] = {
   Opcode_ae_sbi_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_vles16c_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vles16c_encode_fns[] = {
   Opcode_ae_vles16c_Slot_inst_encode, 0, 0, 0, 0
 };
 
-xtensa_opcode_encode_fn Opcode_ae_sbf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sbf_encode_fns[] = {
   Opcode_ae_sbf_Slot_inst_encode, 0, 0, 0, 0
 };
 
@@ -30818,7 +30818,7 @@ Slot_inst_decode (const xtensa_insnbuf insn)
 	}
       break;
     }
-  return 0;
+  return XTENSA_UNDEFINED;
 }
 
 static int
@@ -30869,7 +30869,7 @@ Slot_inst16b_decode (const xtensa_insnbuf insn)
 	}
       break;
     }
-  return 0;
+  return XTENSA_UNDEFINED;
 }
 
 static int
@@ -30886,7 +30886,7 @@ Slot_inst16a_decode (const xtensa_insnbuf insn)
     case 11:
       return OPCODE_ADDI_N;
     }
-  return 0;
+  return XTENSA_UNDEFINED;
 }
 
 static int
@@ -31561,7 +31561,7 @@ Slot_ae_slot0_decode (const xtensa_insnbuf insn)
 	return OPCODE_BF;
       break;
     }
-  return 0;
+  return XTENSA_UNDEFINED;
 }
 
 static int
@@ -32279,7 +32279,7 @@ Slot_ae_slot1_decode (const xtensa_insnbuf insn)
 	return OPCODE_AE_MULZSSQ32SP16U_LL;
       break;
     }
-  return 0;
+  return XTENSA_UNDEFINED;
 }
 
 
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index b665bfc006..4d8152682f 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -131,6 +131,7 @@ enum {
     ACCLO = 16,
     ACCHI = 17,
     MR = 32,
+    PREFCTL = 40,
     WINDOW_BASE = 72,
     WINDOW_START = 73,
     PTEVADDR = 83,
@@ -345,14 +346,21 @@ typedef struct XtensaMemory {
     } location[MAX_NMEMORY];
 } XtensaMemory;
 
+typedef struct opcode_arg {
+    uint32_t imm;
+    uint32_t raw_imm;
+    void *in;
+    void *out;
+} OpcodeArg;
+
 typedef struct DisasContext DisasContext;
-typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
+typedef void (*XtensaOpcodeOp)(DisasContext *dc, const OpcodeArg arg[],
                                const uint32_t par[]);
 typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
-                                     const uint32_t arg[],
+                                     const OpcodeArg arg[],
                                      const uint32_t par[]);
 typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
-                                         const uint32_t arg[],
+                                         const OpcodeArg arg[],
                                          const uint32_t par[]);
 
 enum {
@@ -368,19 +376,34 @@ enum {
 
     XTENSA_OP_DIVIDE_BY_ZERO = 0x100,
 
+    /* Postprocessing flags */
     XTENSA_OP_CHECK_INTERRUPTS = 0x200,
     XTENSA_OP_EXIT_TB_M1 = 0x400,
     XTENSA_OP_EXIT_TB_0 = 0x800,
+    XTENSA_OP_SYNC_REGISTER_WINDOW = 0x1000,
+
+    XTENSA_OP_POSTPROCESS =
+        XTENSA_OP_CHECK_INTERRUPTS |
+        XTENSA_OP_EXIT_TB_M1 |
+        XTENSA_OP_EXIT_TB_0 |
+        XTENSA_OP_SYNC_REGISTER_WINDOW,
+
+    XTENSA_OP_NAME_ARRAY = 0x8000,
+
+    XTENSA_OP_CONTROL_FLOW = 0x10000,
+    XTENSA_OP_STORE = 0x20000,
+    XTENSA_OP_LOAD = 0x40000,
+    XTENSA_OP_LOAD_STORE =
+        XTENSA_OP_LOAD | XTENSA_OP_STORE,
 };
 
 typedef struct XtensaOpcodeOps {
-    const char *name;
+    const void *name;
     XtensaOpcodeOp translate;
     XtensaOpcodeBoolTest test_ill;
     XtensaOpcodeUintTest test_overflow;
     const uint32_t *par;
     uint32_t op_flags;
-    uint32_t windowed_register_op;
     uint32_t coprocessor;
 } XtensaOpcodeOps;
 
@@ -438,6 +461,8 @@ struct XtensaConfig {
     xtensa_isa isa;
     XtensaOpcodeOps **opcode_ops;
     const XtensaOpcodeTranslators **opcode_translators;
+    xtensa_regfile a_regfile;
+    void ***regfile;
 
     uint32_t clock_freq_khz;
 
@@ -474,6 +499,7 @@ typedef struct CPUXtensaState {
         float64 f64;
     } fregs[16];
     float_status fp_status;
+    uint32_t windowbase_next;
 
 #ifndef CONFIG_USER_ONLY
     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
@@ -565,8 +591,8 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
     XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
 
 void xtensa_translate_init(void);
+void **xtensa_get_regfile_by_name(const char *name);
 void xtensa_breakpoint_handler(CPUState *cs);
-void xtensa_finalize_config(XtensaConfig *config);
 void xtensa_register_core(XtensaConfigList *node);
 void xtensa_sim_open_console(Chardev *chr);
 void check_interrupts(CPUXtensaState *s);
@@ -588,8 +614,6 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env,
     env->static_vectors = n;
 }
 void xtensa_runstall(CPUXtensaState *env, bool runstall);
-XtensaOpcodeOps *xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
-                                        const char *opcode);
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 #define XTENSA_OPTION_ALL (~(uint64_t)0)
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index bcf2f20d48..f4867a9b56 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -30,24 +30,60 @@
 #include "exec/exec-all.h"
 #include "exec/gdbstub.h"
 #include "exec/helper-proto.h"
+#include "qemu/error-report.h"
 #include "qemu/host-utils.h"
 
 static struct XtensaConfigList *xtensa_cores;
 
-static void xtensa_core_class_init(ObjectClass *oc, void *data)
+static void add_translator_to_hash(GHashTable *translator,
+                                   const char *name,
+                                   const XtensaOpcodeOps *opcode)
 {
-    CPUClass *cc = CPU_CLASS(oc);
-    XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
-    const XtensaConfig *config = data;
+    if (!g_hash_table_insert(translator, (void *)name, (void *)opcode)) {
+        error_report("Multiple definitions of '%s' opcode in a single table",
+                     name);
+    }
+}
 
-    xcc->config = config;
+static GHashTable *hash_opcode_translators(const XtensaOpcodeTranslators *t)
+{
+    unsigned i, j;
+    GHashTable *translator = g_hash_table_new(g_str_hash, g_str_equal);
 
-    /* Use num_core_regs to see only non-privileged registers in an unmodified
-     * gdb. Use num_regs to see all registers. gdb modification is required
-     * for that: reset bit 0 in the 'flags' field of the registers definitions
-     * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
-     */
-    cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+    for (i = 0; i < t->num_opcodes; ++i) {
+        if (t->opcode[i].op_flags & XTENSA_OP_NAME_ARRAY) {
+            const char * const *name = t->opcode[i].name;
+
+            for (j = 0; name[j]; ++j) {
+                add_translator_to_hash(translator,
+                                       (void *)name[j],
+                                       (void *)(t->opcode + i));
+            }
+        } else {
+            add_translator_to_hash(translator,
+                                   (void *)t->opcode[i].name,
+                                   (void *)(t->opcode + i));
+        }
+    }
+    return translator;
+}
+
+static XtensaOpcodeOps *
+xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
+                       const char *name)
+{
+    static GHashTable *translators;
+    GHashTable *translator;
+
+    if (translators == NULL) {
+        translators = g_hash_table_new(g_direct_hash, g_direct_equal);
+    }
+    translator = g_hash_table_lookup(translators, t);
+    if (translator == NULL) {
+        translator = hash_opcode_translators(t);
+        g_hash_table_insert(translators, (void *)t, translator);
+    }
+    return g_hash_table_lookup(translator, name);
 }
 
 static void init_libisa(XtensaConfig *config)
@@ -55,11 +91,13 @@ static void init_libisa(XtensaConfig *config)
     unsigned i, j;
     unsigned opcodes;
     unsigned formats;
+    unsigned regfiles;
 
     config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
     assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
     opcodes = xtensa_isa_num_opcodes(config->isa);
     formats = xtensa_isa_num_formats(config->isa);
+    regfiles = xtensa_isa_num_regfiles(config->isa);
     config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
 
     for (i = 0; i < formats; ++i) {
@@ -88,9 +126,23 @@ static void init_libisa(XtensaConfig *config)
 #endif
         config->opcode_ops[i] = ops;
     }
+    config->a_regfile = xtensa_regfile_lookup(config->isa, "AR");
+
+    config->regfile = g_new(void **, regfiles);
+    for (i = 0; i < regfiles; ++i) {
+        const char *name = xtensa_regfile_name(config->isa, i);
+
+        config->regfile[i] = xtensa_get_regfile_by_name(name);
+#ifdef DEBUG
+        if (config->regfile[i] == NULL) {
+            fprintf(stderr, "regfile '%s' not found for %s\n",
+                    name, config->name);
+        }
+#endif
+    }
 }
 
-void xtensa_finalize_config(XtensaConfig *config)
+static void xtensa_finalize_config(XtensaConfig *config)
 {
     if (config->isa_internal) {
         init_libisa(config);
@@ -111,6 +163,24 @@ void xtensa_finalize_config(XtensaConfig *config)
     }
 }
 
+static void xtensa_core_class_init(ObjectClass *oc, void *data)
+{
+    CPUClass *cc = CPU_CLASS(oc);
+    XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
+    XtensaConfig *config = data;
+
+    xtensa_finalize_config(config);
+    xcc->config = config;
+
+    /*
+     * Use num_core_regs to see only non-privileged registers in an unmodified
+     * gdb. Use num_regs to see all registers. gdb modification is required
+     * for that: reset bit 0 in the 'flags' field of the registers definitions
+     * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
+     */
+    cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+}
+
 void xtensa_register_core(XtensaConfigList *node)
 {
     TypeInfo type = {
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index 2a7db35874..0b9ec670c8 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -3,12 +3,11 @@ DEF_HELPER_3(exception_cause, noreturn, env, i32, i32)
 DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32)
 DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
 
-DEF_HELPER_2(wsr_windowbase, void, env, i32)
+DEF_HELPER_1(sync_windowbase, void, env)
 DEF_HELPER_4(entry, void, env, i32, i32, i32)
 DEF_HELPER_2(test_ill_retw, void, env, i32)
 DEF_HELPER_2(test_underflow_retw, void, env, i32)
-DEF_HELPER_2(retw, i32, env, i32)
-DEF_HELPER_2(rotw, void, env, i32)
+DEF_HELPER_2(retw, void, env, i32)
 DEF_HELPER_3(window_check, noreturn, env, i32, i32)
 DEF_HELPER_1(restore_owb, void, env)
 DEF_HELPER_2(movsp, void, env, i32)
diff --git a/target/xtensa/import_core.sh b/target/xtensa/import_core.sh
index 039406bf28..e4a2e39f63 100755
--- a/target/xtensa/import_core.sh
+++ b/target/xtensa/import_core.sh
@@ -27,7 +27,7 @@ tar -xf "$OVERLAY" -O gdb/xtensa-config.c | \
 # Fix up known issues in the xtensa-modules.c
 #
 tar -xf "$OVERLAY" -O binutils/xtensa-modules.c | \
-    sed -e 's/\(xtensa_opcode_encode_fn.*\[\] =\)/static \1/' \
+    sed -e 's/^\(xtensa_opcode_encode_fn.*\[\] =\)/static \1/' \
         -e '/^int num_bypass_groups()/,/}/d' \
         -e '/^int num_bypass_group_chunks()/,/}/d' \
         -e '/^uint32 \*bypass_entry(int i)/,/}/d' \
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index 12609a0d0c..ea07576bc9 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -377,7 +377,6 @@
         static XtensaConfigList node = { \
             .config = &core, \
         }; \
-        xtensa_finalize_config(&core); \
         xtensa_register_core(&node); \
     }
 #else
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index d1e9f59b31..77bc04d6b0 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -71,7 +71,7 @@ struct DisasContext {
 
     unsigned cpenable;
 
-    uint32_t *raw_arg;
+    uint32_t op_flags;
     xtensa_insnbuf insnbuf;
     xtensa_insnbuf slotbuf;
 };
@@ -79,8 +79,15 @@ struct DisasContext {
 static TCGv_i32 cpu_pc;
 static TCGv_i32 cpu_R[16];
 static TCGv_i32 cpu_FR[16];
+static TCGv_i32 cpu_MR[4];
+static TCGv_i32 cpu_BR[16];
+static TCGv_i32 cpu_BR4[4];
+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 GHashTable *xtensa_regfile_table;
 
 #include "exec/gen-icount.h"
 
@@ -127,6 +134,7 @@ static const XtensaReg sregnames[256] = {
     [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),
@@ -220,6 +228,15 @@ void xtensa_translate_init(void)
         "f8", "f9", "f10", "f11",
         "f12", "f13", "f14", "f15",
     };
+    static const char * const mregnames[] = {
+        "m0", "m1", "m2", "m3",
+    };
+    static const char * const bregnames[] = {
+        "b0", "b1", "b2", "b3",
+        "b4", "b5", "b6", "b7",
+        "b8", "b9", "b10", "b11",
+        "b12", "b13", "b14", "b15",
+    };
     int i;
 
     cpu_pc = tcg_global_mem_new_i32(cpu_env,
@@ -227,14 +244,41 @@ void xtensa_translate_init(void)
 
     for (i = 0; i < 16; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
-                offsetof(CPUXtensaState, regs[i]),
-                regnames[i]);
+                                          offsetof(CPUXtensaState, regs[i]),
+                                          regnames[i]);
     }
 
     for (i = 0; i < 16; i++) {
         cpu_FR[i] = tcg_global_mem_new_i32(cpu_env,
-                offsetof(CPUXtensaState, fregs[i].f32[FP_F32_LOW]),
-                fregnames[i]);
+                                           offsetof(CPUXtensaState,
+                                                    fregs[i].f32[FP_F32_LOW]),
+                                           fregnames[i]);
+    }
+
+    for (i = 0; i < 4; i++) {
+        cpu_MR[i] = tcg_global_mem_new_i32(cpu_env,
+                                           offsetof(CPUXtensaState,
+                                                    sregs[MR + i]),
+                                           mregnames[i]);
+    }
+
+    for (i = 0; i < 16; i++) {
+        cpu_BR[i] = tcg_global_mem_new_i32(cpu_env,
+                                           offsetof(CPUXtensaState,
+                                                    sregs[BR]),
+                                           bregnames[i]);
+        if (i % 4 == 0) {
+            cpu_BR4[i / 4] = tcg_global_mem_new_i32(cpu_env,
+                                                    offsetof(CPUXtensaState,
+                                                             sregs[BR]),
+                                                    bregnames[i]);
+        }
+        if (i % 8 == 0) {
+            cpu_BR8[i / 8] = tcg_global_mem_new_i32(cpu_env,
+                                                    offsetof(CPUXtensaState,
+                                                             sregs[BR]),
+                                                    bregnames[i]);
+        }
     }
 
     for (i = 0; i < 256; ++i) {
@@ -252,6 +296,31 @@ void xtensa_translate_init(void)
                     uregnames[i].name);
         }
     }
+
+    cpu_windowbase_next =
+        tcg_global_mem_new_i32(cpu_env,
+                               offsetof(CPUXtensaState, windowbase_next),
+                               "windowbase_next");
+}
+
+void **xtensa_get_regfile_by_name(const char *name)
+{
+    if (xtensa_regfile_table == NULL) {
+        xtensa_regfile_table = g_hash_table_new(g_str_hash, g_str_equal);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"AR", (void *)cpu_R);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"MR", (void *)cpu_MR);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"FR", (void *)cpu_FR);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"BR", (void *)cpu_BR);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"BR4", (void *)cpu_BR4);
+        g_hash_table_insert(xtensa_regfile_table,
+                            (void *)"BR8", (void *)cpu_BR8);
+    }
+    return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name);
 }
 
 static inline bool option_enabled(DisasContext *dc, int opt)
@@ -363,6 +432,8 @@ static bool gen_check_cpenable(DisasContext *dc, uint32_t cp_mask)
     return true;
 }
 
+static int gen_postprocess(DisasContext *dc, int slot);
+
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
@@ -372,6 +443,9 @@ static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
     if (dc->base.singlestep_enabled) {
         gen_exception(dc, EXCP_DEBUG);
     } else {
+        if (dc->op_flags & XTENSA_OP_POSTPROCESS) {
+            slot = gen_postprocess(dc, slot);
+        }
         if (slot >= 0) {
             tcg_gen_goto_tb(slot);
             tcg_gen_exit_tb(dc->base.tb, slot);
@@ -387,13 +461,19 @@ static void gen_jump(DisasContext *dc, TCGv dest)
     gen_jump_slot(dc, dest, -1);
 }
 
-static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
+static int adjust_jump_slot(DisasContext *dc, uint32_t dest, int slot)
 {
-    TCGv_i32 tmp = tcg_const_i32(dest);
     if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
-        slot = -1;
+        return -1;
+    } else {
+        return slot;
     }
-    gen_jump_slot(dc, tmp, slot);
+}
+
+static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
+{
+    TCGv_i32 tmp = tcg_const_i32(dest);
+    gen_jump_slot(dc, tmp, adjust_jump_slot(dc, dest, slot));
     tcg_temp_free(tmp);
 }
 
@@ -410,21 +490,6 @@ static void gen_callw_slot(DisasContext *dc, int callinc, TCGv_i32 dest,
     gen_jump_slot(dc, dest, slot);
 }
 
-static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
-{
-    gen_callw_slot(dc, callinc, dest, -1);
-}
-
-static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
-{
-    TCGv_i32 tmp = tcg_const_i32(dest);
-    if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
-        slot = -1;
-    }
-    gen_callw_slot(dc, callinc, tmp, slot);
-    tcg_temp_free(tmp);
-}
-
 static bool gen_check_loop_end(DisasContext *dc, int slot)
 {
     if (dc->base.pc_next == dc->lend) {
@@ -560,7 +625,7 @@ static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 #ifndef CONFIG_USER_ONLY
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_windowbase(cpu_env, v);
+    tcg_gen_mov_i32(cpu_windowbase_next, v);
 }
 
 static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
@@ -841,11 +906,11 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
     return m;
 }
 
-static void gen_zero_check(DisasContext *dc, const uint32_t arg[])
+static void gen_zero_check(DisasContext *dc, const OpcodeArg arg[])
 {
     TCGLabel *label = gen_new_label();
 
-    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label);
+    tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0, label);
     gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
     gen_set_label(label);
 }
@@ -855,6 +920,270 @@ static inline unsigned xtensa_op0_insn_len(DisasContext *dc, uint8_t op0)
     return xtensa_isa_length_from_chars(dc->config->isa, &op0);
 }
 
+static int gen_postprocess(DisasContext *dc, int slot)
+{
+    uint32_t op_flags = dc->op_flags;
+
+    if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
+        gen_check_interrupts(dc);
+    }
+    if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) {
+        gen_helper_sync_windowbase(cpu_env);
+    }
+    if (op_flags & XTENSA_OP_EXIT_TB_M1) {
+        slot = -1;
+    }
+    return slot;
+}
+
+struct opcode_arg_copy {
+    uint32_t resource;
+    void *temp;
+    OpcodeArg *arg;
+};
+
+struct opcode_arg_info {
+    uint32_t resource;
+    int index;
+};
+
+struct slot_prop {
+    XtensaOpcodeOps *ops;
+    OpcodeArg arg[MAX_OPCODE_ARGS];
+    struct opcode_arg_info in[MAX_OPCODE_ARGS];
+    struct opcode_arg_info out[MAX_OPCODE_ARGS];
+    unsigned n_in;
+    unsigned n_out;
+    uint32_t op_flags;
+};
+
+enum resource_type {
+    RES_REGFILE,
+    RES_STATE,
+    RES_MAX,
+};
+
+static uint32_t encode_resource(enum resource_type r, unsigned g, unsigned n)
+{
+    assert(r < RES_MAX && g < 256 && n < 65536);
+    return (r << 24) | (g << 16) | n;
+}
+
+static enum resource_type get_resource_type(uint32_t resource)
+{
+    return resource >> 24;
+}
+
+/*
+ * a depends on b if b must be executed before a,
+ * because a's side effects will destroy b's inputs.
+ */
+static bool op_depends_on(const struct slot_prop *a,
+                          const struct slot_prop *b)
+{
+    unsigned i = 0;
+    unsigned j = 0;
+
+    if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+        return true;
+    }
+    if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+        (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+        return true;
+    }
+    while (i < a->n_out && j < b->n_in) {
+        if (a->out[i].resource < b->in[j].resource) {
+            ++i;
+        } else if (a->out[i].resource > b->in[j].resource) {
+            ++j;
+        } else {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * Try to break a dependency on b, append temporary register copy records
+ * to the end of copy and update n_copy in case of success.
+ * This is not always possible: e.g. control flow must always be the last,
+ * load/store must be first and state dependencies are not supported yet.
+ */
+static bool break_dependency(struct slot_prop *a,
+                             struct slot_prop *b,
+                             struct opcode_arg_copy *copy,
+                             unsigned *n_copy)
+{
+    unsigned i = 0;
+    unsigned j = 0;
+    unsigned n = *n_copy;
+    bool rv = false;
+
+    if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+        return false;
+    }
+    if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+        (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+        return false;
+    }
+    while (i < a->n_out && j < b->n_in) {
+        if (a->out[i].resource < b->in[j].resource) {
+            ++i;
+        } else if (a->out[i].resource > b->in[j].resource) {
+            ++j;
+        } else {
+            int index = b->in[j].index;
+
+            if (get_resource_type(a->out[i].resource) != RES_REGFILE ||
+                index < 0) {
+                return false;
+            }
+            copy[n].resource = b->in[j].resource;
+            copy[n].arg = b->arg + index;
+            ++n;
+            ++i;
+            ++j;
+            rv = true;
+        }
+    }
+    *n_copy = n;
+    return rv;
+}
+
+/*
+ * Calculate evaluation order for slot opcodes.
+ * Build opcode order graph and output its nodes in topological sort order.
+ * An edge a -> b in the graph means that opcode a must be followed by
+ * opcode b.
+ */
+static bool tsort(struct slot_prop *slot,
+                  struct slot_prop *sorted[],
+                  unsigned n,
+                  struct opcode_arg_copy *copy,
+                  unsigned *n_copy)
+{
+    struct tsnode {
+        unsigned n_in_edge;
+        unsigned n_out_edge;
+        unsigned out_edge[MAX_INSN_SLOTS];
+    } node[MAX_INSN_SLOTS];
+
+    unsigned in[MAX_INSN_SLOTS];
+    unsigned i, j;
+    unsigned n_in = 0;
+    unsigned n_out = 0;
+    unsigned n_edge = 0;
+    unsigned in_idx = 0;
+    unsigned node_idx = 0;
+
+    for (i = 0; i < n; ++i) {
+        node[i].n_in_edge = 0;
+        node[i].n_out_edge = 0;
+    }
+
+    for (i = 0; i < n; ++i) {
+        unsigned n_out_edge = 0;
+
+        for (j = 0; j < n; ++j) {
+            if (i != j && op_depends_on(slot + j, slot + i)) {
+                node[i].out_edge[n_out_edge] = j;
+                ++node[j].n_in_edge;
+                ++n_out_edge;
+                ++n_edge;
+            }
+        }
+        node[i].n_out_edge = n_out_edge;
+    }
+
+    for (i = 0; i < n; ++i) {
+        if (!node[i].n_in_edge) {
+            in[n_in] = i;
+            ++n_in;
+        }
+    }
+
+again:
+    for (; in_idx < n_in; ++in_idx) {
+        i = in[in_idx];
+        sorted[n_out] = slot + i;
+        ++n_out;
+        for (j = 0; j < node[i].n_out_edge; ++j) {
+            --n_edge;
+            if (--node[node[i].out_edge[j]].n_in_edge == 0) {
+                in[n_in] = node[i].out_edge[j];
+                ++n_in;
+            }
+        }
+    }
+    if (n_edge) {
+        for (; node_idx < n; ++node_idx) {
+            struct tsnode *cnode = node + node_idx;
+
+            if (cnode->n_in_edge) {
+                for (j = 0; j < cnode->n_out_edge; ++j) {
+                    unsigned k = cnode->out_edge[j];
+
+                    if (break_dependency(slot + k, slot + node_idx,
+                                         copy, n_copy) &&
+                        --node[k].n_in_edge == 0) {
+                        in[n_in] = k;
+                        ++n_in;
+                        --n_edge;
+                        cnode->out_edge[j] =
+                            cnode->out_edge[cnode->n_out_edge - 1];
+                        --cnode->n_out_edge;
+                        goto again;
+                    }
+                }
+            }
+        }
+    }
+    return n_edge == 0;
+}
+
+static void opcode_add_resource(struct slot_prop *op,
+                                uint32_t resource, char direction,
+                                int index)
+{
+    switch (direction) {
+    case 'm':
+    case 'i':
+        assert(op->n_in < ARRAY_SIZE(op->in));
+        op->in[op->n_in].resource = resource;
+        op->in[op->n_in].index = index;
+        ++op->n_in;
+        /* fall through */
+    case 'o':
+        if (direction == 'm' || direction == 'o') {
+            assert(op->n_out < ARRAY_SIZE(op->out));
+            op->out[op->n_out].resource = resource;
+            op->out[op->n_out].index = index;
+            ++op->n_out;
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static int resource_compare(const void *a, const void *b)
+{
+    const struct opcode_arg_info *pa = a;
+    const struct opcode_arg_info *pb = b;
+
+    return pa->resource < pb->resource ?
+        -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
+static int arg_copy_compare(const void *a, const void *b)
+{
+    const struct opcode_arg_copy *pa = a;
+    const struct opcode_arg_copy *pb = b;
+
+    return pa->resource < pb->resource ?
+        -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
 static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 {
     xtensa_isa isa = dc->config->isa;
@@ -864,11 +1193,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
     int slot, slots;
     unsigned i;
     uint32_t op_flags = 0;
-    struct {
-        XtensaOpcodeOps *ops;
-        uint32_t arg[MAX_OPCODE_ARGS];
-        uint32_t raw_arg[MAX_OPCODE_ARGS];
-    } slot_prop[MAX_INSN_SLOTS];
+    struct slot_prop slot_prop[MAX_INSN_SLOTS];
+    struct slot_prop *ordered[MAX_INSN_SLOTS];
+    struct opcode_arg_copy arg_copy[MAX_INSN_SLOTS * MAX_OPCODE_ARGS];
+    unsigned n_arg_copy = 0;
     uint32_t debug_cause = 0;
     uint32_t windowed_register = 0;
     uint32_t coprocessor = 0;
@@ -898,12 +1226,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
     for (slot = 0; slot < slots; ++slot) {
         xtensa_opcode opc;
         int opnd, vopnd, opnds;
-        uint32_t *raw_arg = slot_prop[slot].raw_arg;
-        uint32_t *arg = slot_prop[slot].arg;
+        OpcodeArg *arg = slot_prop[slot].arg;
         XtensaOpcodeOps *ops;
 
-        dc->raw_arg = raw_arg;
-
         xtensa_format_get_slot(isa, fmt, slot, dc->insnbuf, dc->slotbuf);
         opc = xtensa_opcode_decode(isa, fmt, slot, dc->slotbuf);
         if (opc == XTENSA_UNDEFINED) {
@@ -916,17 +1241,37 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         opnds = xtensa_opcode_num_operands(isa, opc);
 
         for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
+            void **register_file = NULL;
+
+            if (xtensa_operand_is_register(isa, opc, opnd)) {
+                xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+
+                register_file = dc->config->regfile[rf];
+
+                if (rf == dc->config->a_regfile) {
+                    uint32_t v;
+
+                    xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+                                             dc->slotbuf, &v);
+                    xtensa_operand_decode(isa, opc, opnd, &v);
+                    windowed_register |= 1u << v;
+                }
+            }
             if (xtensa_operand_is_visible(isa, opc, opnd)) {
                 uint32_t v;
 
                 xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
                                          dc->slotbuf, &v);
                 xtensa_operand_decode(isa, opc, opnd, &v);
-                raw_arg[vopnd] = v;
+                arg[vopnd].raw_imm = v;
                 if (xtensa_operand_is_PCrelative(isa, opc, opnd)) {
                     xtensa_operand_undo_reloc(isa, opc, opnd, &v, dc->pc);
                 }
-                arg[vopnd] = v;
+                arg[vopnd].imm = v;
+                if (register_file) {
+                    arg[vopnd].in = register_file[v];
+                    arg[vopnd].out = register_file[v];
+                }
                 ++vopnd;
             }
         }
@@ -952,17 +1297,69 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         if (ops->test_overflow) {
             windowed_register |= ops->test_overflow(dc, arg, ops->par);
         }
-        if (ops->windowed_register_op) {
-            uint32_t reg_opnd = ops->windowed_register_op;
+        coprocessor |= ops->coprocessor;
+
+        if (slots > 1) {
+            slot_prop[slot].n_in = 0;
+            slot_prop[slot].n_out = 0;
+            slot_prop[slot].op_flags = ops->op_flags & XTENSA_OP_LOAD_STORE;
 
-            while (reg_opnd) {
-                unsigned i = ctz32(reg_opnd);
+            opnds = xtensa_opcode_num_operands(isa, opc);
 
-                windowed_register |= 1 << arg[i];
-                reg_opnd ^= 1 << i;
+            for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
+                bool visible = xtensa_operand_is_visible(isa, opc, opnd);
+
+                if (xtensa_operand_is_register(isa, opc, opnd)) {
+                    xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+                    uint32_t v = 0;
+
+                    xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+                                             dc->slotbuf, &v);
+                    xtensa_operand_decode(isa, opc, opnd, &v);
+                    opcode_add_resource(slot_prop + slot,
+                                        encode_resource(RES_REGFILE, rf, v),
+                                        xtensa_operand_inout(isa, opc, opnd),
+                                        visible ? vopnd : -1);
+                }
+                if (visible) {
+                    ++vopnd;
+                }
+            }
+
+            opnds = xtensa_opcode_num_stateOperands(isa, opc);
+
+            for (opnd = 0; opnd < opnds; ++opnd) {
+                xtensa_state state = xtensa_stateOperand_state(isa, opc, opnd);
+
+                opcode_add_resource(slot_prop + slot,
+                                    encode_resource(RES_STATE, 0, state),
+                                    xtensa_stateOperand_inout(isa, opc, opnd),
+                                    -1);
+            }
+            if (xtensa_opcode_is_branch(isa, opc) ||
+                xtensa_opcode_is_jump(isa, opc) ||
+                xtensa_opcode_is_loop(isa, opc) ||
+                xtensa_opcode_is_call(isa, opc)) {
+                slot_prop[slot].op_flags |= XTENSA_OP_CONTROL_FLOW;
             }
+
+            qsort(slot_prop[slot].in, slot_prop[slot].n_in,
+                  sizeof(slot_prop[slot].in[0]), resource_compare);
+            qsort(slot_prop[slot].out, slot_prop[slot].n_out,
+                  sizeof(slot_prop[slot].out[0]), resource_compare);
         }
-        coprocessor |= ops->coprocessor;
+    }
+
+    if (slots > 1) {
+        if (!tsort(slot_prop, ordered, slots, arg_copy, &n_arg_copy)) {
+            qemu_log_mask(LOG_UNIMP,
+                          "Circular resource dependencies (pc = %08x)\n",
+                          dc->pc);
+            gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+            return;
+        }
+    } else {
+        ordered[0] = slot_prop + 0;
     }
 
     if ((op_flags & XTENSA_OP_PRIVILEGED) &&
@@ -1002,6 +1399,29 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         return;
     }
 
+    if (n_arg_copy) {
+        uint32_t resource;
+        void *temp;
+        unsigned j;
+
+        qsort(arg_copy, n_arg_copy, sizeof(*arg_copy), arg_copy_compare);
+        for (i = j = 0; i < n_arg_copy; ++i) {
+            if (i == 0 || arg_copy[i].resource != resource) {
+                resource = arg_copy[i].resource;
+                temp = tcg_temp_local_new();
+                tcg_gen_mov_i32(temp, arg_copy[i].arg->in);
+                arg_copy[i].temp = temp;
+
+                if (i != j) {
+                    arg_copy[j] = arg_copy[i];
+                }
+                ++j;
+            }
+            arg_copy[i].arg->in = temp;
+        }
+        n_arg_copy = j;
+    }
+
     if (op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
         for (slot = 0; slot < slots; ++slot) {
             if (slot_prop[slot].ops->op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
@@ -1010,29 +1430,31 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         }
     }
 
+    dc->op_flags = op_flags;
+
     for (slot = 0; slot < slots; ++slot) {
-        XtensaOpcodeOps *ops = slot_prop[slot].ops;
+        struct slot_prop *pslot = ordered[slot];
+        XtensaOpcodeOps *ops = pslot->ops;
 
-        dc->raw_arg = slot_prop[slot].raw_arg;
-        ops->translate(dc, slot_prop[slot].arg, ops->par);
+        ops->translate(dc, pslot->arg, ops->par);
     }
 
-    if (dc->base.is_jmp == DISAS_NEXT) {
-        if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
-            gen_check_interrupts(dc);
-        }
+    for (i = 0; i < n_arg_copy; ++i) {
+        tcg_temp_free(arg_copy[i].temp);
+    }
 
+    if (dc->base.is_jmp == DISAS_NEXT) {
+        gen_postprocess(dc, 0);
+        dc->op_flags = 0;
         if (op_flags & XTENSA_OP_EXIT_TB_M1) {
             /* Change in mmu index, memory mapping or tb->flags; exit tb */
             gen_jumpi_check_loop_end(dc, -1);
         } else if (op_flags & XTENSA_OP_EXIT_TB_0) {
             gen_jumpi_check_loop_end(dc, 0);
+        } else {
+            gen_check_loop_end(dc, 0);
         }
     }
-
-    if (dc->base.is_jmp == DISAS_NEXT) {
-        gen_check_loop_end(dc, 0);
-    }
     dc->pc = dc->base.pc_next;
 }
 
@@ -1283,105 +1705,91 @@ void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb,
     env->pc = data[0];
 }
 
-static int compare_opcode_ops(const void *a, const void *b)
-{
-    return strcmp((const char *)a,
-                  ((const XtensaOpcodeOps *)b)->name);
-}
-
-XtensaOpcodeOps *
-xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
-                       const char *name)
-{
-    return bsearch(name, t->opcode, t->num_opcodes,
-                   sizeof(XtensaOpcodeOps), compare_opcode_ops);
-}
-
-static void translate_abs(DisasContext *dc, const uint32_t arg[],
+static void translate_abs(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     TCGv_i32 zero = tcg_const_i32(0);
     TCGv_i32 neg = tcg_temp_new_i32();
 
-    tcg_gen_neg_i32(neg, cpu_R[arg[1]]);
-    tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]],
-                        cpu_R[arg[1]], zero, cpu_R[arg[1]], neg);
+    tcg_gen_neg_i32(neg, arg[1].in);
+    tcg_gen_movcond_i32(TCG_COND_GE, arg[0].out,
+                        arg[1].in, zero, arg[1].in, neg);
     tcg_temp_free(neg);
     tcg_temp_free(zero);
 }
 
-static void translate_add(DisasContext *dc, const uint32_t arg[],
+static void translate_add(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_add_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_addi(DisasContext *dc, const uint32_t arg[],
+static void translate_addi(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+    tcg_gen_addi_i32(arg[0].out, arg[1].in, arg[2].imm);
 }
 
-static void translate_addx(DisasContext *dc, const uint32_t arg[],
+static void translate_addx(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
-    tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+    tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+    tcg_gen_add_i32(arg[0].out, tmp, arg[2].in);
     tcg_temp_free(tmp);
 }
 
-static void translate_all(DisasContext *dc, const uint32_t arg[],
+static void translate_all(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     uint32_t shift = par[1];
-    TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1]);
+    TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1].imm);
     TCGv_i32 tmp = tcg_temp_new_i32();
 
-    tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
+    tcg_gen_and_i32(tmp, arg[1].in, mask);
     if (par[0]) {
-        tcg_gen_addi_i32(tmp, tmp, 1 << arg[1]);
+        tcg_gen_addi_i32(tmp, tmp, 1 << arg[1].imm);
     } else {
         tcg_gen_add_i32(tmp, tmp, mask);
     }
-    tcg_gen_shri_i32(tmp, tmp, arg[1] + shift);
-    tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
-                        tmp, arg[0], 1);
+    tcg_gen_shri_i32(tmp, tmp, arg[1].imm + shift);
+    tcg_gen_deposit_i32(arg[0].out, arg[0].out,
+                        tmp, arg[0].imm, 1);
     tcg_temp_free(mask);
     tcg_temp_free(tmp);
 }
 
-static void translate_and(DisasContext *dc, const uint32_t arg[],
+static void translate_and(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_and_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_ball(DisasContext *dc, const uint32_t arg[],
+static void translate_ball(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
-    gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]);
+    tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+    gen_brcond(dc, par[0], tmp, arg[1].in, arg[2].imm);
     tcg_temp_free(tmp);
 }
 
-static void translate_bany(DisasContext *dc, const uint32_t arg[],
+static void translate_bany(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
-    gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+    tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+    gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
     tcg_temp_free(tmp);
 }
 
-static void translate_b(DisasContext *dc, const uint32_t arg[],
+static void translate_b(DisasContext *dc, const OpcodeArg arg[],
                         const uint32_t par[])
 {
-    gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+    gen_brcond(dc, par[0], arg[0].in, arg[1].in, arg[2].imm);
 }
 
-static void translate_bb(DisasContext *dc, const uint32_t arg[],
+static void translate_bb(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -1390,41 +1798,41 @@ static void translate_bb(DisasContext *dc, const uint32_t arg[],
     TCGv_i32 bit = tcg_const_i32(0x00000001u);
 #endif
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f);
+    tcg_gen_andi_i32(tmp, arg[1].in, 0x1f);
 #ifdef TARGET_WORDS_BIGENDIAN
     tcg_gen_shr_i32(bit, bit, tmp);
 #else
     tcg_gen_shl_i32(bit, bit, tmp);
 #endif
-    tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit);
-    gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+    tcg_gen_and_i32(tmp, arg[0].in, bit);
+    gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
     tcg_temp_free(tmp);
     tcg_temp_free(bit);
 }
 
-static void translate_bbi(DisasContext *dc, const uint32_t arg[],
+static void translate_bbi(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
 #ifdef TARGET_WORDS_BIGENDIAN
-    tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]);
+    tcg_gen_andi_i32(tmp, arg[0].in, 0x80000000u >> arg[1].imm);
 #else
-    tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]);
+    tcg_gen_andi_i32(tmp, arg[0].in, 0x00000001u << arg[1].imm);
 #endif
-    gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+    gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
     tcg_temp_free(tmp);
 }
 
-static void translate_bi(DisasContext *dc, const uint32_t arg[],
+static void translate_bi(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
-    gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]);
+    gen_brcondi(dc, par[0], arg[0].in, arg[1].imm, arg[2].imm);
 }
 
-static void translate_bz(DisasContext *dc, const uint32_t arg[],
+static void translate_bz(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
-    gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]);
+    gen_brcondi(dc, par[0], arg[0].in, 0, arg[1].imm);
 }
 
 enum {
@@ -1435,7 +1843,7 @@ enum {
     BOOLEAN_XOR,
 };
 
-static void translate_boolean(DisasContext *dc, const uint32_t arg[],
+static void translate_boolean(DisasContext *dc, const OpcodeArg arg[],
                               const uint32_t par[])
 {
     static void (* const op[])(TCGv_i32, TCGv_i32, TCGv_i32) = {
@@ -1449,114 +1857,110 @@ static void translate_boolean(DisasContext *dc, const uint32_t arg[],
     TCGv_i32 tmp1 = tcg_temp_new_i32();
     TCGv_i32 tmp2 = tcg_temp_new_i32();
 
-    tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1]);
-    tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2]);
+    tcg_gen_shri_i32(tmp1, arg[1].in, arg[1].imm);
+    tcg_gen_shri_i32(tmp2, arg[2].in, arg[2].imm);
     op[par[0]](tmp1, tmp1, tmp2);
-    tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0], 1);
+    tcg_gen_deposit_i32(arg[0].out, arg[0].out, tmp1, arg[0].imm, 1);
     tcg_temp_free(tmp1);
     tcg_temp_free(tmp2);
 }
 
-static void translate_bp(DisasContext *dc, const uint32_t arg[],
+static void translate_bp(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
 
-    tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0]);
-    gen_brcondi(dc, par[0], tmp, 0, arg[1]);
+    tcg_gen_andi_i32(tmp, arg[0].in, 1 << arg[0].imm);
+    gen_brcondi(dc, par[0], tmp, 0, arg[1].imm);
     tcg_temp_free(tmp);
 }
 
-static void translate_call0(DisasContext *dc, const uint32_t arg[],
+static void translate_call0(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
-    gen_jumpi(dc, arg[0], 0);
-}
-
-static uint32_t test_overflow_callw(DisasContext *dc, const uint32_t arg[],
-                                    const uint32_t par[])
-{
-    return 1 << (par[0] * 4);
+    gen_jumpi(dc, arg[0].imm, 0);
 }
 
-static void translate_callw(DisasContext *dc, const uint32_t arg[],
+static void translate_callw(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_callwi(dc, par[0], arg[0], 0);
+    TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
+    gen_callw_slot(dc, par[0], tmp, adjust_jump_slot(dc, arg[0].imm, 0));
+    tcg_temp_free(tmp);
 }
 
-static void translate_callx0(DisasContext *dc, const uint32_t arg[],
+static void translate_callx0(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
+    tcg_gen_mov_i32(tmp, arg[0].in);
     tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
     gen_jump(dc, tmp);
     tcg_temp_free(tmp);
 }
 
-static void translate_callxw(DisasContext *dc, const uint32_t arg[],
+static void translate_callxw(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
 
-    tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
-    gen_callw(dc, par[0], tmp);
+    tcg_gen_mov_i32(tmp, arg[0].in);
+    gen_callw_slot(dc, par[0], tmp, -1);
     tcg_temp_free(tmp);
 }
 
-static void translate_clamps(DisasContext *dc, const uint32_t arg[],
+static void translate_clamps(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
-    TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]);
-    TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1);
+    TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2].imm);
+    TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2].imm) - 1);
 
-    tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]);
-    tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2);
+    tcg_gen_smax_i32(tmp1, tmp1, arg[1].in);
+    tcg_gen_smin_i32(arg[0].out, tmp1, tmp2);
     tcg_temp_free(tmp1);
     tcg_temp_free(tmp2);
 }
 
-static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_clrb_expstate(DisasContext *dc, const OpcodeArg arg[],
                                     const uint32_t par[])
 {
     /* TODO: GPIO32 may be a part of coprocessor */
-    tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0]));
+    tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0].imm));
 }
 
-static void translate_const16(DisasContext *dc, const uint32_t arg[],
+static void translate_const16(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
-    TCGv_i32 c = tcg_const_i32(arg[1]);
+    TCGv_i32 c = tcg_const_i32(arg[1].imm);
 
-    tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16);
+    tcg_gen_deposit_i32(arg[0].out, c, arg[0].in, 16, 16);
     tcg_temp_free(c);
 }
 
-static void translate_dcache(DisasContext *dc, const uint32_t arg[],
+static void translate_dcache(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
     TCGv_i32 res = tcg_temp_new_i32();
 
-    tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+    tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
     tcg_gen_qemu_ld8u(res, addr, dc->cring);
     tcg_temp_free(addr);
     tcg_temp_free(res);
 }
 
-static void translate_depbits(DisasContext *dc, const uint32_t arg[],
+static void translate_depbits(DisasContext *dc, const OpcodeArg arg[],
                               const uint32_t par[])
 {
-    tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]],
-                        arg[2], arg[3]);
+    tcg_gen_deposit_i32(arg[1].out, arg[1].in, arg[0].in,
+                        arg[2].imm, arg[3].imm);
 }
 
-static bool test_ill_entry(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_entry(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    if (arg[0] > 3 || !dc->cwoe) {
+    if (arg[0].imm > 3 || !dc->cwoe) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "Illegal entry instruction(pc = %08x)\n", dc->pc);
         return true;
@@ -1565,88 +1969,88 @@ static bool test_ill_entry(DisasContext *dc, const uint32_t arg[],
     }
 }
 
-static uint32_t test_overflow_entry(DisasContext *dc, const uint32_t arg[],
+static uint32_t test_overflow_entry(DisasContext *dc, const OpcodeArg arg[],
                                     const uint32_t par[])
 {
     return 1 << (dc->callinc * 4);
 }
 
-static void translate_entry(DisasContext *dc, const uint32_t arg[],
+static void translate_entry(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 pc = tcg_const_i32(dc->pc);
-    TCGv_i32 s = tcg_const_i32(arg[0]);
-    TCGv_i32 imm = tcg_const_i32(arg[1]);
+    TCGv_i32 s = tcg_const_i32(arg[0].imm);
+    TCGv_i32 imm = tcg_const_i32(arg[1].imm);
     gen_helper_entry(cpu_env, pc, s, imm);
     tcg_temp_free(imm);
     tcg_temp_free(s);
     tcg_temp_free(pc);
 }
 
-static void translate_extui(DisasContext *dc, const uint32_t arg[],
+static void translate_extui(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    int maskimm = (1 << arg[3]) - 1;
+    int maskimm = (1 << arg[3].imm) - 1;
 
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]);
-    tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm);
+    tcg_gen_shri_i32(tmp, arg[1].in, arg[2].imm);
+    tcg_gen_andi_i32(arg[0].out, tmp, maskimm);
     tcg_temp_free(tmp);
 }
 
-static void translate_icache(DisasContext *dc, const uint32_t arg[],
+static void translate_icache(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
     TCGv_i32 addr = tcg_temp_new_i32();
 
     tcg_gen_movi_i32(cpu_pc, dc->pc);
-    tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+    tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
     gen_helper_itlb_hit_test(cpu_env, addr);
     tcg_temp_free(addr);
 #endif
 }
 
-static void translate_itlb(DisasContext *dc, const uint32_t arg[],
+static void translate_itlb(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
     TCGv_i32 dtlb = tcg_const_i32(par[0]);
 
-    gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb);
+    gen_helper_itlb(cpu_env, arg[0].in, dtlb);
     tcg_temp_free(dtlb);
 #endif
 }
 
-static void translate_j(DisasContext *dc, const uint32_t arg[],
+static void translate_j(DisasContext *dc, const OpcodeArg arg[],
                         const uint32_t par[])
 {
-    gen_jumpi(dc, arg[0], 0);
+    gen_jumpi(dc, arg[0].imm, 0);
 }
 
-static void translate_jx(DisasContext *dc, const uint32_t arg[],
+static void translate_jx(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
-    gen_jump(dc, cpu_R[arg[0]]);
+    gen_jump(dc, arg[0].in);
 }
 
-static void translate_l32e(DisasContext *dc, const uint32_t arg[],
+static void translate_l32e(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
 
-    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+    tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
     gen_load_store_alignment(dc, 2, addr, false);
-    tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+    tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->ring, MO_TEUL);
     tcg_temp_free(addr);
 }
 
-static void translate_ldst(DisasContext *dc, const uint32_t arg[],
+static void translate_ldst(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
 
-    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+    tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
     if (par[0] & MO_SIZE) {
         gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]);
     }
@@ -1654,9 +2058,9 @@ static void translate_ldst(DisasContext *dc, const uint32_t arg[],
         if (par[1]) {
             tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL);
         }
-        tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+        tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, par[0]);
     } else {
-        tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+        tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, par[0]);
         if (par[1]) {
             tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL);
         }
@@ -1664,33 +2068,33 @@ static void translate_ldst(DisasContext *dc, const uint32_t arg[],
     tcg_temp_free(addr);
 }
 
-static void translate_l32r(DisasContext *dc, const uint32_t arg[],
+static void translate_l32r(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 tmp;
 
     if (dc->base.tb->flags & XTENSA_TBFLAG_LITBASE) {
-        tmp = tcg_const_i32(dc->raw_arg[1] - 1);
+        tmp = tcg_const_i32(arg[1].raw_imm - 1);
         tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp);
     } else {
-        tmp = tcg_const_i32(arg[1]);
+        tmp = tcg_const_i32(arg[1].imm);
     }
-    tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring);
+    tcg_gen_qemu_ld32u(arg[0].out, tmp, dc->cring);
     tcg_temp_free(tmp);
 }
 
-static void translate_loop(DisasContext *dc, const uint32_t arg[],
+static void translate_loop(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    uint32_t lend = arg[1];
+    uint32_t lend = arg[1].imm;
 
-    tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1);
+    tcg_gen_subi_i32(cpu_SR[LCOUNT], arg[0].in, 1);
     tcg_gen_movi_i32(cpu_SR[LBEG], dc->base.pc_next);
     tcg_gen_movi_i32(cpu_SR[LEND], lend);
 
     if (par[0] != TCG_COND_NEVER) {
         TCGLabel *label = gen_new_label();
-        tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label);
+        tcg_gen_brcondi_i32(par[0], arg[0].in, 0, label);
         gen_jumpi(dc, lend, 1);
         gen_set_label(label);
     }
@@ -1716,41 +2120,25 @@ enum {
     MAC16_XH = 0x2,
 };
 
-enum {
-    MAC16_AA,
-    MAC16_AD,
-    MAC16_DA,
-    MAC16_DD,
-
-    MAC16_XD = 0x1,
-    MAC16_DX = 0x2,
-};
-
-static void translate_mac16(DisasContext *dc, const uint32_t arg[],
+static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     int op = par[0];
-    bool is_m1_sr = par[1] & MAC16_DX;
-    bool is_m2_sr = par[1] & MAC16_XD;
-    unsigned half = par[2];
-    uint32_t ld_offset = par[3];
+    unsigned half = par[1];
+    uint32_t ld_offset = par[2];
     unsigned off = ld_offset ? 2 : 0;
     TCGv_i32 vaddr = tcg_temp_new_i32();
     TCGv_i32 mem32 = tcg_temp_new_i32();
 
     if (ld_offset) {
-        tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset);
+        tcg_gen_addi_i32(vaddr, arg[1].in, ld_offset);
         gen_load_store_alignment(dc, 2, vaddr, false);
         tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
     }
     if (op != MAC16_NONE) {
-        TCGv_i32 m1 = gen_mac16_m(is_m1_sr ?
-                                  cpu_SR[MR + arg[off]] :
-                                  cpu_R[arg[off]],
+        TCGv_i32 m1 = gen_mac16_m(arg[off].in,
                                   half & MAC16_HX, op == MAC16_UMUL);
-        TCGv_i32 m2 = gen_mac16_m(is_m2_sr ?
-                                  cpu_SR[MR + arg[off + 1]] :
-                                  cpu_R[arg[off + 1]],
+        TCGv_i32 m2 = gen_mac16_m(arg[off + 1].in,
                                   half & MAC16_XH, op == MAC16_UMUL);
 
         if (op == MAC16_MUL || op == MAC16_UMUL) {
@@ -1784,221 +2172,221 @@ static void translate_mac16(DisasContext *dc, const uint32_t arg[],
         tcg_temp_free(m2);
     }
     if (ld_offset) {
-        tcg_gen_mov_i32(cpu_R[arg[1]], vaddr);
-        tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32);
+        tcg_gen_mov_i32(arg[1].out, vaddr);
+        tcg_gen_mov_i32(cpu_SR[MR + arg[0].imm], mem32);
     }
     tcg_temp_free(vaddr);
     tcg_temp_free(mem32);
 }
 
-static void translate_memw(DisasContext *dc, const uint32_t arg[],
+static void translate_memw(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
 }
 
-static void translate_smin(DisasContext *dc, const uint32_t arg[],
+static void translate_smin(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_smin_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_umin(DisasContext *dc, const uint32_t arg[],
+static void translate_umin(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_umin_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_smax(DisasContext *dc, const uint32_t arg[],
+static void translate_smax(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_smax_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_umax(DisasContext *dc, const uint32_t arg[],
+static void translate_umax(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_umax_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_mov(DisasContext *dc, const uint32_t arg[],
+static void translate_mov(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_mov_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_movcond(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond(DisasContext *dc, const OpcodeArg arg[],
                               const uint32_t par[])
 {
     TCGv_i32 zero = tcg_const_i32(0);
 
-    tcg_gen_movcond_i32(par[0], cpu_R[arg[0]],
-                        cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]);
+    tcg_gen_movcond_i32(par[0], arg[0].out,
+                        arg[2].in, zero, arg[1].in, arg[0].in);
     tcg_temp_free(zero);
 }
 
-static void translate_movi(DisasContext *dc, const uint32_t arg[],
+static void translate_movi(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]);
+    tcg_gen_movi_i32(arg[0].out, arg[1].imm);
 }
 
-static void translate_movp(DisasContext *dc, const uint32_t arg[],
+static void translate_movp(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 zero = tcg_const_i32(0);
     TCGv_i32 tmp = tcg_temp_new_i32();
 
-    tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+    tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
     tcg_gen_movcond_i32(par[0],
-                        cpu_R[arg[0]], tmp, zero,
-                        cpu_R[arg[1]], cpu_R[arg[0]]);
+                        arg[0].out, tmp, zero,
+                        arg[1].in, arg[0].in);
     tcg_temp_free(tmp);
     tcg_temp_free(zero);
 }
 
-static void translate_movsp(DisasContext *dc, const uint32_t arg[],
+static void translate_movsp(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_mov_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_mul16(DisasContext *dc, const uint32_t arg[],
+static void translate_mul16(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 v1 = tcg_temp_new_i32();
     TCGv_i32 v2 = tcg_temp_new_i32();
 
     if (par[0]) {
-        tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]);
-        tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]);
+        tcg_gen_ext16s_i32(v1, arg[1].in);
+        tcg_gen_ext16s_i32(v2, arg[2].in);
     } else {
-        tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]);
-        tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]);
+        tcg_gen_ext16u_i32(v1, arg[1].in);
+        tcg_gen_ext16u_i32(v2, arg[2].in);
     }
-    tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2);
+    tcg_gen_mul_i32(arg[0].out, v1, v2);
     tcg_temp_free(v2);
     tcg_temp_free(v1);
 }
 
-static void translate_mull(DisasContext *dc, const uint32_t arg[],
+static void translate_mull(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_mul_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_mulh(DisasContext *dc, const uint32_t arg[],
+static void translate_mulh(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 lo = tcg_temp_new();
 
     if (par[0]) {
-        tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+        tcg_gen_muls2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
     } else {
-        tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+        tcg_gen_mulu2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
     }
     tcg_temp_free(lo);
 }
 
-static void translate_neg(DisasContext *dc, const uint32_t arg[],
+static void translate_neg(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_neg_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_nop(DisasContext *dc, const uint32_t arg[],
+static void translate_nop(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
 }
 
-static void translate_nsa(DisasContext *dc, const uint32_t arg[],
+static void translate_nsa(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_clrsb_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_nsau(DisasContext *dc, const uint32_t arg[],
+static void translate_nsau(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32);
+    tcg_gen_clzi_i32(arg[0].out, arg[1].in, 32);
 }
 
-static void translate_or(DisasContext *dc, const uint32_t arg[],
+static void translate_or(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
-    tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_or_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_ptlb(DisasContext *dc, const uint32_t arg[],
+static void translate_ptlb(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
     TCGv_i32 dtlb = tcg_const_i32(par[0]);
 
     tcg_gen_movi_i32(cpu_pc, dc->pc);
-    gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+    gen_helper_ptlb(arg[0].out, cpu_env, arg[1].in, dtlb);
     tcg_temp_free(dtlb);
 #endif
 }
 
-static void translate_quos(DisasContext *dc, const uint32_t arg[],
+static void translate_quos(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGLabel *label1 = gen_new_label();
     TCGLabel *label2 = gen_new_label();
 
-    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000,
+    tcg_gen_brcondi_i32(TCG_COND_NE, arg[1].in, 0x80000000,
                         label1);
-    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff,
+    tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0xffffffff,
                         label1);
-    tcg_gen_movi_i32(cpu_R[arg[0]],
+    tcg_gen_movi_i32(arg[0].out,
                      par[0] ? 0x80000000 : 0);
     tcg_gen_br(label2);
     gen_set_label(label1);
     if (par[0]) {
-        tcg_gen_div_i32(cpu_R[arg[0]],
-                        cpu_R[arg[1]], cpu_R[arg[2]]);
+        tcg_gen_div_i32(arg[0].out,
+                        arg[1].in, arg[2].in);
     } else {
-        tcg_gen_rem_i32(cpu_R[arg[0]],
-                        cpu_R[arg[1]], cpu_R[arg[2]]);
+        tcg_gen_rem_i32(arg[0].out,
+                        arg[1].in, arg[2].in);
     }
     gen_set_label(label2);
 }
 
-static void translate_quou(DisasContext *dc, const uint32_t arg[],
+static void translate_quou(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_divu_i32(cpu_R[arg[0]],
-                     cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_divu_i32(arg[0].out,
+                     arg[1].in, arg[2].in);
 }
 
-static void translate_read_impwire(DisasContext *dc, const uint32_t arg[],
+static void translate_read_impwire(DisasContext *dc, const OpcodeArg arg[],
                                    const uint32_t par[])
 {
     /* TODO: GPIO32 may be a part of coprocessor */
-    tcg_gen_movi_i32(cpu_R[arg[0]], 0);
+    tcg_gen_movi_i32(arg[0].out, 0);
 }
 
-static void translate_remu(DisasContext *dc, const uint32_t arg[],
+static void translate_remu(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_remu_i32(cpu_R[arg[0]],
-                     cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_remu_i32(arg[0].out,
+                     arg[1].in, arg[2].in);
 }
 
-static void translate_rer(DisasContext *dc, const uint32_t arg[],
+static void translate_rer(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]);
+    gen_helper_rer(arg[0].out, cpu_env, arg[1].in);
 }
 
-static void translate_ret(DisasContext *dc, const uint32_t arg[],
+static void translate_ret(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     gen_jump(dc, cpu_R[0]);
 }
 
-static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_retw(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (!dc->cwoe) {
@@ -2014,36 +2402,41 @@ static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
     }
 }
 
-static void translate_retw(DisasContext *dc, const uint32_t arg[],
+static void translate_retw(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    TCGv_i32 tmp = tcg_const_i32(dc->pc);
-    gen_helper_retw(tmp, cpu_env, tmp);
+    TCGv_i32 tmp = tcg_const_i32(1);
+    tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
+    tcg_gen_andc_i32(cpu_SR[WINDOW_START],
+                     cpu_SR[WINDOW_START], tmp);
+    tcg_gen_movi_i32(tmp, dc->pc);
+    tcg_gen_deposit_i32(tmp, tmp, cpu_R[0], 0, 30);
+    gen_helper_retw(cpu_env, cpu_R[0]);
     gen_jump(dc, tmp);
     tcg_temp_free(tmp);
 }
 
-static void translate_rfde(DisasContext *dc, const uint32_t arg[],
+static void translate_rfde(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]);
 }
 
-static void translate_rfe(DisasContext *dc, const uint32_t arg[],
+static void translate_rfe(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
     gen_jump(dc, cpu_SR[EPC1]);
 }
 
-static void translate_rfi(DisasContext *dc, const uint32_t arg[],
+static void translate_rfi(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]);
-    gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]);
+    tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0].imm - 2]);
+    gen_jump(dc, cpu_SR[EPC1 + arg[0].imm - 1]);
 }
 
-static void translate_rfw(DisasContext *dc, const uint32_t arg[],
+static void translate_rfw(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_const_i32(1);
@@ -2064,35 +2457,33 @@ static void translate_rfw(DisasContext *dc, const uint32_t arg[],
     gen_jump(dc, cpu_SR[EPC1]);
 }
 
-static void translate_rotw(DisasContext *dc, const uint32_t arg[],
+static void translate_rotw(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    TCGv_i32 tmp = tcg_const_i32(arg[0]);
-    gen_helper_rotw(cpu_env, tmp);
-    tcg_temp_free(tmp);
+    tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0].imm);
 }
 
-static void translate_rsil(DisasContext *dc, const uint32_t arg[],
+static void translate_rsil(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]);
+    tcg_gen_mov_i32(arg[0].out, cpu_SR[PS]);
     tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
-    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]);
+    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1].imm);
 }
 
-static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_rsr(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
     return !check_sr(dc, par[0], SR_R);
 }
 
-static void translate_rsr(DisasContext *dc, const uint32_t arg[],
+static void translate_rsr(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_rsr(dc, cpu_R[arg[0]], par[0]);
+    gen_rsr(dc, arg[0].out, par[0]);
 }
 
-static void translate_rtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
@@ -2103,26 +2494,26 @@ static void translate_rtlb(DisasContext *dc, const uint32_t arg[],
     };
     TCGv_i32 dtlb = tcg_const_i32(par[0]);
 
-    helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+    helper[par[1]](arg[0].out, cpu_env, arg[1].in, dtlb);
     tcg_temp_free(dtlb);
 #endif
 }
 
-static void translate_rur(DisasContext *dc, const uint32_t arg[],
+static void translate_rur(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (uregnames[par[0]].name) {
-        tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]);
+        tcg_gen_mov_i32(arg[0].out, cpu_UR[par[0]]);
     } else {
         qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]);
     }
 }
 
-static void translate_setb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_setb_expstate(DisasContext *dc, const OpcodeArg arg[],
                                     const uint32_t par[])
 {
     /* TODO: GPIO32 may be a part of coprocessor */
-    tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0]);
+    tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0].imm);
 }
 
 #ifdef CONFIG_USER_ONLY
@@ -2139,59 +2530,59 @@ static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr)
 }
 #endif
 
-static void translate_s32c1i(DisasContext *dc, const uint32_t arg[],
+static void translate_s32c1i(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_local_new_i32();
     TCGv_i32 addr = tcg_temp_local_new_i32();
 
-    tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
-    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+    tcg_gen_mov_i32(tmp, arg[0].in);
+    tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
     gen_load_store_alignment(dc, 2, addr, true);
     gen_check_atomctl(dc, addr);
-    tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1],
+    tcg_gen_atomic_cmpxchg_i32(arg[0].out, addr, cpu_SR[SCOMPARE1],
                                tmp, dc->cring, MO_TEUL);
     tcg_temp_free(addr);
     tcg_temp_free(tmp);
 }
 
-static void translate_s32e(DisasContext *dc, const uint32_t arg[],
+static void translate_s32e(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
 
-    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+    tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
     gen_load_store_alignment(dc, 2, addr, false);
-    tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+    tcg_gen_qemu_st_tl(arg[0].in, addr, dc->ring, MO_TEUL);
     tcg_temp_free(addr);
 }
 
-static void translate_salt(DisasContext *dc, const uint32_t arg[],
+static void translate_salt(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     tcg_gen_setcond_i32(par[0],
-                        cpu_R[arg[0]],
-                        cpu_R[arg[1]], cpu_R[arg[2]]);
+                        arg[0].out,
+                        arg[1].in, arg[2].in);
 }
 
-static void translate_sext(DisasContext *dc, const uint32_t arg[],
+static void translate_sext(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    int shift = 31 - arg[2];
+    int shift = 31 - arg[2].imm;
 
     if (shift == 24) {
-        tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+        tcg_gen_ext8s_i32(arg[0].out, arg[1].in);
     } else if (shift == 16) {
-        tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+        tcg_gen_ext16s_i32(arg[0].out, arg[1].in);
     } else {
         TCGv_i32 tmp = tcg_temp_new_i32();
-        tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift);
-        tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift);
+        tcg_gen_shli_i32(tmp, arg[1].in, shift);
+        tcg_gen_sari_i32(arg[0].out, tmp, shift);
         tcg_temp_free(tmp);
     }
 }
 
-static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_simcall(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
 #ifdef CONFIG_USER_ONLY
@@ -2205,7 +2596,7 @@ static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[],
     return ill;
 }
 
-static void translate_simcall(DisasContext *dc, const uint32_t arg[],
+static void translate_simcall(DisasContext *dc, const OpcodeArg arg[],
                               const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
@@ -2221,73 +2612,73 @@ static void translate_simcall(DisasContext *dc, const uint32_t arg[],
                     TCGv_i64 tmp = tcg_temp_new_i64(); \
                     tcg_gen_extu_i32_i64(tmp, reg); \
                     tcg_gen_##cmd##_i64(v, v, tmp); \
-                    tcg_gen_extrl_i64_i32(cpu_R[arg[0]], v); \
+                    tcg_gen_extrl_i64_i32(arg[0].out, v); \
                     tcg_temp_free_i64(v); \
                     tcg_temp_free_i64(tmp); \
                 } while (0)
 
 #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
 
-static void translate_sll(DisasContext *dc, const uint32_t arg[],
+static void translate_sll(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (dc->sar_m32_5bit) {
-        tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32);
+        tcg_gen_shl_i32(arg[0].out, arg[1].in, dc->sar_m32);
     } else {
         TCGv_i64 v = tcg_temp_new_i64();
         TCGv_i32 s = tcg_const_i32(32);
         tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
         tcg_gen_andi_i32(s, s, 0x3f);
-        tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+        tcg_gen_extu_i32_i64(v, arg[1].in);
         gen_shift_reg(shl, s);
         tcg_temp_free(s);
     }
 }
 
-static void translate_slli(DisasContext *dc, const uint32_t arg[],
+static void translate_slli(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    if (arg[2] == 32) {
+    if (arg[2].imm == 32) {
         qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n",
-                      arg[0], arg[1]);
+                      arg[0].imm, arg[1].imm);
     }
-    tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f);
+    tcg_gen_shli_i32(arg[0].out, arg[1].in, arg[2].imm & 0x1f);
 }
 
-static void translate_sra(DisasContext *dc, const uint32_t arg[],
+static void translate_sra(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (dc->sar_m32_5bit) {
-        tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+        tcg_gen_sar_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
     } else {
         TCGv_i64 v = tcg_temp_new_i64();
-        tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]);
+        tcg_gen_ext_i32_i64(v, arg[1].in);
         gen_shift(sar);
     }
 }
 
-static void translate_srai(DisasContext *dc, const uint32_t arg[],
+static void translate_srai(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+    tcg_gen_sari_i32(arg[0].out, arg[1].in, arg[2].imm);
 }
 
-static void translate_src(DisasContext *dc, const uint32_t arg[],
+static void translate_src(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     TCGv_i64 v = tcg_temp_new_i64();
-    tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]);
+    tcg_gen_concat_i32_i64(v, arg[2].in, arg[1].in);
     gen_shift(shr);
 }
 
-static void translate_srl(DisasContext *dc, const uint32_t arg[],
+static void translate_srl(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (dc->sar_m32_5bit) {
-        tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+        tcg_gen_shr_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
     } else {
         TCGv_i64 v = tcg_temp_new_i64();
-        tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+        tcg_gen_extu_i32_i64(v, arg[1].in);
         gen_shift(shr);
     }
 }
@@ -2295,138 +2686,138 @@ static void translate_srl(DisasContext *dc, const uint32_t arg[],
 #undef gen_shift
 #undef gen_shift_reg
 
-static void translate_srli(DisasContext *dc, const uint32_t arg[],
+static void translate_srli(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+    tcg_gen_shri_i32(arg[0].out, arg[1].in, arg[2].imm);
 }
 
-static void translate_ssa8b(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8b(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+    tcg_gen_shli_i32(tmp, arg[0].in, 3);
     gen_left_shift_sar(dc, tmp);
     tcg_temp_free(tmp);
 }
 
-static void translate_ssa8l(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8l(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+    tcg_gen_shli_i32(tmp, arg[0].in, 3);
     gen_right_shift_sar(dc, tmp);
     tcg_temp_free(tmp);
 }
 
-static void translate_ssai(DisasContext *dc, const uint32_t arg[],
+static void translate_ssai(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
-    TCGv_i32 tmp = tcg_const_i32(arg[0]);
+    TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
     gen_right_shift_sar(dc, tmp);
     tcg_temp_free(tmp);
 }
 
-static void translate_ssl(DisasContext *dc, const uint32_t arg[],
+static void translate_ssl(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_left_shift_sar(dc, cpu_R[arg[0]]);
+    gen_left_shift_sar(dc, arg[0].in);
 }
 
-static void translate_ssr(DisasContext *dc, const uint32_t arg[],
+static void translate_ssr(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_right_shift_sar(dc, cpu_R[arg[0]]);
+    gen_right_shift_sar(dc, arg[0].in);
 }
 
-static void translate_sub(DisasContext *dc, const uint32_t arg[],
+static void translate_sub(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_sub_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static void translate_subx(DisasContext *dc, const uint32_t arg[],
+static void translate_subx(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
     TCGv_i32 tmp = tcg_temp_new_i32();
-    tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
-    tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+    tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+    tcg_gen_sub_i32(arg[0].out, tmp, arg[2].in);
     tcg_temp_free(tmp);
 }
 
-static void translate_waiti(DisasContext *dc, const uint32_t arg[],
+static void translate_waiti(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
-    gen_waiti(dc, arg[0]);
+    gen_waiti(dc, arg[0].imm);
 #endif
 }
 
-static void translate_wtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_wtlb(DisasContext *dc, const OpcodeArg arg[],
                            const uint32_t par[])
 {
 #ifndef CONFIG_USER_ONLY
     TCGv_i32 dtlb = tcg_const_i32(par[0]);
 
-    gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb);
+    gen_helper_wtlb(cpu_env, arg[0].in, arg[1].in, dtlb);
     tcg_temp_free(dtlb);
 #endif
 }
 
-static void translate_wer(DisasContext *dc, const uint32_t arg[],
+static void translate_wer(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]);
+    gen_helper_wer(cpu_env, arg[0].in, arg[1].in);
 }
 
-static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_wrmsk_expstate(DisasContext *dc, const OpcodeArg arg[],
                                      const uint32_t par[])
 {
     /* TODO: GPIO32 may be a part of coprocessor */
-    tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_and_i32(cpu_UR[EXPSTATE], arg[0].in, arg[1].in);
 }
 
-static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_wsr(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
     return !check_sr(dc, par[0], SR_W);
 }
 
-static void translate_wsr(DisasContext *dc, const uint32_t arg[],
+static void translate_wsr(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    gen_wsr(dc, par[0], cpu_R[arg[0]]);
+    gen_wsr(dc, par[0], arg[0].in);
 }
 
-static void translate_wur(DisasContext *dc, const uint32_t arg[],
+static void translate_wur(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
     if (uregnames[par[0]].name) {
-        gen_wur(par[0], cpu_R[arg[0]]);
+        gen_wur(par[0], arg[0].in);
     } else {
         qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]);
     }
 }
 
-static void translate_xor(DisasContext *dc, const uint32_t arg[],
+static void translate_xor(DisasContext *dc, const OpcodeArg arg[],
                           const uint32_t par[])
 {
-    tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_xor_i32(arg[0].out, arg[1].in, arg[2].in);
 }
 
-static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_xsr(DisasContext *dc, const OpcodeArg arg[],
                          const uint32_t par[])
 {
     return !check_sr(dc, par[0], SR_X);
 }
 
-static void translate_xsr(DisasContext *dc, const uint32_t arg[],
+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, cpu_R[arg[0]]);
-    gen_rsr(dc, cpu_R[arg[0]], par[0]);
+    tcg_gen_mov_i32(tmp, arg[0].in);
+    gen_rsr(dc, arg[0].out, par[0]);
     gen_wsr(dc, par[0], tmp);
     tcg_temp_free(tmp);
 }
@@ -2435,42 +2826,33 @@ static const XtensaOpcodeOps core_ops[] = {
     {
         .name = "abs",
         .translate = translate_abs,
-        .windowed_register_op = 0x3,
     }, {
-        .name = "add",
+        .name = (const char * const[]) {
+            "add", "add.n", NULL,
+        },
         .translate = translate_add,
-        .windowed_register_op = 0x7,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "add.n",
-        .translate = translate_add,
-        .windowed_register_op = 0x7,
-    }, {
-        .name = "addi",
-        .translate = translate_addi,
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "addi.n",
+        .name = (const char * const[]) {
+            "addi", "addi.n", NULL,
+        },
         .translate = translate_addi,
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "addmi",
         .translate = translate_addi,
-        .windowed_register_op = 0x3,
     }, {
         .name = "addx2",
         .translate = translate_addx,
         .par = (const uint32_t[]){1},
-        .windowed_register_op = 0x7,
     }, {
         .name = "addx4",
         .translate = translate_addx,
         .par = (const uint32_t[]){2},
-        .windowed_register_op = 0x7,
     }, {
         .name = "addx8",
         .translate = translate_addx,
         .par = (const uint32_t[]){3},
-        .windowed_register_op = 0x7,
     }, {
         .name = "all4",
         .translate = translate_all,
@@ -2482,7 +2864,6 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "and",
         .translate = translate_and,
-        .windowed_register_op = 0x7,
     }, {
         .name = "andb",
         .translate = translate_boolean,
@@ -2500,139 +2881,177 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_all,
         .par = (const uint32_t[]){false, 8},
     }, {
-        .name = "ball",
+        .name = (const char * const[]) {
+            "ball", "ball.w15", "ball.w18", NULL,
+        },
         .translate = translate_ball,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bany",
+        .name = (const char * const[]) {
+            "bany", "bany.w15", "bany.w18", NULL,
+        },
         .translate = translate_bany,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bbc",
+        .name = (const char * const[]) {
+            "bbc", "bbc.w15", "bbc.w18", NULL,
+        },
         .translate = translate_bb,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bbci",
+        .name = (const char * const[]) {
+            "bbci", "bbci.w15", "bbci.w18", NULL,
+        },
         .translate = translate_bbi,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bbs",
+        .name = (const char * const[]) {
+            "bbs", "bbs.w15", "bbs.w18", NULL,
+        },
         .translate = translate_bb,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bbsi",
+        .name = (const char * const[]) {
+            "bbsi", "bbsi.w15", "bbsi.w18", NULL,
+        },
         .translate = translate_bbi,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "beq",
+        .name = (const char * const[]) {
+            "beq", "beq.w15", "beq.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "beqi",
+        .name = (const char * const[]) {
+            "beqi", "beqi.w15", "beqi.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x1,
-    }, {
-        .name = "beqz",
-        .translate = translate_bz,
-        .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "beqz.n",
+        .name = (const char * const[]) {
+            "beqz", "beqz.n", "beqz.w15", "beqz.w18", NULL,
+        },
         .translate = translate_bz,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "bf",
         .translate = translate_bp,
         .par = (const uint32_t[]){TCG_COND_EQ},
     }, {
-        .name = "bge",
+        .name = (const char * const[]) {
+            "bge", "bge.w15", "bge.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_GE},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bgei",
+        .name = (const char * const[]) {
+            "bgei", "bgei.w15", "bgei.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_GE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bgeu",
+        .name = (const char * const[]) {
+            "bgeu", "bgeu.w15", "bgeu.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_GEU},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bgeui",
+        .name = (const char * const[]) {
+            "bgeui", "bgeui.w15", "bgeui.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_GEU},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bgez",
+        .name = (const char * const[]) {
+            "bgez", "bgez.w15", "bgez.w18", NULL,
+        },
         .translate = translate_bz,
         .par = (const uint32_t[]){TCG_COND_GE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "blt",
+        .name = (const char * const[]) {
+            "blt", "blt.w15", "blt.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "blti",
+        .name = (const char * const[]) {
+            "blti", "blti.w15", "blti.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bltu",
+        .name = (const char * const[]) {
+            "bltu", "bltu.w15", "bltu.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_LTU},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bltui",
+        .name = (const char * const[]) {
+            "bltui", "bltui.w15", "bltui.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_LTU},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bltz",
+        .name = (const char * const[]) {
+            "bltz", "bltz.w15", "bltz.w18", NULL,
+        },
         .translate = translate_bz,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bnall",
+        .name = (const char * const[]) {
+            "bnall", "bnall.w15", "bnall.w18", NULL,
+        },
         .translate = translate_ball,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bne",
+        .name = (const char * const[]) {
+            "bne", "bne.w15", "bne.w18", NULL,
+        },
         .translate = translate_b,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bnei",
+        .name = (const char * const[]) {
+            "bnei", "bnei.w15", "bnei.w18", NULL,
+        },
         .translate = translate_bi,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bnez",
+        .name = (const char * const[]) {
+            "bnez", "bnez.n", "bnez.w15", "bnez.w18", NULL,
+        },
         .translate = translate_bz,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "bnez.n",
-        .translate = translate_bz,
-        .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x1,
-    }, {
-        .name = "bnone",
+        .name = (const char * const[]) {
+            "bnone", "bnone.w15", "bnone.w18", NULL,
+        },
         .translate = translate_bany,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "break",
         .translate = translate_nop,
@@ -2653,114 +3072,88 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "call12",
         .translate = translate_callw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){3},
     }, {
         .name = "call4",
         .translate = translate_callw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){1},
     }, {
         .name = "call8",
         .translate = translate_callw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){2},
     }, {
         .name = "callx0",
         .translate = translate_callx0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "callx12",
         .translate = translate_callxw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){3},
-        .windowed_register_op = 0x1,
     }, {
         .name = "callx4",
         .translate = translate_callxw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "callx8",
         .translate = translate_callxw,
-        .test_overflow = test_overflow_callw,
         .par = (const uint32_t[]){2},
-        .windowed_register_op = 0x1,
     }, {
         .name = "clamps",
         .translate = translate_clamps,
-        .windowed_register_op = 0x3,
     }, {
         .name = "clrb_expstate",
         .translate = translate_clrb_expstate,
     }, {
         .name = "const16",
         .translate = translate_const16,
-        .windowed_register_op = 0x1,
     }, {
         .name = "depbits",
         .translate = translate_depbits,
-        .windowed_register_op = 0x3,
     }, {
         .name = "dhi",
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dhu",
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dhwb",
         .translate = translate_dcache,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dhwbi",
         .translate = translate_dcache,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dii",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "diu",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "diwb",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "diwbi",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dpfl",
         .translate = translate_dcache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dpfr",
         .translate = translate_nop,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dpfro",
         .translate = translate_nop,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dpfw",
         .translate = translate_nop,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dpfwo",
         .translate = translate_nop,
-        .windowed_register_op = 0x1,
     }, {
         .name = "dsync",
         .translate = translate_nop,
@@ -2769,7 +3162,8 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_entry,
         .test_ill = test_ill_entry,
         .test_overflow = test_overflow_entry,
-        .op_flags = XTENSA_OP_EXIT_TB_M1,
+        .op_flags = XTENSA_OP_EXIT_TB_M1 |
+            XTENSA_OP_SYNC_REGISTER_WINDOW,
     }, {
         .name = "esync",
         .translate = translate_nop,
@@ -2779,7 +3173,6 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "extui",
         .translate = translate_extui,
-        .windowed_register_op = 0x3,
     }, {
         .name = "extw",
         .translate = translate_memw,
@@ -2794,47 +3187,38 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_itlb,
         .par = (const uint32_t[]){true},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ihi",
         .translate = translate_icache,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ihu",
         .translate = translate_icache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "iii",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "iitlb",
         .translate = translate_itlb,
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "iiu",
         .translate = translate_nop,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
-        .name = "ill",
-        .op_flags = XTENSA_OP_ILL,
-    }, {
-        .name = "ill.n",
-        .op_flags = XTENSA_OP_ILL,
+        .name = (const char * const[]) {
+            "ill", "ill.n", NULL,
+        },
+        .op_flags = XTENSA_OP_ILL | XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "ipf",
         .translate = translate_nop,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ipfl",
         .translate = translate_icache,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "isync",
         .translate = translate_nop,
@@ -2844,498 +3228,423 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "jx",
         .translate = translate_jx,
-        .windowed_register_op = 0x1,
     }, {
         .name = "l16si",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TESW, false, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "l16ui",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUW, false, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "l32ai",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUL, true, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "l32e",
         .translate = translate_l32e,
-        .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "l32i",
-        .translate = translate_ldst,
-        .par = (const uint32_t[]){MO_TEUL, false, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_LOAD,
     }, {
-        .name = "l32i.n",
+        .name = (const char * const[]) {
+            "l32i", "l32i.n", NULL,
+        },
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUL, false, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_LOAD,
     }, {
         .name = "l32r",
         .translate = translate_l32r,
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "l8ui",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_UB, false, false},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_NONE, 0, 0, -4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_NONE, 0, -4},
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_NONE, 0, 4},
+        .op_flags = XTENSA_OP_LOAD,
     }, {
         .name = "ldpte",
         .op_flags = XTENSA_OP_ILL,
     }, {
-        .name = "loop",
+        .name = (const char * const[]) {
+            "loop", "loop.w15", NULL,
+        },
         .translate = translate_loop,
         .par = (const uint32_t[]){TCG_COND_NEVER},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "loopgtz",
+        .name = (const char * const[]) {
+            "loopgtz", "loopgtz.w15", NULL,
+        },
         .translate = translate_loop,
         .par = (const uint32_t[]){TCG_COND_GT},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "loopnez",
+        .name = (const char * const[]) {
+            "loopnez", "loopnez.w15", NULL,
+        },
         .translate = translate_loop,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x1,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "max",
         .translate = translate_smax,
-        .windowed_register_op = 0x7,
     }, {
         .name = "maxu",
         .translate = translate_umax,
-        .windowed_register_op = 0x7,
     }, {
         .name = "memw",
         .translate = translate_memw,
     }, {
         .name = "min",
         .translate = translate_smin,
-        .windowed_register_op = 0x7,
     }, {
         .name = "minu",
         .translate = translate_umin,
-        .windowed_register_op = 0x7,
     }, {
-        .name = "mov",
+        .name = (const char * const[]) {
+            "mov", "mov.n", NULL,
+        },
         .translate = translate_mov,
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "mov.n",
-        .translate = translate_mov,
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "moveqz",
         .translate = translate_movcond,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x7,
     }, {
         .name = "movf",
         .translate = translate_movp,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x3,
     }, {
         .name = "movgez",
         .translate = translate_movcond,
         .par = (const uint32_t[]){TCG_COND_GE},
-        .windowed_register_op = 0x7,
     }, {
         .name = "movi",
         .translate = translate_movi,
-        .windowed_register_op = 0x1,
     }, {
         .name = "movi.n",
         .translate = translate_movi,
-        .windowed_register_op = 0x1,
     }, {
         .name = "movltz",
         .translate = translate_movcond,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x7,
     }, {
         .name = "movnez",
         .translate = translate_movcond,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x7,
     }, {
         .name = "movsp",
         .translate = translate_movsp,
-        .windowed_register_op = 0x3,
         .op_flags = XTENSA_OP_ALLOCA,
     }, {
         .name = "movt",
         .translate = translate_movp,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x3,
     }, {
         .name = "mul.aa.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
     }, {
         .name = "mul.aa.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
     }, {
         .name = "mul.aa.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
     }, {
         .name = "mul.aa.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
     }, {
         .name = "mul.ad.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
     }, {
         .name = "mul.ad.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
     }, {
         .name = "mul.ad.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
     }, {
         .name = "mul.ad.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
     }, {
         .name = "mul.da.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
     }, {
         .name = "mul.da.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
     }, {
         .name = "mul.da.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
     }, {
         .name = "mul.da.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
     }, {
         .name = "mul.dd.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HH, 0},
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
     }, {
         .name = "mul.dd.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HL, 0},
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
     }, {
         .name = "mul.dd.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LH, 0},
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
     }, {
         .name = "mul.dd.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LL, 0},
+        .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
     }, {
         .name = "mul16s",
         .translate = translate_mul16,
         .par = (const uint32_t[]){true},
-        .windowed_register_op = 0x7,
     }, {
         .name = "mul16u",
         .translate = translate_mul16,
         .par = (const uint32_t[]){false},
-        .windowed_register_op = 0x7,
     }, {
         .name = "mula.aa.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
     }, {
         .name = "mula.aa.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
     }, {
         .name = "mula.aa.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
     }, {
         .name = "mula.aa.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
     }, {
         .name = "mula.ad.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
     }, {
         .name = "mula.ad.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
     }, {
         .name = "mula.ad.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
     }, {
         .name = "mula.ad.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
     }, {
         .name = "mula.da.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
     }, {
         .name = "mula.da.hh.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, -4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
     }, {
         .name = "mula.da.hh.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
     }, {
         .name = "mula.da.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
     }, {
         .name = "mula.da.hl.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, -4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
     }, {
         .name = "mula.da.hl.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
     }, {
         .name = "mula.da.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
     }, {
         .name = "mula.da.lh.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, -4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
     }, {
         .name = "mula.da.lh.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
     }, {
         .name = "mula.da.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
     }, {
         .name = "mula.da.ll.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, -4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
     }, {
         .name = "mula.da.ll.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 4},
-        .windowed_register_op = 0xa,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
     }, {
         .name = "mula.dd.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 0},
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
     }, {
         .name = "mula.dd.hh.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, -4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
     }, {
         .name = "mula.dd.hh.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
     }, {
         .name = "mula.dd.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 0},
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
     }, {
         .name = "mula.dd.hl.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, -4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
     }, {
         .name = "mula.dd.hl.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
     }, {
         .name = "mula.dd.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 0},
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
     }, {
         .name = "mula.dd.lh.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, -4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
     }, {
         .name = "mula.dd.lh.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
     }, {
         .name = "mula.dd.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 0},
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
     }, {
         .name = "mula.dd.ll.lddec",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, -4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
     }, {
         .name = "mula.dd.ll.ldinc",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 4},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
     }, {
         .name = "mull",
         .translate = translate_mull,
-        .windowed_register_op = 0x7,
     }, {
         .name = "muls.aa.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
     }, {
         .name = "muls.aa.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
     }, {
         .name = "muls.aa.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
     }, {
         .name = "muls.aa.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
     }, {
         .name = "muls.ad.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
     }, {
         .name = "muls.ad.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
     }, {
         .name = "muls.ad.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LH, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
     }, {
         .name = "muls.ad.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LL, 0},
-        .windowed_register_op = 0x1,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
     }, {
         .name = "muls.da.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
     }, {
         .name = "muls.da.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
     }, {
         .name = "muls.da.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LH, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
     }, {
         .name = "muls.da.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LL, 0},
-        .windowed_register_op = 0x2,
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
     }, {
         .name = "muls.dd.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HH, 0},
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
     }, {
         .name = "muls.dd.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HL, 0},
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
     }, {
         .name = "muls.dd.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LH, 0},
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
     }, {
         .name = "muls.dd.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LL, 0},
+        .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
     }, {
         .name = "mulsh",
         .translate = translate_mulh,
         .par = (const uint32_t[]){true},
-        .windowed_register_op = 0x7,
     }, {
         .name = "muluh",
         .translate = translate_mulh,
         .par = (const uint32_t[]){false},
-        .windowed_register_op = 0x7,
     }, {
         .name = "neg",
         .translate = translate_neg,
-        .windowed_register_op = 0x3,
     }, {
-        .name = "nop",
-        .translate = translate_nop,
-    }, {
-        .name = "nop.n",
+        .name = (const char * const[]) {
+            "nop", "nop.n", NULL,
+        },
         .translate = translate_nop,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "nsa",
         .translate = translate_nsa,
-        .windowed_register_op = 0x3,
     }, {
         .name = "nsau",
         .translate = translate_nsau,
-        .windowed_register_op = 0x3,
     }, {
         .name = "or",
         .translate = translate_or,
-        .windowed_register_op = 0x7,
     }, {
         .name = "orb",
         .translate = translate_boolean,
@@ -3349,72 +3658,59 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_ptlb,
         .par = (const uint32_t[]){true},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "pitlb",
         .translate = translate_ptlb,
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "quos",
         .translate = translate_quos,
         .par = (const uint32_t[]){true},
         .op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
-        .windowed_register_op = 0x7,
     }, {
         .name = "quou",
         .translate = translate_quou,
         .op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
-        .windowed_register_op = 0x7,
     }, {
         .name = "rdtlb0",
         .translate = translate_rtlb,
         .par = (const uint32_t[]){true, 0},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "rdtlb1",
         .translate = translate_rtlb,
         .par = (const uint32_t[]){true, 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "read_impwire",
         .translate = translate_read_impwire,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rems",
         .translate = translate_quos,
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
-        .windowed_register_op = 0x7,
     }, {
         .name = "remu",
         .translate = translate_remu,
         .op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
-        .windowed_register_op = 0x7,
     }, {
         .name = "rer",
         .translate = translate_rer,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "ret",
-        .translate = translate_ret,
     }, {
-        .name = "ret.n",
+        .name = (const char * const[]) {
+            "ret", "ret.n", NULL,
+        },
         .translate = translate_ret,
+        .op_flags = XTENSA_OP_NAME_ARRAY,
     }, {
-        .name = "retw",
+        .name = (const char * const[]) {
+            "retw", "retw.n", NULL,
+        },
         .translate = translate_retw,
         .test_ill = test_ill_retw,
-        .op_flags = XTENSA_OP_UNDERFLOW,
-    }, {
-        .name = "retw.n",
-        .translate = translate_retw,
-        .test_ill = test_ill_retw,
-        .op_flags = XTENSA_OP_UNDERFLOW,
+        .op_flags = XTENSA_OP_UNDERFLOW | XTENSA_OP_NAME_ARRAY,
     }, {
         .name = "rfdd",
         .op_flags = XTENSA_OP_ILL,
@@ -3448,17 +3744,17 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_rtlb,
         .par = (const uint32_t[]){false, 0},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "ritlb1",
         .translate = translate_rtlb,
         .par = (const uint32_t[]){false, 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "rotw",
         .translate = translate_rotw,
-        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+        .op_flags = XTENSA_OP_PRIVILEGED |
+            XTENSA_OP_EXIT_TB_M1 |
+            XTENSA_OP_SYNC_REGISTER_WINDOW,
     }, {
         .name = "rsil",
         .translate = translate_rsil,
@@ -3466,526 +3762,454 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.176",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){176},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.208",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){208},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.acchi",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ACCHI},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.acclo",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ACCLO},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.atomctl",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ATOMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.br",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){BR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.cacheattr",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CACHEATTR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ccompare0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CCOMPARE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ccompare1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CCOMPARE + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ccompare2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CCOMPARE + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ccount",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CCOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.configid0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CONFIGID0},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.configid1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CONFIGID1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.cpenable",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){CPENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.dbreaka0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.dbreaka1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.dbreakc0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DBREAKC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.dbreakc1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DBREAKC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ddr",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.debugcause",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DEBUGCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.depc",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DEPC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.dtlbcfg",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){DTLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc3",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc4",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc5",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc6",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.epc7",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPC1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps3",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps4",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps5",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps6",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.eps7",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EPS2 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.exccause",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave3",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave4",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave5",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave6",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excsave7",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCSAVE1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.excvaddr",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){EXCVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ibreaka0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){IBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ibreaka1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){IBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ibreakenable",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){IBREAKENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.icount",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ICOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.icountlevel",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ICOUNTLEVEL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.intclear",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){INTCLEAR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.intenable",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){INTENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.interrupt",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){INTSET},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.intset",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){INTSET},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.itlbcfg",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){ITLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.lbeg",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){LBEG},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.lcount",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){LCOUNT},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.lend",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){LEND},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.litbase",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){LITBASE},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.m0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.m1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MR + 1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.m2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MR + 2},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.m3",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MR + 3},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.memctl",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.misc0",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MISC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.misc1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MISC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.misc2",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MISC + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.misc3",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){MISC + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
+    }, {
+        .name = "rsr.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},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ps",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){PS},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.ptevaddr",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){PTEVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.rasid",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){RASID},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.sar",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){SAR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.scompare1",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){SCOMPARE1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.vecbase",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){VECBASE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.windowbase",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){WINDOW_BASE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsr.windowstart",
         .translate = translate_rsr,
         .test_ill = test_ill_rsr,
         .par = (const uint32_t[]){WINDOW_START},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "rsync",
         .translate = translate_nop,
@@ -3993,80 +4217,64 @@ static const XtensaOpcodeOps core_ops[] = {
         .name = "rur.expstate",
         .translate = translate_rur,
         .par = (const uint32_t[]){EXPSTATE},
-        .windowed_register_op = 0x1,
     }, {
         .name = "rur.fcr",
         .translate = translate_rur,
         .par = (const uint32_t[]){FCR},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "rur.fsr",
         .translate = translate_rur,
         .par = (const uint32_t[]){FSR},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "rur.threadptr",
         .translate = translate_rur,
         .par = (const uint32_t[]){THREADPTR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "s16i",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUW, false, true},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_STORE,
     }, {
         .name = "s32c1i",
         .translate = translate_s32c1i,
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_LOAD | XTENSA_OP_STORE,
     }, {
         .name = "s32e",
         .translate = translate_s32e,
-        .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "s32i",
-        .translate = translate_ldst,
-        .par = (const uint32_t[]){MO_TEUL, false, true},
-        .windowed_register_op = 0x3,
-    }, {
-        .name = "s32i.n",
-        .translate = translate_ldst,
-        .par = (const uint32_t[]){MO_TEUL, false, true},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_STORE,
     }, {
-        .name = "s32nb",
+        .name = (const char * const[]) {
+            "s32i", "s32i.n", "s32nb", NULL,
+        },
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUL, false, true},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_STORE,
     }, {
         .name = "s32ri",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_TEUL, true, true},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_STORE,
     }, {
         .name = "s8i",
         .translate = translate_ldst,
         .par = (const uint32_t[]){MO_UB, false, true},
-        .windowed_register_op = 0x3,
+        .op_flags = XTENSA_OP_STORE,
     }, {
         .name = "salt",
         .translate = translate_salt,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x7,
     }, {
         .name = "saltu",
         .translate = translate_salt,
         .par = (const uint32_t[]){TCG_COND_LTU},
-        .windowed_register_op = 0x7,
     }, {
         .name = "setb_expstate",
         .translate = translate_setb_expstate,
     }, {
         .name = "sext",
         .translate = translate_sext,
-        .windowed_register_op = 0x3,
     }, {
         .name = "simcall",
         .translate = translate_simcall,
@@ -4075,92 +4283,73 @@ static const XtensaOpcodeOps core_ops[] = {
     }, {
         .name = "sll",
         .translate = translate_sll,
-        .windowed_register_op = 0x3,
     }, {
         .name = "slli",
         .translate = translate_slli,
-        .windowed_register_op = 0x3,
     }, {
         .name = "sra",
         .translate = translate_sra,
-        .windowed_register_op = 0x3,
     }, {
         .name = "srai",
         .translate = translate_srai,
-        .windowed_register_op = 0x3,
     }, {
         .name = "src",
         .translate = translate_src,
-        .windowed_register_op = 0x7,
     }, {
         .name = "srl",
         .translate = translate_srl,
-        .windowed_register_op = 0x3,
     }, {
         .name = "srli",
         .translate = translate_srli,
-        .windowed_register_op = 0x3,
     }, {
         .name = "ssa8b",
         .translate = translate_ssa8b,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ssa8l",
         .translate = translate_ssa8l,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ssai",
         .translate = translate_ssai,
     }, {
         .name = "ssl",
         .translate = translate_ssl,
-        .windowed_register_op = 0x1,
     }, {
         .name = "ssr",
         .translate = translate_ssr,
-        .windowed_register_op = 0x1,
     }, {
         .name = "sub",
         .translate = translate_sub,
-        .windowed_register_op = 0x7,
     }, {
         .name = "subx2",
         .translate = translate_subx,
         .par = (const uint32_t[]){1},
-        .windowed_register_op = 0x7,
     }, {
         .name = "subx4",
         .translate = translate_subx,
         .par = (const uint32_t[]){2},
-        .windowed_register_op = 0x7,
     }, {
         .name = "subx8",
         .translate = translate_subx,
         .par = (const uint32_t[]){3},
-        .windowed_register_op = 0x7,
     }, {
         .name = "syscall",
         .op_flags = XTENSA_OP_SYSCALL,
     }, {
         .name = "umul.aa.hh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_UMUL, MAC16_HH, 0},
     }, {
         .name = "umul.aa.hl",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_UMUL, MAC16_HL, 0},
     }, {
         .name = "umul.aa.lh",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LH, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_UMUL, MAC16_LH, 0},
     }, {
         .name = "umul.aa.ll",
         .translate = translate_mac16,
-        .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LL, 0},
-        .windowed_register_op = 0x3,
+        .par = (const uint32_t[]){MAC16_UMUL, MAC16_LL, 0},
     }, {
         .name = "waiti",
         .translate = translate_waiti,
@@ -4170,362 +4359,309 @@ static const XtensaOpcodeOps core_ops[] = {
         .translate = translate_wtlb,
         .par = (const uint32_t[]){true},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x3,
     }, {
         .name = "wer",
         .translate = translate_wer,
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x3,
     }, {
         .name = "witlb",
         .translate = translate_wtlb,
         .par = (const uint32_t[]){false},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x3,
     }, {
         .name = "wrmsk_expstate",
         .translate = translate_wrmsk_expstate,
-        .windowed_register_op = 0x3,
     }, {
         .name = "wsr.176",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){176},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.208",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){208},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.acchi",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ACCHI},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.acclo",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ACCLO},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.atomctl",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ATOMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.br",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){BR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.cacheattr",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CACHEATTR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ccompare0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CCOMPARE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ccompare1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CCOMPARE + 1},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ccompare2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CCOMPARE + 2},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ccount",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CCOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.configid0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CONFIGID0},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.configid1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CONFIGID1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.cpenable",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){CPENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.dbreaka0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.dbreaka1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.dbreakc0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DBREAKC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.dbreakc1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DBREAKC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ddr",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.debugcause",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DEBUGCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.depc",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DEPC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.dtlbcfg",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){DTLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc3",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc4",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc5",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc6",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.epc7",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPC1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps3",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps4",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps5",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps6",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.eps7",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EPS2 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.exccause",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave3",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave4",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave5",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave6",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excsave7",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCSAVE1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.excvaddr",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){EXCVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ibreaka0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){IBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ibreaka1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){IBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ibreakenable",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){IBREAKENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.icount",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ICOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.icountlevel",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ICOUNTLEVEL},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.intclear",
         .translate = translate_wsr,
@@ -4535,7 +4671,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.intenable",
         .translate = translate_wsr,
@@ -4545,7 +4680,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.interrupt",
         .translate = translate_wsr,
@@ -4555,7 +4689,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.intset",
         .translate = translate_wsr,
@@ -4565,114 +4698,102 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.itlbcfg",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){ITLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.lbeg",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){LBEG},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.lcount",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){LCOUNT},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.lend",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){LEND},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.litbase",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){LITBASE},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.m0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.m1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MR + 1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.m2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MR + 2},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.m3",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MR + 3},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.memctl",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.misc0",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MISC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.misc1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MISC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.misc2",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MISC + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.misc3",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MISC + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.mmid",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){MMID},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
+    }, {
+        .name = "wsr.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,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ps",
         .translate = translate_wsr,
@@ -4682,80 +4803,69 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.ptevaddr",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){PTEVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.rasid",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){RASID},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.sar",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){SAR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.scompare1",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){SCOMPARE1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.vecbase",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){VECBASE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wsr.windowbase",
         .translate = translate_wsr,
         .test_ill = test_ill_wsr,
         .par = (const uint32_t[]){WINDOW_BASE},
-        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
+        .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},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "wur.expstate",
         .translate = translate_wur,
         .par = (const uint32_t[]){EXPSTATE},
-        .windowed_register_op = 0x1,
     }, {
         .name = "wur.fcr",
         .translate = translate_wur,
         .par = (const uint32_t[]){FCR},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "wur.fsr",
         .translate = translate_wur,
         .par = (const uint32_t[]){FSR},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "wur.threadptr",
         .translate = translate_wur,
         .par = (const uint32_t[]){THREADPTR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xor",
         .translate = translate_xor,
-        .windowed_register_op = 0x7,
     }, {
         .name = "xorb",
         .translate = translate_boolean,
@@ -4766,340 +4876,291 @@ static const XtensaOpcodeOps core_ops[] = {
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){176},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.208",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){208},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.acchi",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ACCHI},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.acclo",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ACCLO},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.atomctl",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ATOMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.br",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){BR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.cacheattr",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CACHEATTR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ccompare0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CCOMPARE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ccompare1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CCOMPARE + 1},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ccompare2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CCOMPARE + 2},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ccount",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CCOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.configid0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CONFIGID0},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.configid1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CONFIGID1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.cpenable",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){CPENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.dbreaka0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.dbreaka1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.dbreakc0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DBREAKC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.dbreakc1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DBREAKC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ddr",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.debugcause",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DEBUGCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.depc",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DEPC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.dtlbcfg",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){DTLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc3",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc4",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc5",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc6",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.epc7",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPC1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps3",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps4",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps5",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps6",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.eps7",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EPS2 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.exccause",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCCAUSE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave3",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave4",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave5",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 4},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave6",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 5},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excsave7",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCSAVE1 + 6},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.excvaddr",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){EXCVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ibreaka0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){IBREAKA},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ibreaka1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){IBREAKA + 1},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ibreakenable",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){IBREAKENABLE},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.icount",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ICOUNT},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.icountlevel",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ICOUNTLEVEL},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.intclear",
         .translate = translate_xsr,
@@ -5109,7 +5170,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.intenable",
         .translate = translate_xsr,
@@ -5119,7 +5179,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.interrupt",
         .translate = translate_xsr,
@@ -5129,7 +5188,6 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.intset",
         .translate = translate_xsr,
@@ -5139,107 +5197,96 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_0 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.itlbcfg",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){ITLBCFG},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.lbeg",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){LBEG},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.lcount",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){LCOUNT},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.lend",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){LEND},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.litbase",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){LITBASE},
         .op_flags = XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.m0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.m1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MR + 1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.m2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MR + 2},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.m3",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MR + 3},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.memctl",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MEMCTL},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.misc0",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MISC},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.misc1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MISC + 1},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.misc2",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MISC + 2},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.misc3",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){MISC + 3},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
+    }, {
+        .name = "xsr.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,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ps",
         .translate = translate_xsr,
@@ -5249,54 +5296,48 @@ static const XtensaOpcodeOps core_ops[] = {
             XTENSA_OP_PRIVILEGED |
             XTENSA_OP_EXIT_TB_M1 |
             XTENSA_OP_CHECK_INTERRUPTS,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.ptevaddr",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){PTEVADDR},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.rasid",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){RASID},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.sar",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){SAR},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.scompare1",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){SCOMPARE1},
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.vecbase",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){VECBASE},
         .op_flags = XTENSA_OP_PRIVILEGED,
-        .windowed_register_op = 0x1,
     }, {
         .name = "xsr.windowbase",
         .translate = translate_xsr,
         .test_ill = test_ill_xsr,
         .par = (const uint32_t[]){WINDOW_BASE},
-        .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
+        .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},
         .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
-        .windowed_register_op = 0x1,
     },
 };
 
@@ -5306,17 +5347,17 @@ const XtensaOpcodeTranslators xtensa_core_opcodes = {
 };
 
 
-static void translate_abs_s(DisasContext *dc, const uint32_t arg[],
+static void translate_abs_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+    gen_helper_abs_s(arg[0].out, arg[1].in);
 }
 
-static void translate_add_s(DisasContext *dc, const uint32_t arg[],
+static void translate_add_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_helper_add_s(cpu_FR[arg[0]], cpu_env,
-                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    gen_helper_add_s(arg[0].out, cpu_env,
+                     arg[1].in, arg[2].in);
 }
 
 enum {
@@ -5329,7 +5370,7 @@ enum {
     COMPARE_ULE,
 };
 
-static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
+static void translate_compare_s(DisasContext *dc, const OpcodeArg arg[],
                                 const uint32_t par[])
 {
     static void (* const helper[])(TCGv_env env, TCGv_i32 bit,
@@ -5342,153 +5383,153 @@ static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
         [COMPARE_OLE] = gen_helper_ole_s,
         [COMPARE_ULE] = gen_helper_ule_s,
     };
-    TCGv_i32 bit = tcg_const_i32(1 << arg[0]);
+    TCGv_i32 bit = tcg_const_i32(1 << arg[0].imm);
 
-    helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    helper[par[0]](cpu_env, bit, arg[1].in, arg[2].in);
     tcg_temp_free(bit);
 }
 
-static void translate_float_s(DisasContext *dc, const uint32_t arg[],
+static void translate_float_s(DisasContext *dc, const OpcodeArg arg[],
                               const uint32_t par[])
 {
-    TCGv_i32 scale = tcg_const_i32(-arg[2]);
+    TCGv_i32 scale = tcg_const_i32(-arg[2].imm);
 
     if (par[0]) {
-        gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+        gen_helper_uitof(arg[0].out, cpu_env, arg[1].in, scale);
     } else {
-        gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+        gen_helper_itof(arg[0].out, cpu_env, arg[1].in, scale);
     }
     tcg_temp_free(scale);
 }
 
-static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[],
+static void translate_ftoi_s(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 rounding_mode = tcg_const_i32(par[0]);
-    TCGv_i32 scale = tcg_const_i32(arg[2]);
+    TCGv_i32 scale = tcg_const_i32(arg[2].imm);
 
     if (par[1]) {
-        gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]],
+        gen_helper_ftoui(arg[0].out, arg[1].in,
                          rounding_mode, scale);
     } else {
-        gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]],
+        gen_helper_ftoi(arg[0].out, arg[1].in,
                         rounding_mode, scale);
     }
     tcg_temp_free(rounding_mode);
     tcg_temp_free(scale);
 }
 
-static void translate_ldsti(DisasContext *dc, const uint32_t arg[],
+static void translate_ldsti(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
 
-    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+    tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
     gen_load_store_alignment(dc, 2, addr, false);
     if (par[0]) {
-        tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+        tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
     } else {
-        tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+        tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
     }
     if (par[1]) {
-        tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+        tcg_gen_mov_i32(arg[1].out, addr);
     }
     tcg_temp_free(addr);
 }
 
-static void translate_ldstx(DisasContext *dc, const uint32_t arg[],
+static void translate_ldstx(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
     TCGv_i32 addr = tcg_temp_new_i32();
 
-    tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]);
+    tcg_gen_add_i32(addr, arg[1].in, arg[2].in);
     gen_load_store_alignment(dc, 2, addr, false);
     if (par[0]) {
-        tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+        tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
     } else {
-        tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+        tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
     }
     if (par[1]) {
-        tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+        tcg_gen_mov_i32(arg[1].out, addr);
     }
     tcg_temp_free(addr);
 }
 
-static void translate_madd_s(DisasContext *dc, const uint32_t arg[],
+static void translate_madd_s(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
-    gen_helper_madd_s(cpu_FR[arg[0]], cpu_env,
-                      cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    gen_helper_madd_s(arg[0].out, cpu_env,
+                      arg[0].in, arg[1].in, arg[2].in);
 }
 
-static void translate_mov_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mov_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+    tcg_gen_mov_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_movcond_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond_s(DisasContext *dc, const OpcodeArg arg[],
                                 const uint32_t par[])
 {
     TCGv_i32 zero = tcg_const_i32(0);
 
-    tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]],
-                        cpu_R[arg[2]], zero,
-                        cpu_FR[arg[1]], cpu_FR[arg[0]]);
+    tcg_gen_movcond_i32(par[0], arg[0].out,
+                        arg[2].in, zero,
+                        arg[1].in, arg[0].in);
     tcg_temp_free(zero);
 }
 
-static void translate_movp_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
     TCGv_i32 zero = tcg_const_i32(0);
     TCGv_i32 tmp = tcg_temp_new_i32();
 
-    tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+    tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
     tcg_gen_movcond_i32(par[0],
-                        cpu_FR[arg[0]], tmp, zero,
-                        cpu_FR[arg[1]], cpu_FR[arg[0]]);
+                        arg[0].out, tmp, zero,
+                        arg[1].in, arg[0].in);
     tcg_temp_free(tmp);
     tcg_temp_free(zero);
 }
 
-static void translate_mul_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mul_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_helper_mul_s(cpu_FR[arg[0]], cpu_env,
-                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    gen_helper_mul_s(arg[0].out, cpu_env,
+                     arg[1].in, arg[2].in);
 }
 
-static void translate_msub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_msub_s(DisasContext *dc, const OpcodeArg arg[],
                              const uint32_t par[])
 {
-    gen_helper_msub_s(cpu_FR[arg[0]], cpu_env,
-                      cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    gen_helper_msub_s(arg[0].out, cpu_env,
+                      arg[0].in, arg[1].in, arg[2].in);
 }
 
-static void translate_neg_s(DisasContext *dc, const uint32_t arg[],
+static void translate_neg_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+    gen_helper_neg_s(arg[0].out, arg[1].in);
 }
 
-static void translate_rfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_rfr_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]);
+    tcg_gen_mov_i32(arg[0].out, arg[1].in);
 }
 
-static void translate_sub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_sub_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    gen_helper_sub_s(cpu_FR[arg[0]], cpu_env,
-                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
+    gen_helper_sub_s(arg[0].out, cpu_env,
+                     arg[1].in, arg[2].in);
 }
 
-static void translate_wfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_wfr_s(DisasContext *dc, const OpcodeArg arg[],
                             const uint32_t par[])
 {
-    tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]);
+    tcg_gen_mov_i32(arg[0].out, arg[1].in);
 }
 
 static const XtensaOpcodeOps fpu2000_ops[] = {
@@ -5504,43 +5545,40 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "ceil.s",
         .translate = translate_ftoi_s,
         .par = (const uint32_t[]){float_round_up, false},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "float.s",
         .translate = translate_float_s,
         .par = (const uint32_t[]){false},
-        .windowed_register_op = 0x2,
         .coprocessor = 0x1,
     }, {
         .name = "floor.s",
         .translate = translate_ftoi_s,
         .par = (const uint32_t[]){float_round_down, false},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "lsi",
         .translate = translate_ldsti,
         .par = (const uint32_t[]){false, false},
-        .windowed_register_op = 0x2,
+        .op_flags = XTENSA_OP_LOAD,
         .coprocessor = 0x1,
     }, {
         .name = "lsiu",
         .translate = translate_ldsti,
         .par = (const uint32_t[]){false, true},
-        .windowed_register_op = 0x2,
+        .op_flags = XTENSA_OP_LOAD,
         .coprocessor = 0x1,
     }, {
         .name = "lsx",
         .translate = translate_ldstx,
         .par = (const uint32_t[]){false, false},
-        .windowed_register_op = 0x6,
+        .op_flags = XTENSA_OP_LOAD,
         .coprocessor = 0x1,
     }, {
         .name = "lsxu",
         .translate = translate_ldstx,
         .par = (const uint32_t[]){false, true},
-        .windowed_register_op = 0x6,
+        .op_flags = XTENSA_OP_LOAD,
         .coprocessor = 0x1,
     }, {
         .name = "madd.s",
@@ -5554,7 +5592,6 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "moveqz.s",
         .translate = translate_movcond_s,
         .par = (const uint32_t[]){TCG_COND_EQ},
-        .windowed_register_op = 0x4,
         .coprocessor = 0x1,
     }, {
         .name = "movf.s",
@@ -5565,19 +5602,16 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "movgez.s",
         .translate = translate_movcond_s,
         .par = (const uint32_t[]){TCG_COND_GE},
-        .windowed_register_op = 0x4,
         .coprocessor = 0x1,
     }, {
         .name = "movltz.s",
         .translate = translate_movcond_s,
         .par = (const uint32_t[]){TCG_COND_LT},
-        .windowed_register_op = 0x4,
         .coprocessor = 0x1,
     }, {
         .name = "movnez.s",
         .translate = translate_movcond_s,
         .par = (const uint32_t[]){TCG_COND_NE},
-        .windowed_register_op = 0x4,
         .coprocessor = 0x1,
     }, {
         .name = "movt.s",
@@ -5614,37 +5648,35 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
     }, {
         .name = "rfr",
         .translate = translate_rfr_s,
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "round.s",
         .translate = translate_ftoi_s,
         .par = (const uint32_t[]){float_round_nearest_even, false},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "ssi",
         .translate = translate_ldsti,
         .par = (const uint32_t[]){true, false},
-        .windowed_register_op = 0x2,
+        .op_flags = XTENSA_OP_STORE,
         .coprocessor = 0x1,
     }, {
         .name = "ssiu",
         .translate = translate_ldsti,
         .par = (const uint32_t[]){true, true},
-        .windowed_register_op = 0x2,
+        .op_flags = XTENSA_OP_STORE,
         .coprocessor = 0x1,
     }, {
         .name = "ssx",
         .translate = translate_ldstx,
         .par = (const uint32_t[]){true, false},
-        .windowed_register_op = 0x6,
+        .op_flags = XTENSA_OP_STORE,
         .coprocessor = 0x1,
     }, {
         .name = "ssxu",
         .translate = translate_ldstx,
         .par = (const uint32_t[]){true, true},
-        .windowed_register_op = 0x6,
+        .op_flags = XTENSA_OP_STORE,
         .coprocessor = 0x1,
     }, {
         .name = "sub.s",
@@ -5654,7 +5686,6 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "trunc.s",
         .translate = translate_ftoi_s,
         .par = (const uint32_t[]){float_round_to_zero, false},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "ueq.s",
@@ -5665,7 +5696,6 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "ufloat.s",
         .translate = translate_float_s,
         .par = (const uint32_t[]){true},
-        .windowed_register_op = 0x2,
         .coprocessor = 0x1,
     }, {
         .name = "ule.s",
@@ -5686,12 +5716,10 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
         .name = "utrunc.s",
         .translate = translate_ftoi_s,
         .par = (const uint32_t[]){float_round_to_zero, true},
-        .windowed_register_op = 0x1,
         .coprocessor = 0x1,
     }, {
         .name = "wfr",
         .translate = translate_wfr_s,
-        .windowed_register_op = 0x2,
         .coprocessor = 0x1,
     },
 };
diff --git a/target/xtensa/win_helper.c b/target/xtensa/win_helper.c
index 7d793d4f9c..f6f96a64c3 100644
--- a/target/xtensa/win_helper.c
+++ b/target/xtensa/win_helper.c
@@ -96,9 +96,9 @@ void xtensa_rotate_window(CPUXtensaState *env, uint32_t delta)
     xtensa_rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta);
 }
 
-void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
+void HELPER(sync_windowbase)(CPUXtensaState *env)
 {
-    xtensa_rotate_window_abs(env, v);
+    xtensa_rotate_window_abs(env, env->windowbase_next);
 }
 
 void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
@@ -106,9 +106,8 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
     int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
 
     env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
-    xtensa_rotate_window(env, callinc);
-    env->sregs[WINDOW_START] |=
-        windowstart_bit(env->sregs[WINDOW_BASE], env);
+    env->windowbase_next = env->sregs[WINDOW_BASE] + callinc;
+    env->sregs[WINDOW_START] |= windowstart_bit(env->windowbase_next, env);
 }
 
 void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
@@ -185,20 +184,11 @@ void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc)
     }
 }
 
-uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
+void HELPER(retw)(CPUXtensaState *env, uint32_t a0)
 {
-    int n = (env->regs[0] >> 30) & 0x3;
-    uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
-    uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
+    int n = (a0 >> 30) & 0x3;
 
     xtensa_rotate_window(env, -n);
-    env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
-    return ret_pc;
-}
-
-void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4)
-{
-    xtensa_rotate_window(env, imm4);
 }
 
 void xtensa_restore_owb(CPUXtensaState *env)