aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-02-18 16:20:13 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-02-18 16:20:13 +0000
commit2e68b8620637a4ee8c79b5724144b726af1e261b (patch)
treee53cbfaf5cbdd0d0b0c326838634e92096540256 /target
parenta0430dd8abb8a2f31c5ee919daab2e3d76353c04 (diff)
parent73e14c6a9cdefb94c01ea488f04e7fba7ac0dc5b (diff)
downloadqemu-2e68b8620637a4ee8c79b5724144b726af1e261b.zip
qemu-2e68b8620637a4ee8c79b5724144b726af1e261b.tar.gz
qemu-2e68b8620637a4ee8c79b5724144b726af1e261b.tar.bz2
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190219' into staging
ppc patch queue 2019-02-19 Here's the next batch of ppc and spapr patches. Higlights are: * A bunch of improvements to TCG handling of vector instructions from Richard Henderson and Marc Cave-Ayland * Cleanup to the XICS interrupt controller from Greg Kurz, removing the special KVM subclasses which were a bad idea * Some refinements to the XIVE interrupt controller from Cédric Le Goater * Fix from Fabiano Rosas for a really dumb buffer overflow in the device tree code for memory hotplug * Code for allowing access to SPRs from the gdb stub from Fabiano Rosas * Assorted minor fixes and cleanups # gpg: Signature made Mon 18 Feb 2019 13:47:54 GMT # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-4.0-20190219: (43 commits) target/ppc: convert vmin* and vmax* to vector operations target/ppc: convert vadd*s and vsub*s to vector operations target/ppc: Split out VSCR_SAT to a vector field target/ppc: Add set_vscr_sat target/ppc: Use mtvscr/mfvscr for vmstate target/ppc: Add helper_mfvscr target/ppc: Remove vscr_nj and vscr_sat target/ppc: Use helper_mtvscr for reset and gdb target/ppc: Pass integer to helper_mtvscr target/ppc: convert xxsel to vector operations target/ppc: convert xxspltw to vector operations target/ppc: convert xxspltib to vector operations target/ppc: convert VSX logical operations to vector operations target/ppc: convert vsplt[bhw] to use vector operations target/ppc: convert vspltis[bhw] to use vector operations target/ppc: convert vaddu[b,h,w,d] and vsubu[b,h,w,d] over to use vector operations target/ppc: convert VMX logical instructions to use vector operations xics: Drop the KVM ICS class spapr/irq: Use the "simple" ICS class for KVM xics: Handle KVM interrupt presentation from "simple" ICS code ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/ppc/arch_dump.c3
-rw-r--r--target/ppc/cpu-qom.h4
-rw-r--r--target/ppc/cpu.h11
-rw-r--r--target/ppc/excp_helper.c12
-rw-r--r--target/ppc/gdbstub.c61
-rw-r--r--target/ppc/helper.h57
-rw-r--r--target/ppc/int_helper.c129
-rw-r--r--target/ppc/machine.c44
-rw-r--r--target/ppc/mmu_helper.c12
-rw-r--r--target/ppc/translate.c49
-rw-r--r--target/ppc/translate/vmx-impl.inc.c251
-rw-r--r--target/ppc/translate/vsx-impl.inc.c147
-rw-r--r--target/ppc/translate_init.inc.c71
13 files changed, 444 insertions, 407 deletions
diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c
index 3a00606..9ab04b2 100644
--- a/target/ppc/arch_dump.c
+++ b/target/ppc/arch_dump.c
@@ -17,6 +17,7 @@
#include "elf.h"
#include "sysemu/dump.h"
#include "sysemu/kvm.h"
+#include "exec/helper-proto.h"
#ifdef TARGET_PPC64
#define ELFCLASS ELFCLASS64
@@ -175,7 +176,7 @@ static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
vmxregset->avr[i].u64[1] = avr->u64[1];
}
}
- vmxregset->vscr.u32[3] = cpu_to_dump32(s, cpu->env.vscr);
+ vmxregset->vscr.u32[3] = cpu_to_dump32(s, helper_mfvscr(&cpu->env));
}
static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 4ea6769..3130802 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -179,6 +179,10 @@ typedef struct PowerPCCPUClass {
uint32_t flags;
int bfd_mach;
uint32_t l1_dcache_size, l1_icache_size;
+#ifndef CONFIG_USER_ONLY
+ unsigned int gdb_num_sprs;
+ const char *gdb_spr_xml;
+#endif
const PPCHash64Options *hash64_opts;
struct ppc_radix_page_info *radix_page_info;
void (*init_proc)(CPUPPCState *env);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 2c22292..325ebbe 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -230,6 +230,7 @@ struct ppc_spr_t {
void (*oea_write)(DisasContext *ctx, int spr_num, int gpr_num);
void (*hea_read)(DisasContext *ctx, int gpr_num, int spr_num);
void (*hea_write)(DisasContext *ctx, int spr_num, int gpr_num);
+ unsigned int gdb_id;
#endif
const char *name;
target_ulong default_value;
@@ -688,8 +689,6 @@ enum {
/* Vector status and control register */
#define VSCR_NJ 16 /* Vector non-java */
#define VSCR_SAT 0 /* Vector saturation */
-#define vscr_nj (((env->vscr) >> VSCR_NJ) & 0x1)
-#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
/*****************************************************************************/
/* BookE e500 MMU registers */
@@ -1053,10 +1052,12 @@ struct CPUPPCState {
/* Special purpose registers */
target_ulong spr[1024];
ppc_spr_t spr_cb[1024];
- /* Vector status and control register */
+ /* Vector status and control register, minus VSCR_SAT. */
uint32_t vscr;
/* VSX registers (including FP and AVR) */
ppc_vsr_t vsr[64] QEMU_ALIGNED(16);
+ /* Non-zero if and only if VSCR_SAT should be set. */
+ ppc_vsr_t vscr_sat QEMU_ALIGNED(16);
/* SPE registers */
uint64_t spe_acc;
uint32_t spe_fscr;
@@ -1263,6 +1264,10 @@ int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_read_register_apple(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
+#endif
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0ec7ae1..751d759 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -748,13 +748,7 @@ void ppc_cpu_do_interrupt(CPUState *cs)
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
-#if 0
- CPUState *cs = CPU(cpu);
- qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
- __func__, env, env->pending_interrupts,
- cs->interrupt_request, (int)msr_me, (int)msr_ee);
-#endif
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
@@ -797,12 +791,6 @@ static void ppc_hw_interrupt(CPUPPCState *env)
if (msr_ce != 0) {
/* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
- /* Taking a critical external interrupt does not clear the external
- * critical interrupt status
- */
-#if 0
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
-#endif
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
return;
}
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 19565b5..fbf3821 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -319,3 +319,64 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
}
return r;
}
+
+#ifndef CONFIG_USER_ONLY
+void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ GString *xml;
+ char *spr_name;
+ unsigned int num_regs = 0;
+ int i;
+
+ if (pcc->gdb_spr_xml) {
+ return;
+ }
+
+ xml = g_string_new("<?xml version=\"1.0\"?>");
+ g_string_append(xml, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append(xml, "<feature name=\"org.qemu.power.spr\">");
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (!spr->name) {
+ continue;
+ }
+
+ spr_name = g_ascii_strdown(spr->name, -1);
+ g_string_append_printf(xml, "<reg name=\"%s\"", spr_name);
+ g_free(spr_name);
+
+ g_string_append_printf(xml, " bitsize=\"%d\"", TARGET_LONG_BITS);
+ g_string_append(xml, " group=\"spr\"/>");
+
+ /*
+ * GDB identifies registers based on the order they are
+ * presented in the XML. These ids will not match QEMU's
+ * representation (which follows the PowerISA).
+ *
+ * Store the position of the current register description so
+ * we can make the correspondence later.
+ */
+ spr->gdb_id = num_regs;
+ num_regs++;
+ }
+
+ g_string_append(xml, "</feature>");
+
+ pcc->gdb_num_sprs = num_regs;
+ pcc->gdb_spr_xml = g_string_free(xml, false);
+}
+
+const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+
+ if (strcmp(xml_name, "power-spr.xml") == 0) {
+ return pcc->gdb_spr_xml;
+ }
+ return NULL;
+}
+#endif
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index c7de04e..18910d1 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -108,14 +108,6 @@ DEF_HELPER_FLAGS_1(ftsqrt, TCG_CALL_NO_RWG_SE, i32, i64)
#define dh_ctype_avr ppc_avr_t *
#define dh_is_signed_avr dh_is_signed_ptr
-DEF_HELPER_3(vaddubm, void, avr, avr, avr)
-DEF_HELPER_3(vadduhm, void, avr, avr, avr)
-DEF_HELPER_3(vadduwm, void, avr, avr, avr)
-DEF_HELPER_3(vaddudm, void, avr, avr, avr)
-DEF_HELPER_3(vsububm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuhm, void, avr, avr, avr)
-DEF_HELPER_3(vsubuwm, void, avr, avr, avr)
-DEF_HELPER_3(vsubudm, void, avr, avr, avr)
DEF_HELPER_3(vavgub, void, avr, avr, avr)
DEF_HELPER_3(vavguh, void, avr, avr, avr)
DEF_HELPER_3(vavguw, void, avr, avr, avr)
@@ -125,22 +117,6 @@ DEF_HELPER_3(vabsduw, void, avr, avr, avr)
DEF_HELPER_3(vavgsb, void, avr, avr, avr)
DEF_HELPER_3(vavgsh, void, avr, avr, avr)
DEF_HELPER_3(vavgsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsb, void, avr, avr, avr)
-DEF_HELPER_3(vminsh, void, avr, avr, avr)
-DEF_HELPER_3(vminsw, void, avr, avr, avr)
-DEF_HELPER_3(vminsd, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsb, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxsd, void, avr, avr, avr)
-DEF_HELPER_3(vminub, void, avr, avr, avr)
-DEF_HELPER_3(vminuh, void, avr, avr, avr)
-DEF_HELPER_3(vminuw, void, avr, avr, avr)
-DEF_HELPER_3(vminud, void, avr, avr, avr)
-DEF_HELPER_3(vmaxub, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuh, void, avr, avr, avr)
-DEF_HELPER_3(vmaxuw, void, avr, avr, avr)
-DEF_HELPER_3(vmaxud, void, avr, avr, avr)
DEF_HELPER_4(vcmpequb, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequh, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpequw, void, env, avr, avr, avr)
@@ -227,18 +203,18 @@ DEF_HELPER_2(vprtybq, void, avr, avr)
DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
DEF_HELPER_2(lvsl, void, avr, tl)
DEF_HELPER_2(lvsr, void, avr, tl)
-DEF_HELPER_4(vaddsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsbs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubshs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubsws, void, env, avr, avr, avr)
-DEF_HELPER_4(vaddubs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vadduws, void, env, avr, avr, avr)
-DEF_HELPER_4(vsububs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuhs, void, env, avr, avr, avr)
-DEF_HELPER_4(vsubuws, void, env, avr, avr, avr)
+DEF_HELPER_FLAGS_5(vaddsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vaddubs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vadduws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_3(vadduqm, void, avr, avr, avr)
DEF_HELPER_4(vaddecuq, void, avr, avr, avr, avr)
DEF_HELPER_4(vaddeuqm, void, avr, avr, avr, avr)
@@ -254,12 +230,6 @@ DEF_HELPER_3(vrld, void, avr, avr, avr)
DEF_HELPER_3(vsl, void, avr, avr, avr)
DEF_HELPER_3(vsr, void, avr, avr, avr)
DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32)
-DEF_HELPER_2(vspltisb, void, avr, i32)
-DEF_HELPER_2(vspltish, void, avr, i32)
-DEF_HELPER_2(vspltisw, void, avr, i32)
-DEF_HELPER_3(vspltb, void, avr, avr, i32)
-DEF_HELPER_3(vsplth, void, avr, avr, i32)
-DEF_HELPER_3(vspltw, void, avr, avr, i32)
DEF_HELPER_3(vextractub, void, avr, avr, i32)
DEF_HELPER_3(vextractuh, void, avr, avr, i32)
DEF_HELPER_3(vextractuw, void, avr, avr, i32)
@@ -308,7 +278,8 @@ DEF_HELPER_5(vmsumuhs, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
-DEF_HELPER_2(mtvscr, void, env, avr)
+DEF_HELPER_FLAGS_2(mtvscr, TCG_CALL_NO_RWG, void, env, i32)
+DEF_HELPER_FLAGS_1(mfvscr, TCG_CALL_NO_RWG, i32, env)
DEF_HELPER_3(lvebx, void, env, avr, tl)
DEF_HELPER_3(lvehx, void, env, avr, tl)
DEF_HELPER_3(lvewx, void, env, avr, tl)
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 8efc283..162add5 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -457,10 +457,25 @@ void helper_lvsr(ppc_avr_t *r, target_ulong sh)
}
}
-void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
+void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
{
- env->vscr = r->VsrW(3);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ env->vscr = vscr & ~(1u << VSCR_SAT);
+ /* Which bit we set is completely arbitrary, but clear the rest. */
+ env->vscr_sat.u64[0] = vscr & (1u << VSCR_SAT);
+ env->vscr_sat.u64[1] = 0;
+ set_flush_to_zero((vscr >> VSCR_NJ) & 1, &env->vec_status);
+}
+
+uint32_t helper_mfvscr(CPUPPCState *env)
+{
+ uint32_t sat = (env->vscr_sat.u64[0] | env->vscr_sat.u64[1]) != 0;
+ return env->vscr | (sat << VSCR_SAT);
+}
+
+static inline void set_vscr_sat(CPUPPCState *env)
+{
+ /* The choice of non-zero value is arbitrary. */
+ env->vscr_sat.u32[0] = 1;
}
void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
@@ -515,13 +530,6 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b)
r->element[i] = a->element[i] op b->element[i]; \
} \
}
-#define VARITH(suffix, element) \
- VARITH_DO(add##suffix, +, element) \
- VARITH_DO(sub##suffix, -, element)
-VARITH(ubm, u8)
-VARITH(uhm, u16)
-VARITH(uwm, u32)
-VARITH(udm, u64)
VARITH_DO(muluwm, *, u32)
#undef VARITH_DO
#undef VARITH
@@ -563,27 +571,17 @@ VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
}
#define VARITHSAT_DO(name, op, optype, cvt, element) \
- void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
- ppc_avr_t *b) \
+ void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat, \
+ ppc_avr_t *a, ppc_avr_t *b, uint32_t desc) \
{ \
int sat = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- switch (sizeof(r->element[0])) { \
- case 1: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 2: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- case 4: \
- VARITHSAT_CASE(optype, op, cvt, element); \
- break; \
- } \
+ VARITHSAT_CASE(optype, op, cvt, element); \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ vscr_sat->u32[0] = 1; \
} \
}
#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
@@ -855,7 +853,7 @@ void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
} \
} \
if (sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
VCT(uxs, cvtsduw, u32)
@@ -902,7 +900,7 @@ void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -919,37 +917,10 @@ void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
-#define VMINMAX_DO(name, compare, element) \
- void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
- { \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- if (a->element[i] compare b->element[i]) { \
- r->element[i] = b->element[i]; \
- } else { \
- r->element[i] = a->element[i]; \
- } \
- } \
- }
-#define VMINMAX(suffix, element) \
- VMINMAX_DO(min##suffix, >, element) \
- VMINMAX_DO(max##suffix, <, element)
-VMINMAX(sb, s8)
-VMINMAX(sh, s16)
-VMINMAX(sw, s32)
-VMINMAX(sd, s64)
-VMINMAX(ub, u8)
-VMINMAX(uh, u16)
-VMINMAX(uw, u32)
-VMINMAX(ud, u64)
-#undef VMINMAX_DO
-#undef VMINMAX
-
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
@@ -1031,7 +1002,7 @@ void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -1084,7 +1055,7 @@ void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -1601,7 +1572,7 @@ void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
} \
*r = result; \
if (dosat && sat) { \
- env->vscr |= (1 << VSCR_SAT); \
+ set_vscr_sat(env); \
} \
}
#define I(x, y) (x)
@@ -1876,25 +1847,6 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
#endif
}
-/* Experimental testing shows that hardware masks the immediate. */
-#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
-#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
-#define VSPLT(suffix, element, access) \
- void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
- { \
- uint32_t s = b->access(SPLAT_ELEMENT(element)); \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->access(i) = s; \
- } \
- }
-VSPLT(b, u8, VsrB)
-VSPLT(h, u16, VsrH)
-VSPLT(w, u32, VsrW)
-#undef VSPLT
-#undef SPLAT_ELEMENT
-#undef _SPLAT_MASKED
#if defined(HOST_WORDS_BIGENDIAN)
#define VINSERT(suffix, element) \
void helper_vinsert##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
@@ -2005,21 +1957,6 @@ VNEG(vnegw, s32)
VNEG(vnegd, s64)
#undef VNEG
-#define VSPLTI(suffix, element, splat_type) \
- void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
- { \
- splat_type x = (int8_t)(splat << 3) >> 3; \
- int i; \
- \
- for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
- r->element[i] = x; \
- } \
- }
-VSPLTI(b, s8, int8_t)
-VSPLTI(h, s16, int16_t)
-VSPLTI(w, s32, int32_t)
-#undef VSPLTI
-
#define VSR(suffix, element, mask) \
void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
@@ -2079,7 +2016,7 @@ void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2102,7 +2039,7 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
*r = result;
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2121,7 +2058,7 @@ void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2138,7 +2075,7 @@ void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
@@ -2157,7 +2094,7 @@ void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
}
if (sat) {
- env->vscr |= (1 << VSCR_SAT);
+ set_vscr_sat(env);
}
}
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index eff3005..756b6d2 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -10,6 +10,7 @@
#include "migration/cpu.h"
#include "qapi/error.h"
#include "kvm_ppc.h"
+#include "exec/helper-proto.h"
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
{
@@ -17,7 +18,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
CPUPPCState *env = &cpu->env;
unsigned int i, j;
target_ulong sdr1;
- uint32_t fpscr;
+ uint32_t fpscr, vscr;
#if defined(TARGET_PPC64)
int32_t slb_nr;
#endif
@@ -84,7 +85,8 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
if (!cpu->vhyp) {
ppc_store_sdr1(env, sdr1);
}
- qemu_get_be32s(f, &env->vscr);
+ qemu_get_be32s(f, &vscr);
+ helper_mtvscr(env, vscr);
qemu_get_be64s(f, &env->spe_acc);
qemu_get_be32s(f, &env->spe_fscr);
qemu_get_betls(f, &env->msr_mask);
@@ -429,6 +431,28 @@ static bool altivec_needed(void *opaque)
return (cpu->env.insns_flags & PPC_ALTIVEC);
}
+static int get_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field)
+{
+ PowerPCCPU *cpu = opaque;
+ helper_mtvscr(&cpu->env, qemu_get_be32(f));
+ return 0;
+}
+
+static int put_vscr(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field, QJSON *vmdesc)
+{
+ PowerPCCPU *cpu = opaque;
+ qemu_put_be32(f, helper_mfvscr(&cpu->env));
+ return 0;
+}
+
+static const VMStateInfo vmstate_vscr = {
+ .name = "cpu/altivec/vscr",
+ .get = get_vscr,
+ .put = put_vscr,
+};
+
static const VMStateDescription vmstate_altivec = {
.name = "cpu/altivec",
.version_id = 1,
@@ -436,7 +460,21 @@ static const VMStateDescription vmstate_altivec = {
.needed = altivec_needed,
.fields = (VMStateField[]) {
VMSTATE_AVR_ARRAY(env.vsr, PowerPCCPU, 32),
- VMSTATE_UINT32(env.vscr, PowerPCCPU),
+ /*
+ * Save the architecture value of the vscr, not the internally
+ * expanded version. Since this architecture value does not
+ * exist in memory to be stored, this requires a but of hoop
+ * jumping. We want OFFSET=0 so that we effectively pass CPU
+ * to the helper functions.
+ */
+ {
+ .name = "vscr",
+ .version_id = 0,
+ .size = sizeof(uint32_t),
+ .info = &vmstate_vscr,
+ .flags = VMS_SINGLE,
+ .offset = 0
+ },
VMSTATE_END_OF_LIST()
},
};
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index cefed34..bcf19da 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1415,10 +1415,6 @@ static int get_physical_address_wtlb(
bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
|| (access_type != ACCESS_CODE && msr_dr == 0);
-#if 0
- qemu_log("%s\n", __func__);
-#endif
-
switch (env->mmu_model) {
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
@@ -1468,10 +1464,6 @@ static int get_physical_address_wtlb(
cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
return -1;
}
-#if 0
- qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
- __func__, eaddr, ret, ctx->raddr);
-#endif
return ret;
}
@@ -1805,10 +1797,6 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
break;
}
}
-#if 0
- printf("%s: set exception to %d %02x\n", __func__,
- cs->exception, env->error_code);
-#endif
ret = 1;
}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e169c43..f4d70e7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -24,6 +24,7 @@
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
+#include "tcg-op-gvec.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
@@ -287,26 +288,22 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->exception = (excp);
}
-/* Translates the EXCP_TRACE/BRANCH exceptions used on most PowerPCs to
- * EXCP_DEBUG, if we are running on cores using the debug enable bit (e.g.
- * BookE).
+/*
+ * Tells the caller what is the appropriate exception to generate and prepares
+ * SPR registers for this exception.
+ *
+ * The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
+ * POWERPC_EXCP_DEBUG (on BookE).
*/
-static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
+static uint32_t gen_prep_dbgex(DisasContext *ctx)
{
- if ((ctx->singlestep_enabled & CPU_SINGLE_STEP)
- && (excp == POWERPC_EXCP_BRANCH)) {
- /* Trace excpt. has priority */
- excp = POWERPC_EXCP_TRACE;
- }
if (ctx->flags & POWERPC_FLAG_DE) {
target_ulong dbsr = 0;
- switch (excp) {
- case POWERPC_EXCP_TRACE:
+ if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
dbsr = DBCR0_ICMP;
- break;
- case POWERPC_EXCP_BRANCH:
+ } else {
+ /* Must have been branch */
dbsr = DBCR0_BRT;
- break;
}
TCGv t0 = tcg_temp_new();
gen_load_spr(t0, SPR_BOOKE_DBSR);
@@ -315,7 +312,7 @@ static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
tcg_temp_free(t0);
return POWERPC_EXCP_DEBUG;
} else {
- return excp;
+ return POWERPC_EXCP_TRACE;
}
}
@@ -3652,10 +3649,8 @@ static void gen_lookup_and_goto_ptr(DisasContext *ctx)
if (sse & GDBSTUB_SINGLE_STEP) {
gen_debug_exception(ctx);
} else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_BRANCH);
- if (excp != POWERPC_EXCP_NONE) {
- gen_exception(ctx, excp);
- }
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception(ctx, excp);
}
tcg_gen_exit_tb(NULL, 0);
} else {
@@ -6476,7 +6471,12 @@ static void gen_mbar(DisasContext *ctx)
/* msync replaces sync on 440 */
static void gen_msync_4xx(DisasContext *ctx)
{
- /* interpreted as no-op */
+ /* Only e500 seems to treat reserved bits as invalid */
+ if ((ctx->insns_flags2 & PPC2_BOOKE206) &&
+ (ctx->opcode & 0x03FFF801)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ }
+ /* otherwise interpreted as no-op */
}
/* icbt */
@@ -7054,11 +7054,11 @@ GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
PPC_BOOKE, PPC2_BOOKE206),
-GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
+GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x039FF801, PPC_BOOKE),
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
- PPC_440_SPEC),
+ PPC_440_SPEC),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
@@ -7785,9 +7785,8 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
ctx->exception != POWERPC_SYSCALL &&
ctx->exception != POWERPC_EXCP_TRAP &&
ctx->exception != POWERPC_EXCP_BRANCH)) {
- uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_TRACE);
- if (excp != POWERPC_EXCP_NONE)
- gen_exception_nip(ctx, excp, ctx->base.pc_next);
+ uint32_t excp = gen_prep_dbgex(ctx);
+ gen_exception_nip(ctx, excp, ctx->base.pc_next);
}
if (tcg_check_temp_count()) {
diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c
index f99d028..f1b15ae 100644
--- a/target/ppc/translate/vmx-impl.inc.c
+++ b/target/ppc/translate/vmx-impl.inc.c
@@ -187,7 +187,7 @@ static void gen_mfvscr(DisasContext *ctx)
tcg_gen_movi_i64(avr, 0);
set_avr64(rD(ctx->opcode), avr, true);
t = tcg_temp_new_i32();
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
+ gen_helper_mfvscr(t, cpu_env);
tcg_gen_extu_i32_i64(avr, t);
set_avr64(rD(ctx->opcode), avr, false);
tcg_temp_free_i32(t);
@@ -196,14 +196,23 @@ static void gen_mfvscr(DisasContext *ctx)
static void gen_mtvscr(DisasContext *ctx)
{
- TCGv_ptr p;
+ TCGv_i32 val;
+ int bofs;
+
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
}
- p = gen_avr_ptr(rB(ctx->opcode));
- gen_helper_mtvscr(cpu_env, p);
- tcg_temp_free_ptr(p);
+
+ val = tcg_temp_new_i32();
+ bofs = avr64_offset(rB(ctx->opcode), true);
+#ifdef HOST_WORDS_BIGENDIAN
+ bofs += 3 * 4;
+#endif
+
+ tcg_gen_ld_i32(val, cpu_env, bofs);
+ gen_helper_mtvscr(cpu_env, val);
+ tcg_temp_free_i32(val);
}
#define GEN_VX_VMUL10(name, add_cin, ret_carry) \
@@ -266,45 +275,30 @@ GEN_VX_VMUL10(vmul10euq, 1, 0);
GEN_VX_VMUL10(vmul10cuq, 0, 1);
GEN_VX_VMUL10(vmul10ecuq, 1, 1);
-/* Logical operations */
-#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+#define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 avr; \
- \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- avr = tcg_temp_new_i64(); \
- \
- get_avr64(t0, rA(ctx->opcode), true); \
- get_avr64(t1, rB(ctx->opcode), true); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, true); \
\
- get_avr64(t0, rA(ctx->opcode), false); \
- get_avr64(t1, rB(ctx->opcode), false); \
- tcg_op(avr, t0, t1); \
- set_avr64(rD(ctx->opcode), avr, false); \
- \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(avr); \
+ tcg_op(vece, \
+ avr64_offset(rD(ctx->opcode), true), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16); \
}
-GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
-GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
-GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
-GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
-GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
-GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
-GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
-GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
+/* Logical operations */
+GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16);
+GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17);
+GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18);
+GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19);
+GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20);
+GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26);
+GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
+GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
#define GEN_VXFORM(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -410,34 +404,34 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rb); \
}
-GEN_VXFORM(vaddubm, 0, 0);
+GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM(vadduhm, 0, 1);
+GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1);
GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE, \
vmul10ecuq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vadduwm, 0, 2);
-GEN_VXFORM(vaddudm, 0, 3);
-GEN_VXFORM(vsububm, 0, 16);
-GEN_VXFORM(vsubuhm, 0, 17);
-GEN_VXFORM(vsubuwm, 0, 18);
-GEN_VXFORM(vsubudm, 0, 19);
-GEN_VXFORM(vmaxub, 1, 0);
-GEN_VXFORM(vmaxuh, 1, 1);
-GEN_VXFORM(vmaxuw, 1, 2);
-GEN_VXFORM(vmaxud, 1, 3);
-GEN_VXFORM(vmaxsb, 1, 4);
-GEN_VXFORM(vmaxsh, 1, 5);
-GEN_VXFORM(vmaxsw, 1, 6);
-GEN_VXFORM(vmaxsd, 1, 7);
-GEN_VXFORM(vminub, 1, 8);
-GEN_VXFORM(vminuh, 1, 9);
-GEN_VXFORM(vminuw, 1, 10);
-GEN_VXFORM(vminud, 1, 11);
-GEN_VXFORM(vminsb, 1, 12);
-GEN_VXFORM(vminsh, 1, 13);
-GEN_VXFORM(vminsw, 1, 14);
-GEN_VXFORM(vminsd, 1, 15);
+GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2);
+GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3);
+GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16);
+GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17);
+GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18);
+GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19);
+GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0);
+GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1);
+GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2);
+GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3);
+GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4);
+GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5);
+GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6);
+GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7);
+GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8);
+GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9);
+GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10);
+GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11);
+GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
+GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
+GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
+GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
GEN_VXFORM(vavgub, 1, 16);
GEN_VXFORM(vabsdub, 1, 16);
GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
@@ -558,22 +552,55 @@ GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
-GEN_VXFORM_ENV(vaddubs, 0, 8);
+
+#define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3) \
+static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
+ TCGv_vec sat, TCGv_vec a, \
+ TCGv_vec b) \
+{ \
+ TCGv_vec x = tcg_temp_new_vec_matching(t); \
+ glue(glue(tcg_gen_, NORM), _vec)(VECE, x, a, b); \
+ glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b); \
+ tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t); \
+ tcg_gen_or_vec(VECE, sat, sat, x); \
+ tcg_temp_free_vec(x); \
+} \
+static void glue(gen_, NAME)(DisasContext *ctx) \
+{ \
+ static const GVecGen4 g = { \
+ .fniv = glue(glue(gen_, NAME), _vec), \
+ .fno = glue(gen_helper_, NAME), \
+ .opc = glue(glue(INDEX_op_, SAT), _vec), \
+ .write_aofs = true, \
+ .vece = VECE, \
+ }; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ tcg_gen_gvec_4(avr64_offset(rD(ctx->opcode), true), \
+ offsetof(CPUPPCState, vscr_sat), \
+ avr64_offset(rA(ctx->opcode), true), \
+ avr64_offset(rB(ctx->opcode), true), \
+ 16, 16, &g); \
+}
+
+GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8);
GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0, \
vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
-GEN_VXFORM_ENV(vadduhs, 0, 9);
+GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9);
GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
vmul10euq, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_ENV(vadduws, 0, 10);
-GEN_VXFORM_ENV(vaddsbs, 0, 12);
-GEN_VXFORM_ENV(vaddshs, 0, 13);
-GEN_VXFORM_ENV(vaddsws, 0, 14);
-GEN_VXFORM_ENV(vsububs, 0, 24);
-GEN_VXFORM_ENV(vsubuhs, 0, 25);
-GEN_VXFORM_ENV(vsubuws, 0, 26);
-GEN_VXFORM_ENV(vsubsbs, 0, 28);
-GEN_VXFORM_ENV(vsubshs, 0, 29);
-GEN_VXFORM_ENV(vsubsws, 0, 30);
+GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10);
+GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12);
+GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13);
+GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14);
+GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24);
+GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25);
+GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
+GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
+GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
+GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
GEN_VXFORM(vadduqm, 0, 4);
GEN_VXFORM(vaddcuq, 0, 5);
GEN_VXFORM3(vaddeuqm, 30, 0);
@@ -719,25 +746,21 @@ GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+#define GEN_VXFORM_DUPI(name, tcg_op, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
+ int simm; \
if (unlikely(!ctx->altivec_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
+ simm = SIMM5(ctx->opcode); \
+ tcg_op(avr64_offset(rD(ctx->opcode), true), 16, 16, simm); \
}
-GEN_VXFORM_SIMM(vspltisb, 6, 12);
-GEN_VXFORM_SIMM(vspltish, 6, 13);
-GEN_VXFORM_SIMM(vspltisw, 6, 14);
+GEN_VXFORM_DUPI(vspltisb, tcg_gen_gvec_dup8i, 6, 12);
+GEN_VXFORM_DUPI(vspltish, tcg_gen_gvec_dup16i, 6, 13);
+GEN_VXFORM_DUPI(vspltisw, tcg_gen_gvec_dup32i, 6, 14);
#define GEN_VXFORM_NOA(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -817,40 +840,32 @@ GEN_VXFORM_NOA(vprtybw, 1, 24);
GEN_VXFORM_NOA(vprtybd, 1, 24);
GEN_VXFORM_NOA(vprtybq, 1, 24);
-#define GEN_VXFORM_SIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rd; \
- TCGv_i32 simm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- simm = tcg_const_i32(SIMM5(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, simm); \
- tcg_temp_free_i32(simm); \
- tcg_temp_free_ptr(rd); \
- }
+static void gen_vsplt(DisasContext *ctx, int vece)
+{
+ int uimm, dofs, bofs;
-#define GEN_VXFORM_UIMM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_ptr rb, rd; \
- TCGv_i32 uimm; \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
- rb = gen_avr_ptr(rB(ctx->opcode)); \
- rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, rb, uimm); \
- tcg_temp_free_i32(uimm); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
}
+ uimm = UIMM5(ctx->opcode);
+ bofs = avr64_offset(rB(ctx->opcode), true);
+ dofs = avr64_offset(rD(ctx->opcode), true);
+
+ /* Experimental testing shows that hardware masks the immediate. */
+ bofs += (uimm << vece) & 15;
+#ifndef HOST_WORDS_BIGENDIAN
+ bofs ^= 15;
+ bofs &= ~((1 << vece) - 1);
+#endif
+
+ tcg_gen_gvec_dup_mem(vece, dofs, bofs, 16, 16);
+}
+
+#define GEN_VXFORM_VSPLT(name, vece, opc2, opc3) \
+static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); }
+
#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
@@ -893,9 +908,9 @@ static void glue(gen_, name)(DisasContext *ctx) \
tcg_temp_free_ptr(rd); \
}
-GEN_VXFORM_UIMM(vspltb, 6, 8);
-GEN_VXFORM_UIMM(vsplth, 6, 9);
-GEN_VXFORM_UIMM(vspltw, 6, 10);
+GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
+GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9);
+GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10);
GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
@@ -1255,7 +1270,7 @@ GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
#undef GEN_VXRFORM_DUAL
#undef GEN_VXRFORM1
#undef GEN_VXRFORM
-#undef GEN_VXFORM_SIMM
+#undef GEN_VXFORM_DUPI
#undef GEN_VXFORM_NOA
#undef GEN_VXFORM_UIMM
#undef GEN_VAFORM_PAIRED
diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c
index ed4fdce..e73197e 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -10,6 +10,11 @@ static inline void set_vsr(int n, TCGv_i64 src)
tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[n].u64[1]));
}
+static inline int vsr_full_offset(int n)
+{
+ return offsetof(CPUPPCState, vsr[n].u64[0]);
+}
+
static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
{
if (n < 32) {
@@ -1255,40 +1260,26 @@ static void gen_xxbrw(DisasContext *ctx)
tcg_temp_free_i64(xbl);
}
-#define VSX_LOGICAL(name, tcg_op) \
+#define VSX_LOGICAL(name, vece, tcg_op) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 t2; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- t2 = tcg_temp_new_i64(); \
- get_cpu_vsrh(t0, xA(ctx->opcode)); \
- get_cpu_vsrh(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrh(xT(ctx->opcode), t2); \
- get_cpu_vsrl(t0, xA(ctx->opcode)); \
- get_cpu_vsrl(t1, xB(ctx->opcode)); \
- tcg_op(t2, t0, t1); \
- set_cpu_vsrl(xT(ctx->opcode), t2); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
+ tcg_op(vece, vsr_full_offset(xT(ctx->opcode)), \
+ vsr_full_offset(xA(ctx->opcode)), \
+ vsr_full_offset(xB(ctx->opcode)), 16, 16); \
}
-VSX_LOGICAL(xxland, tcg_gen_and_i64)
-VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
-VSX_LOGICAL(xxlor, tcg_gen_or_i64)
-VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
-VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
-VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
-VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
-VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
+VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
+VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
+VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
+VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
+VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
+VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
+VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
+VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
#define VSX_XXMRG(name, high) \
static void glue(gen_, name)(DisasContext * ctx) \
@@ -1330,85 +1321,71 @@ static void glue(gen_, name)(DisasContext * ctx) \
VSX_XXMRG(xxmrghw, 1)
VSX_XXMRG(xxmrglw, 0)
-static void gen_xxsel(DisasContext * ctx)
+static void xxsel_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c)
{
- TCGv_i64 a, b, c, tmp;
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
- a = tcg_temp_new_i64();
- b = tcg_temp_new_i64();
- c = tcg_temp_new_i64();
- tmp = tcg_temp_new_i64();
-
- get_cpu_vsrh(a, xA(ctx->opcode));
- get_cpu_vsrh(b, xB(ctx->opcode));
- get_cpu_vsrh(c, xC(ctx->opcode));
-
tcg_gen_and_i64(b, b, c);
tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrh(xT(ctx->opcode), tmp);
-
- get_cpu_vsrl(a, xA(ctx->opcode));
- get_cpu_vsrl(b, xB(ctx->opcode));
- get_cpu_vsrl(c, xC(ctx->opcode));
-
- tcg_gen_and_i64(b, b, c);
- tcg_gen_andc_i64(a, a, c);
- tcg_gen_or_i64(tmp, a, b);
- set_cpu_vsrl(xT(ctx->opcode), tmp);
+ tcg_gen_or_i64(t, a, b);
+}
- tcg_temp_free_i64(a);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(c);
- tcg_temp_free_i64(tmp);
+static void xxsel_vec(unsigned vece, TCGv_vec t, TCGv_vec a,
+ TCGv_vec b, TCGv_vec c)
+{
+ tcg_gen_and_vec(vece, b, b, c);
+ tcg_gen_andc_vec(vece, a, a, c);
+ tcg_gen_or_vec(vece, t, a, b);
}
-static void gen_xxspltw(DisasContext *ctx)
+static void gen_xxsel(DisasContext *ctx)
{
- TCGv_i64 b, b2;
- TCGv_i64 vsr;
+ static const GVecGen4 g = {
+ .fni8 = xxsel_i64,
+ .fniv = xxsel_vec,
+ .vece = MO_64,
+ };
+ int rt = xT(ctx->opcode);
+ int ra = xA(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int rc = xC(ctx->opcode);
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
+ tcg_gen_gvec_4(vsr_full_offset(rt), vsr_full_offset(ra),
+ vsr_full_offset(rb), vsr_full_offset(rc), 16, 16, &g);
+}
- vsr = tcg_temp_new_i64();
- if (UIM(ctx->opcode) & 2) {
- get_cpu_vsrl(vsr, xB(ctx->opcode));
- } else {
- get_cpu_vsrh(vsr, xB(ctx->opcode));
- }
-
- b = tcg_temp_new_i64();
- b2 = tcg_temp_new_i64();
+static void gen_xxspltw(DisasContext *ctx)
+{
+ int rt = xT(ctx->opcode);
+ int rb = xB(ctx->opcode);
+ int uim = UIM(ctx->opcode);
+ int tofs, bofs;
- if (UIM(ctx->opcode) & 1) {
- tcg_gen_ext32u_i64(b, vsr);
- } else {
- tcg_gen_shri_i64(b, vsr, 32);
+ if (unlikely(!ctx->vsx_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VSXU);
+ return;
}
- tcg_gen_shli_i64(b2, b, 32);
- tcg_gen_or_i64(vsr, b, b2);
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
+ tofs = vsr_full_offset(rt);
+ bofs = vsr_full_offset(rb);
+ bofs += uim << MO_32;
+#ifndef HOST_WORDS_BIG_ENDIAN
+ bofs ^= 8 | 4;
+#endif
- tcg_temp_free_i64(vsr);
- tcg_temp_free_i64(b);
- tcg_temp_free_i64(b2);
+ tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
}
#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
static void gen_xxspltib(DisasContext *ctx)
{
- unsigned char uim8 = IMM8(ctx->opcode);
- TCGv_i64 vsr;
- if (xS(ctx->opcode) < 32) {
+ uint8_t uim8 = IMM8(ctx->opcode);
+ int rt = xT(ctx->opcode);
+
+ if (rt < 32) {
if (unlikely(!ctx->altivec_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VPU);
return;
@@ -1419,11 +1396,7 @@ static void gen_xxspltib(DisasContext *ctx)
return;
}
}
- vsr = tcg_temp_new_i64();
- tcg_gen_movi_i64(vsr, pattern(uim8));
- set_cpu_vsrh(xT(ctx->opcode), vsr);
- set_cpu_vsrl(xT(ctx->opcode), vsr);
- tcg_temp_free_i64(vsr);
+ tcg_gen_gvec_dup8i(vsr_full_offset(rt), 16, 16, uim8);
}
static void gen_xxsldwi(DisasContext *ctx)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index f393a40..d884906 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -602,10 +602,9 @@ static void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn)
static inline void vscr_init(CPUPPCState *env, uint32_t val)
{
- env->vscr = val;
/* Altivec always uses round-to-nearest */
set_float_rounding_mode(float_round_nearest_even, &env->vec_status);
- set_flush_to_zero(vscr_nj, &env->vec_status);
+ helper_mtvscr(env, val);
}
#ifdef CONFIG_USER_ONLY
@@ -8874,7 +8873,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300 | PPC2_PRCNTL;
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
@@ -8980,6 +8979,10 @@ static void init_ppc_proc(PowerPCCPU *cpu)
/* PowerPC implementation specific initialisations (SPRs, timers, ...) */
(*pcc->init_proc)(env);
+#if !defined(CONFIG_USER_ONLY)
+ ppc_gdb_gen_spr_xml(cpu);
+#endif
+
/* MSR bits & flags consistency checks */
if (env->msr_mask & (1 << 25)) {
switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
@@ -9476,6 +9479,55 @@ static bool avr_need_swap(CPUPPCState *env)
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static int gdb_find_spr_idx(CPUPPCState *env, int n)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
+ ppc_spr_t *spr = &env->spr_cb[i];
+
+ if (spr->name && spr->gdb_id == n) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ stn_p(mem_buf, len, env->spr[reg]);
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ return len;
+}
+
+static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+{
+ int reg;
+ int len;
+
+ reg = gdb_find_spr_idx(env, n);
+ if (reg < 0) {
+ return 0;
+ }
+
+ len = TARGET_LONG_SIZE;
+ ppc_maybe_bswap_register(env, mem_buf, len);
+ env->spr[reg] = ldn_p(mem_buf, len);
+
+ return len;
+}
+#endif
+
static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
@@ -9522,7 +9574,7 @@ static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 16;
}
if (n == 32) {
- stl_p(mem_buf, env->vscr);
+ stl_p(mem_buf, helper_mfvscr(env));
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@@ -9551,7 +9603,7 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
if (n == 32) {
ppc_maybe_bswap_register(env, mem_buf, 4);
- env->vscr = ldl_p(mem_buf);
+ helper_mtvscr(env, ldl_p(mem_buf));
return 4;
}
if (n == 33) {
@@ -9705,7 +9757,10 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp)
gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
32, "power-vsx.xml", 0);
}
-
+#ifndef CONFIG_USER_ONLY
+ gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
+ pcc->gdb_num_sprs, "power-spr.xml", 0);
+#endif
qemu_init_vcpu(cs);
pcc->parent_realize(dev, errp);
@@ -10468,7 +10523,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
#endif
cc->gdb_num_core_regs = 71;
-
+#ifndef CONFIG_USER_ONLY
+ cc->gdb_get_dynamic_xml = ppc_gdb_get_dynamic_xml;
+#endif
#ifdef USE_APPLE_GDB
cc->gdb_read_register = ppc_cpu_gdb_read_register_apple;
cc->gdb_write_register = ppc_cpu_gdb_write_register_apple;