aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/cpu64.c15
-rw-r--r--target/arm/helper.c9
-rw-r--r--target/arm/m_helper.c114
-rw-r--r--target/arm/translate.c14
-rw-r--r--target/ppc/kvm.c21
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);