aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-06-16 18:26:21 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-16 18:26:21 +0100
commitaf44da87e926ff64260b95f4350d338c4fc113ca (patch)
tree303a18d80e73641bb6e23218ac7b7df0666bcc6b /target-ppc
parentf27701510cdce9f76cdad0aaf9fb0bbcb23d299a (diff)
parent9dbae97723e964692364fb43012c6fa5448a661f (diff)
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-06-16 This pull request brings a lot of fun things. Among others we have - e500: u-boot firmware support - sPAPR: magic page enablement - sPAPR: add "compat" CPU option to support older guests - sPAPR: refactorings in preparation for VFIO - POWER8 live migration - mac99: expose bus frequency - little endian core dump, gdb and disas support - new ppc64le-linux-user target - DFP emulation - bug fixes # gpg: Signature made Mon 16 Jun 2014 12:28:32 BST using RSA key ID 03FEDC60 # gpg: Can't check signature: public key not found * remotes/agraf/tags/signed-ppc-for-upstream: (156 commits) spapr_pci: Advertise MSI quota PPC: KVM: Make pv hcall endian agnostic powerpc: use float64 for frsqrte spapr: Add kvm-type property spapr: Create SPAPRMachine struct linux-user: Tell guest about big host page sizes spapr_hcall: Add address-translation-mode-on-interrupt resource in H_SET_MODE spapr_hcall: Split h_set_mode() target-ppc: Enable DABRX SPR and limit it to <=POWER7 target-ppc: Enable PPR and VRSAVE SPRs migration target-ppc: Add POWER8's Event Based Branch (EBB) control SPRs KVM: target-ppc: Enable TM state migration target-ppc: Add POWER8's TM SPRs target-ppc: Add POWER8's MMCR2/MMCRS SPRs target-ppc: Enable FSCR facility check for TAR target-ppc: Add POWER8's FSCR SPR target-ppc: Add POWER8's TIR SPR target-ppc: Refactor class init for POWER7/8 target-ppc: Switch POWER7/8 classes to use correct PMU SPRs target-ppc: Make use of gen_spr_power5p_lpar() for POWER7/8 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/Makefile.objs1
-rw-r--r--target-ppc/arch_dump.c107
-rw-r--r--target-ppc/cpu-models.c46
-rw-r--r--target-ppc/cpu-models.h12
-rw-r--r--target-ppc/cpu-qom.h22
-rw-r--r--target-ppc/cpu.h163
-rw-r--r--target-ppc/dfp_helper.c1317
-rw-r--r--target-ppc/excp_helper.c12
-rw-r--r--target-ppc/fpu_helper.c3
-rw-r--r--target-ppc/gdbstub.c124
-rw-r--r--target-ppc/helper.h59
-rw-r--r--target-ppc/int_helper.c292
-rw-r--r--target-ppc/kvm.c111
-rw-r--r--target-ppc/kvm_ppc.h20
-rw-r--r--target-ppc/machine.c43
-rw-r--r--target-ppc/mem_helper.c26
-rw-r--r--target-ppc/misc_helper.c39
-rw-r--r--target-ppc/mmu_helper.c7
-rw-r--r--target-ppc/translate.c1283
-rw-r--r--target-ppc/translate_init.c1956
20 files changed, 4150 insertions, 1493 deletions
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 3cb23e0f11..a7ae392cc0 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -6,6 +6,7 @@ obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o
endif
obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
+obj-y += dfp_helper.o
obj-y += excp_helper.o
obj-y += fpu_helper.o
obj-y += int_helper.o
diff --git a/target-ppc/arch_dump.c b/target-ppc/arch_dump.c
index 9dccf1ae1f..5acafc68a4 100644
--- a/target-ppc/arch_dump.c
+++ b/target-ppc/arch_dump.c
@@ -79,94 +79,122 @@ typedef struct noteStruct {
} contents;
} QEMU_PACKED Note;
+typedef struct NoteFuncArg {
+ Note note;
+ DumpState *state;
+} NoteFuncArg;
-static void ppc64_write_elf64_prstatus(Note *note, PowerPCCPU *cpu)
+static void ppc64_write_elf64_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu)
{
int i;
uint64_t cr;
struct PPC64ElfPrstatus *prstatus;
struct PPC64UserRegStruct *reg;
+ Note *note = &arg->note;
+ DumpState *s = arg->state;
- note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
+ note->hdr.n_type = cpu_to_dump32(s, NT_PRSTATUS);
prstatus = &note->contents.prstatus;
memset(prstatus, 0, sizeof(*prstatus));
reg = &prstatus->pr_reg;
for (i = 0; i < 32; i++) {
- reg->gpr[i] = cpu_to_be64(cpu->env.gpr[i]);
+ reg->gpr[i] = cpu_to_dump64(s, cpu->env.gpr[i]);
}
- reg->nip = cpu_to_be64(cpu->env.nip);
- reg->msr = cpu_to_be64(cpu->env.msr);
- reg->ctr = cpu_to_be64(cpu->env.ctr);
- reg->link = cpu_to_be64(cpu->env.lr);
- reg->xer = cpu_to_be64(cpu_read_xer(&cpu->env));
+ reg->nip = cpu_to_dump64(s, cpu->env.nip);
+ reg->msr = cpu_to_dump64(s, cpu->env.msr);
+ reg->ctr = cpu_to_dump64(s, cpu->env.ctr);
+ reg->link = cpu_to_dump64(s, cpu->env.lr);
+ reg->xer = cpu_to_dump64(s, cpu_read_xer(&cpu->env));
cr = 0;
for (i = 0; i < 8; i++) {
cr |= (cpu->env.crf[i] & 15) << (4 * (7 - i));
}
- reg->ccr = cpu_to_be64(cr);
+ reg->ccr = cpu_to_dump64(s, cr);
}
-static void ppc64_write_elf64_fpregset(Note *note, PowerPCCPU *cpu)
+static void ppc64_write_elf64_fpregset(NoteFuncArg *arg, PowerPCCPU *cpu)
{
int i;
struct PPC64ElfFpregset *fpregset;
+ Note *note = &arg->note;
+ DumpState *s = arg->state;
- note->hdr.n_type = cpu_to_be32(NT_PRFPREG);
+ note->hdr.n_type = cpu_to_dump32(s, NT_PRFPREG);
fpregset = &note->contents.fpregset;
memset(fpregset, 0, sizeof(*fpregset));
for (i = 0; i < 32; i++) {
- fpregset->fpr[i] = cpu_to_be64(cpu->env.fpr[i]);
+ fpregset->fpr[i] = cpu_to_dump64(s, cpu->env.fpr[i]);
}
- fpregset->fpscr = cpu_to_be64(cpu->env.fpscr);
+ fpregset->fpscr = cpu_to_dump64(s, cpu->env.fpscr);
}
-static void ppc64_write_elf64_vmxregset(Note *note, PowerPCCPU *cpu)
+static void ppc64_write_elf64_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
{
int i;
struct PPC64ElfVmxregset *vmxregset;
+ Note *note = &arg->note;
+ DumpState *s = arg->state;
- note->hdr.n_type = cpu_to_be32(NT_PPC_VMX);
+ note->hdr.n_type = cpu_to_dump32(s, NT_PPC_VMX);
vmxregset = &note->contents.vmxregset;
memset(vmxregset, 0, sizeof(*vmxregset));
for (i = 0; i < 32; i++) {
- vmxregset->avr[i].u64[0] = cpu_to_be64(cpu->env.avr[i].u64[0]);
- vmxregset->avr[i].u64[1] = cpu_to_be64(cpu->env.avr[i].u64[1]);
+ bool needs_byteswap;
+
+#ifdef HOST_WORDS_BIGENDIAN
+ needs_byteswap = s->dump_info.d_endian == ELFDATA2LSB;
+#else
+ needs_byteswap = s->dump_info.d_endian == ELFDATA2MSB;
+#endif
+
+ if (needs_byteswap) {
+ vmxregset->avr[i].u64[0] = bswap64(cpu->env.avr[i].u64[1]);
+ vmxregset->avr[i].u64[1] = bswap64(cpu->env.avr[i].u64[0]);
+ } else {
+ vmxregset->avr[i].u64[0] = cpu->env.avr[i].u64[0];
+ vmxregset->avr[i].u64[1] = cpu->env.avr[i].u64[1];
+ }
}
- vmxregset->vscr.u32[3] = cpu_to_be32(cpu->env.vscr);
+ vmxregset->vscr.u32[3] = cpu_to_dump32(s, cpu->env.vscr);
}
-static void ppc64_write_elf64_vsxregset(Note *note, PowerPCCPU *cpu)
+static void ppc64_write_elf64_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
{
int i;
struct PPC64ElfVsxregset *vsxregset;
+ Note *note = &arg->note;
+ DumpState *s = arg->state;
- note->hdr.n_type = cpu_to_be32(NT_PPC_VSX);
+ note->hdr.n_type = cpu_to_dump32(s, NT_PPC_VSX);
vsxregset = &note->contents.vsxregset;
memset(vsxregset, 0, sizeof(*vsxregset));
for (i = 0; i < 32; i++) {
- vsxregset->vsr[i] = cpu_to_be64(cpu->env.vsr[i]);
+ vsxregset->vsr[i] = cpu_to_dump64(s, cpu->env.vsr[i]);
}
}
-static void ppc64_write_elf64_speregset(Note *note, PowerPCCPU *cpu)
+static void ppc64_write_elf64_speregset(NoteFuncArg *arg, PowerPCCPU *cpu)
{
struct PPC64ElfSperegset *speregset;
- note->hdr.n_type = cpu_to_be32(NT_PPC_SPE);
+ Note *note = &arg->note;
+ DumpState *s = arg->state;
+
+ note->hdr.n_type = cpu_to_dump32(s, NT_PPC_SPE);
speregset = &note->contents.speregset;
memset(speregset, 0, sizeof(*speregset));
- speregset->spe_acc = cpu_to_be64(cpu->env.spe_acc);
- speregset->spe_fscr = cpu_to_be32(cpu->env.spe_fscr);
+ speregset->spe_acc = cpu_to_dump64(s, cpu->env.spe_acc);
+ speregset->spe_fscr = cpu_to_dump32(s, cpu->env.spe_fscr);
}
static const struct NoteFuncDescStruct {
int contents_size;
- void (*note_contents_func)(Note *note, PowerPCCPU *cpu);
+ void (*note_contents_func)(NoteFuncArg *arg, PowerPCCPU *cpu);
} note_func[] = {
{sizeof(((Note *)0)->contents.prstatus), ppc64_write_elf64_prstatus},
{sizeof(((Note *)0)->contents.fpregset), ppc64_write_elf64_fpregset},
@@ -181,12 +209,16 @@ typedef struct NoteFuncDescStruct NoteFuncDesc;
int cpu_get_dump_info(ArchDumpInfo *info,
const struct GuestPhysBlockList *guest_phys_blocks)
{
- /*
- * Currently only handling PPC64 big endian.
- */
+ PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
info->d_machine = EM_PPC64;
- info->d_endian = ELFDATA2MSB;
info->d_class = ELFCLASS64;
+ if ((*pcc->interrupts_big_endian)(cpu)) {
+ info->d_endian = ELFDATA2MSB;
+ } else {
+ info->d_endian = ELFDATA2LSB;
+ }
return 0;
}
@@ -218,20 +250,21 @@ static int ppc64_write_all_elf64_notes(const char *note_name,
PowerPCCPU *cpu, int id,
void *opaque)
{
- Note note;
+ NoteFuncArg arg = { .state = opaque };
int ret = -1;
int note_size;
const NoteFuncDesc *nf;
for (nf = note_func; nf->note_contents_func; nf++) {
- note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
- note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
- strncpy(note.name, note_name, sizeof(note.name));
+ arg.note.hdr.n_namesz = cpu_to_dump32(opaque, sizeof(arg.note.name));
+ arg.note.hdr.n_descsz = cpu_to_dump32(opaque, nf->contents_size);
+ strncpy(arg.note.name, note_name, sizeof(arg.note.name));
- (*nf->note_contents_func)(&note, cpu);
+ (*nf->note_contents_func)(&arg, cpu);
- note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
- ret = f(&note, note_size, opaque);
+ note_size =
+ sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size;
+ ret = f(&arg.note, note_size, opaque);
if (ret < 0) {
return -1;
}
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index f6c9b3ab01..97a81d8660 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -671,20 +671,20 @@
POWERPC_DEF_SVR("MPC8379E", "MPC8379E",
CPU_POWERPC_MPC837x, POWERPC_SVR_8379E, e300)
/* e500 family */
- POWERPC_DEF("e500_v10", CPU_POWERPC_e500v1_v10, e500v1,
- "PowerPC e500 v1.0 core")
- POWERPC_DEF("e500_v20", CPU_POWERPC_e500v1_v20, e500v1,
- "PowerPC e500 v2.0 core")
- POWERPC_DEF("e500v2_v10", CPU_POWERPC_e500v2_v10, e500v2,
- "PowerPC e500v2 v1.0 core")
- POWERPC_DEF("e500v2_v20", CPU_POWERPC_e500v2_v20, e500v2,
- "PowerPC e500v2 v2.0 core")
- POWERPC_DEF("e500v2_v21", CPU_POWERPC_e500v2_v21, e500v2,
- "PowerPC e500v2 v2.1 core")
- POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2,
- "PowerPC e500v2 v2.2 core")
- POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2,
- "PowerPC e500v2 v3.0 core")
+ POWERPC_DEF_SVR("e500_v10", "PowerPC e500 v1.0 core",
+ CPU_POWERPC_e500v1_v10, POWERPC_SVR_E500, e500v1);
+ POWERPC_DEF_SVR("e500_v20", "PowerPC e500 v2.0 core",
+ CPU_POWERPC_e500v1_v20, POWERPC_SVR_E500, e500v1);
+ POWERPC_DEF_SVR("e500v2_v10", "PowerPC e500v2 v1.0 core",
+ CPU_POWERPC_e500v2_v10, POWERPC_SVR_E500, e500v2);
+ POWERPC_DEF_SVR("e500v2_v20", "PowerPC e500v2 v2.0 core",
+ CPU_POWERPC_e500v2_v20, POWERPC_SVR_E500, e500v2);
+ POWERPC_DEF_SVR("e500v2_v21", "PowerPC e500v2 v2.1 core",
+ CPU_POWERPC_e500v2_v21, POWERPC_SVR_E500, e500v2);
+ POWERPC_DEF_SVR("e500v2_v22", "PowerPC e500v2 v2.2 core",
+ CPU_POWERPC_e500v2_v22, POWERPC_SVR_E500, e500v2);
+ POWERPC_DEF_SVR("e500v2_v30", "PowerPC e500v2 v3.0 core",
+ CPU_POWERPC_e500v2_v30, POWERPC_SVR_E500, e500v2);
POWERPC_DEF_SVR("e500mc", "e500mc",
CPU_POWERPC_e500mc, POWERPC_SVR_E500, e500mc)
#ifdef TARGET_PPC64
@@ -1134,10 +1134,6 @@
POWERPC_DEF("POWER6A", CPU_POWERPC_POWER6A, POWER6,
"POWER6A")
#endif
- POWERPC_DEF("POWER7_v2.0", CPU_POWERPC_POWER7_v20, POWER7,
- "POWER7 v2.0")
- POWERPC_DEF("POWER7_v2.1", CPU_POWERPC_POWER7_v21, POWER7,
- "POWER7 v2.1")
POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7,
"POWER7 v2.3")
POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7P,
@@ -1146,19 +1142,19 @@
"POWER8 v1.0")
POWERPC_DEF("970", CPU_POWERPC_970, 970,
"PowerPC 970")
- POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970FX,
+ POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
"PowerPC 970FX v1.0 (G5)")
- POWERPC_DEF("970fx_v2.0", CPU_POWERPC_970FX_v20, 970FX,
+ POWERPC_DEF("970fx_v2.0", CPU_POWERPC_970FX_v20, 970,
"PowerPC 970FX v2.0 (G5)")
- POWERPC_DEF("970fx_v2.1", CPU_POWERPC_970FX_v21, 970FX,
+ POWERPC_DEF("970fx_v2.1", CPU_POWERPC_970FX_v21, 970,
"PowerPC 970FX v2.1 (G5)")
- POWERPC_DEF("970fx_v3.0", CPU_POWERPC_970FX_v30, 970FX,
+ POWERPC_DEF("970fx_v3.0", CPU_POWERPC_970FX_v30, 970,
"PowerPC 970FX v3.0 (G5)")
- POWERPC_DEF("970fx_v3.1", CPU_POWERPC_970FX_v31, 970FX,
+ POWERPC_DEF("970fx_v3.1", CPU_POWERPC_970FX_v31, 970,
"PowerPC 970FX v3.1 (G5)")
- POWERPC_DEF("970mp_v1.0", CPU_POWERPC_970MP_v10, 970MP,
+ POWERPC_DEF("970mp_v1.0", CPU_POWERPC_970MP_v10, 970,
"PowerPC 970MP v1.0")
- POWERPC_DEF("970mp_v1.1", CPU_POWERPC_970MP_v11, 970MP,
+ POWERPC_DEF("970mp_v1.1", CPU_POWERPC_970MP_v11, 970,
"PowerPC 970MP v1.1")
#if defined(TODO)
POWERPC_DEF("Cell", CPU_POWERPC_CELL, 970,
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index 644a126459..db75896012 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -555,8 +555,6 @@ enum {
CPU_POWERPC_POWER6A = 0x0F000002,
CPU_POWERPC_POWER7_BASE = 0x003F0000,
CPU_POWERPC_POWER7_MASK = 0xFFFF0000,
- CPU_POWERPC_POWER7_v20 = 0x003F0200,
- CPU_POWERPC_POWER7_v21 = 0x003F0201,
CPU_POWERPC_POWER7_v23 = 0x003F0203,
CPU_POWERPC_POWER7P_BASE = 0x004A0000,
CPU_POWERPC_POWER7P_MASK = 0xFFFF0000,
@@ -597,6 +595,16 @@ enum {
CPU_POWERPC_PA6T = 0x00900000,
};
+/* Logical PVR definitions for sPAPR */
+enum {
+ CPU_POWERPC_LOGICAL_2_04 = 0x0F000001,
+ CPU_POWERPC_LOGICAL_2_05 = 0x0F000002,
+ CPU_POWERPC_LOGICAL_2_06 = 0x0F000003,
+ CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003,
+ CPU_POWERPC_LOGICAL_2_07 = 0x0F000004,
+ CPU_POWERPC_LOGICAL_2_08 = 0x0F000005,
+};
+
/* System version register (used on MPC 8xxx) */
enum {
POWERPC_SVR_NONE = 0x00000000,
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 47dc8e6fdf..13c7031265 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -57,6 +57,7 @@ typedef struct PowerPCCPUClass {
uint32_t pvr;
uint32_t pvr_mask;
+ uint64_t pcr_mask;
uint32_t svr;
uint64_t insns_flags;
uint64_t insns_flags2;
@@ -76,12 +77,15 @@ typedef struct PowerPCCPUClass {
int (*handle_mmu_fault)(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
int mmu_idx);
#endif
+ bool (*interrupts_big_endian)(PowerPCCPU *cpu);
} PowerPCCPUClass;
/**
* PowerPCCPU:
* @env: #CPUPPCState
* @cpu_dt_id: CPU index used in the device tree. KVM uses this index too
+ * @max_compat: Maximal supported logical PVR from the command line
+ * @cpu_version: Current logical PVR, zero if in "raw" mode
*
* A PowerPC CPU.
*/
@@ -92,6 +96,8 @@ struct PowerPCCPU {
CPUPPCState env;
int cpu_dt_id;
+ uint32_t max_compat;
+ uint32_t cpu_version;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
@@ -120,6 +126,22 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
#ifndef CONFIG_USER_ONLY
extern const struct VMStateDescription vmstate_ppc_cpu;
+
+typedef struct PPCTimebase {
+ uint64_t guest_timebase;
+ int64_t time_of_the_day_ns;
+} PPCTimebase;
+
+extern const struct VMStateDescription vmstate_ppc_timebase;
+
+#define VMSTATE_PPC_TIMEBASE_V(_field, _state, _version) { \
+ .name = (stringify(_field)), \
+ .version_id = (_version), \
+ .size = sizeof(PPCTimebase), \
+ .vmsd = &vmstate_ppc_timebase, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, PPCTimebase), \
+}
#endif
#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 75ed5fa636..74407ee209 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -238,6 +238,7 @@ enum {
POWERPC_EXCP_DTLBE = 93, /* Data TLB error */
/* VSX Unavailable (Power ISA 2.06 and later) */
POWERPC_EXCP_VSXU = 94, /* VSX Unavailable */
+ POWERPC_EXCP_FU = 95, /* Facility Unavailable */
/* EOL */
POWERPC_EXCP_NB = 96,
/* QEMU exceptions: used internally during code translation */
@@ -426,6 +427,9 @@ struct ppc_slb_t {
#define MSR_TAG 62 /* Tag-active mode (POWERx ?) */
#define MSR_ISF 61 /* Sixty-four-bit interrupt mode on 630 */
#define MSR_SHV 60 /* hypervisor state hflags */
+#define MSR_TS0 34 /* Transactional state, 2 bits (Book3s) */
+#define MSR_TS1 33
+#define MSR_TM 32 /* Transactional Memory Available (Book3s) */
#define MSR_CM 31 /* Computation mode for BookE hflags */
#define MSR_ICM 30 /* Interrupt computation mode for BookE */
#define MSR_THV 29 /* hypervisor state for 32 bits PowerPC hflags */
@@ -463,6 +467,8 @@ struct ppc_slb_t {
#define MSR_LE 0 /* Little-endian mode 1 hflags */
#define LPCR_ILE (1 << (63-38))
+#define LPCR_AIL_SHIFT (63-40) /* Alternate interrupt location */
+#define LPCR_AIL (3 << LPCR_AIL_SHIFT)
#define msr_sf ((env->msr >> MSR_SF) & 1)
#define msr_isf ((env->msr >> MSR_ISF) & 1)
@@ -502,6 +508,9 @@ struct ppc_slb_t {
#define msr_pmm ((env->msr >> MSR_PMM) & 1)
#define msr_ri ((env->msr >> MSR_RI) & 1)
#define msr_le ((env->msr >> MSR_LE) & 1)
+#define msr_ts ((env->msr >> MSR_TS1) & 3)
+#define msr_tm ((env->msr >> MSR_TM) & 1)
+
/* Hypervisor bit is more specific */
#if defined(TARGET_PPC64)
#define MSR_HVB (1ULL << MSR_SHV)
@@ -516,6 +525,19 @@ struct ppc_slb_t {
#endif
#endif
+/* Facility Status and Control (FSCR) bits */
+#define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */
+#define FSCR_TAR (63 - 55) /* Target Address Register */
+/* Interrupt cause mask and position in FSCR. HFSCR has the same format */
+#define FSCR_IC_MASK (0xFFULL)
+#define FSCR_IC_POS (63 - 7)
+#define FSCR_IC_DSCR_SPR3 2
+#define FSCR_IC_PMU 3
+#define FSCR_IC_BHRB 4
+#define FSCR_IC_TM 5
+#define FSCR_IC_EBB 7
+#define FSCR_IC_TAR 8
+
/* Exception state register bits definition */
#define ESR_PIL (1 << (63 - 36)) /* Illegal Instruction */
#define ESR_PPR (1 << (63 - 37)) /* Privileged Instruction */
@@ -908,10 +930,8 @@ struct CPUPPCState {
*/
/* general purpose registers */
target_ulong gpr[32];
-#if !defined(TARGET_PPC64)
/* Storage for GPR MSB, used by the SPE extension */
target_ulong gprh[32];
-#endif
/* LR */
target_ulong lr;
/* CTR */
@@ -1081,6 +1101,20 @@ struct CPUPPCState {
*/
uint8_t fit_period[4];
uint8_t wdt_period[4];
+
+ /* Transactional memory state */
+ target_ulong tm_gpr[32];
+ ppc_avr_t tm_vsr[64];
+ uint64_t tm_cr;
+ uint64_t tm_lr;
+ uint64_t tm_ctr;
+ uint64_t tm_fpscr;
+ uint64_t tm_amr;
+ uint64_t tm_ppr;
+ uint64_t tm_vrsave;
+ uint32_t tm_vscr;
+ uint64_t tm_dscr;
+ uint64_t tm_tar;
};
#define SET_FIT_PERIOD(a_, b_, c_, d_) \
@@ -1104,6 +1138,7 @@ do { \
/*****************************************************************************/
PowerPCCPU *cpu_ppc_init(const char *cpu_model);
void ppc_translate_init(void);
+void gen_update_current_nip(void *opaque);
int cpu_ppc_exec (CPUPPCState *s);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
@@ -1122,6 +1157,8 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_msr (CPUPPCState *env, target_ulong value);
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
+int ppc_get_compat_smt_threads(PowerPCCPU *cpu);
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
@@ -1162,7 +1199,6 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
uint64_t gprv;
gprv = env->gpr[gprn];
-#if !defined(TARGET_PPC64)
if (env->flags & POWERPC_FLAG_SPE) {
/* If the CPU implements the SPE extension, we have to get the
* high bits of the GPR from the gprh storage area
@@ -1170,7 +1206,6 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
gprv &= 0xFFFFFFFFULL;
gprv |= (uint64_t)env->gprh[gprn] << 32;
}
-#endif
return gprv;
}
@@ -1258,6 +1293,10 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_MPC_EIE (0x050)
#define SPR_MPC_EID (0x051)
#define SPR_MPC_NRI (0x052)
+#define SPR_TFHAR (0x080)
+#define SPR_TFIAR (0x081)
+#define SPR_TEXASR (0x082)
+#define SPR_TEXASRU (0x083)
#define SPR_UCTRL (0x088)
#define SPR_MPC_CMPA (0x090)
#define SPR_MPC_CMPB (0x091)
@@ -1270,6 +1309,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_CTRL (0x098)
#define SPR_MPC_CMPE (0x098)
#define SPR_MPC_CMPF (0x099)
+#define SPR_FSCR (0x099)
#define SPR_MPC_CMPG (0x09A)
#define SPR_MPC_CMPH (0x09B)
#define SPR_MPC_LCTRL1 (0x09C)
@@ -1338,6 +1378,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_LPCR (0x13E)
#define SPR_BOOKE_DVC2 (0x13F)
#define SPR_BOOKE_TSR (0x150)
+#define SPR_PCR (0x152)
#define SPR_BOOKE_TCR (0x154)
#define SPR_BOOKE_TLB0PS (0x158)
#define SPR_BOOKE_TLB1PS (0x159)
@@ -1365,10 +1406,18 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_BOOKE_IVOR40 (0x1B2)
#define SPR_BOOKE_IVOR41 (0x1B3)
#define SPR_BOOKE_IVOR42 (0x1B4)
+#define SPR_BOOKE_GIVOR2 (0x1B8)
+#define SPR_BOOKE_GIVOR3 (0x1B9)
+#define SPR_BOOKE_GIVOR4 (0x1BA)
+#define SPR_BOOKE_GIVOR8 (0x1BB)
+#define SPR_BOOKE_GIVOR13 (0x1BC)
+#define SPR_BOOKE_GIVOR14 (0x1BD)
+#define SPR_TIR (0x1BE)
#define SPR_BOOKE_SPEFSCR (0x200)
#define SPR_Exxx_BBEAR (0x201)
#define SPR_Exxx_BBTAR (0x202)
#define SPR_Exxx_L1CFG0 (0x203)
+#define SPR_Exxx_L1CFG1 (0x204)
#define SPR_Exxx_NPIDR (0x205)
#define SPR_ATBL (0x20E)
#define SPR_ATBU (0x20F)
@@ -1453,62 +1502,96 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_MPC_MI_CTR (0x300)
#define SPR_PERF1 (0x301)
#define SPR_RCPU_MI_RBA1 (0x301)
+#define SPR_POWER_UMMCR2 (0x301)
#define SPR_PERF2 (0x302)
#define SPR_RCPU_MI_RBA2 (0x302)
#define SPR_MPC_MI_AP (0x302)
-#define SPR_MMCRA (0x302)
+#define SPR_POWER_UMMCRA (0x302)
#define SPR_PERF3 (0x303)
#define SPR_RCPU_MI_RBA3 (0x303)
#define SPR_MPC_MI_EPN (0x303)
+#define SPR_POWER_UPMC1 (0x303)
#define SPR_PERF4 (0x304)
+#define SPR_POWER_UPMC2 (0x304)
#define SPR_PERF5 (0x305)
#define SPR_MPC_MI_TWC (0x305)
+#define SPR_POWER_UPMC3 (0x305)
#define SPR_PERF6 (0x306)
#define SPR_MPC_MI_RPN (0x306)
+#define SPR_POWER_UPMC4 (0x306)
#define SPR_PERF7 (0x307)
+#define SPR_POWER_UPMC5 (0x307)
#define SPR_PERF8 (0x308)
#define SPR_RCPU_L2U_RBA0 (0x308)
#define SPR_MPC_MD_CTR (0x308)
+#define SPR_POWER_UPMC6 (0x308)
#define SPR_PERF9 (0x309)
#define SPR_RCPU_L2U_RBA1 (0x309)
#define SPR_MPC_MD_CASID (0x309)
+#define SPR_970_UPMC7 (0X309)
#define SPR_PERFA (0x30A)
#define SPR_RCPU_L2U_RBA2 (0x30A)
#define SPR_MPC_MD_AP (0x30A)
+#define SPR_970_UPMC8 (0X30A)
#define SPR_PERFB (0x30B)
#define SPR_RCPU_L2U_RBA3 (0x30B)
#define SPR_MPC_MD_EPN (0x30B)
+#define SPR_POWER_UMMCR0 (0X30B)
#define SPR_PERFC (0x30C)
#define SPR_MPC_MD_TWB (0x30C)
+#define SPR_POWER_USIAR (0X30C)
#define SPR_PERFD (0x30D)
#define SPR_MPC_MD_TWC (0x30D)
+#define SPR_POWER_USDAR (0X30D)
#define SPR_PERFE (0x30E)
#define SPR_MPC_MD_RPN (0x30E)
+#define SPR_POWER_UMMCR1 (0X30E)
#define SPR_PERFF (0x30F)
#define SPR_MPC_MD_TW (0x30F)
#define SPR_UPERF0 (0x310)
#define SPR_UPERF1 (0x311)
+#define SPR_POWER_MMCR2 (0x311)
#define SPR_UPERF2 (0x312)
+#define SPR_POWER_MMCRA (0X312)
#define SPR_UPERF3 (0x313)
+#define SPR_POWER_PMC1 (0X313)
#define SPR_UPERF4 (0x314)
+#define SPR_POWER_PMC2 (0X314)
#define SPR_UPERF5 (0x315)
+#define SPR_POWER_PMC3 (0X315)
#define SPR_UPERF6 (0x316)
+#define SPR_POWER_PMC4 (0X316)
#define SPR_UPERF7 (0x317)
+#define SPR_POWER_PMC5 (0X317)
#define SPR_UPERF8 (0x318)
+#define SPR_POWER_PMC6 (0X318)
#define SPR_UPERF9 (0x319)
+#define SPR_970_PMC7 (0X319)
#define SPR_UPERFA (0x31A)
+#define SPR_970_PMC8 (0X31A)
#define SPR_UPERFB (0x31B)
+#define SPR_POWER_MMCR0 (0X31B)
#define SPR_UPERFC (0x31C)
+#define SPR_POWER_SIAR (0X31C)
#define SPR_UPERFD (0x31D)
+#define SPR_POWER_SDAR (0X31D)
#define SPR_UPERFE (0x31E)
+#define SPR_POWER_MMCR1 (0X31E)
#define SPR_UPERFF (0x31F)
#define SPR_RCPU_MI_RA0 (0x320)
#define SPR_MPC_MI_DBCAM (0x320)
+#define SPR_BESCRS (0x320)
#define SPR_RCPU_MI_RA1 (0x321)
#define SPR_MPC_MI_DBRAM0 (0x321)
+#define SPR_BESCRSU (0x321)
#define SPR_RCPU_MI_RA2 (0x322)
#define SPR_MPC_MI_DBRAM1 (0x322)
+#define SPR_BESCRR (0x322)
#define SPR_RCPU_MI_RA3 (0x323)
+#define SPR_BESCRRU (0x323)
+#define SPR_EBBHR (0x324)
+#define SPR_EBBRR (0x325)
+#define SPR_BESCR (0x326)
#define SPR_RCPU_L2U_RA0 (0x328)
#define SPR_MPC_MD_DBCAM (0x328)
#define SPR_RCPU_L2U_RA1 (0x329)
@@ -1527,6 +1610,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_440_ITV3 (0x377)
#define SPR_440_CCR1 (0x378)
#define SPR_DCRIPR (0x37B)
+#define SPR_POWER_MMCRS (0x37E)
#define SPR_PPR (0x380)
#define SPR_750_GQR0 (0x390)
#define SPR_440_DNV0 (0x390)
@@ -1556,24 +1640,24 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_BOOKE_DCDBTRH (0x39D)
#define SPR_BOOKE_ICDBTRL (0x39E)
#define SPR_BOOKE_ICDBTRH (0x39F)
-#define SPR_UMMCR2 (0x3A0)
-#define SPR_UPMC5 (0x3A1)
-#define SPR_UPMC6 (0x3A2)
+#define SPR_74XX_UMMCR2 (0x3A0)
+#define SPR_7XX_UPMC5 (0x3A1)
+#define SPR_7XX_UPMC6 (0x3A2)
#define SPR_UBAMR (0x3A7)
-#define SPR_UMMCR0 (0x3A8)
-#define SPR_UPMC1 (0x3A9)
-#define SPR_UPMC2 (0x3AA)
-#define SPR_USIAR (0x3AB)
-#define SPR_UMMCR1 (0x3AC)
-#define SPR_UPMC3 (0x3AD)
-#define SPR_UPMC4 (0x3AE)
+#define SPR_7XX_UMMCR0 (0x3A8)
+#define SPR_7XX_UPMC1 (0x3A9)
+#define SPR_7XX_UPMC2 (0x3AA)
+#define SPR_7XX_USIAR (0x3AB)
+#define SPR_7XX_UMMCR1 (0x3AC)
+#define SPR_7XX_UPMC3 (0x3AD)
+#define SPR_7XX_UPMC4 (0x3AE)
#define SPR_USDA (0x3AF)
#define SPR_40x_ZPR (0x3B0)
#define SPR_BOOKE_MAS7 (0x3B0)
-#define SPR_MMCR2 (0x3B0)
-#define SPR_PMC5 (0x3B1)
+#define SPR_74XX_MMCR2 (0x3B0)
+#define SPR_7XX_PMC5 (0x3B1)
#define SPR_40x_PID (0x3B1)
-#define SPR_PMC6 (0x3B2)
+#define SPR_7XX_PMC6 (0x3B2)
#define SPR_440_MMUCR (0x3B2)
#define SPR_4xx_CCR0 (0x3B3)
#define SPR_BOOKE_EPLC (0x3B3)
@@ -1583,19 +1667,19 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_405_DVC1 (0x3B6)
#define SPR_405_DVC2 (0x3B7)
#define SPR_BAMR (0x3B7)
-#define SPR_MMCR0 (0x3B8)
-#define SPR_PMC1 (0x3B9)
+#define SPR_7XX_MMCR0 (0x3B8)
+#define SPR_7XX_PMC1 (0x3B9)
#define SPR_40x_SGR (0x3B9)
-#define SPR_PMC2 (0x3BA)
+#define SPR_7XX_PMC2 (0x3BA)
#define SPR_40x_DCWR (0x3BA)
-#define SPR_SIAR (0x3BB)
+#define SPR_7XX_SIAR (0x3BB)
#define SPR_405_SLER (0x3BB)
-#define SPR_MMCR1 (0x3BC)
+#define SPR_7XX_MMCR1 (0x3BC)
#define SPR_405_SU0R (0x3BC)
#define SPR_401_SKR (0x3BC)
-#define SPR_PMC3 (0x3BD)
+#define SPR_7XX_PMC3 (0x3BD)
#define SPR_405_DBCR1 (0x3BD)
-#define SPR_PMC4 (0x3BE)
+#define SPR_7XX_PMC4 (0x3BE)
#define SPR_SDA (0x3BF)
#define SPR_403_VTBL (0x3CC)
#define SPR_403_VTBU (0x3CD)
@@ -1648,6 +1732,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_750_TDCL (0x3F4)
#define SPR_40x_IAC1 (0x3F4)
#define SPR_MMUCSR0 (0x3F4)
+#define SPR_970_HID4 (0x3F4)
#define SPR_DABR (0x3F5)
#define DABR_MASK (~(target_ulong)0x7)
#define SPR_Exxx_BUCSR (0x3F5)
@@ -1709,6 +1794,23 @@ static inline int cpu_mmu_index (CPUPPCState *env)
/* External Input Interrupt Directed to Guest State */
#define EPCR_EXTGS (1 << 31)
+#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
+#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */
+#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
+#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
+#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
+
+#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */
+#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */
+#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
+#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
+#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
+
+/* HID0 bits */
+#define HID0_DEEPNAP (1 << 24)
+#define HID0_DOZE (1 << 23)
+#define HID0_NAP (1 << 22)
+
/*****************************************************************************/
/* PowerPC Instructions types definitions */
enum {
@@ -1910,7 +2012,7 @@ enum {
PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | \
PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | \
PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | \
- PPC2_ALTIVEC_207)
+ PPC2_ALTIVEC_207 | PPC2_ISA207S)
};
/*****************************************************************************/
@@ -2042,6 +2144,15 @@ enum {
PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */
};
+/* Processor Compatibility mask (PCR) */
+enum {
+ PCR_COMPAT_2_05 = 1ull << (63-62),
+ PCR_COMPAT_2_06 = 1ull << (63-61),
+ PCR_VEC_DIS = 1ull << (63-0), /* Vec. disable (bit NA since POWER8) */
+ PCR_VSX_DIS = 1ull << (63-1), /* VSX disable (bit NA since POWER8) */
+ PCR_TM_DIS = 1ull << (63-2), /* Trans. memory disable (POWER8) */
+};
+
/*****************************************************************************/
static inline target_ulong cpu_read_xer(CPUPPCState *env)
diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c
new file mode 100644
index 0000000000..773803a285
--- /dev/null
+++ b/target-ppc/dfp_helper.c
@@ -0,0 +1,1317 @@
+/*
+ * PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU.
+ *
+ * Copyright (c) 2014 IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "exec/helper-proto.h"
+
+#define DECNUMDIGITS 34
+#include "libdecnumber/decContext.h"
+#include "libdecnumber/decNumber.h"
+#include "libdecnumber/dpd/decimal32.h"
+#include "libdecnumber/dpd/decimal64.h"
+#include "libdecnumber/dpd/decimal128.h"
+
+#if defined(HOST_WORDS_BIGENDIAN)
+#define HI_IDX 0
+#define LO_IDX 1
+#else
+#define HI_IDX 1
+#define LO_IDX 0
+#endif
+
+struct PPC_DFP {
+ CPUPPCState *env;
+ uint64_t t64[2], a64[2], b64[2];
+ decNumber t, a, b;
+ decContext context;
+ uint8_t crbf;
+};
+
+static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr)
+{
+ enum rounding rnd;
+
+ switch ((fpscr >> 32) & 0x7) {
+ case 0:
+ rnd = DEC_ROUND_HALF_EVEN;
+ break;
+ case 1:
+ rnd = DEC_ROUND_DOWN;
+ break;
+ case 2:
+ rnd = DEC_ROUND_CEILING;
+ break;
+ case 3:
+ rnd = DEC_ROUND_FLOOR;
+ break;
+ case 4:
+ rnd = DEC_ROUND_HALF_UP;
+ break;
+ case 5:
+ rnd = DEC_ROUND_HALF_DOWN;
+ break;
+ case 6:
+ rnd = DEC_ROUND_UP;
+ break;
+ case 7:
+ rnd = DEC_ROUND_05UP;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ decContextSetRounding(context, rnd);
+}
+
+static void dfp_set_round_mode_from_immediate(uint8_t r, uint8_t rmc,
+ struct PPC_DFP *dfp)
+{
+ enum rounding rnd;
+ if (r == 0) {
+ switch (rmc & 3) {
+ case 0:
+ rnd = DEC_ROUND_HALF_EVEN;
+ break;
+ case 1:
+ rnd = DEC_ROUND_DOWN;
+ break;
+ case 2:
+ rnd = DEC_ROUND_HALF_UP;
+ break;
+ case 3: /* use FPSCR rounding mode */
+ return;
+ default:
+ assert(0); /* cannot get here */
+ }
+ } else { /* r == 1 */
+ switch (rmc & 3) {
+ case 0:
+ rnd = DEC_ROUND_CEILING;
+ break;
+ case 1:
+ rnd = DEC_ROUND_FLOOR;
+ break;
+ case 2:
+ rnd = DEC_ROUND_UP;
+ break;
+ case 3:
+ rnd = DEC_ROUND_HALF_DOWN;
+ break;
+ default:
+ assert(0); /* cannot get here */
+ }
+ }
+ decContextSetRounding(&dfp->context, rnd);
+}
+
+static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a,
+ uint64_t *b, CPUPPCState *env)
+{
+ decContextDefault(&dfp->context, DEC_INIT_DECIMAL64);
+ dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
+ dfp->env = env;
+
+ if (a) {
+ dfp->a64[0] = *a;
+ decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a);
+ } else {
+ dfp->a64[0] = 0;
+ decNumberZero(&dfp->a);
+ }
+
+ if (b) {
+ dfp->b64[0] = *b;
+ decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b);
+ } else {
+ dfp->b64[0] = 0;
+ decNumberZero(&dfp->b);
+ }
+}
+
+static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a,
+ uint64_t *b, CPUPPCState *env)
+{
+ decContextDefault(&dfp->context, DEC_INIT_DECIMAL128);
+ dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
+ dfp->env = env;
+
+ if (a) {
+ dfp->a64[0] = a[HI_IDX];
+ dfp->a64[1] = a[LO_IDX];
+ decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a);
+ } else {
+ dfp->a64[0] = dfp->a64[1] = 0;
+ decNumberZero(&dfp->a);
+ }
+
+ if (b) {
+ dfp->b64[0] = b[HI_IDX];
+ dfp->b64[1] = b[LO_IDX];
+ decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b);
+ } else {
+ dfp->b64[0] = dfp->b64[1] = 0;
+ decNumberZero(&dfp->b);
+ }
+}
+
+#define FP_FX (1ull << FPSCR_FX)
+#define FP_FEX (1ull << FPSCR_FEX)
+#define FP_OX (1ull << FPSCR_OX)
+#define FP_OE (1ull << FPSCR_OE)
+#define FP_UX (1ull << FPSCR_UX)
+#define FP_UE (1ull << FPSCR_UE)
+#define FP_XX (1ull << FPSCR_XX)
+#define FP_XE (1ull << FPSCR_XE)
+#define FP_ZX (1ull << FPSCR_ZX)
+#define FP_ZE (1ull << FPSCR_ZE)
+#define FP_VX (1ull << FPSCR_VX)
+#define FP_VXSNAN (1ull << FPSCR_VXSNAN)
+#define FP_VXISI (1ull << FPSCR_VXISI)
+#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
+#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
+#define FP_VXIDI (1ull << FPSCR_VXIDI)
+#define FP_VXVC (1ull << FPSCR_VXVC)
+#define FP_VXCVI (1ull << FPSCR_VXCVI)
+#define FP_VE (1ull << FPSCR_VE)
+#define FP_FI (1ull << FPSCR_FI)
+
+static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
+ uint64_t enabled)
+{
+ dfp->env->fpscr |= (flag | FP_FX);
+ if (dfp->env->fpscr & enabled) {
+ dfp->env->fpscr |= FP_FEX;
+ }
+}
+
+static void dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
+ decContext *context)
+{
+ uint64_t fprf = 0;
+
+ /* construct FPRF */
+ switch (decNumberClass(&dfp->t, context)) {
+ case DEC_CLASS_SNAN:
+ fprf = 0x01;
+ break;
+ case DEC_CLASS_QNAN:
+ fprf = 0x11;
+ break;
+ case DEC_CLASS_NEG_INF:
+ fprf = 0x09;
+ break;
+ case DEC_CLASS_NEG_NORMAL:
+ fprf = 0x08;
+ break;
+ case DEC_CLASS_NEG_SUBNORMAL:
+ fprf = 0x18;
+ break;
+ case DEC_CLASS_NEG_ZERO:
+ fprf = 0x12;
+ break;
+ case DEC_CLASS_POS_ZERO:
+ fprf = 0x02;
+ break;
+ case DEC_CLASS_POS_SUBNORMAL:
+ fprf = 0x14;
+ break;
+ case DEC_CLASS_POS_NORMAL:
+ fprf = 0x04;
+ break;
+ case DEC_CLASS_POS_INF:
+ fprf = 0x05;
+ break;
+ default:
+ assert(0); /* should never get here */
+ }
+ dfp->env->fpscr &= ~(0x1F << 12);
+ dfp->env->fpscr |= (fprf << 12);
+}
+
+static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
+}
+
+static void dfp_set_FPRF_from_FRT_short(struct PPC_DFP *dfp)
+{
+ decContext shortContext;
+ decContextDefault(&shortContext, DEC_INIT_DECIMAL32);
+ dfp_set_FPRF_from_FRT_with_context(dfp, &shortContext);
+}
+
+static void dfp_set_FPRF_from_FRT_long(struct PPC_DFP *dfp)
+{
+ decContext longContext;
+ decContextDefault(&longContext, DEC_INIT_DECIMAL64);
+ dfp_set_FPRF_from_FRT_with_context(dfp, &longContext);
+}
+
+static void dfp_check_for_OX(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Overflow) {
+ dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
+ }
+}
+
+static void dfp_check_for_UX(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Underflow) {
+ dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
+ }
+}
+
+static void dfp_check_for_XX(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Inexact) {
+ dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
+ }
+}
+
+static void dfp_check_for_ZX(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Division_by_zero) {
+ dfp_set_FPSCR_flag(dfp, FP_ZX, FP_ZE);
+ }
+}
+
+static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Invalid_operation) {
+ if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
+ }
+ }
+}
+
+static void dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP *dfp)
+{
+ if (decNumberIsSNaN(&dfp->t)) {
+ dfp->t.bits &= ~DECSNAN;
+ dfp->t.bits |= DECNAN;
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
+ }
+}
+
+static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
+{
+ if (dfp->context.status & DEC_Invalid_operation) {
+ if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
+ int same = decNumberClass(&dfp->a, &dfp->context) ==
+ decNumberClass(&dfp->b, &dfp->context);
+ if ((same && testForSameSign) || (!same && !testForSameSign)) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
+ }
+ }
+ }
+}
+
+static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
+{
+ dfp_check_for_VXISI(dfp, 0);
+}
+
+static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp)
+{
+ dfp_check_for_VXISI(dfp, 1);
+}
+
+static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Invalid_operation) {
+ if ((decNumberIsInfinite(&dfp->a) && decNumberIsZero(&dfp->b)) ||
+ (decNumberIsInfinite(&dfp->b) && decNumberIsZero(&dfp->a))) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIMZ, FP_VE);
+ }
+ }
+}
+
+static void dfp_check_for_VXZDZ(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Division_undefined) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXZDZ, FP_VE);
+ }
+}
+
+static void dfp_check_for_VXIDI(struct PPC_DFP *dfp)
+{
+ if (dfp->context.status & DEC_Invalid_operation) {
+ if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIDI, FP_VE);
+ }
+ }
+}
+
+static void dfp_check_for_VXVC(struct PPC_DFP *dfp)
+{
+ if (decNumberIsNaN(&dfp->a) || decNumberIsNaN(&dfp->b)) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXVC, FP_VE);
+ }
+}
+
+static void dfp_check_for_VXCVI(struct PPC_DFP *dfp)
+{
+ if ((dfp->context.status & DEC_Invalid_operation) &&
+ (!decNumberIsSNaN(&dfp->a)) &&
+ (!decNumberIsSNaN(&dfp->b))) {
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
+ }
+}
+
+static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp)
+{
+ if (decNumberIsNaN(&dfp->t)) {
+ dfp->crbf = 1;
+ } else if (decNumberIsZero(&dfp->t)) {
+ dfp->crbf = 2;
+ } else if (decNumberIsNegative(&dfp->t)) {
+ dfp->crbf = 8;
+ } else {
+ dfp->crbf = 4;
+ }
+}
+
+static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp)
+{
+ dfp->env->fpscr &= ~(0xF << 12);
+ dfp->env->fpscr |= (dfp->crbf << 12);
+}
+
+static inline void dfp_makeQNaN(decNumber *dn)
+{
+ dn->bits &= ~DECSPECIAL;
+ dn->bits |= DECNAN;
+}
+
+static inline int dfp_get_digit(decNumber *dn, int n)
+{
+ assert(DECDPUN == 3);
+ int unit = n / DECDPUN;
+ int dig = n % DECDPUN;
+ switch (dig) {
+ case 0:
+ return dn->lsu[unit] % 10;
+ case 1:
+ return (dn->lsu[unit] / 10) % 10;
+ case 2:
+ return dn->lsu[unit] / 100;
+ default:
+ assert(0);
+ }
+}
+
+#define DFP_HELPER_TAB(op, dnop, postprocs, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ dfp_prepare_decimal##size(&dfp, a, b, env); \
+ dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
+ postprocs(&dfp); \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+static void ADD_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_OX(dfp);
+ dfp_check_for_UX(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXISI_add(dfp);
+}
+
+DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64)
+DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128)
+
+static void SUB_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_OX(dfp);
+ dfp_check_for_UX(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXISI_subtract(dfp);
+}
+
+DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64)
+DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128)
+
+static void MUL_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_OX(dfp);
+ dfp_check_for_UX(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXIMZ(dfp);
+}
+
+DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64)
+DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128)
+
+static void DIV_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_OX(dfp);
+ dfp_check_for_UX(dfp);
+ dfp_check_for_ZX(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXZDZ(dfp);
+ dfp_check_for_VXIDI(dfp);
+}
+
+DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64)
+DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128)
+
+#define DFP_HELPER_BF_AB(op, dnop, postprocs, size) \
+uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ dfp_prepare_decimal##size(&dfp, a, b, env); \
+ dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
+ postprocs(&dfp); \
+ return dfp.crbf; \
+}
+
+static void CMPU_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_CRBF_from_T(dfp);
+ dfp_set_FPCC_from_CRBF(dfp);
+ dfp_check_for_VXSNAN(dfp);
+}
+
+DFP_HELPER_BF_AB(dcmpu, decNumberCompare, CMPU_PPs, 64)
+DFP_HELPER_BF_AB(dcmpuq, decNumberCompare, CMPU_PPs, 128)
+
+static void CMPO_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_CRBF_from_T(dfp);
+ dfp_set_FPCC_from_CRBF(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXVC(dfp);
+}
+
+DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64)
+DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128)
+
+#define DFP_HELPER_TSTDC(op, size) \
+uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \
+{ \
+ struct PPC_DFP dfp; \
+ int match = 0; \
+ \
+ dfp_prepare_decimal##size(&dfp, a, 0, env); \
+ \
+ match |= (dcm & 0x20) && decNumberIsZero(&dfp.a); \
+ match |= (dcm & 0x10) && decNumberIsSubnormal(&dfp.a, &dfp.context); \
+ match |= (dcm & 0x08) && decNumberIsNormal(&dfp.a, &dfp.context); \
+ match |= (dcm & 0x04) && decNumberIsInfinite(&dfp.a); \
+ match |= (dcm & 0x02) && decNumberIsQNaN(&dfp.a); \
+ match |= (dcm & 0x01) && decNumberIsSNaN(&dfp.a); \
+ \
+ if (decNumberIsNegative(&dfp.a)) { \
+ dfp.crbf = match ? 0xA : 0x8; \
+ } else { \
+ dfp.crbf = match ? 0x2 : 0x0; \
+ } \
+ \
+ dfp_set_FPCC_from_CRBF(&dfp); \
+ return dfp.crbf; \
+}
+
+DFP_HELPER_TSTDC(dtstdc, 64)
+DFP_HELPER_TSTDC(dtstdcq, 128)
+
+#define DFP_HELPER_TSTDG(op, size) \
+uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \
+{ \
+ struct PPC_DFP dfp; \
+ int minexp, maxexp, nzero_digits, nzero_idx, is_negative, is_zero, \
+ is_extreme_exp, is_subnormal, is_normal, leftmost_is_nonzero, \
+ match; \
+ \
+ dfp_prepare_decimal##size(&dfp, a, 0, env); \
+ \
+ if ((size) == 64) { \
+ minexp = -398; \
+ maxexp = 369; \
+ nzero_digits = 16; \
+ nzero_idx = 5; \
+ } else if ((size) == 128) { \
+ minexp = -6176; \
+ maxexp = 6111; \
+ nzero_digits = 34; \
+ nzero_idx = 11; \
+ } \
+ \
+ is_negative = decNumberIsNegative(&dfp.a); \
+ is_zero = decNumberIsZero(&dfp.a); \
+ is_extreme_exp = (dfp.a.exponent == maxexp) || \
+ (dfp.a.exponent == minexp); \
+ is_subnormal = decNumberIsSubnormal(&dfp.a, &dfp.context); \
+ is_normal = decNumberIsNormal(&dfp.a, &dfp.context); \
+ leftmost_is_nonzero = (dfp.a.digits == nzero_digits) && \
+ (dfp.a.lsu[nzero_idx] != 0); \
+ match = 0; \
+ \
+ match |= (dcm & 0x20) && is_zero && !is_extreme_exp; \
+ match |= (dcm & 0x10) && is_zero && is_extreme_exp; \
+ match |= (dcm & 0x08) && \
+ (is_subnormal || (is_normal && is_extreme_exp)); \
+ match |= (dcm & 0x04) && is_normal && !is_extreme_exp && \
+ !leftmost_is_nonzero; \
+ match |= (dcm & 0x02) && is_normal && !is_extreme_exp && \
+ leftmost_is_nonzero; \
+ match |= (dcm & 0x01) && decNumberIsSpecial(&dfp.a); \
+ \
+ if (is_negative) { \
+ dfp.crbf = match ? 0xA : 0x8; \
+ } else { \
+ dfp.crbf = match ? 0x2 : 0x0; \
+ } \
+ \
+ dfp_set_FPCC_from_CRBF(&dfp); \
+ return dfp.crbf; \
+}
+
+DFP_HELPER_TSTDG(dtstdg, 64)
+DFP_HELPER_TSTDG(dtstdgq, 128)
+
+#define DFP_HELPER_TSTEX(op, size) \
+uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ int expa, expb, a_is_special, b_is_special; \
+ \
+ dfp_prepare_decimal##size(&dfp, a, b, env); \
+ \
+ expa = dfp.a.exponent; \
+ expb = dfp.b.exponent; \
+ a_is_special = decNumberIsSpecial(&dfp.a); \
+ b_is_special = decNumberIsSpecial(&dfp.b); \
+ \
+ if (a_is_special || b_is_special) { \
+ int atype = a_is_special ? (decNumberIsNaN(&dfp.a) ? 4 : 2) : 1; \
+ int btype = b_is_special ? (decNumberIsNaN(&dfp.b) ? 4 : 2) : 1; \
+ dfp.crbf = (atype ^ btype) ? 0x1 : 0x2; \
+ } else if (expa < expb) { \
+ dfp.crbf = 0x8; \
+ } else if (expa > expb) { \
+ dfp.crbf = 0x4; \
+ } else { \
+ dfp.crbf = 0x2; \
+ } \
+ \
+ dfp_set_FPCC_from_CRBF(&dfp); \
+ return dfp.crbf; \
+}
+
+DFP_HELPER_TSTEX(dtstex, 64)
+DFP_HELPER_TSTEX(dtstexq, 128)
+
+#define DFP_HELPER_TSTSF(op, size) \
+uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ unsigned k; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ k = *a & 0x3F; \
+ \
+ if (unlikely(decNumberIsSpecial(&dfp.b))) { \
+ dfp.crbf = 1; \
+ } else if (k == 0) { \
+ dfp.crbf = 4; \
+ } else if (unlikely(decNumberIsZero(&dfp.b))) { \
+ /* Zero has no sig digits */ \
+ dfp.crbf = 4; \
+ } else { \
+ unsigned nsd = dfp.b.digits; \
+ if (k < nsd) { \
+ dfp.crbf = 8; \
+ } else if (k > nsd) { \
+ dfp.crbf = 4; \
+ } else { \
+ dfp.crbf = 2; \
+ } \
+ } \
+ \
+ dfp_set_FPCC_from_CRBF(&dfp); \
+ return dfp.crbf; \
+}
+
+DFP_HELPER_TSTSF(dtstsf, 64)
+DFP_HELPER_TSTSF(dtstsfq, 128)
+
+static void QUA_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+ dfp_check_for_VXCVI(dfp);
+}
+
+static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp)
+{
+ dfp_set_round_mode_from_immediate(0, rmc, dfp);
+ decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context);
+ if (decNumberIsSNaN(&dfp->a)) {
+ dfp->t = dfp->a;
+ dfp_makeQNaN(&dfp->t);
+ } else if (decNumberIsSNaN(&dfp->b)) {
+ dfp->t = dfp->b;
+ dfp_makeQNaN(&dfp->t);
+ } else if (decNumberIsQNaN(&dfp->a)) {
+ dfp->t = dfp->a;
+ } else if (decNumberIsQNaN(&dfp->b)) {
+ dfp->t = dfp->b;
+ }
+}
+
+#define DFP_HELPER_QUAI(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, \
+ uint32_t te, uint32_t rmc) \
+{ \
+ struct PPC_DFP dfp; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ decNumberFromUInt32(&dfp.a, 1); \
+ dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3); \
+ \
+ dfp_quantize(rmc, &dfp); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ QUA_PPs(&dfp); \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_QUAI(dquai, 64)
+DFP_HELPER_QUAI(dquaiq, 128)
+
+#define DFP_HELPER_QUA(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \
+ uint64_t *b, uint32_t rmc) \
+{ \
+ struct PPC_DFP dfp; \
+ \
+ dfp_prepare_decimal##size(&dfp, a, b, env); \
+ \
+ dfp_quantize(rmc, &dfp); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ QUA_PPs(&dfp); \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_QUA(dqua, 64)
+DFP_HELPER_QUA(dquaq, 128)
+
+static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax,
+ struct PPC_DFP *dfp)
+{
+ int msd_orig, msd_rslt;
+
+ if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) {
+ dfp->t = dfp->b;
+ if (decNumberIsSNaN(&dfp->b)) {
+ dfp_makeQNaN(&dfp->t);
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE);
+ }
+ return;
+ }
+
+ /* Reround is equivalent to quantizing b with 1**E(n) where */
+ /* n = exp(b) + numDigits(b) - reference_significance. */
+
+ decNumberFromUInt32(&dfp->a, 1);
+ dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig;
+
+ if (unlikely(dfp->a.exponent > xmax)) {
+ dfp->t.digits = 0;
+ dfp->t.bits &= ~DECNEG;
+ dfp_makeQNaN(&dfp->t);
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
+ return;
+ }
+
+ dfp_quantize(rmc, dfp);
+
+ msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1);
+ msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1);
+
+ /* If the quantization resulted in rounding up to the next magnitude, */
+ /* then we need to shift the significand and adjust the exponent. */
+
+ if (unlikely((msd_orig == 9) && (msd_rslt == 1))) {
+
+ decNumber negone;
+
+ decNumberFromInt32(&negone, -1);
+ decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context);
+ dfp->t.exponent++;
+
+ if (unlikely(dfp->t.exponent > xmax)) {
+ dfp_makeQNaN(&dfp->t);
+ dfp->t.digits = 0;
+ dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
+ /* Inhibit XX in this case */
+ decContextClearStatus(&dfp->context, DEC_Inexact);
+ }
+ }
+}
+
+#define DFP_HELPER_RRND(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \
+ uint64_t *b, uint32_t rmc) \
+{ \
+ struct PPC_DFP dfp; \
+ int32_t ref_sig = *a & 0x3F; \
+ int32_t xmax = ((size) == 64) ? 369 : 6111; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ _dfp_reround(rmc, ref_sig, xmax, &dfp); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ QUA_PPs(&dfp); \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_RRND(drrnd, 64)
+DFP_HELPER_RRND(drrndq, 128)
+
+#define DFP_HELPER_RINT(op, postprocs, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, \
+ uint32_t r, uint32_t rmc) \
+{ \
+ struct PPC_DFP dfp; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ dfp_set_round_mode_from_immediate(r, rmc, &dfp); \
+ decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
+ postprocs(&dfp); \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+static void RINTX_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_XX(dfp);
+ dfp_check_for_VXSNAN(dfp);
+}
+
+DFP_HELPER_RINT(drintx, RINTX_PPs, 64)
+DFP_HELPER_RINT(drintxq, RINTX_PPs, 128)
+
+static void RINTN_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_VXSNAN(dfp);
+}
+
+DFP_HELPER_RINT(drintn, RINTN_PPs, 64)
+DFP_HELPER_RINT(drintnq, RINTN_PPs, 128)
+
+void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b)
+{
+ struct PPC_DFP dfp;
+ uint32_t b_short = *b;
+ dfp_prepare_decimal64(&dfp, 0, 0, env);
+ decimal32ToNumber((decimal32 *)&b_short, &dfp.t);
+ decimal64FromNumber((decimal64 *)t, &dfp.t, &dfp.context);
+ dfp_set_FPRF_from_FRT(&dfp);
+}
+
+void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
+{
+ struct PPC_DFP dfp;
+ dfp_prepare_decimal128(&dfp, 0, 0, env);
+ decimal64ToNumber((decimal64 *)b, &dfp.t);
+
+ dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
+ dfp_set_FPRF_from_FRT(&dfp);
+
+ decimal128FromNumber((decimal128 *)&dfp.t64, &dfp.t, &dfp.context);
+ t[0] = dfp.t64[HI_IDX];
+ t[1] = dfp.t64[LO_IDX];
+}
+
+void helper_drsp(CPUPPCState *env, uint64_t *t, uint64_t *b)
+{
+ struct PPC_DFP dfp;
+ uint32_t t_short = 0;
+ dfp_prepare_decimal64(&dfp, 0, b, env);
+ decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context);
+ decimal32ToNumber((decimal32 *)&t_short, &dfp.t);
+
+ dfp_set_FPRF_from_FRT_short(&dfp);
+ dfp_check_for_OX(&dfp);
+ dfp_check_for_UX(&dfp);
+ dfp_check_for_XX(&dfp);
+
+ *t = t_short;
+}
+
+void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
+{
+ struct PPC_DFP dfp;
+ dfp_prepare_decimal128(&dfp, 0, b, env);
+ decimal64FromNumber((decimal64 *)&dfp.t64, &dfp.b, &dfp.context);
+ decimal64ToNumber((decimal64 *)&dfp.t64, &dfp.t);
+
+ dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
+ dfp_set_FPRF_from_FRT_long(&dfp);
+ dfp_check_for_OX(&dfp);
+ dfp_check_for_UX(&dfp);
+ dfp_check_for_XX(&dfp);
+
+ decimal64FromNumber((decimal64 *)dfp.t64, &dfp.t, &dfp.context);
+ t[0] = dfp.t64[0];
+ t[1] = 0;
+}
+
+#define DFP_HELPER_CFFIX(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ decNumberFromInt64(&dfp.t, (int64_t)(*b)); \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
+ CFFIX_PPs(&dfp); \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+static void CFFIX_PPs(struct PPC_DFP *dfp)
+{
+ dfp_set_FPRF_from_FRT(dfp);
+ dfp_check_for_XX(dfp);
+}
+
+DFP_HELPER_CFFIX(dcffix, 64)
+DFP_HELPER_CFFIX(dcffixq, 128)
+
+#define DFP_HELPER_CTFIX(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ if (unlikely(decNumberIsSpecial(&dfp.b))) { \
+ uint64_t invalid_flags = FP_VX | FP_VXCVI; \
+ if (decNumberIsInfinite(&dfp.b)) { \
+ dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
+ } else { /* NaN */ \
+ dfp.t64[0] = INT64_MIN; \
+ if (decNumberIsSNaN(&dfp.b)) { \
+ invalid_flags |= FP_VXSNAN; \
+ } \
+ } \
+ dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE); \
+ } else if (unlikely(decNumberIsZero(&dfp.b))) { \
+ dfp.t64[0] = 0; \
+ } else { \
+ decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context); \
+ dfp.t64[0] = decNumberIntegralToInt64(&dfp.b, &dfp.context); \
+ if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) { \
+ dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
+ dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE); \
+ } else { \
+ dfp_check_for_XX(&dfp); \
+ } \
+ } \
+ \
+ *t = dfp.t64[0]; \
+}
+
+DFP_HELPER_CTFIX(dctfix, 64)
+DFP_HELPER_CTFIX(dctfixq, 128)
+
+static inline void dfp_set_bcd_digit_64(uint64_t *t, uint8_t digit,
+ unsigned n)
+{
+ *t |= ((uint64_t)(digit & 0xF) << (n << 2));
+}
+
+static inline void dfp_set_bcd_digit_128(uint64_t *t, uint8_t digit,
+ unsigned n)
+{
+ t[(n & 0x10) ? HI_IDX : LO_IDX] |=
+ ((uint64_t)(digit & 0xF) << ((n & 15) << 2));
+}
+
+static inline void dfp_set_sign_64(uint64_t *t, uint8_t sgn)
+{
+ *t <<= 4;
+ *t |= (sgn & 0xF);
+}
+
+static inline void dfp_set_sign_128(uint64_t *t, uint8_t sgn)
+{
+ t[HI_IDX] <<= 4;
+ t[HI_IDX] |= (t[LO_IDX] >> 60);
+ t[LO_IDX] <<= 4;
+ t[LO_IDX] |= (sgn & 0xF);
+}
+
+#define DFP_HELPER_DEDPD(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \
+{ \
+ struct PPC_DFP dfp; \
+ uint8_t digits[34]; \
+ int i, N; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ decNumberGetBCD(&dfp.b, digits); \
+ dfp.t64[0] = dfp.t64[1] = 0; \
+ N = dfp.b.digits; \
+ \
+ for (i = 0; (i < N) && (i < (size)/4); i++) { \
+ dfp_set_bcd_digit_##size(dfp.t64, digits[N-i-1], i); \
+ } \
+ \
+ if (sp & 2) { \
+ uint8_t sgn; \
+ \
+ if (decNumberIsNegative(&dfp.b)) { \
+ sgn = 0xD; \
+ } else { \
+ sgn = ((sp & 1) ? 0xF : 0xC); \
+ } \
+ dfp_set_sign_##size(dfp.t64, sgn); \
+ } \
+ \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_DEDPD(ddedpd, 64)
+DFP_HELPER_DEDPD(ddedpdq, 128)
+
+static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n)
+{
+ return *t >> ((n << 2) & 63) & 15;
+}
+
+static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n)
+{
+ return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15;
+}
+
+#define DFP_HELPER_ENBCD(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s) \
+{ \
+ struct PPC_DFP dfp; \
+ uint8_t digits[32]; \
+ int n = 0, offset = 0, sgn = 0, nonzero = 0; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ decNumberZero(&dfp.t); \
+ \
+ if (s) { \
+ uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
+ switch (sgnNibble) { \
+ case 0xD: \
+ case 0xB: \
+ sgn = 1; \
+ break; \
+ case 0xC: \
+ case 0xF: \
+ case 0xA: \
+ case 0xE: \
+ sgn = 0; \
+ break; \
+ default: \
+ dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
+ return; \
+ } \
+ } \
+ \
+ while (offset < (size)/4) { \
+ n++; \
+ digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
+ if (digits[(size)/4-n] > 10) { \
+ dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
+ return; \
+ } else { \
+ nonzero |= (digits[(size)/4-n] > 0); \
+ } \
+ } \
+ \
+ if (nonzero) { \
+ decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n); \
+ } \
+ \
+ if (s && sgn) { \
+ dfp.t.bits |= DECNEG; \
+ } \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ dfp_set_FPRF_from_FRT(&dfp); \
+ if ((size) == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if ((size) == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_ENBCD(denbcd, 64)
+DFP_HELPER_ENBCD(denbcdq, 128)
+
+#define DFP_HELPER_XEX(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ if (unlikely(decNumberIsSpecial(&dfp.b))) { \
+ if (decNumberIsInfinite(&dfp.b)) { \
+ *t = -1; \
+ } else if (decNumberIsSNaN(&dfp.b)) { \
+ *t = -3; \
+ } else if (decNumberIsQNaN(&dfp.b)) { \
+ *t = -2; \
+ } else { \
+ assert(0); \
+ } \
+ } else { \
+ if ((size) == 64) { \
+ *t = dfp.b.exponent + 398; \
+ } else if ((size) == 128) { \
+ *t = dfp.b.exponent + 6176; \
+ } else { \
+ assert(0); \
+ } \
+ } \
+}
+
+DFP_HELPER_XEX(dxex, 64)
+DFP_HELPER_XEX(dxexq, 128)
+
+static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw)
+{
+ *t &= 0x8003ffffffffffffULL;
+ *t |= (raw << (63-13));
+}
+
+static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw)
+{
+ t[HI_IDX] &= 0x80003fffffffffffULL;
+ t[HI_IDX] |= (raw << (63-17));
+}
+
+#define DFP_HELPER_IEX(op, size) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
+{ \
+ struct PPC_DFP dfp; \
+ uint64_t raw_qnan, raw_snan, raw_inf, max_exp; \
+ int bias; \
+ int64_t exp = *((int64_t *)a); \
+ \
+ dfp_prepare_decimal##size(&dfp, 0, b, env); \
+ \
+ if ((size) == 64) { \
+ max_exp = 767; \
+ raw_qnan = 0x1F00; \
+ raw_snan = 0x1F80; \
+ raw_inf = 0x1E00; \
+ bias = 398; \
+ } else if ((size) == 128) { \
+ max_exp = 12287; \
+ raw_qnan = 0x1f000; \
+ raw_snan = 0x1f800; \
+ raw_inf = 0x1e000; \
+ bias = 6176; \
+ } else { \
+ assert(0); \
+ } \
+ \
+ if (unlikely((exp < 0) || (exp > max_exp))) { \
+ dfp.t64[0] = dfp.b64[0]; \
+ dfp.t64[1] = dfp.b64[1]; \
+ if (exp == -1) { \
+ dfp_set_raw_exp_##size(dfp.t64, raw_inf); \
+ } else if (exp == -3) { \
+ dfp_set_raw_exp_##size(dfp.t64, raw_snan); \
+ } else { \
+ dfp_set_raw_exp_##size(dfp.t64, raw_qnan); \
+ } \
+ } else { \
+ dfp.t = dfp.b; \
+ if (unlikely(decNumberIsSpecial(&dfp.t))) { \
+ dfp.t.bits &= ~DECSPECIAL; \
+ } \
+ dfp.t.exponent = exp - bias; \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ } \
+ if (size == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else if (size == 128) { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_IEX(diex, 64)
+DFP_HELPER_IEX(diexq, 128)
+
+static void dfp_clear_lmd_from_g5msb(uint64_t *t)
+{
+
+ /* The most significant 5 bits of the PowerPC DFP format combine bits */
+ /* from the left-most decimal digit (LMD) and the biased exponent. */
+ /* This routine clears the LMD bits while preserving the exponent */
+ /* bits. See "Figure 80: Encoding of bits 0:4 of the G field for */
+ /* Finite Numbers" in the Power ISA for additional details. */
+
+ uint64_t g5msb = (*t >> 58) & 0x1F;
+
+ if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
+ *t &= ~(7ULL << 58);
+ } else {
+ switch (g5msb & 7) {
+ case 0:
+ case 1:
+ g5msb = 0;
+ break;
+ case 2:
+ case 3:
+ g5msb = 0x8;
+ break;
+ case 4:
+ case 5:
+ g5msb = 0x10;
+ break;
+ case 6:
+ g5msb = 0x1E;
+ break;
+ case 7:
+ g5msb = 0x1F;
+ break;
+ }
+
+ *t &= ~(0x1fULL << 58);
+ *t |= (g5msb << 58);
+ }
+}
+
+#define DFP_HELPER_SHIFT(op, size, shift_left) \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \
+ uint32_t sh) \
+{ \
+ struct PPC_DFP dfp; \
+ unsigned max_digits = ((size) == 64) ? 16 : 34; \
+ \
+ dfp_prepare_decimal##size(&dfp, a, 0, env); \
+ \
+ if (sh <= max_digits) { \
+ \
+ decNumber shd; \
+ unsigned special = dfp.a.bits & DECSPECIAL; \
+ \
+ if (shift_left) { \
+ decNumberFromUInt32(&shd, sh); \
+ } else { \
+ decNumberFromInt32(&shd, -((int32_t)sh)); \
+ } \
+ \
+ dfp.a.bits &= ~DECSPECIAL; \
+ decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context); \
+ \
+ dfp.t.bits |= special; \
+ if (special && (dfp.t.digits >= max_digits)) { \
+ dfp.t.digits = max_digits - 1; \
+ } \
+ \
+ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
+ &dfp.context); \
+ } else { \
+ if ((size) == 64) { \
+ dfp.t64[0] = dfp.a64[0] & 0xFFFC000000000000ULL; \
+ dfp_clear_lmd_from_g5msb(dfp.t64); \
+ } else { \
+ dfp.t64[HI_IDX] = dfp.a64[HI_IDX] & \
+ 0xFFFFC00000000000ULL; \
+ dfp_clear_lmd_from_g5msb(dfp.t64 + HI_IDX); \
+ dfp.t64[LO_IDX] = 0; \
+ } \
+ } \
+ \
+ if ((size) == 64) { \
+ t[0] = dfp.t64[0]; \
+ } else { \
+ t[0] = dfp.t64[HI_IDX]; \
+ t[1] = dfp.t64[LO_IDX]; \
+ } \
+}
+
+DFP_HELPER_SHIFT(dscli, 64, 1)
+DFP_HELPER_SHIFT(dscliq, 128, 1)
+DFP_HELPER_SHIFT(dscri, 64, 0)
+DFP_HELPER_SHIFT(dscriq, 128, 0)
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 7dfc52d159..be7159013f 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -399,6 +399,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
new_msr |= (target_ulong)MSR_HVB;
}
goto store_current;
+ case POWERPC_EXCP_FU: /* Facility unavailable exception */
+ if (lpes1 == 0) {
+ new_msr |= (target_ulong)MSR_HVB;
+ }
+ goto store_current;
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
LOG_EXCP("PIT exception\n");
goto store_next;
@@ -615,8 +620,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
if (asrr1 != -1) {
env->spr[asrr1] = env->spr[srr1];
}
- /* If we disactivated any translation, flush TLBs */
- if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
+
+ if (env->spr[SPR_LPCR] & LPCR_AIL) {
+ new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
+ } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
+ /* If we disactivated any translation, flush TLBs */
tlb_flush(cs, 1);
}
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index cd8f015bd7..da93d1215a 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -977,7 +977,6 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
{
CPU_DoubleU farg;
- float32 f32;
farg.ll = arg;
@@ -991,8 +990,6 @@ uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
}
farg.d = float64_sqrt(farg.d, &env->fp_status);
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
}
return farg.ll;
}
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c
index 1c910902ea..381a3c7e31 100644
--- a/target-ppc/gdbstub.c
+++ b/target-ppc/gdbstub.c
@@ -21,6 +21,55 @@
#include "qemu-common.h"
#include "exec/gdbstub.h"
+static int ppc_gdb_register_len(int n)
+{
+ switch (n) {
+ case 0 ... 31:
+ /* gprs */
+ return sizeof(target_ulong);
+ case 32 ... 63:
+ /* fprs */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return 8;
+ case 66:
+ /* cr */
+ return 4;
+ case 64:
+ /* nip */
+ case 65:
+ /* msr */
+ case 67:
+ /* lr */
+ case 68:
+ /* ctr */
+ case 69:
+ /* xer */
+ return sizeof(target_ulong);
+ case 70:
+ /* fpscr */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return sizeof(target_ulong);
+ default:
+ return 0;
+ }
+}
+
+
+static void ppc_gdb_swap_register(uint8_t *mem_buf, int n, int len)
+{
+ if (len == 4) {
+ bswap32s((uint32_t *)mem_buf);
+ } else if (len == 8) {
+ bswap64s((uint64_t *)mem_buf);
+ } else {
+ g_assert_not_reached();
+ }
+}
+
/* Old gdb always expects FP registers. Newer (xml-aware) gdb only
* expects whatever the target description contains. Due to a
* historical mishap the FP registers appear in between core integer
@@ -32,23 +81,26 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
+ int r = ppc_gdb_register_len(n);
+
+ if (!r) {
+ return r;
+ }
if (n < 32) {
/* gprs */
- return gdb_get_regl(mem_buf, env->gpr[n]);
+ gdb_get_regl(mem_buf, env->gpr[n]);
} else if (n < 64) {
/* fprs */
- if (gdb_has_xml) {
- return 0;
- }
stfq_p(mem_buf, env->fpr[n-32]);
- return 8;
} else {
switch (n) {
case 64:
- return gdb_get_regl(mem_buf, env->nip);
+ gdb_get_regl(mem_buf, env->nip);
+ break;
case 65:
- return gdb_get_regl(mem_buf, env->msr);
+ gdb_get_regl(mem_buf, env->msr);
+ break;
case 66:
{
uint32_t cr = 0;
@@ -56,50 +108,57 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
cr |= env->crf[i] << (32 - ((i + 1) * 4));
}
- return gdb_get_reg32(mem_buf, cr);
+ gdb_get_reg32(mem_buf, cr);
+ break;
}
case 67:
- return gdb_get_regl(mem_buf, env->lr);
+ gdb_get_regl(mem_buf, env->lr);
+ break;
case 68:
- return gdb_get_regl(mem_buf, env->ctr);
+ gdb_get_regl(mem_buf, env->ctr);
+ break;
case 69:
- return gdb_get_regl(mem_buf, env->xer);
+ gdb_get_regl(mem_buf, env->xer);
+ break;
case 70:
- {
- if (gdb_has_xml) {
- return 0;
- }
- return gdb_get_reg32(mem_buf, env->fpscr);
- }
+ gdb_get_reg32(mem_buf, env->fpscr);
+ break;
}
}
- return 0;
+ if (msr_le) {
+ /* If cpu is in LE mode, convert memory contents to LE. */
+ ppc_gdb_swap_register(mem_buf, n, r);
+ }
+ return r;
}
int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
+ int r = ppc_gdb_register_len(n);
+ if (!r) {
+ return r;
+ }
+ if (msr_le) {
+ /* If cpu is in LE mode, convert memory contents to LE. */
+ ppc_gdb_swap_register(mem_buf, n, r);
+ }
if (n < 32) {
/* gprs */
env->gpr[n] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
} else if (n < 64) {
/* fprs */
- if (gdb_has_xml) {
- return 0;
- }
env->fpr[n-32] = ldfq_p(mem_buf);
- return 8;
} else {
switch (n) {
case 64:
env->nip = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ break;
case 65:
ppc_store_msr(env, ldtul_p(mem_buf));
- return sizeof(target_ulong);
+ break;
case 66:
{
uint32_t cr = ldl_p(mem_buf);
@@ -107,25 +166,22 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
}
- return 4;
+ break;
}
case 67:
env->lr = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ break;
case 68:
env->ctr = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ break;
case 69:
env->xer = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ break;
case 70:
/* fpscr */
- if (gdb_has_xml) {
- return 0;
- }
store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
- return sizeof(target_ulong);
+ break;
}
}
- return 0;
+ return r;
}
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 08f3916e74..509eae52ff 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -539,7 +539,7 @@ DEF_HELPER_2(booke206_tlbivax, void, env, tl)
DEF_HELPER_2(booke206_tlbilx0, void, env, tl)
DEF_HELPER_2(booke206_tlbilx1, void, env, tl)
DEF_HELPER_2(booke206_tlbilx3, void, env, tl)
-DEF_HELPER_2(booke206_tlbflush, void, env, i32)
+DEF_HELPER_2(booke206_tlbflush, void, env, tl)
DEF_HELPER_3(booke_setpid, void, env, i32, tl)
DEF_HELPER_2(6xx_tlbd, void, env, tl)
DEF_HELPER_2(6xx_tlbi, void, env, tl)
@@ -577,6 +577,8 @@ DEF_HELPER_3(store_dcr, void, env, tl, tl)
DEF_HELPER_2(load_dump_spr, void, env, i32)
DEF_HELPER_2(store_dump_spr, void, env, i32)
+DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32)
+DEF_HELPER_4(msr_facility_check, void, env, i32, i32, i32)
DEF_HELPER_1(load_tbl, tl, env)
DEF_HELPER_1(load_tbu, tl, env)
DEF_HELPER_1(load_atbl, tl, env)
@@ -611,3 +613,58 @@ DEF_HELPER_3(store_dbatu, void, env, i32, tl)
DEF_HELPER_3(store_601_batl, void, env, i32, tl)
DEF_HELPER_3(store_601_batu, void, env, i32, tl)
#endif
+
+#define dh_alias_fprp ptr
+#define dh_ctype_fprp uint64_t *
+#define dh_is_signed_fprp dh_is_signed_ptr
+
+DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(dsub, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(dsubq, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(dmul, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(dmulq, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(ddiv, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(ddivq, void, env, fprp, fprp, fprp)
+DEF_HELPER_3(dcmpo, i32, env, fprp, fprp)
+DEF_HELPER_3(dcmpoq, i32, env, fprp, fprp)
+DEF_HELPER_3(dcmpu, i32, env, fprp, fprp)
+DEF_HELPER_3(dcmpuq, i32, env, fprp, fprp)
+DEF_HELPER_3(dtstdc, i32, env, fprp, i32)
+DEF_HELPER_3(dtstdcq, i32, env, fprp, i32)
+DEF_HELPER_3(dtstdg, i32, env, fprp, i32)
+DEF_HELPER_3(dtstdgq, i32, env, fprp, i32)
+DEF_HELPER_3(dtstex, i32, env, fprp, fprp)
+DEF_HELPER_3(dtstexq, i32, env, fprp, fprp)
+DEF_HELPER_3(dtstsf, i32, env, fprp, fprp)
+DEF_HELPER_3(dtstsfq, i32, env, fprp, fprp)
+DEF_HELPER_5(dquai, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_5(dquaiq, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_5(dqua, void, env, fprp, fprp, fprp, i32)
+DEF_HELPER_5(dquaq, void, env, fprp, fprp, fprp, i32)
+DEF_HELPER_5(drrnd, void, env, fprp, fprp, fprp, i32)
+DEF_HELPER_5(drrndq, void, env, fprp, fprp, fprp, i32)
+DEF_HELPER_5(drintx, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_5(drintxq, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_5(drintn, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_5(drintnq, void, env, fprp, fprp, i32, i32)
+DEF_HELPER_3(dctdp, void, env, fprp, fprp)
+DEF_HELPER_3(dctqpq, void, env, fprp, fprp)
+DEF_HELPER_3(drsp, void, env, fprp, fprp)
+DEF_HELPER_3(drdpq, void, env, fprp, fprp)
+DEF_HELPER_3(dcffix, void, env, fprp, fprp)
+DEF_HELPER_3(dcffixq, void, env, fprp, fprp)
+DEF_HELPER_3(dctfix, void, env, fprp, fprp)
+DEF_HELPER_3(dctfixq, void, env, fprp, fprp)
+DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32)
+DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32)
+DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32)
+DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32)
+DEF_HELPER_3(dxex, void, env, fprp, fprp)
+DEF_HELPER_3(dxexq, void, env, fprp, fprp)
+DEF_HELPER_4(diex, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(dscri, void, env, fprp, fprp, i32)
+DEF_HELPER_4(dscriq, void, env, fprp, fprp, i32)
+DEF_HELPER_4(dscli, void, env, fprp, fprp, i32)
+DEF_HELPER_4(dscliq, void, env, fprp, fprp, i32)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 588f6a9b95..f6e8846707 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -19,6 +19,7 @@
#include "cpu.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
+#include "qemu/aes.h"
#include "helper_regs.h"
/*****************************************************************************/
@@ -396,9 +397,13 @@ target_ulong helper_602_mfrom(target_ulong arg)
#if defined(HOST_WORDS_BIGENDIAN)
#define HI_IDX 0
#define LO_IDX 1
+#define AVRB(i) u8[i]
+#define AVRW(i) u32[i]
#else
#define HI_IDX 1
#define LO_IDX 0
+#define AVRB(i) u8[15-(i)]
+#define AVRW(i) u32[3-(i)]
#endif
#if defined(HOST_WORDS_BIGENDIAN)
@@ -2338,284 +2343,63 @@ uint32_t helper_bcdsub(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
return helper_bcdadd(r, a, &bcopy, ps);
}
-static uint8_t SBOX[256] = {
-0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
-0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
-0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
-0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
-0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
-0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
-0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
-0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
-0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
-0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
-0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
-0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
-0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
-0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
-0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
-0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
-0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
-0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
-0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
-0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
-0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
-0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
-0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
-0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
-0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
-0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
-0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
-0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
-0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
-0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
-0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
-0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
-};
-
-static void SubBytes(ppc_avr_t *r, ppc_avr_t *a)
-{
- int i;
- VECTOR_FOR_INORDER_I(i, u8) {
- r->u8[i] = SBOX[a->u8[i]];
- }
-}
-
-static uint8_t InvSBOX[256] = {
-0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
-0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
-0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
-0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
-0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
-0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
-0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
-0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
-0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
-0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
-0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
-0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
-0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
-0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
-0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
-0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
-0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
-0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
-0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
-0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
-0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
-0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
-0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
-0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
-0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
-0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
-0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
-0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
-0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
-0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
-0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
-0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
-};
-
-static void InvSubBytes(ppc_avr_t *r, ppc_avr_t *a)
+void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
{
int i;
VECTOR_FOR_INORDER_I(i, u8) {
- r->u8[i] = InvSBOX[a->u8[i]];
+ r->u8[i] = AES_sbox[a->u8[i]];
}
}
-static uint8_t ROTL8(uint8_t x, int n)
-{
- return (x << n) | (x >> (8-n));
-}
-
-static inline int BIT8(uint8_t x, int n)
-{
- return (x & (0x80 >> n)) != 0;
-}
-
-static uint8_t GFx02(uint8_t x)
-{
- return ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0);
-}
-
-static uint8_t GFx03(uint8_t x)
-{
- return x ^ ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0);
-}
-
-static uint8_t GFx09(uint8_t x)
-{
- uint8_t term2 = ROTL8(x, 3);
- uint8_t term3 = (BIT8(x, 0) ? 0x68 : 0) | (BIT8(x, 1) ? 0x14 : 0) |
- (BIT8(x, 2) ? 0x02 : 0);
- uint8_t term4 = (BIT8(x, 1) ? 0x20 : 0) | (BIT8(x, 2) ? 0x18 : 0);
- return x ^ term2 ^ term3 ^ term4;
-}
-
-static uint8_t GFx0B(uint8_t x)
-{
- uint8_t term2 = ROTL8(x, 1);
- uint8_t term3 = (x << 3) | (BIT8(x, 0) ? 0x06 : 0) |
- (BIT8(x, 2) ? 0x01 : 0);
- uint8_t term4 = (BIT8(x, 0) ? 0x70 : 0) | (BIT8(x, 1) ? 0x06 : 0) |
- (BIT8(x, 2) ? 0x08 : 0);
- uint8_t term5 = (BIT8(x, 1) ? 0x30 : 0) | (BIT8(x, 2) ? 0x02 : 0);
- uint8_t term6 = BIT8(x, 2) ? 0x10 : 0;
- return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6;
-}
-
-static uint8_t GFx0D(uint8_t x)
-{
- uint8_t term2 = ROTL8(x, 2);
- uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) |
- (BIT8(x, 2) ? 0x03 : 0);
- uint8_t term4 = (BIT8(x, 0) ? 0x58 : 0) | (BIT8(x, 1) ? 0x20 : 0);
- uint8_t term5 = (BIT8(x, 1) ? 0x08 : 0) | (BIT8(x, 2) ? 0x10 : 0);
- uint8_t term6 = BIT8(x, 2) ? 0x08 : 0;
- return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6;
-}
-
-static uint8_t GFx0E(uint8_t x)
-{
- uint8_t term1 = ROTL8(x, 1);
- uint8_t term2 = (x << 2) | (BIT8(x, 2) ? 0x02 : 0) |
- (BIT8(x, 1) ? 0x01 : 0);
- uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) |
- (BIT8(x, 2) ? 0x01 : 0);
- uint8_t term4 = (BIT8(x, 0) ? 0x40 : 0) | (BIT8(x, 1) ? 0x28 : 0) |
- (BIT8(x, 2) ? 0x10 : 0);
- uint8_t term5 = (BIT8(x, 2) ? 0x08 : 0);
- return term1 ^ term2 ^ term3 ^ term4 ^ term5;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN)
-#define MCB(x, i, b) ((x)->u8[(i)*4 + (b)])
-#else
-#define MCB(x, i, b) ((x)->u8[15 - ((i)*4 + (b))])
-#endif
-
-static void MixColumns(ppc_avr_t *r, ppc_avr_t *x)
+void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
int i;
- for (i = 0; i < 4; i++) {
- MCB(r, i, 0) = GFx02(MCB(x, i, 0)) ^ GFx03(MCB(x, i, 1)) ^
- MCB(x, i, 2) ^ MCB(x, i, 3);
- MCB(r, i, 1) = MCB(x, i, 0) ^ GFx02(MCB(x, i, 1)) ^
- GFx03(MCB(x, i, 2)) ^ MCB(x, i, 3);
- MCB(r, i, 2) = MCB(x, i, 0) ^ MCB(x, i, 1) ^
- GFx02(MCB(x, i, 2)) ^ GFx03(MCB(x, i, 3));
- MCB(r, i, 3) = GFx03(MCB(x, i, 0)) ^ MCB(x, i, 1) ^
- MCB(x, i, 2) ^ GFx02(MCB(x, i, 3));
- }
-}
-static void InvMixColumns(ppc_avr_t *r, ppc_avr_t *x)
-{
- int i;
- for (i = 0; i < 4; i++) {
- MCB(r, i, 0) = GFx0E(MCB(x, i, 0)) ^ GFx0B(MCB(x, i, 1)) ^
- GFx0D(MCB(x, i, 2)) ^ GFx09(MCB(x, i, 3));
- MCB(r, i, 1) = GFx09(MCB(x, i, 0)) ^ GFx0E(MCB(x, i, 1)) ^
- GFx0B(MCB(x, i, 2)) ^ GFx0D(MCB(x, i, 3));
- MCB(r, i, 2) = GFx0D(MCB(x, i, 0)) ^ GFx09(MCB(x, i, 1)) ^
- GFx0E(MCB(x, i, 2)) ^ GFx0B(MCB(x, i, 3));
- MCB(r, i, 3) = GFx0B(MCB(x, i, 0)) ^ GFx0D(MCB(x, i, 1)) ^
- GFx09(MCB(x, i, 2)) ^ GFx0E(MCB(x, i, 3));
+ VECTOR_FOR_INORDER_I(i, u32) {
+ r->AVRW(i) = b->AVRW(i) ^
+ (AES_Te0[a->AVRB(AES_shifts[4*i + 0])] ^
+ AES_Te1[a->AVRB(AES_shifts[4*i + 1])] ^
+ AES_Te2[a->AVRB(AES_shifts[4*i + 2])] ^
+ AES_Te3[a->AVRB(AES_shifts[4*i + 3])]);
}
}
-static void ShiftRows(ppc_avr_t *r, ppc_avr_t *x)
-{
- MCB(r, 0, 0) = MCB(x, 0, 0);
- MCB(r, 1, 0) = MCB(x, 1, 0);
- MCB(r, 2, 0) = MCB(x, 2, 0);
- MCB(r, 3, 0) = MCB(x, 3, 0);
-
- MCB(r, 0, 1) = MCB(x, 1, 1);
- MCB(r, 1, 1) = MCB(x, 2, 1);
- MCB(r, 2, 1) = MCB(x, 3, 1);
- MCB(r, 3, 1) = MCB(x, 0, 1);
-
- MCB(r, 0, 2) = MCB(x, 2, 2);
- MCB(r, 1, 2) = MCB(x, 3, 2);
- MCB(r, 2, 2) = MCB(x, 0, 2);
- MCB(r, 3, 2) = MCB(x, 1, 2);
-
- MCB(r, 0, 3) = MCB(x, 3, 3);
- MCB(r, 1, 3) = MCB(x, 0, 3);
- MCB(r, 2, 3) = MCB(x, 1, 3);
- MCB(r, 3, 3) = MCB(x, 2, 3);
-}
-
-static void InvShiftRows(ppc_avr_t *r, ppc_avr_t *x)
-{
- MCB(r, 0, 0) = MCB(x, 0, 0);
- MCB(r, 1, 0) = MCB(x, 1, 0);
- MCB(r, 2, 0) = MCB(x, 2, 0);
- MCB(r, 3, 0) = MCB(x, 3, 0);
-
- MCB(r, 0, 1) = MCB(x, 3, 1);
- MCB(r, 1, 1) = MCB(x, 0, 1);
- MCB(r, 2, 1) = MCB(x, 1, 1);
- MCB(r, 3, 1) = MCB(x, 2, 1);
-
- MCB(r, 0, 2) = MCB(x, 2, 2);
- MCB(r, 1, 2) = MCB(x, 3, 2);
- MCB(r, 2, 2) = MCB(x, 0, 2);
- MCB(r, 3, 2) = MCB(x, 1, 2);
-
- MCB(r, 0, 3) = MCB(x, 1, 3);
- MCB(r, 1, 3) = MCB(x, 2, 3);
- MCB(r, 2, 3) = MCB(x, 3, 3);
- MCB(r, 3, 3) = MCB(x, 0, 3);
-}
-
-#undef MCB
-
-void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
-{
- SubBytes(r, a);
-}
-
-void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
-{
- ppc_avr_t vtemp1, vtemp2, vtemp3;
- SubBytes(&vtemp1, a);
- ShiftRows(&vtemp2, &vtemp1);
- MixColumns(&vtemp3, &vtemp2);
- r->u64[0] = vtemp3.u64[0] ^ b->u64[0];
- r->u64[1] = vtemp3.u64[1] ^ b->u64[1];
-}
-
void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
- ppc_avr_t vtemp1, vtemp2;
- SubBytes(&vtemp1, a);
- ShiftRows(&vtemp2, &vtemp1);
- r->u64[0] = vtemp2.u64[0] ^ b->u64[0];
- r->u64[1] = vtemp2.u64[1] ^ b->u64[1];
+ int i;
+
+ VECTOR_FOR_INORDER_I(i, u8) {
+ r->AVRB(i) = b->AVRB(i) ^ (AES_Te4[a->AVRB(AES_shifts[i])] & 0xFF);
+ }
}
void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
/* This differs from what is written in ISA V2.07. The RTL is */
/* incorrect and will be fixed in V2.07B. */
- ppc_avr_t vtemp1, vtemp2, vtemp3;
- InvShiftRows(&vtemp1, a);
- InvSubBytes(&vtemp2, &vtemp1);
- vtemp3.u64[0] = vtemp2.u64[0] ^ b->u64[0];
- vtemp3.u64[1] = vtemp2.u64[1] ^ b->u64[1];
- InvMixColumns(r, &vtemp3);
+ int i;
+ ppc_avr_t tmp;
+
+ VECTOR_FOR_INORDER_I(i, u8) {
+ tmp.AVRB(i) = b->AVRB(i) ^ AES_isbox[a->AVRB(AES_ishifts[i])];
+ }
+
+ VECTOR_FOR_INORDER_I(i, u32) {
+ r->AVRW(i) =
+ AES_imc[tmp.AVRB(4*i + 0)][0] ^
+ AES_imc[tmp.AVRB(4*i + 1)][1] ^
+ AES_imc[tmp.AVRB(4*i + 2)][2] ^
+ AES_imc[tmp.AVRB(4*i + 3)][3];
+ }
}
void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
- ppc_avr_t vtemp1, vtemp2;
- InvShiftRows(&vtemp1, a);
- InvSubBytes(&vtemp2, &vtemp1);
- r->u64[0] = vtemp2.u64[0] ^ b->u64[0];
- r->u64[1] = vtemp2.u64[1] ^ b->u64[1];
+ int i;
+
+ VECTOR_FOR_INORDER_I(i, u8) {
+ r->AVRB(i) = b->AVRB(i) ^ (AES_Td4[a->AVRB(AES_ishifts[i])] & 0xFF);
+ }
}
#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n)))
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 8ff1777dcb..561f8ccf2f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -35,6 +35,7 @@
#include "hw/sysbus.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
+#include "hw/ppc/ppc.h"
#include "sysemu/watchdog.h"
#include "trace.h"
@@ -61,12 +62,14 @@ static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_rma;
static int cap_spapr_tce;
+static int cap_spapr_multitce;
static int cap_hior;
static int cap_one_reg;
static int cap_epr;
static int cap_ppc_watchdog;
static int cap_papr;
static int cap_htab_fd;
+static int cap_fixup_hcalls;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -97,6 +100,7 @@ int kvm_arch_init(KVMState *s)
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+ cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
@@ -104,6 +108,7 @@ int kvm_arch_init(KVMState *s)
/* Note: we don't set cap_papr here, because this capability is
* only activated after this by kvmppc_set_papr() */
cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
+ cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -356,6 +361,10 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
/* Convert to QEMU form */
memset(&env->sps, 0, sizeof(env->sps));
+ /*
+ * XXX This loop should be an entry wide AND of the capabilities that
+ * the selected CPU has with the capabilities that KVM supports.
+ */
for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) {
struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq];
struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik];
@@ -382,9 +391,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
}
}
env->slb_nr = smmu_info.slb_size;
- if (smmu_info.flags & KVM_PPC_1T_SEGMENTS) {
- env->mmu_model |= POWERPC_MMU_1TSEG;
- } else {
+ if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) {
env->mmu_model &= ~POWERPC_MMU_1TSEG;
}
}
@@ -858,11 +865,32 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
#ifdef TARGET_PPC64
+ if (msr_ts) {
+ for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) {
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]);
+ }
+ for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) {
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]);
+ }
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr);
+ kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar);
+ }
+
if (cap_papr) {
if (kvm_put_vpa(cs) < 0) {
DPRINTF("Warning: Unable to set VPA information to KVM\n");
}
}
+
+ kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
#endif /* TARGET_PPC64 */
}
@@ -1082,11 +1110,32 @@ int kvm_arch_get_registers(CPUState *cs)
}
#ifdef TARGET_PPC64
+ if (msr_ts) {
+ for (i = 0; i < ARRAY_SIZE(env->tm_gpr); i++) {
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]);
+ }
+ for (i = 0; i < ARRAY_SIZE(env->tm_vsr); i++) {
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]);
+ }
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr);
+ kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar);
+ }
+
if (cap_papr) {
if (kvm_get_vpa(cs) < 0) {
DPRINTF("Warning: Unable to get VPA information from KVM\n");
}
}
+
+ kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
#endif
}
@@ -1476,18 +1525,18 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
}
/*
- * Fallback to always fail hypercalls:
+ * Fallback to always fail hypercalls regardless of endianness:
*
+ * tdi 0,r0,72 (becomes b .+8 in wrong endian, nop in good endian)
* li r3, -1
- * nop
- * nop
- * nop
+ * b .+8 (becomes nop in wrong endian)
+ * bswap32(li r3, -1)
*/
- hc[0] = 0x3860ffff;
- hc[1] = 0x60000000;
- hc[2] = 0x60000000;
- hc[3] = 0x60000000;
+ hc[0] = cpu_to_be32(0x08000048);
+ hc[1] = cpu_to_be32(0x3860ffff);
+ hc[2] = cpu_to_be32(0x48000008);
+ hc[3] = cpu_to_be32(bswap32(0x3860ffff));
return 0;
}
@@ -1507,6 +1556,11 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
cap_papr = 1;
}
+int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &cpu_version);
+}
+
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
CPUState *cs = CPU(cpu);
@@ -1601,6 +1655,11 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
}
#endif
+bool kvmppc_spapr_use_multitce(void)
+{
+ return cap_spapr_multitce;
+}
+
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
{
struct kvm_create_spapr_tce args = {
@@ -1641,7 +1700,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
return table;
}
-int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
+int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table)
{
long len;
@@ -1649,7 +1708,7 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
return -1;
}
- len = (window_size / SPAPR_TCE_PAGE_SIZE)*sizeof(uint64_t);
+ len = nb_table * sizeof(uint64_t);
if ((munmap(table, len) < 0) ||
(close(fd) < 0)) {
fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
@@ -1761,6 +1820,23 @@ bool kvmppc_has_cap_htab_fd(void)
return cap_htab_fd;
}
+bool kvmppc_has_cap_fixup_hcalls(void)
+{
+ return cap_fixup_hcalls;
+}
+
+static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
+{
+ ObjectClass *oc = OBJECT_CLASS(pcc);
+
+ while (oc && !object_class_is_abstract(oc)) {
+ oc = object_class_get_parent(oc);
+ }
+ assert(oc);
+
+ return POWERPC_CPU_CLASS(oc);
+}
+
static int kvm_ppc_register_host_cpu_type(void)
{
TypeInfo type_info = {
@@ -1770,6 +1846,7 @@ static int kvm_ppc_register_host_cpu_type(void)
};
uint32_t host_pvr = mfpvr();
PowerPCCPUClass *pvr_pcc;
+ DeviceClass *dc;
pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
if (pvr_pcc == NULL) {
@@ -1780,6 +1857,14 @@ static int kvm_ppc_register_host_cpu_type(void)
}
type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
type_register(&type_info);
+
+ /* Register generic family CPU class for a family */
+ pvr_pcc = ppc_cpu_get_family_class(pvr_pcc);
+ dc = DEVICE_CLASS(pvr_pcc);
+ type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
+ type_info.name = g_strdup_printf("%s-"TYPE_POWERPC_CPU, dc->desc);
+ type_register(&type_info);
+
return 0;
}
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index ff077ec502..412cc7f3c1 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -23,6 +23,7 @@ int kvmppc_get_hasidle(CPUPPCState *env);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
void kvmppc_set_papr(PowerPCCPU *cpu);
+int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
int kvmppc_smt_threads(void);
int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
@@ -31,6 +32,7 @@ int kvmppc_set_tcr(PowerPCCPU *cpu);
int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
#ifndef CONFIG_USER_ONLY
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
+bool kvmppc_spapr_use_multitce(void);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
@@ -48,6 +50,7 @@ void kvmppc_hash64_free_pteg(uint64_t token);
void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index,
target_ulong pte0, target_ulong pte1);
+bool kvmppc_has_cap_fixup_hcalls(void);
#else
@@ -95,6 +98,11 @@ static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{
}
+static inline int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ return 0;
+}
+
static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
}
@@ -130,6 +138,11 @@ static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
return 0;
}
+static inline bool kvmppc_spapr_use_multitce(void)
+{
+ return false;
+}
+
static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
uint32_t window_size, int *fd)
{
@@ -137,7 +150,7 @@ static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
}
static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
- uint32_t window_size)
+ uint32_t nb_table)
{
return -1;
}
@@ -211,6 +224,11 @@ static inline void kvmppc_hash64_write_pte(CPUPPCState *env,
abort();
}
+static inline bool kvmppc_has_cap_fixup_hcalls(void)
+{
+ abort();
+}
+
#endif
#ifndef CONFIG_KVM
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index d7807f88e6..c801b822c9 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -160,6 +160,11 @@ static int cpu_post_load(void *opaque, int version_id)
CPUPPCState *env = &cpu->env;
int i;
+ /*
+ * We always ignore the source PVR. The user or management
+ * software has to take care of running QEMU in a compatible mode.
+ */
+ env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value;
env->lr = env->spr[SPR_LR];
env->ctr = env->spr[SPR_CTR];
env->xer = env->spr[SPR_XER];
@@ -244,6 +249,38 @@ static const VMStateDescription vmstate_vsx = {
},
};
+#ifdef TARGET_PPC64
+/* Transactional memory state */
+static bool tm_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+ return msr_ts;
+}
+
+static const VMStateDescription vmstate_tm = {
+ .name = "cpu/tm",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINTTL_ARRAY(env.tm_gpr, PowerPCCPU, 32),
+ VMSTATE_AVR_ARRAY(env.tm_vsr, PowerPCCPU, 64),
+ VMSTATE_UINT64(env.tm_cr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_lr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_ctr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_fpscr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_amr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_ppr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_vrsave, PowerPCCPU),
+ VMSTATE_UINT32(env.tm_vscr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_dscr, PowerPCCPU),
+ VMSTATE_UINT64(env.tm_tar, PowerPCCPU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+#endif
+
static bool sr_needed(void *opaque)
{
#ifdef TARGET_PPC64
@@ -459,8 +496,7 @@ const VMStateDescription vmstate_ppc_cpu = {
.pre_save = cpu_pre_save,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
- /* Verify we haven't changed the pvr */
- VMSTATE_UINTTL_EQUAL(env.spr[SPR_PVR], PowerPCCPU),
+ VMSTATE_UNUSED(sizeof(target_ulong)), /* was _EQUAL(env.spr[SPR_PVR]) */
/* User mode architected state */
VMSTATE_UINTTL_ARRAY(env.gpr, PowerPCCPU, 32),
@@ -506,6 +542,9 @@ const VMStateDescription vmstate_ppc_cpu = {
.needed = sr_needed,
} , {
#ifdef TARGET_PPC64
+ .vmsd = &vmstate_tm,
+ .needed = tm_needed,
+ } , {
.vmsd = &vmstate_slb,
.needed = slb_needed,
} , {
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index 02b627e47b..50344b81cf 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -25,6 +25,15 @@
//#define DEBUG_OP
+static inline bool needs_byteswap(const CPUPPCState *env)
+{
+#if defined(TARGET_WORDS_BIGENDIAN)
+ return msr_le;
+#else
+ return !msr_le;
+#endif
+}
+
/*****************************************************************************/
/* Memory load and stores */
@@ -44,7 +53,7 @@ static inline target_ulong addr_add(CPUPPCState *env, target_ulong addr,
void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
- if (msr_le) {
+ if (needs_byteswap(env)) {
env->gpr[reg] = bswap32(cpu_ldl_data(env, addr));
} else {
env->gpr[reg] = cpu_ldl_data(env, addr);
@@ -56,7 +65,7 @@ void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
- if (msr_le) {
+ if (needs_byteswap(env)) {
cpu_stl_data(env, addr, bswap32((uint32_t)env->gpr[reg]));
} else {
cpu_stl_data(env, addr, (uint32_t)env->gpr[reg]);
@@ -199,6 +208,11 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
#define LO_IDX 0
#endif
+/* We use msr_le to determine index ordering in a vector. However,
+ byteswapping is not simply controlled by msr_le. We also need to take
+ into account endianness of the target. This is done for the little-endian
+ PPC64 user-mode target. */
+
#define LVE(name, access, swap, element) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
@@ -207,9 +221,11 @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
int adjust = HI_IDX*(n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
index = n_elems - index - 1; \
+ } \
+ \
+ if (needs_byteswap(env)) { \
r->element[LO_IDX ? index : (adjust - index)] = \
swap(access(env, addr)); \
} else { \
@@ -232,9 +248,11 @@ LVE(lvewx, cpu_ldl_data, bswap32, u32)
int adjust = HI_IDX * (n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
index = n_elems - index - 1; \
+ } \
+ \
+ if (needs_byteswap(env)) { \
access(env, addr, swap(r->element[LO_IDX ? index : \
(adjust - index)])); \
} else { \
diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
index 7331b1b240..a577b3afd1 100644
--- a/target-ppc/misc_helper.c
+++ b/target-ppc/misc_helper.c
@@ -34,6 +34,45 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
env->spr[sprn]);
}
+
+#ifdef TARGET_PPC64
+static void raise_fu_exception(CPUPPCState *env, uint32_t bit,
+ uint32_t sprn, uint32_t cause)
+{
+ qemu_log("Facility SPR %d is unavailable (SPR FSCR:%d)\n", sprn, bit);
+
+ env->spr[SPR_FSCR] &= ~((target_ulong)FSCR_IC_MASK << FSCR_IC_POS);
+ cause &= FSCR_IC_MASK;
+ env->spr[SPR_FSCR] |= (target_ulong)cause << FSCR_IC_POS;
+
+ helper_raise_exception_err(env, POWERPC_EXCP_FU, 0);
+}
+#endif
+
+void helper_fscr_facility_check(CPUPPCState *env, uint32_t bit,
+ uint32_t sprn, uint32_t cause)
+{
+#ifdef TARGET_PPC64
+ if (env->spr[SPR_FSCR] & (1ULL << bit)) {
+ /* Facility is enabled, continue */
+ return;
+ }
+ raise_fu_exception(env, bit, sprn, cause);
+#endif
+}
+
+void helper_msr_facility_check(CPUPPCState *env, uint32_t bit,
+ uint32_t sprn, uint32_t cause)
+{
+#ifdef TARGET_PPC64
+ if (env->msr & (1ULL << bit)) {
+ /* Facility is enabled, continue */
+ return;
+ }
+ raise_fu_exception(env, bit, sprn, cause);
+#endif
+}
+
#if !defined(CONFIG_USER_ONLY)
void helper_store_sdr1(CPUPPCState *env, target_ulong val)
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index f029f41965..4d6b1e20c0 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -903,6 +903,11 @@ static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
target_ulong mask;
uint32_t tlb_pid;
+ if (!msr_cm) {
+ /* In 32bit mode we can only address 32bit EAs */
+ address = (uint32_t)address;
+ }
+
/* Check valid flag */
if (!(tlb->mas1 & MAS1_VALID)) {
return -1;
@@ -2886,7 +2891,7 @@ void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
tlb_flush(CPU(cpu), 1);
}
-void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
+void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
{
int flags = 0;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index f08901470b..48017219a4 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -46,17 +46,13 @@
/* global register indexes */
static TCGv_ptr cpu_env;
static char cpu_reg_names[10*3 + 22*4 /* GPR */
-#if !defined(TARGET_PPC64)
+ 10*4 + 22*5 /* SPE GPRh */
-#endif
+ 10*4 + 22*5 /* FPR */
+ 2*(10*6 + 22*7) /* AVRh, AVRl */
+ 10*5 + 22*6 /* VSR */
+ 8*5 /* CRF */];
static TCGv cpu_gpr[32];
-#if !defined(TARGET_PPC64)
static TCGv cpu_gprh[32];
-#endif
static TCGv_i64 cpu_fpr[32];
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
static TCGv_i64 cpu_vsr[32];
@@ -104,13 +100,11 @@ void ppc_translate_init(void)
offsetof(CPUPPCState, gpr[i]), p);
p += (i < 10) ? 3 : 4;
cpu_reg_names_size -= (i < 10) ? 3 : 4;
-#if !defined(TARGET_PPC64)
snprintf(p, cpu_reg_names_size, "r%dH", i);
- cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUPPCState, gprh[i]), p);
+ cpu_gprh[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUPPCState, gprh[i]), p);
p += (i < 10) ? 4 : 5;
cpu_reg_names_size -= (i < 10) ? 4 : 5;
-#endif
snprintf(p, cpu_reg_names_size, "fp%d", i);
cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
@@ -196,6 +190,7 @@ typedef struct DisasContext {
int access_type;
/* Translation flags */
int le_mode;
+ TCGMemOp default_tcg_memop_mask;
#if defined(TARGET_PPC64)
int sf_mode;
int has_cfar;
@@ -210,6 +205,16 @@ typedef struct DisasContext {
uint64_t insns_flags2;
} DisasContext;
+/* Return true iff byteswap is needed in a scalar memop */
+static inline bool need_byteswap(const DisasContext *ctx)
+{
+#if defined(TARGET_WORDS_BIGENDIAN)
+ return ctx->le_mode;
+#else
+ return !ctx->le_mode;
+#endif
+}
+
/* True when active word size < size of target_long. */
#ifdef TARGET_PPC64
# define NARROW_MODE(C) (!(C)->sf_mode)
@@ -279,6 +284,13 @@ static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
tcg_gen_movi_tl(cpu_nip, nip);
}
+void gen_update_current_nip(void *opaque)
+{
+ DisasContext *ctx = opaque;
+
+ tcg_gen_movi_tl(cpu_nip, ctx->nip);
+}
+
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
{
TCGv_i32 t0, t1;
@@ -467,6 +479,12 @@ EXTRACT_HELPER(AA, 1, 1);
/* Link */
EXTRACT_HELPER(LK, 0, 1);
+/* DFP Z22-form */
+EXTRACT_HELPER(DCM, 10, 6)
+
+/* DFP Z23-form */
+EXTRACT_HELPER(RMC, 9, 2)
+
/* Create a mask between <start> and <end> bits */
static inline target_ulong MASK(uint32_t start, uint32_t end)
{
@@ -503,6 +521,7 @@ EXTRACT_HELPER_SPLIT(xC, 3, 1, 6, 5);
EXTRACT_HELPER(DM, 8, 2);
EXTRACT_HELPER(UIM, 16, 2);
EXTRACT_HELPER(SHW, 8, 2);
+EXTRACT_HELPER(SP, 19, 2);
/*****************************************************************************/
/* PowerPC instructions table */
@@ -1217,6 +1236,7 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
}
tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */
tcg_gen_add_tl(t0, t0, inv1);
+ tcg_temp_free(inv1);
tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */
tcg_temp_free(t1);
tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */
@@ -2652,29 +2672,20 @@ static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
- tcg_gen_bswap16_tl(arg1, arg1);
- }
+ TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
- tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- tcg_gen_bswap16_tl(arg1, arg1);
- tcg_gen_ext16s_tl(arg1, arg1);
- } else {
- tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_SW | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
- tcg_gen_bswap32_tl(arg1, arg1);
- }
+ TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
@@ -2687,12 +2698,8 @@ static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
- tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- tcg_gen_bswap32_tl(arg1, arg1);
- tcg_gen_ext32s_tl(arg1, arg1);
- } else
- tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
+ TCGMemOp op = MO_SL | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
@@ -2705,10 +2712,8 @@ static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
{
- tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
- if (unlikely(ctx->le_mode)) {
- tcg_gen_bswap64_i64(arg1, arg1);
- }
+ TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
}
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
@@ -2718,28 +2723,14 @@ static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ext16u_tl(t0, arg1);
- tcg_gen_bswap16_tl(t0, t0);
- tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
- tcg_temp_free(t0);
- } else {
- tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
}
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ext32u_tl(t0, arg1);
- tcg_gen_bswap32_tl(t0, t0);
- tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
- tcg_temp_free(t0);
- } else {
- tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
}
static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
@@ -2752,13 +2743,8 @@ static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
{
- if (unlikely(ctx->le_mode)) {
- TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_bswap64_i64(t0, arg1);
- tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
- tcg_temp_free_i64(t0);
- } else
- tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
+ TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
+ tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
}
#define GEN_LD(name, ldop, opc, type) \
@@ -2902,6 +2888,8 @@ static void gen_lq(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x0F);
+ /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
+ 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
gen_addr_add(ctx, EA, EA, 8);
@@ -3020,6 +3008,8 @@ static void gen_std(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x03);
+ /* We only need to swap high and low halves. gen_qemu_st64 does
+ necessary 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
gen_addr_add(ctx, EA, EA, 8);
@@ -3049,23 +3039,20 @@ static void gen_std(DisasContext *ctx)
}
#endif
/*** Integer load and store with byte reverse ***/
+
/* lhbrx */
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
- tcg_gen_bswap16_tl(arg1, arg1);
- }
+ TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
/* lwbrx */
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
- tcg_gen_bswap32_tl(arg1, arg1);
- }
+ TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
}
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
@@ -3073,10 +3060,8 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
/* ldbrx */
static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
- if (likely(!ctx->le_mode)) {
- tcg_gen_bswap64_tl(arg1, arg1);
- }
+ TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
}
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
#endif /* TARGET_PPC64 */
@@ -3084,30 +3069,16 @@ GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
/* sthbrx */
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ext16u_tl(t0, arg1);
- tcg_gen_bswap16_tl(t0, t0);
- tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
- tcg_temp_free(t0);
- } else {
- tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
}
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
/* stwbrx */
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_ext32u_tl(t0, arg1);
- tcg_gen_bswap32_tl(t0, t0);
- tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
- tcg_temp_free(t0);
- } else {
- tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
}
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
@@ -3115,14 +3086,8 @@ GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
/* stdbrx */
static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (likely(!ctx->le_mode)) {
- TCGv t0 = tcg_temp_new();
- tcg_gen_bswap64_tl(t0, arg1);
- tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
- tcg_temp_free(t0);
- } else {
- tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
- }
+ TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
+ tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
}
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
#endif /* TARGET_PPC64 */
@@ -3542,7 +3507,9 @@ static void gen_lfdp(DisasContext *ctx)
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
- gen_addr_imm_index(ctx, EA, 0); \
+ gen_addr_imm_index(ctx, EA, 0);
+ /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
+ 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
@@ -3566,6 +3533,8 @@ static void gen_lfdpx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
+ /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
+ 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
@@ -3714,7 +3683,9 @@ static void gen_stfdp(DisasContext *ctx)
}
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
- gen_addr_imm_index(ctx, EA, 0); \
+ gen_addr_imm_index(ctx, EA, 0);
+ /* We only need to swap high and low halves. gen_qemu_st64 does necessary
+ 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
@@ -3738,6 +3709,8 @@ static void gen_stfdpx(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_FLOAT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
+ /* We only need to swap high and low halves. gen_qemu_st64 does necessary
+ 64-bit byteswap already. */
if (unlikely(ctx->le_mode)) {
gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
tcg_gen_addi_tl(EA, EA, 8);
@@ -3913,6 +3886,9 @@ static inline void gen_bcond(DisasContext *ctx, int type)
gen_update_nip(ctx, ctx->nip);
tcg_gen_exit_tb(0);
}
+ if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
+ tcg_temp_free(target);
+ }
}
static void gen_bc(DisasContext *ctx)
@@ -4360,6 +4336,7 @@ static void gen_mtmsr(DisasContext *ctx)
tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
#endif
gen_helper_store_msr(cpu_env, msr);
+ tcg_temp_free(msr);
/* Must stop the translation as machine state (may have) changed */
/* Note that mtmsr is not always defined as context-synchronizing */
gen_stop_exception(ctx);
@@ -4469,6 +4446,17 @@ static void gen_dcbtst(DisasContext *ctx)
*/
}
+/* dcbtls */
+static void gen_dcbtls(DisasContext *ctx)
+{
+ /* Always fails locking the cache */
+ TCGv t0 = tcg_temp_new();
+ gen_load_spr(t0, SPR_Exxx_L1CSR0);
+ tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
+ gen_store_spr(SPR_Exxx_L1CSR0, t0);
+ tcg_temp_free(t0);
+}
+
/* dcbz */
static void gen_dcbz(DisasContext *ctx)
{
@@ -6494,6 +6482,7 @@ static void gen_tlbsx_booke206(DisasContext *ctx)
tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
gen_helper_booke206_tlbsx(cpu_env, t0);
+ tcg_temp_free(t0);
#endif
}
@@ -6527,6 +6516,7 @@ static void gen_tlbivax_booke206(DisasContext *ctx)
gen_addr_reg_index(ctx, t0);
gen_helper_booke206_tlbivax(cpu_env, t0);
+ tcg_temp_free(t0);
#endif
}
@@ -6691,6 +6681,8 @@ static void glue(gen_, name)(DisasContext *ctx)
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
+ /* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
+ 64-bit byteswap already. */ \
if (ctx->le_mode) { \
gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
@@ -6715,6 +6707,8 @@ static void gen_st##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
+ /* We only need to swap high and low halves. gen_qemu_st64 does necessary \
+ 64-bit byteswap already. */ \
if (ctx->le_mode) { \
gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
tcg_gen_addi_tl(EA, EA, 8); \
@@ -8180,6 +8174,225 @@ static void gen_xxsldwi(DisasContext *ctx)
tcg_temp_free_i64(xtl);
}
+/*** Decimal Floating Point ***/
+
+static inline TCGv_ptr gen_fprp_ptr(int reg)
+{
+ TCGv_ptr r = tcg_temp_new_ptr();
+ tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
+ return r;
+}
+
+#if defined(TARGET_PPC64)
+static void gen_set_cr6_from_fpscr(DisasContext *ctx)
+{
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
+ tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
+ tcg_temp_free_i32(tmp);
+}
+#else
+static void gen_set_cr6_from_fpscr(DisasContext *ctx)
+{
+ tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
+}
+#endif
+
+#define GEN_DFP_T_A_B_Rc(name) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr rd, ra, rb; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ rd = gen_fprp_ptr(rD(ctx->opcode)); \
+ ra = gen_fprp_ptr(rA(ctx->opcode)); \
+ rb = gen_fprp_ptr(rB(ctx->opcode)); \
+ gen_helper_##name(cpu_env, rd, ra, rb); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_cr6_from_fpscr(ctx); \
+ } \
+ tcg_temp_free_ptr(rd); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_ptr(rb); \
+}
+
+#define GEN_DFP_BF_A_B(name) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr ra, rb; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ ra = gen_fprp_ptr(rA(ctx->opcode)); \
+ rb = gen_fprp_ptr(rB(ctx->opcode)); \
+ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
+ cpu_env, ra, rb); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_ptr(rb); \
+}
+
+#define GEN_DFP_BF_A_DCM(name) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr ra; \
+ TCGv_i32 dcm; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ ra = gen_fprp_ptr(rA(ctx->opcode)); \
+ dcm = tcg_const_i32(DCM(ctx->opcode)); \
+ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
+ cpu_env, ra, dcm); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_i32(dcm); \
+}
+
+#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr rt, rb; \
+ TCGv_i32 u32_1, u32_2; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ rt = gen_fprp_ptr(rD(ctx->opcode)); \
+ rb = gen_fprp_ptr(rB(ctx->opcode)); \
+ u32_1 = tcg_const_i32(u32f1(ctx->opcode)); \
+ u32_2 = tcg_const_i32(u32f2(ctx->opcode)); \
+ gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_cr6_from_fpscr(ctx); \
+ } \
+ tcg_temp_free_ptr(rt); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_i32(u32_1); \
+ tcg_temp_free_i32(u32_2); \
+}
+
+#define GEN_DFP_T_A_B_I32_Rc(name, i32fld) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr rt, ra, rb; \
+ TCGv_i32 i32; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ rt = gen_fprp_ptr(rD(ctx->opcode)); \
+ ra = gen_fprp_ptr(rA(ctx->opcode)); \
+ rb = gen_fprp_ptr(rB(ctx->opcode)); \
+ i32 = tcg_const_i32(i32fld(ctx->opcode)); \
+ gen_helper_##name(cpu_env, rt, ra, rb, i32); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_cr6_from_fpscr(ctx); \
+ } \
+ tcg_temp_free_ptr(rt); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_i32(i32); \
+ }
+
+#define GEN_DFP_T_B_Rc(name) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr rt, rb; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ rt = gen_fprp_ptr(rD(ctx->opcode)); \
+ rb = gen_fprp_ptr(rB(ctx->opcode)); \
+ gen_helper_##name(cpu_env, rt, rb); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_cr6_from_fpscr(ctx); \
+ } \
+ tcg_temp_free_ptr(rt); \
+ tcg_temp_free_ptr(rb); \
+ }
+
+#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_ptr rt, rs; \
+ TCGv_i32 i32; \
+ if (unlikely(!ctx->fpu_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_FPU); \
+ return; \
+ } \
+ gen_update_nip(ctx, ctx->nip - 4); \
+ rt = gen_fprp_ptr(rD(ctx->opcode)); \
+ rs = gen_fprp_ptr(fprfld(ctx->opcode)); \
+ i32 = tcg_const_i32(i32fld(ctx->opcode)); \
+ gen_helper_##name(cpu_env, rt, rs, i32); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_cr6_from_fpscr(ctx); \
+ } \
+ tcg_temp_free_ptr(rt); \
+ tcg_temp_free_ptr(rs); \
+ tcg_temp_free_i32(i32); \
+}
+
+GEN_DFP_T_A_B_Rc(dadd)
+GEN_DFP_T_A_B_Rc(daddq)
+GEN_DFP_T_A_B_Rc(dsub)
+GEN_DFP_T_A_B_Rc(dsubq)
+GEN_DFP_T_A_B_Rc(dmul)
+GEN_DFP_T_A_B_Rc(dmulq)
+GEN_DFP_T_A_B_Rc(ddiv)
+GEN_DFP_T_A_B_Rc(ddivq)
+GEN_DFP_BF_A_B(dcmpu)
+GEN_DFP_BF_A_B(dcmpuq)
+GEN_DFP_BF_A_B(dcmpo)
+GEN_DFP_BF_A_B(dcmpoq)
+GEN_DFP_BF_A_DCM(dtstdc)
+GEN_DFP_BF_A_DCM(dtstdcq)
+GEN_DFP_BF_A_DCM(dtstdg)
+GEN_DFP_BF_A_DCM(dtstdgq)
+GEN_DFP_BF_A_B(dtstex)
+GEN_DFP_BF_A_B(dtstexq)
+GEN_DFP_BF_A_B(dtstsf)
+GEN_DFP_BF_A_B(dtstsfq)
+GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC)
+GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC)
+GEN_DFP_T_A_B_I32_Rc(dqua, RMC)
+GEN_DFP_T_A_B_I32_Rc(dquaq, RMC)
+GEN_DFP_T_A_B_I32_Rc(drrnd, RMC)
+GEN_DFP_T_A_B_I32_Rc(drrndq, RMC)
+GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC)
+GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC)
+GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC)
+GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC)
+GEN_DFP_T_B_Rc(dctdp)
+GEN_DFP_T_B_Rc(dctqpq)
+GEN_DFP_T_B_Rc(drsp)
+GEN_DFP_T_B_Rc(drdpq)
+GEN_DFP_T_B_Rc(dcffix)
+GEN_DFP_T_B_Rc(dcffixq)
+GEN_DFP_T_B_Rc(dctfix)
+GEN_DFP_T_B_Rc(dctfixq)
+GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
+GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
+GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
+GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
+GEN_DFP_T_B_Rc(dxex)
+GEN_DFP_T_B_Rc(dxexq)
+GEN_DFP_T_A_B_Rc(diex)
+GEN_DFP_T_A_B_Rc(diexq)
+GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
+GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
+GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
+GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
/*** SPE extension ***/
/* Register moves */
@@ -8192,50 +8405,28 @@ static inline void gen_evmra(DisasContext *ctx)
return;
}
-#if defined(TARGET_PPC64)
- /* rD := rA */
- tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
-
- /* spe_acc := rA */
- tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
- cpu_env,
- offsetof(CPUPPCState, spe_acc));
-#else
TCGv_i64 tmp = tcg_temp_new_i64();
/* tmp := rA_lo + rA_hi << 32 */
- tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
+ tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
/* spe_acc := tmp */
tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
tcg_temp_free_i64(tmp);
/* rD := rA */
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
-#endif
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
}
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
-#if defined(TARGET_PPC64)
- tcg_gen_mov_i64(t, cpu_gpr[reg]);
-#else
- tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
-#endif
+ tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
}
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
-#if defined(TARGET_PPC64)
- tcg_gen_mov_i64(cpu_gpr[reg], t);
-#else
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
- tcg_gen_shri_i64(tmp, t, 32);
- tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
- tcg_temp_free_i64(tmp);
-#endif
+ tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
}
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
@@ -8254,18 +8445,6 @@ static inline void gen_speundef(DisasContext *ctx)
}
/* SPE logic */
-#if defined(TARGET_PPC64)
-#define GEN_SPEOP_LOGIC2(name, tcg_op) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
- cpu_gpr[rB(ctx->opcode)]); \
-}
-#else
#define GEN_SPEOP_LOGIC2(name, tcg_op) \
static inline void gen_##name(DisasContext *ctx) \
{ \
@@ -8278,7 +8457,6 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
cpu_gprh[rB(ctx->opcode)]); \
}
-#endif
GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
@@ -8290,80 +8468,52 @@ GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
/* SPE logic immediate */
-#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- TCGv_i32 t0 = tcg_temp_local_new_i32(); \
- TCGv_i32 t1 = tcg_temp_local_new_i32(); \
- TCGv_i64 t2 = tcg_temp_local_new_i64(); \
- tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ t0 = tcg_temp_new_i32(); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_opi(t0, t0, rB(ctx->opcode)); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
tcg_opi(t0, t0, rB(ctx->opcode)); \
- tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t1, t2); \
- tcg_temp_free_i64(t2); \
- tcg_opi(t1, t1, rB(ctx->opcode)); \
- tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
+ \
tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
-}
-#else
-#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
- rB(ctx->opcode)); \
- tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
- rB(ctx->opcode)); \
}
-#endif
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
/* SPE arithmetic */
-#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- TCGv_i32 t0 = tcg_temp_local_new_i32(); \
- TCGv_i32 t1 = tcg_temp_local_new_i32(); \
- TCGv_i64 t2 = tcg_temp_local_new_i64(); \
- tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ t0 = tcg_temp_new_i32(); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_op(t0, t0); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
tcg_op(t0, t0); \
- tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t1, t2); \
- tcg_temp_free_i64(t2); \
- tcg_op(t1, t1); \
- tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
+ \
tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
}
-#else
-#define GEN_SPEOP_ARITH1(name, tcg_op) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
- tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
-}
-#endif
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
{
@@ -8390,46 +8540,30 @@ GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
-#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0, t1; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- TCGv_i32 t0 = tcg_temp_local_new_i32(); \
- TCGv_i32 t1 = tcg_temp_local_new_i32(); \
- TCGv_i32 t2 = tcg_temp_local_new_i32(); \
- TCGv_i64 t3 = tcg_temp_local_new_i64(); \
- tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
- tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
- tcg_op(t0, t0, t2); \
- tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t1, t3); \
- tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t2, t3); \
- tcg_temp_free_i64(t3); \
- tcg_op(t1, t1, t2); \
- tcg_temp_free_i32(t2); \
- tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
+ t0 = tcg_temp_new_i32(); \
+ t1 = tcg_temp_new_i32(); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
+ tcg_op(t0, t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
+ tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]); \
+ tcg_op(t0, t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
+ \
tcg_temp_free_i32(t0); \
tcg_temp_free_i32(t1); \
}
-#else
-#define GEN_SPEOP_ARITH2(name, tcg_op) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
- cpu_gpr[rB(ctx->opcode)]); \
- tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
- cpu_gprh[rB(ctx->opcode)]); \
-}
-#endif
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
@@ -8502,18 +8636,8 @@ static inline void gen_evmergehi(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
- tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-#else
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
-#endif
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
}
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -8523,86 +8647,30 @@ static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
/* SPE arithmetic immediate */
-#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- TCGv_i32 t0 = tcg_temp_local_new_i32(); \
- TCGv_i32 t1 = tcg_temp_local_new_i32(); \
- TCGv_i64 t2 = tcg_temp_local_new_i64(); \
- tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
+ t0 = tcg_temp_new_i32(); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
tcg_op(t0, t0, rA(ctx->opcode)); \
- tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t1, t2); \
- tcg_temp_free_i64(t2); \
- tcg_op(t1, t1, rA(ctx->opcode)); \
- tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]); \
+ tcg_op(t0, t0, rA(ctx->opcode)); \
+ tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
+ \
tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
-}
-#else
-#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
- rA(ctx->opcode)); \
- tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
- rA(ctx->opcode)); \
}
-#endif
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
/* SPE comparison */
-#if defined(TARGET_PPC64)
-#define GEN_SPEOP_COMP(name, tcg_cond) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- int l1 = gen_new_label(); \
- int l2 = gen_new_label(); \
- int l3 = gen_new_label(); \
- int l4 = gen_new_label(); \
- TCGv_i32 t0 = tcg_temp_local_new_i32(); \
- TCGv_i32 t1 = tcg_temp_local_new_i32(); \
- TCGv_i64 t2 = tcg_temp_local_new_i64(); \
- tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
- tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
- tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
- tcg_gen_br(l2); \
- gen_set_label(l1); \
- tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
- CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
- gen_set_label(l2); \
- tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t0, t2); \
- tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
- tcg_gen_trunc_i64_i32(t1, t2); \
- tcg_temp_free_i64(t2); \
- tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
- tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
- ~(CRF_CH | CRF_CH_AND_CL)); \
- tcg_gen_br(l4); \
- gen_set_label(l3); \
- tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
- CRF_CH | CRF_CH_OR_CL); \
- gen_set_label(l4); \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
-}
-#else
#define GEN_SPEOP_COMP(name, tcg_cond) \
static inline void gen_##name(DisasContext *ctx) \
{ \
@@ -8615,15 +8683,20 @@ static inline void gen_##name(DisasContext *ctx) \
int l3 = gen_new_label(); \
int l4 = gen_new_label(); \
\
- tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
+ tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
+ tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
+ tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
+ tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); \
+ \
+ tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
cpu_gpr[rB(ctx->opcode)], l1); \
- tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
+ tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
tcg_gen_br(l2); \
gen_set_label(l1); \
tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
gen_set_label(l2); \
- tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
+ tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
cpu_gprh[rB(ctx->opcode)], l3); \
tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
~(CRF_CH | CRF_CH_AND_CL)); \
@@ -8633,7 +8706,6 @@ static inline void gen_##name(DisasContext *ctx) \
CRF_CH | CRF_CH_OR_CL); \
gen_set_label(l4); \
}
-#endif
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
@@ -8653,18 +8725,8 @@ static inline void gen_evmergelo(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-#else
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-#endif
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
}
static inline void gen_evmergehilo(DisasContext *ctx)
{
@@ -8672,18 +8734,8 @@ static inline void gen_evmergehilo(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-#else
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
-#endif
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
}
static inline void gen_evmergelohi(DisasContext *ctx)
{
@@ -8691,48 +8743,30 @@ static inline void gen_evmergelohi(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
- tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-#else
if (rD(ctx->opcode) == rA(ctx->opcode)) {
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
- tcg_temp_free_i32(tmp);
+ TCGv tmp = tcg_temp_new();
+ tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
+ tcg_temp_free(tmp);
} else {
- tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
- tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
+ tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
}
-#endif
}
static inline void gen_evsplati(DisasContext *ctx)
{
uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
-#if defined(TARGET_PPC64)
- tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
-#else
- tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
- tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
-#endif
+ tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
+ tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
}
static inline void gen_evsplatfi(DisasContext *ctx)
{
uint64_t imm = rA(ctx->opcode) << 27;
-#if defined(TARGET_PPC64)
- tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
-#else
- tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
- tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
-#endif
+ tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
+ tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
}
static inline void gen_evsel(DisasContext *ctx)
@@ -8742,46 +8776,21 @@ static inline void gen_evsel(DisasContext *ctx)
int l3 = gen_new_label();
int l4 = gen_new_label();
TCGv_i32 t0 = tcg_temp_local_new_i32();
-#if defined(TARGET_PPC64)
- TCGv t1 = tcg_temp_local_new();
- TCGv t2 = tcg_temp_local_new();
-#endif
tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
-#if defined(TARGET_PPC64)
- tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
-#else
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
-#endif
tcg_gen_br(l2);
gen_set_label(l1);
-#if defined(TARGET_PPC64)
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
-#else
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
-#endif
gen_set_label(l2);
tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
-#if defined(TARGET_PPC64)
- tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
-#else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
-#endif
tcg_gen_br(l4);
gen_set_label(l3);
-#if defined(TARGET_PPC64)
- tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
-#else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-#endif
gen_set_label(l4);
tcg_temp_free_i32(t0);
-#if defined(TARGET_PPC64)
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
-#endif
}
static void gen_evsel0(DisasContext *ctx)
@@ -8819,13 +8828,10 @@ static inline void gen_evmwumi(DisasContext *ctx)
t1 = tcg_temp_new_i64();
/* t0 := rA; t1 := rB */
-#if defined(TARGET_PPC64)
- tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
-#else
tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_ext32u_i64(t0, t0);
tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
-#endif
+ tcg_gen_ext32u_i64(t1, t1);
tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
@@ -8901,13 +8907,10 @@ static inline void gen_evmwsmi(DisasContext *ctx)
t1 = tcg_temp_new_i64();
/* t0 := rA; t1 := rB */
-#if defined(TARGET_PPC64)
- tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
-#else
- tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
-#endif
+ tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_ext32s_i64(t0, t0);
+ tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
+ tcg_gen_ext32s_i64(t1, t1);
tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
@@ -9008,53 +9011,22 @@ static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
-#else
TCGv_i64 t0 = tcg_temp_new_i64();
gen_qemu_ld64(ctx, t0, addr);
- tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_gen_shri_i64(t0, t0, 32);
- tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
+ gen_store_gpr64(rD(ctx->opcode), t0);
tcg_temp_free_i64(t0);
-#endif
}
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- gen_qemu_ld32u(ctx, t0, addr);
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
- gen_addr_add(ctx, addr, addr, 4);
- gen_qemu_ld32u(ctx, t0, addr);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
-#else
gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
gen_addr_add(ctx, addr, addr, 4);
gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
-#endif
}
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
-#if defined(TARGET_PPC64)
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(t0, t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(t0, t0, 16);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
gen_addr_add(ctx, addr, addr, 2);
@@ -9066,7 +9038,6 @@ static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
@@ -9074,15 +9045,9 @@ static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
gen_qemu_ld16u(ctx, t0, addr);
-#if defined(TARGET_PPC64)
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
- tcg_gen_shli_tl(t0, t0, 16);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
tcg_gen_shli_tl(t0, t0, 16);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
@@ -9090,13 +9055,8 @@ static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
gen_qemu_ld16u(ctx, t0, addr);
-#if defined(TARGET_PPC64)
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
@@ -9104,100 +9064,48 @@ static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
gen_qemu_ld16s(ctx, t0, addr);
-#if defined(TARGET_PPC64)
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
-#if defined(TARGET_PPC64)
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(t0, t0, 16);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
-#endif
tcg_temp_free(t0);
}
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(t0, t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
-#else
gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
-#endif
}
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- gen_qemu_ld16s(ctx, t0, addr);
- tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16s(ctx, t0, addr);
- tcg_gen_shli_tl(t0, t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
-#else
gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
-#endif
}
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
gen_qemu_ld32u(ctx, t0, addr);
-#if defined(TARGET_PPC64)
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
-#if defined(TARGET_PPC64)
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
- tcg_gen_shli_tl(t0, t0, 32);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- gen_addr_add(ctx, addr, addr, 2);
- gen_qemu_ld16u(ctx, t0, addr);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- tcg_gen_shli_tl(t0, t0, 16);
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
-#else
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
@@ -9205,32 +9113,20 @@ static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
-#endif
tcg_temp_free(t0);
}
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
-#else
TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
+ gen_load_gpr64(t0, rS(ctx->opcode));
gen_qemu_st64(ctx, t0, addr);
tcg_temp_free_i64(t0);
-#endif
}
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
- gen_qemu_st32(ctx, t0, addr);
- tcg_temp_free(t0);
-#else
gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
-#endif
gen_addr_add(ctx, addr, addr, 4);
gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
}
@@ -9238,19 +9134,10 @@ static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
-#if defined(TARGET_PPC64)
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
-#else
tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
-#endif
gen_qemu_st16(ctx, t0, addr);
gen_addr_add(ctx, addr, addr, 2);
-#if defined(TARGET_PPC64)
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
- gen_qemu_st16(ctx, t0, addr);
-#else
gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
-#endif
gen_addr_add(ctx, addr, addr, 2);
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
gen_qemu_st16(ctx, t0, addr);
@@ -9262,11 +9149,7 @@ static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
{
TCGv t0 = tcg_temp_new();
-#if defined(TARGET_PPC64)
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
-#else
tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
-#endif
gen_qemu_st16(ctx, t0, addr);
gen_addr_add(ctx, addr, addr, 2);
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
@@ -9276,28 +9159,14 @@ static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
- gen_qemu_st16(ctx, t0, addr);
- tcg_temp_free(t0);
-#else
gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
-#endif
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
}
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
{
-#if defined(TARGET_PPC64)
- TCGv t0 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
- gen_qemu_st32(ctx, t0, addr);
- tcg_temp_free(t0);
-#else
gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
-#endif
}
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
@@ -9417,133 +9286,36 @@ GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_S
#endif
/*** SPE floating-point extension ***/
-#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- TCGv_i32 t0; \
- TCGv t1; \
- t0 = tcg_temp_new_i32(); \
+ TCGv_i32 t0 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
gen_helper_##name(t0, cpu_env, t0); \
- t1 = tcg_temp_new(); \
- tcg_gen_extu_i32_tl(t1, t0); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
tcg_temp_free_i32(t0); \
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
- 0xFFFFFFFF00000000ULL); \
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
- tcg_temp_free(t1); \
-}
-#define GEN_SPEFPUOP_CONV_32_64(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_i32 t0; \
- TCGv t1; \
- t0 = tcg_temp_new_i32(); \
- gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]); \
- t1 = tcg_temp_new(); \
- tcg_gen_extu_i32_tl(t1, t0); \
- tcg_temp_free_i32(t0); \
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
- 0xFFFFFFFF00000000ULL); \
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
- tcg_temp_free(t1); \
-}
-#define GEN_SPEFPUOP_CONV_64_32(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_i32 t0 = tcg_temp_new_i32(); \
- tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); \
- tcg_temp_free_i32(t0); \
-}
-#define GEN_SPEFPUOP_CONV_64_64(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
- cpu_gpr[rB(ctx->opcode)]); \
-}
-#define GEN_SPEFPUOP_ARITH2_32_32(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_i32 t0, t1; \
- TCGv_i64 t2; \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i32(); \
- tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
- tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(t0, cpu_env, t0, t1); \
- tcg_temp_free_i32(t1); \
- t2 = tcg_temp_new(); \
- tcg_gen_extu_i32_tl(t2, t0); \
- tcg_temp_free_i32(t0); \
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
- 0xFFFFFFFF00000000ULL); \
- tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
- tcg_temp_free(t2); \
-}
-#define GEN_SPEFPUOP_ARITH2_64_64(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
-}
-#define GEN_SPEFPUOP_COMP_32(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_i32 t0, t1; \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i32(); \
- tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
- tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
-}
-#define GEN_SPEFPUOP_COMP_64(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- if (unlikely(!ctx->spe_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_SPEU); \
- return; \
- } \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
-}
-#else
-#define GEN_SPEFPUOP_CONV_32_32(name) \
-static inline void gen_##name(DisasContext *ctx) \
-{ \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
- cpu_gpr[rB(ctx->opcode)]); \
}
#define GEN_SPEFPUOP_CONV_32_64(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
TCGv_i64 t0 = tcg_temp_new_i64(); \
+ TCGv_i32 t1 = tcg_temp_new_i32(); \
gen_load_gpr64(t0, rB(ctx->opcode)); \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); \
+ gen_helper_##name(t1, cpu_env, t0); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \
tcg_temp_free_i64(t0); \
+ tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_CONV_64_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
TCGv_i64 t0 = tcg_temp_new_i64(); \
- gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]); \
+ TCGv_i32 t1 = tcg_temp_new_i32(); \
+ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
+ gen_helper_##name(t0, cpu_env, t1); \
gen_store_gpr64(rD(ctx->opcode), t0); \
tcg_temp_free_i64(t0); \
+ tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_CONV_64_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -9557,12 +9329,20 @@ static inline void gen_##name(DisasContext *ctx) \
#define GEN_SPEFPUOP_ARITH2_32_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0, t1; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
+ t0 = tcg_temp_new_i32(); \
+ t1 = tcg_temp_new_i32(); \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
+ gen_helper_##name(t0, cpu_env, t0, t1); \
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
+ \
+ tcg_temp_free_i32(t0); \
+ tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -9584,12 +9364,20 @@ static inline void gen_##name(DisasContext *ctx) \
#define GEN_SPEFPUOP_COMP_32(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
+ TCGv_i32 t0, t1; \
if (unlikely(!ctx->spe_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_SPEU); \
return; \
} \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, \
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
+ t0 = tcg_temp_new_i32(); \
+ t1 = tcg_temp_new_i32(); \
+ \
+ tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
+ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
+ \
+ tcg_temp_free_i32(t0); \
+ tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_COMP_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -9607,7 +9395,6 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_temp_free_i64(t0); \
tcg_temp_free_i64(t1); \
}
-#endif
/* Single precision floating-point vectors operations */
/* Arithmetic */
@@ -9621,12 +9408,10 @@ static inline void gen_evfsabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
-#else
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
- tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
-#endif
+ tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ ~0x80000000);
+ tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ ~0x80000000);
}
static inline void gen_evfsnabs(DisasContext *ctx)
{
@@ -9634,12 +9419,10 @@ static inline void gen_evfsnabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
-#else
- tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
- tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
-#endif
+ tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ 0x80000000);
+ tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ 0x80000000);
}
static inline void gen_evfsneg(DisasContext *ctx)
{
@@ -9647,12 +9430,10 @@ static inline void gen_evfsneg(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
-#else
- tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
- tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
-#endif
+ tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ 0x80000000);
+ tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ 0x80000000);
}
/* Conversion */
@@ -9771,12 +9552,9 @@ static inline void gen_efdabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
-#else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
-#endif
+ tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ ~0x80000000);
}
static inline void gen_efdnabs(DisasContext *ctx)
{
@@ -9784,12 +9562,9 @@ static inline void gen_efdnabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
-#else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
-#endif
+ tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ 0x80000000);
}
static inline void gen_efdneg(DisasContext *ctx)
{
@@ -9797,12 +9572,9 @@ static inline void gen_efdneg(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
-#if defined(TARGET_PPC64)
- tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
-#else
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
-#endif
+ tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
+ 0x80000000);
}
/* Conversion */
@@ -9880,7 +9652,7 @@ GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
-GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
+GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
#if defined(TARGET_PPC64)
@@ -9982,6 +9754,7 @@ GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
+GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
@@ -10999,6 +10772,166 @@ GEN_XXSEL_ROW(0x1F)
GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
+#undef GEN_DFP_T_A_B_Rc
+#undef GEN_DFP_BF_A_B
+#undef GEN_DFP_BF_A_DCM
+#undef GEN_DFP_T_B_U32_U32_Rc
+#undef GEN_DFP_T_A_B_I32_Rc
+#undef GEN_DFP_T_B_Rc
+#undef GEN_DFP_T_FPR_I32_Rc
+
+#define _GEN_DFP_LONG(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP)
+
+#define _GEN_DFP_LONGx2(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
+
+#define _GEN_DFP_LONGx4(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
+
+#define _GEN_DFP_QUAD(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP)
+
+#define _GEN_DFP_QUADx2(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
+
+#define _GEN_DFP_QUADx4(name, op1, op2, mask) \
+GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
+GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
+
+#define GEN_DFP_T_A_B_Rc(name, op1, op2) \
+_GEN_DFP_LONG(name, op1, op2, 0x00000000)
+
+#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x00210800)
+
+#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x00200800)
+
+#define GEN_DFP_T_B_Rc(name, op1, op2) \
+_GEN_DFP_LONG(name, op1, op2, 0x001F0000)
+
+#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x003F0800)
+
+#define GEN_DFP_Tp_B_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x003F0000)
+
+#define GEN_DFP_T_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x001F0800)
+
+#define GEN_DFP_BF_A_B(name, op1, op2) \
+_GEN_DFP_LONG(name, op1, op2, 0x00000001)
+
+#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x00610801)
+
+#define GEN_DFP_BF_A_Bp(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x00600801)
+
+#define GEN_DFP_BF_A_DCM(name, op1, op2) \
+_GEN_DFP_LONGx2(name, op1, op2, 0x00600001)
+
+#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \
+_GEN_DFP_QUADx2(name, op1, op2, 0x00610001)
+
+#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \
+_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
+
+#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \
+_GEN_DFP_QUADx4(name, op1, op2, 0x02010800)
+
+#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \
+_GEN_DFP_QUADx4(name, op1, op2, 0x02000800)
+
+#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \
+_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
+
+#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \
+_GEN_DFP_QUADx4(name, op1, op2, 0x00200800)
+
+#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \
+_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000)
+
+#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \
+_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800)
+
+#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \
+_GEN_DFP_LONG(name, op1, op2, 0x00070000)
+
+#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x00270800)
+
+#define GEN_DFP_S_T_B_Rc(name, op1, op2) \
+_GEN_DFP_LONG(name, op1, op2, 0x000F0000)
+
+#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \
+_GEN_DFP_QUAD(name, op1, op2, 0x002F0800)
+
+#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \
+_GEN_DFP_LONGx2(name, op1, op2, 0x00000000)
+
+#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \
+_GEN_DFP_QUADx2(name, op1, op2, 0x00210000)
+
+GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00),
+GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00),
+GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10),
+GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10),
+GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01),
+GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01),
+GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11),
+GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11),
+GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14),
+GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14),
+GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04),
+GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04),
+GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06),
+GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06),
+GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07),
+GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07),
+GEN_DFP_BF_A_B(dtstex, 0x02, 0x05),
+GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05),
+GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15),
+GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15),
+GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02),
+GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02),
+GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00),
+GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00),
+GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01),
+GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01),
+GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03),
+GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03),
+GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07),
+GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07),
+GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08),
+GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08),
+GEN_DFP_T_B_Rc(drsp, 0x02, 0x18),
+GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18),
+GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19),
+GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19),
+GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
+GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
+GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
+GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
+GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
+GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
+GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
+GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
+GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
+GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
+GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
+GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
+GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
+GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
+
#undef GEN_SPE
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
@@ -11337,6 +11270,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
ctx.insns_flags2 = env->insns_flags2;
ctx.access_type = -1;
ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
+ ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE;
#if defined(TARGET_PPC64)
ctx.sf_mode = msr_is_64bit(env, env->msr);
ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
@@ -11374,6 +11308,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
max_insns = CF_COUNT_MASK;
gen_tb_start();
+ tcg_clear_temp_count();
/* Set env in case of segfault during code fetch */
while (ctx.exception == POWERPC_EXCP_NONE
&& tcg_ctx.gen_opc_ptr < gen_opc_end) {
@@ -11401,7 +11336,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
ctx.nip, ctx.mem_idx, (int)msr_ir);
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- if (unlikely(ctx.le_mode)) {
+ if (unlikely(need_byteswap(&ctx))) {
ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
} else {
ctx.opcode = cpu_ldl_code(env, ctx.nip);
@@ -11473,6 +11408,12 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
*/
break;
}
+ if (tcg_check_temp_count()) {
+ fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked temporaries\n",
+ opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
+ ctx.opcode);
+ exit(1);
+ }
}
if (tb->cflags & CF_LAST_IO)
gen_io_end();
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4d94015942..85581c9537 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -28,6 +28,8 @@
#include "mmu-hash32.h"
#include "mmu-hash64.h"
#include "qemu/error-report.h"
+#include "qapi/visitor.h"
+#include "hw/qdev-properties.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -173,6 +175,13 @@ static void spr_read_ureg (void *opaque, int gprn, int sprn)
gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
}
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+static void spr_write_ureg(void *opaque, int sprn, int gprn)
+{
+ gen_store_spr(sprn + 0x10, cpu_gpr[gprn]);
+}
+#endif
+
/* SPR common to all non-embedded PowerPC */
/* DECR */
#if !defined(CONFIG_USER_ONLY)
@@ -951,72 +960,72 @@ static void gen_spr_7xx (CPUPPCState *env)
0x00000000);
/* Performance monitors */
/* XXX : not implemented */
- spr_register(env, SPR_MMCR0, "MMCR0",
+ spr_register(env, SPR_7XX_MMCR0, "MMCR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_MMCR1, "MMCR1",
+ spr_register(env, SPR_7XX_MMCR1, "MMCR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC1, "PMC1",
+ spr_register(env, SPR_7XX_PMC1, "PMC1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC2, "PMC2",
+ spr_register(env, SPR_7XX_PMC2, "PMC2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC3, "PMC3",
+ spr_register(env, SPR_7XX_PMC3, "PMC3",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC4, "PMC4",
+ spr_register(env, SPR_7XX_PMC4, "PMC4",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_SIAR, "SIAR",
+ spr_register(env, SPR_7XX_SIAR, "SIAR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UMMCR0, "UMMCR0",
+ spr_register(env, SPR_7XX_UMMCR0, "UMMCR0",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UMMCR1, "UMMCR1",
+ spr_register(env, SPR_7XX_UMMCR1, "UMMCR1",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC1, "UPMC1",
+ spr_register(env, SPR_7XX_UPMC1, "UPMC1",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC2, "UPMC2",
+ spr_register(env, SPR_7XX_UPMC2, "UPMC2",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC3, "UPMC3",
+ spr_register(env, SPR_7XX_UPMC3, "UPMC3",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC4, "UPMC4",
+ spr_register(env, SPR_7XX_UPMC4, "UPMC4",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_USIAR, "USIAR",
+ spr_register(env, SPR_7XX_USIAR, "USIAR",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -1117,22 +1126,22 @@ static void gen_spr_604 (CPUPPCState *env)
KVM_REG_PPC_DABR, 0x00000000);
/* Performance counters */
/* XXX : not implemented */
- spr_register(env, SPR_MMCR0, "MMCR0",
+ spr_register(env, SPR_7XX_MMCR0, "MMCR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC1, "PMC1",
+ spr_register(env, SPR_7XX_PMC1, "PMC1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC2, "PMC2",
+ spr_register(env, SPR_7XX_PMC2, "PMC2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_SIAR, "SIAR",
+ spr_register(env, SPR_7XX_SIAR, "SIAR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000);
@@ -1352,12 +1361,12 @@ static void gen_spr_74xx (CPUPPCState *env)
&spr_read_generic, &spr_write_pir,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_MMCR2, "MMCR2",
+ spr_register(env, SPR_74XX_MMCR2, "MMCR2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UMMCR2, "UMMCR2",
+ spr_register(env, SPR_74XX_UMMCR2, "UMMCR2",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -1448,16 +1457,23 @@ static void spr_write_e500_l1csr0 (void *opaque, int sprn, int gprn)
{
TCGv t0 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[gprn], ~256);
+ tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR0_DCE | L1CSR0_CPE);
+ gen_store_spr(sprn, t0);
+ tcg_temp_free(t0);
+}
+
+static void spr_write_e500_l1csr1(void *opaque, int sprn, int gprn)
+{
+ TCGv t0 = tcg_temp_new();
+
+ tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR1_ICE | L1CSR1_CPE);
gen_store_spr(sprn, t0);
tcg_temp_free(t0);
}
static void spr_write_booke206_mmucsr0 (void *opaque, int sprn, int gprn)
{
- TCGv_i32 t0 = tcg_const_i32(sprn);
- gen_helper_booke206_tlbflush(cpu_env, t0);
- tcg_temp_free_i32(t0);
+ gen_helper_booke206_tlbflush(cpu_env, cpu_gpr[gprn]);
}
static void spr_write_booke_pid (void *opaque, int sprn, int gprn)
@@ -3064,6 +3080,7 @@ static void init_excp_POWER7 (CPUPPCState *env)
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20;
env->excp_vectors[POWERPC_EXCP_VSXU] = 0x00000F40;
+ env->excp_vectors[POWERPC_EXCP_FU] = 0x00000F60;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700;
@@ -3102,6 +3119,18 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
return 0;
}
+static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu)
+{
+ return true;
+}
+
+#ifdef TARGET_PPC64
+static bool ppc_cpu_interrupts_big_endian_lpcr(PowerPCCPU *cpu)
+{
+ return !(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
+}
+#endif
+
/*****************************************************************************/
/* PowerPC implementations definitions */
@@ -3156,7 +3185,15 @@ POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x00000000000FD201ULL;
+ pcc->msr_mask = (1ull << MSR_KEY) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_REAL;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3203,7 +3240,18 @@ POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x00000000001FD231ULL;
+ pcc->msr_mask = (1ull << 20) |
+ (1ull << MSR_KEY) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3244,7 +3292,19 @@ POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x00000000001FD631ULL;
+ pcc->msr_mask = (1ull << 20) |
+ (1ull << MSR_KEY) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3291,7 +3351,18 @@ POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x00000000001FD231ULL;
+ pcc->msr_mask = (1ull << 20) |
+ (1ull << MSR_KEY) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3330,7 +3401,15 @@ POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x000000000007D00DULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_PE) |
+ (1ull << MSR_PX) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_REAL;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3389,7 +3468,15 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
PPC_4xx_COMMON | PPC_40x_EXCP;
- pcc->msr_mask = 0x000000000007D00DULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_PE) |
+ (1ull << MSR_PX) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_401;
@@ -3447,7 +3534,15 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP;
- pcc->msr_mask = 0x000000000006E630ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_SOFT_4xx;
pcc->excp_model = POWERPC_EXCP_40x;
pcc->bus_model = PPC_FLAGS_INPUT_405;
@@ -3540,7 +3635,18 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_MFTB |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -3612,7 +3718,18 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -3684,7 +3801,18 @@ POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_MFTB |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -3774,7 +3902,18 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_MFTB |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -3870,7 +4009,18 @@ POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_TLBIVA |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -3969,7 +4119,18 @@ POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_TLBIVA |
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
PPC_440_SPEC;
- pcc->msr_mask = 0x000000000006FF30ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4002,7 +4163,18 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX |
PPC_MFTB;
- pcc->msr_mask = 0x000000000001FF43ULL;
+ pcc->msr_mask = (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_REAL;
pcc->excp_model = POWERPC_EXCP_603;
pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
@@ -4034,7 +4206,18 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
PPC_MEM_EIEIO | PPC_MEM_SYNC |
PPC_CACHE_ICBI | PPC_MFTB;
- pcc->msr_mask = 0x000000000001F673ULL;
+ pcc->msr_mask = (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_MPC8xx;
pcc->excp_model = POWERPC_EXCP_603;
pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
@@ -4100,7 +4283,21 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000006FFF2ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_AL) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_G2;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -4191,7 +4388,23 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000007FFF3ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_AL) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_G2;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -4249,8 +4462,8 @@ static void init_proc_e200 (CPUPPCState *env)
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
@@ -4331,7 +4544,20 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
PPC_MEM_TLBSYNC | PPC_TLBIVAX |
PPC_BOOKE;
- pcc->msr_mask = 0x000000000606FF30ULL;
+ pcc->msr_mask = (1ull << MSR_UCLE) |
+ (1ull << MSR_SPE) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE206;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4389,7 +4615,23 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000007FFF3ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_AL) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_603;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -4438,6 +4680,8 @@ static void init_proc_e500 (CPUPPCState *env, int version)
uint64_t ivpr_mask = 0xFFFF0000ULL;
uint32_t l1cfg0 = 0x3800 /* 8 ways */
| 0x0020; /* 32 kb */
+ uint32_t l1cfg1 = 0x3800 /* 8 ways */
+ | 0x0020; /* 32 kb */
#if !defined(CONFIG_USER_ONLY)
int i;
#endif
@@ -4506,6 +4750,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
env->dcache_line_size = 64;
env->icache_line_size = 64;
l1cfg0 |= 0x1000000; /* 64 byte cache block size */
+ l1cfg1 |= 0x1000000; /* 64 byte cache block size */
break;
default:
cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
@@ -4553,18 +4798,20 @@ static void init_proc_e500 (CPUPPCState *env, int version)
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
l1cfg0);
- /* XXX : not implemented */
+ spr_register(env, SPR_Exxx_L1CFG1, "L1CFG1",
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ l1cfg1);
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_e500_l1csr0,
0x00000000);
- /* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR1, "L1CSR1",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_e500_l1csr1,
0x00000000);
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
SPR_NOACCESS, SPR_NOACCESS,
@@ -4628,7 +4875,20 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
pcc->insns_flags2 = PPC2_BOOKE206;
- pcc->msr_mask = 0x000000000606FF30ULL;
+ pcc->msr_mask = (1ull << MSR_UCLE) |
+ (1ull << MSR_SPE) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE206;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4658,7 +4918,20 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
pcc->insns_flags2 = PPC2_BOOKE206;
- pcc->msr_mask = 0x000000000606FF30ULL;
+ pcc->msr_mask = (1ull << MSR_UCLE) |
+ (1ull << MSR_SPE) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DWE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_BOOKE206;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4690,7 +4963,20 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
PPC_FLOAT_STFIWX | PPC_WAIT |
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL;
- pcc->msr_mask = 0x000000001402FB36ULL;
+ pcc->msr_mask = (1ull << MSR_GS) |
+ (1ull << MSR_UCLE) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PX) |
+ (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_BOOKE206;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4724,7 +5010,21 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC |
PPC_64B | PPC_POPCNTB | PPC_POPCNTWD;
pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206;
- pcc->msr_mask = 0x000000009402FB36ULL;
+ pcc->msr_mask = (1ull << MSR_CM) |
+ (1ull << MSR_GS) |
+ (1ull << MSR_UCLE) |
+ (1ull << MSR_CE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PX) |
+ (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_BOOKE206;
pcc->excp_model = POWERPC_EXCP_BOOKE;
pcc->bus_model = PPC_FLAGS_INPUT_BookE;
@@ -4746,7 +5046,17 @@ POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data)
dc->desc = "POWER";
/* pcc->insns_flags = XXX_TODO; */
/* POWER RSC (from RAD6000) */
- pcc->msr_mask = 0x00000000FEF0ULL;
+ pcc->msr_mask = (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_AL) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
}
#define POWERPC_MSRR_601 (0x0000000000001040ULL)
@@ -4801,7 +5111,16 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000000FD70ULL;
+ pcc->msr_mask = (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_601;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -4837,7 +5156,16 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000000FD70ULL;
+ pcc->msr_mask = (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR);
pcc->mmu_model = POWERPC_MMU_601;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -4889,7 +5217,24 @@ POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_602_SPEC;
- pcc->msr_mask = 0x0000000000C7FF73ULL;
+ pcc->msr_mask = (1ull << MSR_VSX) |
+ (1ull << MSR_SA) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
/* XXX: 602 MMU is quite specific. Should add a special case */
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_602;
@@ -4941,7 +5286,22 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000007FF73ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_603;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -4992,7 +5352,22 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000007FF73ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_TGPR) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_603E;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -5037,7 +5412,22 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5054,17 +5444,17 @@ static void init_proc_604E (CPUPPCState *env)
gen_spr_ne_601(env);
gen_spr_604(env);
/* XXX : not implemented */
- spr_register(env, SPR_MMCR1, "MMCR1",
+ spr_register(env, SPR_7XX_MMCR1, "MMCR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC3, "PMC3",
+ spr_register(env, SPR_7XX_PMC3, "PMC3",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC4, "PMC4",
+ spr_register(env, SPR_7XX_PMC4, "PMC4",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
@@ -5105,7 +5495,22 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5160,7 +5565,22 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5223,7 +5643,22 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5409,7 +5844,22 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5476,7 +5926,22 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5548,7 +6013,22 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5620,7 +6100,22 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5683,7 +6178,22 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_7x5;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -5754,7 +6264,22 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
PPC_SEGMENT | PPC_EXTERN;
- pcc->msr_mask = 0x000000000005FF77ULL;
+ pcc->msr_mask = (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
pcc->excp_model = POWERPC_EXCP_7x5;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -5812,7 +6337,23 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5880,7 +6421,23 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -5926,22 +6483,22 @@ static void init_proc_7440 (CPUPPCState *env)
0x00000000);
/* PMC */
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -5974,7 +6531,23 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA | PPC_74xx_TLB |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -6043,22 +6616,22 @@ static void init_proc_7450 (CPUPPCState *env)
0x00000000);
/* PMC */
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -6091,7 +6664,23 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA | PPC_74xx_TLB |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -6129,22 +6718,22 @@ static void init_proc_7445 (CPUPPCState *env)
0x00000000);
/* PMC */
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -6211,7 +6800,23 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA | PPC_74xx_TLB |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -6251,22 +6856,22 @@ static void init_proc_7455 (CPUPPCState *env)
0x00000000);
/* PMC */
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -6333,7 +6938,23 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA | PPC_74xx_TLB |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -6397,22 +7018,22 @@ static void init_proc_7457 (CPUPPCState *env)
0x00000000);
/* PMC */
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -6479,7 +7100,23 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
PPC_MEM_TLBIA | PPC_74xx_TLB |
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
pcc->excp_model = POWERPC_EXCP_74xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
@@ -6518,22 +7155,22 @@ static void init_proc_e600 (CPUPPCState *env)
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC5, "PMC5",
+ spr_register(env, SPR_7XX_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC5, "UPMC5",
+ spr_register(env, SPR_7XX_UPMC5, "UPMC5",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_PMC6, "PMC6",
+ spr_register(env, SPR_7XX_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
- spr_register(env, SPR_UPMC6, "UPMC6",
+ spr_register(env, SPR_7XX_UPMC6, "UPMC6",
&spr_read_ureg, SPR_NOACCESS,
&spr_read_ureg, SPR_NOACCESS,
0x00000000);
@@ -6601,7 +7238,23 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
PPC_SEGMENT | PPC_EXTERN |
PPC_ALTIVEC;
pcc->insns_flags2 = PPC_NONE;
- pcc->msr_mask = 0x000000000205FF77ULL;
+ pcc->msr_mask = (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_ILE) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_EP) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
@@ -6621,246 +7274,628 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
#define POWERPC970_HID5_INIT 0x00000000
#endif
+enum BOOK3S_CPU_TYPE {
+ BOOK3S_CPU_970,
+ BOOK3S_CPU_POWER5PLUS,
+ BOOK3S_CPU_POWER6,
+ BOOK3S_CPU_POWER7,
+ BOOK3S_CPU_POWER8
+};
+
+static void gen_fscr_facility_check(void *opaque, int facility_sprn, int bit,
+ int sprn, int cause)
+{
+ TCGv_i32 t1 = tcg_const_i32(bit);
+ TCGv_i32 t2 = tcg_const_i32(sprn);
+ TCGv_i32 t3 = tcg_const_i32(cause);
+
+ gen_update_current_nip(opaque);
+ gen_helper_fscr_facility_check(cpu_env, t1, t2, t3);
+
+ tcg_temp_free_i32(t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t1);
+}
+
+static void gen_msr_facility_check(void *opaque, int facility_sprn, int bit,
+ int sprn, int cause)
+{
+ TCGv_i32 t1 = tcg_const_i32(bit);
+ TCGv_i32 t2 = tcg_const_i32(sprn);
+ TCGv_i32 t3 = tcg_const_i32(cause);
+
+ gen_update_current_nip(opaque);
+ gen_helper_msr_facility_check(cpu_env, t1, t2, t3);
+
+ tcg_temp_free_i32(t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t1);
+}
+
+static void spr_read_prev_upper32(void *opaque, int gprn, int sprn)
+{
+ TCGv spr_up = tcg_temp_new();
+ TCGv spr = tcg_temp_new();
+
+ gen_load_spr(spr, sprn - 1);
+ tcg_gen_shri_tl(spr_up, spr, 32);
+ tcg_gen_ext32u_tl(cpu_gpr[gprn], spr_up);
+
+ tcg_temp_free(spr);
+ tcg_temp_free(spr_up);
+}
+
+static void spr_write_prev_upper32(void *opaque, int sprn, int gprn)
+{
+ TCGv spr = tcg_temp_new();
+
+ gen_load_spr(spr, sprn - 1);
+ tcg_gen_deposit_tl(spr, spr, cpu_gpr[gprn], 32, 32);
+ gen_store_spr(sprn - 1, spr);
+
+ tcg_temp_free(spr);
+}
+
static int check_pow_970 (CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00600000)
+ if (env->spr[SPR_HID0] & (HID0_DEEPNAP | HID0_DOZE | HID0_NAP)) {
return 1;
+ }
return 0;
}
-static void init_proc_970 (CPUPPCState *env)
+static void gen_spr_970_hid(CPUPPCState *env)
{
- gen_spr_ne_601(env);
- gen_spr_7xx(env);
- /* Time base */
- gen_tbl(env);
/* Hardware implementation registers */
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_clear,
0x60000000);
- /* XXX : not implemented */
spr_register(env, SPR_HID1, "HID1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* XXX : not implemented */
spr_register(env, SPR_970_HID5, "HID5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
POWERPC970_HID5_INIT);
- /* Memory management */
- /* XXX: not correct */
- gen_low_BATs(env);
+}
+
+static void gen_spr_970_hior(CPUPPCState *env)
+{
spr_register(env, SPR_HIOR, "SPR_HIOR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_hior, &spr_write_hior,
0x00000000);
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
-#endif
- init_excp_970(env);
- env->dcache_line_size = 128;
- env->icache_line_size = 128;
- /* Allocate hardware IRQ controller */
- ppc970_irq_init(env);
+}
+
+static void gen_spr_970_lpar(CPUPPCState *env)
+{
+ /* Logical partitionning */
+ /* PPC970: HID4 is effectively the LPCR */
+ spr_register(env, SPR_970_HID4, "HID4",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+}
+
+static void gen_spr_book3s_common(CPUPPCState *env)
+{
+ spr_register(env, SPR_CTRL, "SPR_CTRL",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_UCTRL, "SPR_UCTRL",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, SPR_NOACCESS,
+ 0x00000000);
+}
+
+static void gen_spr_book3s_altivec(CPUPPCState *env)
+{
+ if (!(env->insns_flags & PPC_ALTIVEC)) {
+ return;
+ }
+
+ spr_register_kvm(env, SPR_VRSAVE, "VRSAVE",
+ &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_VRSAVE, 0x00000000);
+
/* Can't find information on what this should be on reset. This
* value is the one used by 74xx processors. */
vscr_init(env, 0x00010000);
}
-POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
+static void gen_spr_book3s_dbg(CPUPPCState *env)
{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+ /*
+ * TODO: different specs define different scopes for these,
+ * will have to address this:
+ * 970: super/write and super/read
+ * powerisa 2.03..2.04: hypv/write and super/read.
+ * powerisa 2.05 and newer: hypv/write and hypv/read.
+ */
+ spr_register_kvm(env, SPR_DABR, "DABR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_DABR, 0x00000000);
+ spr_register_kvm(env, SPR_DABRX, "DABRX",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_DABRX, 0x00000000);
+}
- dc->desc = "PowerPC 970";
- pcc->init_proc = init_proc_970;
- pcc->check_pow = check_pow_970;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
- PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
- PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
- PPC_FLOAT_STFIWX |
- PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
- PPC_MEM_SYNC | PPC_MEM_EIEIO |
- PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
- PPC_64B | PPC_ALTIVEC |
- PPC_SEGMENT_64B | PPC_SLBI;
- pcc->msr_mask = 0x900000000204FF36ULL;
- pcc->mmu_model = POWERPC_MMU_64B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
-#endif
- pcc->excp_model = POWERPC_EXCP_970;
- pcc->bus_model = PPC_FLAGS_INPUT_970;
- pcc->bfd_mach = bfd_mach_ppc64;
- pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
- POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
- POWERPC_FLAG_BUS_CLK;
- pcc->l1_dcache_size = 0x8000;
- pcc->l1_icache_size = 0x10000;
+static void gen_spr_970_dbg(CPUPPCState *env)
+{
+ /* Breakpoints */
+ spr_register(env, SPR_IABR, "IABR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
}
-static int check_pow_970FX (CPUPPCState *env)
+static void gen_spr_book3s_pmu_sup(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00600000)
- return 1;
+ spr_register_kvm(env, SPR_POWER_MMCR0, "MMCR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCR0, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_MMCR1, "MMCR1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCR1, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_MMCRA, "MMCRA",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCRA, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC1, "PMC1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC1, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC2, "PMC2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC2, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC3, "PMC3",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC3, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC4, "PMC4",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC4, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC5, "PMC5",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC5, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_PMC6, "PMC6",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC6, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_SIAR, "SIAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_SIAR, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_SDAR, "SDAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_SDAR, 0x00000000);
+}
- return 0;
+static void gen_spr_book3s_pmu_user(CPUPPCState *env)
+{
+ spr_register(env, SPR_POWER_UMMCR0, "UMMCR0",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UMMCR1, "UMMCR1",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UMMCRA, "UMMCRA",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC1, "UPMC1",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC2, "UPMC2",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC3, "UPMC3",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC4, "UPMC4",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC5, "UPMC5",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_UPMC6, "UPMC6",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_USIAR, "USIAR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+ spr_register(env, SPR_POWER_USDAR, "USDAR",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
}
-static void init_proc_970FX (CPUPPCState *env)
+static void gen_spr_970_pmu_sup(CPUPPCState *env)
{
- gen_spr_ne_601(env);
- gen_spr_7xx(env);
- /* Time base */
- gen_tbl(env);
- /* Hardware implementation registers */
- /* XXX : not implemented */
- spr_register(env, SPR_HID0, "HID0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_clear,
- 0x60000000);
- /* XXX : not implemented */
- spr_register(env, SPR_HID1, "HID1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ spr_register_kvm(env, SPR_970_PMC7, "PMC7",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC7, 0x00000000);
+ spr_register_kvm(env, SPR_970_PMC8, "PMC8",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC8, 0x00000000);
+}
+
+static void gen_spr_970_pmu_user(CPUPPCState *env)
+{
+ spr_register(env, SPR_970_UPMC7, "UPMC7",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_970_HID5, "HID5",
+ spr_register(env, SPR_970_UPMC8, "UPMC8",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+}
+
+static void gen_spr_power8_pmu_sup(CPUPPCState *env)
+{
+ spr_register_kvm(env, SPR_POWER_MMCR2, "MMCR2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCR2, 0x00000000);
+ spr_register_kvm(env, SPR_POWER_MMCRS, "MMCRS",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCRS, 0x00000000);
+}
+
+static void gen_spr_power8_pmu_user(CPUPPCState *env)
+{
+ spr_register(env, SPR_POWER_UMMCR2, "UMMCR2",
+ &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_ureg, &spr_write_ureg,
+ 0x00000000);
+}
+
+static void gen_spr_power5p_ear(CPUPPCState *env)
+{
+ /* External access control */
+ spr_register(env, SPR_EAR, "EAR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
- POWERPC970_HID5_INIT);
- /* Memory management */
- /* XXX: not correct */
- gen_low_BATs(env);
- spr_register(env, SPR_HIOR, "SPR_HIOR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_hior, &spr_write_hior,
0x00000000);
- spr_register(env, SPR_CTRL, "SPR_CTRL",
+}
+
+static void gen_spr_power5p_lpar(CPUPPCState *env)
+{
+ /* Logical partitionning */
+ spr_register_kvm(env, SPR_LPCR, "LPCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_LPCR, 0x00000000);
+}
+
+static void gen_spr_book3s_ids(CPUPPCState *env)
+{
+ /* Processor identification */
+ spr_register(env, SPR_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_generic,
+ &spr_read_generic, &spr_write_pir,
0x00000000);
- spr_register(env, SPR_UCTRL, "SPR_UCTRL",
+}
+
+static void gen_spr_power8_ids(CPUPPCState *env)
+{
+ /* Thread identification */
+ spr_register(env, SPR_TIR, "TIR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000);
- spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
+}
+
+static void gen_spr_book3s_purr(CPUPPCState *env)
+{
#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 64;
+ /* PURR & SPURR: Hack - treat these as aliases for the TB for now */
+ spr_register_kvm(env, SPR_PURR, "PURR",
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, SPR_NOACCESS,
+ KVM_REG_PPC_PURR, 0x00000000);
+ spr_register_kvm(env, SPR_SPURR, "SPURR",
+ &spr_read_purr, SPR_NOACCESS,
+ &spr_read_purr, SPR_NOACCESS,
+ KVM_REG_PPC_SPURR, 0x00000000);
#endif
- init_excp_970(env);
- env->dcache_line_size = 128;
- env->icache_line_size = 128;
- /* Allocate hardware IRQ controller */
- ppc970_irq_init(env);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
- vscr_init(env, 0x00010000);
}
-POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
+static void gen_spr_power6_dbg(CPUPPCState *env)
{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 970FX (aka G5)";
- pcc->init_proc = init_proc_970FX;
- pcc->check_pow = check_pow_970FX;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
- PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
- PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
- PPC_FLOAT_STFIWX |
- PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
- PPC_MEM_SYNC | PPC_MEM_EIEIO |
- PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
- PPC_64B | PPC_ALTIVEC |
- PPC_SEGMENT_64B | PPC_SLBI;
- pcc->msr_mask = 0x800000000204FF36ULL;
- pcc->mmu_model = POWERPC_MMU_64B;
-#if defined(CONFIG_SOFTMMU)
- pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#if !defined(CONFIG_USER_ONLY)
+ spr_register(env, SPR_CFAR, "SPR_CFAR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_cfar, &spr_write_cfar,
+ 0x00000000);
#endif
- pcc->excp_model = POWERPC_EXCP_970;
- pcc->bus_model = PPC_FLAGS_INPUT_970;
- pcc->bfd_mach = bfd_mach_ppc64;
- pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
- POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
- POWERPC_FLAG_BUS_CLK;
- pcc->l1_dcache_size = 0x8000;
- pcc->l1_icache_size = 0x10000;
}
-static int check_pow_970MP (CPUPPCState *env)
+static void gen_spr_power5p_common(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x01C00000)
- return 1;
-
- return 0;
+ spr_register_kvm(env, SPR_PPR, "PPR",
+ &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PPR, 0x00000000);
}
-static void init_proc_970MP (CPUPPCState *env)
+static void gen_spr_power6_common(CPUPPCState *env)
{
- gen_spr_ne_601(env);
- gen_spr_7xx(env);
- /* Time base */
- gen_tbl(env);
- /* Hardware implementation registers */
- /* XXX : not implemented */
- spr_register(env, SPR_HID0, "HID0",
+#if !defined(CONFIG_USER_ONLY)
+ spr_register_kvm(env, SPR_DSCR, "SPR_DSCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_DSCR, 0x00000000);
+#endif
+ /*
+ * Register PCR to report POWERPC_EXCP_PRIV_REG instead of
+ * POWERPC_EXCP_INVAL_SPR.
+ */
+ spr_register(env, SPR_PCR, "PCR",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_clear,
- 0x60000000);
- /* XXX : not implemented */
- spr_register(env, SPR_HID1, "HID1",
SPR_NOACCESS, SPR_NOACCESS,
+ 0x00000000);
+}
+
+static void spr_read_tar(void *opaque, int gprn, int sprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
+ spr_read_generic(opaque, gprn, sprn);
+}
+
+static void spr_write_tar(void *opaque, int sprn, int gprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
+ spr_write_generic(opaque, sprn, gprn);
+}
+
+static void gen_spr_power8_tce_address_control(CPUPPCState *env)
+{
+ spr_register(env, SPR_TAR, "TAR",
+ &spr_read_tar, &spr_write_tar,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_970_HID5, "HID5",
- SPR_NOACCESS, SPR_NOACCESS,
+}
+
+static void spr_read_tm(void *opaque, int gprn, int sprn)
+{
+ gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+ spr_read_generic(opaque, gprn, sprn);
+}
+
+static void spr_write_tm(void *opaque, int sprn, int gprn)
+{
+ gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+ spr_write_generic(opaque, sprn, gprn);
+}
+
+static void spr_read_tm_upper32(void *opaque, int gprn, int sprn)
+{
+ gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+ spr_read_prev_upper32(opaque, gprn, sprn);
+}
+
+static void spr_write_tm_upper32(void *opaque, int sprn, int gprn)
+{
+ gen_msr_facility_check(opaque, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
+ spr_write_prev_upper32(opaque, sprn, gprn);
+}
+
+static void gen_spr_power8_tm(CPUPPCState *env)
+{
+ spr_register_kvm(env, SPR_TFHAR, "TFHAR",
+ &spr_read_tm, &spr_write_tm,
+ &spr_read_tm, &spr_write_tm,
+ KVM_REG_PPC_TFHAR, 0x00000000);
+ spr_register_kvm(env, SPR_TFIAR, "TFIAR",
+ &spr_read_tm, &spr_write_tm,
+ &spr_read_tm, &spr_write_tm,
+ KVM_REG_PPC_TFIAR, 0x00000000);
+ spr_register_kvm(env, SPR_TEXASR, "TEXASR",
+ &spr_read_tm, &spr_write_tm,
+ &spr_read_tm, &spr_write_tm,
+ KVM_REG_PPC_TEXASR, 0x00000000);
+ spr_register(env, SPR_TEXASRU, "TEXASRU",
+ &spr_read_tm_upper32, &spr_write_tm_upper32,
+ &spr_read_tm_upper32, &spr_write_tm_upper32,
+ 0x00000000);
+}
+
+static void spr_read_ebb(void *opaque, int gprn, int sprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
+ spr_read_generic(opaque, gprn, sprn);
+}
+
+static void spr_write_ebb(void *opaque, int sprn, int gprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
+ spr_write_generic(opaque, sprn, gprn);
+}
+
+static void spr_read_ebb_upper32(void *opaque, int gprn, int sprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
+ spr_read_prev_upper32(opaque, gprn, sprn);
+}
+
+static void spr_write_ebb_upper32(void *opaque, int sprn, int gprn)
+{
+ gen_fscr_facility_check(opaque, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
+ spr_write_prev_upper32(opaque, sprn, gprn);
+}
+
+static void gen_spr_power8_ebb(CPUPPCState *env)
+{
+ spr_register(env, SPR_BESCRS, "BESCRS",
+ &spr_read_ebb, &spr_write_ebb,
&spr_read_generic, &spr_write_generic,
- POWERPC970_HID5_INIT);
- /* XXX : not implemented */
- /* Memory management */
- /* XXX: not correct */
- gen_low_BATs(env);
- spr_register(env, SPR_HIOR, "SPR_HIOR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_hior, &spr_write_hior,
0x00000000);
- /* Logical partitionning */
- spr_register_kvm(env, SPR_LPCR, "LPCR",
+ spr_register(env, SPR_BESCRSU, "BESCRSU",
+ &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+ &spr_read_prev_upper32, &spr_write_prev_upper32,
+ 0x00000000);
+ spr_register(env, SPR_BESCRR, "BESCRR",
+ &spr_read_ebb, &spr_write_ebb,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_BESCRRU, "BESCRRU",
+ &spr_read_ebb_upper32, &spr_write_ebb_upper32,
+ &spr_read_prev_upper32, &spr_write_prev_upper32,
+ 0x00000000);
+ spr_register_kvm(env, SPR_EBBHR, "EBBHR",
+ &spr_read_ebb, &spr_write_ebb,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_EBBHR, 0x00000000);
+ spr_register_kvm(env, SPR_EBBRR, "EBBRR",
+ &spr_read_ebb, &spr_write_ebb,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_EBBRR, 0x00000000);
+ spr_register_kvm(env, SPR_BESCR, "BESCR",
+ &spr_read_ebb, &spr_write_ebb,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_BESCR, 0x00000000);
+}
+
+static void gen_spr_power8_fscr(CPUPPCState *env)
+{
+#if defined(CONFIG_USER_ONLY)
+ target_ulong initval = 1ULL << FSCR_TAR;
+#else
+ target_ulong initval = 0;
+#endif
+ spr_register_kvm(env, SPR_FSCR, "FSCR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_LPCR, 0x00000000);
+ KVM_REG_PPC_FSCR, initval);
+}
+
+static void init_proc_book3s_64(CPUPPCState *env, int version)
+{
+ gen_spr_ne_601(env);
+ gen_tbl(env);
+ gen_spr_book3s_altivec(env);
+ gen_spr_book3s_pmu_sup(env);
+ gen_spr_book3s_pmu_user(env);
+ gen_spr_book3s_common(env);
+
+ switch (version) {
+ case BOOK3S_CPU_970:
+ case BOOK3S_CPU_POWER5PLUS:
+ gen_spr_970_hid(env);
+ gen_spr_970_hior(env);
+ gen_low_BATs(env);
+ gen_spr_970_pmu_sup(env);
+ gen_spr_970_pmu_user(env);
+ break;
+ case BOOK3S_CPU_POWER7:
+ case BOOK3S_CPU_POWER8:
+ gen_spr_book3s_ids(env);
+ gen_spr_amr(env);
+ gen_spr_book3s_purr(env);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (version >= BOOK3S_CPU_POWER5PLUS) {
+ gen_spr_power5p_common(env);
+ gen_spr_power5p_lpar(env);
+ gen_spr_power5p_ear(env);
+ } else {
+ gen_spr_970_lpar(env);
+ }
+ if (version == BOOK3S_CPU_970) {
+ gen_spr_970_dbg(env);
+ }
+ if (version >= BOOK3S_CPU_POWER6) {
+ gen_spr_power6_common(env);
+ gen_spr_power6_dbg(env);
+ }
+ if (version >= BOOK3S_CPU_POWER8) {
+ gen_spr_power8_tce_address_control(env);
+ gen_spr_power8_ids(env);
+ gen_spr_power8_ebb(env);
+ gen_spr_power8_fscr(env);
+ gen_spr_power8_pmu_sup(env);
+ gen_spr_power8_pmu_user(env);
+ gen_spr_power8_tm(env);
+ }
+ if (version < BOOK3S_CPU_POWER8) {
+ gen_spr_book3s_dbg(env);
+ }
#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
+ switch (version) {
+ case BOOK3S_CPU_970:
+ case BOOK3S_CPU_POWER5PLUS:
+ env->slb_nr = 64;
+ break;
+ case BOOK3S_CPU_POWER7:
+ case BOOK3S_CPU_POWER8:
+ default:
+ env->slb_nr = 32;
+ break;
+ }
#endif
- init_excp_970(env);
+ /* Allocate hardware IRQ controller */
+ switch (version) {
+ case BOOK3S_CPU_970:
+ case BOOK3S_CPU_POWER5PLUS:
+ init_excp_970(env);
+ ppc970_irq_init(env);
+ break;
+ case BOOK3S_CPU_POWER7:
+ case BOOK3S_CPU_POWER8:
+ init_excp_POWER7(env);
+ ppcPOWER7_irq_init(env);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
env->dcache_line_size = 128;
env->icache_line_size = 128;
- /* Allocate hardware IRQ controller */
- ppc970_irq_init(env);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
- vscr_init(env, 0x00010000);
}
-POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
+static void init_proc_970(CPUPPCState *env)
+{
+ init_proc_book3s_64(env, BOOK3S_CPU_970);
+}
+
+POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
- dc->desc = "PowerPC 970 MP";
- pcc->init_proc = init_proc_970MP;
- pcc->check_pow = check_pow_970MP;
+ dc->desc = "PowerPC 970";
+ pcc->init_proc = init_proc_970;
+ pcc->check_pow = check_pow_970;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6870,7 +7905,21 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI;
- pcc->msr_mask = 0x900000000204FF36ULL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_64B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -6887,61 +7936,7 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
static void init_proc_power5plus(CPUPPCState *env)
{
- gen_spr_ne_601(env);
- gen_spr_7xx(env);
- /* Time base */
- gen_tbl(env);
- /* Hardware implementation registers */
- /* XXX : not implemented */
- spr_register(env, SPR_HID0, "HID0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_clear,
- 0x60000000);
- /* XXX : not implemented */
- spr_register(env, SPR_HID1, "HID1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_970_HID5, "HID5",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- POWERPC970_HID5_INIT);
- /* Memory management */
- /* XXX: not correct */
- gen_low_BATs(env);
- spr_register(env, SPR_HIOR, "SPR_HIOR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_hior, &spr_write_hior,
- 0x00000000);
- spr_register(env, SPR_CTRL, "SPR_CTRL",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_UCTRL, "SPR_UCTRL",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, SPR_NOACCESS,
- 0x00000000);
- spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Logical partitionning */
- spr_register_kvm(env, SPR_LPCR, "LPCR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_LPCR, 0x00000000);
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 64;
-#endif
- init_excp_970(env);
- env->dcache_line_size = 128;
- env->icache_line_size = 128;
- /* Allocate hardware IRQ controller */
- ppc970_irq_init(env);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
- vscr_init(env, 0x00010000);
+ init_proc_book3s_64(env, BOOK3S_CPU_POWER5PLUS);
}
POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
@@ -6952,7 +7947,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER5";
dc->desc = "POWER5+";
pcc->init_proc = init_proc_power5plus;
- pcc->check_pow = check_pow_970FX;
+ pcc->check_pow = check_pow_970;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6962,7 +7957,21 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B |
PPC_SEGMENT_64B | PPC_SLBI;
- pcc->msr_mask = 0x800000000204FF36ULL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_POW) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_64B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -6977,83 +7986,79 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->l1_icache_size = 0x10000;
}
-static void init_proc_POWER7 (CPUPPCState *env)
+static void powerpc_get_compat(Object *obj, Visitor *v,
+ void *opaque, const char *name, Error **errp)
{
- gen_spr_ne_601(env);
- gen_spr_7xx(env);
- /* Time base */
- gen_tbl(env);
- /* Processor identification */
- spr_register(env, SPR_PIR, "PIR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_pir,
- 0x00000000);
-#if !defined(CONFIG_USER_ONLY)
- /* PURR & SPURR: Hack - treat these as aliases for the TB for now */
- spr_register_kvm(env, SPR_PURR, "PURR",
- &spr_read_purr, SPR_NOACCESS,
- &spr_read_purr, SPR_NOACCESS,
- KVM_REG_PPC_PURR, 0x00000000);
- spr_register_kvm(env, SPR_SPURR, "SPURR",
- &spr_read_purr, SPR_NOACCESS,
- &spr_read_purr, SPR_NOACCESS,
- KVM_REG_PPC_SPURR, 0x00000000);
- spr_register(env, SPR_CFAR, "SPR_CFAR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_cfar, &spr_write_cfar,
- 0x00000000);
- spr_register_kvm(env, SPR_DSCR, "SPR_DSCR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_DSCR, 0x00000000);
- spr_register_kvm(env, SPR_MMCRA, "SPR_MMCRA",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_MMCRA, 0x00000000);
- spr_register_kvm(env, SPR_PMC5, "SPR_PMC5",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_PMC5, 0x00000000);
- spr_register_kvm(env, SPR_PMC6, "SPR_PMC6",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_PMC6, 0x00000000);
-#endif /* !CONFIG_USER_ONLY */
- gen_spr_amr(env);
- /* XXX : not implemented */
- spr_register(env, SPR_CTRL, "SPR_CTRLT",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_generic,
- 0x80800000);
- spr_register(env, SPR_UCTRL, "SPR_CTRLF",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, SPR_NOACCESS,
- 0x80800000);
- spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_PPR, "PPR",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Logical partitionning */
- spr_register_kvm(env, SPR_LPCR, "LPCR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- KVM_REG_PPC_LPCR, 0x00000000);
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
-#endif
- init_excp_POWER7(env);
- env->dcache_line_size = 128;
- env->icache_line_size = 128;
+ char *value = (char *)"";
+ Property *prop = opaque;
+ uint32_t *max_compat = qdev_get_prop_ptr(DEVICE(obj), prop);
- /* Allocate hardware IRQ controller */
- ppcPOWER7_irq_init(env);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
- vscr_init(env, 0x00010000);
+ switch (*max_compat) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ value = (char *)"power6";
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ value = (char *)"power7";
+ break;
+ case CPU_POWERPC_LOGICAL_2_07:
+ value = (char *)"power8";
+ break;
+ case 0:
+ break;
+ default:
+ error_setg(errp, "Internal error: compat is set to %x",
+ max_compat ? *max_compat : -1);
+ break;
+ }
+
+ visit_type_str(v, &value, name, errp);
+}
+
+static void powerpc_set_compat(Object *obj, Visitor *v,
+ void *opaque, const char *name, Error **errp)
+{
+ Error *error = NULL;
+ char *value = NULL;
+ Property *prop = opaque;
+ uint32_t *max_compat = qdev_get_prop_ptr(DEVICE(obj), prop);
+
+ visit_type_str(v, &value, name, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ if (strcmp(value, "power6") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_05;
+ } else if (strcmp(value, "power7") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_06;
+ } else if (strcmp(value, "power8") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_07;
+ } else {
+ error_setg(errp, "Invalid compatibility mode \"%s\"", value);
+ }
+
+ g_free(value);
+}
+
+static PropertyInfo powerpc_compat_propinfo = {
+ .name = "str",
+ .legacy_name = "powerpc-server-compat",
+ .get = powerpc_get_compat,
+ .set = powerpc_set_compat,
+};
+
+#define DEFINE_PROP_POWERPC_COMPAT(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, powerpc_compat_propinfo, uint32_t)
+
+static Property powerpc_servercpu_properties[] = {
+ DEFINE_PROP_POWERPC_COMPAT("compat", PowerPCCPU, max_compat),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void init_proc_POWER7 (CPUPPCState *env)
+{
+ init_proc_book3s_64(env, BOOK3S_CPU_POWER7);
}
POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
@@ -7063,8 +8068,10 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7083,7 +8090,22 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
PPC2_FP_TST_ISA206;
- pcc->msr_mask = 0x800000000280FF37ULL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_VSX) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -7097,6 +8119,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
+ pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
@@ -7106,8 +8129,10 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7+";
dc->desc = "POWER7+";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7P_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7126,7 +8151,22 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
PPC2_FP_TST_ISA206;
- pcc->msr_mask = 0x800000000280FF37ULL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_VSX) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -7140,18 +8180,12 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
+ pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
static void init_proc_POWER8(CPUPPCState *env)
{
- /* inherit P7 */
- init_proc_POWER7(env);
-
- /* P8 supports the TAR */
- spr_register(env, SPR_TAR, "TAR",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
+ init_proc_book3s_64(env, BOOK3S_CPU_POWER8);
}
POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
@@ -7161,8 +8195,10 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER8";
dc->desc = "POWER8";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER8_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER8;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7183,7 +8219,23 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S;
- pcc->msr_mask = 0x800000000280FF37ULL;
+ pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_TM) |
+ (1ull << MSR_VR) |
+ (1ull << MSR_VSX) |
+ (1ull << MSR_EE) |
+ (1ull << MSR_PR) |
+ (1ull << MSR_FP) |
+ (1ull << MSR_ME) |
+ (1ull << MSR_FE0) |
+ (1ull << MSR_SE) |
+ (1ull << MSR_DE) |
+ (1ull << MSR_FE1) |
+ (1ull << MSR_IR) |
+ (1ull << MSR_DR) |
+ (1ull << MSR_PMM) |
+ (1ull << MSR_RI) |
+ (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -7197,6 +8249,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
+ pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
}
#endif /* defined (TARGET_PPC64) */
@@ -8083,6 +9136,63 @@ static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
}
}
+int ppc_get_compat_smt_threads(PowerPCCPU *cpu)
+{
+ int ret = smp_threads;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ switch (cpu->cpu_version) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ ret = 2;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ ret = 4;
+ break;
+ case CPU_POWERPC_LOGICAL_2_07:
+ ret = 8;
+ break;
+ default:
+ if (pcc->pcr_mask & PCR_COMPAT_2_06) {
+ ret = 4;
+ } else if (pcc->pcr_mask & PCR_COMPAT_2_05) {
+ ret = 2;
+ }
+ break;
+ }
+
+ return MIN(ret, smp_threads);
+}
+
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ int ret = 0;
+ CPUPPCState *env = &cpu->env;
+
+ cpu->cpu_version = cpu_version;
+
+ switch (cpu_version) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_05;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06_PLUS:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ default:
+ env->spr[SPR_PCR] = 0;
+ break;
+ }
+
+ if (kvm_enabled() && kvmppc_set_compat(cpu, cpu->max_compat) < 0) {
+ error_report("Unable to set compatibility mode in KVM");
+ ret = -1;
+ }
+
+ return ret;
+}
+
static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
{
ObjectClass *oc = (ObjectClass *)a;
@@ -8218,12 +9328,6 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
}
}
- for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
- if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) {
- return ppc_cpu_class_by_alias(&ppc_cpu_aliases[i]);
- }
- }
-
list = object_class_get_list(TYPE_POWERPC_CPU, false);
item = g_slist_find_custom(list, name, ppc_cpu_compare_class_name);
if (item != NULL) {
@@ -8231,7 +9335,17 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
}
g_slist_free(list);
- return ret;
+ if (ret) {
+ return ret;
+ }
+
+ for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
+ if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) {
+ return ppc_cpu_class_by_alias(&ppc_cpu_aliases[i]);
+ }
+ }
+
+ return NULL;
}
PowerPCCPU *cpu_ppc_init(const char *cpu_model)
@@ -8416,8 +9530,15 @@ static void ppc_cpu_reset(CPUState *s)
#if defined(CONFIG_USER_ONLY)
msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
+ msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
msr |= (target_ulong)1 << MSR_PR;
+#if defined(TARGET_PPC64)
+ msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
+#endif
+#if !defined(TARGET_WORDS_BIGENDIAN)
+ msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
+#endif
#endif
#if defined(TARGET_PPC64)
@@ -8519,6 +9640,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
pcc->parent_realize = dc->realize;
pcc->pvr = CPU_POWERPC_DEFAULT_MASK;
pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK;
+ pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
dc->realize = ppc_cpu_realizefn;
dc->unrealize = ppc_cpu_unrealizefn;