diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-08-16 14:35:50 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-08-16 14:35:50 +0100 |
commit | bb16c0412a572c2c9cd44496deb3ad430bc49c1a (patch) | |
tree | cb87c31c5440a9128cf7762407237b5b57fbed33 /target/arm | |
parent | c542a9f9794ec8e0bc3fcf5956d3cc8bce667789 (diff) | |
parent | fcf13ca556f462b52956059bf8fa622bc8575edb (diff) | |
download | qemu-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.c | 17 | ||||
-rw-r--r-- | target/arm/cpu.h | 5 | ||||
-rw-r--r-- | target/arm/cpu64.c | 29 | ||||
-rw-r--r-- | target/arm/helper.c | 18 | ||||
-rw-r--r-- | target/arm/sve_helper.c | 4 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 118 | ||||
-rw-r--r-- | target/arm/translate-sve.c | 30 |
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); } |