aboutsummaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-08-16 14:35:50 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-16 14:35:50 +0100
commitbb16c0412a572c2c9cd44496deb3ad430bc49c1a (patch)
treecb87c31c5440a9128cf7762407237b5b57fbed33 /target/arm
parentc542a9f9794ec8e0bc3fcf5956d3cc8bce667789 (diff)
parentfcf13ca556f462b52956059bf8fa622bc8575edb (diff)
downloadqemu-bb16c0412a572c2c9cd44496deb3ad430bc49c1a.zip
qemu-bb16c0412a572c2c9cd44496deb3ad430bc49c1a.tar.gz
qemu-bb16c0412a572c2c9cd44496deb3ad430bc49c1a.tar.bz2
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180816' into staging
target-arm queue: * Fixes for various bugs in SVE instructions * Add model of Freescale i.MX6 UltraLite 14x14 EVK Board * hw/arm: make bitbanded IO optional on ARMv7-M * Add model of Cortex-M0 CPU * Add support for loading Intel HEX files to the generic loader * imx_spi: Unset XCH when TX FIFO becomes empty * aspeed_sdmc: fix various bugs * Fix bugs in Arm FP16 instruction support * Fix aa64 FCADD and FCMLA decode * softfloat: Fix missing inexact for floating-point add * hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj() # gpg: Signature made Thu 16 Aug 2018 14:33:41 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180816: (30 commits) hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj() softfloat: Fix missing inexact for floating-point add target/arm: Fix aa64 FCADD and FCMLA decode target/arm: Use FZ not FZ16 for SVE FCVT single-half and double-half target/arm: Use fp_status_fp16 for do_fmpa_zpzzz_h target/arm: Ignore float_flag_input_denormal from fp_status_f16 target/arm: Adjust FPCR_MASK for FZ16 aspeed: add a max_ram_size property to the memory controller aspeed_sdmc: Handle ECC training aspeed_sdmc: Init status always idle aspeed_sdmc: Set 'cache initial sequence' always true aspeed_sdmc: Fix saved values aspeed_sdmc: Extend number of valid registers imx_spi: Unset XCH when TX FIFO becomes empty Add QTest testcase for the Intel Hexadecimal loader: Implement .hex file loader loader: add rom transaction API loader: extract rom_free() function target/arm: add "cortex-m0" CPU model hw/arm: make bitbanded IO optional on ARMv7-M ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/cpu.c17
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/cpu64.c29
-rw-r--r--target/arm/helper.c18
-rw-r--r--target/arm/sve_helper.c4
-rw-r--r--target/arm/translate-a64.c118
-rw-r--r--target/arm/translate-sve.c30
7 files changed, 172 insertions, 49 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3848ef4..258ba6d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -168,9 +168,9 @@ static void arm_cpu_reset(CPUState *s)
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
env->cp15.cptr_el[3] |= CPTR_EZ;
/* with maximum vector length */
- env->vfp.zcr_el[1] = ARM_MAX_VQ - 1;
- env->vfp.zcr_el[2] = ARM_MAX_VQ - 1;
- env->vfp.zcr_el[3] = ARM_MAX_VQ - 1;
+ env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
+ env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
+ env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
#else
/* Reset into the highest available EL */
if (arm_feature(env, ARM_FEATURE_EL3)) {
@@ -1255,6 +1255,15 @@ static void arm11mpcore_initfn(Object *obj)
cpu->reset_auxcr = 1;
}
+static void cortex_m0_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ set_feature(&cpu->env, ARM_FEATURE_V6);
+ set_feature(&cpu->env, ARM_FEATURE_M);
+
+ cpu->midr = 0x410cc200;
+}
+
static void cortex_m3_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -1845,6 +1854,8 @@ static const ARMCPUInfo arm_cpus[] = {
{ .name = "arm1136", .initfn = arm1136_initfn },
{ .name = "arm1176", .initfn = arm1176_initfn },
{ .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
+ .class_init = arm_v7m_class_init },
{ .name = "cortex-m3", .initfn = cortex_m3_initfn,
.class_init = arm_v7m_class_init },
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4289c33..62c36b4 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -857,6 +857,9 @@ struct ARMCPU {
/* Used to synchronize KVM and QEMU in-kernel device levels */
uint8_t device_irq_level;
+
+ /* Used to set the maximum vector length the cpu will support. */
+ uint32_t sve_max_vq;
};
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
@@ -1266,7 +1269,7 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
* we store the underlying state in fpscr and just mask on read/write.
*/
#define FPSR_MASK 0xf800009f
-#define FPCR_MASK 0x07f79f00
+#define FPCR_MASK 0x07ff9f00
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index d0581d5..800bff7 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -29,6 +29,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
+#include "qapi/visitor.h"
static inline void set_feature(CPUARMState *env, int feature)
{
@@ -217,6 +218,29 @@ static void aarch64_a53_initfn(Object *obj)
define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
}
+static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ visit_type_uint32(v, name, &cpu->sve_max_vq, errp);
+}
+
+static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ Error *err = NULL;
+
+ visit_type_uint32(v, name, &cpu->sve_max_vq, &err);
+
+ if (!err && (cpu->sve_max_vq == 0 || cpu->sve_max_vq > ARM_MAX_VQ)) {
+ error_setg(&err, "unsupported SVE vector length");
+ error_append_hint(&err, "Valid sve-max-vq in range [1-%d]\n",
+ ARM_MAX_VQ);
+ }
+ error_propagate(errp, err);
+}
+
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
* otherwise, a CPU with as many features enabled as our emulation supports.
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
@@ -253,6 +277,10 @@ static void aarch64_max_initfn(Object *obj)
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */
#endif
+
+ cpu->sve_max_vq = ARM_MAX_VQ;
+ object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_vq,
+ cpu_max_set_sve_vq, NULL, NULL, &error_fatal);
}
}
@@ -405,6 +433,7 @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
uint64_t pmask;
assert(vq >= 1 && vq <= ARM_MAX_VQ);
+ assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
/* Zap the high bits of the zregs. */
for (i = 0; i < 32; i++) {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8b07bf2..a312408 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11312,9 +11312,13 @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
| (env->vfp.vec_len << 16)
| (env->vfp.vec_stride << 20);
+
i = get_float_exception_flags(&env->vfp.fp_status);
i |= get_float_exception_flags(&env->vfp.standard_fp_status);
- i |= get_float_exception_flags(&env->vfp.fp_status_f16);
+ /* FZ16 does not generate an input denormal exception. */
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
+ & ~float_flag_input_denormal);
+
fpscr |= vfp_exceptbits_from_host(i);
return fpscr;
}
@@ -11349,6 +11353,11 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
int i;
uint32_t changed;
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
+ if (!arm_feature(env, ARM_FEATURE_V8_FP16)) {
+ val &= ~FPCR_FZ16;
+ }
+
changed = env->vfp.xregs[ARM_VFP_FPSCR];
env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
env->vfp.vec_len = (val >> 16) & 7;
@@ -12437,9 +12446,12 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
zcr_len = 0;
} else {
int current_el = arm_current_el(env);
+ ARMCPU *cpu = arm_env_get_cpu(env);
- zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el];
- zcr_len &= 0xf;
+ zcr_len = cpu->sve_max_vq - 1;
+ if (current_el <= 1) {
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
+ }
if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
}
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index c3cbec9..0f98097 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -3358,7 +3358,7 @@ static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc,
e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1;
e2 = *(uint16_t *)(vm + H1_2(i));
e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3;
- r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status);
+ r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status_f16);
*(uint16_t *)(vd + H1_2(i)) = r;
}
} while (i & 63);
@@ -4045,7 +4045,7 @@ DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
-DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
+DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int16_t, H1_4)
DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 45a6c2a..8ca3876 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -137,14 +137,13 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
int el = arm_current_el(env);
const char *ns_status;
- cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n",
- env->pc, env->xregs[31]);
- for (i = 0; i < 31; i++) {
- cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
- if ((i % 4) == 3) {
- cpu_fprintf(f, "\n");
+ cpu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
+ for (i = 0; i < 32; i++) {
+ if (i == 31) {
+ cpu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]);
} else {
- cpu_fprintf(f, " ");
+ cpu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i],
+ (i + 2) % 3 ? " " : "\n");
}
}
@@ -153,8 +152,7 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
} else {
ns_status = "";
}
-
- cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n",
+ cpu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c",
psr,
psr & PSTATE_N ? 'N' : '-',
psr & PSTATE_Z ? 'Z' : '-',
@@ -164,17 +162,89 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
el,
psr & PSTATE_SP ? 'h' : 't');
- if (flags & CPU_DUMP_FPU) {
- int numvfpregs = 32;
- for (i = 0; i < numvfpregs; i++) {
+ if (!(flags & CPU_DUMP_FPU)) {
+ cpu_fprintf(f, "\n");
+ return;
+ }
+ cpu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
+ vfp_get_fpcr(env), vfp_get_fpsr(env));
+
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
+ int j, zcr_len = env->vfp.zcr_el[1] & 0xf; /* fix for system mode */
+
+ for (i = 0; i <= FFR_PRED_NUM; i++) {
+ bool eol;
+ if (i == FFR_PRED_NUM) {
+ cpu_fprintf(f, "FFR=");
+ /* It's last, so end the line. */
+ eol = true;
+ } else {
+ cpu_fprintf(f, "P%02d=", i);
+ switch (zcr_len) {
+ case 0:
+ eol = i % 8 == 7;
+ break;
+ case 1:
+ eol = i % 6 == 5;
+ break;
+ case 2:
+ case 3:
+ eol = i % 3 == 2;
+ break;
+ default:
+ /* More than one quadword per predicate. */
+ eol = true;
+ break;
+ }
+ }
+ for (j = zcr_len / 4; j >= 0; j--) {
+ int digits;
+ if (j * 4 + 4 <= zcr_len + 1) {
+ digits = 16;
+ } else {
+ digits = (zcr_len % 4 + 1) * 4;
+ }
+ cpu_fprintf(f, "%0*" PRIx64 "%s", digits,
+ env->vfp.pregs[i].p[j],
+ j ? ":" : eol ? "\n" : " ");
+ }
+ }
+
+ for (i = 0; i < 32; i++) {
+ if (zcr_len == 0) {
+ cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s",
+ i, env->vfp.zregs[i].d[1],
+ env->vfp.zregs[i].d[0], i & 1 ? "\n" : " ");
+ } else if (zcr_len == 1) {
+ cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64
+ ":%016" PRIx64 ":%016" PRIx64 "\n",
+ i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2],
+ env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]);
+ } else {
+ for (j = zcr_len; j >= 0; j--) {
+ bool odd = (zcr_len - j) % 2 != 0;
+ if (j == zcr_len) {
+ cpu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1);
+ } else if (!odd) {
+ if (j > 0) {
+ cpu_fprintf(f, " [%x-%x]=", j, j - 1);
+ } else {
+ cpu_fprintf(f, " [%x]=", j);
+ }
+ }
+ cpu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s",
+ env->vfp.zregs[i].d[j * 2 + 1],
+ env->vfp.zregs[i].d[j * 2],
+ odd || j == 0 ? "\n" : ":");
+ }
+ }
+ }
+ } else {
+ for (i = 0; i < 32; i++) {
uint64_t *q = aa64_vfp_qreg(env, i);
- uint64_t vlo = q[0];
- uint64_t vhi = q[1];
- cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
- i, vhi, vlo, (i & 1 ? '\n' : ' '));
+ cpu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s",
+ i, q[1], q[0], (i & 1 ? "\n" : " "));
}
- cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
- vfp_get_fpcr(env), vfp_get_fpsr(env));
}
}
@@ -11353,12 +11423,12 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
}
feature = ARM_FEATURE_V8_DOTPROD;
break;
- case 0x8: /* FCMLA, #0 */
- case 0x9: /* FCMLA, #90 */
- case 0xa: /* FCMLA, #180 */
- case 0xb: /* FCMLA, #270 */
- case 0xc: /* FCADD, #90 */
- case 0xe: /* FCADD, #270 */
+ case 0x18: /* FCMLA, #0 */
+ case 0x19: /* FCMLA, #90 */
+ case 0x1a: /* FCMLA, #180 */
+ case 0x1b: /* FCMLA, #270 */
+ case 0x1c: /* FCADD, #90 */
+ case 0x1e: /* FCADD, #270 */
if (size == 0
|| (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
|| (size == 3 && !is_q)) {
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 89efc80..6678795 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -4093,7 +4093,7 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
{
- return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_sh);
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sh);
}
static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
@@ -4103,7 +4103,7 @@ static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
{
- return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_dh);
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_dh);
}
static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
@@ -4372,12 +4372,11 @@ static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
* The load should begin at the address Rn + IMM.
*/
-static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len,
- int rn, int imm)
+static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
{
- uint32_t len_align = QEMU_ALIGN_DOWN(len, 8);
- uint32_t len_remain = len % 8;
- uint32_t nparts = len / 8 + ctpop8(len_remain);
+ int len_align = QEMU_ALIGN_DOWN(len, 8);
+ int len_remain = len % 8;
+ int nparts = len / 8 + ctpop8(len_remain);
int midx = get_mem_index(s);
TCGv_i64 addr, t0, t1;
@@ -4458,12 +4457,11 @@ static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len,
}
/* Similarly for stores. */
-static void do_str(DisasContext *s, uint32_t vofs, uint32_t len,
- int rn, int imm)
+static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
{
- uint32_t len_align = QEMU_ALIGN_DOWN(len, 8);
- uint32_t len_remain = len % 8;
- uint32_t nparts = len / 8 + ctpop8(len_remain);
+ int len_align = QEMU_ALIGN_DOWN(len, 8);
+ int len_remain = len % 8;
+ int nparts = len / 8 + ctpop8(len_remain);
int midx = get_mem_index(s);
TCGv_i64 addr, t0;
@@ -4667,8 +4665,7 @@ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
}
if (sve_access_check(s)) {
TCGv_i64 addr = new_tmp_a64(s);
- tcg_gen_muli_i64(addr, cpu_reg(s, a->rm),
- (a->nreg + 1) << dtype_msz(a->dtype));
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
do_ld_zpa(s, a->rd, a->pg, addr, a->dtype, a->nreg);
}
@@ -4821,6 +4818,7 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
unsigned vsz = vec_full_reg_size(s);
unsigned psz = pred_full_reg_size(s);
unsigned esz = dtype_esz[a->dtype];
+ unsigned msz = dtype_msz(a->dtype);
TCGLabel *over = gen_new_label();
TCGv_i64 temp;
@@ -4844,7 +4842,7 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
/* Load the data. */
temp = tcg_temp_new_i64();
- tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << esz);
+ tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << msz);
tcg_gen_qemu_ld_i64(temp, temp, get_mem_index(s),
s->be_data | dtype_mop[a->dtype]);
@@ -4900,7 +4898,7 @@ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn)
}
if (sve_access_check(s)) {
TCGv_i64 addr = new_tmp_a64(s);
- tcg_gen_muli_i64(addr, cpu_reg(s, a->rm), (a->nreg + 1) << a->msz);
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->msz);
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
do_st_zpa(s, a->rd, a->pg, addr, a->msz, a->esz, a->nreg);
}