:p
atchew
Login
The following changes since commit 314f2d7fe601b8dba2a88ac4870469e9f6bb8464: Merge tag 'qtest-20260217-pull-request' of https://gitlab.com/farosas/qemu into staging (2026-02-17 16:46:05 +0000) are available in the Git repository at: https://gitlab.com/pm215/qemu.git tags/pull-target-arm-20260219 for you to fetch changes up to 10059583c7bfea50c1596310b0639669e93ce1ee: include/tcg/tcg-op.h: eradicate TARGET_INSN_START_EXTRA_WORDS (2026-02-19 10:12:25 +0000) ---------------------------------------------------------------- target-arm queue: * Allow TCG to emulate CPUs with SME but not SVE * Refactorings for single-binary * whpx: minor fixes * hw/usb/hcd-ohci: Implement frame number overflow event ---------------------------------------------------------------- BALATON Zoltan (1): hw/usb/hcd-ohci: Implement frame number overflow event Osama Abdelkader (2): whpx: remove duplicate include whpx: fix FP register loop Peter Maydell (17): target/arm: Account for SME in aarch64_sve_narrow_vq() assertion target/arm: Report correct vector width in gdbstub when SME present target/arm: Fix feature check in DO_SVE2_RRX, DO_SVE2_RRX_TB target/arm/tcg: Allow SVE RAX1 in SME2p1 streaming mode target/arm: Don't let 'sme=on' downgrade SME target/arm: Handle SME-only CPUs in sve_vqm1_for_el_sm() target/arm: Handle SME-without-SVE on change of EL target/arm: Add aa64_sme_or_sve, aa64_sme_or_sve2 features target/arm/tcg: Drop unnecessary aa64_sve check from do_trans_pmull() target/arm/tcg: Use "or SME" feature checks where needed target/arm/tcg: Correct SVE/SME I8MM checks target/arm/tcg: Correct SVE/SME BF16 checks target/arm: Don't squash all ID_AA64ZFR0_EL1 fields for non-SVE target/arm: Squash FEAT_SME_FA64 if FEAT_SVE is not present target/arm: Permit configurations with SME but not SVE target/arm: Move TCG-specific code out of debug_helper.c target/arm: Don't require helper prototypes in helper.c Pierrick Bouvier (12): target/arm: extract helper-mve.h from helper.h target/arm: extract helper-a64.h from helper.h target/arm: extract helper-sve.h from helper.h target/arm: extract helper-sme.h from helper.h tcg: move tcg_use_softmmu to tcg/tcg-internal.h target/arm: move exec/helper-* plumbery to helper.h target/arm/tcg/psci.c: make compilation unit common target/arm/tcg/cpu-v7m.c: make compilation unit common target/arm/tcg/vec_helper.c: make compilation unit common target/arm/tcg/translate.h: replace target_ulong with vaddr target/arm/tcg/translate.h: replace target_long with int64_t include/tcg/tcg-op.h: eradicate TARGET_INSN_START_EXTRA_WORDS docs/system/arm/cpu-features.rst | 20 +- hw/usb/hcd-ohci.c | 4 + include/tcg/tcg-op-common.h | 8 + include/tcg/tcg-op.h | 29 - include/tcg/tcg.h | 6 - target/alpha/cpu-param.h | 2 - target/alpha/translate.c | 4 +- target/arm/cpu-features.h | 27 +- target/arm/cpu-param.h | 7 - target/arm/cpu.c | 10 - target/arm/cpu64.c | 36 +- target/arm/debug_helper.c | 769 ------------------ target/arm/gdbstub64.c | 12 +- target/arm/helper-a64.h | 14 + target/arm/helper-mve.h | 14 + target/arm/helper-sme.h | 14 + target/arm/helper-sve.h | 14 + target/arm/helper.c | 19 +- target/arm/helper.h | 17 +- target/arm/internals.h | 9 + target/arm/tcg/arith_helper.c | 4 +- target/arm/tcg/crypto_helper.c | 4 +- target/arm/tcg/debug.c | 780 ++++++++++++++++++ target/arm/tcg/gengvec64.c | 3 +- target/arm/tcg/{helper-a64.h => helper-a64-defs.h} | 0 target/arm/tcg/helper-a64.c | 6 +- target/arm/tcg/{helper.h => helper-defs.h} | 0 target/arm/tcg/{helper-mve.h => helper-mve-defs.h} | 0 target/arm/tcg/{helper-sme.h => helper-sme-defs.h} | 0 target/arm/tcg/{helper-sve.h => helper-sve-defs.h} | 0 target/arm/tcg/hflags.c | 4 +- target/arm/tcg/m_helper.c | 2 +- target/arm/tcg/meson.build | 13 +- target/arm/tcg/mte_helper.c | 3 +- target/arm/tcg/mve_helper.c | 6 +- target/arm/tcg/neon_helper.c | 4 +- target/arm/tcg/op_helper.c | 2 +- target/arm/tcg/pauth_helper.c | 3 +- target/arm/tcg/psci.c | 4 +- target/arm/tcg/sme_helper.c | 5 +- target/arm/tcg/sve_helper.c | 6 +- target/arm/tcg/tlb_helper.c | 4 +- target/arm/tcg/translate-a32.h | 2 +- target/arm/tcg/translate-a64.c | 3 + target/arm/tcg/translate-mve.c | 1 + target/arm/tcg/translate-sme.c | 3 + target/arm/tcg/translate-sve.c | 894 +++++++++++---------- target/arm/tcg/translate.c | 28 +- target/arm/tcg/translate.h | 22 +- target/arm/tcg/vec_helper.c | 224 +----- target/arm/tcg/vec_helper64.c | 142 ++++ target/arm/tcg/vec_internal.h | 49 ++ target/arm/tcg/vfp_helper.c | 4 +- target/arm/whpx/whpx-all.c | 5 +- target/avr/cpu-param.h | 2 - target/avr/translate.c | 2 +- target/hexagon/cpu-param.h | 2 - target/hexagon/translate.c | 2 +- target/hppa/cpu-param.h | 2 - target/i386/cpu-param.h | 2 - target/i386/tcg/translate.c | 2 +- target/loongarch/cpu-param.h | 2 - target/loongarch/tcg/translate.c | 2 +- target/m68k/cpu-param.h | 2 - target/m68k/translate.c | 2 +- target/microblaze/cpu-param.h | 2 - target/microblaze/translate.c | 2 +- target/mips/cpu-param.h | 2 - target/or1k/cpu-param.h | 2 - target/or1k/translate.c | 2 +- target/ppc/cpu-param.h | 2 - target/ppc/translate.c | 2 +- target/riscv/cpu-param.h | 7 - target/rx/cpu-param.h | 2 - target/rx/translate.c | 2 +- target/s390x/cpu-param.h | 2 - target/sh4/cpu-param.h | 2 - target/sh4/translate.c | 4 +- target/sparc/cpu-param.h | 2 - target/sparc/translate.c | 2 +- target/tricore/cpu-param.h | 2 - target/tricore/translate.c | 2 +- target/xtensa/cpu-param.h | 2 - target/xtensa/translate.c | 2 +- tcg/tcg-internal.h | 6 + tcg/tcg.c | 4 - 86 files changed, 1722 insertions(+), 1620 deletions(-) create mode 100644 target/arm/helper-a64.h create mode 100644 target/arm/helper-mve.h create mode 100644 target/arm/helper-sme.h create mode 100644 target/arm/helper-sve.h create mode 100644 target/arm/tcg/debug.c rename target/arm/tcg/{helper-a64.h => helper-a64-defs.h} (100%) rename target/arm/tcg/{helper.h => helper-defs.h} (100%) rename target/arm/tcg/{helper-mve.h => helper-mve-defs.h} (100%) rename target/arm/tcg/{helper-sme.h => helper-sme-defs.h} (100%) rename target/arm/tcg/{helper-sve.h => helper-sve-defs.h} (100%) create mode 100644 target/arm/tcg/vec_helper64.c
In aarch64_sve_narrow_vq() we assert that the new VQ is within the maximum supported range for the CPU. We forgot to update this to account for SME, which might have a different maximum. Update the assert to permit any VQ which is valid for either SVE or SME. Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-2-peter.maydell@linaro.org --- target/arm/helper.c | 2 +- target/arm/internals.h | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) uint64_t pmask; assert(vq >= 1 && vq <= ARM_MAX_VQ); - assert(vq <= env_archcpu(env)->sve_max_vq); + assert(vq <= arm_max_vq(env_archcpu(env))); /* Zap the high bits of the zregs. */ for (i = 0; i < 32; i++) { diff --git a/target/arm/internals.h b/target/arm/internals.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -XXX,XX +XXX,XX @@ static inline uint64_t arm_mdcr_el2_eff(CPUARMState *env) ((1 << (1 - 1)) | (1 << (2 - 1)) | \ (1 << (4 - 1)) | (1 << (8 - 1)) | (1 << (16 - 1))) +/* + * Return the maximum SVE/SME VQ for this CPU. This defines + * the maximum possible size of the Zn vector registers. + */ +static inline int arm_max_vq(ARMCPU *cpu) +{ + return MAX(cpu->sve_max_vq, cpu->sme_max_vq); +} + /* * Return true if it is possible to take a fine-grained-trap to EL2. */ -- 2.43.0
Our gdbstub implementation of the org.gnu.gdb.aarch64.sve feature doesn't account for SME correctly. We always report the Zn vector registers with a width based on the maximum SVE vector register size, even though SME's maximum size could be larger. This is particularly bad in the case of a CPU with SME but not SVE, because there the SVE vector width will be zero. If we report the Zn registers in the XML as having a zero width then gdb falls over with an internal error: (gdb) target remote :1234 Remote debugging using :1234 /build/gdb-1WjiBe/gdb-15.0.50.20240403/gdb/aarch64-tdep.c:3066: internal-error: aarch64_pseudo_register_type: bad register number 160 A problem internal to GDB has been detected, further debugging may prove unreliable. Report the Zn registers with their correct size. This matches how we already handle the 'vg' pseudoregister in org.gnu.gdb.aarch64.sve: we call sve_vqm1_for_el(), which returns the vector size accounting for SME, not the pure SVE vector size. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20260202133353.2231685-3-peter.maydell@linaro.org --- target/arm/gdbstub64.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -XXX,XX +XXX,XX @@ int aarch64_gdb_get_sve_reg(CPUState *cs, GByteArray *buf, int reg) case 0 ... 31: { int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq++) { + for (vq = 0; vq < arm_max_vq(cpu); vq++) { len += gdb_get_reg128(buf, env->vfp.zregs[reg].d[vq * 2 + 1], env->vfp.zregs[reg].d[vq * 2]); @@ -XXX,XX +XXX,XX @@ int aarch64_gdb_get_sve_reg(CPUState *cs, GByteArray *buf, int reg) { int preg = reg - 34; int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { + for (vq = 0; vq < arm_max_vq(cpu); vq = vq + 4) { len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]); } return len; @@ -XXX,XX +XXX,XX @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg) case 0 ... 31: { int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq++) { + for (vq = 0; vq < arm_max_vq(cpu); vq++) { if (target_big_endian()) { env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf); buf += 8; @@ -XXX,XX +XXX,XX @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg) { int preg = reg - 34; int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { + for (vq = 0; vq < arm_max_vq(cpu); vq = vq + 4) { env->vfp.pregs[preg].p[vq / 4] = ldq_p(buf); buf += 8; len += 8; @@ -XXX,XX +XXX,XX @@ static void output_vector_union_type(GDBFeatureBuilder *builder, int reg_width, GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cs, int base_reg) { ARMCPU *cpu = ARM_CPU(cs); - int reg_width = cpu->sve_max_vq * 128; - int pred_width = cpu->sve_max_vq * 16; + int reg_width = arm_max_vq(cpu) * 128; + int pred_width = arm_max_vq(cpu) * 16; GDBFeatureBuilder builder; char *name; int reg = 0; -- 2.43.0
In the macros DO_SVE2_RRX and DO_SVE2_RRX_TB we use the feature check aa64_sve, thus exposing this set of instructions in SVE as well as SVE2. Use aa64_sve2 instead, so they UNDEF on an SVE1-only CPU as they should. Strictly, the condition here should be "SVE2 or SME"; but we will correct that in a following commit with all the other missing "or SME" checks. Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> Message-id: 20260202133353.2231685-4-peter.maydell@linaro.org --- target/arm/tcg/translate-sve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UDOT_zzxw_2s, aa64_sme2_or_sve2p1, gen_gvec_ool_arg_zzxz, gen_helper_gvec_udot_idx_2h, a) #define DO_SVE2_RRX(NAME, FUNC) \ - TRANS_FEAT(NAME, aa64_sve, gen_gvec_ool_zzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzz, FUNC, \ a->rd, a->rn, a->rm, a->index) DO_SVE2_RRX(MUL_zzx_h, gen_helper_gvec_mul_idx_h) @@ -XXX,XX +XXX,XX @@ DO_SVE2_RRX(SQRDMULH_zzx_d, gen_helper_sve2_sqrdmulh_idx_d) #undef DO_SVE2_RRX #define DO_SVE2_RRX_TB(NAME, FUNC, TOP) \ - TRANS_FEAT(NAME, aa64_sve, gen_gvec_ool_zzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzz, FUNC, \ a->rd, a->rn, a->rm, (a->index << 1) | TOP) DO_SVE2_RRX_TB(SQDMULLB_zzx_s, gen_helper_sve2_sqdmull_idx_s, false) -- 2.43.0
The SVE RAX1 instruction is permitted in SME streaming mode starting from SME2p1. We forgot to allow this relaxation when we implemented SME2p1. Cc: qemu-stable@nongnu.org Fixes: 7b1613a1020d2 ("target/arm: Enable FEAT_SME2p1 on -cpu max") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-5-peter.maydell@linaro.org --- target/arm/tcg/translate-sve.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT_NONSTREAMING(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz, TRANS_FEAT_NONSTREAMING(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz, gen_helper_crypto_sm4ekey, a, 0) -TRANS_FEAT_NONSTREAMING(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz, - gen_gvec_rax1, a) +static bool trans_RAX1(DisasContext *s, arg_RAX1 *a) +{ + if (!dc_isar_feature(aa64_sve2_sha3, s)) { + return false; + } + if (!dc_isar_feature(aa64_sme2p1, s)) { + /* SME2p1 adds this as valid in streaming SVE mode */ + s->is_nonstreaming = true; + } + return gen_gvec_fn_arg_zzz(s, gen_gvec_rax1, a); +} TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtnt_sh, a, 0, FPST_A64) -- 2.43.0
In our handling of the boolean 'sme' CPU property, we write this 0/1 value directly to ID_AA64PFR1_EL1.SME. This worked when the only valid values in that field were 0 (for no SME) and 1 (for SME1). However, with the addition of SME2 the SME field can now also read 2. This means that "-cpu max,sme=on" will result in an inconsistent set of ID registers, where ID_AA64PFR1_EL1.SME claims SME1 but ID_AA64SMFR0_EL1.SMEver claims SME2p1. This isn't a valid thing to report, and confuses Linux into reporting SME2 to userspace but not actually enabling userspace access for it. Fix this bug by having arm_cpu_sme_finalize() fix up the ID_AA64PFR1_EL1.SME field to match ID_AA64SMFR0.SMEver. This means the "sme" property's semantics are "off" for "no SME" and "on" for "enable at whatever the default SME version this CPU provides is". Update the documentation to clarify what 'sve=on' and 'sme=on' do. (We don't have the equivalent bug for 'sve=on' because ID_AA64PFR0_EL1.SVE only has 0 and 1 as valid values, but the semantics of the property are the same.) Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> Message-id: 20260202133353.2231685-6-peter.maydell@linaro.org --- docs/system/arm/cpu-features.rst | 10 ++++++++++ target/arm/cpu64.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -XXX,XX +XXX,XX @@ SVE CPU Property Parsing Semantics provided an error will be generated. To avoid this error, one must enable at least one vector length prior to enabling SVE. + 10) Enabling SVE (with ``sve=on`` or by default) enables all the SVE + sub-features that the CPU supports (for example, it may also + enable SVE2). There are not generally any lower-level controls + for disabling specific SVE sub-features. + SVE CPU Property Examples ------------------------- @@ -XXX,XX +XXX,XX @@ and all vector lengths must be powers of 2. The maximum vector length supported by qemu is 2048 bits. Otherwise, there are no additional constraints on the set of vector lengths supported by SME. +As with SVE, ``sme=on`` enables all the SME sub-features the CPU +supports (for example, it may also enable SME2), and there are +no lower-level controls for fine-grained disabling of specific +SME sub-features. + SME User-mode Default Vector Length Property -------------------------------------------- diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -XXX,XX +XXX,XX @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) cpu->sme_vq.map = vq_map; cpu->sme_max_vq = 32 - clz32(vq_map); + + /* + * The "sme" property setter writes a bool value into ID_AA64PFR1_EL1.SME + * (and at this point we know it's not 0). Correct that value to report + * the same SME version as ID_AA64SMFR0_EL1.SMEver. + */ + if (FIELD_EX64_IDREG(&cpu->isar, ID_AA64SMFR0, SMEVER) != 0) { + /* SME2 or better */ + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, 2); + } } static bool cpu_arm_get_sme(Object *obj, Error **errp) @@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sme(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); + /* + * For now, write 0 for "off" and 1 for "on" into the PFR1 field. + * We will correct this value to report the right SME + * level (SME vs SME2) in arm_cpu_sme_finalize() later. + */ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, value); } -- 2.43.0
In sve_vqm1_for_el_sm(), we implicitly assume that the CPU has SVE: if called with sm == false for non-streaming mode, we try to return a vector length from svq_vq. This hits the "assert(sm)" at the bettom of the function in an SME-only CPU where sve_vq.map is zero. Add code to handle the "SME-only CPU not in streaming mode" case: we report an effective VL of 128 bits, which is what the architecture rule R_KXKNK says should be used when SVE instructions are disabled or trapped but floating point instructions are enabled. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-7-peter.maydell@linaro.org --- target/arm/helper.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ int sme_exception_el(CPUARMState *env, int el) } /* - * Given that SVE is enabled, return the vector length for EL. + * Given that SVE or SME is enabled, return the vector length for EL. */ uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm) { @@ -XXX,XX +XXX,XX @@ uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm) if (sm) { cr = env->vfp.smcr_el; map = cpu->sme_vq.map; + } else if (map == 0) { + /* + * SME-only CPU not in streaming mode: effective VL + * is 128 bits, per R_KXKNK. + */ + return 0; } if (el <= 1 && !el_is_in_host(env, el)) { -- 2.43.0
aarch64_sve_change_el() currently assumes that SME implies SVE, and will return without doing anything if SVE is not implemented, skipping a possible requirement to change the vector register state because the SME vector length has changed. Update it to handle SME also. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20260202133353.2231685-8-peter.maydell@linaro.org --- target/arm/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el, int old_len, new_len; bool old_a64, new_a64, sm; - /* Nothing to do if no SVE. */ - if (!cpu_isar_feature(aa64_sve, cpu)) { + /* Nothing to do if no SVE or SME. */ + if (!cpu_isar_feature(aa64_sve, cpu) && !cpu_isar_feature(aa64_sme, cpu)) { return; } -- 2.43.0
With FEAT_SME, even a CPU which does not implement FEAT_SVE is allowed to execute the subset of SVE instructions which are permitted in streaming SVE mode. We correctly handle this when the emulated CPU has both FEAT_SVE and FEAT_SME, because sve_access_check() includes the logic for this, matching the pseudocode CheckSVEEnabled(). However if the emulated CPU only implement FEAT_SME, it will fail the initial dc_isar_feature(aa64_sve, s) feature check, because this doesn't match the check in the per-instruction decode pseudocode, which is typically: !IsFeatureImplemented(FEAT_SVE) && !IsFeatureImplemented(FEAT_SME) Add a new aa64_sme_or_sve feature function that we can use to update the relevant uses of aa64_sve, and similarly aa64_sme_or_sve2 for where we need to check FEAT_SVE2 || FEAT_SME. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20260202133353.2231685-9-peter.maydell@linaro.org --- target/arm/cpu-features.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme2p1(const ARMISARegisters *id) /* * Combinations of feature tests, for ease of use with TRANS_FEAT. */ +static inline bool isar_feature_aa64_sme_or_sve(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme(id) || isar_feature_aa64_sve(id); +} + +static inline bool isar_feature_aa64_sme_or_sve2(const ARMISARegisters *id) +{ + return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2(id); +} + static inline bool isar_feature_aa64_sme_or_sve2p1(const ARMISARegisters *id) { return isar_feature_aa64_sme(id) || isar_feature_aa64_sve2p1(id); -- 2.43.0
Part of the logic inside do_trans_pmull() applies the aa64_sve feature check for the non-128-bit-element versions of these insns (PMULLB and PMULLT). This is currently a redundant check because we only invoke this function via the macro invocation TRANS_FEAT(..., aa64_sve2, do_trans_pmull, ...) and it's actively wrong for an SME-only CPU, because these insns are also available via SME. Remove the unnecessary logic. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-10-peter.maydell@linaro.org --- target/arm/tcg/translate-sve.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel) return false; } s->is_nonstreaming = true; - } else if (!dc_isar_feature(aa64_sve, s)) { - return false; } return gen_gvec_ool_arg_zzz(s, fns[a->esz], a, sel); } -- 2.43.0
Many SVE instructions should be provided where the CPU implements either SVE or SME. Currently we largely check only for features aa64_sve or aa64_sve2. This happens to work because we forbid creation of a CPU with SME but not SVE. To allow users to create SME-only CPUs we need to update the conditions to use the "or SME" versions of the feature tests instead. This commit was created by going through translate-sve.c from top to bottom looking for aa64_sve feature tests and cross checking those against the instruction descriptions in the Arm ARM, which will say "(FEAT_SVE || FEAT_SME)" for instructions that are provided for both features, and "(FEAT_SME)" for the rarer instructions that are SME only. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-11-peter.maydell@linaro.org --- target/arm/tcg/translate-sve.c | 854 ++++++++++++++++----------------- 1 file changed, 427 insertions(+), 427 deletions(-) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ static bool trans_INVALID(DisasContext *s, arg_INVALID *a) *** SVE Logical - Unpredicated Group */ -TRANS_FEAT(AND_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_and, a) -TRANS_FEAT(ORR_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_or, a) -TRANS_FEAT(EOR_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_xor, a) -TRANS_FEAT(BIC_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_andc, a) +TRANS_FEAT(AND_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_and, a) +TRANS_FEAT(ORR_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_or, a) +TRANS_FEAT(EOR_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_xor, a) +TRANS_FEAT(BIC_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_andc, a) static bool trans_XAR(DisasContext *s, arg_rrri_esz *a) { - if (a->esz < 0 || !dc_isar_feature(aa64_sve2, s)) { + if (a->esz < 0 || !dc_isar_feature(aa64_sme_or_sve2, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_XAR(DisasContext *s, arg_rrri_esz *a) return true; } -TRANS_FEAT(EOR3, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_gvec_eor3, a) -TRANS_FEAT(BCAX, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_gvec_bcax, a) +TRANS_FEAT(EOR3, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_gvec_eor3, a) +TRANS_FEAT(BCAX, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_gvec_bcax, a) static void gen_bsl(unsigned vece, uint32_t d, uint32_t n, uint32_t m, uint32_t a, uint32_t oprsz, uint32_t maxsz) @@ -XXX,XX +XXX,XX @@ static void gen_bsl(unsigned vece, uint32_t d, uint32_t n, uint32_t m, tcg_gen_gvec_bitsel(vece, d, a, n, m, oprsz, maxsz); } -TRANS_FEAT(BSL, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_bsl, a) +TRANS_FEAT(BSL, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_bsl, a) static void gen_bsl1n_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) { @@ -XXX,XX +XXX,XX @@ static void gen_bsl1n(unsigned vece, uint32_t d, uint32_t n, uint32_t m, tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &op); } -TRANS_FEAT(BSL1N, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_bsl1n, a) +TRANS_FEAT(BSL1N, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_bsl1n, a) static void gen_bsl2n_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) { @@ -XXX,XX +XXX,XX @@ static void gen_bsl2n(unsigned vece, uint32_t d, uint32_t n, uint32_t m, tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &op); } -TRANS_FEAT(BSL2N, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_bsl2n, a) +TRANS_FEAT(BSL2N, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_bsl2n, a) static void gen_nbsl_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) { @@ -XXX,XX +XXX,XX @@ static void gen_nbsl(unsigned vece, uint32_t d, uint32_t n, uint32_t m, tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &op); } -TRANS_FEAT(NBSL, aa64_sve2, gen_gvec_fn_arg_zzzz, gen_nbsl, a) +TRANS_FEAT(NBSL, aa64_sme_or_sve2, gen_gvec_fn_arg_zzzz, gen_nbsl, a) /* *** SVE Integer Arithmetic - Unpredicated Group */ -TRANS_FEAT(ADD_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_add, a) -TRANS_FEAT(SUB_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_sub, a) -TRANS_FEAT(SQADD_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_ssadd, a) -TRANS_FEAT(SQSUB_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_sssub, a) -TRANS_FEAT(UQADD_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_usadd, a) -TRANS_FEAT(UQSUB_zzz, aa64_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_ussub, a) +TRANS_FEAT(ADD_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_add, a) +TRANS_FEAT(SUB_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_sub, a) +TRANS_FEAT(SQADD_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_ssadd, a) +TRANS_FEAT(SQSUB_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_sssub, a) +TRANS_FEAT(UQADD_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_usadd, a) +TRANS_FEAT(UQSUB_zzz, aa64_sme_or_sve, gen_gvec_fn_arg_zzz, tcg_gen_gvec_ussub, a) /* *** SVE Integer Arithmetic - Binary Predicated Group @@ -XXX,XX +XXX,XX @@ static bool do_sel_z(DisasContext *s, int rd, int rn, int rm, int pg, int esz) TRANS_FEAT(NAME, FEAT, gen_gvec_ool_arg_zpzz, \ name##_zpzz_fns[a->esz], a, 0) -DO_ZPZZ(AND_zpzz, aa64_sve, sve_and) -DO_ZPZZ(EOR_zpzz, aa64_sve, sve_eor) -DO_ZPZZ(ORR_zpzz, aa64_sve, sve_orr) -DO_ZPZZ(BIC_zpzz, aa64_sve, sve_bic) +DO_ZPZZ(AND_zpzz, aa64_sme_or_sve, sve_and) +DO_ZPZZ(EOR_zpzz, aa64_sme_or_sve, sve_eor) +DO_ZPZZ(ORR_zpzz, aa64_sme_or_sve, sve_orr) +DO_ZPZZ(BIC_zpzz, aa64_sme_or_sve, sve_bic) -DO_ZPZZ(ADD_zpzz, aa64_sve, sve_add) -DO_ZPZZ(SUB_zpzz, aa64_sve, sve_sub) +DO_ZPZZ(ADD_zpzz, aa64_sme_or_sve, sve_add) +DO_ZPZZ(SUB_zpzz, aa64_sme_or_sve, sve_sub) -DO_ZPZZ(SMAX_zpzz, aa64_sve, sve_smax) -DO_ZPZZ(UMAX_zpzz, aa64_sve, sve_umax) -DO_ZPZZ(SMIN_zpzz, aa64_sve, sve_smin) -DO_ZPZZ(UMIN_zpzz, aa64_sve, sve_umin) -DO_ZPZZ(SABD_zpzz, aa64_sve, sve_sabd) -DO_ZPZZ(UABD_zpzz, aa64_sve, sve_uabd) +DO_ZPZZ(SMAX_zpzz, aa64_sme_or_sve, sve_smax) +DO_ZPZZ(UMAX_zpzz, aa64_sme_or_sve, sve_umax) +DO_ZPZZ(SMIN_zpzz, aa64_sme_or_sve, sve_smin) +DO_ZPZZ(UMIN_zpzz, aa64_sme_or_sve, sve_umin) +DO_ZPZZ(SABD_zpzz, aa64_sme_or_sve, sve_sabd) +DO_ZPZZ(UABD_zpzz, aa64_sme_or_sve, sve_uabd) -DO_ZPZZ(MUL_zpzz, aa64_sve, sve_mul) -DO_ZPZZ(SMULH_zpzz, aa64_sve, sve_smulh) -DO_ZPZZ(UMULH_zpzz, aa64_sve, sve_umulh) +DO_ZPZZ(MUL_zpzz, aa64_sme_or_sve, sve_mul) +DO_ZPZZ(SMULH_zpzz, aa64_sme_or_sve, sve_smulh) +DO_ZPZZ(UMULH_zpzz, aa64_sme_or_sve, sve_umulh) -DO_ZPZZ(ASR_zpzz, aa64_sve, sve_asr) -DO_ZPZZ(LSR_zpzz, aa64_sve, sve_lsr) -DO_ZPZZ(LSL_zpzz, aa64_sve, sve_lsl) +DO_ZPZZ(ASR_zpzz, aa64_sme_or_sve, sve_asr) +DO_ZPZZ(LSR_zpzz, aa64_sme_or_sve, sve_lsr) +DO_ZPZZ(LSL_zpzz, aa64_sme_or_sve, sve_lsl) static gen_helper_gvec_4 * const sdiv_fns[4] = { NULL, NULL, gen_helper_sve_sdiv_zpzz_s, gen_helper_sve_sdiv_zpzz_d }; -TRANS_FEAT(SDIV_zpzz, aa64_sve, gen_gvec_ool_arg_zpzz, sdiv_fns[a->esz], a, 0) +TRANS_FEAT(SDIV_zpzz, aa64_sme_or_sve, gen_gvec_ool_arg_zpzz, sdiv_fns[a->esz], a, 0) static gen_helper_gvec_4 * const udiv_fns[4] = { NULL, NULL, gen_helper_sve_udiv_zpzz_s, gen_helper_sve_udiv_zpzz_d }; -TRANS_FEAT(UDIV_zpzz, aa64_sve, gen_gvec_ool_arg_zpzz, udiv_fns[a->esz], a, 0) +TRANS_FEAT(UDIV_zpzz, aa64_sme_or_sve, gen_gvec_ool_arg_zpzz, udiv_fns[a->esz], a, 0) -TRANS_FEAT(SEL_zpzz, aa64_sve, do_sel_z, a->rd, a->rn, a->rm, a->pg, a->esz) +TRANS_FEAT(SEL_zpzz, aa64_sme_or_sve, do_sel_z, a->rd, a->rn, a->rm, a->pg, a->esz) /* *** SVE Integer Arithmetic - Unary Predicated Group @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SEL_zpzz, aa64_sve, do_sel_z, a->rd, a->rn, a->rm, a->pg, a->esz) }; \ TRANS_FEAT(NAME, FEAT, gen_gvec_ool_arg_zpz, name##_fns[a->esz], a, 0) -DO_ZPZ(CLS, aa64_sve, sve_cls) -DO_ZPZ(CLZ, aa64_sve, sve_clz) -DO_ZPZ(CNT_zpz, aa64_sve, sve_cnt_zpz) -DO_ZPZ(CNOT, aa64_sve, sve_cnot) -DO_ZPZ(NOT_zpz, aa64_sve, sve_not_zpz) -DO_ZPZ(ABS, aa64_sve, sve_abs) -DO_ZPZ(NEG, aa64_sve, sve_neg) -DO_ZPZ(RBIT, aa64_sve, sve_rbit) +DO_ZPZ(CLS, aa64_sme_or_sve, sve_cls) +DO_ZPZ(CLZ, aa64_sme_or_sve, sve_clz) +DO_ZPZ(CNT_zpz, aa64_sme_or_sve, sve_cnt_zpz) +DO_ZPZ(CNOT, aa64_sme_or_sve, sve_cnot) +DO_ZPZ(NOT_zpz, aa64_sme_or_sve, sve_not_zpz) +DO_ZPZ(ABS, aa64_sme_or_sve, sve_abs) +DO_ZPZ(NEG, aa64_sme_or_sve, sve_neg) +DO_ZPZ(RBIT, aa64_sme_or_sve, sve_rbit) DO_ZPZ(ORQV, aa64_sme2p1_or_sve2p1, sve2p1_orqv) DO_ZPZ(EORQV, aa64_sme2p1_or_sve2p1, sve2p1_eorqv) DO_ZPZ(ANDQV, aa64_sme2p1_or_sve2p1, sve2p1_andqv) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const fabs_ah_fns[4] = { NULL, gen_helper_sve_ah_fabs_h, gen_helper_sve_ah_fabs_s, gen_helper_sve_ah_fabs_d, }; -TRANS_FEAT(FABS, aa64_sve, gen_gvec_ool_arg_zpz, +TRANS_FEAT(FABS, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, s->fpcr_ah ? fabs_ah_fns[a->esz] : fabs_fns[a->esz], a, 0) static gen_helper_gvec_3 * const fneg_fns[4] = { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const fneg_ah_fns[4] = { NULL, gen_helper_sve_ah_fneg_h, gen_helper_sve_ah_fneg_s, gen_helper_sve_ah_fneg_d, }; -TRANS_FEAT(FNEG, aa64_sve, gen_gvec_ool_arg_zpz, +TRANS_FEAT(FNEG, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, s->fpcr_ah ? fneg_ah_fns[a->esz] : fneg_fns[a->esz], a, 0) static gen_helper_gvec_3 * const sxtb_fns[4] = { NULL, gen_helper_sve_sxtb_h, gen_helper_sve_sxtb_s, gen_helper_sve_sxtb_d, }; -TRANS_FEAT(SXTB, aa64_sve, gen_gvec_ool_arg_zpz, sxtb_fns[a->esz], a, 0) +TRANS_FEAT(SXTB, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, sxtb_fns[a->esz], a, 0) static gen_helper_gvec_3 * const uxtb_fns[4] = { NULL, gen_helper_sve_uxtb_h, gen_helper_sve_uxtb_s, gen_helper_sve_uxtb_d, }; -TRANS_FEAT(UXTB, aa64_sve, gen_gvec_ool_arg_zpz, uxtb_fns[a->esz], a, 0) +TRANS_FEAT(UXTB, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, uxtb_fns[a->esz], a, 0) static gen_helper_gvec_3 * const sxth_fns[4] = { NULL, NULL, gen_helper_sve_sxth_s, gen_helper_sve_sxth_d }; -TRANS_FEAT(SXTH, aa64_sve, gen_gvec_ool_arg_zpz, sxth_fns[a->esz], a, 0) +TRANS_FEAT(SXTH, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, sxth_fns[a->esz], a, 0) static gen_helper_gvec_3 * const uxth_fns[4] = { NULL, NULL, gen_helper_sve_uxth_s, gen_helper_sve_uxth_d }; -TRANS_FEAT(UXTH, aa64_sve, gen_gvec_ool_arg_zpz, uxth_fns[a->esz], a, 0) +TRANS_FEAT(UXTH, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, uxth_fns[a->esz], a, 0) -TRANS_FEAT(SXTW, aa64_sve, gen_gvec_ool_arg_zpz, +TRANS_FEAT(SXTW, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, a->esz == 3 ? gen_helper_sve_sxtw_d : NULL, a, 0) -TRANS_FEAT(UXTW, aa64_sve, gen_gvec_ool_arg_zpz, +TRANS_FEAT(UXTW, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, a->esz == 3 ? gen_helper_sve_uxtw_d : NULL, a, 0) static gen_helper_gvec_3 * const addqv_fns[4] = { @@ -XXX,XX +XXX,XX @@ static bool do_vpz_ool(DisasContext *s, arg_rpr_esz *a, gen_helper_sve_##name##_b, gen_helper_sve_##name##_h, \ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d, \ }; \ - TRANS_FEAT(NAME, aa64_sve, do_vpz_ool, a, name##_fns[a->esz]) + TRANS_FEAT(NAME, aa64_sme_or_sve, do_vpz_ool, a, name##_fns[a->esz]) DO_VPZ(ORV, orv) DO_VPZ(ANDV, andv) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_reduc * const saddv_fns[4] = { gen_helper_sve_saddv_b, gen_helper_sve_saddv_h, gen_helper_sve_saddv_s, NULL }; -TRANS_FEAT(SADDV, aa64_sve, do_vpz_ool, a, saddv_fns[a->esz]) +TRANS_FEAT(SADDV, aa64_sme_or_sve, do_vpz_ool, a, saddv_fns[a->esz]) #undef DO_VPZ @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const asr_zpzi_fns[4] = { gen_helper_sve_asr_zpzi_b, gen_helper_sve_asr_zpzi_h, gen_helper_sve_asr_zpzi_s, gen_helper_sve_asr_zpzi_d, }; -TRANS_FEAT(ASR_zpzi, aa64_sve, do_shift_zpzi, a, true, asr_zpzi_fns) +TRANS_FEAT(ASR_zpzi, aa64_sme_or_sve, do_shift_zpzi, a, true, asr_zpzi_fns) static gen_helper_gvec_3 * const lsr_zpzi_fns[4] = { gen_helper_sve_lsr_zpzi_b, gen_helper_sve_lsr_zpzi_h, gen_helper_sve_lsr_zpzi_s, gen_helper_sve_lsr_zpzi_d, }; -TRANS_FEAT(LSR_zpzi, aa64_sve, do_shift_zpzi, a, false, lsr_zpzi_fns) +TRANS_FEAT(LSR_zpzi, aa64_sme_or_sve, do_shift_zpzi, a, false, lsr_zpzi_fns) static gen_helper_gvec_3 * const lsl_zpzi_fns[4] = { gen_helper_sve_lsl_zpzi_b, gen_helper_sve_lsl_zpzi_h, gen_helper_sve_lsl_zpzi_s, gen_helper_sve_lsl_zpzi_d, }; -TRANS_FEAT(LSL_zpzi, aa64_sve, do_shift_zpzi, a, false, lsl_zpzi_fns) +TRANS_FEAT(LSL_zpzi, aa64_sme_or_sve, do_shift_zpzi, a, false, lsl_zpzi_fns) static gen_helper_gvec_3 * const asrd_fns[4] = { gen_helper_sve_asrd_b, gen_helper_sve_asrd_h, gen_helper_sve_asrd_s, gen_helper_sve_asrd_d, }; -TRANS_FEAT(ASRD, aa64_sve, do_shift_zpzi, a, false, asrd_fns) +TRANS_FEAT(ASRD, aa64_sme_or_sve, do_shift_zpzi, a, false, asrd_fns) static gen_helper_gvec_3 * const sqshl_zpzi_fns[4] = { gen_helper_sve2_sqshl_zpzi_b, gen_helper_sve2_sqshl_zpzi_h, gen_helper_sve2_sqshl_zpzi_s, gen_helper_sve2_sqshl_zpzi_d, }; -TRANS_FEAT(SQSHL_zpzi, aa64_sve2, gen_gvec_ool_arg_zpzi, +TRANS_FEAT(SQSHL_zpzi, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzi, a->esz < 0 ? NULL : sqshl_zpzi_fns[a->esz], a) static gen_helper_gvec_3 * const uqshl_zpzi_fns[4] = { gen_helper_sve2_uqshl_zpzi_b, gen_helper_sve2_uqshl_zpzi_h, gen_helper_sve2_uqshl_zpzi_s, gen_helper_sve2_uqshl_zpzi_d, }; -TRANS_FEAT(UQSHL_zpzi, aa64_sve2, gen_gvec_ool_arg_zpzi, +TRANS_FEAT(UQSHL_zpzi, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzi, a->esz < 0 ? NULL : uqshl_zpzi_fns[a->esz], a) static gen_helper_gvec_3 * const srshr_fns[4] = { gen_helper_sve2_srshr_b, gen_helper_sve2_srshr_h, gen_helper_sve2_srshr_s, gen_helper_sve2_srshr_d, }; -TRANS_FEAT(SRSHR, aa64_sve2, gen_gvec_ool_arg_zpzi, +TRANS_FEAT(SRSHR, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzi, a->esz < 0 ? NULL : srshr_fns[a->esz], a) static gen_helper_gvec_3 * const urshr_fns[4] = { gen_helper_sve2_urshr_b, gen_helper_sve2_urshr_h, gen_helper_sve2_urshr_s, gen_helper_sve2_urshr_d, }; -TRANS_FEAT(URSHR, aa64_sve2, gen_gvec_ool_arg_zpzi, +TRANS_FEAT(URSHR, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzi, a->esz < 0 ? NULL : urshr_fns[a->esz], a) static gen_helper_gvec_3 * const sqshlu_fns[4] = { gen_helper_sve2_sqshlu_b, gen_helper_sve2_sqshlu_h, gen_helper_sve2_sqshlu_s, gen_helper_sve2_sqshlu_d, }; -TRANS_FEAT(SQSHLU, aa64_sve2, gen_gvec_ool_arg_zpzi, +TRANS_FEAT(SQSHLU, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzi, a->esz < 0 ? NULL : sqshlu_fns[a->esz], a) /* @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SQSHLU, aa64_sve2, gen_gvec_ool_arg_zpzi, gen_helper_sve_##name##_zpzw_b, gen_helper_sve_##name##_zpzw_h, \ gen_helper_sve_##name##_zpzw_s, NULL \ }; \ - TRANS_FEAT(NAME##_zpzw, aa64_sve, gen_gvec_ool_arg_zpzz, \ + TRANS_FEAT(NAME##_zpzw, aa64_sme_or_sve, gen_gvec_ool_arg_zpzz, \ a->esz < 0 ? NULL : name##_zpzw_fns[a->esz], a, 0) DO_ZPZW(ASR, asr) @@ -XXX,XX +XXX,XX @@ static bool do_shift_imm(DisasContext *s, arg_rri_esz *a, bool asr, return true; } -TRANS_FEAT(ASR_zzi, aa64_sve, do_shift_imm, a, true, tcg_gen_gvec_sari) -TRANS_FEAT(LSR_zzi, aa64_sve, do_shift_imm, a, false, tcg_gen_gvec_shri) -TRANS_FEAT(LSL_zzi, aa64_sve, do_shift_imm, a, false, tcg_gen_gvec_shli) +TRANS_FEAT(ASR_zzi, aa64_sme_or_sve, do_shift_imm, a, true, tcg_gen_gvec_sari) +TRANS_FEAT(LSR_zzi, aa64_sme_or_sve, do_shift_imm, a, false, tcg_gen_gvec_shri) +TRANS_FEAT(LSL_zzi, aa64_sme_or_sve, do_shift_imm, a, false, tcg_gen_gvec_shli) #define DO_ZZW(NAME, name) \ static gen_helper_gvec_3 * const name##_zzw_fns[4] = { \ gen_helper_sve_##name##_zzw_b, gen_helper_sve_##name##_zzw_h, \ gen_helper_sve_##name##_zzw_s, NULL \ }; \ - TRANS_FEAT(NAME, aa64_sve, gen_gvec_ool_arg_zzz, \ + TRANS_FEAT(NAME, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, \ name##_zzw_fns[a->esz], a, 0) DO_ZZW(ASR_zzw, asr) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_5 * const mla_fns[4] = { gen_helper_sve_mla_b, gen_helper_sve_mla_h, gen_helper_sve_mla_s, gen_helper_sve_mla_d, }; -TRANS_FEAT(MLA, aa64_sve, do_zpzzz_ool, a, mla_fns[a->esz]) +TRANS_FEAT(MLA, aa64_sme_or_sve, do_zpzzz_ool, a, mla_fns[a->esz]) static gen_helper_gvec_5 * const mls_fns[4] = { gen_helper_sve_mls_b, gen_helper_sve_mls_h, gen_helper_sve_mls_s, gen_helper_sve_mls_d, }; -TRANS_FEAT(MLS, aa64_sve, do_zpzzz_ool, a, mls_fns[a->esz]) +TRANS_FEAT(MLS, aa64_sme_or_sve, do_zpzzz_ool, a, mls_fns[a->esz]) /* *** SVE Index Generation Group @@ -XXX,XX +XXX,XX @@ static bool do_index(DisasContext *s, int esz, int rd, return true; } -TRANS_FEAT(INDEX_ii, aa64_sve, do_index, a->esz, a->rd, +TRANS_FEAT(INDEX_ii, aa64_sme_or_sve, do_index, a->esz, a->rd, tcg_constant_i64(a->imm1), tcg_constant_i64(a->imm2)) -TRANS_FEAT(INDEX_ir, aa64_sve, do_index, a->esz, a->rd, +TRANS_FEAT(INDEX_ir, aa64_sme_or_sve, do_index, a->esz, a->rd, tcg_constant_i64(a->imm), cpu_reg(s, a->rm)) -TRANS_FEAT(INDEX_ri, aa64_sve, do_index, a->esz, a->rd, +TRANS_FEAT(INDEX_ri, aa64_sme_or_sve, do_index, a->esz, a->rd, cpu_reg(s, a->rn), tcg_constant_i64(a->imm)) -TRANS_FEAT(INDEX_rr, aa64_sve, do_index, a->esz, a->rd, +TRANS_FEAT(INDEX_rr, aa64_sme_or_sve, do_index, a->esz, a->rd, cpu_reg(s, a->rn), cpu_reg(s, a->rm)) /* @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(INDEX_rr, aa64_sve, do_index, a->esz, a->rd, static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a) static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a) static bool trans_RDVL(DisasContext *s, arg_RDVL *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_AND_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!a->s) { @@ -XXX,XX +XXX,XX @@ static bool trans_BIC_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!a->s && a->pg == a->rn) { @@ -XXX,XX +XXX,XX @@ static bool trans_EOR_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } /* Alias NOT (predicate) is EOR Pd.B, Pg/Z, Pn.B, Pg.B */ @@ -XXX,XX +XXX,XX @@ static bool trans_EOR_pppp(DisasContext *s, arg_rprr_s *a) static bool trans_SEL_pppp(DisasContext *s, arg_rprr_s *a) { - if (a->s || !dc_isar_feature(aa64_sve, s)) { + if (a->s || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_ORR_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!a->s && a->pg == a->rn && a->rn == a->rm) { @@ -XXX,XX +XXX,XX @@ static bool trans_ORN_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } return do_pppp_flags(s, a, &op); @@ -XXX,XX +XXX,XX @@ static bool trans_NOR_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } return do_pppp_flags(s, a, &op); @@ -XXX,XX +XXX,XX @@ static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a) .prefer_i64 = true, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } return do_pppp_flags(s, a, &op); @@ -XXX,XX +XXX,XX @@ static bool trans_NAND_pppp(DisasContext *s, arg_rprr_s *a) static bool trans_PTEST(DisasContext *s, arg_PTEST *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag) return true; } -TRANS_FEAT(PTRUE, aa64_sve, do_predset, a->esz, a->rd, a->pat, a->s) +TRANS_FEAT(PTRUE, aa64_sme_or_sve, do_predset, a->esz, a->rd, a->pat, a->s) static bool trans_PTRUE_cnt(DisasContext *s, arg_PTRUE_cnt *a) { @@ -XXX,XX +XXX,XX @@ TRANS_FEAT_NONSTREAMING(SETFFR, aa64_sve, do_predset, 0, FFR_PRED_NUM, 31, false) /* Note pat == 32 is #unimp, to set no elements. */ -TRANS_FEAT(PFALSE, aa64_sve, do_predset, 0, a->rd, 32, false) +TRANS_FEAT(PFALSE, aa64_sme_or_sve, do_predset, 0, a->rd, 32, false) static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a) { @@ -XXX,XX +XXX,XX @@ static bool do_pfirst_pnext(DisasContext *s, arg_rr_esz *a, return true; } -TRANS_FEAT(PFIRST, aa64_sve, do_pfirst_pnext, a, gen_helper_sve_pfirst) -TRANS_FEAT(PNEXT, aa64_sve, do_pfirst_pnext, a, gen_helper_sve_pnext) +TRANS_FEAT(PFIRST, aa64_sme_or_sve, do_pfirst_pnext, a, gen_helper_sve_pfirst) +TRANS_FEAT(PNEXT, aa64_sme_or_sve, do_pfirst_pnext, a, gen_helper_sve_pnext) /* *** SVE Element Count Group @@ -XXX,XX +XXX,XX @@ static void do_sat_addsub_vec(DisasContext *s, int esz, int rd, int rn, static bool trans_CNT_r(DisasContext *s, arg_CNT_r *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_CNT_r(DisasContext *s, arg_CNT_r *a) static bool trans_INCDEC_r(DisasContext *s, arg_incdec_cnt *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_INCDEC_r(DisasContext *s, arg_incdec_cnt *a) static bool trans_SINCDEC_r_32(DisasContext *s, arg_incdec_cnt *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SINCDEC_r_32(DisasContext *s, arg_incdec_cnt *a) static bool trans_SINCDEC_r_64(DisasContext *s, arg_incdec_cnt *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SINCDEC_r_64(DisasContext *s, arg_incdec_cnt *a) static bool trans_INCDEC_v(DisasContext *s, arg_incdec2_cnt *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } @@ -XXX,XX +XXX,XX @@ static bool trans_INCDEC_v(DisasContext *s, arg_incdec2_cnt *a) static bool trans_SINCDEC_v(DisasContext *s, arg_incdec2_cnt *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } @@ -XXX,XX +XXX,XX @@ static bool do_zz_dbm(DisasContext *s, arg_rr_dbm *a, GVecGen2iFn *gvec_fn) return gen_gvec_fn_zzi(s, gvec_fn, MO_64, a->rd, a->rn, imm); } -TRANS_FEAT(AND_zzi, aa64_sve, do_zz_dbm, a, tcg_gen_gvec_andi) -TRANS_FEAT(ORR_zzi, aa64_sve, do_zz_dbm, a, tcg_gen_gvec_ori) -TRANS_FEAT(EOR_zzi, aa64_sve, do_zz_dbm, a, tcg_gen_gvec_xori) +TRANS_FEAT(AND_zzi, aa64_sme_or_sve, do_zz_dbm, a, tcg_gen_gvec_andi) +TRANS_FEAT(ORR_zzi, aa64_sme_or_sve, do_zz_dbm, a, tcg_gen_gvec_ori) +TRANS_FEAT(EOR_zzi, aa64_sme_or_sve, do_zz_dbm, a, tcg_gen_gvec_xori) static bool trans_DUPM(DisasContext *s, arg_DUPM *a) { uint64_t imm; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!logic_imm_decode_wmask(&imm, extract32(a->dbm, 12, 1), @@ -XXX,XX +XXX,XX @@ static void do_cpy_m(DisasContext *s, int esz, int rd, int rn, int pg, static bool trans_FCPY(DisasContext *s, arg_FCPY *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_FCPY(DisasContext *s, arg_FCPY *a) static bool trans_CPY_m_i(DisasContext *s, arg_rpri_esz *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_CPY_z_i(DisasContext *s, arg_CPY_z_i *a) gen_helper_sve_cpy_z_s, gen_helper_sve_cpy_z_d, }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool do_EXT(DisasContext *s, int rd, int rn, int rm, int imm) return true; } -TRANS_FEAT(EXT, aa64_sve, do_EXT, a->rd, a->rn, a->rm, a->imm) -TRANS_FEAT(EXT_sve2, aa64_sve2, do_EXT, a->rd, a->rn, (a->rn + 1) % 32, a->imm) +TRANS_FEAT(EXT, aa64_sme_or_sve, do_EXT, a->rd, a->rn, a->rm, a->imm) +TRANS_FEAT(EXT_sve2, aa64_sme_or_sve2, do_EXT, a->rd, a->rn, (a->rn + 1) % 32, a->imm) static bool trans_EXTQ(DisasContext *s, arg_EXTQ *a) { @@ -XXX,XX +XXX,XX @@ static bool trans_EXTQ(DisasContext *s, arg_EXTQ *a) static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a) static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if ((a->imm & 0x1f) == 0) { @@ -XXX,XX +XXX,XX @@ static void do_insr_i64(DisasContext *s, arg_rrr_esz *a, TCGv_i64 val) static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a) static bool trans_INSR_r(DisasContext *s, arg_rrr_esz *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2 * const rev_fns[4] = { gen_helper_sve_rev_b, gen_helper_sve_rev_h, gen_helper_sve_rev_s, gen_helper_sve_rev_d }; -TRANS_FEAT(REV_v, aa64_sve, gen_gvec_ool_zz, rev_fns[a->esz], a->rd, a->rn, 0) +TRANS_FEAT(REV_v, aa64_sme_or_sve, gen_gvec_ool_zz, rev_fns[a->esz], a->rd, a->rn, 0) static gen_helper_gvec_3 * const sve_tbl_fns[4] = { gen_helper_sve_tbl_b, gen_helper_sve_tbl_h, gen_helper_sve_tbl_s, gen_helper_sve_tbl_d }; -TRANS_FEAT(TBL, aa64_sve, gen_gvec_ool_arg_zzz, sve_tbl_fns[a->esz], a, 0) +TRANS_FEAT(TBL, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, sve_tbl_fns[a->esz], a, 0) static gen_helper_gvec_4 * const sve2_tbl_fns[4] = { gen_helper_sve2_tbl_b, gen_helper_sve2_tbl_h, gen_helper_sve2_tbl_s, gen_helper_sve2_tbl_d }; -TRANS_FEAT(TBL_sve2, aa64_sve2, gen_gvec_ool_zzzz, sve2_tbl_fns[a->esz], +TRANS_FEAT(TBL_sve2, aa64_sme_or_sve2, gen_gvec_ool_zzzz, sve2_tbl_fns[a->esz], a->rd, a->rn, (a->rn + 1) % 32, a->rm, 0) static gen_helper_gvec_3 * const tblq_fns[4] = { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const tbx_fns[4] = { gen_helper_sve2_tbx_b, gen_helper_sve2_tbx_h, gen_helper_sve2_tbx_s, gen_helper_sve2_tbx_d }; -TRANS_FEAT(TBX, aa64_sve2, gen_gvec_ool_arg_zzz, tbx_fns[a->esz], a, 0) +TRANS_FEAT(TBX, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, tbx_fns[a->esz], a, 0) static gen_helper_gvec_3 * const tbxq_fns[4] = { gen_helper_sve2p1_tbxq_b, gen_helper_sve2p1_tbxq_h, @@ -XXX,XX +XXX,XX @@ static bool trans_UNPK(DisasContext *s, arg_UNPK *a) { gen_helper_sve_sunpk_d, gen_helper_sve_uunpk_d }, }; - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool do_perm_pred2(DisasContext *s, arg_rr_esz *a, bool high_odd, return true; } -TRANS_FEAT(ZIP1_p, aa64_sve, do_perm_pred3, a, 0, gen_helper_sve_zip_p) -TRANS_FEAT(ZIP2_p, aa64_sve, do_perm_pred3, a, 1, gen_helper_sve_zip_p) -TRANS_FEAT(UZP1_p, aa64_sve, do_perm_pred3, a, 0, gen_helper_sve_uzp_p) -TRANS_FEAT(UZP2_p, aa64_sve, do_perm_pred3, a, 1, gen_helper_sve_uzp_p) -TRANS_FEAT(TRN1_p, aa64_sve, do_perm_pred3, a, 0, gen_helper_sve_trn_p) -TRANS_FEAT(TRN2_p, aa64_sve, do_perm_pred3, a, 1, gen_helper_sve_trn_p) +TRANS_FEAT(ZIP1_p, aa64_sme_or_sve, do_perm_pred3, a, 0, gen_helper_sve_zip_p) +TRANS_FEAT(ZIP2_p, aa64_sme_or_sve, do_perm_pred3, a, 1, gen_helper_sve_zip_p) +TRANS_FEAT(UZP1_p, aa64_sme_or_sve, do_perm_pred3, a, 0, gen_helper_sve_uzp_p) +TRANS_FEAT(UZP2_p, aa64_sme_or_sve, do_perm_pred3, a, 1, gen_helper_sve_uzp_p) +TRANS_FEAT(TRN1_p, aa64_sme_or_sve, do_perm_pred3, a, 0, gen_helper_sve_trn_p) +TRANS_FEAT(TRN2_p, aa64_sme_or_sve, do_perm_pred3, a, 1, gen_helper_sve_trn_p) -TRANS_FEAT(REV_p, aa64_sve, do_perm_pred2, a, 0, gen_helper_sve_rev_p) -TRANS_FEAT(PUNPKLO, aa64_sve, do_perm_pred2, a, 0, gen_helper_sve_punpk_p) -TRANS_FEAT(PUNPKHI, aa64_sve, do_perm_pred2, a, 1, gen_helper_sve_punpk_p) +TRANS_FEAT(REV_p, aa64_sme_or_sve, do_perm_pred2, a, 0, gen_helper_sve_rev_p) +TRANS_FEAT(PUNPKLO, aa64_sme_or_sve, do_perm_pred2, a, 0, gen_helper_sve_punpk_p) +TRANS_FEAT(PUNPKHI, aa64_sme_or_sve, do_perm_pred2, a, 1, gen_helper_sve_punpk_p) /* *** SVE Permute - Interleaving Group @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const zip_fns[4] = { gen_helper_sve_zip_b, gen_helper_sve_zip_h, gen_helper_sve_zip_s, gen_helper_sve_zip_d, }; -TRANS_FEAT(ZIP1_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(ZIP1_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, zip_fns[a->esz], a, 0) -TRANS_FEAT(ZIP2_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(ZIP2_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, zip_fns[a->esz], a, vec_full_reg_size(s) / 2) TRANS_FEAT_NONSTREAMING(ZIP1_q, aa64_sve_f64mm, do_interleave_q, @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const uzp_fns[4] = { gen_helper_sve_uzp_b, gen_helper_sve_uzp_h, gen_helper_sve_uzp_s, gen_helper_sve_uzp_d, }; -TRANS_FEAT(UZP1_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UZP1_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, uzp_fns[a->esz], a, 0) -TRANS_FEAT(UZP2_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UZP2_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, uzp_fns[a->esz], a, 1 << a->esz) TRANS_FEAT_NONSTREAMING(UZP1_q, aa64_sve_f64mm, do_interleave_q, @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const trn_fns[4] = { gen_helper_sve_trn_s, gen_helper_sve_trn_d, }; -TRANS_FEAT(TRN1_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(TRN1_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, trn_fns[a->esz], a, 0) -TRANS_FEAT(TRN2_z, aa64_sve, gen_gvec_ool_arg_zzz, +TRANS_FEAT(TRN2_z, aa64_sme_or_sve, gen_gvec_ool_arg_zzz, trn_fns[a->esz], a, 1 << a->esz) TRANS_FEAT_NONSTREAMING(TRN1_q, aa64_sve_f64mm, do_interleave_q, @@ -XXX,XX +XXX,XX @@ static bool do_clast_vector(DisasContext *s, arg_rprr_esz *a, bool before) return true; } -TRANS_FEAT(CLASTA_z, aa64_sve, do_clast_vector, a, false) -TRANS_FEAT(CLASTB_z, aa64_sve, do_clast_vector, a, true) +TRANS_FEAT(CLASTA_z, aa64_sme_or_sve, do_clast_vector, a, false) +TRANS_FEAT(CLASTB_z, aa64_sme_or_sve, do_clast_vector, a, true) /* Compute CLAST for a scalar. */ static void do_clast_scalar(DisasContext *s, int esz, int pg, int rm, @@ -XXX,XX +XXX,XX @@ static bool do_clast_fp(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -TRANS_FEAT(CLASTA_v, aa64_sve, do_clast_fp, a, false) -TRANS_FEAT(CLASTB_v, aa64_sve, do_clast_fp, a, true) +TRANS_FEAT(CLASTA_v, aa64_sme_or_sve, do_clast_fp, a, false) +TRANS_FEAT(CLASTB_v, aa64_sme_or_sve, do_clast_fp, a, true) /* Compute CLAST for a Xreg. */ static bool do_clast_general(DisasContext *s, arg_rpr_esz *a, bool before) @@ -XXX,XX +XXX,XX @@ static bool do_clast_general(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -TRANS_FEAT(CLASTA_r, aa64_sve, do_clast_general, a, false) -TRANS_FEAT(CLASTB_r, aa64_sve, do_clast_general, a, true) +TRANS_FEAT(CLASTA_r, aa64_sme_or_sve, do_clast_general, a, false) +TRANS_FEAT(CLASTB_r, aa64_sme_or_sve, do_clast_general, a, true) /* Compute LAST for a scalar. */ static TCGv_i64 do_last_scalar(DisasContext *s, int esz, @@ -XXX,XX +XXX,XX @@ static bool do_last_fp(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -TRANS_FEAT(LASTA_v, aa64_sve, do_last_fp, a, false) -TRANS_FEAT(LASTB_v, aa64_sve, do_last_fp, a, true) +TRANS_FEAT(LASTA_v, aa64_sme_or_sve, do_last_fp, a, false) +TRANS_FEAT(LASTB_v, aa64_sme_or_sve, do_last_fp, a, true) /* Compute LAST for a Xreg. */ static bool do_last_general(DisasContext *s, arg_rpr_esz *a, bool before) @@ -XXX,XX +XXX,XX @@ static bool do_last_general(DisasContext *s, arg_rpr_esz *a, bool before) return true; } -TRANS_FEAT(LASTA_r, aa64_sve, do_last_general, a, false) -TRANS_FEAT(LASTB_r, aa64_sve, do_last_general, a, true) +TRANS_FEAT(LASTA_r, aa64_sme_or_sve, do_last_general, a, false) +TRANS_FEAT(LASTB_r, aa64_sme_or_sve, do_last_general, a, true) static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a) static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const revb_fns[4] = { NULL, gen_helper_sve_revb_h, gen_helper_sve_revb_s, gen_helper_sve_revb_d, }; -TRANS_FEAT(REVB, aa64_sve, gen_gvec_ool_arg_zpz, revb_fns[a->esz], a, 0) +TRANS_FEAT(REVB, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, revb_fns[a->esz], a, 0) static gen_helper_gvec_3 * const revh_fns[4] = { NULL, NULL, gen_helper_sve_revh_s, gen_helper_sve_revh_d, }; -TRANS_FEAT(REVH, aa64_sve, gen_gvec_ool_arg_zpz, revh_fns[a->esz], a, 0) +TRANS_FEAT(REVH, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, revh_fns[a->esz], a, 0) -TRANS_FEAT(REVW, aa64_sve, gen_gvec_ool_arg_zpz, +TRANS_FEAT(REVW, aa64_sme_or_sve, gen_gvec_ool_arg_zpz, a->esz == 3 ? gen_helper_sve_revw_d : NULL, a, 0) TRANS_FEAT(REVD, aa64_sme, gen_gvec_ool_arg_zpz, gen_helper_sme_revd_q, a, 0) -TRANS_FEAT(SPLICE, aa64_sve, gen_gvec_ool_arg_zpzz, +TRANS_FEAT(SPLICE, aa64_sme_or_sve, gen_gvec_ool_arg_zpzz, gen_helper_sve_splice, a, a->esz) -TRANS_FEAT(SPLICE_sve2, aa64_sve2, gen_gvec_ool_zzzp, gen_helper_sve_splice, +TRANS_FEAT(SPLICE_sve2, aa64_sme_or_sve2, gen_gvec_ool_zzzp, gen_helper_sve_splice, a->rd, a->rn, (a->rn + 1) % 32, a->pg, a->esz) /* @@ -XXX,XX +XXX,XX @@ static bool do_ppzz_flags(DisasContext *s, arg_rprr_esz *a, gen_helper_sve_##name##_ppzz_b, gen_helper_sve_##name##_ppzz_h, \ gen_helper_sve_##name##_ppzz_s, gen_helper_sve_##name##_ppzz_d, \ }; \ - TRANS_FEAT(NAME##_ppzz, aa64_sve, do_ppzz_flags, \ + TRANS_FEAT(NAME##_ppzz, aa64_sme_or_sve, do_ppzz_flags, \ a, name##_ppzz_fns[a->esz]) DO_PPZZ(CMPEQ, cmpeq) @@ -XXX,XX +XXX,XX @@ DO_PPZZ(CMPHS, cmphs) gen_helper_sve_##name##_ppzw_b, gen_helper_sve_##name##_ppzw_h, \ gen_helper_sve_##name##_ppzw_s, NULL \ }; \ - TRANS_FEAT(NAME##_ppzw, aa64_sve, do_ppzz_flags, \ + TRANS_FEAT(NAME##_ppzw, aa64_sme_or_sve, do_ppzz_flags, \ a, name##_ppzw_fns[a->esz]) DO_PPZW(CMPEQ, cmpeq) @@ -XXX,XX +XXX,XX @@ static bool do_ppzi_flags(DisasContext *s, arg_rpri_esz *a, gen_helper_sve_##name##_ppzi_b, gen_helper_sve_##name##_ppzi_h, \ gen_helper_sve_##name##_ppzi_s, gen_helper_sve_##name##_ppzi_d, \ }; \ - TRANS_FEAT(NAME##_ppzi, aa64_sve, do_ppzi_flags, a, \ + TRANS_FEAT(NAME##_ppzi, aa64_sme_or_sve, do_ppzi_flags, a, \ name##_ppzi_fns[a->esz]) DO_PPZI(CMPEQ, cmpeq) @@ -XXX,XX +XXX,XX @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a, return true; } -TRANS_FEAT(BRKPA, aa64_sve, do_brk3, a, +TRANS_FEAT(BRKPA, aa64_sme_or_sve, do_brk3, a, gen_helper_sve_brkpa, gen_helper_sve_brkpas) -TRANS_FEAT(BRKPB, aa64_sve, do_brk3, a, +TRANS_FEAT(BRKPB, aa64_sme_or_sve, do_brk3, a, gen_helper_sve_brkpb, gen_helper_sve_brkpbs) -TRANS_FEAT(BRKA_m, aa64_sve, do_brk2, a, +TRANS_FEAT(BRKA_m, aa64_sme_or_sve, do_brk2, a, gen_helper_sve_brka_m, gen_helper_sve_brkas_m) -TRANS_FEAT(BRKB_m, aa64_sve, do_brk2, a, +TRANS_FEAT(BRKB_m, aa64_sme_or_sve, do_brk2, a, gen_helper_sve_brkb_m, gen_helper_sve_brkbs_m) -TRANS_FEAT(BRKA_z, aa64_sve, do_brk2, a, +TRANS_FEAT(BRKA_z, aa64_sme_or_sve, do_brk2, a, gen_helper_sve_brka_z, gen_helper_sve_brkas_z) -TRANS_FEAT(BRKB_z, aa64_sve, do_brk2, a, +TRANS_FEAT(BRKB_z, aa64_sme_or_sve, do_brk2, a, gen_helper_sve_brkb_z, gen_helper_sve_brkbs_z) -TRANS_FEAT(BRKN, aa64_sve, do_brk2, a, +TRANS_FEAT(BRKN, aa64_sme_or_sve, do_brk2, a, gen_helper_sve_brkn, gen_helper_sve_brkns) /* @@ -XXX,XX +XXX,XX @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg) static bool trans_CNTP(DisasContext *s, arg_CNTP *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_CNTP_c(DisasContext *s, arg_CNTP_c *a) static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a) static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a) static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a) static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a) static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a) static bool trans_CTERM(DisasContext *s, arg_CTERM *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool do_WHILE(DisasContext *s, arg_while *a, return true; } -TRANS_FEAT(WHILE_lt, aa64_sve, do_WHILE, +TRANS_FEAT(WHILE_lt, aa64_sme_or_sve, do_WHILE, a, true, 0, 0, gen_helper_sve_whilel) -TRANS_FEAT(WHILE_gt, aa64_sve2, do_WHILE, +TRANS_FEAT(WHILE_gt, aa64_sme_or_sve2, do_WHILE, a, false, 0, 0, gen_helper_sve_whileg) TRANS_FEAT(WHILE_lt_pair, aa64_sme2_or_sve2p1, do_WHILE, @@ -XXX,XX +XXX,XX @@ static bool trans_WHILE_ptr(DisasContext *s, arg_WHILE_ptr *a) unsigned vsz = vec_full_reg_size(s); unsigned desc = 0; - if (!dc_isar_feature(aa64_sve2, s)) { + if (!dc_isar_feature(aa64_sme_or_sve2, s)) { return false; } if (!sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(PEXT_2, aa64_sme2_or_sve2p1, do_pext, a, 2) static bool trans_FDUP(DisasContext *s, arg_FDUP *a) { - if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) { + if (a->esz == 0 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_FDUP(DisasContext *s, arg_FDUP *a) static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a) return true; } -TRANS_FEAT(ADD_zzi, aa64_sve, gen_gvec_fn_arg_zzi, tcg_gen_gvec_addi, a) +TRANS_FEAT(ADD_zzi, aa64_sme_or_sve, gen_gvec_fn_arg_zzi, tcg_gen_gvec_addi, a) static bool trans_SUB_zzi(DisasContext *s, arg_rri_esz *a) { @@ -XXX,XX +XXX,XX @@ static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a) .scalar_first = true } }; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a) return true; } -TRANS_FEAT(MUL_zzi, aa64_sve, gen_gvec_fn_arg_zzi, tcg_gen_gvec_muli, a) +TRANS_FEAT(MUL_zzi, aa64_sme_or_sve, gen_gvec_fn_arg_zzi, tcg_gen_gvec_muli, a) static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, bool u, bool d) { @@ -XXX,XX +XXX,XX @@ static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, bool u, bool d) return true; } -TRANS_FEAT(SQADD_zzi, aa64_sve, do_zzi_sat, a, false, false) -TRANS_FEAT(UQADD_zzi, aa64_sve, do_zzi_sat, a, true, false) -TRANS_FEAT(SQSUB_zzi, aa64_sve, do_zzi_sat, a, false, true) -TRANS_FEAT(UQSUB_zzi, aa64_sve, do_zzi_sat, a, true, true) +TRANS_FEAT(SQADD_zzi, aa64_sme_or_sve, do_zzi_sat, a, false, false) +TRANS_FEAT(UQADD_zzi, aa64_sme_or_sve, do_zzi_sat, a, true, false) +TRANS_FEAT(SQSUB_zzi, aa64_sme_or_sve, do_zzi_sat, a, false, true) +TRANS_FEAT(UQSUB_zzi, aa64_sme_or_sve, do_zzi_sat, a, true, true) static bool do_zzi_ool(DisasContext *s, arg_rri_esz *a, gen_helper_gvec_2i *fn) { @@ -XXX,XX +XXX,XX @@ static bool do_zzi_ool(DisasContext *s, arg_rri_esz *a, gen_helper_gvec_2i *fn) gen_helper_sve_##name##i_b, gen_helper_sve_##name##i_h, \ gen_helper_sve_##name##i_s, gen_helper_sve_##name##i_d, \ }; \ - TRANS_FEAT(NAME##_zzi, aa64_sve, do_zzi_ool, a, name##i_fns[a->esz]) + TRANS_FEAT(NAME##_zzi, aa64_sme_or_sve, do_zzi_ool, a, name##i_fns[a->esz]) DO_ZZI(SMAX, smax) DO_ZZI(UMAX, umax) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4 * const dot_fns[2][2] = { { gen_helper_gvec_sdot_4b, gen_helper_gvec_sdot_4h }, { gen_helper_gvec_udot_4b, gen_helper_gvec_udot_4h } }; -TRANS_FEAT(DOT_zzzz, aa64_sve, gen_gvec_ool_zzzz, +TRANS_FEAT(DOT_zzzz, aa64_sme_or_sve, gen_gvec_ool_zzzz, dot_fns[a->u][a->sz], a->rd, a->rn, a->rm, a->ra, 0) /* * SVE Multiply - Indexed */ -TRANS_FEAT(SDOT_zzxw_4s, aa64_sve, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(SDOT_zzxw_4s, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, gen_helper_gvec_sdot_idx_4b, a) -TRANS_FEAT(SDOT_zzxw_4d, aa64_sve, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(SDOT_zzxw_4d, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, gen_helper_gvec_sdot_idx_4h, a) -TRANS_FEAT(UDOT_zzxw_4s, aa64_sve, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(UDOT_zzxw_4s, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, gen_helper_gvec_udot_idx_4b, a) -TRANS_FEAT(UDOT_zzxw_4d, aa64_sve, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(UDOT_zzxw_4d, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, gen_helper_gvec_udot_idx_4h, a) TRANS_FEAT(SUDOT_zzxw_4s, aa64_sve_i8mm, gen_gvec_ool_arg_zzxz, @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UDOT_zzxw_2s, aa64_sme2_or_sve2p1, gen_gvec_ool_arg_zzxz, gen_helper_gvec_udot_idx_2h, a) #define DO_SVE2_RRX(NAME, FUNC) \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_zzz, FUNC, \ a->rd, a->rn, a->rm, a->index) DO_SVE2_RRX(MUL_zzx_h, gen_helper_gvec_mul_idx_h) @@ -XXX,XX +XXX,XX @@ DO_SVE2_RRX(SQRDMULH_zzx_d, gen_helper_sve2_sqrdmulh_idx_d) #undef DO_SVE2_RRX #define DO_SVE2_RRX_TB(NAME, FUNC, TOP) \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_zzz, FUNC, \ a->rd, a->rn, a->rm, (a->index << 1) | TOP) DO_SVE2_RRX_TB(SQDMULLB_zzx_s, gen_helper_sve2_sqdmull_idx_s, false) @@ -XXX,XX +XXX,XX @@ DO_SVE2_RRX_TB(UMULLT_zzx_d, gen_helper_sve2_umull_idx_d, true) #undef DO_SVE2_RRX_TB #define DO_SVE2_RRXR(NAME, FUNC) \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_arg_zzxz, FUNC, a) + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_arg_zzxz, FUNC, a) DO_SVE2_RRXR(MLA_zzxz_h, gen_helper_gvec_mla_idx_h) DO_SVE2_RRXR(MLA_zzxz_s, gen_helper_gvec_mla_idx_s) @@ -XXX,XX +XXX,XX @@ DO_SVE2_RRXR(SQRDMLSH_zzxz_d, gen_helper_sve2_sqrdmlsh_idx_d) #undef DO_SVE2_RRXR #define DO_SVE2_RRXR_TB(NAME, FUNC, TOP) \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_zzzz, FUNC, \ a->rd, a->rn, a->rm, a->ra, (a->index << 1) | TOP) DO_SVE2_RRXR_TB(SQDMLALB_zzxw_s, gen_helper_sve2_sqdmlal_idx_s, false) @@ -XXX,XX +XXX,XX @@ DO_SVE2_RRXR_TB(UMLSLT_zzxw_d, gen_helper_sve2_umlsl_idx_d, true) #undef DO_SVE2_RRXR_TB #define DO_SVE2_RRXR_ROT(NAME, FUNC) \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_zzzz, FUNC, \ + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_zzzz, FUNC, \ a->rd, a->rn, a->rm, a->ra, (a->index << 2) | a->rot) DO_SVE2_RRXR_ROT(CMLA_zzxz_h, gen_helper_sve2_cmla_idx_h) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4_ptr * const fmla_idx_fns[4] = { gen_helper_gvec_bfmla_idx, gen_helper_gvec_fmla_idx_h, gen_helper_gvec_fmla_idx_s, gen_helper_gvec_fmla_idx_d }; -TRANS_FEAT(FMLA_zzxz, aa64_sve, do_fmla_zzxz, a, fmla_idx_fns[a->esz]) +TRANS_FEAT(FMLA_zzxz, aa64_sme_or_sve, do_fmla_zzxz, a, fmla_idx_fns[a->esz]) static gen_helper_gvec_4_ptr * const fmls_idx_fns[4][2] = { { gen_helper_gvec_bfmls_idx, gen_helper_gvec_ah_bfmls_idx }, @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4_ptr * const fmls_idx_fns[4][2] = { { gen_helper_gvec_fmls_idx_s, gen_helper_gvec_ah_fmls_idx_s }, { gen_helper_gvec_fmls_idx_d, gen_helper_gvec_ah_fmls_idx_d }, }; -TRANS_FEAT(FMLS_zzxz, aa64_sve, do_fmla_zzxz, a, +TRANS_FEAT(FMLS_zzxz, aa64_sme_or_sve, do_fmla_zzxz, a, fmls_idx_fns[a->esz][s->fpcr_ah]) /* @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const fmul_idx_fns[4] = { gen_helper_gvec_fmul_idx_b16, gen_helper_gvec_fmul_idx_h, gen_helper_gvec_fmul_idx_s, gen_helper_gvec_fmul_idx_d, }; -TRANS_FEAT(FMUL_zzx, aa64_sve, gen_gvec_fpst_zzz, +TRANS_FEAT(FMUL_zzx, aa64_sme_or_sve, gen_gvec_fpst_zzz, fmul_idx_fns[a->esz], a->rd, a->rn, a->rm, a->index, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) @@ -XXX,XX +XXX,XX @@ static bool do_reduce(DisasContext *s, arg_rpr_esz *a, NULL, gen_helper_sve_##name##_h, \ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d, \ }; \ - TRANS_FEAT(NAME, aa64_sve, do_reduce, a, name##_fns[a->esz]) + TRANS_FEAT(NAME, aa64_sme_or_sve, do_reduce, a, name##_fns[a->esz]) #define DO_VPZ_AH(NAME, name) \ static gen_helper_fp_reduce * const name##_fns[4] = { \ @@ -XXX,XX +XXX,XX @@ static bool do_reduce(DisasContext *s, arg_rpr_esz *a, NULL, gen_helper_sve_ah_##name##_h, \ gen_helper_sve_ah_##name##_s, gen_helper_sve_ah_##name##_d, \ }; \ - TRANS_FEAT(NAME, aa64_sve, do_reduce, a, \ + TRANS_FEAT(NAME, aa64_sme_or_sve, do_reduce, a, \ s->fpcr_ah ? name##_ah_fns[a->esz] : name##_fns[a->esz]) DO_VPZ(FADDV, faddv) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2_ptr * const frecpe_rpres_fns[] = { NULL, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_rpres_s, gen_helper_gvec_frecpe_d, }; -TRANS_FEAT(FRECPE, aa64_sve, gen_gvec_fpst_ah_arg_zz, +TRANS_FEAT(FRECPE, aa64_sme_or_sve, gen_gvec_fpst_ah_arg_zz, s->fpcr_ah && dc_isar_feature(aa64_rpres, s) ? frecpe_rpres_fns[a->esz] : frecpe_fns[a->esz], a, 0) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2_ptr * const frsqrte_rpres_fns[] = { NULL, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_rpres_s, gen_helper_gvec_frsqrte_d, }; -TRANS_FEAT(FRSQRTE, aa64_sve, gen_gvec_fpst_ah_arg_zz, +TRANS_FEAT(FRSQRTE, aa64_sme_or_sve, gen_gvec_fpst_ah_arg_zz, s->fpcr_ah && dc_isar_feature(aa64_rpres, s) ? frsqrte_rpres_fns[a->esz] : frsqrte_fns[a->esz], a, 0) @@ -XXX,XX +XXX,XX @@ static bool do_ppz_fp(DisasContext *s, arg_rpr_esz *a, NULL, gen_helper_sve_##name##_h, \ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d, \ }; \ - TRANS_FEAT(NAME, aa64_sve, do_ppz_fp, a, name##_fns[a->esz]) + TRANS_FEAT(NAME, aa64_sme_or_sve, do_ppz_fp, a, name##_fns[a->esz]) DO_PPZ(FCMGE_ppz0, fcmge0) DO_PPZ(FCMGT_ppz0, fcmgt0) @@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) gen_helper_gvec_##name##_b16, gen_helper_gvec_##name##_h, \ gen_helper_gvec_##name##_s, gen_helper_gvec_##name##_d \ }; \ - TRANS_FEAT(NAME, aa64_sve, gen_gvec_fpst_arg_zzz, name##_fns[a->esz], a, 0) + TRANS_FEAT(NAME, aa64_sme_or_sve, gen_gvec_fpst_arg_zzz, name##_fns[a->esz], a, 0) #define DO_FP3_AH(NAME, name) \ static gen_helper_gvec_3_ptr * const name##_fns[4] = { \ @@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) NULL, gen_helper_gvec_ah_##name##_h, \ gen_helper_gvec_ah_##name##_s, gen_helper_gvec_ah_##name##_d \ }; \ - TRANS_FEAT(NAME, aa64_sve, gen_gvec_fpst_ah_arg_zzz, \ + TRANS_FEAT(NAME, aa64_sme_or_sve, gen_gvec_fpst_ah_arg_zzz, \ s->fpcr_ah ? name##_ah_fns[a->esz] : name##_fns[a->esz], a, 0) DO_FP3(FADD_zzz, fadd) @@ -XXX,XX +XXX,XX @@ TRANS_FEAT_NONSTREAMING(FTSMUL, aa64_sve, gen_gvec_fpst_arg_zzz, s->fpcr_ah ? name##_ah_zpzz_fns[a->esz] : \ name##_zpzz_fns[a->esz], a) -DO_ZPZZ_FP_B16(FADD_zpzz, aa64_sve, sve_fadd) -DO_ZPZZ_FP_B16(FSUB_zpzz, aa64_sve, sve_fsub) -DO_ZPZZ_FP_B16(FMUL_zpzz, aa64_sve, sve_fmul) -DO_ZPZZ_AH_FP_B16(FMIN_zpzz, aa64_sve, sve_fmin, sve_ah_fmin) -DO_ZPZZ_AH_FP_B16(FMAX_zpzz, aa64_sve, sve_fmax, sve_ah_fmax) -DO_ZPZZ_FP_B16(FMINNM_zpzz, aa64_sve, sve_fminnum) -DO_ZPZZ_FP_B16(FMAXNM_zpzz, aa64_sve, sve_fmaxnum) -DO_ZPZZ_AH_FP(FABD, aa64_sve, sve_fabd, sve_ah_fabd) -DO_ZPZZ_FP(FSCALE, aa64_sve, sve_fscalbn) -DO_ZPZZ_FP(FDIV, aa64_sve, sve_fdiv) -DO_ZPZZ_FP(FMULX, aa64_sve, sve_fmulx) +DO_ZPZZ_FP_B16(FADD_zpzz, aa64_sme_or_sve, sve_fadd) +DO_ZPZZ_FP_B16(FSUB_zpzz, aa64_sme_or_sve, sve_fsub) +DO_ZPZZ_FP_B16(FMUL_zpzz, aa64_sme_or_sve, sve_fmul) +DO_ZPZZ_AH_FP_B16(FMIN_zpzz, aa64_sme_or_sve, sve_fmin, sve_ah_fmin) +DO_ZPZZ_AH_FP_B16(FMAX_zpzz, aa64_sme_or_sve, sve_fmax, sve_ah_fmax) +DO_ZPZZ_FP_B16(FMINNM_zpzz, aa64_sme_or_sve, sve_fminnum) +DO_ZPZZ_FP_B16(FMAXNM_zpzz, aa64_sme_or_sve, sve_fmaxnum) +DO_ZPZZ_AH_FP(FABD, aa64_sme_or_sve, sve_fabd, sve_ah_fabd) +DO_ZPZZ_FP(FSCALE, aa64_sme_or_sve, sve_fscalbn) +DO_ZPZZ_FP(FDIV, aa64_sme_or_sve, sve_fdiv) +DO_ZPZZ_FP(FMULX, aa64_sme_or_sve, sve_fmulx) typedef void gen_helper_sve_fp2scalar(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr, TCGv_i32); @@ -XXX,XX +XXX,XX @@ static bool do_fp_imm(DisasContext *s, arg_rpri_esz *a, uint64_t imm, { float32_##const0, float32_##const1 }, \ { float64_##const0, float64_##const1 }, \ }; \ - TRANS_FEAT(NAME##_zpzi, aa64_sve, do_fp_imm, a, \ + TRANS_FEAT(NAME##_zpzi, aa64_sme_or_sve, do_fp_imm, a, \ name##_const[a->esz][a->imm], name##_fns[a->esz]) #define DO_FP_AH_IMM(NAME, name, const0, const1) \ @@ -XXX,XX +XXX,XX @@ static bool do_fp_imm(DisasContext *s, arg_rpri_esz *a, uint64_t imm, { float32_##const0, float32_##const1 }, \ { float64_##const0, float64_##const1 }, \ }; \ - TRANS_FEAT(NAME##_zpzi, aa64_sve, do_fp_imm, a, \ + TRANS_FEAT(NAME##_zpzi, aa64_sme_or_sve, do_fp_imm, a, \ name##_const[a->esz][a->imm], \ s->fpcr_ah ? name##_ah_fns[a->esz] : name##_fns[a->esz]) @@ -XXX,XX +XXX,XX @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a, NULL, gen_helper_sve_##name##_h, \ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d \ }; \ - TRANS_FEAT(NAME##_ppzz, aa64_sve, do_fp_cmp, a, name##_fns[a->esz]) + TRANS_FEAT(NAME##_ppzz, aa64_sme_or_sve, do_fp_cmp, a, name##_fns[a->esz]) DO_FPCMP(FCMGE, fcmge) DO_FPCMP(FCMGT, fcmgt) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4_ptr * const fcadd_fns[] = { NULL, gen_helper_sve_fcadd_h, gen_helper_sve_fcadd_s, gen_helper_sve_fcadd_d, }; -TRANS_FEAT(FCADD, aa64_sve, gen_gvec_fpst_zzzp, fcadd_fns[a->esz], +TRANS_FEAT(FCADD, aa64_sme_or_sve, gen_gvec_fpst_zzzp, fcadd_fns[a->esz], a->rd, a->rn, a->rm, a->pg, a->rot | (s->fpcr_ah << 1), a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) @@ -XXX,XX +XXX,XX @@ static bool do_fmla_zpzzz(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_##ah_name##_b16, gen_helper_sve_##ah_name##_h, \ gen_helper_sve_##ah_name##_s, gen_helper_sve_##ah_name##_d \ }; \ - TRANS_FEAT(NAME, aa64_sve, do_fmla_zpzzz, a, \ + TRANS_FEAT(NAME, aa64_sme_or_sve, do_fmla_zpzzz, a, \ s->fpcr_ah ? name##_ah_fns[a->esz] : name##_fns[a->esz]) /* We don't need an ah_fmla_zpzzz because fmla doesn't negate anything */ @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_5_ptr * const fcmla_fns[4] = { NULL, gen_helper_sve_fcmla_zpzzz_h, gen_helper_sve_fcmla_zpzzz_s, gen_helper_sve_fcmla_zpzzz_d, }; -TRANS_FEAT(FCMLA_zpzzz, aa64_sve, gen_gvec_fpst_zzzzp, fcmla_fns[a->esz], +TRANS_FEAT(FCMLA_zpzzz, aa64_sme_or_sve, gen_gvec_fpst_zzzzp, fcmla_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->pg, a->rot | (s->fpcr_ah << 2), a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static gen_helper_gvec_4_ptr * const fcmla_idx_fns[4] = { NULL, gen_helper_gvec_fcmlah_idx, gen_helper_gvec_fcmlas_idx, NULL }; -TRANS_FEAT(FCMLA_zzxz, aa64_sve, gen_gvec_fpst_zzzz, fcmla_idx_fns[a->esz], +TRANS_FEAT(FCMLA_zzxz, aa64_sme_or_sve, gen_gvec_fpst_zzzz, fcmla_idx_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->index * 4 + a->rot, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FCMLA_zzxz, aa64_sve, gen_gvec_fpst_zzzz, fcmla_idx_fns[a->esz], *** SVE Floating Point Unary Operations Predicated Group */ -TRANS_FEAT(FCVT_sh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_sh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_sh, a, 0, FPST_A64) -TRANS_FEAT(FCVT_hs, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_hs, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_hs, a, 0, FPST_A64_F16) TRANS_FEAT(BFCVT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, gen_helper_sve_bfcvt, a, 0, s->fpcr_ah ? FPST_AH : FPST_A64) -TRANS_FEAT(FCVT_dh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_dh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_dh, a, 0, FPST_A64) -TRANS_FEAT(FCVT_hd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_hd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_hd, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVT_ds, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_ds, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_ds, a, 0, FPST_A64) -TRANS_FEAT(FCVT_sd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVT_sd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_sd, a, 0, FPST_A64) -TRANS_FEAT(FCVTZS_hh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_hh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_hh, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZU_hh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_hh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_hh, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZS_hs, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_hs, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_hs, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZU_hs, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_hs, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_hs, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZS_hd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_hd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_hd, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZU_hd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_hd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_hd, a, 0, FPST_A64_F16) -TRANS_FEAT(FCVTZS_ss, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_ss, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_ss, a, 0, FPST_A64) -TRANS_FEAT(FCVTZU_ss, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_ss, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_ss, a, 0, FPST_A64) -TRANS_FEAT(FCVTZS_sd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_sd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_sd, a, 0, FPST_A64) -TRANS_FEAT(FCVTZU_sd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_sd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_sd, a, 0, FPST_A64) -TRANS_FEAT(FCVTZS_ds, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_ds, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_ds, a, 0, FPST_A64) -TRANS_FEAT(FCVTZU_ds, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_ds, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_ds, a, 0, FPST_A64) -TRANS_FEAT(FCVTZS_dd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZS_dd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzs_dd, a, 0, FPST_A64) -TRANS_FEAT(FCVTZU_dd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTZU_dd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvtzu_dd, a, 0, FPST_A64) static gen_helper_gvec_3_ptr * const frint_fns[] = { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const frint_fns[] = { gen_helper_sve_frint_s, gen_helper_sve_frint_d }; -TRANS_FEAT(FRINTI, aa64_sve, gen_gvec_fpst_arg_zpz, frint_fns[a->esz], +TRANS_FEAT(FRINTI, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, frint_fns[a->esz], a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static gen_helper_gvec_3_ptr * const frintx_fns[] = { @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const frintx_fns[] = { gen_helper_sve_frintx_s, gen_helper_sve_frintx_d }; -TRANS_FEAT(FRINTX, aa64_sve, gen_gvec_fpst_arg_zpz, frintx_fns[a->esz], +TRANS_FEAT(FRINTX, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, frintx_fns[a->esz], a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, @@ -XXX,XX +XXX,XX @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, return true; } -TRANS_FEAT(FRINTN, aa64_sve, do_frint_mode, a, +TRANS_FEAT(FRINTN, aa64_sme_or_sve, do_frint_mode, a, FPROUNDING_TIEEVEN, frint_fns[a->esz]) -TRANS_FEAT(FRINTP, aa64_sve, do_frint_mode, a, +TRANS_FEAT(FRINTP, aa64_sme_or_sve, do_frint_mode, a, FPROUNDING_POSINF, frint_fns[a->esz]) -TRANS_FEAT(FRINTM, aa64_sve, do_frint_mode, a, +TRANS_FEAT(FRINTM, aa64_sme_or_sve, do_frint_mode, a, FPROUNDING_NEGINF, frint_fns[a->esz]) -TRANS_FEAT(FRINTZ, aa64_sve, do_frint_mode, a, +TRANS_FEAT(FRINTZ, aa64_sme_or_sve, do_frint_mode, a, FPROUNDING_ZERO, frint_fns[a->esz]) -TRANS_FEAT(FRINTA, aa64_sve, do_frint_mode, a, +TRANS_FEAT(FRINTA, aa64_sme_or_sve, do_frint_mode, a, FPROUNDING_TIEAWAY, frint_fns[a->esz]) static gen_helper_gvec_3_ptr * const frecpx_fns[] = { NULL, gen_helper_sve_frecpx_h, gen_helper_sve_frecpx_s, gen_helper_sve_frecpx_d, }; -TRANS_FEAT(FRECPX, aa64_sve, gen_gvec_fpst_arg_zpz, frecpx_fns[a->esz], +TRANS_FEAT(FRECPX, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, frecpx_fns[a->esz], a, 0, select_ah_fpst(s, a->esz)) static gen_helper_gvec_3_ptr * const fsqrt_fns[] = { NULL, gen_helper_sve_fsqrt_h, gen_helper_sve_fsqrt_s, gen_helper_sve_fsqrt_d, }; -TRANS_FEAT(FSQRT, aa64_sve, gen_gvec_fpst_arg_zpz, fsqrt_fns[a->esz], +TRANS_FEAT(FSQRT, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, fsqrt_fns[a->esz], a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) -TRANS_FEAT(SCVTF_hh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_hh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_hh, a, 0, FPST_A64_F16) -TRANS_FEAT(SCVTF_sh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_sh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_sh, a, 0, FPST_A64_F16) -TRANS_FEAT(SCVTF_dh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_dh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_dh, a, 0, FPST_A64_F16) -TRANS_FEAT(SCVTF_ss, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_ss, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_ss, a, 0, FPST_A64) -TRANS_FEAT(SCVTF_ds, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_ds, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_ds, a, 0, FPST_A64) -TRANS_FEAT(SCVTF_sd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_sd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_sd, a, 0, FPST_A64) -TRANS_FEAT(SCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(SCVTF_dd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_scvt_dd, a, 0, FPST_A64) -TRANS_FEAT(UCVTF_hh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_hh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_hh, a, 0, FPST_A64_F16) -TRANS_FEAT(UCVTF_sh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_sh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_sh, a, 0, FPST_A64_F16) -TRANS_FEAT(UCVTF_dh, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_dh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_dh, a, 0, FPST_A64_F16) -TRANS_FEAT(UCVTF_ss, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_ss, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_ss, a, 0, FPST_A64) -TRANS_FEAT(UCVTF_ds, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_ds, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_ds, a, 0, FPST_A64) -TRANS_FEAT(UCVTF_sd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_sd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_sd, a, 0, FPST_A64) -TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(UCVTF_dd, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_ucvt_dd, a, 0, FPST_A64) /* @@ -XXX,XX +XXX,XX @@ void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs, static bool trans_LDR_zri(DisasContext *s, arg_rri *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a) static bool trans_LDR_pri(DisasContext *s, arg_rri *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a) static bool trans_STR_zri(DisasContext *s, arg_rri *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a) static bool trans_STR_pri(DisasContext *s, arg_rri *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a) /* dtypes 16-18 are artificial, representing 128-bit element */ switch (a->dtype) { case 0 ... 15: - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } break; @@ -XXX,XX +XXX,XX @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a) /* dtypes 16-18 are artificial, representing 128-bit element */ switch (a->dtype) { case 0 ... 15: - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } break; @@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int dtype) static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a) { - if (a->rm == 31 || !dc_isar_feature(aa64_sve, s)) { + if (a->rm == 31 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a) static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a) TCGv_i64 temp, clean_addr; MemOp memop; - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } if (!sve_access_check(s)) { @@ -XXX,XX +XXX,XX @@ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a) } switch (a->esz) { case MO_8 ... MO_64: - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } break; @@ -XXX,XX +XXX,XX @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a) } switch (a->esz) { case MO_8 ... MO_64: - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } break; @@ -XXX,XX +XXX,XX @@ static bool trans_STNT1_zprz(DisasContext *s, arg_ST1_zprz *a) static bool trans_PRF(DisasContext *s, arg_PRF *a) { - if (!dc_isar_feature(aa64_sve, s)) { + if (!dc_isar_feature(aa64_sme_or_sve, s)) { return false; } /* Prefetch is a nop within QEMU. */ @@ -XXX,XX +XXX,XX @@ static bool trans_PRF(DisasContext *s, arg_PRF *a) static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a) { - if (a->rm == 31 || !dc_isar_feature(aa64_sve, s)) { + if (a->rm == 31 || !dc_isar_feature(aa64_sme_or_sve, s)) { return false; } /* Prefetch is a nop within QEMU. */ @@ -XXX,XX +XXX,XX @@ static bool trans_PRF_ns(DisasContext *s, arg_PRF_ns *a) * In the meantime, just emit the moves. */ -TRANS_FEAT(MOVPRFX, aa64_sve, do_mov_z, a->rd, a->rn) -TRANS_FEAT(MOVPRFX_m, aa64_sve, do_sel_z, a->rd, a->rn, a->rd, a->pg, a->esz) -TRANS_FEAT(MOVPRFX_z, aa64_sve, do_movz_zpz, a->rd, a->rn, a->pg, a->esz, false) +TRANS_FEAT(MOVPRFX, aa64_sme_or_sve, do_mov_z, a->rd, a->rn) +TRANS_FEAT(MOVPRFX_m, aa64_sme_or_sve, do_sel_z, a->rd, a->rn, a->rd, a->pg, a->esz) +TRANS_FEAT(MOVPRFX_z, aa64_sme_or_sve, do_movz_zpz, a->rd, a->rn, a->pg, a->esz, false) /* * SVE2 Integer Multiply - Unpredicated */ -TRANS_FEAT(MUL_zzz, aa64_sve2, gen_gvec_fn_arg_zzz, tcg_gen_gvec_mul, a) -TRANS_FEAT(SQDMULH_zzz, aa64_sve2, gen_gvec_fn_arg_zzz, gen_gvec_sve2_sqdmulh, a) +TRANS_FEAT(MUL_zzz, aa64_sme_or_sve2, gen_gvec_fn_arg_zzz, tcg_gen_gvec_mul, a) +TRANS_FEAT(SQDMULH_zzz, aa64_sme_or_sve2, gen_gvec_fn_arg_zzz, gen_gvec_sve2_sqdmulh, a) static gen_helper_gvec_3 * const smulh_zzz_fns[4] = { gen_helper_gvec_smulh_b, gen_helper_gvec_smulh_h, gen_helper_gvec_smulh_s, gen_helper_gvec_smulh_d, }; -TRANS_FEAT(SMULH_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SMULH_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, smulh_zzz_fns[a->esz], a, 0) static gen_helper_gvec_3 * const umulh_zzz_fns[4] = { gen_helper_gvec_umulh_b, gen_helper_gvec_umulh_h, gen_helper_gvec_umulh_s, gen_helper_gvec_umulh_d, }; -TRANS_FEAT(UMULH_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UMULH_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, umulh_zzz_fns[a->esz], a, 0) -TRANS_FEAT(PMUL_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(PMUL_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, gen_helper_gvec_pmul_b, a, 0) static gen_helper_gvec_3 * const sqrdmulh_zzz_fns[4] = { gen_helper_sve2_sqrdmulh_b, gen_helper_sve2_sqrdmulh_h, gen_helper_sve2_sqrdmulh_s, gen_helper_sve2_sqrdmulh_d, }; -TRANS_FEAT(SQRDMULH_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SQRDMULH_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sqrdmulh_zzz_fns[a->esz], a, 0) /* @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4 * const sadlp_fns[4] = { NULL, gen_helper_sve2_sadalp_zpzz_h, gen_helper_sve2_sadalp_zpzz_s, gen_helper_sve2_sadalp_zpzz_d, }; -TRANS_FEAT(SADALP_zpzz, aa64_sve2, gen_gvec_ool_arg_zpzz, +TRANS_FEAT(SADALP_zpzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzz, sadlp_fns[a->esz], a, 0) static gen_helper_gvec_4 * const uadlp_fns[4] = { NULL, gen_helper_sve2_uadalp_zpzz_h, gen_helper_sve2_uadalp_zpzz_s, gen_helper_sve2_uadalp_zpzz_d, }; -TRANS_FEAT(UADALP_zpzz, aa64_sve2, gen_gvec_ool_arg_zpzz, +TRANS_FEAT(UADALP_zpzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zpzz, uadlp_fns[a->esz], a, 0) /* * SVE2 integer unary operations (predicated) */ -TRANS_FEAT(URECPE, aa64_sve2, gen_gvec_ool_arg_zpz, +TRANS_FEAT(URECPE, aa64_sme_or_sve2, gen_gvec_ool_arg_zpz, a->esz == 2 ? gen_helper_sve2_urecpe_s : NULL, a, 0) -TRANS_FEAT(URSQRTE, aa64_sve2, gen_gvec_ool_arg_zpz, +TRANS_FEAT(URSQRTE, aa64_sme_or_sve2, gen_gvec_ool_arg_zpz, a->esz == 2 ? gen_helper_sve2_ursqrte_s : NULL, a, 0) static gen_helper_gvec_3 * const sqabs_fns[4] = { gen_helper_sve2_sqabs_b, gen_helper_sve2_sqabs_h, gen_helper_sve2_sqabs_s, gen_helper_sve2_sqabs_d, }; -TRANS_FEAT(SQABS, aa64_sve2, gen_gvec_ool_arg_zpz, sqabs_fns[a->esz], a, 0) +TRANS_FEAT(SQABS, aa64_sme_or_sve2, gen_gvec_ool_arg_zpz, sqabs_fns[a->esz], a, 0) static gen_helper_gvec_3 * const sqneg_fns[4] = { gen_helper_sve2_sqneg_b, gen_helper_sve2_sqneg_h, gen_helper_sve2_sqneg_s, gen_helper_sve2_sqneg_d, }; -TRANS_FEAT(SQNEG, aa64_sve2, gen_gvec_ool_arg_zpz, sqneg_fns[a->esz], a, 0) +TRANS_FEAT(SQNEG, aa64_sme_or_sve2, gen_gvec_ool_arg_zpz, sqneg_fns[a->esz], a, 0) -DO_ZPZZ(SQSHL, aa64_sve2, sve2_sqshl) -DO_ZPZZ(SQRSHL, aa64_sve2, sve2_sqrshl) -DO_ZPZZ(SRSHL, aa64_sve2, sve2_srshl) +DO_ZPZZ(SQSHL, aa64_sme_or_sve2, sve2_sqshl) +DO_ZPZZ(SQRSHL, aa64_sme_or_sve2, sve2_sqrshl) +DO_ZPZZ(SRSHL, aa64_sme_or_sve2, sve2_srshl) -DO_ZPZZ(UQSHL, aa64_sve2, sve2_uqshl) -DO_ZPZZ(UQRSHL, aa64_sve2, sve2_uqrshl) -DO_ZPZZ(URSHL, aa64_sve2, sve2_urshl) +DO_ZPZZ(UQSHL, aa64_sme_or_sve2, sve2_uqshl) +DO_ZPZZ(UQRSHL, aa64_sme_or_sve2, sve2_uqrshl) +DO_ZPZZ(URSHL, aa64_sme_or_sve2, sve2_urshl) -DO_ZPZZ(SHADD, aa64_sve2, sve2_shadd) -DO_ZPZZ(SRHADD, aa64_sve2, sve2_srhadd) -DO_ZPZZ(SHSUB, aa64_sve2, sve2_shsub) +DO_ZPZZ(SHADD, aa64_sme_or_sve2, sve2_shadd) +DO_ZPZZ(SRHADD, aa64_sme_or_sve2, sve2_srhadd) +DO_ZPZZ(SHSUB, aa64_sme_or_sve2, sve2_shsub) -DO_ZPZZ(UHADD, aa64_sve2, sve2_uhadd) -DO_ZPZZ(URHADD, aa64_sve2, sve2_urhadd) -DO_ZPZZ(UHSUB, aa64_sve2, sve2_uhsub) +DO_ZPZZ(UHADD, aa64_sme_or_sve2, sve2_uhadd) +DO_ZPZZ(URHADD, aa64_sme_or_sve2, sve2_urhadd) +DO_ZPZZ(UHSUB, aa64_sme_or_sve2, sve2_uhsub) -DO_ZPZZ(ADDP, aa64_sve2, sve2_addp) -DO_ZPZZ(SMAXP, aa64_sve2, sve2_smaxp) -DO_ZPZZ(UMAXP, aa64_sve2, sve2_umaxp) -DO_ZPZZ(SMINP, aa64_sve2, sve2_sminp) -DO_ZPZZ(UMINP, aa64_sve2, sve2_uminp) +DO_ZPZZ(ADDP, aa64_sme_or_sve2, sve2_addp) +DO_ZPZZ(SMAXP, aa64_sme_or_sve2, sve2_smaxp) +DO_ZPZZ(UMAXP, aa64_sme_or_sve2, sve2_umaxp) +DO_ZPZZ(SMINP, aa64_sme_or_sve2, sve2_sminp) +DO_ZPZZ(UMINP, aa64_sme_or_sve2, sve2_uminp) -DO_ZPZZ(SQADD_zpzz, aa64_sve2, sve2_sqadd) -DO_ZPZZ(UQADD_zpzz, aa64_sve2, sve2_uqadd) -DO_ZPZZ(SQSUB_zpzz, aa64_sve2, sve2_sqsub) -DO_ZPZZ(UQSUB_zpzz, aa64_sve2, sve2_uqsub) -DO_ZPZZ(SUQADD, aa64_sve2, sve2_suqadd) -DO_ZPZZ(USQADD, aa64_sve2, sve2_usqadd) +DO_ZPZZ(SQADD_zpzz, aa64_sme_or_sve2, sve2_sqadd) +DO_ZPZZ(UQADD_zpzz, aa64_sme_or_sve2, sve2_uqadd) +DO_ZPZZ(SQSUB_zpzz, aa64_sme_or_sve2, sve2_sqsub) +DO_ZPZZ(UQSUB_zpzz, aa64_sme_or_sve2, sve2_uqsub) +DO_ZPZZ(SUQADD, aa64_sme_or_sve2, sve2_suqadd) +DO_ZPZZ(USQADD, aa64_sme_or_sve2, sve2_usqadd) /* * SVE2 Widening Integer Arithmetic @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const saddl_fns[4] = { NULL, gen_helper_sve2_saddl_h, gen_helper_sve2_saddl_s, gen_helper_sve2_saddl_d, }; -TRANS_FEAT(SADDLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SADDLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, saddl_fns[a->esz], a, 0) -TRANS_FEAT(SADDLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SADDLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, saddl_fns[a->esz], a, 3) -TRANS_FEAT(SADDLBT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SADDLBT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, saddl_fns[a->esz], a, 2) static gen_helper_gvec_3 * const ssubl_fns[4] = { NULL, gen_helper_sve2_ssubl_h, gen_helper_sve2_ssubl_s, gen_helper_sve2_ssubl_d, }; -TRANS_FEAT(SSUBLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SSUBLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubl_fns[a->esz], a, 0) -TRANS_FEAT(SSUBLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SSUBLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubl_fns[a->esz], a, 3) -TRANS_FEAT(SSUBLBT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SSUBLBT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubl_fns[a->esz], a, 2) -TRANS_FEAT(SSUBLTB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SSUBLTB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubl_fns[a->esz], a, 1) static gen_helper_gvec_3 * const sabdl_fns[4] = { NULL, gen_helper_sve2_sabdl_h, gen_helper_sve2_sabdl_s, gen_helper_sve2_sabdl_d, }; -TRANS_FEAT(SABDLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SABDLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sabdl_fns[a->esz], a, 0) -TRANS_FEAT(SABDLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SABDLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sabdl_fns[a->esz], a, 3) static gen_helper_gvec_3 * const uaddl_fns[4] = { NULL, gen_helper_sve2_uaddl_h, gen_helper_sve2_uaddl_s, gen_helper_sve2_uaddl_d, }; -TRANS_FEAT(UADDLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UADDLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uaddl_fns[a->esz], a, 0) -TRANS_FEAT(UADDLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UADDLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uaddl_fns[a->esz], a, 3) static gen_helper_gvec_3 * const usubl_fns[4] = { NULL, gen_helper_sve2_usubl_h, gen_helper_sve2_usubl_s, gen_helper_sve2_usubl_d, }; -TRANS_FEAT(USUBLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(USUBLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, usubl_fns[a->esz], a, 0) -TRANS_FEAT(USUBLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(USUBLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, usubl_fns[a->esz], a, 3) static gen_helper_gvec_3 * const uabdl_fns[4] = { NULL, gen_helper_sve2_uabdl_h, gen_helper_sve2_uabdl_s, gen_helper_sve2_uabdl_d, }; -TRANS_FEAT(UABDLB, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UABDLB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uabdl_fns[a->esz], a, 0) -TRANS_FEAT(UABDLT, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UABDLT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uabdl_fns[a->esz], a, 3) static gen_helper_gvec_3 * const sqdmull_fns[4] = { NULL, gen_helper_sve2_sqdmull_zzz_h, gen_helper_sve2_sqdmull_zzz_s, gen_helper_sve2_sqdmull_zzz_d, }; -TRANS_FEAT(SQDMULLB_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SQDMULLB_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sqdmull_fns[a->esz], a, 0) -TRANS_FEAT(SQDMULLT_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SQDMULLT_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sqdmull_fns[a->esz], a, 3) static gen_helper_gvec_3 * const smull_fns[4] = { NULL, gen_helper_sve2_smull_zzz_h, gen_helper_sve2_smull_zzz_s, gen_helper_sve2_smull_zzz_d, }; -TRANS_FEAT(SMULLB_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SMULLB_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, smull_fns[a->esz], a, 0) -TRANS_FEAT(SMULLT_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SMULLT_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, smull_fns[a->esz], a, 3) static gen_helper_gvec_3 * const umull_fns[4] = { NULL, gen_helper_sve2_umull_zzz_h, gen_helper_sve2_umull_zzz_s, gen_helper_sve2_umull_zzz_d, }; -TRANS_FEAT(UMULLB_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UMULLB_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, umull_fns[a->esz], a, 0) -TRANS_FEAT(UMULLT_zzz, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(UMULLT_zzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, umull_fns[a->esz], a, 3) static gen_helper_gvec_3 * const eoril_fns[4] = { gen_helper_sve2_eoril_b, gen_helper_sve2_eoril_h, gen_helper_sve2_eoril_s, gen_helper_sve2_eoril_d, }; -TRANS_FEAT(EORBT, aa64_sve2, gen_gvec_ool_arg_zzz, eoril_fns[a->esz], a, 2) -TRANS_FEAT(EORTB, aa64_sve2, gen_gvec_ool_arg_zzz, eoril_fns[a->esz], a, 1) +TRANS_FEAT(EORBT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, eoril_fns[a->esz], a, 2) +TRANS_FEAT(EORTB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, eoril_fns[a->esz], a, 1) static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel) { @@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel) return gen_gvec_ool_arg_zzz(s, fns[a->esz], a, sel); } -TRANS_FEAT(PMULLB, aa64_sve2, do_trans_pmull, a, false) -TRANS_FEAT(PMULLT, aa64_sve2, do_trans_pmull, a, true) +TRANS_FEAT(PMULLB, aa64_sme_or_sve2, do_trans_pmull, a, false) +TRANS_FEAT(PMULLT, aa64_sme_or_sve2, do_trans_pmull, a, true) static gen_helper_gvec_3 * const saddw_fns[4] = { NULL, gen_helper_sve2_saddw_h, gen_helper_sve2_saddw_s, gen_helper_sve2_saddw_d, }; -TRANS_FEAT(SADDWB, aa64_sve2, gen_gvec_ool_arg_zzz, saddw_fns[a->esz], a, 0) -TRANS_FEAT(SADDWT, aa64_sve2, gen_gvec_ool_arg_zzz, saddw_fns[a->esz], a, 1) +TRANS_FEAT(SADDWB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, saddw_fns[a->esz], a, 0) +TRANS_FEAT(SADDWT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, saddw_fns[a->esz], a, 1) static gen_helper_gvec_3 * const ssubw_fns[4] = { NULL, gen_helper_sve2_ssubw_h, gen_helper_sve2_ssubw_s, gen_helper_sve2_ssubw_d, }; -TRANS_FEAT(SSUBWB, aa64_sve2, gen_gvec_ool_arg_zzz, ssubw_fns[a->esz], a, 0) -TRANS_FEAT(SSUBWT, aa64_sve2, gen_gvec_ool_arg_zzz, ssubw_fns[a->esz], a, 1) +TRANS_FEAT(SSUBWB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubw_fns[a->esz], a, 0) +TRANS_FEAT(SSUBWT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, ssubw_fns[a->esz], a, 1) static gen_helper_gvec_3 * const uaddw_fns[4] = { NULL, gen_helper_sve2_uaddw_h, gen_helper_sve2_uaddw_s, gen_helper_sve2_uaddw_d, }; -TRANS_FEAT(UADDWB, aa64_sve2, gen_gvec_ool_arg_zzz, uaddw_fns[a->esz], a, 0) -TRANS_FEAT(UADDWT, aa64_sve2, gen_gvec_ool_arg_zzz, uaddw_fns[a->esz], a, 1) +TRANS_FEAT(UADDWB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uaddw_fns[a->esz], a, 0) +TRANS_FEAT(UADDWT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, uaddw_fns[a->esz], a, 1) static gen_helper_gvec_3 * const usubw_fns[4] = { NULL, gen_helper_sve2_usubw_h, gen_helper_sve2_usubw_s, gen_helper_sve2_usubw_d, }; -TRANS_FEAT(USUBWB, aa64_sve2, gen_gvec_ool_arg_zzz, usubw_fns[a->esz], a, 0) -TRANS_FEAT(USUBWT, aa64_sve2, gen_gvec_ool_arg_zzz, usubw_fns[a->esz], a, 1) +TRANS_FEAT(USUBWB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, usubw_fns[a->esz], a, 0) +TRANS_FEAT(USUBWT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, usubw_fns[a->esz], a, 1) static void gen_sshll_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t imm) { @@ -XXX,XX +XXX,XX @@ static const GVecGen2i sshll_ops[3] = { .fno = gen_helper_sve2_sshll_d, .vece = MO_64 } }; -TRANS_FEAT(SSHLLB, aa64_sve2, do_shll_tb, a, sshll_ops, false) -TRANS_FEAT(SSHLLT, aa64_sve2, do_shll_tb, a, sshll_ops, true) +TRANS_FEAT(SSHLLB, aa64_sme_or_sve2, do_shll_tb, a, sshll_ops, false) +TRANS_FEAT(SSHLLT, aa64_sme_or_sve2, do_shll_tb, a, sshll_ops, true) static const TCGOpcode ushll_list[] = { INDEX_op_shli_vec, INDEX_op_shri_vec, 0 @@ -XXX,XX +XXX,XX @@ static const GVecGen2i ushll_ops[3] = { .fno = gen_helper_sve2_ushll_d, .vece = MO_64 }, }; -TRANS_FEAT(USHLLB, aa64_sve2, do_shll_tb, a, ushll_ops, false) -TRANS_FEAT(USHLLT, aa64_sve2, do_shll_tb, a, ushll_ops, true) +TRANS_FEAT(USHLLB, aa64_sme_or_sve2, do_shll_tb, a, ushll_ops, false) +TRANS_FEAT(USHLLT, aa64_sme_or_sve2, do_shll_tb, a, ushll_ops, true) static gen_helper_gvec_3 * const bext_fns[4] = { gen_helper_sve2_bext_b, gen_helper_sve2_bext_h, @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const cadd_fns[4] = { gen_helper_sve2_cadd_b, gen_helper_sve2_cadd_h, gen_helper_sve2_cadd_s, gen_helper_sve2_cadd_d, }; -TRANS_FEAT(CADD_rot90, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(CADD_rot90, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, cadd_fns[a->esz], a, 0) -TRANS_FEAT(CADD_rot270, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(CADD_rot270, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, cadd_fns[a->esz], a, 1) static gen_helper_gvec_3 * const sqcadd_fns[4] = { gen_helper_sve2_sqcadd_b, gen_helper_sve2_sqcadd_h, gen_helper_sve2_sqcadd_s, gen_helper_sve2_sqcadd_d, }; -TRANS_FEAT(SQCADD_rot90, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SQCADD_rot90, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sqcadd_fns[a->esz], a, 0) -TRANS_FEAT(SQCADD_rot270, aa64_sve2, gen_gvec_ool_arg_zzz, +TRANS_FEAT(SQCADD_rot270, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, sqcadd_fns[a->esz], a, 1) static gen_helper_gvec_4 * const sabal_fns[4] = { NULL, gen_helper_sve2_sabal_h, gen_helper_sve2_sabal_s, gen_helper_sve2_sabal_d, }; -TRANS_FEAT(SABALB, aa64_sve2, gen_gvec_ool_arg_zzzz, sabal_fns[a->esz], a, 0) -TRANS_FEAT(SABALT, aa64_sve2, gen_gvec_ool_arg_zzzz, sabal_fns[a->esz], a, 1) +TRANS_FEAT(SABALB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sabal_fns[a->esz], a, 0) +TRANS_FEAT(SABALT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sabal_fns[a->esz], a, 1) static gen_helper_gvec_4 * const uabal_fns[4] = { NULL, gen_helper_sve2_uabal_h, gen_helper_sve2_uabal_s, gen_helper_sve2_uabal_d, }; -TRANS_FEAT(UABALB, aa64_sve2, gen_gvec_ool_arg_zzzz, uabal_fns[a->esz], a, 0) -TRANS_FEAT(UABALT, aa64_sve2, gen_gvec_ool_arg_zzzz, uabal_fns[a->esz], a, 1) +TRANS_FEAT(UABALB, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, uabal_fns[a->esz], a, 0) +TRANS_FEAT(UABALT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, uabal_fns[a->esz], a, 1) static bool do_adcl(DisasContext *s, arg_rrrr_esz *a, bool sel) { @@ -XXX,XX +XXX,XX @@ static bool do_adcl(DisasContext *s, arg_rrrr_esz *a, bool sel) return gen_gvec_ool_arg_zzzz(s, fns[a->esz & 1], a, (a->esz & 2) | sel); } -TRANS_FEAT(ADCLB, aa64_sve2, do_adcl, a, false) -TRANS_FEAT(ADCLT, aa64_sve2, do_adcl, a, true) +TRANS_FEAT(ADCLB, aa64_sme_or_sve2, do_adcl, a, false) +TRANS_FEAT(ADCLT, aa64_sme_or_sve2, do_adcl, a, true) -TRANS_FEAT(SSRA, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_ssra, a) -TRANS_FEAT(USRA, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_usra, a) -TRANS_FEAT(SRSRA, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_srsra, a) -TRANS_FEAT(URSRA, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_ursra, a) -TRANS_FEAT(SRI, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_sri, a) -TRANS_FEAT(SLI, aa64_sve2, gen_gvec_fn_arg_zzi, gen_gvec_sli, a) +TRANS_FEAT(SSRA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_ssra, a) +TRANS_FEAT(USRA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_usra, a) +TRANS_FEAT(SRSRA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_srsra, a) +TRANS_FEAT(URSRA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_ursra, a) +TRANS_FEAT(SRI, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_sri, a) +TRANS_FEAT(SLI, aa64_sme_or_sve2, gen_gvec_fn_arg_zzi, gen_gvec_sli, a) -TRANS_FEAT(SABA, aa64_sve2, gen_gvec_fn_arg_zzz, gen_gvec_saba, a) -TRANS_FEAT(UABA, aa64_sve2, gen_gvec_fn_arg_zzz, gen_gvec_uaba, a) +TRANS_FEAT(SABA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzz, gen_gvec_saba, a) +TRANS_FEAT(UABA, aa64_sme_or_sve2, gen_gvec_fn_arg_zzz, gen_gvec_uaba, a) static bool do_narrow_extract(DisasContext *s, arg_rri_esz *a, const GVecGen2 ops[3]) @@ -XXX,XX +XXX,XX @@ static const GVecGen2 sqxtnb_ops[3] = { .fno = gen_helper_sve2_sqxtnb_d, .vece = MO_64 }, }; -TRANS_FEAT(SQXTNB, aa64_sve2, do_narrow_extract, a, sqxtnb_ops) +TRANS_FEAT(SQXTNB, aa64_sme_or_sve2, do_narrow_extract, a, sqxtnb_ops) static void gen_sqxtnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n) { @@ -XXX,XX +XXX,XX @@ static const GVecGen2 sqxtnt_ops[3] = { .fno = gen_helper_sve2_sqxtnt_d, .vece = MO_64 }, }; -TRANS_FEAT(SQXTNT, aa64_sve2, do_narrow_extract, a, sqxtnt_ops) +TRANS_FEAT(SQXTNT, aa64_sme_or_sve2, do_narrow_extract, a, sqxtnt_ops) static const TCGOpcode uqxtn_list[] = { INDEX_op_shli_vec, INDEX_op_umin_vec, 0 @@ -XXX,XX +XXX,XX @@ static const GVecGen2 uqxtnb_ops[3] = { .fno = gen_helper_sve2_uqxtnb_d, .vece = MO_64 }, }; -TRANS_FEAT(UQXTNB, aa64_sve2, do_narrow_extract, a, uqxtnb_ops) +TRANS_FEAT(UQXTNB, aa64_sme_or_sve2, do_narrow_extract, a, uqxtnb_ops) static void gen_uqxtnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n) { @@ -XXX,XX +XXX,XX @@ static const GVecGen2 uqxtnt_ops[3] = { .fno = gen_helper_sve2_uqxtnt_d, .vece = MO_64 }, }; -TRANS_FEAT(UQXTNT, aa64_sve2, do_narrow_extract, a, uqxtnt_ops) +TRANS_FEAT(UQXTNT, aa64_sme_or_sve2, do_narrow_extract, a, uqxtnt_ops) static const TCGOpcode sqxtun_list[] = { INDEX_op_shli_vec, INDEX_op_umin_vec, INDEX_op_smax_vec, 0 @@ -XXX,XX +XXX,XX @@ static const GVecGen2 sqxtunb_ops[3] = { .fno = gen_helper_sve2_sqxtunb_d, .vece = MO_64 }, }; -TRANS_FEAT(SQXTUNB, aa64_sve2, do_narrow_extract, a, sqxtunb_ops) +TRANS_FEAT(SQXTUNB, aa64_sme_or_sve2, do_narrow_extract, a, sqxtunb_ops) static void gen_sqxtunt_vec(unsigned vece, TCGv_vec d, TCGv_vec n) { @@ -XXX,XX +XXX,XX @@ static const GVecGen2 sqxtunt_ops[3] = { .fno = gen_helper_sve2_sqxtunt_d, .vece = MO_64 }, }; -TRANS_FEAT(SQXTUNT, aa64_sve2, do_narrow_extract, a, sqxtunt_ops) +TRANS_FEAT(SQXTUNT, aa64_sme_or_sve2, do_narrow_extract, a, sqxtunt_ops) static bool do_shr_narrow(DisasContext *s, arg_rri_esz *a, const GVecGen2i ops[3]) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i shrnb_ops[3] = { .fno = gen_helper_sve2_shrnb_d, .vece = MO_64 }, }; -TRANS_FEAT(SHRNB, aa64_sve2, do_shr_narrow, a, shrnb_ops) +TRANS_FEAT(SHRNB, aa64_sme_or_sve2, do_shr_narrow, a, shrnb_ops) static void gen_shrnt_i64(unsigned vece, TCGv_i64 d, TCGv_i64 n, int shr) { @@ -XXX,XX +XXX,XX @@ static const GVecGen2i shrnt_ops[3] = { .fno = gen_helper_sve2_shrnt_d, .vece = MO_64 }, }; -TRANS_FEAT(SHRNT, aa64_sve2, do_shr_narrow, a, shrnt_ops) +TRANS_FEAT(SHRNT, aa64_sme_or_sve2, do_shr_narrow, a, shrnt_ops) static const GVecGen2i rshrnb_ops[3] = { { .fno = gen_helper_sve2_rshrnb_h }, { .fno = gen_helper_sve2_rshrnb_s }, { .fno = gen_helper_sve2_rshrnb_d }, }; -TRANS_FEAT(RSHRNB, aa64_sve2, do_shr_narrow, a, rshrnb_ops) +TRANS_FEAT(RSHRNB, aa64_sme_or_sve2, do_shr_narrow, a, rshrnb_ops) static const GVecGen2i rshrnt_ops[3] = { { .fno = gen_helper_sve2_rshrnt_h }, { .fno = gen_helper_sve2_rshrnt_s }, { .fno = gen_helper_sve2_rshrnt_d }, }; -TRANS_FEAT(RSHRNT, aa64_sve2, do_shr_narrow, a, rshrnt_ops) +TRANS_FEAT(RSHRNT, aa64_sme_or_sve2, do_shr_narrow, a, rshrnt_ops) static void gen_sqshrunb_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i sqshrunb_ops[3] = { .fno = gen_helper_sve2_sqshrunb_d, .vece = MO_64 }, }; -TRANS_FEAT(SQSHRUNB, aa64_sve2, do_shr_narrow, a, sqshrunb_ops) +TRANS_FEAT(SQSHRUNB, aa64_sme_or_sve2, do_shr_narrow, a, sqshrunb_ops) static void gen_sqshrunt_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i sqshrunt_ops[3] = { .fno = gen_helper_sve2_sqshrunt_d, .vece = MO_64 }, }; -TRANS_FEAT(SQSHRUNT, aa64_sve2, do_shr_narrow, a, sqshrunt_ops) +TRANS_FEAT(SQSHRUNT, aa64_sme_or_sve2, do_shr_narrow, a, sqshrunt_ops) static const GVecGen2i sqrshrunb_ops[3] = { { .fno = gen_helper_sve2_sqrshrunb_h }, { .fno = gen_helper_sve2_sqrshrunb_s }, { .fno = gen_helper_sve2_sqrshrunb_d }, }; -TRANS_FEAT(SQRSHRUNB, aa64_sve2, do_shr_narrow, a, sqrshrunb_ops) +TRANS_FEAT(SQRSHRUNB, aa64_sme_or_sve2, do_shr_narrow, a, sqrshrunb_ops) static const GVecGen2i sqrshrunt_ops[3] = { { .fno = gen_helper_sve2_sqrshrunt_h }, { .fno = gen_helper_sve2_sqrshrunt_s }, { .fno = gen_helper_sve2_sqrshrunt_d }, }; -TRANS_FEAT(SQRSHRUNT, aa64_sve2, do_shr_narrow, a, sqrshrunt_ops) +TRANS_FEAT(SQRSHRUNT, aa64_sme_or_sve2, do_shr_narrow, a, sqrshrunt_ops) static void gen_sqshrnb_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i sqshrnb_ops[3] = { .fno = gen_helper_sve2_sqshrnb_d, .vece = MO_64 }, }; -TRANS_FEAT(SQSHRNB, aa64_sve2, do_shr_narrow, a, sqshrnb_ops) +TRANS_FEAT(SQSHRNB, aa64_sme_or_sve2, do_shr_narrow, a, sqshrnb_ops) static void gen_sqshrnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i sqshrnt_ops[3] = { .fno = gen_helper_sve2_sqshrnt_d, .vece = MO_64 }, }; -TRANS_FEAT(SQSHRNT, aa64_sve2, do_shr_narrow, a, sqshrnt_ops) +TRANS_FEAT(SQSHRNT, aa64_sme_or_sve2, do_shr_narrow, a, sqshrnt_ops) static const GVecGen2i sqrshrnb_ops[3] = { { .fno = gen_helper_sve2_sqrshrnb_h }, { .fno = gen_helper_sve2_sqrshrnb_s }, { .fno = gen_helper_sve2_sqrshrnb_d }, }; -TRANS_FEAT(SQRSHRNB, aa64_sve2, do_shr_narrow, a, sqrshrnb_ops) +TRANS_FEAT(SQRSHRNB, aa64_sme_or_sve2, do_shr_narrow, a, sqrshrnb_ops) static const GVecGen2i sqrshrnt_ops[3] = { { .fno = gen_helper_sve2_sqrshrnt_h }, { .fno = gen_helper_sve2_sqrshrnt_s }, { .fno = gen_helper_sve2_sqrshrnt_d }, }; -TRANS_FEAT(SQRSHRNT, aa64_sve2, do_shr_narrow, a, sqrshrnt_ops) +TRANS_FEAT(SQRSHRNT, aa64_sme_or_sve2, do_shr_narrow, a, sqrshrnt_ops) static void gen_uqshrnb_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i uqshrnb_ops[3] = { .fno = gen_helper_sve2_uqshrnb_d, .vece = MO_64 }, }; -TRANS_FEAT(UQSHRNB, aa64_sve2, do_shr_narrow, a, uqshrnb_ops) +TRANS_FEAT(UQSHRNB, aa64_sme_or_sve2, do_shr_narrow, a, uqshrnb_ops) static void gen_uqshrnt_vec(unsigned vece, TCGv_vec d, TCGv_vec n, int64_t shr) @@ -XXX,XX +XXX,XX @@ static const GVecGen2i uqshrnt_ops[3] = { .fno = gen_helper_sve2_uqshrnt_d, .vece = MO_64 }, }; -TRANS_FEAT(UQSHRNT, aa64_sve2, do_shr_narrow, a, uqshrnt_ops) +TRANS_FEAT(UQSHRNT, aa64_sme_or_sve2, do_shr_narrow, a, uqshrnt_ops) static const GVecGen2i uqrshrnb_ops[3] = { { .fno = gen_helper_sve2_uqrshrnb_h }, { .fno = gen_helper_sve2_uqrshrnb_s }, { .fno = gen_helper_sve2_uqrshrnb_d }, }; -TRANS_FEAT(UQRSHRNB, aa64_sve2, do_shr_narrow, a, uqrshrnb_ops) +TRANS_FEAT(UQRSHRNB, aa64_sme_or_sve2, do_shr_narrow, a, uqrshrnb_ops) static const GVecGen2i uqrshrnt_ops[3] = { { .fno = gen_helper_sve2_uqrshrnt_h }, { .fno = gen_helper_sve2_uqrshrnt_s }, { .fno = gen_helper_sve2_uqrshrnt_d }, }; -TRANS_FEAT(UQRSHRNT, aa64_sve2, do_shr_narrow, a, uqrshrnt_ops) +TRANS_FEAT(UQRSHRNT, aa64_sme_or_sve2, do_shr_narrow, a, uqrshrnt_ops) #define DO_SVE2_ZZZ_NARROW(NAME, name) \ static gen_helper_gvec_3 * const name##_fns[4] = { \ NULL, gen_helper_sve2_##name##_h, \ gen_helper_sve2_##name##_s, gen_helper_sve2_##name##_d, \ }; \ - TRANS_FEAT(NAME, aa64_sve2, gen_gvec_ool_arg_zzz, \ + TRANS_FEAT(NAME, aa64_sme_or_sve2, gen_gvec_ool_arg_zzz, \ name##_fns[a->esz], a, 0) DO_SVE2_ZZZ_NARROW(ADDHNB, addhnb) @@ -XXX,XX +XXX,XX @@ TRANS_FEAT_NONSTREAMING(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz, TRANS_FEAT_NONSTREAMING(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz, a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0) -DO_ZPZZ_FP(FADDP, aa64_sve2, sve2_faddp_zpzz) -DO_ZPZZ_FP(FMAXNMP, aa64_sve2, sve2_fmaxnmp_zpzz) -DO_ZPZZ_FP(FMINNMP, aa64_sve2, sve2_fminnmp_zpzz) -DO_ZPZZ_FP(FMAXP, aa64_sve2, sve2_fmaxp_zpzz) -DO_ZPZZ_FP(FMINP, aa64_sve2, sve2_fminp_zpzz) +DO_ZPZZ_FP(FADDP, aa64_sme_or_sve2, sve2_faddp_zpzz) +DO_ZPZZ_FP(FMAXNMP, aa64_sme_or_sve2, sve2_fmaxnmp_zpzz) +DO_ZPZZ_FP(FMINNMP, aa64_sme_or_sve2, sve2_fminnmp_zpzz) +DO_ZPZZ_FP(FMAXP, aa64_sme_or_sve2, sve2_fmaxp_zpzz) +DO_ZPZZ_FP(FMINP, aa64_sme_or_sve2, sve2_fminp_zpzz) static bool do_fmmla(DisasContext *s, arg_rrrr_esz *a, gen_helper_gvec_4_ptr *fn) @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4 * const sqdmlal_zzzw_fns[] = { NULL, gen_helper_sve2_sqdmlal_zzzw_h, gen_helper_sve2_sqdmlal_zzzw_s, gen_helper_sve2_sqdmlal_zzzw_d, }; -TRANS_FEAT(SQDMLALB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLALB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlal_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(SQDMLALT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLALT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlal_zzzw_fns[a->esz], a, 3) -TRANS_FEAT(SQDMLALBT, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLALBT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlal_zzzw_fns[a->esz], a, 2) static gen_helper_gvec_4 * const sqdmlsl_zzzw_fns[] = { NULL, gen_helper_sve2_sqdmlsl_zzzw_h, gen_helper_sve2_sqdmlsl_zzzw_s, gen_helper_sve2_sqdmlsl_zzzw_d, }; -TRANS_FEAT(SQDMLSLB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLSLB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlsl_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(SQDMLSLT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLSLT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlsl_zzzw_fns[a->esz], a, 3) -TRANS_FEAT(SQDMLSLBT, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQDMLSLBT, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqdmlsl_zzzw_fns[a->esz], a, 2) static gen_helper_gvec_4 * const sqrdmlah_fns[] = { gen_helper_sve2_sqrdmlah_b, gen_helper_sve2_sqrdmlah_h, gen_helper_sve2_sqrdmlah_s, gen_helper_sve2_sqrdmlah_d, }; -TRANS_FEAT(SQRDMLAH_zzzz, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQRDMLAH_zzzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqrdmlah_fns[a->esz], a, 0) static gen_helper_gvec_4 * const sqrdmlsh_fns[] = { gen_helper_sve2_sqrdmlsh_b, gen_helper_sve2_sqrdmlsh_h, gen_helper_sve2_sqrdmlsh_s, gen_helper_sve2_sqrdmlsh_d, }; -TRANS_FEAT(SQRDMLSH_zzzz, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SQRDMLSH_zzzz, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, sqrdmlsh_fns[a->esz], a, 0) static gen_helper_gvec_4 * const smlal_zzzw_fns[] = { NULL, gen_helper_sve2_smlal_zzzw_h, gen_helper_sve2_smlal_zzzw_s, gen_helper_sve2_smlal_zzzw_d, }; -TRANS_FEAT(SMLALB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SMLALB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, smlal_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(SMLALT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SMLALT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, smlal_zzzw_fns[a->esz], a, 1) static gen_helper_gvec_4 * const umlal_zzzw_fns[] = { NULL, gen_helper_sve2_umlal_zzzw_h, gen_helper_sve2_umlal_zzzw_s, gen_helper_sve2_umlal_zzzw_d, }; -TRANS_FEAT(UMLALB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(UMLALB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, umlal_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(UMLALT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(UMLALT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, umlal_zzzw_fns[a->esz], a, 1) static gen_helper_gvec_4 * const smlsl_zzzw_fns[] = { NULL, gen_helper_sve2_smlsl_zzzw_h, gen_helper_sve2_smlsl_zzzw_s, gen_helper_sve2_smlsl_zzzw_d, }; -TRANS_FEAT(SMLSLB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SMLSLB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, smlsl_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(SMLSLT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(SMLSLT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, smlsl_zzzw_fns[a->esz], a, 1) static gen_helper_gvec_4 * const umlsl_zzzw_fns[] = { NULL, gen_helper_sve2_umlsl_zzzw_h, gen_helper_sve2_umlsl_zzzw_s, gen_helper_sve2_umlsl_zzzw_d, }; -TRANS_FEAT(UMLSLB_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(UMLSLB_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, umlsl_zzzw_fns[a->esz], a, 0) -TRANS_FEAT(UMLSLT_zzzw, aa64_sve2, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(UMLSLT_zzzw, aa64_sme_or_sve2, gen_gvec_ool_arg_zzzz, umlsl_zzzw_fns[a->esz], a, 1) static gen_helper_gvec_4 * const cmla_fns[] = { gen_helper_sve2_cmla_zzzz_b, gen_helper_sve2_cmla_zzzz_h, gen_helper_sve2_cmla_zzzz_s, gen_helper_sve2_cmla_zzzz_d, }; -TRANS_FEAT(CMLA_zzzz, aa64_sve2, gen_gvec_ool_zzzz, +TRANS_FEAT(CMLA_zzzz, aa64_sme_or_sve2, gen_gvec_ool_zzzz, cmla_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->rot) static gen_helper_gvec_4 * const cdot_fns[] = { NULL, NULL, gen_helper_sve2_cdot_zzzz_s, gen_helper_sve2_cdot_zzzz_d }; -TRANS_FEAT(CDOT_zzzz, aa64_sve2, gen_gvec_ool_zzzz, +TRANS_FEAT(CDOT_zzzz, aa64_sme_or_sve2, gen_gvec_ool_zzzz, cdot_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->rot) static gen_helper_gvec_4 * const sqrdcmlah_fns[] = { gen_helper_sve2_sqrdcmlah_zzzz_b, gen_helper_sve2_sqrdcmlah_zzzz_h, gen_helper_sve2_sqrdcmlah_zzzz_s, gen_helper_sve2_sqrdcmlah_zzzz_d, }; -TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sve2, gen_gvec_ool_zzzz, +TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sme_or_sve2, gen_gvec_ool_zzzz, sqrdcmlah_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->rot) TRANS_FEAT(USDOT_zzzz_4s, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz, @@ -XXX,XX +XXX,XX @@ static bool trans_RAX1(DisasContext *s, arg_RAX1 *a) return gen_gvec_fn_arg_zzz(s, gen_gvec_rax1, a); } -TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTNT_sh, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtnt_sh, a, 0, FPST_A64) -TRANS_FEAT(FCVTNT_ds, aa64_sve2, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTNT_ds, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtnt_ds, a, 0, FPST_A64) TRANS_FEAT(BFCVTNT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, gen_helper_sve_bfcvtnt, a, 0, s->fpcr_ah ? FPST_AH : FPST_A64) -TRANS_FEAT(FCVTLT_hs, aa64_sve2, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTLT_hs, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtlt_hs, a, 0, FPST_A64) -TRANS_FEAT(FCVTLT_sd, aa64_sve2, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(FCVTLT_sd, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtlt_sd, a, 0, FPST_A64) -TRANS_FEAT(FCVTX_ds, aa64_sve2, do_frint_mode, a, +TRANS_FEAT(FCVTX_ds, aa64_sme_or_sve2, do_frint_mode, a, FPROUNDING_ODD, gen_helper_sve_fcvt_ds) -TRANS_FEAT(FCVTXNT_ds, aa64_sve2, do_frint_mode, a, +TRANS_FEAT(FCVTXNT_ds, aa64_sme_or_sve2, do_frint_mode, a, FPROUNDING_ODD, gen_helper_sve2_fcvtnt_ds) static gen_helper_gvec_3_ptr * const flogb_fns[] = { NULL, gen_helper_flogb_h, gen_helper_flogb_s, gen_helper_flogb_d }; -TRANS_FEAT(FLOGB, aa64_sve2, gen_gvec_fpst_arg_zpz, flogb_fns[a->esz], +TRANS_FEAT(FLOGB, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, flogb_fns[a->esz], a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static bool do_FMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sub, bool sel) @@ -XXX,XX +XXX,XX @@ static bool do_FMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sub, bool sel) (sel << 1) | sub, tcg_env); } -TRANS_FEAT(FMLALB_zzzw, aa64_sve2, do_FMLAL_zzzw, a, false, false) -TRANS_FEAT(FMLALT_zzzw, aa64_sve2, do_FMLAL_zzzw, a, false, true) -TRANS_FEAT(FMLSLB_zzzw, aa64_sve2, do_FMLAL_zzzw, a, true, false) -TRANS_FEAT(FMLSLT_zzzw, aa64_sve2, do_FMLAL_zzzw, a, true, true) +TRANS_FEAT(FMLALB_zzzw, aa64_sme_or_sve2, do_FMLAL_zzzw, a, false, false) +TRANS_FEAT(FMLALT_zzzw, aa64_sme_or_sve2, do_FMLAL_zzzw, a, false, true) +TRANS_FEAT(FMLSLB_zzzw, aa64_sme_or_sve2, do_FMLAL_zzzw, a, true, false) +TRANS_FEAT(FMLSLT_zzzw, aa64_sme_or_sve2, do_FMLAL_zzzw, a, true, true) static bool do_FMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sub, bool sel) { @@ -XXX,XX +XXX,XX @@ static bool do_FMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sub, bool sel) (a->index << 3) | (sel << 1) | sub, tcg_env); } -TRANS_FEAT(FMLALB_zzxw, aa64_sve2, do_FMLAL_zzxw, a, false, false) -TRANS_FEAT(FMLALT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, false, true) -TRANS_FEAT(FMLSLB_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, false) -TRANS_FEAT(FMLSLT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, true) +TRANS_FEAT(FMLALB_zzxw, aa64_sme_or_sve2, do_FMLAL_zzxw, a, false, false) +TRANS_FEAT(FMLALT_zzxw, aa64_sme_or_sve2, do_FMLAL_zzxw, a, false, true) +TRANS_FEAT(FMLSLB_zzxw, aa64_sme_or_sve2, do_FMLAL_zzxw, a, true, false) +TRANS_FEAT(FMLSLT_zzxw, aa64_sme_or_sve2, do_FMLAL_zzxw, a, true, true) TRANS_FEAT_NONSTREAMING(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz, gen_helper_gvec_smmla_b, a, 0) -- 2.43.0
The I8MM field of ID_AA64ZFR0_EL1 is set when the CPU implements FEAT_I8MM and either FEAT_SVE or FEAT_SME. Currently we assume that it is only set for FEAT_SVE. Update the feature checks: * we rename the existing feature check function to sve_sme_i8mm to indicate that it is true for either SVE or SME I8MM * we add a new check function for FEAT_SVE && FEAT_I8MM (giving it the sve_i8mm name that the old function used to have) * the instructions which are (SVE || SME) && I8MM need their checks updating to sve_sme_i8mm: these are SUDOT, USDOT * instructions which are SVE && I8MM (i.e. really SVE-only) stay unchanged with sve_i8mm: these are SMMLA, USMMLA, UMMLA Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-12-peter.maydell@linaro.org --- target/arm/cpu-features.h | 8 +++++++- target/arm/tcg/translate-sve.c | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SM4) != 0; } -static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) +/* Note that this is true if either SVE or SME are implemented with I8MM */ +static inline bool isar_feature_aa64_sme_sve_i8mm(const ARMISARegisters *id) { return FIELD_EX64_IDREG(id, ID_AA64ZFR0, I8MM) != 0; } @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme2_f64f64(const ARMISARegisters *id) return isar_feature_aa64_sme2(id) && isar_feature_aa64_sme_f64f64(id); } +static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) +{ + return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_i8mm(id); +} + /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UDOT_zzxw_4s, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, TRANS_FEAT(UDOT_zzxw_4d, aa64_sme_or_sve, gen_gvec_ool_arg_zzxz, gen_helper_gvec_udot_idx_4h, a) -TRANS_FEAT(SUDOT_zzxw_4s, aa64_sve_i8mm, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(SUDOT_zzxw_4s, aa64_sme_sve_i8mm, gen_gvec_ool_arg_zzxz, gen_helper_gvec_sudot_idx_4b, a) -TRANS_FEAT(USDOT_zzxw_4s, aa64_sve_i8mm, gen_gvec_ool_arg_zzxz, +TRANS_FEAT(USDOT_zzxw_4s, aa64_sme_sve_i8mm, gen_gvec_ool_arg_zzxz, gen_helper_gvec_usdot_idx_4b, a) TRANS_FEAT(SDOT_zzxw_2s, aa64_sme2_or_sve2p1, gen_gvec_ool_arg_zzxz, @@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_4 * const sqrdcmlah_fns[] = { TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sme_or_sve2, gen_gvec_ool_zzzz, sqrdcmlah_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->rot) -TRANS_FEAT(USDOT_zzzz_4s, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz, +TRANS_FEAT(USDOT_zzzz_4s, aa64_sme_sve_i8mm, gen_gvec_ool_arg_zzzz, gen_helper_gvec_usdot_4b, a, 0) TRANS_FEAT(SDOT_zzzz_2s, aa64_sme2_or_sve2p1, gen_gvec_ool_arg_zzzz, -- 2.43.0
As with I8MM, the BF16 field of ID_AA64ZFR0_EL1 is set when the CPU implements FEAT_BF16 and either FEAT_SVE or FEAT_SME, so we need to have separate checks for "(SVE || SME) && BF16" and "SVE && BF16". Follow the same pattern as with I8MM: * aa64_sve_sme_bf16 means (SVE || SME) && BF16 * aa64_sve_bf16 means (SVE && BF16) BFMMLA is the only SVE BF16 insn that isn't in SME. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-13-peter.maydell@linaro.org --- target/arm/cpu-features.h | 7 ++++++- target/arm/tcg/translate-sve.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0; } -static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) +static inline bool isar_feature_aa64_sme_sve_bf16(const ARMISARegisters *id) { return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BFLOAT16) != 0; } @@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_i8mm(id); } +static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) +{ + return isar_feature_aa64_sve(id) && isar_feature_aa64_sme_sve_bf16(id); +} + /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FCVT_sh, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, TRANS_FEAT(FCVT_hs, aa64_sme_or_sve, gen_gvec_fpst_arg_zpz, gen_helper_sve_fcvt_hs, a, 0, FPST_A64_F16) -TRANS_FEAT(BFCVT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(BFCVT, aa64_sme_sve_bf16, gen_gvec_fpst_arg_zpz, gen_helper_sve_bfcvt, a, 0, s->fpcr_ah ? FPST_AH : FPST_A64) @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FCVTNT_sh, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, TRANS_FEAT(FCVTNT_ds, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz, gen_helper_sve2_fcvtnt_ds, a, 0, FPST_A64) -TRANS_FEAT(BFCVTNT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, +TRANS_FEAT(BFCVTNT, aa64_sme_sve_bf16, gen_gvec_fpst_arg_zpz, gen_helper_sve_bfcvtnt, a, 0, s->fpcr_ah ? FPST_AH : FPST_A64) @@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FDOT_zzzz, aa64_sme2_or_sve2p1, gen_gvec_env_arg_zzzz, TRANS_FEAT(FDOT_zzxz, aa64_sme2_or_sve2p1, gen_gvec_env_arg_zzxz, gen_helper_sme2_fdot_idx_h, a) -TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_env_arg_zzzz, +TRANS_FEAT(BFDOT_zzzz, aa64_sme_sve_bf16, gen_gvec_env_arg_zzzz, gen_helper_gvec_bfdot, a, 0) -TRANS_FEAT(BFDOT_zzxz, aa64_sve_bf16, gen_gvec_env_arg_zzxz, +TRANS_FEAT(BFDOT_zzxz, aa64_sme_sve_bf16, gen_gvec_env_arg_zzxz, gen_helper_gvec_bfdot_idx, a) TRANS_FEAT_NONSTREAMING(BFMMLA, aa64_sve_bf16, gen_gvec_env_arg_zzzz, @@ -XXX,XX +XXX,XX @@ static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel) s->fpcr_ah ? FPST_AH : FPST_A64); } -TRANS_FEAT(BFMLALB_zzzw, aa64_sve_bf16, do_BFMLAL_zzzw, a, false) -TRANS_FEAT(BFMLALT_zzzw, aa64_sve_bf16, do_BFMLAL_zzzw, a, true) +TRANS_FEAT(BFMLALB_zzzw, aa64_sme_sve_bf16, do_BFMLAL_zzzw, a, false) +TRANS_FEAT(BFMLALT_zzzw, aa64_sme_sve_bf16, do_BFMLAL_zzzw, a, true) static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel) { @@ -XXX,XX +XXX,XX @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel) s->fpcr_ah ? FPST_AH : FPST_A64); } -TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false) -TRANS_FEAT(BFMLALT_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, true) +TRANS_FEAT(BFMLALB_zzxw, aa64_sme_sve_bf16, do_BFMLAL_zzxw, a, false) +TRANS_FEAT(BFMLALT_zzxw, aa64_sme_sve_bf16, do_BFMLAL_zzxw, a, true) static bool do_BFMLSL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel) { -- 2.43.0
The ID register ID_AA64ZFR0_EL1's fields are not all for SVE exclusive features; some are also used to describe SME on an SME-only CPU: SVE-only fields: * F64MM, F32MM, F16MM, SM4, B16B16, SVEVer Fields used for SVE and SME (in some cases there is also a field for SME in ID_AA64SMFR0_EL1, but it is just a "present or absent" single bit flag and the ZFR0 field then tells you what level of support is present): * I8MM, SHA3, BF16, BitPerm, EltPerm, AES Currently we zero the whole ID_AA64ZFR0_EL1 register in arm_cpu_sve_finalize() if SVE is not present, which wipes also the fields we need for SME. Only clear the fields which are SVE-specific here, and clear the rest in arm_cpu_sme_finalize() if we have neither SME nor SVE. This requires us to update our ID_AA64ZFR0 field definitions to match the rev M.a.a Arm ARM, as the F16MM SVE-only field is not one we had a definition for previously. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-14-peter.maydell@linaro.org --- target/arm/cpu-features.h | 2 ++ target/arm/cpu64.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, HPMN0, 60, 4) FIELD(ID_AA64ZFR0, SVEVER, 0, 4) FIELD(ID_AA64ZFR0, AES, 4, 4) +FIELD(ID_AA64ZFR0, ELTPERM, 12, 4) FIELD(ID_AA64ZFR0, BITPERM, 16, 4) FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4) FIELD(ID_AA64ZFR0, B16B16, 24, 4) FIELD(ID_AA64ZFR0, SHA3, 32, 4) FIELD(ID_AA64ZFR0, SM4, 40, 4) FIELD(ID_AA64ZFR0, I8MM, 44, 4) +FIELD(ID_AA64ZFR0, F16MM, 48, 4) FIELD(ID_AA64ZFR0, F32MM, 52, 4) FIELD(ID_AA64ZFR0, F64MM, 56, 4) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) if (!cpu_isar_feature(aa64_sve, cpu)) { /* * SVE is disabled and so are all vector lengths. Good. - * Disable all SVE extensions as well. + * Disable all SVE extensions as well. Note that some ZFR0 + * fields are used also by SME so must not be wiped in + * an SME-no-SVE config. We will clear the rest in + * arm_cpu_sme_finalize() if necessary. */ - SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F64MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F32MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F16MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, SM4, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, B16B16, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, SVEVER, 0); return; } @@ -XXX,XX +XXX,XX @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) if (vq_map == 0) { if (!cpu_isar_feature(aa64_sme, cpu)) { SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0); + if (!cpu_isar_feature(aa64_sve, cpu)) { + /* This clears the "SVE or SME" fields in ZFR0 */ + SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); + } return; } -- 2.43.0
FEAT_SME_FA64 allows Streaming SVE code to access the whole SVE instruction set; it requires FEAT_SVE to be present. If we have a CPU with SME but not SVE, squash the FA64 bit in arm_cpu_sme_finalize(). This doesn't have any effect at the moment because we don't let the user create an SME-without-SVE CPU, but we are about to lift that restriction. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260202133353.2231685-15-peter.maydell@linaro.org --- target/arm/cpu64.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -XXX,XX +XXX,XX @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) /* SME2 or better */ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, 2); } + + if (!cpu_isar_feature(aa64_sve, cpu)) { + /* FEAT_SME_FA64 requires SVE, not just SME */ + FIELD_DP64_IDREG(&cpu->isar, ID_AA64SMFR0, FA64, 0); + } } static bool cpu_arm_get_sme(Object *obj, Error **errp) -- 2.43.0
In commit f7767ca30179 ("target/arm: Disable SME if SVE is disabled") we added code that forces SME to be disabled if SVE is disabled. This was something we did in the run-up to a release to avoid an assertion failure in smcr_write() if the user disabled SVE on the 'max' CPU without disabling SME also. Now that we have corrected the code so that it doesn't assert in an SME-without-SVE setup, we can let users select it. This effectively reverts f7767ca30179. Note that this now means that command lines like "-cpu max,sve=off" which used to turn off SME and SVE will now give you a CPU with SME but not SVE. This is permitted by our loose "max can always give you extra stuff" rules, but may be unexpected to users. Mention this in the CPU property documentation. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260202133353.2231685-16-peter.maydell@linaro.org --- docs/system/arm/cpu-features.rst | 10 ++++++++-- target/arm/cpu.c | 10 ---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -XXX,XX +XXX,XX @@ SVE CPU Property Parsing Semantics enable SVE2). There are not generally any lower-level controls for disabling specific SVE sub-features. + 11) Disabling SVE does not automatically disable SME. If you want to + disable both you must use ``sve=off,sme=off``. In particular, + for the ``max`` CPU, ``sve=off`` alone will give you a CPU with + SME only (and which therefore still has the SVE vector registers). + Most users will want to disable both at once. + SVE CPU Property Examples ------------------------- - 1) Disable SVE:: + 1) Disable SVE and SME:: - $ qemu-system-aarch64 -M virt -cpu max,sve=off + $ qemu-system-aarch64 -M virt -cpu max,sve=off,sme=off 2) Implicitly enable all vector lengths for the ``max`` CPU type:: diff --git a/target/arm/cpu.c b/target/arm/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -XXX,XX +XXX,XX @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp) return; } - /* - * FEAT_SME is not architecturally dependent on FEAT_SVE (unless - * FEAT_SME_FA64 is present). However our implementation currently - * assumes it, so if the user asked for sve=off then turn off SME also. - * (KVM doesn't currently support SME at all.) - */ - if (cpu_isar_feature(aa64_sme, cpu) && !cpu_isar_feature(aa64_sve, cpu)) { - object_property_set_bool(OBJECT(cpu), "sme", false, &error_abort); - } - arm_cpu_sme_finalize(cpu, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); -- 2.43.0
From: BALATON Zoltan <balaton@eik.bme.hu> According to the USB OHCI specification section 6.5.6 ("FrameNumberOverflow Event"), when bit 15 of the frame count changes (either from 1 to 0 or 0 to 1) a FrameNumberOverflow interrupt should be generated. This fixes usb-audio on mac99,via=pmu with MacOS 9. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3274 Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> Tested-by: Elisey Konstantinov <elisey.konstantinov@gmail.com> Message-id: 20260212185425.2F854596A29@zero.eik.bme.hu [PMM: added brief comment, tweaked commit message] Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> --- hw/usb/hcd-ohci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index XXXXXXX..XXXXXXX 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -XXX,XX +XXX,XX @@ static void ohci_frame_boundary(void *opaque) hcca.frame = cpu_to_le16(ohci->frame_number); /* When the HC updates frame number, set pad to 0. Ref OHCI Spec 4.4.1*/ hcca.pad = 0; + /* FrameNumberOverflow happens when bit 15 of frame number changes */ + if (ohci->frame_number == 0x8000 || ohci->frame_number == 0) { + ohci_set_interrupt(ohci, OHCI_INTR_FNO); + } if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { if (!ohci->done) { -- 2.43.0
From: Osama Abdelkader <osama.abdelkader@gmail.com> cpu.h is included twice Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com> Message-id: 20260217204754.101223-1-osama.abdelkader@gmail.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/whpx/whpx-all.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/whpx/whpx-all.c +++ b/target/arm/whpx/whpx-all.c @@ -XXX,XX +XXX,XX @@ #include <winerror.h> #include "syndrome.h" -#include "cpu.h" #include "target/arm/cpregs.h" #include "internals.h" -- 2.43.0
From: Osama Abdelkader <osama.abdelkader@gmail.com> In whpx_get_registers and whpx_set_registers the loops over FP registers were using whpx_reg_match[i].reg instead of whpx_fpreg_match[i].reg Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr <mailto:mohamed@unpredictable.fr>> Message-id: 20260217210805.104427-1-osama.abdelkader@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/whpx/whpx-all.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/whpx/whpx-all.c +++ b/target/arm/whpx/whpx-all.c @@ -XXX,XX +XXX,XX @@ void whpx_get_registers(CPUState *cpu) } for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) { - whpx_get_reg(cpu, whpx_reg_match[i].reg, &val); + whpx_get_reg(cpu, whpx_fpreg_match[i].reg, &val); memcpy((char *)env + whpx_fpreg_match[i].offset, &val, sizeof(val.Reg128)); } @@ -XXX,XX +XXX,XX @@ void whpx_set_registers(CPUState *cpu, int level) for (i = 0; i < ARRAY_SIZE(whpx_fpreg_match); i++) { memcpy(&val.Reg128, (char *)env + whpx_fpreg_match[i].offset, sizeof(val.Reg128)); - whpx_set_reg(cpu, whpx_reg_match[i].reg, val); + whpx_set_reg(cpu, whpx_fpreg_match[i].reg, val); } clean_whv_register_value(&val); -- 2.43.0
The target/arm/debug_helper.c file has some code which we need for non-TCG accelerators, but quite a lot which is guarded by a CONFIG_TCG ifdef. Move all this TCG-only code out to a new file target/arm/tcg/debug.c. In particular all the code requiring access to the TCG helper function prototypes is in the moved code, so we can drop the use of tcg/helper.h from debug_helper.c. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-2-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/debug_helper.c | 769 --------------------- target/arm/{debug_helper.c => tcg/debug.c} | 544 +-------------- target/arm/tcg/meson.build | 2 + 3 files changed, 4 insertions(+), 1311 deletions(-) copy target/arm/{debug_helper.c => tcg/debug.c} (53%) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -XXX,XX +XXX,XX @@ #include "exec/watchpoint.h" #include "system/tcg.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - -#ifdef CONFIG_TCG -/* Return the Exception Level targeted by debug exceptions. */ -static int arm_debug_target_el(CPUARMState *env) -{ - bool secure = arm_is_secure(env); - bool route_to_el2 = false; - - if (arm_feature(env, ARM_FEATURE_M)) { - return 1; - } - - if (arm_is_el2_enabled(env)) { - route_to_el2 = env->cp15.hcr_el2 & HCR_TGE || - env->cp15.mdcr_el2 & MDCR_TDE; - } - - if (route_to_el2) { - return 2; - } else if (arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3) && secure) { - return 3; - } else { - return 1; - } -} - -/* - * Raise an exception to the debug target el. - * Modify syndrome to indicate when origin and target EL are the same. - */ -G_NORETURN static void -raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome) -{ - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* - * If singlestep is targeting a lower EL than the current one, then - * DisasContext.ss_active must be false and we can never get here. - * Similarly for watchpoint and breakpoint matches. - */ - assert(debug_el >= cur_el); - syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT; - raise_exception(env, excp, syndrome, debug_el); -} - -/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ -static bool aa64_generate_debug_exceptions(CPUARMState *env) -{ - int cur_el = arm_current_el(env); - int debug_el; - - if (cur_el == 3) { - return false; - } - - /* MDCR_EL3.SDD disables debug events from Secure state */ - if (arm_is_secure_below_el3(env) - && extract32(env->cp15.mdcr_el3, 16, 1)) { - return false; - } - - /* - * Same EL to same EL debug exceptions need MDSCR_KDE enabled - * while not masking the (D)ebug bit in DAIF. - */ - debug_el = arm_debug_target_el(env); - - if (cur_el == debug_el) { - return extract32(env->cp15.mdscr_el1, 13, 1) - && !(env->daif & PSTATE_D); - } - - /* Otherwise the debug target needs to be a higher EL */ - return debug_el > cur_el; -} - -static bool aa32_generate_debug_exceptions(CPUARMState *env) -{ - int el = arm_current_el(env); - - if (el == 0 && arm_el_is_aa64(env, 1)) { - return aa64_generate_debug_exceptions(env); - } - - if (arm_is_secure(env)) { - int spd; - - if (el == 0 && (env->cp15.sder & 1)) { - /* - * SDER.SUIDEN means debug exceptions from Secure EL0 - * are always enabled. Otherwise they are controlled by - * SDCR.SPD like those from other Secure ELs. - */ - return true; - } - - spd = extract32(env->cp15.mdcr_el3, 14, 2); - switch (spd) { - case 1: - /* SPD == 0b01 is reserved, but behaves as 0b00. */ - case 0: - /* - * For 0b00 we return true if external secure invasive debug - * is enabled. On real hardware this is controlled by external - * signals to the core. QEMU always permits debug, and behaves - * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high. - */ - return true; - case 2: - return false; - case 3: - return true; - } - } - - return el != 2; -} - -/* - * Return true if debugging exceptions are currently enabled. - * This corresponds to what in ARM ARM pseudocode would be - * if UsingAArch32() then - * return AArch32.GenerateDebugExceptions() - * else - * return AArch64.GenerateDebugExceptions() - * We choose to push the if() down into this function for clarity, - * since the pseudocode has it at all callsites except for the one in - * CheckSoftwareStep(), where it is elided because both branches would - * always return the same value. - */ -bool arm_generate_debug_exceptions(CPUARMState *env) -{ - if ((env->cp15.oslsr_el1 & 1) || (env->cp15.osdlr_el1 & 1)) { - return false; - } - if (is_a64(env)) { - return aa64_generate_debug_exceptions(env); - } else { - return aa32_generate_debug_exceptions(env); - } -} - -/* - * Is single-stepping active? (Note that the "is EL_D AArch64?" check - * implicitly means this always returns false in pre-v8 CPUs.) - */ -bool arm_singlestep_active(CPUARMState *env) -{ - return extract32(env->cp15.mdscr_el1, 0, 1) - && arm_el_is_aa64(env, arm_debug_target_el(env)) - && arm_generate_debug_exceptions(env); -} - -/* Return true if the linked breakpoint entry lbn passes its checks */ -static bool linked_bp_matches(ARMCPU *cpu, int lbn) -{ - CPUARMState *env = &cpu->env; - uint64_t bcr = env->cp15.dbgbcr[lbn]; - int brps = arm_num_brps(cpu); - int ctx_cmps = arm_num_ctx_cmps(cpu); - int bt; - uint32_t contextidr; - uint64_t hcr_el2; - - /* - * Links to unimplemented or non-context aware breakpoints are - * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or - * as if linked to an UNKNOWN context-aware breakpoint (in which - * case DBGWCR<n>_EL1.LBN must indicate that breakpoint). - * We choose the former. - */ - if (lbn >= brps || lbn < (brps - ctx_cmps)) { - return false; - } - - bcr = env->cp15.dbgbcr[lbn]; - - if (extract64(bcr, 0, 1) == 0) { - /* Linked breakpoint disabled : generate no events */ - return false; - } - - bt = extract64(bcr, 20, 4); - hcr_el2 = arm_hcr_el2_eff(env); - - switch (bt) { - case 3: /* linked context ID match */ - switch (arm_current_el(env)) { - default: - /* Context matches never fire in AArch64 EL3 */ - return false; - case 2: - if (!(hcr_el2 & HCR_E2H)) { - /* Context matches never fire in EL2 without E2H enabled. */ - return false; - } - contextidr = env->cp15.contextidr_el[2]; - break; - case 1: - contextidr = env->cp15.contextidr_el[1]; - break; - case 0: - if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) { - contextidr = env->cp15.contextidr_el[2]; - } else { - contextidr = env->cp15.contextidr_el[1]; - } - break; - } - break; - - case 7: /* linked contextidr_el1 match */ - contextidr = env->cp15.contextidr_el[1]; - break; - case 13: /* linked contextidr_el2 match */ - contextidr = env->cp15.contextidr_el[2]; - break; - - case 9: /* linked VMID match (reserved if no EL2) */ - case 11: /* linked context ID and VMID match (reserved if no EL2) */ - case 15: /* linked full context ID match */ - default: - /* - * Links to Unlinked context breakpoints must generate no - * events; we choose to do the same for reserved values too. - */ - return false; - } - - /* - * We match the whole register even if this is AArch32 using the - * short descriptor format (in which case it holds both PROCID and ASID), - * since we don't implement the optional v7 context ID masking. - */ - return contextidr == (uint32_t)env->cp15.dbgbvr[lbn]; -} - -static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp) -{ - CPUARMState *env = &cpu->env; - uint64_t cr; - int pac, hmc, ssc, wt, lbn; - /* - * Note that for watchpoints the check is against the CPU security - * state, not the S/NS attribute on the offending data access. - */ - bool is_secure = arm_is_secure(env); - int access_el = arm_current_el(env); - - if (is_wp) { - CPUWatchpoint *wp = env->cpu_watchpoint[n]; - - if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) { - return false; - } - cr = env->cp15.dbgwcr[n]; - if (wp->hitattrs.user) { - /* - * The LDRT/STRT/LDT/STT "unprivileged access" instructions should - * match watchpoints as if they were accesses done at EL0, even if - * the CPU is at EL1 or higher. - */ - access_el = 0; - } - } else { - uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; - - if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) { - return false; - } - cr = env->cp15.dbgbcr[n]; - } - /* - * The WATCHPOINT_HIT flag guarantees us that the watchpoint is - * enabled and that the address and access type match; for breakpoints - * we know the address matched; check the remaining fields, including - * linked breakpoints. We rely on WCR and BCR having the same layout - * for the LBN, SSC, HMC, PAC/PMC and is-linked fields. - * Note that some combinations of {PAC, HMC, SSC} are reserved and - * must act either like some valid combination or as if the watchpoint - * were disabled. We choose the former, and use this together with - * the fact that EL3 must always be Secure and EL2 must always be - * Non-Secure to simplify the code slightly compared to the full - * table in the ARM ARM. - */ - pac = FIELD_EX64(cr, DBGWCR, PAC); - hmc = FIELD_EX64(cr, DBGWCR, HMC); - ssc = FIELD_EX64(cr, DBGWCR, SSC); - - switch (ssc) { - case 0: - break; - case 1: - case 3: - if (is_secure) { - return false; - } - break; - case 2: - if (!is_secure) { - return false; - } - break; - } - - switch (access_el) { - case 3: - case 2: - if (!hmc) { - return false; - } - break; - case 1: - if (extract32(pac, 0, 1) == 0) { - return false; - } - break; - case 0: - if (extract32(pac, 1, 1) == 0) { - return false; - } - break; - default: - g_assert_not_reached(); - } - - wt = FIELD_EX64(cr, DBGWCR, WT); - lbn = FIELD_EX64(cr, DBGWCR, LBN); - - if (wt && !linked_bp_matches(cpu, lbn)) { - return false; - } - - return true; -} - -static bool check_watchpoints(ARMCPU *cpu) -{ - CPUARMState *env = &cpu->env; - int n; - - /* - * If watchpoints are disabled globally or we can't take debug - * exceptions here then watchpoint firings are ignored. - */ - if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 - || !arm_generate_debug_exceptions(env)) { - return false; - } - - for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) { - if (bp_wp_matches(cpu, n, true)) { - return true; - } - } - return false; -} - -bool arm_debug_check_breakpoint(CPUState *cs) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - vaddr pc; - int n; - - /* - * If breakpoints are disabled globally or we can't take debug - * exceptions here then breakpoint firings are ignored. - */ - if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 - || !arm_generate_debug_exceptions(env)) { - return false; - } - - /* - * Single-step exceptions have priority over breakpoint exceptions. - * If single-step state is active-pending, suppress the bp. - */ - if (arm_singlestep_active(env) && !(env->pstate & PSTATE_SS)) { - return false; - } - - /* - * PC alignment faults have priority over breakpoint exceptions. - */ - pc = is_a64(env) ? env->pc : env->regs[15]; - if ((is_a64(env) || !env->thumb) && (pc & 3) != 0) { - return false; - } - - /* - * Instruction aborts have priority over breakpoint exceptions. - * TODO: We would need to look up the page for PC and verify that - * it is present and executable. - */ - - for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) { - if (bp_wp_matches(cpu, n, false)) { - return true; - } - } - return false; -} - -bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) -{ - /* - * Called by core code when a CPU watchpoint fires; need to check if this - * is also an architectural watchpoint match. - */ - ARMCPU *cpu = ARM_CPU(cs); - - return check_watchpoints(cpu); -} - -/* - * Return the FSR value for a debug exception (watchpoint, hardware - * breakpoint or BKPT insn) targeting the specified exception level. - */ -static uint32_t arm_debug_exception_fsr(CPUARMState *env) -{ - ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; - int target_el = arm_debug_target_el(env); - bool using_lpae; - - if (arm_feature(env, ARM_FEATURE_M)) { - using_lpae = false; - } else if (target_el == 2 || arm_el_is_aa64(env, target_el)) { - using_lpae = true; - } else if (arm_feature(env, ARM_FEATURE_PMSA) && - arm_feature(env, ARM_FEATURE_V8)) { - using_lpae = true; - } else if (arm_feature(env, ARM_FEATURE_LPAE) && - (env->cp15.tcr_el[target_el] & TTBCR_EAE)) { - using_lpae = true; - } else { - using_lpae = false; - } - - if (using_lpae) { - return arm_fi_to_lfsc(&fi); - } else { - return arm_fi_to_sfsc(&fi); - } -} - -void arm_debug_excp_handler(CPUState *cs) -{ - /* - * Called by core code when a watchpoint or breakpoint fires; - * need to check which one and raise the appropriate exception. - */ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - CPUWatchpoint *wp_hit = cs->watchpoint_hit; - - if (wp_hit) { - if (wp_hit->flags & BP_CPU) { - bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0; - - cs->watchpoint_hit = NULL; - - env->exception.fsr = arm_debug_exception_fsr(env); - env->exception.vaddress = wp_hit->hitaddr; - raise_exception_debug(env, EXCP_DATA_ABORT, - syn_watchpoint(0, 0, wnr)); - } - } else { - uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; - - /* - * (1) GDB breakpoints should be handled first. - * (2) Do not raise a CPU exception if no CPU breakpoint has fired, - * since singlestep is also done by generating a debug internal - * exception. - */ - if (cpu_breakpoint_test(cs, pc, BP_GDB) - || !cpu_breakpoint_test(cs, pc, BP_CPU)) { - return; - } - - env->exception.fsr = arm_debug_exception_fsr(env); - /* - * FAR is UNKNOWN: clear vaddress to avoid potentially exposing - * values to the guest that it shouldn't be able to see at its - * exception/security level. - */ - env->exception.vaddress = 0; - raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0)); - } -} - -/* - * Raise an EXCP_BKPT with the specified syndrome register value, - * targeting the correct exception level for debug exceptions. - */ -void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) -{ - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* FSR will only be used if the debug target EL is AArch32. */ - env->exception.fsr = arm_debug_exception_fsr(env); - /* - * FAR is UNKNOWN: clear vaddress to avoid potentially exposing - * values to the guest that it shouldn't be able to see at its - * exception/security level. - */ - env->exception.vaddress = 0; - /* - * Other kinds of architectural debug exception are ignored if - * they target an exception level below the current one (in QEMU - * this is checked by arm_generate_debug_exceptions()). Breakpoint - * instructions are special because they always generate an exception - * to somewhere: if they can't go to the configured debug exception - * level they are taken to the current exception level. - */ - if (debug_el < cur_el) { - debug_el = cur_el; - } - raise_exception(env, EXCP_BKPT, syndrome, debug_el); -} - -void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) -{ - raise_exception_debug(env, EXCP_UDEF, syndrome); -} - -void hw_watchpoint_update(ARMCPU *cpu, int n) -{ - CPUARMState *env = &cpu->env; - vaddr len = 0; - vaddr wvr = env->cp15.dbgwvr[n]; - uint64_t wcr = env->cp15.dbgwcr[n]; - int mask; - int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; - - if (env->cpu_watchpoint[n]) { - cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); - env->cpu_watchpoint[n] = NULL; - } - - if (!FIELD_EX64(wcr, DBGWCR, E)) { - /* E bit clear : watchpoint disabled */ - return; - } - - switch (FIELD_EX64(wcr, DBGWCR, LSC)) { - case 0: - /* LSC 00 is reserved and must behave as if the wp is disabled */ - return; - case 1: - flags |= BP_MEM_READ; - break; - case 2: - flags |= BP_MEM_WRITE; - break; - case 3: - flags |= BP_MEM_ACCESS; - break; - } - - /* - * Attempts to use both MASK and BAS fields simultaneously are - * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, - * thus generating a watchpoint for every byte in the masked region. - */ - mask = FIELD_EX64(wcr, DBGWCR, MASK); - if (mask == 1 || mask == 2) { - /* - * Reserved values of MASK; we must act as if the mask value was - * some non-reserved value, or as if the watchpoint were disabled. - * We choose the latter. - */ - return; - } else if (mask) { - /* Watchpoint covers an aligned area up to 2GB in size */ - len = 1ULL << mask; - /* - * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE - * whether the watchpoint fires when the unmasked bits match; we opt - * to generate the exceptions. - */ - wvr &= ~(len - 1); - } else { - /* Watchpoint covers bytes defined by the byte address select bits */ - int bas = FIELD_EX64(wcr, DBGWCR, BAS); - int basstart; - - if (extract64(wvr, 2, 1)) { - /* - * Deprecated case of an only 4-aligned address. BAS[7:4] are - * ignored, and BAS[3:0] define which bytes to watch. - */ - bas &= 0xf; - } - - if (bas == 0) { - /* This must act as if the watchpoint is disabled */ - return; - } - - /* - * The BAS bits are supposed to be programmed to indicate a contiguous - * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether - * we fire for each byte in the word/doubleword addressed by the WVR. - * We choose to ignore any non-zero bits after the first range of 1s. - */ - basstart = ctz32(bas); - len = cto32(bas >> basstart); - wvr += basstart; - } - - cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, - &env->cpu_watchpoint[n]); -} - -void hw_watchpoint_update_all(ARMCPU *cpu) -{ - int i; - CPUARMState *env = &cpu->env; - - /* - * Completely clear out existing QEMU watchpoints and our array, to - * avoid possible stale entries following migration load. - */ - cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); - memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); - - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { - hw_watchpoint_update(cpu, i); - } -} - -void hw_breakpoint_update(ARMCPU *cpu, int n) -{ - CPUARMState *env = &cpu->env; - uint64_t bvr = env->cp15.dbgbvr[n]; - uint64_t bcr = env->cp15.dbgbcr[n]; - vaddr addr; - int bt; - int flags = BP_CPU; - - if (env->cpu_breakpoint[n]) { - cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); - env->cpu_breakpoint[n] = NULL; - } - - if (!extract64(bcr, 0, 1)) { - /* E bit clear : watchpoint disabled */ - return; - } - - bt = extract64(bcr, 20, 4); - - switch (bt) { - case 4: /* unlinked address mismatch (reserved if AArch64) */ - case 5: /* linked address mismatch (reserved if AArch64) */ - qemu_log_mask(LOG_UNIMP, - "arm: address mismatch breakpoint types not implemented\n"); - return; - case 0: /* unlinked address match */ - case 1: /* linked address match */ - { - /* - * Bits [1:0] are RES0. - * - * It is IMPLEMENTATION DEFINED whether bits [63:49] - * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit - * of the VA field ([48] or [52] for FEAT_LVA), or whether the - * value is read as written. It is CONSTRAINED UNPREDICTABLE - * whether the RESS bits are ignored when comparing an address. - * Therefore we are allowed to compare the entire register, which - * lets us avoid considering whether FEAT_LVA is actually enabled. - * - * The BAS field is used to allow setting breakpoints on 16-bit - * wide instructions; it is CONSTRAINED UNPREDICTABLE whether - * a bp will fire if the addresses covered by the bp and the addresses - * covered by the insn overlap but the insn doesn't start at the - * start of the bp address range. We choose to require the insn and - * the bp to have the same address. The constraints on writing to - * BAS enforced in dbgbcr_write mean we have only four cases: - * 0b0000 => no breakpoint - * 0b0011 => breakpoint on addr - * 0b1100 => breakpoint on addr + 2 - * 0b1111 => breakpoint on addr - * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). - */ - int bas = extract64(bcr, 5, 4); - addr = bvr & ~3ULL; - if (bas == 0) { - return; - } - if (bas == 0xc) { - addr += 2; - } - break; - } - case 2: /* unlinked context ID match */ - case 8: /* unlinked VMID match (reserved if no EL2) */ - case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ - qemu_log_mask(LOG_UNIMP, - "arm: unlinked context breakpoint types not implemented\n"); - return; - case 9: /* linked VMID match (reserved if no EL2) */ - case 11: /* linked context ID and VMID match (reserved if no EL2) */ - case 3: /* linked context ID match */ - default: - /* - * We must generate no events for Linked context matches (unless - * they are linked to by some other bp/wp, which is handled in - * updates for the linking bp/wp). We choose to also generate no events - * for reserved values. - */ - return; - } - - cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); -} - -void hw_breakpoint_update_all(ARMCPU *cpu) -{ - int i; - CPUARMState *env = &cpu->env; - - /* - * Completely clear out existing QEMU breakpoints and our array, to - * avoid possible stale entries following migration load. - */ - cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); - memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); - - for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { - hw_breakpoint_update(cpu, i); - } -} - -#if !defined(CONFIG_USER_ONLY) - -vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - - /* - * In BE32 system mode, target memory is stored byteswapped (on a - * little-endian host system), and by the time we reach here (via an - * opcode helper) the addresses of subword accesses have been adjusted - * to account for that, which means that watchpoints will not match. - * Undo the adjustment here. - */ - if (arm_sctlr_b(env)) { - if (len == 1) { - addr ^= 3; - } else if (len == 2) { - addr ^= 2; - } - } - - return addr; -} - -#endif /* !CONFIG_USER_ONLY */ -#endif /* CONFIG_TCG */ - /* * Check for traps to "powerdown debug" registers, which are controlled * by MDCR.TDOSA diff --git a/target/arm/debug_helper.c b/target/arm/tcg/debug.c similarity index 53% copy from target/arm/debug_helper.c copy to target/arm/tcg/debug.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/tcg/debug.c @@ -XXX,XX +XXX,XX @@ /* - * ARM debug helpers. + * ARM debug helpers used by TCG * * This code is licensed under the GNU GPL v2 or later. * @@ -XXX,XX +XXX,XX @@ #define HELPER_H "tcg/helper.h" #include "exec/helper-proto.h.inc" -#ifdef CONFIG_TCG /* Return the Exception Level targeted by debug exceptions. */ static int arm_debug_target_el(CPUARMState *env) { @@ -XXX,XX +XXX,XX @@ static int arm_debug_target_el(CPUARMState *env) * Raise an exception to the debug target el. * Modify syndrome to indicate when origin and target EL are the same. */ -G_NORETURN static void +static G_NORETURN void raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome) { int debug_el = arm_debug_target_el(env); @@ -XXX,XX +XXX,XX @@ vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) } #endif /* !CONFIG_USER_ONLY */ -#endif /* CONFIG_TCG */ - -/* - * Check for traps to "powerdown debug" registers, which are controlled - * by MDCR.TDOSA - */ -static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); - bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tdosa) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* - * Check for traps to "debug ROM" registers, which are controlled - * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. - */ -static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); - bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tdra) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* - * Check for traps to general debug registers, which are controlled - * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. - */ -static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); - bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tda) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static CPAccessResult access_dbgvcr32(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - /* MCDR_EL3.TDMA doesn't apply for FEAT_NV traps */ - if (arm_current_el(env) == 2 && (env->cp15.mdcr_el3 & MDCR_TDA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* - * Check for traps to Debug Comms Channel registers. If FEAT_FGT - * is implemented then these are controlled by MDCR_EL2.TDCC for - * EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by - * the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA. - * For EL0, they are also controlled by MDSCR_EL1.TDCC. - */ -static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); - bool mdscr_el1_tdcc = extract32(env->cp15.mdscr_el1, 12, 1); - bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || - (arm_hcr_el2_eff(env) & HCR_TGE); - bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) && - (mdcr_el2 & MDCR_TDCC); - bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) && - (env->cp15.mdcr_el3 & MDCR_TDCC); - - if (el < 1 && mdscr_el1_tdcc) { - return CP_ACCESS_TRAP_EL1; - } - if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) { - return CP_ACCESS_TRAP_EL2; - } - if (!arm_is_el3_or_mon(env) && - ((env->cp15.mdcr_el3 & MDCR_TDA) || mdcr_el3_tdcc)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Writes to OSLAR_EL1 may update the OS lock status, which can be - * read via a bit in OSLSR_EL1. - */ - int oslock; - - if (ri->state == ARM_CP_STATE_AA32) { - oslock = (value == 0xC5ACCE55); - } else { - oslock = value & 1; - } - - env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock); -} - -static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = env_archcpu(env); - /* - * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not - * implemented this is RAZ/WI. - */ - if(arm_feature(env, ARM_FEATURE_AARCH64) - ? cpu_isar_feature(aa64_doublelock, cpu) - : cpu_isar_feature(aa32_doublelock, cpu)) { - env->cp15.osdlr_el1 = value & 1; - } -} - -static void dbgclaimset_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.dbgclaim |= (value & 0xFF); -} - -static uint64_t dbgclaimset_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* CLAIM bits are RAO */ - return 0xFF; -} - -static void dbgclaimclr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.dbgclaim &= ~(value & 0xFF); -} - -static CPAccessResult access_bogus(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - /* Always UNDEF, as if this cpreg didn't exist */ - return CP_ACCESS_UNDEFINED; -} - -static const ARMCPRegInfo debug_cp_reginfo[] = { - /* - * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped - * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; - * unlike DBGDRAR it is never accessible from EL0. - * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64 - * accessor. - */ - { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .accessfn = access_tdra, - .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 }, - { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64, - .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0, - .access = PL1_R, .accessfn = access_tdra, - .type = ARM_CP_CONST, .resetvalue = 0 }, - { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .accessfn = access_tdra, - .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 }, - /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */ - { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_MDSCR_EL1, - .nv2_redirect_offset = 0x158, - .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), - .resetvalue = 0 }, - /* - * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external - * Debug Communication Channel is not implemented. - */ - { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64, - .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0, - .access = PL0_R, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* - * These registers belong to the Debug Communications Channel, - * which is not implemented. However we implement RAZ/WI behaviour - * with trapping to prevent spurious SIGILLs if the guest OS does - * access them as the support cannot be probed for. - */ - { .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, - .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - { .name = "OSDTRTX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, - .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* Architecturally DBGDTRTX is named DBGDTRRX when used for reads */ - { .name = "DBGDTRTX_EL0", .state = ARM_CP_STATE_AA64, - .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0, - .access = PL0_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - { .name = "DBGDTRTX", .state = ARM_CP_STATE_AA32, .cp = 14, - .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, - .access = PL0_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* This is AArch64-only and is a combination of DBGDTRTX and DBGDTRRX */ - { .name = "DBGDTR_EL0", .state = ARM_CP_STATE_AA64, - .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 4, .opc2 = 0, - .access = PL0_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* - * This is not a real AArch32 register. We used to incorrectly expose - * this due to a QEMU bug; to avoid breaking migration compatibility we - * need to continue to provide it so that we don't fail the inbound - * migration when it tells us about a sysreg that we don't have. - * We set an always-fails .accessfn, which means that the guest doesn't - * actually see this register (it will always UNDEF, identically to if - * there were no cpreg definition for it other than that we won't print - * a LOG_UNIMP message about it), and we set the ARM_CP_NO_GDB flag so the - * gdbstub won't see it either. - * (We can't just set .access = 0, because add_cpreg_to_hashtable() - * helpfully ignores cpregs which aren't accessible to the highest - * implemented EL.) - * - * TODO: implement a system for being able to describe "this register - * can be ignored if it appears in the inbound stream"; then we can - * remove this temporary hack. - */ - { .name = "BOGUS_DBGDTR_EL0", .state = ARM_CP_STATE_AA32, - .cp = 14, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0, - .access = PL0_RW, .accessfn = access_bogus, - .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 }, - /* - * OSECCR_EL1 provides a mechanism for an operating system - * to access the contents of EDECCR. EDECCR is not implemented though, - * as is the rest of external device mechanism. - */ - { .name = "OSECCR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, - .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_OSECCR_EL1, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* - * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as - * it is unlikely a guest will care. - * We don't implement the configurable EL0 access. - */ - { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32, - .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, - .type = ARM_CP_ALIAS, - .access = PL1_R, .accessfn = access_tda, - .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), }, - { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4, - .access = PL1_W, .type = ARM_CP_NO_RAW, - .accessfn = access_tdosa, - .fgt = FGT_OSLAR_EL1, - .writefn = oslar_write }, - { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4, - .access = PL1_R, .resetvalue = 10, - .accessfn = access_tdosa, - .fgt = FGT_OSLSR_EL1, - .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) }, - /* Dummy OSDLR_EL1: 32-bit Linux will read this */ - { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, - .access = PL1_RW, .accessfn = access_tdosa, - .fgt = FGT_OSDLR_EL1, - .writefn = osdlr_write, - .fieldoffset = offsetof(CPUARMState, cp15.osdlr_el1) }, - /* - * Dummy DBGVCR: Linux wants to clear this on startup, but we don't - * implement vector catch debug events yet. - */ - { .name = "DBGVCR", - .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, - .access = PL1_RW, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* - * Dummy MDCCINT_EL1, since we don't implement the Debug Communications - * Channel but Linux may try to access this register. The 32-bit - * alias is DBGDCCINT. - */ - { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, - .access = PL1_RW, .accessfn = access_tdcc, - .type = ARM_CP_CONST, .resetvalue = 0 }, - /* - * Dummy DBGCLAIM registers. - * "The architecture does not define any functionality for the CLAIM tag bits.", - * so we only keep the raw bits - */ - { .name = "DBGCLAIMSET_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 6, - .type = ARM_CP_ALIAS, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGCLAIM, - .writefn = dbgclaimset_write, .readfn = dbgclaimset_read }, - { .name = "DBGCLAIMCLR_EL1", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 6, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGCLAIM, - .writefn = dbgclaimclr_write, .raw_writefn = raw_write, - .fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) }, -}; - -/* These are present only when EL1 supports AArch32 */ -static const ARMCPRegInfo debug_aa32_el1_reginfo[] = { - /* - * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor - * to save and restore a 32-bit guest's DBGVCR) - */ - { .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64, - .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0, - .access = PL2_RW, .accessfn = access_dbgvcr32, - .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP, - .resetvalue = 0 }, -}; - -static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { - /* 64 bit access versions of the (dummy) debug registers */ - { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0, - .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB, - .resetvalue = 0 }, - { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0, - .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB, - .resetvalue = 0 }, -}; - -static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = env_archcpu(env); - int i = ri->crm; - - /* - * Bits [1:0] are RES0. - * - * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) - * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if - * they contain the value written. It is CONSTRAINED UNPREDICTABLE - * whether the RESS bits are ignored when comparing an address. - * - * Therefore we are allowed to compare the entire register, which lets - * us avoid considering whether or not FEAT_LVA is actually enabled. - */ - value &= ~3ULL; - - raw_write(env, ri, value); - if (tcg_enabled()) { - hw_watchpoint_update(cpu, i); - } -} - -static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = env_archcpu(env); - int i = ri->crm; - - raw_write(env, ri, value); - if (tcg_enabled()) { - hw_watchpoint_update(cpu, i); - } -} - -static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = env_archcpu(env); - int i = ri->crm; - - raw_write(env, ri, value); - if (tcg_enabled()) { - hw_breakpoint_update(cpu, i); - } -} - -static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu = env_archcpu(env); - int i = ri->crm; - - /* - * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only - * copy of BAS[0]. - */ - value = deposit64(value, 6, 1, extract64(value, 5, 1)); - value = deposit64(value, 8, 1, extract64(value, 7, 1)); - - raw_write(env, ri, value); - if (tcg_enabled()) { - hw_breakpoint_update(cpu, i); - } -} - -void define_debug_regs(ARMCPU *cpu) -{ - /* - * Define v7 and v8 architectural debug registers. - * These are just dummy implementations for now. - */ - int i; - int wrps, brps, ctx_cmps; - - /* - * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot - * use AArch32. Given that bit 15 is RES1, if the value is 0 then - * the register must not exist for this cpu. - */ - if (cpu->isar.dbgdidr != 0) { - ARMCPRegInfo dbgdidr = { - .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, - .opc1 = 0, .opc2 = 0, - .access = PL0_R, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, - }; - define_one_arm_cp_reg(cpu, &dbgdidr); - } - - /* - * DBGDEVID is present in the v7 debug architecture if - * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is - * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist - * from v7.1 of the debug architecture. Because no fields have yet - * been defined in DBGDEVID2 (and quite possibly none will ever - * be) we don't define an ARMISARegisters field for it. - * These registers exist only if EL1 can use AArch32, but that - * happens naturally because they are only PL1 accessible anyway. - */ - if (extract32(cpu->isar.dbgdidr, 15, 1)) { - ARMCPRegInfo dbgdevid = { - .name = "DBGDEVID", - .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 2, .crn = 7, - .access = PL1_R, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid, - }; - define_one_arm_cp_reg(cpu, &dbgdevid); - } - if (cpu_isar_feature(aa32_debugv7p1, cpu)) { - ARMCPRegInfo dbgdevid12[] = { - { - .name = "DBGDEVID1", - .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 1, .crn = 7, - .access = PL1_R, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid1, - }, { - .name = "DBGDEVID2", - .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 0, .crn = 7, - .access = PL1_R, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = 0, - }, - }; - define_arm_cp_regs(cpu, dbgdevid12); - } - - brps = arm_num_brps(cpu); - wrps = arm_num_wrps(cpu); - ctx_cmps = arm_num_ctx_cmps(cpu); - - assert(ctx_cmps <= brps); - - define_arm_cp_regs(cpu, debug_cp_reginfo); - if (cpu_isar_feature(aa64_aa32_el1, cpu)) { - define_arm_cp_regs(cpu, debug_aa32_el1_reginfo); - } - - if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) { - define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); - } - - for (i = 0; i < brps; i++) { - char *dbgbvr_el1_name = g_strdup_printf("DBGBVR%d_EL1", i); - char *dbgbcr_el1_name = g_strdup_printf("DBGBCR%d_EL1", i); - ARMCPRegInfo dbgregs[] = { - { .name = dbgbvr_el1_name, .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGBVRN_EL1, - .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]), - .writefn = dbgbvr_write, .raw_writefn = raw_write - }, - { .name = dbgbcr_el1_name, .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGBCRN_EL1, - .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]), - .writefn = dbgbcr_write, .raw_writefn = raw_write - }, - }; - define_arm_cp_regs(cpu, dbgregs); - g_free(dbgbvr_el1_name); - g_free(dbgbcr_el1_name); - } - - for (i = 0; i < wrps; i++) { - char *dbgwvr_el1_name = g_strdup_printf("DBGWVR%d_EL1", i); - char *dbgwcr_el1_name = g_strdup_printf("DBGWCR%d_EL1", i); - ARMCPRegInfo dbgregs[] = { - { .name = dbgwvr_el1_name, .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGWVRN_EL1, - .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]), - .writefn = dbgwvr_write, .raw_writefn = raw_write - }, - { .name = dbgwcr_el1_name, .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7, - .access = PL1_RW, .accessfn = access_tda, - .fgt = FGT_DBGWCRN_EL1, - .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]), - .writefn = dbgwcr_write, .raw_writefn = raw_write - }, - }; - define_arm_cp_regs(cpu, dbgregs); - g_free(dbgwvr_el1_name); - g_free(dbgwcr_el1_name); - } -} diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -XXX,XX +XXX,XX @@ arm_common_ss.add(files( arm_common_system_ss.add(files( 'cpregs-at.c', + 'debug.c', 'hflags.c', 'neon_helper.c', 'tlb_helper.c', @@ -XXX,XX +XXX,XX @@ arm_common_system_ss.add(files( 'vfp_helper.c', )) arm_user_ss.add(files( + 'debug.c', 'hflags.c', 'neon_helper.c', 'tlb_helper.c', -- 2.43.0
In arm_cpu_do_interrupt_aarch64() we call the TCG helper function helper_rebuild_hflags_a64(), which requires helper.c to include the TCG helper function prototypes even when this file is being compiled with TCG disabled. We don't actually need to do this -- because we have already written the new EL into pstate and updated env->aarch64, we can call aarch64_rebuild_hflags() to achieve the same effect. This is the function we use everywhere else in this file to update hflags. Switch to aarch64_rebuild_hflags() and drop the include of the TCG helper headers. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-3-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -XXX,XX +XXX,XX @@ #include "target/arm/gtimer.h" #include "qemu/plugin.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - static void switch_mode(CPUARMState *env, int mode); int compare_u64(const void *a, const void *b) @@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) aarch64_restore_sp(env, new_el); if (tcg_enabled()) { - helper_rebuild_hflags_a64(env, new_el); + arm_rebuild_hflags(env); } env->pc = addr; -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> A few points to mention: - We mix helper prototypes and gen_helper definitions in a single header for convenience and to avoid headers boilerplate. - We rename existing tcg/helper-mve.h to helper-mve-defs.h to avoid conflict when including helper-mve.h. - We move mve helper_info definitions to tcg/mve_helper.c We'll repeat the same for other helpers. This allow to get rid of TARGET_AARCH64 in target/arm/helper.h. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-4-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper-mve.h | 14 ++++++++++++++ target/arm/helper.h | 2 -- target/arm/tcg/{helper-mve.h => helper-mve-defs.h} | 0 target/arm/tcg/mve_helper.c | 4 ++++ target/arm/tcg/translate-mve.c | 1 + target/arm/tcg/translate.c | 1 + 6 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 target/arm/helper-mve.h rename target/arm/tcg/{helper-mve.h => helper-mve-defs.h} (100%) diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/helper-mve.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef HELPER_MVE_H +#define HELPER_MVE_H + +#include "exec/helper-proto-common.h" +#include "exec/helper-gen-common.h" + +#define HELPER_H "tcg/helper-mve-defs.h" +#include "exec/helper-proto.h.inc" +#include "exec/helper-gen.h.inc" +#undef HELPER_H + +#endif /* HELPER_MVE_H */ diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ #include "tcg/helper-sve.h" #include "tcg/helper-sme.h" #endif - -#include "tcg/helper-mve.h" diff --git a/target/arm/tcg/helper-mve.h b/target/arm/tcg/helper-mve-defs.h similarity index 100% rename from target/arm/tcg/helper-mve.h rename to target/arm/tcg/helper-mve-defs.h diff --git a/target/arm/tcg/mve_helper.c b/target/arm/tcg/mve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/mve_helper.c +++ b/target/arm/tcg/mve_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper-mve.h" #include "internals.h" #include "vec_internal.h" #include "exec/helper-proto.h" @@ -XXX,XX +XXX,XX @@ #include "fpu/softfloat.h" #include "crypto/clmul.h" +#define HELPER_H "tcg/helper-mve-defs.h" +#include "exec/helper-info.c.inc" + static uint16_t mve_eci_mask(CPUARMState *env) { /* diff --git a/target/arm/tcg/translate-mve.c b/target/arm/tcg/translate-mve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-mve.c +++ b/target/arm/tcg/translate-mve.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "helper-mve.h" #include "translate.h" #include "translate-a32.h" diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -XXX,XX +XXX,XX @@ #include "cpregs.h" #include "exec/helper-proto.h" #include "exec/target_page.h" +#include "helper-mve.h" #define HELPER_H "helper.h" #include "exec/helper-info.c.inc" -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-5-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper-a64.h | 14 ++++++++++++++ target/arm/helper.h | 1 - target/arm/tcg/{helper-a64.h => helper-a64-defs.h} | 0 target/arm/tcg/helper-a64.c | 4 ++++ target/arm/tcg/mte_helper.c | 1 + target/arm/tcg/pauth_helper.c | 1 + target/arm/tcg/sve_helper.c | 1 + target/arm/tcg/translate-a64.c | 1 + target/arm/tcg/vec_helper.c | 1 + 9 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 target/arm/helper-a64.h rename target/arm/tcg/{helper-a64.h => helper-a64-defs.h} (100%) diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/helper-a64.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef HELPER_A64_H +#define HELPER_A64_H + +#include "exec/helper-proto-common.h" +#include "exec/helper-gen-common.h" + +#define HELPER_H "tcg/helper-a64-defs.h" +#include "exec/helper-proto.h.inc" +#include "exec/helper-gen.h.inc" +#undef HELPER_H + +#endif /* HELPER_A64_H */ diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ #include "tcg/helper.h" #ifdef TARGET_AARCH64 -#include "tcg/helper-a64.h" #include "tcg/helper-sve.h" #include "tcg/helper-sme.h" #endif diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64-defs.h similarity index 100% rename from target/arm/tcg/helper-a64.h rename to target/arm/tcg/helper-a64-defs.h diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "gdbstub/helpers.h" #include "exec/helper-proto.h" +#include "helper-a64.h" #include "qemu/host-utils.h" #include "qemu/log.h" #include "qemu/main-loop.h" @@ -XXX,XX +XXX,XX @@ #endif #include "vec_internal.h" +#define HELPER_H "tcg/helper-a64-defs.h" +#include "exec/helper-info.c.inc" + /* C2.4.7 Multiply and divide */ /* special cases for 0 and LLONG_MIN are mandated by the standard */ uint64_t HELPER(udiv64)(uint64_t num, uint64_t den) diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/mte_helper.c +++ b/target/arm/tcg/mte_helper.c @@ -XXX,XX +XXX,XX @@ #endif #include "accel/tcg/cpu-ldst.h" #include "accel/tcg/probe.h" +#include "helper-a64.h" #include "exec/helper-proto.h" #include "exec/tlb-flags.h" #include "accel/tcg/cpu-ops.h" diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/pauth_helper.c +++ b/target/arm/tcg/pauth_helper.c @@ -XXX,XX +XXX,XX @@ #include "internals.h" #include "cpu-features.h" #include "accel/tcg/cpu-ldst.h" +#include "helper-a64.h" #include "exec/helper-proto.h" #include "tcg/tcg-gvec-desc.h" #include "qemu/xxhash.h" diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ #include "exec/helper-proto.h" #include "exec/target_page.h" #include "exec/tlb-flags.h" +#include "helper-a64.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "tcg/tcg.h" diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" #include "exec/target_page.h" +#include "helper-a64.h" #include "translate.h" #include "translate-a64.h" #include "qemu/log.h" diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "helper-a64.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "qemu/int128.h" -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-6-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper-sve.h | 14 ++++++++++++++ target/arm/helper.h | 1 - target/arm/tcg/gengvec64.c | 3 ++- target/arm/tcg/{helper-sve.h => helper-sve-defs.h} | 0 target/arm/tcg/sve_helper.c | 3 +++ target/arm/tcg/translate-a64.c | 1 + target/arm/tcg/translate-sme.c | 2 ++ target/arm/tcg/translate-sve.c | 2 ++ target/arm/tcg/vec_helper.c | 1 + 9 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 target/arm/helper-sve.h rename target/arm/tcg/{helper-sve.h => helper-sve-defs.h} (100%) diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/helper-sve.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef HELPER_SVE_H +#define HELPER_SVE_H + +#include "exec/helper-proto-common.h" +#include "exec/helper-gen-common.h" + +#define HELPER_H "tcg/helper-sve-defs.h" +#include "exec/helper-proto.h.inc" +#include "exec/helper-gen.h.inc" +#undef HELPER_H + +#endif /* HELPER_SVE_H */ diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ #include "tcg/helper.h" #ifdef TARGET_AARCH64 -#include "tcg/helper-sve.h" #include "tcg/helper-sme.h" #endif diff --git a/target/arm/tcg/gengvec64.c b/target/arm/tcg/gengvec64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/gengvec64.c +++ b/target/arm/tcg/gengvec64.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "cpu.h" +#include "helper-sve.h" #include "translate.h" #include "translate-a64.h" - static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) { tcg_gen_rotli_i64(d, m, 1); diff --git a/target/arm/tcg/helper-sve.h b/target/arm/tcg/helper-sve-defs.h similarity index 100% rename from target/arm/tcg/helper-sve.h rename to target/arm/tcg/helper-sve-defs.h diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ #include "exec/target_page.h" #include "exec/tlb-flags.h" #include "helper-a64.h" +#include "helper-sve.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "tcg/tcg.h" @@ -XXX,XX +XXX,XX @@ #include "user/page-protection.h" #endif +#define HELPER_H "tcg/helper-sve-defs.h" +#include "exec/helper-info.c.inc" /* Return a value for NZCV as per the ARM PredTest pseudofunction. * diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "exec/target_page.h" #include "helper-a64.h" +#include "helper-sve.h" #include "translate.h" #include "translate-a64.h" #include "qemu/log.h" diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "cpu.h" +#include "helper-sve.h" #include "translate.h" #include "translate-a64.h" diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "cpu.h" +#include "helper-sve.h" #include "translate.h" #include "translate-a64.h" #include "fpu/softfloat.h" diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "exec/helper-proto.h" #include "helper-a64.h" +#include "helper-sve.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "qemu/int128.h" -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-7-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper-sme.h | 14 ++++++++++++++ target/arm/helper.h | 4 ---- target/arm/tcg/{helper-sme.h => helper-sme-defs.h} | 0 target/arm/tcg/sme_helper.c | 3 +++ target/arm/tcg/translate-a64.c | 1 + target/arm/tcg/translate-sme.c | 1 + target/arm/tcg/translate-sve.c | 1 + target/arm/tcg/vec_helper.c | 1 + 8 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 target/arm/helper-sme.h rename target/arm/tcg/{helper-sme.h => helper-sme-defs.h} (100%) diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/helper-sme.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef HELPER_SME_H +#define HELPER_SME_H + +#include "exec/helper-proto-common.h" +#include "exec/helper-gen-common.h" + +#define HELPER_H "tcg/helper-sme-defs.h" +#include "exec/helper-proto.h.inc" +#include "exec/helper-gen.h.inc" +#undef HELPER_H + +#endif /* HELPER_SME_H */ diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "tcg/helper.h" - -#ifdef TARGET_AARCH64 -#include "tcg/helper-sme.h" -#endif diff --git a/target/arm/tcg/helper-sme.h b/target/arm/tcg/helper-sme-defs.h similarity index 100% rename from target/arm/tcg/helper-sme.h rename to target/arm/tcg/helper-sme-defs.h diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sme_helper.c +++ b/target/arm/tcg/sme_helper.c @@ -XXX,XX +XXX,XX @@ #include "internals.h" #include "tcg/tcg-gvec-desc.h" #include "exec/helper-proto.h" +#include "helper-sme.h" #include "accel/tcg/cpu-ldst.h" #include "accel/tcg/helper-retaddr.h" #include "qemu/int128.h" @@ -XXX,XX +XXX,XX @@ #include "vec_internal.h" #include "sve_ldst_internal.h" +#define HELPER_H "tcg/helper-sme-defs.h" +#include "exec/helper-info.c.inc" static bool vectors_overlap(ARMVectorReg *x, unsigned nx, ARMVectorReg *y, unsigned ny) diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "exec/target_page.h" #include "helper-a64.h" +#include "helper-sme.h" #include "helper-sve.h" #include "translate.h" #include "translate-a64.h" diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper-sme.h" #include "helper-sve.h" #include "translate.h" #include "translate-a64.h" diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper-sme.h" #include "helper-sve.h" #include "translate.h" #include "translate-a64.h" diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "exec/helper-proto.h" #include "helper-a64.h" +#include "helper-sme.h" #include "helper-sve.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> In next commit, we'll apply same helper pattern for base helpers remaining. Our new helper pattern always include helper-*-common.h, which ends up including include/tcg/tcg.h, which contains one occurrence of CONFIG_USER_ONLY. Thus, common files not being duplicated between system and target relying on helpers will fail to compile. Existing occurrences are: - target/arm/tcg/arith_helper.c - target/arm/tcg/crypto_helper.c This occurrence of CONFIG_USER_ONLY is for defining variable tcg_use_softmmu, and we rely on dead code elimination with it in various tcg-target.c.inc. Thus, move its definition to tcg/tcg-internal.h, so helpers can be included by common files. Also, change it to a define, as it has fixed values for now. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-8-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/tcg/tcg.h | 6 ------ tcg/tcg-internal.h | 6 ++++++ tcg/tcg.c | 4 ---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index XXXXXXX..XXXXXXX 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -XXX,XX +XXX,XX @@ static inline bool temp_readonly(TCGTemp *ts) return ts->kind >= TEMP_FIXED; } -#ifdef CONFIG_USER_ONLY -extern bool tcg_use_softmmu; -#else -#define tcg_use_softmmu true -#endif - extern __thread TCGContext *tcg_ctx; extern const void *tcg_code_gen_epilogue; extern uintptr_t tcg_splitwx_diff; diff --git a/tcg/tcg-internal.h b/tcg/tcg-internal.h index XXXXXXX..XXXXXXX 100644 --- a/tcg/tcg-internal.h +++ b/tcg/tcg-internal.h @@ -XXX,XX +XXX,XX @@ extern TCGContext **tcg_ctxs; extern unsigned int tcg_cur_ctxs; extern unsigned int tcg_max_ctxs; +#ifdef CONFIG_USER_ONLY +#define tcg_use_softmmu false +#else +#define tcg_use_softmmu true +#endif + void tcg_region_init(size_t tb_size, int splitwx, unsigned max_threads); bool tcg_region_alloc(TCGContext *s); void tcg_region_initial_alloc(TCGContext *s); diff --git a/tcg/tcg.c b/tcg/tcg.c index XXXXXXX..XXXXXXX 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -XXX,XX +XXX,XX @@ static TCGAtomAlign atom_and_align_for_opc(TCGContext *s, MemOp opc, MemOp host_atom, bool allow_two_ops) __attribute__((unused)); -#ifdef CONFIG_USER_ONLY -bool tcg_use_softmmu; -#endif - TCGContext tcg_init_ctx; __thread TCGContext *tcg_ctx; -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Since we cleaned helper.h, we can continue further and remove all exec/helper-* inclusion. This way, all helpers use the same pattern, and helper include details are limited to those headers. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-9-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/helper.h | 13 ++++++++++++- target/arm/tcg/arith_helper.c | 4 +--- target/arm/tcg/crypto_helper.c | 4 +--- target/arm/tcg/debug.c | 4 +--- target/arm/tcg/helper-a64.c | 2 +- target/arm/tcg/{helper.h => helper-defs.h} | 0 target/arm/tcg/hflags.c | 4 +--- target/arm/tcg/m_helper.c | 2 +- target/arm/tcg/mte_helper.c | 2 +- target/arm/tcg/mve_helper.c | 2 +- target/arm/tcg/neon_helper.c | 4 +--- target/arm/tcg/op_helper.c | 2 +- target/arm/tcg/pauth_helper.c | 2 +- target/arm/tcg/psci.c | 2 +- target/arm/tcg/sme_helper.c | 2 +- target/arm/tcg/sve_helper.c | 2 +- target/arm/tcg/tlb_helper.c | 4 +--- target/arm/tcg/translate.c | 9 ++++----- target/arm/tcg/translate.h | 2 +- target/arm/tcg/vec_helper.c | 2 +- target/arm/tcg/vfp_helper.c | 4 +--- 21 files changed, 34 insertions(+), 38 deletions(-) rename target/arm/tcg/{helper.h => helper-defs.h} (100%) diff --git a/target/arm/helper.h b/target/arm/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -XXX,XX +XXX,XX @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "tcg/helper.h" +#ifndef HELPER__H +#define HELPER__H + +#include "exec/helper-proto-common.h" +#include "exec/helper-gen-common.h" + +#define HELPER_H "tcg/helper-defs.h" +#include "exec/helper-proto.h.inc" +#include "exec/helper-gen.h.inc" +#undef HELPER_H + +#endif /* HELPER__H */ diff --git a/target/arm/tcg/arith_helper.c b/target/arm/tcg/arith_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/arith_helper.c +++ b/target/arm/tcg/arith_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/bswap.h" #include "qemu/crc32c.h" +#include "helper.h" #include <zlib.h> /* for crc32 */ -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - /* * Note that signed overflow is undefined in C. The following routines are * careful to use unsigned types where modulo arithmetic is required. diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/crypto_helper.c +++ b/target/arm/tcg/crypto_helper.c @@ -XXX,XX +XXX,XX @@ #include "tcg/tcg-gvec-desc.h" #include "crypto/aes-round.h" #include "crypto/sm4.h" +#include "helper.h" #include "vec_internal.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - union CRYPTO_STATE { uint8_t bytes[16]; uint32_t words[4]; diff --git a/target/arm/tcg/debug.c b/target/arm/tcg/debug.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/debug.c +++ b/target/arm/tcg/debug.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "cpregs.h" #include "exec/watchpoint.h" #include "system/tcg.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - /* Return the Exception Level targeted by debug exceptions. */ static int arm_debug_target_el(CPUARMState *env) { diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -XXX,XX +XXX,XX @@ #include "qemu/units.h" #include "cpu.h" #include "gdbstub/helpers.h" -#include "exec/helper-proto.h" +#include "helper.h" #include "helper-a64.h" #include "qemu/host-utils.h" #include "qemu/log.h" diff --git a/target/arm/tcg/helper.h b/target/arm/tcg/helper-defs.h similarity index 100% rename from target/arm/tcg/helper.h rename to target/arm/tcg/helper-defs.h diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "exec/translation-block.h" #include "accel/tcg/cpu-ops.h" #include "cpregs.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - static inline bool fgt_svc(CPUARMState *env, int el) { /* diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/m_helper.c +++ b/target/arm/tcg/m_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "gdbstub/helpers.h" -#include "exec/helper-proto.h" #include "qemu/main-loop.h" #include "qemu/bitops.h" #include "qemu/log.h" diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/mte_helper.c +++ b/target/arm/tcg/mte_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "exec/target_page.h" #include "exec/page-protection.h" @@ -XXX,XX +XXX,XX @@ #include "accel/tcg/cpu-ldst.h" #include "accel/tcg/probe.h" #include "helper-a64.h" -#include "exec/helper-proto.h" #include "exec/tlb-flags.h" #include "accel/tcg/cpu-ops.h" #include "qapi/error.h" diff --git a/target/arm/tcg/mve_helper.c b/target/arm/tcg/mve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/mve_helper.c +++ b/target/arm/tcg/mve_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "helper-mve.h" #include "internals.h" #include "vec_internal.h" -#include "exec/helper-proto.h" #include "accel/tcg/cpu-ldst.h" #include "tcg/tcg.h" #include "fpu/softfloat.h" diff --git a/target/arm/tcg/neon_helper.c b/target/arm/tcg/neon_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/neon_helper.c +++ b/target/arm/tcg/neon_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "vec_internal.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" #include "cpu.h" -#include "exec/helper-proto.h" #include "exec/target_page.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "accel/tcg/cpu-ldst.h" diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/pauth_helper.c +++ b/target/arm/tcg/pauth_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "accel/tcg/cpu-ldst.h" #include "helper-a64.h" -#include "exec/helper-proto.h" #include "tcg/tcg-gvec-desc.h" #include "qemu/xxhash.h" diff --git a/target/arm/tcg/psci.c b/target/arm/tcg/psci.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/psci.c +++ b/target/arm/tcg/psci.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" -#include "exec/helper-proto.h" +#include "helper.h" #include "kvm-consts.h" #include "qemu/main-loop.h" #include "system/runstate.h" diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sme_helper.c +++ b/target/arm/tcg/sme_helper.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "internals.h" #include "tcg/tcg-gvec-desc.h" -#include "exec/helper-proto.h" +#include "helper.h" #include "helper-sme.h" #include "accel/tcg/cpu-ldst.h" #include "accel/tcg/helper-retaddr.h" diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "internals.h" #include "exec/page-protection.h" -#include "exec/helper-proto.h" #include "exec/target_page.h" #include "exec/tlb-flags.h" +#include "helper.h" #include "helper-a64.h" #include "helper-sve.h" #include "tcg/tcg-gvec-desc.h" diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - /* * Returns true if the stage 1 translation regime is using LPAE format page * tables. Used when raising alignment exceptions, whose FSR changes depending diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -XXX,XX +XXX,XX @@ #include "arm_ldst.h" #include "semihosting/semihost.h" #include "cpregs.h" -#include "exec/helper-proto.h" #include "exec/target_page.h" +#include "helper.h" #include "helper-mve.h" -#define HELPER_H "helper.h" -#include "exec/helper-info.c.inc" -#undef HELPER_H - #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T) #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5) /* currently all emulated v5 cores are also v5TE, so don't bother */ @@ -XXX,XX +XXX,XX @@ #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7) #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8) +#define HELPER_H "tcg/helper-defs.h" +#include "exec/helper-info.c.inc" + /* These are TCG globals which alias CPUARMState fields */ static TCGv_i32 cpu_R[16]; TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -XXX,XX +XXX,XX @@ #include "tcg/tcg-op-gvec.h" #include "exec/translator.h" #include "exec/translation-block.h" -#include "exec/helper-gen.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" -#include "exec/helper-proto.h" +#include "helper.h" #include "helper-a64.h" #include "helper-sme.h" #include "helper-sve.h" diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vfp_helper.c +++ b/target/arm/tcg/vfp_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" +#include "helper.h" #include "internals.h" #include "cpu-features.h" #include "fpu/softfloat.h" #include "qemu/log.h" -#define HELPER_H "tcg/helper.h" -#include "exec/helper-proto.h.inc" - /* * Set the float_status behaviour to match the Arm defaults: * * tininess-before-rounding -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Now that helper.h does not contain TARGET_AARCH64 identifier, we can move forward with this file. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-10-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/meson.build | 5 +---- target/arm/tcg/psci.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'sve_helper.c', )) -arm_system_ss.add(files( - 'psci.c', -)) - arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c')) arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c')) @@ -XXX,XX +XXX,XX @@ arm_common_system_ss.add(files( 'debug.c', 'hflags.c', 'neon_helper.c', + 'psci.c', 'tlb_helper.c', 'tlb-insns.c', 'vfp_helper.c', diff --git a/target/arm/tcg/psci.c b/target/arm/tcg/psci.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/psci.c +++ b/target/arm/tcg/psci.c @@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu) CPUARMState *env = &cpu->env; uint64_t param[4]; uint64_t context_id, mpidr; - target_ulong entry; + uint64_t entry; int32_t ret = 0; int i; -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-11-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'sve_helper.c', )) -arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c')) +arm_common_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c')) arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c')) arm_common_ss.add(zlib) -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> We need to extract 64 bits helper in a new file (vec_helper64.c), and extract some macro definition also, since they will be used in both files. As well, DO_3OP_PAIR was defined twice, so rename the second variant to DO_3OP_PAIR_NO_STATUS to reflect what it does. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-12-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/meson.build | 4 +- target/arm/tcg/vec_helper.c | 225 +++------------------------------- target/arm/tcg/vec_helper64.c | 142 +++++++++++++++++++++ target/arm/tcg/vec_internal.h | 49 ++++++++ 4 files changed, 212 insertions(+), 208 deletions(-) create mode 100644 target/arm/tcg/vec_helper64.c diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -XXX,XX +XXX,XX @@ arm_ss.add(files( 'm_helper.c', 'mve_helper.c', 'op_helper.c', - 'vec_helper.c', )) arm_ss.add(when: 'TARGET_AARCH64', if_true: files( @@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'pauth_helper.c', 'sme_helper.c', 'sve_helper.c', + 'vec_helper64.c', )) arm_common_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c')) @@ -XXX,XX +XXX,XX @@ arm_common_system_ss.add(files( 'psci.c', 'tlb_helper.c', 'tlb-insns.c', + 'vec_helper.c', 'vfp_helper.c', )) arm_user_ss.add(files( @@ -XXX,XX +XXX,XX @@ arm_user_ss.add(files( 'hflags.c', 'neon_helper.c', 'tlb_helper.c', + 'vec_helper.c', 'vfp_helper.c', )) diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" #include "helper.h" -#include "helper-a64.h" -#include "helper-sme.h" -#include "helper-sve.h" #include "tcg/tcg-gvec-desc.h" #include "fpu/softfloat.h" #include "qemu/int128.h" @@ -XXX,XX +XXX,XX @@ static float32 float32_rsqrts_nf(float32 op1, float32 op2, float_status *stat) return float32_div(op1, float32_two, stat); } -#define DO_3OP(NAME, FUNC, TYPE) \ -void HELPER(NAME)(void *vd, void *vn, void *vm, \ - float_status *stat, uint32_t desc) \ -{ \ - intptr_t i, oprsz = simd_oprsz(desc); \ - TYPE *d = vd, *n = vn, *m = vm; \ - for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ - d[i] = FUNC(n[i], m[i], stat); \ - } \ - clear_tail(d, oprsz, simd_maxsz(desc)); \ -} - DO_3OP(gvec_fadd_b16, bfloat16_add, float16) DO_3OP(gvec_fadd_h, float16_add, float16) DO_3OP(gvec_fadd_s, float32_add, float32) @@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32) DO_3OP(gvec_rsqrts_nf_h, float16_rsqrts_nf, float16) DO_3OP(gvec_rsqrts_nf_s, float32_rsqrts_nf, float32) -#ifdef TARGET_AARCH64 -DO_3OP(gvec_fdiv_h, float16_div, float16) -DO_3OP(gvec_fdiv_s, float32_div, float32) -DO_3OP(gvec_fdiv_d, float64_div, float64) - -DO_3OP(gvec_fmulx_h, helper_advsimd_mulxh, float16) -DO_3OP(gvec_fmulx_s, helper_vfp_mulxs, float32) -DO_3OP(gvec_fmulx_d, helper_vfp_mulxd, float64) - -DO_3OP(gvec_recps_h, helper_recpsf_f16, float16) -DO_3OP(gvec_recps_s, helper_recpsf_f32, float32) -DO_3OP(gvec_recps_d, helper_recpsf_f64, float64) - -DO_3OP(gvec_rsqrts_h, helper_rsqrtsf_f16, float16) -DO_3OP(gvec_rsqrts_s, helper_rsqrtsf_f32, float32) -DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64) - -DO_3OP(gvec_ah_recps_h, helper_recpsf_ah_f16, float16) -DO_3OP(gvec_ah_recps_s, helper_recpsf_ah_f32, float32) -DO_3OP(gvec_ah_recps_d, helper_recpsf_ah_f64, float64) - -DO_3OP(gvec_ah_rsqrts_h, helper_rsqrtsf_ah_f16, float16) -DO_3OP(gvec_ah_rsqrts_s, helper_rsqrtsf_ah_f32, float32) -DO_3OP(gvec_ah_rsqrts_d, helper_rsqrtsf_ah_f64, float64) - -DO_3OP(gvec_ah_fmax_h, helper_vfp_ah_maxh, float16) -DO_3OP(gvec_ah_fmax_s, helper_vfp_ah_maxs, float32) -DO_3OP(gvec_ah_fmax_d, helper_vfp_ah_maxd, float64) - -DO_3OP(gvec_ah_fmin_h, helper_vfp_ah_minh, float16) -DO_3OP(gvec_ah_fmin_s, helper_vfp_ah_mins, float32) -DO_3OP(gvec_ah_fmin_d, helper_vfp_ah_mind, float64) - -DO_3OP(gvec_fmax_b16, bfloat16_max, bfloat16) -DO_3OP(gvec_fmin_b16, bfloat16_min, bfloat16) -DO_3OP(gvec_fmaxnum_b16, bfloat16_maxnum, bfloat16) -DO_3OP(gvec_fminnum_b16, bfloat16_minnum, bfloat16) -DO_3OP(gvec_ah_fmax_b16, helper_sme2_ah_fmax_b16, bfloat16) -DO_3OP(gvec_ah_fmin_b16, helper_sme2_ah_fmin_b16, bfloat16) - -#endif -#undef DO_3OP - /* Non-fused multiply-add (unlike float16_muladd etc, which are fused) */ static float16 float16_muladd_nf(float16 dest, float16 op1, float16 op2, float_status *stat) @@ -XXX,XX +XXX,XX @@ DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, H8) #undef DO_MLA_IDX -#define DO_FMUL_IDX(NAME, ADD, MUL, TYPE, H) \ -void HELPER(NAME)(void *vd, void *vn, void *vm, \ - float_status *stat, uint32_t desc) \ -{ \ - intptr_t i, j, oprsz = simd_oprsz(desc); \ - intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ - intptr_t idx = simd_data(desc); \ - TYPE *d = vd, *n = vn, *m = vm; \ - for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ - TYPE mm = m[H(i + idx)]; \ - for (j = 0; j < segment; j++) { \ - d[i + j] = ADD(d[i + j], MUL(n[i + j], mm, stat), stat); \ - } \ - } \ - clear_tail(d, oprsz, simd_maxsz(desc)); \ -} - #define nop(N, M, S) (M) DO_FMUL_IDX(gvec_fmul_idx_b16, nop, bfloat16_mul, float16, H2) @@ -XXX,XX +XXX,XX @@ DO_FMUL_IDX(gvec_fmul_idx_h, nop, float16_mul, float16, H2) DO_FMUL_IDX(gvec_fmul_idx_s, nop, float32_mul, float32, H4) DO_FMUL_IDX(gvec_fmul_idx_d, nop, float64_mul, float64, H8) -#ifdef TARGET_AARCH64 - -DO_FMUL_IDX(gvec_fmulx_idx_h, nop, helper_advsimd_mulxh, float16, H2) -DO_FMUL_IDX(gvec_fmulx_idx_s, nop, helper_vfp_mulxs, float32, H4) -DO_FMUL_IDX(gvec_fmulx_idx_d, nop, helper_vfp_mulxd, float64, H8) - -#endif - #undef nop /* @@ -XXX,XX +XXX,XX @@ DO_FMUL_IDX(gvec_fmla_nf_idx_s, float32_add, float32_mul, float32, H4) DO_FMUL_IDX(gvec_fmls_nf_idx_h, float16_sub, float16_mul, float16, H2) DO_FMUL_IDX(gvec_fmls_nf_idx_s, float32_sub, float32_mul, float32, H4) -#undef DO_FMUL_IDX - #define DO_FMLA_IDX(NAME, TYPE, H, NEGX, NEGF) \ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \ float_status *stat, uint32_t desc) \ @@ -XXX,XX +XXX,XX @@ void HELPER(neon_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc) clear_tail(d, 16, simd_maxsz(desc)); } -#ifdef TARGET_AARCH64 -void HELPER(sve2_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc) -{ - int shift = simd_data(desc) * 8; - intptr_t i, opr_sz = simd_oprsz(desc); - uint64_t *d = vd, *n = vn, *m = vm; - - for (i = 0; i < opr_sz / 8; ++i) { - d[i] = clmul_8x4_even(n[i] >> shift, m[i] >> shift); - } -} - -void HELPER(sve2_pmull_d)(void *vd, void *vn, void *vm, uint32_t desc) -{ - intptr_t sel = H4(simd_data(desc)); - intptr_t i, opr_sz = simd_oprsz(desc); - uint32_t *n = vn, *m = vm; - uint64_t *d = vd; - - for (i = 0; i < opr_sz / 8; ++i) { - d[i] = clmul_32(n[2 * i + sel], m[2 * i + sel]); - } -} -#endif - #define DO_CMP0(NAME, TYPE, OP) \ void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \ { \ @@ -XXX,XX +XXX,XX @@ DO_ABA(gvec_uaba_d, uint64_t) #undef DO_ABA -#define DO_3OP_PAIR(NAME, FUNC, TYPE, H) \ -void HELPER(NAME)(void *vd, void *vn, void *vm, \ - float_status *stat, uint32_t desc) \ -{ \ - ARMVectorReg scratch; \ - intptr_t oprsz = simd_oprsz(desc); \ - intptr_t half = oprsz / sizeof(TYPE) / 2; \ - TYPE *d = vd, *n = vn, *m = vm; \ - if (unlikely(d == m)) { \ - m = memcpy(&scratch, m, oprsz); \ - } \ - for (intptr_t i = 0; i < half; ++i) { \ - d[H(i)] = FUNC(n[H(i * 2)], n[H(i * 2 + 1)], stat); \ - } \ - for (intptr_t i = 0; i < half; ++i) { \ - d[H(i + half)] = FUNC(m[H(i * 2)], m[H(i * 2 + 1)], stat); \ - } \ - clear_tail(d, oprsz, simd_maxsz(desc)); \ -} - DO_3OP_PAIR(gvec_faddp_h, float16_add, float16, H2) DO_3OP_PAIR(gvec_faddp_s, float32_add, float32, H4) DO_3OP_PAIR(gvec_faddp_d, float64_add, float64, ) @@ -XXX,XX +XXX,XX @@ DO_3OP_PAIR(gvec_fminnump_h, float16_minnum, float16, H2) DO_3OP_PAIR(gvec_fminnump_s, float32_minnum, float32, H4) DO_3OP_PAIR(gvec_fminnump_d, float64_minnum, float64, ) -#ifdef TARGET_AARCH64 -DO_3OP_PAIR(gvec_ah_fmaxp_h, helper_vfp_ah_maxh, float16, H2) -DO_3OP_PAIR(gvec_ah_fmaxp_s, helper_vfp_ah_maxs, float32, H4) -DO_3OP_PAIR(gvec_ah_fmaxp_d, helper_vfp_ah_maxd, float64, ) - -DO_3OP_PAIR(gvec_ah_fminp_h, helper_vfp_ah_minh, float16, H2) -DO_3OP_PAIR(gvec_ah_fminp_s, helper_vfp_ah_mins, float32, H4) -DO_3OP_PAIR(gvec_ah_fminp_d, helper_vfp_ah_mind, float64, ) -#endif - -#undef DO_3OP_PAIR - -#define DO_3OP_PAIR(NAME, FUNC, TYPE, H) \ +#define DO_3OP_PAIR_NO_STATUS(NAME, FUNC, TYPE, H) \ void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ { \ ARMVectorReg scratch; \ @@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ } #define ADD(A, B) (A + B) -DO_3OP_PAIR(gvec_addp_b, ADD, uint8_t, H1) -DO_3OP_PAIR(gvec_addp_h, ADD, uint16_t, H2) -DO_3OP_PAIR(gvec_addp_s, ADD, uint32_t, H4) -DO_3OP_PAIR(gvec_addp_d, ADD, uint64_t, ) +DO_3OP_PAIR_NO_STATUS(gvec_addp_b, ADD, uint8_t, H1) +DO_3OP_PAIR_NO_STATUS(gvec_addp_h, ADD, uint16_t, H2) +DO_3OP_PAIR_NO_STATUS(gvec_addp_s, ADD, uint32_t, H4) +DO_3OP_PAIR_NO_STATUS(gvec_addp_d, ADD, uint64_t, /**/) #undef ADD -DO_3OP_PAIR(gvec_smaxp_b, MAX, int8_t, H1) -DO_3OP_PAIR(gvec_smaxp_h, MAX, int16_t, H2) -DO_3OP_PAIR(gvec_smaxp_s, MAX, int32_t, H4) +DO_3OP_PAIR_NO_STATUS(gvec_smaxp_b, MAX, int8_t, H1) +DO_3OP_PAIR_NO_STATUS(gvec_smaxp_h, MAX, int16_t, H2) +DO_3OP_PAIR_NO_STATUS(gvec_smaxp_s, MAX, int32_t, H4) -DO_3OP_PAIR(gvec_umaxp_b, MAX, uint8_t, H1) -DO_3OP_PAIR(gvec_umaxp_h, MAX, uint16_t, H2) -DO_3OP_PAIR(gvec_umaxp_s, MAX, uint32_t, H4) +DO_3OP_PAIR_NO_STATUS(gvec_umaxp_b, MAX, uint8_t, H1) +DO_3OP_PAIR_NO_STATUS(gvec_umaxp_h, MAX, uint16_t, H2) +DO_3OP_PAIR_NO_STATUS(gvec_umaxp_s, MAX, uint32_t, H4) -DO_3OP_PAIR(gvec_sminp_b, MIN, int8_t, H1) -DO_3OP_PAIR(gvec_sminp_h, MIN, int16_t, H2) -DO_3OP_PAIR(gvec_sminp_s, MIN, int32_t, H4) +DO_3OP_PAIR_NO_STATUS(gvec_sminp_b, MIN, int8_t, H1) +DO_3OP_PAIR_NO_STATUS(gvec_sminp_h, MIN, int16_t, H2) +DO_3OP_PAIR_NO_STATUS(gvec_sminp_s, MIN, int32_t, H4) -DO_3OP_PAIR(gvec_uminp_b, MIN, uint8_t, H1) -DO_3OP_PAIR(gvec_uminp_h, MIN, uint16_t, H2) -DO_3OP_PAIR(gvec_uminp_s, MIN, uint32_t, H4) +DO_3OP_PAIR_NO_STATUS(gvec_uminp_b, MIN, uint8_t, H1) +DO_3OP_PAIR_NO_STATUS(gvec_uminp_h, MIN, uint16_t, H2) +DO_3OP_PAIR_NO_STATUS(gvec_uminp_s, MIN, uint32_t, H4) -#undef DO_3OP_PAIR +#undef DO_3OP_PAIR_NO_STATUS #define DO_VCVT_FIXED(NAME, FUNC, TYPE) \ void HELPER(NAME)(void *vd, void *vn, float_status *stat, uint32_t desc) \ @@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t) #undef DO_VRINT_RMODE -#ifdef TARGET_AARCH64 -void HELPER(simd_tblx)(void *vd, void *vm, CPUARMState *env, uint32_t desc) -{ - const uint8_t *indices = vm; - size_t oprsz = simd_oprsz(desc); - uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5); - bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1); - uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6); - union { - uint8_t b[16]; - uint64_t d[2]; - } result; - - /* - * We must construct the final result in a temp, lest the output - * overlaps the input table. For TBL, begin with zero; for TBX, - * begin with the original register contents. Note that we always - * copy 16 bytes here to avoid an extra branch; clearing the high - * bits of the register for oprsz == 8 is handled below. - */ - if (is_tbx) { - memcpy(&result, vd, 16); - } else { - memset(&result, 0, 16); - } - - for (size_t i = 0; i < oprsz; ++i) { - uint32_t index = indices[H1(i)]; - - if (index < table_len) { - /* - * Convert index (a byte offset into the virtual table - * which is a series of 128-bit vectors concatenated) - * into the correct register element, bearing in mind - * that the table can wrap around from V31 to V0. - */ - const uint8_t *table = (const uint8_t *) - aa64_vfp_qreg(env, (rn + (index >> 4)) % 32); - result.b[H1(i)] = table[H1(index % 16)]; - } - } - - memcpy(vd, &result, 16); - clear_tail(vd, oprsz, simd_maxsz(desc)); -} -#endif - /* * NxN -> N highpart multiply * diff --git a/target/arm/tcg/vec_helper64.c b/target/arm/tcg/vec_helper64.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/arm/tcg/vec_helper64.c @@ -XXX,XX +XXX,XX @@ +/* + * ARM AdvSIMD / SVE Vector Operations + * + * Copyright (c) 2026 Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "helper.h" +#include "helper-a64.h" +#include "helper-sme.h" +#include "helper-sve.h" +#include "tcg/tcg-gvec-desc.h" +#include "fpu/softfloat.h" +#include "qemu/int128.h" +#include "crypto/clmul.h" +#include "vec_internal.h" + +DO_3OP(gvec_fdiv_h, float16_div, float16) +DO_3OP(gvec_fdiv_s, float32_div, float32) +DO_3OP(gvec_fdiv_d, float64_div, float64) + +DO_3OP(gvec_fmulx_h, helper_advsimd_mulxh, float16) +DO_3OP(gvec_fmulx_s, helper_vfp_mulxs, float32) +DO_3OP(gvec_fmulx_d, helper_vfp_mulxd, float64) + +DO_3OP(gvec_recps_h, helper_recpsf_f16, float16) +DO_3OP(gvec_recps_s, helper_recpsf_f32, float32) +DO_3OP(gvec_recps_d, helper_recpsf_f64, float64) + +DO_3OP(gvec_rsqrts_h, helper_rsqrtsf_f16, float16) +DO_3OP(gvec_rsqrts_s, helper_rsqrtsf_f32, float32) +DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64) + +DO_3OP(gvec_ah_recps_h, helper_recpsf_ah_f16, float16) +DO_3OP(gvec_ah_recps_s, helper_recpsf_ah_f32, float32) +DO_3OP(gvec_ah_recps_d, helper_recpsf_ah_f64, float64) + +DO_3OP(gvec_ah_rsqrts_h, helper_rsqrtsf_ah_f16, float16) +DO_3OP(gvec_ah_rsqrts_s, helper_rsqrtsf_ah_f32, float32) +DO_3OP(gvec_ah_rsqrts_d, helper_rsqrtsf_ah_f64, float64) + +DO_3OP(gvec_ah_fmax_h, helper_vfp_ah_maxh, float16) +DO_3OP(gvec_ah_fmax_s, helper_vfp_ah_maxs, float32) +DO_3OP(gvec_ah_fmax_d, helper_vfp_ah_maxd, float64) + +DO_3OP(gvec_ah_fmin_h, helper_vfp_ah_minh, float16) +DO_3OP(gvec_ah_fmin_s, helper_vfp_ah_mins, float32) +DO_3OP(gvec_ah_fmin_d, helper_vfp_ah_mind, float64) + +DO_3OP(gvec_fmax_b16, bfloat16_max, bfloat16) +DO_3OP(gvec_fmin_b16, bfloat16_min, bfloat16) +DO_3OP(gvec_fmaxnum_b16, bfloat16_maxnum, bfloat16) +DO_3OP(gvec_fminnum_b16, bfloat16_minnum, bfloat16) +DO_3OP(gvec_ah_fmax_b16, helper_sme2_ah_fmax_b16, bfloat16) +DO_3OP(gvec_ah_fmin_b16, helper_sme2_ah_fmin_b16, bfloat16) + +#define nop(N, M, S) (M) + +DO_FMUL_IDX(gvec_fmulx_idx_h, nop, helper_advsimd_mulxh, float16, H2) +DO_FMUL_IDX(gvec_fmulx_idx_s, nop, helper_vfp_mulxs, float32, H4) +DO_FMUL_IDX(gvec_fmulx_idx_d, nop, helper_vfp_mulxd, float64, H8) + +#undef nop + +void HELPER(sve2_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc) +{ + int shift = simd_data(desc) * 8; + intptr_t i, opr_sz = simd_oprsz(desc); + uint64_t *d = vd, *n = vn, *m = vm; + + for (i = 0; i < opr_sz / 8; ++i) { + d[i] = clmul_8x4_even(n[i] >> shift, m[i] >> shift); + } +} + +void HELPER(sve2_pmull_d)(void *vd, void *vn, void *vm, uint32_t desc) +{ + intptr_t sel = H4(simd_data(desc)); + intptr_t i, opr_sz = simd_oprsz(desc); + uint32_t *n = vn, *m = vm; + uint64_t *d = vd; + + for (i = 0; i < opr_sz / 8; ++i) { + d[i] = clmul_32(n[2 * i + sel], m[2 * i + sel]); + } +} + +DO_3OP_PAIR(gvec_ah_fmaxp_h, helper_vfp_ah_maxh, float16, H2) +DO_3OP_PAIR(gvec_ah_fmaxp_s, helper_vfp_ah_maxs, float32, H4) +DO_3OP_PAIR(gvec_ah_fmaxp_d, helper_vfp_ah_maxd, float64, /**/) + +DO_3OP_PAIR(gvec_ah_fminp_h, helper_vfp_ah_minh, float16, H2) +DO_3OP_PAIR(gvec_ah_fminp_s, helper_vfp_ah_mins, float32, H4) +DO_3OP_PAIR(gvec_ah_fminp_d, helper_vfp_ah_mind, float64, /**/) + +void HELPER(simd_tblx)(void *vd, void *vm, CPUARMState *env, uint32_t desc) +{ + const uint8_t *indices = vm; + size_t oprsz = simd_oprsz(desc); + uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5); + bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1); + uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6); + union { + uint8_t b[16]; + uint64_t d[2]; + } result; + + /* + * We must construct the final result in a temp, lest the output + * overlaps the input table. For TBL, begin with zero; for TBX, + * begin with the original register contents. Note that we always + * copy 16 bytes here to avoid an extra branch; clearing the high + * bits of the register for oprsz == 8 is handled below. + */ + if (is_tbx) { + memcpy(&result, vd, 16); + } else { + memset(&result, 0, 16); + } + + for (size_t i = 0; i < oprsz; ++i) { + uint32_t index = indices[H1(i)]; + + if (index < table_len) { + /* + * Convert index (a byte offset into the virtual table + * which is a series of 128-bit vectors concatenated) + * into the correct register element, bearing in mind + * that the table can wrap around from V31 to V0. + */ + const uint8_t *table = (const uint8_t *) + aa64_vfp_qreg(env, (rn + (index >> 4)) % 32); + result.b[H1(i)] = table[H1(index % 16)]; + } + } + + memcpy(vd, &result, 16); + clear_tail(vd, oprsz, simd_maxsz(desc)); +} diff --git a/target/arm/tcg/vec_internal.h b/target/arm/tcg/vec_internal.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/vec_internal.h +++ b/target/arm/tcg/vec_internal.h @@ -XXX,XX +XXX,XX @@ static inline void depositn(uint64_t *p, unsigned pos, } } +#define DO_3OP(NAME, FUNC, TYPE) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, \ + float_status * stat, uint32_t desc) \ +{ \ + intptr_t i, oprsz = simd_oprsz(desc); \ + TYPE *d = vd, *n = vn, *m = vm; \ + for (i = 0; i < oprsz / sizeof(TYPE); i++) { \ + d[i] = FUNC(n[i], m[i], stat); \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +#define DO_3OP_PAIR(NAME, FUNC, TYPE, H) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, \ + float_status * stat, uint32_t desc) \ +{ \ + ARMVectorReg scratch; \ + intptr_t oprsz = simd_oprsz(desc); \ + intptr_t half = oprsz / sizeof(TYPE) / 2; \ + TYPE *d = vd, *n = vn, *m = vm; \ + if (unlikely(d == m)) { \ + m = memcpy(&scratch, m, oprsz); \ + } \ + for (intptr_t i = 0; i < half; ++i) { \ + d[H(i)] = FUNC(n[H(i * 2)], n[H(i * 2 + 1)], stat); \ + } \ + for (intptr_t i = 0; i < half; ++i) { \ + d[H(i + half)] = FUNC(m[H(i * 2)], m[H(i * 2 + 1)], stat); \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +#define DO_FMUL_IDX(NAME, ADD, MUL, TYPE, H) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, \ + float_status * stat, uint32_t desc) \ +{ \ + intptr_t i, j, oprsz = simd_oprsz(desc); \ + intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \ + intptr_t idx = simd_data(desc); \ + TYPE *d = vd, *n = vn, *m = vm; \ + for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \ + TYPE mm = m[H(i + idx)]; \ + for (j = 0; j < segment; j++) { \ + d[i + j] = ADD(d[i + j], MUL(n[i + j], mm, stat), stat); \ + } \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + #endif /* TARGET_ARM_VEC_INTERNAL_H */ -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-13-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/translate.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -XXX,XX +XXX,XX @@ */ typedef struct DisasLabel { TCGLabel *label; - target_ulong pc_save; + vaddr pc_save; } DisasLabel; /* @@ -XXX,XX +XXX,XX @@ typedef struct DisasContext { DisasDelayException *delay_excp_list; /* The address of the current instruction being translated. */ - target_ulong pc_curr; + vaddr pc_curr; /* * For CF_PCREL, the full value of cpu_pc is not known * (although the page offset is known). For convenience, the @@ -XXX,XX +XXX,XX @@ typedef struct DisasContext { * pc_save contains -1 to indicate that relative updates are no * longer possible. */ - target_ulong pc_save; - target_ulong page_start; + vaddr pc_save; + vaddr page_start; uint32_t insn; /* Nonzero if this instruction has been conditionally skipped. */ int condjmp; -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> target_long is used to represent a pc diff. Checked all call sites to make sure we were already passing signed values, so extending works as expected. Use vaddr for pc_curr and pc_save. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-14-pierrick.bouvier@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/tcg/translate-a32.h | 2 +- target/arm/tcg/translate.c | 18 +++++++++--------- target/arm/tcg/translate.h | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/target/arm/tcg/translate-a32.h b/target/arm/tcg/translate-a32.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate-a32.h +++ b/target/arm/tcg/translate-a32.h @@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop); TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs); void gen_set_cpsr(TCGv_i32 var, uint32_t mask); void gen_set_condexec(DisasContext *s); -void gen_update_pc(DisasContext *s, target_long diff); +void gen_update_pc(DisasContext *s, int64_t diff); void gen_lookup_tb(DisasContext *s); long vfp_reg_offset(bool dp, unsigned reg); long neon_full_reg_offset(unsigned reg); diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s) } /* The pc_curr difference for an architectural jump. */ -static target_long jmp_diff(DisasContext *s, target_long diff) +static int64_t jmp_diff(DisasContext *s, int64_t diff) { return diff + (s->thumb ? 4 : 8); } -static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff) +static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, int64_t diff) { assert(s->pc_save != -1); if (tb_cflags(s->base.tb) & CF_PCREL) { @@ -XXX,XX +XXX,XX @@ void gen_set_condexec(DisasContext *s) } } -void gen_update_pc(DisasContext *s, target_long diff) +void gen_update_pc(DisasContext *s, int64_t diff) { gen_pc_plus_diff(s, cpu_R[15], diff); s->pc_save = s->pc_curr + diff; @@ -XXX,XX +XXX,XX @@ static void gen_exception(int excp, uint32_t syndrome) tcg_constant_i32(syndrome)); } -static void gen_exception_insn_el_v(DisasContext *s, target_long pc_diff, +static void gen_exception_insn_el_v(DisasContext *s, int64_t pc_diff, int excp, uint32_t syn, TCGv_i32 tcg_el) { if (s->aarch64) { @@ -XXX,XX +XXX,XX @@ static void gen_exception_insn_el_v(DisasContext *s, target_long pc_diff, s->base.is_jmp = DISAS_NORETURN; } -void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp, +void gen_exception_insn_el(DisasContext *s, int64_t pc_diff, int excp, uint32_t syn, uint32_t target_el) { gen_exception_insn_el_v(s, pc_diff, excp, syn, tcg_constant_i32(target_el)); } -void gen_exception_insn(DisasContext *s, target_long pc_diff, +void gen_exception_insn(DisasContext *s, int64_t pc_diff, int excp, uint32_t syn) { if (s->aarch64) { @@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void) * cpu_loop_exec. Any live exit_requests will be processed as we * enter the next TB. */ -static void gen_goto_tb(DisasContext *s, unsigned tb_slot_idx, target_long diff) +static void gen_goto_tb(DisasContext *s, unsigned tb_slot_idx, int64_t diff) { if (translator_use_goto_tb(&s->base, s->pc_curr + diff)) { /* @@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, unsigned tb_slot_idx, target_long diff) } /* Jump, specifying which TB number to use if we gen_goto_tb() */ -static void gen_jmp_tb(DisasContext *s, target_long diff, int tbno) +static void gen_jmp_tb(DisasContext *s, int64_t diff, int tbno) { if (unlikely(s->ss_active)) { /* An indirect jump so that we still trigger the debug exception. */ @@ -XXX,XX +XXX,XX @@ static void gen_jmp_tb(DisasContext *s, target_long diff, int tbno) } } -static inline void gen_jmp(DisasContext *s, target_long diff) +static inline void gen_jmp(DisasContext *s, int64_t diff) { gen_jmp_tb(s, diff, 0); } diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -XXX,XX +XXX,XX @@ typedef struct DisasLabel { typedef struct DisasDelayException { struct DisasDelayException *next; TCGLabel *lab; - target_long pc_curr; - target_long pc_save; + vaddr pc_curr; + vaddr pc_save; int condexec_mask; int condexec_cond; uint32_t excp; @@ -XXX,XX +XXX,XX @@ static inline int curr_insn_len(DisasContext *s) #ifdef TARGET_AARCH64 void a64_translate_init(void); -void gen_a64_update_pc(DisasContext *s, target_long diff); +void gen_a64_update_pc(DisasContext *s, int64_t diff); extern const TranslatorOps aarch64_translator_ops; #else static inline void a64_translate_init(void) { } -static inline void gen_a64_update_pc(DisasContext *s, target_long diff) +static inline void gen_a64_update_pc(DisasContext *s, int64_t diff) { } #endif @@ -XXX,XX +XXX,XX @@ void arm_gen_test_cc(int cc, TCGLabel *label); MemOp pow2_align(unsigned i); void unallocated_encoding(DisasContext *s); void gen_exception_internal(int excp); -void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp, +void gen_exception_insn_el(DisasContext *s, int64_t pc_diff, int excp, uint32_t syn, uint32_t target_el); -void gen_exception_insn(DisasContext *s, target_long pc_diff, +void gen_exception_insn(DisasContext *s, int64_t pc_diff, int excp, uint32_t syn); TCGLabel *delay_exception_el(DisasContext *s, int excp, uint32_t syn, uint32_t target_el); -- 2.43.0
From: Pierrick Bouvier <pierrick.bouvier@linaro.org> This commit removes TARGET_INSN_START_EXTRA_WORDS and force all arch to call the same version of tcg_gen_insn_start, with additional 0 arguments if needed. Since all arch have a single call site (in translate.c), this is as good documentation as having a single define. The notable exception is target/arm, which has two different translate files for 32/64 bits. Since it's the only one, we accept to have two call sites for this. As well, we update parameter type to use uint64_t instead of target_ulong, so it can be called from common code. Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-id: 20260219040150.2098396-15-pierrick.bouvier@linaro.org Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/tcg/tcg-op-common.h | 8 ++++++++ include/tcg/tcg-op.h | 29 ----------------------------- target/alpha/cpu-param.h | 2 -- target/alpha/translate.c | 4 ++-- target/arm/cpu-param.h | 7 ------- target/avr/cpu-param.h | 2 -- target/avr/translate.c | 2 +- target/hexagon/cpu-param.h | 2 -- target/hexagon/translate.c | 2 +- target/hppa/cpu-param.h | 2 -- target/i386/cpu-param.h | 2 -- target/i386/tcg/translate.c | 2 +- target/loongarch/cpu-param.h | 2 -- target/loongarch/tcg/translate.c | 2 +- target/m68k/cpu-param.h | 2 -- target/m68k/translate.c | 2 +- target/microblaze/cpu-param.h | 2 -- target/microblaze/translate.c | 2 +- target/mips/cpu-param.h | 2 -- target/or1k/cpu-param.h | 2 -- target/or1k/translate.c | 2 +- target/ppc/cpu-param.h | 2 -- target/ppc/translate.c | 2 +- target/riscv/cpu-param.h | 7 ------- target/rx/cpu-param.h | 2 -- target/rx/translate.c | 2 +- target/s390x/cpu-param.h | 2 -- target/sh4/cpu-param.h | 2 -- target/sh4/translate.c | 4 ++-- target/sparc/cpu-param.h | 2 -- target/sparc/translate.c | 2 +- target/tricore/cpu-param.h | 2 -- target/tricore/translate.c | 2 +- target/xtensa/cpu-param.h | 2 -- target/xtensa/translate.c | 2 +- 35 files changed, 24 insertions(+), 93 deletions(-) diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h index XXXXXXX..XXXXXXX 100644 --- a/include/tcg/tcg-op-common.h +++ b/include/tcg/tcg-op-common.h @@ -XXX,XX +XXX,XX @@ TCGv_i64 tcg_global_mem_new_i64(TCGv_ptr reg, intptr_t off, const char *name); TCGv_ptr tcg_global_mem_new_ptr(TCGv_ptr reg, intptr_t off, const char *name); /* Generic ops. */ +static inline void tcg_gen_insn_start(uint64_t pc, uint64_t a1, + uint64_t a2) +{ + TCGOp *op = tcg_emit_op(INDEX_op_insn_start, INSN_START_WORDS); + tcg_set_insn_start_param(op, 0, pc); + tcg_set_insn_start_param(op, 1, a1); + tcg_set_insn_start_param(op, 2, a2); +} void gen_set_label(TCGLabel *l); void tcg_gen_br(TCGLabel *l); diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index XXXXXXX..XXXXXXX 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -XXX,XX +XXX,XX @@ # error Mismatch with insn-start-words.h #endif -#if TARGET_INSN_START_EXTRA_WORDS == 0 -static inline void tcg_gen_insn_start(target_ulong pc) -{ - TCGOp *op = tcg_emit_op(INDEX_op_insn_start, INSN_START_WORDS); - tcg_set_insn_start_param(op, 0, pc); - tcg_set_insn_start_param(op, 1, 0); - tcg_set_insn_start_param(op, 2, 0); -} -#elif TARGET_INSN_START_EXTRA_WORDS == 1 -static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1) -{ - TCGOp *op = tcg_emit_op(INDEX_op_insn_start, INSN_START_WORDS); - tcg_set_insn_start_param(op, 0, pc); - tcg_set_insn_start_param(op, 1, a1); - tcg_set_insn_start_param(op, 2, 0); -} -#elif TARGET_INSN_START_EXTRA_WORDS == 2 -static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1, - target_ulong a2) -{ - TCGOp *op = tcg_emit_op(INDEX_op_insn_start, INSN_START_WORDS); - tcg_set_insn_start_param(op, 0, pc); - tcg_set_insn_start_param(op, 1, a1); - tcg_set_insn_start_param(op, 2, a2); -} -#else -#error Unhandled TARGET_INSN_START_EXTRA_WORDS value -#endif - #if TARGET_LONG_BITS == 32 typedef TCGv_i32 TCGv; #define tcg_temp_new() tcg_temp_new_i32() diff --git a/target/alpha/cpu-param.h b/target/alpha/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/alpha/cpu-param.h +++ b/target/alpha/cpu-param.h @@ -XXX,XX +XXX,XX @@ # define TARGET_VIRT_ADDR_SPACE_BITS (30 + TARGET_PAGE_BITS) #endif -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/alpha/translate.c b/target/alpha/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -XXX,XX +XXX,XX @@ static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) DisasContext *ctx = container_of(dcbase, DisasContext, base); if (ctx->pcrel) { - tcg_gen_insn_start(dcbase->pc_next & ~TARGET_PAGE_MASK); + tcg_gen_insn_start(dcbase->pc_next & ~TARGET_PAGE_MASK, 0, 0); } else { - tcg_gen_insn_start(dcbase->pc_next); + tcg_gen_insn_start(dcbase->pc_next, 0, 0); } } diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/arm/cpu-param.h +++ b/target/arm/cpu-param.h @@ -XXX,XX +XXX,XX @@ # define TARGET_PAGE_BITS_LEGACY 10 #endif /* !CONFIG_USER_ONLY */ -/* - * ARM-specific extra insn start words: - * 1: Conditional execution bits - * 2: Partial exception syndrome for data aborts - */ -#define TARGET_INSN_START_EXTRA_WORDS 2 - #endif diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/avr/cpu-param.h +++ b/target/avr/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 24 #define TARGET_VIRT_ADDR_SPACE_BITS 24 -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/avr/translate.c b/target/avr/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -XXX,XX +XXX,XX @@ static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->npc); + tcg_gen_insn_start(ctx->npc, 0, 0); } static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/hexagon/cpu-param.h b/target/hexagon/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/hexagon/cpu-param.h +++ b/target/hexagon/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 36 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -XXX,XX +XXX,XX @@ static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->base.pc_next); + tcg_gen_insn_start(ctx->base.pc_next, 0, 0); } static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx) diff --git a/target/hppa/cpu-param.h b/target/hppa/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/hppa/cpu-param.h +++ b/target/hppa/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PAGE_BITS 12 -#define TARGET_INSN_START_EXTRA_WORDS 2 - #endif diff --git a/target/i386/cpu-param.h b/target/i386/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/i386/cpu-param.h +++ b/target/i386/cpu-param.h @@ -XXX,XX +XXX,XX @@ #endif #define TARGET_PAGE_BITS 12 -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) if (tb_cflags(dcbase->tb) & CF_PCREL) { pc_arg &= ~TARGET_PAGE_MASK; } - tcg_gen_insn_start(pc_arg, dc->cc_op); + tcg_gen_insn_start(pc_arg, dc->cc_op, 0); } static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-param.h +++ b/target/loongarch/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PAGE_BITS 12 -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/loongarch/tcg/translate.c b/target/loongarch/tcg/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/translate.c +++ b/target/loongarch/tcg/translate.c @@ -XXX,XX +XXX,XX @@ static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->base.pc_next); + tcg_gen_insn_start(ctx->base.pc_next, 0, 0); } /* diff --git a/target/m68k/cpu-param.h b/target/m68k/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/m68k/cpu-param.h +++ b/target/m68k/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/m68k/translate.c b/target/m68k/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -XXX,XX +XXX,XX @@ static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu) static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); + tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 0); } static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) diff --git a/target/microblaze/cpu-param.h b/target/microblaze/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/microblaze/cpu-param.h +++ b/target/microblaze/cpu-param.h @@ -XXX,XX +XXX,XX @@ /* FIXME: MB uses variable pages down to 1K but linux only uses 4k. */ #define TARGET_PAGE_BITS 12 -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -XXX,XX +XXX,XX @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs) { DisasContext *dc = container_of(dcb, DisasContext, base); - tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK); + tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK, 0); } static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) diff --git a/target/mips/cpu-param.h b/target/mips/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/mips/cpu-param.h +++ b/target/mips/cpu-param.h @@ -XXX,XX +XXX,XX @@ #endif #define TARGET_PAGE_BITS 12 -#define TARGET_INSN_START_EXTRA_WORDS 2 - #endif diff --git a/target/or1k/cpu-param.h b/target/or1k/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/or1k/cpu-param.h +++ b/target/or1k/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/or1k/translate.c b/target/or1k/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/or1k/translate.c +++ b/target/or1k/translate.c @@ -XXX,XX +XXX,XX @@ static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) DisasContext *dc = container_of(dcbase, DisasContext, base); tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) - | (dc->base.num_insns > 1 ? 2 : 0)); + | (dc->base.num_insns > 1 ? 2 : 0), 0); } static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/ppc/cpu-param.h b/target/ppc/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/cpu-param.h +++ b/target/ppc/cpu-param.h @@ -XXX,XX +XXX,XX @@ # define TARGET_PAGE_BITS 12 #endif -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/ppc/translate.c b/target/ppc/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -XXX,XX +XXX,XX @@ static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs) static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) { - tcg_gen_insn_start(dcbase->pc_next); + tcg_gen_insn_start(dcbase->pc_next, 0, 0); } static bool is_prefix_insn(DisasContext *ctx, uint32_t insn) diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu-param.h +++ b/target/riscv/cpu-param.h @@ -XXX,XX +XXX,XX @@ #endif #define TARGET_PAGE_BITS 12 /* 4 KiB Pages */ -/* - * RISC-V-specific extra insn start words: - * 1: Original instruction opcode - * 2: more information about instruction - */ -#define TARGET_INSN_START_EXTRA_WORDS 2 - /* * The current MMU Modes are: * - U mode 0b000 diff --git a/target/rx/cpu-param.h b/target/rx/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/rx/cpu-param.h +++ b/target/rx/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/rx/translate.c b/target/rx/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/rx/translate.c +++ b/target/rx/translate.c @@ -XXX,XX +XXX,XX @@ static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->base.pc_next); + tcg_gen_insn_start(ctx->base.pc_next, 0, 0); } static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/s390x/cpu-param.h b/target/s390x/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/s390x/cpu-param.h +++ b/target/s390x/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 64 #define TARGET_VIRT_ADDR_SPACE_BITS 64 -#define TARGET_INSN_START_EXTRA_WORDS 2 - #endif diff --git a/target/sh4/cpu-param.h b/target/sh4/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/sh4/cpu-param.h +++ b/target/sh4/cpu-param.h @@ -XXX,XX +XXX,XX @@ # define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/sh4/translate.c b/target/sh4/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -XXX,XX +XXX,XX @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env) * tb->icount * insn_start. */ for (i = 1; i < max_insns; ++i) { - tcg_gen_insn_start(pc + i * 2, ctx->envflags); + tcg_gen_insn_start(pc + i * 2, ctx->envflags, 0); ctx->base.insn_start = tcg_last_op(); } } @@ -XXX,XX +XXX,XX @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); + tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags, 0); } static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/sparc/cpu-param.h b/target/sparc/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/sparc/cpu-param.h +++ b/target/sparc/cpu-param.h @@ -XXX,XX +XXX,XX @@ # define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif -#define TARGET_INSN_START_EXTRA_WORDS 1 - #endif diff --git a/target/sparc/translate.c b/target/sparc/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -XXX,XX +XXX,XX @@ static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) g_assert_not_reached(); } } - tcg_gen_insn_start(dc->pc, npc); + tcg_gen_insn_start(dc->pc, npc, 0); } static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/tricore/cpu-param.h b/target/tricore/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/tricore/cpu-param.h +++ b/target/tricore/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_PHYS_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/tricore/translate.c b/target/tricore/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -XXX,XX +XXX,XX @@ static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - tcg_gen_insn_start(ctx->base.pc_next); + tcg_gen_insn_start(ctx->base.pc_next, 0, 0); } static bool insn_crosses_page(DisasContext *ctx, CPUTriCoreState *env) diff --git a/target/xtensa/cpu-param.h b/target/xtensa/cpu-param.h index XXXXXXX..XXXXXXX 100644 --- a/target/xtensa/cpu-param.h +++ b/target/xtensa/cpu-param.h @@ -XXX,XX +XXX,XX @@ #define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif -#define TARGET_INSN_START_EXTRA_WORDS 0 - #endif diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -XXX,XX +XXX,XX @@ static void xtensa_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu) static void xtensa_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) { - tcg_gen_insn_start(dcbase->pc_next); + tcg_gen_insn_start(dcbase->pc_next, 0, 0); } static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) -- 2.43.0
v3->v4: Windows headers define an INT type which clashed with an enum value name in arm_gicv3_its.c... The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5: Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100) are available in the Git repository at: https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913-3 for you to fetch changes up to 28e987a7e7edaa3ca7feeac65edca26145df8814: hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 21:01:08 +0100) ---------------------------------------------------------------- target-arm queue: * mark MPS2/MPS3 board-internal i2c buses as 'full' so that command line user-created devices are not plugged into them * Take an exception if PSTATE.IL is set * Support an emulated ITS in the virt board * Add support for kudo-bmc board * Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM * cadence_uart: Fix clock handling issues that prevented u-boot from running ---------------------------------------------------------------- Bin Meng (6): hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase hw/char: cadence_uart: Disable transmit when input clock is disabled hw/char: cadence_uart: Move clock/reset check to uart_can_receive() hw/char: cadence_uart: Convert to memop_with_attrs() ops hw/char: cadence_uart: Ignore access when unclocked or in reset for uart_{read, write}() hw/char: cadence_uart: Log a guest error when device is unclocked or in reset Chris Rauer (1): hw/arm: Add support for kudo-bmc board. Marc Zyngier (1): hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM Peter Maydell (5): target/arm: Take an exception if PSTATE.IL is set qdev: Support marking individual buses as 'full' hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full' hw/arm/mps2.c: Mark internal-only I2C buses as 'full' Richard Henderson (1): target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn Shashi Mallela (9): hw/intc: GICv3 ITS initial framework hw/intc: GICv3 ITS register definitions added hw/intc: GICv3 ITS command queue framework hw/intc: GICv3 ITS Command processing hw/intc: GICv3 ITS Feature enablement hw/intc: GICv3 redistributor ITS processing tests/data/acpi/virt: Add IORT files for ITS hw/arm/virt: add ITS support in virt GIC tests/data/acpi/virt: Update IORT files for ITS docs/system/arm/nuvoton.rst | 1 + hw/intc/gicv3_internal.h | 188 ++++- include/hw/arm/virt.h | 2 + include/hw/intc/arm_gicv3_common.h | 13 + include/hw/intc/arm_gicv3_its_common.h | 32 +- include/hw/qdev-core.h | 24 + target/arm/cpu.h | 1 + target/arm/kvm_arm.h | 4 +- target/arm/syndrome.h | 5 + target/arm/translate.h | 2 + hw/arm/mps2-tz.c | 92 ++- hw/arm/mps2.c | 12 +- hw/arm/npcm7xx_boards.c | 34 + hw/arm/virt.c | 29 +- hw/char/cadence_uart.c | 61 +- hw/intc/arm_gicv3.c | 14 + hw/intc/arm_gicv3_common.c | 13 + hw/intc/arm_gicv3_cpuif.c | 7 +- hw/intc/arm_gicv3_dist.c | 5 +- hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++ hw/intc/arm_gicv3_its_common.c | 7 +- hw/intc/arm_gicv3_its_kvm.c | 2 +- hw/intc/arm_gicv3_redist.c | 153 +++- hw/misc/zynq_slcr.c | 31 +- softmmu/qdev-monitor.c | 7 +- target/arm/helper-a64.c | 1 + target/arm/helper.c | 8 + target/arm/kvm.c | 7 +- target/arm/translate-a64.c | 255 +++--- target/arm/translate.c | 21 + hw/intc/meson.build | 1 + tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes 35 files changed, 2144 insertions(+), 210 deletions(-) create mode 100644 hw/intc/arm_gicv3_its.c create mode 100644 tests/data/acpi/virt/IORT create mode 100644 tests/data/acpi/virt/IORT.memhp create mode 100644 tests/data/acpi/virt/IORT.numamem create mode 100644 tests/data/acpi/virt/IORT.pxb