diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/cpu.h | 5 | ||||
-rw-r--r-- | target/arm/cpu64.c | 15 | ||||
-rw-r--r-- | target/arm/helper.c | 9 | ||||
-rw-r--r-- | target/arm/m_helper.c | 114 | ||||
-rw-r--r-- | target/arm/translate.c | 14 | ||||
-rw-r--r-- | target/ppc/kvm.c | 21 |
6 files changed, 102 insertions, 76 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e1a66a2d1c..83a809d4ba 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -185,12 +185,9 @@ typedef struct { #ifdef TARGET_AARCH64 # define ARM_MAX_VQ 16 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp); -uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq); #else # define ARM_MAX_VQ 1 static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { } -static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq) -{ return 0; } #endif typedef struct ARMVectorReg { @@ -1317,6 +1314,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) if (mask & XPSR_GE) { env->GE = (val & XPSR_GE) >> 16; } +#ifndef CONFIG_USER_ONLY if (mask & XPSR_T) { env->thumb = ((val & XPSR_T) != 0); } @@ -1332,6 +1330,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) /* Note that this only happens on exception exit */ write_v7m_exception(env, val & XPSR_EXCP); } +#endif } #define HCR_VM (1ULL << 0) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 68baf0482f..a39d6fcea3 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -458,21 +458,6 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) cpu->sve_max_vq = max_vq; } -uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq) -{ - uint32_t bitnum; - - /* - * We allow vq == ARM_MAX_VQ + 1 to be input because the caller may want - * to find the maximum vq enabled, which may be ARM_MAX_VQ, but this - * function always returns the next smaller than the input. - */ - assert(vq && vq <= ARM_MAX_VQ + 1); - - bitnum = find_last_bit(cpu->sve_vq_map, vq - 1); - return bitnum == vq - 1 ? 0 : bitnum + 1; -} - static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { diff --git a/target/arm/helper.c b/target/arm/helper.c index be67e2c66d..a089fb5a69 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5363,9 +5363,14 @@ int sve_exception_el(CPUARMState *env, int el) static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len) { - uint32_t start_vq = (start_len & 0xf) + 1; + uint32_t end_len; - return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1; + end_len = start_len &= 0xf; + if (!test_bit(start_len, cpu->sve_vq_map)) { + end_len = find_last_bit(cpu->sve_vq_map, start_len); + assert(end_len < start_len); + } + return end_len; } /* diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index f2512e448e..4a48b79252 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -33,22 +33,82 @@ #include "exec/cpu_ldst.h" #endif +static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask, + uint32_t reg, uint32_t val) +{ + /* Only APSR is actually writable */ + if (!(reg & 4)) { + uint32_t apsrmask = 0; + + if (mask & 8) { + apsrmask |= XPSR_NZCV | XPSR_Q; + } + if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) { + apsrmask |= XPSR_GE; + } + xpsr_write(env, val, apsrmask); + } +} + +static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg, unsigned el) +{ + uint32_t mask = 0; + + if ((reg & 1) && el) { + mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */ + } + if (!(reg & 4)) { + mask |= XPSR_NZCV | XPSR_Q; /* APSR */ + if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) { + mask |= XPSR_GE; + } + } + /* EPSR reads as zero */ + return xpsr_read(env) & mask; +} + +static uint32_t v7m_mrs_control(CPUARMState *env, uint32_t secure) +{ + uint32_t value = env->v7m.control[secure]; + + if (!secure) { + /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */ + value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK; + } + return value; +} + #ifdef CONFIG_USER_ONLY -/* These should probably raise undefined insn exceptions. */ -void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val) +void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) { - ARMCPU *cpu = env_archcpu(env); + uint32_t mask = extract32(maskreg, 8, 4); + uint32_t reg = extract32(maskreg, 0, 8); - cpu_abort(CPU(cpu), "v7m_msr %d\n", reg); + switch (reg) { + case 0 ... 7: /* xPSR sub-fields */ + v7m_msr_xpsr(env, mask, reg, val); + break; + case 20: /* CONTROL */ + /* There are no sub-fields that are actually writable from EL0. */ + break; + default: + /* Unprivileged writes to other registers are ignored */ + break; + } } uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) { - ARMCPU *cpu = env_archcpu(env); - - cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg); - return 0; + switch (reg) { + case 0 ... 7: /* xPSR sub-fields */ + return v7m_mrs_xpsr(env, reg, 0); + case 20: /* CONTROL */ + return v7m_mrs_control(env, 0); + default: + /* Unprivileged reads others as zero. */ + return 0; + } } void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) @@ -2196,35 +2256,14 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) { - uint32_t mask; unsigned el = arm_current_el(env); /* First handle registers which unprivileged can read */ - switch (reg) { case 0 ... 7: /* xPSR sub-fields */ - mask = 0; - if ((reg & 1) && el) { - mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */ - } - if (!(reg & 4)) { - mask |= XPSR_NZCV | XPSR_Q; /* APSR */ - if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) { - mask |= XPSR_GE; - } - } - /* EPSR reads as zero */ - return xpsr_read(env) & mask; - break; + return v7m_mrs_xpsr(env, reg, el); case 20: /* CONTROL */ - { - uint32_t value = env->v7m.control[env->v7m.secure]; - if (!env->v7m.secure) { - /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */ - value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK; - } - return value; - } + return v7m_mrs_control(env, env->v7m.secure); case 0x94: /* CONTROL_NS */ /* * We have to handle this here because unprivileged Secure code @@ -2454,18 +2493,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) switch (reg) { case 0 ... 7: /* xPSR sub-fields */ - /* only APSR is actually writable */ - if (!(reg & 4)) { - uint32_t apsrmask = 0; - - if (mask & 8) { - apsrmask |= XPSR_NZCV | XPSR_Q; - } - if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) { - apsrmask |= XPSR_GE; - } - xpsr_write(env, val, apsrmask); - } + v7m_msr_xpsr(env, mask, reg, val); break; case 8: /* MSP */ if (v7m_using_psp(env)) { diff --git a/target/arm/translate.c b/target/arm/translate.c index 2ea9da7637..4d5d4bd888 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8927,15 +8927,17 @@ static bool trans_SWPB(DisasContext *s, arg_SWP *a) static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel) { TCGv_i32 addr; + /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */ + bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M); /* We UNDEF for these UNPREDICTABLE cases. */ if (a->rd == 15 || a->rn == 15 || a->rt == 15 || a->rd == a->rn || a->rd == a->rt - || (s->thumb && (a->rd == 13 || a->rt == 13)) + || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13)) || (mop == MO_64 && (a->rt2 == 15 - || a->rd == a->rt2 || a->rt == a->rt2 - || (s->thumb && a->rt2 == 13)))) { + || a->rd == a->rt2 + || (!v8a && s->thumb && a->rt2 == 13)))) { unallocated_encoding(s); return true; } @@ -9084,13 +9086,15 @@ static bool trans_STLH(DisasContext *s, arg_STL *a) static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq) { TCGv_i32 addr; + /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */ + bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M); /* We UNDEF for these UNPREDICTABLE cases. */ if (a->rn == 15 || a->rt == 15 - || (s->thumb && a->rt == 13) + || (!v8a && s->thumb && a->rt == 13) || (mop == MO_64 && (a->rt2 == 15 || a->rt == a->rt2 - || (s->thumb && a->rt2 == 13)))) { + || (!v8a && s->thumb && a->rt2 == 13)))) { unallocated_encoding(s); return true; } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 7d2e8969ac..c77f9848ec 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -100,7 +100,7 @@ static bool kvmppc_is_pr(KVMState *ks) return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; } -static int kvm_ppc_register_host_cpu_type(MachineState *ms); +static int kvm_ppc_register_host_cpu_type(void); static void kvmppc_get_cpu_characteristics(KVMState *s); static int kvmppc_get_dec_bits(void); @@ -147,7 +147,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) exit(1); } - kvm_ppc_register_host_cpu_type(ms); + kvm_ppc_register_host_cpu_type(); return 0; } @@ -2534,13 +2534,19 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) return pvr_pcc; } -static int kvm_ppc_register_host_cpu_type(MachineState *ms) +static void pseries_machine_class_fixup(ObjectClass *oc, void *opaque) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; +} + +static int kvm_ppc_register_host_cpu_type(void) { TypeInfo type_info = { .name = TYPE_HOST_POWERPC_CPU, .class_init = kvmppc_host_cpu_class_init, }; - MachineClass *mc = MACHINE_GET_CLASS(ms); PowerPCCPUClass *pvr_pcc; ObjectClass *oc; DeviceClass *dc; @@ -2552,10 +2558,9 @@ static int kvm_ppc_register_host_cpu_type(MachineState *ms) } type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); - if (object_dynamic_cast(OBJECT(ms), TYPE_SPAPR_MACHINE)) { - /* override TCG default cpu type with 'host' cpu model */ - mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; - } + /* override TCG default cpu type with 'host' cpu model */ + object_class_foreach(pseries_machine_class_fixup, TYPE_SPAPR_MACHINE, + false, NULL); oc = object_class_by_name(type_info.name); g_assert(oc); |