aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-02-13 20:33:28 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-02-13 20:33:28 +0000
commitcc5ce8b8b6be83e5fe3b668dbd061ad97c534e3f (patch)
treeee53aebdc8bc0e7e08c676fea9cf14d7b4ba71d8
parent48033ad678ae2def43bf0d543a2c4c3d2a93feaf (diff)
parent10717c26dbe1c138ba6af6d09a3bb9958d4fe3f2 (diff)
downloadqemu-cc5ce8b8b6be83e5fe3b668dbd061ad97c534e3f.zip
qemu-cc5ce8b8b6be83e5fe3b668dbd061ad97c534e3f.tar.gz
qemu-cc5ce8b8b6be83e5fe3b668dbd061ad97c534e3f.tar.bz2
Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220210' into staging
ppc-7.0 queue * Exception model rework (Fabiano) * Unused CPU models removal (Fabiano and Cédric) * Fix for VOF installation (Alexey) * Misc fixes # gpg: Signature made Thu 10 Feb 2022 12:59:07 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-ppc-20220210: (42 commits) spapr/vof: Install rom and nvram binaries docs: rstfy confidential guest documentation target/ppc: Change VSX instructions behavior to fill with zeros target/ppc: books: Remove excp_model argument from ppc_excp_apply_ail target/ppc: Assert if MSR bits differ from msr_mask during exceptions target/ppc: powerpc_excp: Move common code to the caller function target/ppc: Remove powerpc_excp_legacy target/ppc: 7xx: Set SRRs directly in exception code target/ppc: 7xx: Software TLB cleanup target/ppc: 7xx: System Reset cleanup target/ppc: 7xx: System Call exception cleanup target/ppc: 7xx: Program exception cleanup target/ppc: 7xx: External interrupt cleanup target/ppc: 7xx: Machine Check exception cleanup target/ppc: Simplify powerpc_excp_7xx target/ppc: Introduce powerpc_excp_7xx target/ppc: Merge 7x5 and 7x0 exception model IDs target/ppc: 6xx: Set SRRs directly in exception code target/ppc: 6xx: Software TLB exceptions cleanup target/ppc: 6xx: System Reset interrupt cleanup ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS2
-rw-r--r--docs/system/confidential-guest-support.rst (renamed from docs/confidential-guest-support.txt)15
-rw-r--r--docs/system/i386/amd-memory-encryption.rst (renamed from docs/amd-memory-encryption.txt)102
-rw-r--r--docs/system/index.rst1
-rw-r--r--docs/system/ppc/pseries.rst2
-rw-r--r--docs/system/target-i386.rst1
-rw-r--r--hw/ppc/ppc.c21
-rw-r--r--hw/ppc/prep.c9
-rw-r--r--linux-user/ppc/cpu_loop.c16
-rw-r--r--pc-bios/meson.build2
-rw-r--r--target/ppc/cpu-models.c8
-rw-r--r--target/ppc/cpu-models.h3
-rw-r--r--target/ppc/cpu-qom.h20
-rw-r--r--target/ppc/cpu.h39
-rw-r--r--target/ppc/cpu_init.c331
-rw-r--r--target/ppc/excp_helper.c887
-rw-r--r--target/ppc/fpu_helper.c26
-rw-r--r--target/ppc/helper.h13
-rw-r--r--target/ppc/helper_regs.c10
-rw-r--r--target/ppc/int_helper.c66
-rw-r--r--target/ppc/machine.c5
-rw-r--r--target/ppc/misc_helper.c40
-rw-r--r--target/ppc/mmu-hash32.c48
-rw-r--r--target/ppc/mmu-hash32.h9
-rw-r--r--target/ppc/mmu-radix64.c8
-rw-r--r--target/ppc/mmu_common.c21
-rw-r--r--target/ppc/mmu_helper.c84
-rw-r--r--target/ppc/spr_tcg.h8
-rw-r--r--target/ppc/timebase_helper.c20
-rw-r--r--target/ppc/translate.c842
-rw-r--r--target/ppc/translate/fp-impl.c.inc179
-rw-r--r--target/ppc/translate/vsx-impl.c.inc4
32 files changed, 592 insertions, 2250 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index b0b845f..4b3ae2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -408,7 +408,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org
S: Supported
-F: docs/amd-memory-encryption.txt
+F: docs/system/i386/amd-memory-encryption.rst
F: docs/system/i386/sgx.rst
F: target/i386/kvm/
F: target/i386/sev*
diff --git a/docs/confidential-guest-support.txt b/docs/system/confidential-guest-support.rst
index 71d07ba..0c490db 100644
--- a/docs/confidential-guest-support.txt
+++ b/docs/system/confidential-guest-support.rst
@@ -19,10 +19,10 @@ Running a Confidential Guest
To run a confidential guest you need to add two command line parameters:
-1. Use "-object" to create a "confidential guest support" object. The
+1. Use ``-object`` to create a "confidential guest support" object. The
type and parameters will vary with the specific mechanism to be
used
-2. Set the "confidential-guest-support" machine parameter to the ID of
+2. Set the ``confidential-guest-support`` machine parameter to the ID of
the object from (1).
Example (for AMD SEV)::
@@ -37,13 +37,8 @@ Supported mechanisms
Currently supported confidential guest mechanisms are:
-AMD Secure Encrypted Virtualization (SEV)
- docs/amd-memory-encryption.txt
-
-POWER Protected Execution Facility (PEF)
- docs/papr-pef.txt
-
-s390x Protected Virtualization (PV)
- docs/system/s390x/protvirt.rst
+* AMD Secure Encrypted Virtualization (SEV) (see :doc:`i386/amd-memory-encryption`)
+* POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`)
+* s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`)
Other mechanisms may be supported in future.
diff --git a/docs/amd-memory-encryption.txt b/docs/system/i386/amd-memory-encryption.rst
index ffca382..215946f 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/system/i386/amd-memory-encryption.rst
@@ -1,3 +1,6 @@
+AMD Secure Encrypted Virtualization (SEV)
+=========================================
+
Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
SEV is an extension to the AMD-V architecture which supports running encrypted
@@ -24,17 +27,18 @@ the hypervisor to satisfy the requested function.
Launching
---------
+
Boot images (such as bios) must be encrypted before a guest can be booted. The
-MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images: LAUNCH_START,
-LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
+``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images: ``LAUNCH_START``,
+``LAUNCH_UPDATE_DATA``, ``LAUNCH_MEASURE`` and ``LAUNCH_FINISH``. These four commands
together generate a fresh memory encryption key for the VM, encrypt the boot
images and provide a measurement than can be used as an attestation of a
successful launch.
-For a SEV-ES guest, the LAUNCH_UPDATE_VMSA command is also used to encrypt the
+For a SEV-ES guest, the ``LAUNCH_UPDATE_VMSA`` command is also used to encrypt the
guest register state, or VM save area (VMSA), for all of the guest vCPUs.
-LAUNCH_START is called first to create a cryptographic launch context within
+``LAUNCH_START`` is called first to create a cryptographic launch context within
the firmware. To create this context, guest owner must provide a guest policy,
its public Diffie-Hellman key (PDH) and session parameters. These inputs
should be treated as a binary blob and must be passed as-is to the SEV firmware.
@@ -45,37 +49,37 @@ in bad measurement). The guest policy is a 4-byte data structure containing
several flags that restricts what can be done on a running SEV guest.
See KM Spec section 3 and 6.2 for more details.
-The guest policy can be provided via the 'policy' property (see below)
+The guest policy can be provided via the ``policy`` property::
-# ${QEMU} \
- sev-guest,id=sev0,policy=0x1...\
+ # ${QEMU} \
+ sev-guest,id=sev0,policy=0x1...\
Setting the "SEV-ES required" policy bit (bit 2) will launch the guest as a
-SEV-ES guest (see below)
+SEV-ES guest::
-# ${QEMU} \
- sev-guest,id=sev0,policy=0x5...\
+ # ${QEMU} \
+ sev-guest,id=sev0,policy=0x5...\
The guest owner provided DH certificate and session parameters will be used to
establish a cryptographic session with the guest owner to negotiate keys used
for the attestation.
-The DH certificate and session blob can be provided via the 'dh-cert-file' and
-'session-file' properties (see below)
+The DH certificate and session blob can be provided via the ``dh-cert-file`` and
+``session-file`` properties::
-# ${QEMU} \
- sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
+ # ${QEMU} \
+ sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
-LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
-created via the LAUNCH_START command. If required, this command can be called
+``LAUNCH_UPDATE_DATA`` encrypts the memory region using the cryptographic context
+created via the ``LAUNCH_START`` command. If required, this command can be called
multiple times to encrypt different memory regions. The command also calculates
the measurement of the memory contents as it encrypts.
-LAUNCH_UPDATE_VMSA encrypts all the vCPU VMSAs for a SEV-ES guest using the
-cryptographic context created via the LAUNCH_START command. The command also
+``LAUNCH_UPDATE_VMSA`` encrypts all the vCPU VMSAs for a SEV-ES guest using the
+cryptographic context created via the ``LAUNCH_START`` command. The command also
calculates the measurement of the VMSAs as it encrypts them.
-LAUNCH_MEASURE can be used to retrieve the measurement of encrypted memory and,
+``LAUNCH_MEASURE`` can be used to retrieve the measurement of encrypted memory and,
for a SEV-ES guest, encrypted VMSAs. This measurement is a signature of the
memory contents and, for a SEV-ES guest, the VMSA contents, that can be sent
to the guest owner as an attestation that the memory and VMSAs were encrypted
@@ -85,27 +89,28 @@ Since the guest owner knows the initial contents of the guest at boot, the
attestation measurement can be verified by comparing it to what the guest owner
expects.
-LAUNCH_FINISH finalizes the guest launch and destroys the cryptographic
+``LAUNCH_FINISH`` finalizes the guest launch and destroys the cryptographic
context.
-See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
+See SEV KM API Spec ([SEVKM]_) 'Launching a guest' usage flow (Appendix A) for the
complete flow chart.
-To launch a SEV guest
+To launch a SEV guest::
-# ${QEMU} \
- -machine ...,confidential-guest-support=sev0 \
- -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
+ # ${QEMU} \
+ -machine ...,confidential-guest-support=sev0 \
+ -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
-To launch a SEV-ES guest
+To launch a SEV-ES guest::
-# ${QEMU} \
- -machine ...,confidential-guest-support=sev0 \
- -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x5
+ # ${QEMU} \
+ -machine ...,confidential-guest-support=sev0 \
+ -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x5
An SEV-ES guest has some restrictions as compared to a SEV guest. Because the
guest register state is encrypted and cannot be updated by the VMM/hypervisor,
a SEV-ES guest:
+
- Does not support SMM - SMM support requires updating the guest register
state.
- Does not support reboot - a system reset requires updating the guest register
@@ -114,35 +119,42 @@ a SEV-ES guest:
manage booting APs.
Debugging
------------
+---------
+
Since the memory contents of a SEV guest are encrypted, hypervisor access to
the guest memory will return cipher text. If the guest policy allows debugging,
then a hypervisor can use the DEBUG_DECRYPT and DEBUG_ENCRYPT commands to access
the guest memory region for debug purposes. This is not supported in QEMU yet.
Snapshot/Restore
------------------
+----------------
+
TODO
Live Migration
-----------------
+---------------
+
TODO
References
------------------
+----------
-AMD Memory Encryption whitepaper:
-https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+`AMD Memory Encryption whitepaper
+<https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf>`_
-Secure Encrypted Virtualization Key Management:
-[1] http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf
+.. [SEVKM] `Secure Encrypted Virtualization Key Management
+ <http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf>`_
KVM Forum slides:
-http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
-https://www.linux-kvm.org/images/9/94/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf
-
-AMD64 Architecture Programmer's Manual:
- http://support.amd.com/TechDocs/24593.pdf
- SME is section 7.10
- SEV is section 15.34
- SEV-ES is section 15.35
+
+* `AMD’s Virtualization Memory Encryption (2016)
+ <http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf>`_
+* `Extending Secure Encrypted Virtualization With SEV-ES (2018)
+ <https://www.linux-kvm.org/images/9/94/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf>`_
+
+`AMD64 Architecture Programmer's Manual:
+<http://support.amd.com/TechDocs/24593.pdf>`_
+
+* SME is section 7.10
+* SEV is section 15.34
+* SEV-ES is section 15.35
diff --git a/docs/system/index.rst b/docs/system/index.rst
index 73bbedb..23e30e2 100644
--- a/docs/system/index.rst
+++ b/docs/system/index.rst
@@ -34,3 +34,4 @@ or Hypervisor.Framework.
targets
security
multi-process
+ confidential-guest-support
diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst
index 569237d..d9b65ad 100644
--- a/docs/system/ppc/pseries.rst
+++ b/docs/system/ppc/pseries.rst
@@ -224,6 +224,8 @@ nested. Combinations not shown in the table are not available.
.. [3] Introduced on Power10 machines.
+.. _power-papr-protected-execution-facility-pef:
+
POWER (PAPR) Protected Execution Facility (PEF)
-----------------------------------------------
diff --git a/docs/system/target-i386.rst b/docs/system/target-i386.rst
index 4daa53c..96bf548 100644
--- a/docs/system/target-i386.rst
+++ b/docs/system/target-i386.rst
@@ -28,6 +28,7 @@ Architectural features
i386/cpu
i386/kvm-pv
i386/sgx
+ i386/amd-memory-encryption
.. _pcsys_005freq:
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 462c87d..ba7fa0f 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -1083,27 +1083,6 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
return &cpu_ppc_set_tb_clk;
}
-/* Specific helpers for POWER & PowerPC 601 RTC */
-void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
-{
- _cpu_ppc_store_tbu(env, value);
-}
-
-uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
-{
- return _cpu_ppc_load_tbu(env);
-}
-
-void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
-{
- cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
-}
-
-uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
-{
- return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
/*****************************************************************************/
/* PowerPC 40x timers */
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 25a2e86..bf622aa 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -255,13 +255,8 @@ static void ibm_40p_init(MachineState *machine)
exit(1);
}
- if (env->flags & POWERPC_FLAG_RTC_CLK) {
- /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
- cpu_ppc_tb_init(env, 7812500UL);
- } else {
- /* Set time-base frequency to 100 Mhz */
- cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
- }
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
qemu_register_reset(ppc_prep_reset, cpu);
/* PCI host */
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 46e6ffd..38097b0 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -54,14 +54,6 @@ uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
return cpu_ppc_get_tb(env);
}
-uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
-__attribute__ (( alias ("cpu_ppc_load_tbu") ));
-
-uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
-{
- return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
/* XXX: to be fixed */
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
{
@@ -289,14 +281,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n");
break;
- case POWERPC_EXCP_IO: /* IO error exception */
- cpu_abort(cs, "IO error exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- cpu_abort(cs, "Run mode exception while in user mode. "
- "Aborting\n");
- break;
case POWERPC_EXCP_EMUL: /* Emulation trap exception */
cpu_abort(cs, "Emulation trap exception not handled\n");
break;
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index 4ac7a55..c86dedf 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -81,6 +81,8 @@ blobs = files(
'opensbi-riscv32-generic-fw_dynamic.bin',
'opensbi-riscv64-generic-fw_dynamic.bin',
'npcm7xx_bootrom.bin',
+ 'vof.bin',
+ 'vof-nvram.bin',
)
if get_option('install_blobs')
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index a2c720c..976be5e 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -422,12 +422,6 @@
CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, e600)
/* 32 bits "classic" PowerPC */
/* PowerPC 6xx family */
- POWERPC_DEF("601_v0", CPU_POWERPC_601_v0, 601,
- "PowerPC 601v0")
- POWERPC_DEF("601_v1", CPU_POWERPC_601_v1, 601,
- "PowerPC 601v1")
- POWERPC_DEF("601_v2", CPU_POWERPC_601_v2, 601v,
- "PowerPC 601v2")
POWERPC_DEF("603", CPU_POWERPC_603, 603,
"PowerPC 603")
POWERPC_DEF("603e_v1.1", CPU_POWERPC_603E_v11, 603E,
@@ -859,8 +853,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "mpc8555", "mpc8555_v11" },
{ "mpc8555e", "mpc8555e_v11" },
{ "mpc8560", "mpc8560_v21" },
- { "601", "601_v2" },
- { "601v", "601_v2" },
{ "vanilla", "603" },
{ "603e", "603e_v4.1" },
{ "stretch", "603e_v4.1" },
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index 612978a..76775a7 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -205,9 +205,6 @@ enum {
#define CPU_POWERPC_MPC8641 CPU_POWERPC_e600
#define CPU_POWERPC_MPC8641D CPU_POWERPC_e600
/* PowerPC 6xx cores */
- CPU_POWERPC_601_v0 = 0x00010001,
- CPU_POWERPC_601_v1 = 0x00010001,
- CPU_POWERPC_601_v2 = 0x00010002,
CPU_POWERPC_603 = 0x00030100,
CPU_POWERPC_603E_v11 = 0x00060101,
CPU_POWERPC_603E_v12 = 0x00060102,
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 99a6b50..98facee 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -61,8 +61,6 @@ enum powerpc_mmu_t {
POWERPC_MMU_BOOKE = 0x00000008,
/* BookE 2.06 MMU model */
POWERPC_MMU_BOOKE206 = 0x00000009,
- /* PowerPC 601 MMU model (specific BATs format) */
- POWERPC_MMU_601 = 0x0000000A,
#define POWERPC_MMU_64 0x00010000
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
@@ -90,20 +88,10 @@ enum powerpc_excp_t {
POWERPC_EXCP_STD,
/* PowerPC 40x exception model */
POWERPC_EXCP_40x,
- /* PowerPC 601 exception model */
- POWERPC_EXCP_601,
- /* PowerPC 602 exception model */
- POWERPC_EXCP_602,
- /* PowerPC 603 exception model */
- POWERPC_EXCP_603,
- /* PowerPC G2 exception model */
- POWERPC_EXCP_G2,
- /* PowerPC 604 exception model */
- POWERPC_EXCP_604,
- /* PowerPC 7x0 exception model */
- POWERPC_EXCP_7x0,
- /* PowerPC 7x5 exception model */
- POWERPC_EXCP_7x5,
+ /* PowerPC 603/604/G2 exception model */
+ POWERPC_EXCP_6xx,
+ /* PowerPC 7xx exception model */
+ POWERPC_EXCP_7xx,
/* PowerPC 74xx exception model */
POWERPC_EXCP_74xx,
/* BookE exception model */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index dcd83b5..555c6b9 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -89,11 +89,9 @@ enum {
POWERPC_EXCP_VPU = 73, /* Vector unavailable exception */
/* 40x specific exceptions */
POWERPC_EXCP_PIT = 74, /* Programmable interval timer interrupt */
- /* 601 specific exceptions */
- POWERPC_EXCP_IO = 75, /* IO error exception */
- POWERPC_EXCP_RUNM = 76, /* Run mode exception */
+ /* Vectors 75-76 are 601 specific exceptions */
/* 602 specific exceptions */
- POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
+ POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
/* 602/603 specific exceptions */
POWERPC_EXCP_IFTLB = 78, /* Instruction fetch TLB miss */
POWERPC_EXCP_DLTLB = 79, /* Data load TLB miss */
@@ -632,8 +630,7 @@ enum {
POWERPC_FLAG_PX = 0x00000200,
POWERPC_FLAG_PMM = 0x00000400,
/* Flag for special features */
- /* Decrementer clock: RTC clock (POWER, 601) or bus clock */
- POWERPC_FLAG_RTC_CLK = 0x00010000,
+ /* Decrementer clock */
POWERPC_FLAG_BUS_CLK = 0x00020000,
/* Has CFAR */
POWERPC_FLAG_CFAR = 0x00040000,
@@ -643,8 +640,6 @@ enum {
POWERPC_FLAG_TM = 0x00100000,
/* Has SCV (ISA 3.00) */
POWERPC_FLAG_SCV = 0x00200000,
- /* Has HID0 for LE bit (601) */
- POWERPC_FLAG_HID0_LE = 0x00400000,
};
/*
@@ -655,7 +650,7 @@ enum {
* the MSR are validated in hreg_compute_hflags.
*/
enum {
- HFLAGS_LE = 0, /* MSR_LE -- comes from elsewhere on 601 */
+ HFLAGS_LE = 0, /* MSR_LE */
HFLAGS_HV = 1, /* computed from MSR_HV and other state */
HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */
HFLAGS_GTSE = 3, /* computed from SPR_LPCR[GTSE] */
@@ -1389,11 +1384,7 @@ void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value);
uint64_t cpu_ppc_load_purr(CPUPPCState *env);
void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value);
-uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env);
-uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
-void cpu_ppc601_store_rtcl(CPUPPCState *env, uint32_t value);
-void cpu_ppc601_store_rtcu(CPUPPCState *env, uint32_t value);
target_ulong load_40x_pit(CPUPPCState *env);
void store_40x_pit(CPUPPCState *env, target_ulong val);
void store_40x_dbcr0(CPUPPCState *env, uint32_t val);
@@ -1516,17 +1507,12 @@ typedef PowerPCCPU ArchCPU;
/* SPR definitions */
#define SPR_MQ (0x000)
#define SPR_XER (0x001)
-#define SPR_601_VRTCU (0x004)
-#define SPR_601_VRTCL (0x005)
-#define SPR_601_UDECR (0x006)
#define SPR_LR (0x008)
#define SPR_CTR (0x009)
#define SPR_UAMR (0x00D)
#define SPR_DSCR (0x011)
#define SPR_DSISR (0x012)
-#define SPR_DAR (0x013) /* DAE for PowerPC 601 */
-#define SPR_601_RTCU (0x014)
-#define SPR_601_RTCL (0x015)
+#define SPR_DAR (0x013)
#define SPR_DECR (0x016)
#define SPR_SDR1 (0x019)
#define SPR_SRR0 (0x01A)
@@ -2003,7 +1989,6 @@ typedef PowerPCCPU ArchCPU;
#define SPR_HID1 (0x3F1)
#define SPR_IABR (0x3F2)
#define SPR_40x_DBCR0 (0x3F2)
-#define SPR_601_HID2 (0x3F2)
#define SPR_Exxx_L1CSR0 (0x3F2)
#define SPR_ICTRL (0x3F3)
#define SPR_HID2 (0x3F3)
@@ -2019,7 +2004,6 @@ typedef PowerPCCPU ArchCPU;
#define DABR_MASK (~(target_ulong)0x7)
#define SPR_Exxx_BUCSR (0x3F5)
#define SPR_40x_IAC2 (0x3F5)
-#define SPR_601_HID5 (0x3F5)
#define SPR_40x_DAC1 (0x3F6)
#define SPR_MSSCR0 (0x3F6)
#define SPR_970_HID5 (0x3F6)
@@ -2052,7 +2036,6 @@ typedef PowerPCCPU ArchCPU;
#define SPR_403_PBL2 (0x3FE)
#define SPR_PIR (0x3FF)
#define SPR_403_PBU2 (0x3FF)
-#define SPR_601_HID15 (0x3FF)
#define SPR_604_HID15 (0x3FF)
#define SPR_E500_SVR (0x3FF)
@@ -2117,15 +2100,6 @@ enum {
#define PPC_RES PPC_INSNS_BASE
/* spr/msr access instructions */
#define PPC_MISC PPC_INSNS_BASE
- /* Deprecated instruction sets */
- /* Original POWER instruction set */
- PPC_POWER = 0x0000000000000002ULL,
- /* POWER2 instruction set extension */
- PPC_POWER2 = 0x0000000000000004ULL,
- /* Power RTC support */
- PPC_POWER_RTC = 0x0000000000000008ULL,
- /* Power-to-PowerPC bridge (601) */
- PPC_POWER_BR = 0x0000000000000010ULL,
/* 64 bits PowerPC instruction set */
PPC_64B = 0x0000000000000020ULL,
/* New 64 bits extensions (PowerPC 2.0x) */
@@ -2236,8 +2210,7 @@ enum {
/* popcntw and popcntd instructions */
PPC_POPCNTWD = 0x8000000000000000ULL,
-#define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_POWER | PPC_POWER2 \
- | PPC_POWER_RTC | PPC_POWER_BR | PPC_64B \
+#define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_64B \
| PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \
| PPC_ISEL | PPC_POPCNTB \
| PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index bf60529..d97f718 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -749,83 +749,6 @@ static void register_G2_sprs(CPUPPCState *env)
0x00000000);
}
-/* SPR specific to PowerPC 601 implementation */
-static void register_601_sprs(CPUPPCState *env)
-{
- /* Multiplication/division register */
- /* MQ */
- spr_register(env, SPR_MQ, "MQ",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* RTC registers */
- spr_register(env, SPR_601_RTCU, "RTCU",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_601_rtcu,
- 0x00000000);
- spr_register(env, SPR_601_VRTCU, "RTCU",
- &spr_read_601_rtcu, SPR_NOACCESS,
- &spr_read_601_rtcu, SPR_NOACCESS,
- 0x00000000);
- spr_register(env, SPR_601_RTCL, "RTCL",
- SPR_NOACCESS, SPR_NOACCESS,
- SPR_NOACCESS, &spr_write_601_rtcl,
- 0x00000000);
- spr_register(env, SPR_601_VRTCL, "RTCL",
- &spr_read_601_rtcl, SPR_NOACCESS,
- &spr_read_601_rtcl, SPR_NOACCESS,
- 0x00000000);
- /* Timer */
-#if 0 /* ? */
- spr_register(env, SPR_601_UDECR, "UDECR",
- &spr_read_decr, SPR_NOACCESS,
- &spr_read_decr, SPR_NOACCESS,
- 0x00000000);
-#endif
- /* External access control */
- /* XXX : not implemented */
- spr_register(env, SPR_EAR, "EAR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- spr_register(env, SPR_IBAT0U, "IBAT0U",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatu,
- 0x00000000);
- spr_register(env, SPR_IBAT0L, "IBAT0L",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatl,
- 0x00000000);
- spr_register(env, SPR_IBAT1U, "IBAT1U",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatu,
- 0x00000000);
- spr_register(env, SPR_IBAT1L, "IBAT1L",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatl,
- 0x00000000);
- spr_register(env, SPR_IBAT2U, "IBAT2U",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatu,
- 0x00000000);
- spr_register(env, SPR_IBAT2L, "IBAT2L",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatl,
- 0x00000000);
- spr_register(env, SPR_IBAT3U, "IBAT3U",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatu,
- 0x00000000);
- spr_register(env, SPR_IBAT3L, "IBAT3L",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_601_ubat, &spr_write_601_ubatl,
- 0x00000000);
- env->nb_BATs = 4;
-#endif
-}
-
static void register_74xx_sprs(CPUPPCState *env)
{
/* Processor identification */
@@ -2060,26 +1983,6 @@ static void init_excp_BookE(CPUPPCState *env)
#endif
}
-static void init_excp_601(CPUPPCState *env)
-{
-#if !defined(CONFIG_USER_ONLY)
- env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
- env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
- env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
- env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
- env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
- env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
- env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
- env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
- env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
- env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00;
- env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
- env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000;
- /* Hardware reset vector */
- env->hreset_vector = 0x00000100UL;
-#endif
-}
-
static void init_excp_603(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
@@ -2703,89 +2606,6 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
}
-static void init_proc_440x4(CPUPPCState *env)
-{
- /* Time base */
- register_tbl(env);
- register_BookE_sprs(env, 0x000000000000FFFFULL);
- register_440_sprs(env);
- register_usprgh_sprs(env);
- /* Processor identification */
- spr_register(env, SPR_BOOKE_PIR, "PIR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_pir,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC3, "IAC3",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC4, "IAC4",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC1, "DVC1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC2, "DVC2",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
- init_excp_BookE(env);
- env->dcache_line_size = 32;
- env->icache_line_size = 32;
- /* XXX: TODO: allocate internal IRQ controller */
-
- SET_FIT_PERIOD(12, 16, 20, 24);
- SET_WDT_PERIOD(20, 24, 28, 32);
-}
-
-POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 440x4";
- pcc->init_proc = init_proc_440x4;
- pcc->check_pow = check_pow_nocheck;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
- PPC_DCR | PPC_WRTEE |
- PPC_CACHE | PPC_CACHE_ICBI |
- PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
- PPC_MEM_TLBSYNC | PPC_MFTB |
- PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
- PPC_440_SPEC;
- 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;
- pcc->bfd_mach = bfd_mach_ppc_403;
- pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
- POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
-}
-
static void init_proc_440x5(CPUPPCState *env)
{
/* Time base */
@@ -2962,7 +2782,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_REAL;
- pcc->excp_model = POWERPC_EXCP_603;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
pcc->bfd_mach = bfd_mach_ppc_505;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -3005,7 +2825,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_MPC8xx;
- pcc->excp_model = POWERPC_EXCP_603;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
pcc->bfd_mach = bfd_mach_ppc_860;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -3086,7 +2906,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
(1ull << MSR_DR) |
(1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_G2;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@@ -3168,7 +2988,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_G2;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@@ -3423,7 +3243,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_603;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_603;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@@ -3892,120 +3712,6 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
#endif
/* Non-embedded PowerPC */
-
-#define POWERPC_MSRR_601 (0x0000000000001040ULL)
-
-static void init_proc_601(CPUPPCState *env)
-{
- register_ne_601_sprs(env);
- register_sdr1_sprs(env);
- register_601_sprs(env);
- /* Hardware implementation registers */
- /* XXX : not implemented */
- spr_register(env, SPR_HID0, "HID0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_hid0_601,
- 0x80010080);
- /* 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_601_HID2, "HID2",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_601_HID5, "HID5",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Memory management */
- init_excp_601(env);
- /*
- * XXX: beware that dcache line size is 64
- * but dcbz uses 32 bytes "sectors"
- * XXX: this breaks clcs instruction !
- */
- env->dcache_line_size = 32;
- env->icache_line_size = 64;
- /* Allocate hardware IRQ controller */
- ppc6xx_irq_init(env_archcpu(env));
-}
-
-POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 601";
- pcc->init_proc = init_proc_601;
- pcc->check_pow = check_pow_none;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
- PPC_FLOAT |
- PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
- PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
- PPC_SEGMENT | PPC_EXTERN;
- 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;
- pcc->excp_model = POWERPC_EXCP_601;
- pcc->bus_model = PPC_FLAGS_INPUT_6xx;
- pcc->bfd_mach = bfd_mach_ppc_601;
- pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE;
-}
-
-#define POWERPC_MSRR_601v (0x0000000000001040ULL)
-
-static void init_proc_601v(CPUPPCState *env)
-{
- init_proc_601(env);
- /* XXX : not implemented */
- spr_register(env, SPR_601_HID15, "HID15",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
-}
-
-POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 601v";
- pcc->init_proc = init_proc_601v;
- pcc->check_pow = check_pow_none;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
- PPC_FLOAT |
- PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
- PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
- PPC_SEGMENT | PPC_EXTERN;
- 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;
- pcc->excp_model = POWERPC_EXCP_601;
- pcc->bus_model = PPC_FLAGS_INPUT_6xx;
- pcc->bfd_mach = bfd_mach_ppc_601;
- pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE;
-}
-
static void init_proc_603(CPUPPCState *env)
{
register_ne_601_sprs(env);
@@ -4066,7 +3772,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_603;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_603;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@@ -4105,7 +3811,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_603;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@@ -4166,7 +3872,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_604;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4247,7 +3953,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_604;
+ pcc->excp_model = POWERPC_EXCP_6xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4315,7 +4021,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4392,7 +4098,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4592,7 +4298,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4672,7 +4378,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4757,7 +4463,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4842,7 +4548,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B;
- pcc->excp_model = POWERPC_EXCP_7x0;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -4918,7 +4624,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_7x5;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -5005,7 +4711,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
- pcc->excp_model = POWERPC_EXCP_7x5;
+ pcc->excp_model = POWERPC_EXCP_7xx;
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@@ -7760,7 +7466,7 @@ static void init_ppc_proc(PowerPCCPU *cpu)
"Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
exit(1);
}
- if ((env->flags & (POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_BUS_CLK)) == 0) {
+ if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
fprintf(stderr, "PowerPC flags inconsistency\n"
"Should define the time-base and decrementer clock source\n");
exit(1);
@@ -8574,7 +8280,6 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
switch (env->mmu_model) {
case POWERPC_MMU_32B:
- case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index c107953..fcc83a7 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -73,8 +73,6 @@ static const char *powerpc_excp_name(int excp)
case POWERPC_EXCP_HISEG: return "HISEG";
case POWERPC_EXCP_VPU: return "VPU";
case POWERPC_EXCP_PIT: return "PIT";
- case POWERPC_EXCP_IO: return "IO";
- case POWERPC_EXCP_RUNM: return "RUNM";
case POWERPC_EXCP_EMUL: return "EMUL";
case POWERPC_EXCP_IFTLB: return "IFTLB";
case POWERPC_EXCP_DLTLB: return "DLTLB";
@@ -165,7 +163,7 @@ static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
env->error_code);
}
-
+#if defined(TARGET_PPC64)
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
target_ulong *msr)
{
@@ -264,12 +262,10 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
* | a | h | 11 | 1 | 1 | h |
* +--------------------------------------------------------------------+
*/
-static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
- target_ulong msr,
- target_ulong *new_msr,
- target_ulong *vector)
+static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
+ target_ulong *new_msr, target_ulong *vector)
{
-#if defined(TARGET_PPC64)
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
@@ -282,8 +278,13 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
return;
}
- if (excp_model == POWERPC_EXCP_POWER8 ||
- excp_model == POWERPC_EXCP_POWER9) {
+ if (!(pcc->lpcr_mask & LPCR_AIL)) {
+ /* This CPU does not have AIL */
+ return;
+ }
+
+ /* P8 & P9 */
+ if (!(pcc->lpcr_mask & LPCR_HAIL)) {
if (!mmu_all_on) {
/* AIL only works if MSR[IR] and MSR[DR] are both enabled. */
return;
@@ -306,7 +307,8 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
return;
}
- } else if (excp_model == POWERPC_EXCP_POWER10) {
+ /* P10 and up */
+ } else {
if (!mmu_all_on && !hv_escalation) {
/*
* AIL works for HV interrupts even with guest MSR[IR/DR] disabled.
@@ -331,9 +333,6 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
/* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */
return;
}
- } else {
- /* Other processors do not support AIL */
- return;
}
/*
@@ -358,8 +357,8 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
*vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */
}
}
-#endif
}
+#endif
static void powerpc_set_excp_state(PowerPCCPU *cpu,
target_ulong vector, target_ulong msr)
@@ -367,6 +366,8 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu,
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ assert((msr & env->msr_mask) == msr);
+
/*
* We don't use hreg_store_msr here as already have treated any
* special case that could occur. Just store MSR and update hflags
@@ -375,7 +376,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu,
* will prevent setting of the HV bit which some exceptions might need
* to do.
*/
- env->msr = msr & env->msr_mask;
+ env->msr = msr;
hreg_compute_hflags(env);
env->nip = vector;
/* Reset exception state */
@@ -399,14 +400,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
target_ulong msr, new_msr, vector;
int srr0, srr1;
- if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
- }
-
- qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
- " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
- excp, env->error_code);
-
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -530,18 +523,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
break;
}
- /* Sanity check */
- if (!(env->msr_mask & MSR_HVB)) {
- if (new_msr & MSR_HVB) {
- cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
- "no HV support\n", excp);
- }
- if (srr0 == SPR_HSRR0) {
- cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
- "no HV support\n", excp);
- }
- }
-
/* Save PC */
env->spr[srr0] = env->nip;
@@ -551,19 +532,187 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
-static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
+static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
- if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
+ /* new srr1 value excluding must-be-zero bits */
+ msr = env->msr & ~0x783f0000ULL;
+
+ /*
+ * new interrupt handler msr preserves existing ME unless
+ * explicitly overriden
+ */
+ new_msr = env->msr & ((target_ulong)1 << MSR_ME);
+
+ /*
+ * Hypervisor emulation assistance interrupt only exists on server
+ * arch 2.05 server or later.
+ */
+ if (excp == POWERPC_EXCP_HV_EMU) {
+ excp = POWERPC_EXCP_PROGRAM;
+ }
+
+ vector = env->excp_vectors[excp];
+ if (vector == (target_ulong)-1ULL) {
+ cpu_abort(cs, "Raised an exception without defined vector %d\n",
+ excp);
+ }
+
+ vector |= env->excp_prefix;
+
+ switch (excp) {
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ break;
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ if (msr_me == 0) {
+ /*
+ * Machine check exception is not enabled. Enter
+ * checkstop state.
+ */
+ fprintf(stderr, "Machine check while not allowed. "
+ "Entering checkstop state\n");
+ if (qemu_log_separate()) {
+ qemu_log("Machine check while not allowed. "
+ "Entering checkstop state\n");
+ }
+ cs->halted = 1;
+ cpu_interrupt_exittb(cs);
+ }
+
+ /* machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
+ break;
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ trace_ppc_excp_isi(msr, env->nip);
+ msr |= env->error_code;
+ break;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ /* Get rS/rD and rA from faulting opcode */
+ /*
+ * Note: the opcode fields will not be set properly for a
+ * direct store load/store, but nobody cares as nobody
+ * actually uses direct store segments.
+ */
+ env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
+ break;
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ switch (env->error_code & ~0xF) {
+ case POWERPC_EXCP_FP:
+ if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
+ trace_ppc_excp_fp_ignore();
+ cs->exception_index = POWERPC_EXCP_NONE;
+ env->error_code = 0;
+ return;
+ }
+
+ /*
+ * FP exceptions always have NIP pointing to the faulting
+ * instruction, so always use store_next and claim we are
+ * precise in the MSR.
+ */
+ msr |= 0x00100000;
+ break;
+ case POWERPC_EXCP_INVAL:
+ trace_ppc_excp_inval(env->nip);
+ msr |= 0x00080000;
+ break;
+ case POWERPC_EXCP_PRIV:
+ msr |= 0x00040000;
+ break;
+ case POWERPC_EXCP_TRAP:
+ msr |= 0x00020000;
+ break;
+ default:
+ /* Should never occur */
+ cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ env->error_code);
+ break;
+ }
+ break;
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ dump_syscall(env);
+
+ /*
+ * We need to correct the NIP which in this case is supposed
+ * to point to the next instruction
+ */
+ env->nip += 4;
+ break;
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ if (msr_pow) {
+ cpu_abort(cs, "Trying to deliver power-saving system reset "
+ "exception %d with no HV support\n", excp);
+ }
+ break;
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ /* Swap temporary saved registers with GPRs */
+ if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
+ new_msr |= (target_ulong)1 << MSR_TGPR;
+ hreg_swap_gpr_tgpr(env);
+ }
+
+ ppc_excp_debug_sw_tlb(env, excp);
+
+ msr |= env->crf[0] << 28;
+ msr |= env->error_code; /* key, D/I, S/L bits */
+ /* Set way using a LRU mechanism */
+ msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ case POWERPC_EXCP_DABR: /* Data address breakpoint */
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
+ case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
+ cpu_abort(cs, "%s exception not implemented\n",
+ powerpc_excp_name(excp));
+ break;
+ default:
cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ break;
}
- qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
- " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
- excp, env->error_code);
+ /*
+ * Sort out endianness of interrupt, this differs depending on the
+ * CPU, the HV mode, etc...
+ */
+ if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
+ new_msr |= (target_ulong)1 << MSR_LE;
+ }
+
+ /* Save PC */
+ env->spr[SPR_SRR0] = env->nip;
+
+ /* Save MSR */
+ env->spr[SPR_SRR1] = msr;
+
+ powerpc_set_excp_state(cpu, vector, new_msr);
+}
+
+static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
+{
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr, new_msr, vector;
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
@@ -667,7 +816,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
{
int lev = env->error_code;
- if ((lev == 1) && cpu->vhyp) {
+ if (lev == 1 && cpu->vhyp) {
dump_hcall(env);
} else {
dump_syscall(env);
@@ -682,10 +831,10 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
/*
* The Virtual Open Firmware (VOF) relies on the 'sc 1'
* instruction to communicate with QEMU. The pegasos2 machine
- * uses VOF and the 74xx CPUs, so although the 74xx don't have
+ * uses VOF and the 7xx CPUs, so although the 7xx don't have
* HV mode, we need to keep hypercall support.
*/
- if ((lev == 1) && cpu->vhyp) {
+ if (lev == 1 && cpu->vhyp) {
PPCVirtualHypervisorClass *vhc =
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
vhc->hypercall(cpu->vhyp, cpu);
@@ -705,13 +854,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
break;
case POWERPC_EXCP_TRACE: /* Trace exception */
break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ ppc_excp_debug_sw_tlb(env, excp);
+
+ msr |= env->crf[0] << 28;
+ msr |= env->error_code; /* key, D/I, S/L bits */
+ /* Set way using a LRU mechanism */
+ msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
+
break;
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
case POWERPC_EXCP_SMI: /* System management interrupt */
case POWERPC_EXCP_THERM: /* Thermal interrupt */
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- case POWERPC_EXCP_VPUA: /* Vector assist exception */
cpu_abort(cs, "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
@@ -720,14 +877,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
break;
}
- /* Sanity check */
- if (!(env->msr_mask & MSR_HVB)) {
- if (new_msr & MSR_HVB) {
- cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
- "no HV support\n", excp);
- }
- }
-
/*
* Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
@@ -745,49 +894,26 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
-#ifdef TARGET_PPC64
-static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
+static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- int excp_model = env->excp_model;
target_ulong msr, new_msr, vector;
- int srr0, srr1, lev = -1;
-
- if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
- }
-
- qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
- " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
- excp, env->error_code);
/* new srr1 value excluding must-be-zero bits */
msr = env->msr & ~0x783f0000ULL;
/*
- * new interrupt handler msr preserves existing HV and ME unless
+ * new interrupt handler msr preserves existing ME unless
* explicitly overriden
*/
- new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
-
- /* target registers */
- srr0 = SPR_SRR0;
- srr1 = SPR_SRR1;
-
- /*
- * check for special resume at 0x100 from doze/nap/sleep/winkle on
- * P7/P8/P9
- */
- if (env->resume_as_sreset) {
- excp = powerpc_reset_wakeup(cs, env, excp, &msr);
- }
+ new_msr = env->msr & ((target_ulong)1 << MSR_ME);
/*
- * We don't want to generate a Hypervisor Emulation Assistance
- * Interrupt if we don't have HVB in msr_mask (PAPR mode).
+ * Hypervisor emulation assistance interrupt only exists on server
+ * arch 2.05 server or later.
*/
- if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) {
+ if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
@@ -815,13 +941,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
cs->halted = 1;
cpu_interrupt_exittb(cs);
}
- if (env->msr_mask & MSR_HVB) {
- /*
- * ISA specifies HV, but can be delivered to guest with HV
- * clear (e.g., see FWNMI in PAPR).
- */
- new_msr |= (target_ulong)MSR_HVB;
- }
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
@@ -835,28 +954,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
msr |= env->error_code;
break;
case POWERPC_EXCP_EXTERNAL: /* External input */
- {
- bool lpes0;
-
- /*
- * LPES0 is only taken into consideration if we support HV
- * mode for this CPU.
- */
- if (!env->has_hv_mode) {
- break;
- }
-
- lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
-
- if (!lpes0) {
- new_msr |= (target_ulong)MSR_HVB;
- new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
- srr0 = SPR_HSRR0;
- srr1 = SPR_HSRR1;
- }
-
break;
- }
case POWERPC_EXCP_ALIGN: /* Alignment exception */
/* Get rS/rD and rA from faulting opcode */
/*
@@ -901,7 +999,8 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
}
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
- lev = env->error_code;
+ {
+ int lev = env->error_code;
if ((lev == 1) && cpu->vhyp) {
dump_hcall(env);
@@ -915,87 +1014,39 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
*/
env->nip += 4;
- /* "PAPR mode" built-in hypercall emulation */
+ /*
+ * The Virtual Open Firmware (VOF) relies on the 'sc 1'
+ * instruction to communicate with QEMU. The pegasos2 machine
+ * uses VOF and the 74xx CPUs, so although the 74xx don't have
+ * HV mode, we need to keep hypercall support.
+ */
if ((lev == 1) && cpu->vhyp) {
PPCVirtualHypervisorClass *vhc =
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
vhc->hypercall(cpu->vhyp, cpu);
return;
}
- if (lev == 1) {
- new_msr |= (target_ulong)MSR_HVB;
- }
- break;
- case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
- lev = env->error_code;
- dump_syscall(env);
- env->nip += 4;
- new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
- new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
-
- vector += lev * 0x20;
- env->lr = env->nip;
- env->ctr = msr;
break;
+ }
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
case POWERPC_EXCP_DECR: /* Decrementer exception */
break;
case POWERPC_EXCP_RESET: /* System reset exception */
- /* A power-saving exception sets ME, otherwise it is unchanged */
if (msr_pow) {
- /* indicate that we resumed from power save mode */
- msr |= 0x10000;
- new_msr |= ((target_ulong)1 << MSR_ME);
- }
- if (env->msr_mask & MSR_HVB) {
- /*
- * ISA specifies HV, but can be delivered to guest with HV
- * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
- */
- new_msr |= (target_ulong)MSR_HVB;
- } else {
- if (msr_pow) {
- cpu_abort(cs, "Trying to deliver power-saving system reset "
- "exception %d with no HV support\n", excp);
- }
+ cpu_abort(cs, "Trying to deliver power-saving system reset "
+ "exception %d with no HV support\n", excp);
}
break;
- case POWERPC_EXCP_DSEG: /* Data segment exception */
- case POWERPC_EXCP_ISEG: /* Instruction segment exception */
case POWERPC_EXCP_TRACE: /* Trace exception */
break;
- case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
- msr |= env->error_code;
- /* fall through */
- case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
- case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
- case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
- case POWERPC_EXCP_HV_EMU:
- case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
- srr0 = SPR_HSRR0;
- srr1 = SPR_HSRR1;
- new_msr |= (target_ulong)MSR_HVB;
- new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
- break;
case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
- case POWERPC_EXCP_FU: /* Facility unavailable exception */
- env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
- break;
- case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
- env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
- srr0 = SPR_HSRR0;
- srr1 = SPR_HSRR1;
- new_msr |= (target_ulong)MSR_HVB;
- new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ case POWERPC_EXCP_SMI: /* System management interrupt */
case POWERPC_EXCP_THERM: /* Thermal interrupt */
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
case POWERPC_EXCP_VPUA: /* Vector assist exception */
- case POWERPC_EXCP_MAINT: /* Maintenance exception */
- case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
- case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */
cpu_abort(cs, "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
@@ -1004,18 +1055,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
break;
}
- /* Sanity check */
- if (!(env->msr_mask & MSR_HVB)) {
- if (new_msr & MSR_HVB) {
- cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
- "no HV support\n", excp);
- }
- if (srr0 == SPR_HSRR0) {
- cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
- "no HV support\n", excp);
- }
- }
-
/*
* Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
@@ -1024,84 +1063,39 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
new_msr |= (target_ulong)1 << MSR_LE;
}
- new_msr |= (target_ulong)1 << MSR_SF;
-
- if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
- /* Save PC */
- env->spr[srr0] = env->nip;
-
- /* Save MSR */
- env->spr[srr1] = msr;
- }
+ /* Save PC */
+ env->spr[SPR_SRR0] = env->nip;
- /* This can update new_msr and vector if AIL applies */
- ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
+ /* Save MSR */
+ env->spr[SPR_SRR1] = msr;
powerpc_set_excp_state(cpu, vector, new_msr);
}
-#else
-static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
-{
- g_assert_not_reached();
-}
-#endif
-/*
- * Note that this function should be greatly optimized when called
- * with a constant excp, from ppc_hw_interrupt
- */
-static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
+static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- int excp_model = env->excp_model;
target_ulong msr, new_msr, vector;
- int srr0, srr1, lev = -1;
-
- if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
- cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
- }
+ int srr0, srr1;
- qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
- " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
- excp, env->error_code);
-
- /* new srr1 value excluding must-be-zero bits */
- if (excp_model == POWERPC_EXCP_BOOKE) {
- msr = env->msr;
- } else {
- msr = env->msr & ~0x783f0000ULL;
- }
+ msr = env->msr;
/*
- * new interrupt handler msr preserves existing HV and ME unless
+ * new interrupt handler msr preserves existing ME unless
* explicitly overriden
*/
- new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
+ new_msr = env->msr & ((target_ulong)1 << MSR_ME);
/* target registers */
srr0 = SPR_SRR0;
srr1 = SPR_SRR1;
/*
- * check for special resume at 0x100 from doze/nap/sleep/winkle on
- * P7/P8/P9
- */
- if (env->resume_as_sreset) {
- excp = powerpc_reset_wakeup(cs, env, excp, &msr);
- }
-
- /*
* Hypervisor emulation assistance interrupt only exists on server
- * arch 2.05 server or later. We also don't want to generate it if
- * we don't have HVB in msr_mask (PAPR mode).
+ * arch 2.05 server or later.
*/
- if (excp == POWERPC_EXCP_HV_EMU
-#if defined(TARGET_PPC64)
- && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB))
-#endif /* defined(TARGET_PPC64) */
-
- ) {
+ if (excp == POWERPC_EXCP_HV_EMU) {
excp = POWERPC_EXCP_PROGRAM;
}
@@ -1110,7 +1104,7 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
* SPEU and VPU share the same IVOR but they exist in different
* processors. SPEU is e500v1/2 only and VPU is e6500 only.
*/
- if (excp_model == POWERPC_EXCP_BOOKE && excp == POWERPC_EXCP_VPU) {
+ if (excp == POWERPC_EXCP_VPU) {
excp = POWERPC_EXCP_SPEU;
}
#endif
@@ -1125,21 +1119,210 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
switch (excp) {
case POWERPC_EXCP_CRITICAL: /* Critical input */
- switch (excp_model) {
- case POWERPC_EXCP_40x:
- srr0 = SPR_40x_SRR2;
- srr1 = SPR_40x_SRR3;
+ srr0 = SPR_BOOKE_CSRR0;
+ srr1 = SPR_BOOKE_CSRR1;
+ break;
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ if (msr_me == 0) {
+ /*
+ * Machine check exception is not enabled. Enter
+ * checkstop state.
+ */
+ fprintf(stderr, "Machine check while not allowed. "
+ "Entering checkstop state\n");
+ if (qemu_log_separate()) {
+ qemu_log("Machine check while not allowed. "
+ "Entering checkstop state\n");
+ }
+ cs->halted = 1;
+ cpu_interrupt_exittb(cs);
+ }
+
+ /* machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+
+ /* FIXME: choose one or the other based on CPU type */
+ srr0 = SPR_BOOKE_MCSRR0;
+ srr1 = SPR_BOOKE_MCSRR1;
+
+ env->spr[SPR_BOOKE_CSRR0] = env->nip;
+ env->spr[SPR_BOOKE_CSRR1] = msr;
+
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
+ break;
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ trace_ppc_excp_isi(msr, env->nip);
+ break;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ if (env->mpic_proxy) {
+ /* IACK the IRQ on delivery */
+ env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
+ }
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ break;
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ switch (env->error_code & ~0xF) {
+ case POWERPC_EXCP_FP:
+ if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
+ trace_ppc_excp_fp_ignore();
+ cs->exception_index = POWERPC_EXCP_NONE;
+ env->error_code = 0;
+ return;
+ }
+
+ /*
+ * FP exceptions always have NIP pointing to the faulting
+ * instruction, so always use store_next and claim we are
+ * precise in the MSR.
+ */
+ msr |= 0x00100000;
+ env->spr[SPR_BOOKE_ESR] = ESR_FP;
break;
- case POWERPC_EXCP_BOOKE:
- srr0 = SPR_BOOKE_CSRR0;
- srr1 = SPR_BOOKE_CSRR1;
+ case POWERPC_EXCP_INVAL:
+ trace_ppc_excp_inval(env->nip);
+ msr |= 0x00080000;
+ env->spr[SPR_BOOKE_ESR] = ESR_PIL;
break;
- case POWERPC_EXCP_G2:
+ case POWERPC_EXCP_PRIV:
+ msr |= 0x00040000;
+ env->spr[SPR_BOOKE_ESR] = ESR_PPR;
+ break;
+ case POWERPC_EXCP_TRAP:
+ msr |= 0x00020000;
+ env->spr[SPR_BOOKE_ESR] = ESR_PTR;
break;
default:
- goto excp_invalid;
+ /* Should never occur */
+ cpu_abort(cs, "Invalid program exception %d. Aborting\n",
+ env->error_code);
+ break;
}
break;
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ dump_syscall(env);
+
+ /*
+ * We need to correct the NIP which in this case is supposed
+ * to point to the next instruction
+ */
+ env->nip += 4;
+ break;
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ /* FIT on 4xx */
+ trace_ppc_excp_print("FIT");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ trace_ppc_excp_print("WDT");
+ srr0 = SPR_BOOKE_CSRR0;
+ srr1 = SPR_BOOKE_CSRR1;
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ break;
+ case POWERPC_EXCP_DEBUG: /* Debug interrupt */
+ if (env->flags & POWERPC_FLAG_DE) {
+ /* FIXME: choose one or the other based on CPU type */
+ srr0 = SPR_BOOKE_DSRR0;
+ srr1 = SPR_BOOKE_DSRR1;
+
+ env->spr[SPR_BOOKE_CSRR0] = env->nip;
+ env->spr[SPR_BOOKE_CSRR1] = msr;
+
+ /* DBSR already modified by caller */
+ } else {
+ cpu_abort(cs, "Debug exception triggered on unsupported model\n");
+ }
+ break;
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
+ env->spr[SPR_BOOKE_ESR] = ESR_SPV;
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ if (msr_pow) {
+ cpu_abort(cs, "Trying to deliver power-saving system reset "
+ "exception %d with no HV support\n", excp);
+ }
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
+ cpu_abort(cs, "%s exception not implemented\n",
+ powerpc_excp_name(excp));
+ break;
+ default:
+ cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ break;
+ }
+
+#if defined(TARGET_PPC64)
+ if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
+ /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
+ new_msr |= (target_ulong)1 << MSR_CM;
+ } else {
+ vector = (uint32_t)vector;
+ }
+#endif
+
+ /* Save PC */
+ env->spr[srr0] = env->nip;
+
+ /* Save MSR */
+ env->spr[srr1] = msr;
+
+ powerpc_set_excp_state(cpu, vector, new_msr);
+}
+
+#ifdef TARGET_PPC64
+static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
+{
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr, new_msr, vector;
+ int srr0, srr1, lev = -1;
+
+ /* new srr1 value excluding must-be-zero bits */
+ msr = env->msr & ~0x783f0000ULL;
+
+ /*
+ * new interrupt handler msr preserves existing HV and ME unless
+ * explicitly overriden
+ */
+ new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
+
+ /* target registers */
+ srr0 = SPR_SRR0;
+ srr1 = SPR_SRR1;
+
+ /*
+ * check for special resume at 0x100 from doze/nap/sleep/winkle on
+ * P7/P8/P9
+ */
+ if (env->resume_as_sreset) {
+ excp = powerpc_reset_wakeup(cs, env, excp, &msr);
+ }
+
+ /*
+ * We don't want to generate a Hypervisor Emulation Assistance
+ * Interrupt if we don't have HVB in msr_mask (PAPR mode).
+ */
+ if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB)) {
+ excp = POWERPC_EXCP_PROGRAM;
+ }
+
+ vector = env->excp_vectors[excp];
+ if (vector == (target_ulong)-1ULL) {
+ cpu_abort(cs, "Raised an exception without defined vector %d\n",
+ excp);
+ }
+
+ vector |= env->excp_prefix;
+
+ switch (excp) {
case POWERPC_EXCP_MCHECK: /* Machine check exception */
if (msr_me == 0) {
/*
@@ -1166,23 +1349,6 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
/* machine check exceptions don't have ME set */
new_msr &= ~((target_ulong)1 << MSR_ME);
- /* XXX: should also have something loaded in DAR / DSISR */
- switch (excp_model) {
- case POWERPC_EXCP_40x:
- srr0 = SPR_40x_SRR2;
- srr1 = SPR_40x_SRR3;
- break;
- case POWERPC_EXCP_BOOKE:
- /* FIXME: choose one or the other based on CPU type */
- srr0 = SPR_BOOKE_MCSRR0;
- srr1 = SPR_BOOKE_MCSRR1;
-
- env->spr[SPR_BOOKE_CSRR0] = env->nip;
- env->spr[SPR_BOOKE_CSRR1] = msr;
- break;
- default:
- break;
- }
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
@@ -1195,39 +1361,23 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
{
bool lpes0;
- cs = CPU(cpu);
-
/*
- * Exception targeting modifiers
- *
- * LPES0 is supported on POWER7/8/9
- * LPES1 is not supported (old iSeries mode)
- *
- * On anything else, we behave as if LPES0 is 1
- * (externals don't alter MSR:HV)
+ * LPES0 is only taken into consideration if we support HV
+ * mode for this CPU.
*/
-#if defined(TARGET_PPC64)
- if (excp_model == POWERPC_EXCP_POWER7 ||
- excp_model == POWERPC_EXCP_POWER8 ||
- excp_model == POWERPC_EXCP_POWER9 ||
- excp_model == POWERPC_EXCP_POWER10) {
- lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
- } else
-#endif /* defined(TARGET_PPC64) */
- {
- lpes0 = true;
+ if (!env->has_hv_mode) {
+ break;
}
+ lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
+
if (!lpes0) {
new_msr |= (target_ulong)MSR_HVB;
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
}
- if (env->mpic_proxy) {
- /* IACK the IRQ on delivery */
- env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
- }
+
break;
}
case POWERPC_EXCP_ALIGN: /* Alignment exception */
@@ -1255,20 +1405,16 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
* precise in the MSR.
*/
msr |= 0x00100000;
- env->spr[SPR_BOOKE_ESR] = ESR_FP;
break;
case POWERPC_EXCP_INVAL:
trace_ppc_excp_inval(env->nip);
msr |= 0x00080000;
- env->spr[SPR_BOOKE_ESR] = ESR_PIL;
break;
case POWERPC_EXCP_PRIV:
msr |= 0x00040000;
- env->spr[SPR_BOOKE_ESR] = ESR_PPR;
break;
case POWERPC_EXCP_TRAP:
msr |= 0x00020000;
- env->spr[SPR_BOOKE_ESR] = ESR_PTR;
break;
default:
/* Should never occur */
@@ -1316,50 +1462,8 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
env->ctr = msr;
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
case POWERPC_EXCP_DECR: /* Decrementer exception */
break;
- case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
- /* FIT on 4xx */
- trace_ppc_excp_print("FIT");
- break;
- case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
- trace_ppc_excp_print("WDT");
- switch (excp_model) {
- case POWERPC_EXCP_BOOKE:
- srr0 = SPR_BOOKE_CSRR0;
- srr1 = SPR_BOOKE_CSRR1;
- break;
- default:
- break;
- }
- break;
- case POWERPC_EXCP_DTLB: /* Data TLB error */
- case POWERPC_EXCP_ITLB: /* Instruction TLB error */
- break;
- case POWERPC_EXCP_DEBUG: /* Debug interrupt */
- if (env->flags & POWERPC_FLAG_DE) {
- /* FIXME: choose one or the other based on CPU type */
- srr0 = SPR_BOOKE_DSRR0;
- srr1 = SPR_BOOKE_DSRR1;
-
- env->spr[SPR_BOOKE_CSRR0] = env->nip;
- env->spr[SPR_BOOKE_CSRR1] = msr;
-
- /* DBSR already modified by caller */
- } else {
- cpu_abort(cs, "Debug exception triggered on unsupported model\n");
- }
- break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
- env->spr[SPR_BOOKE_ESR] = ESR_SPV;
- break;
- case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
- break;
- case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
- srr0 = SPR_BOOKE_CSRR0;
- srr1 = SPR_BOOKE_CSRR1;
- break;
case POWERPC_EXCP_RESET: /* System reset exception */
/* A power-saving exception sets ME, otherwise it is unchanged */
if (msr_pow) {
@@ -1389,8 +1493,6 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
/* fall through */
case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
- case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
- case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
case POWERPC_EXCP_HV_EMU:
case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
@@ -1402,83 +1504,33 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_VPU: /* Vector unavailable exception */
case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
case POWERPC_EXCP_FU: /* Facility unavailable exception */
-#ifdef TARGET_PPC64
env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
-#endif
break;
case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
-#ifdef TARGET_PPC64
env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
-#endif
- break;
- case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
- trace_ppc_excp_print("PIT");
- break;
- case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
- case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
- case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
- switch (excp_model) {
- case POWERPC_EXCP_603:
- case POWERPC_EXCP_G2:
- /* Swap temporary saved registers with GPRs */
- if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
- new_msr |= (target_ulong)1 << MSR_TGPR;
- hreg_swap_gpr_tgpr(env);
- }
- /* fall through */
- case POWERPC_EXCP_7x5:
- ppc_excp_debug_sw_tlb(env, excp);
-
- msr |= env->crf[0] << 28;
- msr |= env->error_code; /* key, D/I, S/L bits */
- /* Set way using a LRU mechanism */
- msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
- break;
- default:
- cpu_abort(cs, "Invalid TLB miss exception\n");
- break;
- }
break;
- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
- case POWERPC_EXCP_IO: /* IO error exception */
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- case POWERPC_EXCP_EMUL: /* Emulation trap exception */
- case POWERPC_EXCP_FPA: /* Floating-point assist exception */
- case POWERPC_EXCP_DABR: /* Data address breakpoint */
- case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
- case POWERPC_EXCP_SMI: /* System management interrupt */
case POWERPC_EXCP_THERM: /* Thermal interrupt */
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
case POWERPC_EXCP_VPUA: /* Vector assist exception */
- case POWERPC_EXCP_SOFTP: /* Soft patch exception */
case POWERPC_EXCP_MAINT: /* Maintenance exception */
- case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
- case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
+ case POWERPC_EXCP_SDOOR: /* Doorbell interrupt */
+ case POWERPC_EXCP_HV_MAINT: /* Hypervisor Maintenance exception */
cpu_abort(cs, "%s exception not implemented\n",
powerpc_excp_name(excp));
break;
default:
- excp_invalid:
cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
break;
}
/* Sanity check */
- if (!(env->msr_mask & MSR_HVB)) {
- if (new_msr & MSR_HVB) {
- cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
- "no HV support\n", excp);
- }
- if (srr0 == SPR_HSRR0) {
- cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
- "no HV support\n", excp);
- }
+ if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
+ cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
+ "no HV support\n", excp);
}
/*
@@ -1489,22 +1541,7 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
new_msr |= (target_ulong)1 << MSR_LE;
}
-#if defined(TARGET_PPC64)
- if (excp_model == POWERPC_EXCP_BOOKE) {
- if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
- /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
- new_msr |= (target_ulong)1 << MSR_CM;
- } else {
- vector = (uint32_t)vector;
- }
- } else {
- if (!msr_isf && !mmu_is_64bit(env->mmu_model)) {
- vector = (uint32_t)vector;
- } else {
- new_msr |= (target_ulong)1 << MSR_SF;
- }
- }
-#endif
+ new_msr |= (target_ulong)1 << MSR_SF;
if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
/* Save PC */
@@ -1515,22 +1552,46 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
}
/* This can update new_msr and vector if AIL applies */
- ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
+ ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
powerpc_set_excp_state(cpu, vector, new_msr);
}
+#else
+static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
+{
+ g_assert_not_reached();
+}
+#endif
static void powerpc_excp(PowerPCCPU *cpu, int excp)
{
+ CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
+ cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
+ }
+
+ qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
+ " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
+ excp, env->error_code);
+
switch (env->excp_model) {
case POWERPC_EXCP_40x:
powerpc_excp_40x(cpu, excp);
break;
+ case POWERPC_EXCP_6xx:
+ powerpc_excp_6xx(cpu, excp);
+ break;
+ case POWERPC_EXCP_7xx:
+ powerpc_excp_7xx(cpu, excp);
+ break;
case POWERPC_EXCP_74xx:
powerpc_excp_74xx(cpu, excp);
break;
+ case POWERPC_EXCP_BOOKE:
+ powerpc_excp_booke(cpu, excp);
+ break;
case POWERPC_EXCP_970:
case POWERPC_EXCP_POWER7:
case POWERPC_EXCP_POWER8:
@@ -1539,7 +1600,7 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp)
powerpc_excp_books(cpu, excp);
break;
default:
- powerpc_excp_legacy(cpu, excp);
+ g_assert_not_reached();
}
}
@@ -1974,14 +2035,8 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
#endif
#if !defined(CONFIG_USER_ONLY)
-/*****************************************************************************/
-/* PowerPC 601 specific instructions (POWER bridge) */
#ifdef CONFIG_TCG
-void helper_rfsvc(CPUPPCState *env)
-{
- do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
-}
/* Embedded.Processor Control */
static int dbell2irq(target_ulong rb)
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index e5c29b5..bd76bee 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -1696,7 +1696,7 @@ uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -1772,7 +1772,7 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode,
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -1843,7 +1843,7 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode,
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -1919,7 +1919,7 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode,
#define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -1959,7 +1959,7 @@ VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0)
#define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -2004,7 +2004,7 @@ VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0)
#define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@@ -2472,7 +2472,7 @@ void helper_xscmpuqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
for (i = 0; i < nels; i++) { \
@@ -2498,7 +2498,7 @@ VSX_MAX_MIN(xvminsp, minnum, 4, float32, VsrW(i))
void helper_##name(CPUPPCState *env, \
ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
bool vxsnan_flag = false, vex_flag = false; \
\
if (unlikely(float64_is_any_nan(xa->VsrD(0)) || \
@@ -2533,7 +2533,7 @@ VSX_MAX_MINC(xsmincdp, 0);
void helper_##name(CPUPPCState *env, \
ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
bool vxsnan_flag = false, vex_flag = false; \
\
if (unlikely(float64_is_any_nan(xa->VsrD(0)))) { \
@@ -2654,7 +2654,7 @@ VSX_CMP(xvcmpnesp, 4, float32, VsrW(i), eq, 0, 0)
#define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
for (i = 0; i < nels; i++) { \
@@ -2833,7 +2833,7 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
int all_flags = env->fp_status.float_exception_flags, flags; \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
for (i = 0; i < nels; i++) { \
@@ -2917,7 +2917,7 @@ VSX_CVT_FP_TO_INT_VECTOR(xscvqpuwz, float128, uint32, f128, VsrD(0), 0x0ULL)
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
\
for (i = 0; i < nels; i++) { \
@@ -2990,7 +2990,7 @@ VSX_CVT_INT_TO_FP_VECTOR(xscvudqp, uint64, float128, VsrD(0), f128)
#define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- ppc_vsr_t t = *xt; \
+ ppc_vsr_t t = { }; \
int i; \
FloatRoundMode curr_rounding_mode; \
\
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index f2e5060..ab008c9 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -7,7 +7,6 @@ DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(store_msr, void, env, tl)
DEF_HELPER_1(rfi, void, env)
-DEF_HELPER_1(rfsvc, void, env)
DEF_HELPER_1(40x_rfci, void, env)
DEF_HELPER_1(rfci, void, env)
DEF_HELPER_1(rfdi, void, env)
@@ -653,14 +652,9 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
#endif
DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
-DEF_HELPER_FLAGS_2(clcs, TCG_CALL_NO_RWG_SE, tl, env, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(rac, tl, env, tl)
#endif
-DEF_HELPER_3(div, tl, env, tl, tl)
-DEF_HELPER_3(divo, tl, env, tl, tl)
-DEF_HELPER_3(divs, tl, env, tl, tl)
-DEF_HELPER_3(divso, tl, env, tl, tl)
DEF_HELPER_2(load_dcr, tl, env, tl)
DEF_HELPER_3(store_dcr, void, env, tl, tl)
@@ -674,8 +668,6 @@ DEF_HELPER_FLAGS_1(load_tbu, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_atbl, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_atbu, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_vtb, TCG_CALL_NO_RWG, tl, env)
-DEF_HELPER_FLAGS_1(load_601_rtcl, TCG_CALL_NO_RWG, tl, env)
-DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
@@ -693,15 +685,12 @@ DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_atbu, TCG_CALL_NO_RWG, void, env, tl)
-DEF_HELPER_FLAGS_2(store_601_rtcl, TCG_CALL_NO_RWG, void, env, tl)
-DEF_HELPER_FLAGS_2(store_601_rtcu, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_1(load_decr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_decr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_1(load_hdecr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbu40, TCG_CALL_NO_RWG, void, env, tl)
-DEF_HELPER_2(store_hid0_601, void, env, tl)
DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl)
@@ -715,8 +704,6 @@ DEF_HELPER_3(store_ibatl, void, env, i32, tl)
DEF_HELPER_3(store_ibatu, void, env, i32, tl)
DEF_HELPER_3(store_dbatl, void, env, i32, tl)
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
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 5b12cb0..38fcb5f 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -59,15 +59,6 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
msr_mask = ((1 << MSR_LE) | (1 << MSR_PR) |
(1 << MSR_DR) | (1 << MSR_FP));
- if (ppc_flags & POWERPC_FLAG_HID0_LE) {
- /*
- * Note that MSR_LE is not set in env->msr_mask for this cpu,
- * and so will never be set in msr.
- */
- uint32_t le = extract32(env->spr[SPR_HID0], 3, 1);
- hflags |= le << MSR_LE;
- }
-
if (ppc_flags & POWERPC_FLAG_DE) {
target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0];
if (dbcr0 & DBCR0_ICMP) {
@@ -249,7 +240,6 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
hreg_swap_gpr_tgpr(env);
}
if (unlikely((value >> MSR_EP) & 1) != msr_ep) {
- /* Change the exception prefix on PowerPC 601 */
env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
}
/*
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index d7765fd..d1b1278 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -423,72 +423,6 @@ uint64_t helper_PEXTD(uint64_t src, uint64_t mask)
}
/*****************************************************************************/
-/* PowerPC 601 specific instructions (POWER bridge) */
-target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
-{
- uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
-
- if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
- (int32_t)arg2 == 0) {
- env->spr[SPR_MQ] = 0;
- return INT32_MIN;
- } else {
- env->spr[SPR_MQ] = tmp % arg2;
- return tmp / (int32_t)arg2;
- }
-}
-
-target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
- target_ulong arg2)
-{
- uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
-
- if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
- (int32_t)arg2 == 0) {
- env->so = env->ov = 1;
- env->spr[SPR_MQ] = 0;
- return INT32_MIN;
- } else {
- env->spr[SPR_MQ] = tmp % arg2;
- tmp /= (int32_t)arg2;
- if ((int32_t)tmp != tmp) {
- env->so = env->ov = 1;
- } else {
- env->ov = 0;
- }
- return tmp;
- }
-}
-
-target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
- target_ulong arg2)
-{
- if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
- (int32_t)arg2 == 0) {
- env->spr[SPR_MQ] = 0;
- return INT32_MIN;
- } else {
- env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
- return (int32_t)arg1 / (int32_t)arg2;
- }
-}
-
-target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
- target_ulong arg2)
-{
- if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
- (int32_t)arg2 == 0) {
- env->so = env->ov = 1;
- env->spr[SPR_MQ] = 0;
- return INT32_MIN;
- } else {
- env->ov = 0;
- env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
- return (int32_t)arg1 / (int32_t)arg2;
- }
-}
-
-/*****************************************************************************/
/* Altivec extension helpers */
#if defined(HOST_WORDS_BIGENDIAN)
#define VECTOR_FOR_INORDER_I(index, element) \
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index a503e00..1b63146 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -205,9 +205,8 @@ static int cpu_pre_save(void *opaque)
}
}
- /* Retain migration compatibility for pre 6.0 for 601 machines. */
- env->hflags_compat_nmsr = (env->flags & POWERPC_FLAG_HID0_LE
- ? env->hflags & MSR_LE : 0);
+ /* Used to retain migration compatibility for pre 6.0 for 601 machines. */
+ env->hflags_compat_nmsr = 0;
return 0;
}
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 1bcefa7..29e73a6 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -211,21 +211,6 @@ void helper_store_lpidr(CPUPPCState *env, target_ulong val)
tlb_flush(env_cpu(env));
}
-void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
-{
- target_ulong hid0;
-
- hid0 = env->spr[SPR_HID0];
- env->spr[SPR_HID0] = (uint32_t)val;
-
- if ((val ^ hid0) & 0x00000008) {
- /* Change current endianness */
- hreg_compute_hflags(env);
- qemu_log("%s: set endianness to %c => %08x\n", __func__,
- val & 0x8 ? 'l' : 'b', env->hflags);
- }
-}
-
void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val)
{
/* Bits 26 & 27 affect single-stepping. */
@@ -239,31 +224,6 @@ void helper_store_40x_sler(CPUPPCState *env, target_ulong val)
store_40x_sler(env, val);
}
#endif
-/*****************************************************************************/
-/* PowerPC 601 specific instructions (POWER bridge) */
-
-target_ulong helper_clcs(CPUPPCState *env, uint32_t arg)
-{
- switch (arg) {
- case 0x0CUL:
- /* Instruction cache line size */
- return env->icache_line_size;
- case 0x0DUL:
- /* Data cache line size */
- return env->dcache_line_size;
- case 0x0EUL:
- /* Minimum cache line size */
- return (env->icache_line_size < env->dcache_line_size) ?
- env->icache_line_size : env->dcache_line_size;
- case 0x0FUL:
- /* Maximum cache line size */
- return (env->icache_line_size > env->dcache_line_size) ?
- env->icache_line_size : env->dcache_line_size;
- default:
- /* Undefined */
- return 0;
- }
-}
/*****************************************************************************/
/* Special registers manipulation */
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3957aab..cc091c3 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -125,30 +125,6 @@ static int hash32_bat_prot(PowerPCCPU *cpu,
return prot;
}
-static target_ulong hash32_bat_601_size(PowerPCCPU *cpu,
- target_ulong batu, target_ulong batl)
-{
- if (!(batl & BATL32_601_V)) {
- return 0;
- }
-
- return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
-}
-
-static int hash32_bat_601_prot(int mmu_idx,
- target_ulong batu, target_ulong batl)
-{
- int key, pp;
-
- pp = batu & BATU32_601_PP;
- if (mmuidx_pr(mmu_idx) == 0) {
- key = !!(batu & BATU32_601_KS);
- } else {
- key = !!(batu & BATU32_601_KP);
- }
- return ppc_hash32_pp_prot(key, pp, 0);
-}
-
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
MMUAccessType access_type, int *prot,
int mmu_idx)
@@ -172,11 +148,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
target_ulong batl = BATlt[i];
target_ulong mask;
- if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
- mask = hash32_bat_601_size(cpu, batu, batl);
- } else {
- mask = hash32_bat_size(mmu_idx, batu, batl);
- }
+ mask = hash32_bat_size(mmu_idx, batu, batl);
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n", __func__,
ifetch ? 'I' : 'D', i, ea, batu, batl);
@@ -184,11 +156,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
hwaddr raddr = (batl & mask) | (ea & ~mask);
- if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
- *prot = hash32_bat_601_prot(mmu_idx, batu, batl);
- } else {
- *prot = hash32_bat_prot(cpu, batu, batl);
- }
+ *prot = hash32_bat_prot(cpu, batu, batl);
return raddr & TARGET_PAGE_MASK;
}
@@ -231,18 +199,6 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
- if ((sr & 0x1FF00000) >> 20 == 0x07f) {
- /*
- * Memory-forced I/O controller interface access
- *
- * If T=1 and BUID=x'07F', the 601 performs a memory access
- * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
- */
- *raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return true;
- }
-
if (access_type == MMU_INST_FETCH) {
/* No code fetch is allowed in direct-store areas */
if (guest_visible) {
diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h
index 3892b69..7119a63 100644
--- a/target/ppc/mmu-hash32.h
+++ b/target/ppc/mmu-hash32.h
@@ -34,15 +34,6 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
#define BATL32_WIMG 0x00000078
#define BATL32_PP 0x00000003
-/* PowerPC 601 has slightly different BAT registers */
-
-#define BATU32_601_KS 0x00000008
-#define BATU32_601_KP 0x00000004
-#define BATU32_601_PP 0x00000003
-
-#define BATL32_601_V 0x00000040
-#define BATL32_601_BL 0x0000003f
-
/*
* Hash page table definitions
*/
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 040c055..d4e16bd 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -327,13 +327,9 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
uint64_t pte;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx
- " mmu_idx %u (prot %c%c%c) 0x%"HWADDR_PRIx"\n",
+ " mmu_idx %u 0x%"HWADDR_PRIx"\n",
__func__, access_str(access_type),
- eaddr, mmu_idx,
- *h_prot & PAGE_READ ? 'r' : '-',
- *h_prot & PAGE_WRITE ? 'w' : '-',
- *h_prot & PAGE_EXEC ? 'x' : '-',
- g_raddr);
+ eaddr, mmu_idx, g_raddr);
*h_page_size = PRTBE_R_GET_RTS(pate.dw0);
/* No valid pte or access denied due to protection */
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 6512ee0..e9c5b14 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -441,29 +441,9 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
ret = -3;
}
} else {
- target_ulong sr;
-
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
/* Direct-store segment : absolutely *BUGGY* for now */
- /*
- * Direct-store implies a 32-bit MMU.
- * Check the Segment Register's bus unit ID (BUID).
- */
- sr = env->sr[eaddr >> 28];
- if ((sr & 0x1FF00000) >> 20 == 0x07f) {
- /*
- * Memory-forced I/O controller interface access
- *
- * If T=1 and BUID=x'07F', the 601 performs a memory
- * access to SR[28-31] LA[4-31], bypassing all protection
- * mechanisms.
- */
- ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
- ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return 0;
- }
-
switch (type) {
case ACCESS_INT:
/* Integer load/store : only access allowed */
@@ -1539,7 +1519,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
#endif
case POWERPC_MMU_32B:
- case POWERPC_MMU_601:
return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible);
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index a2a52a1..142a717 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -279,88 +279,6 @@ void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
env->DBAT[1][nr] = value;
}
-void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
-{
- target_ulong mask;
-#if defined(FLUSH_ALL_TLBS)
- int do_inval;
-#endif
-
- dump_store_bat(env, 'I', 0, nr, value);
- if (env->IBAT[0][nr] != value) {
-#if defined(FLUSH_ALL_TLBS)
- do_inval = 0;
-#endif
- mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
- if (env->IBAT[1][nr] & 0x40) {
- /* Invalidate BAT only if it is valid */
-#if !defined(FLUSH_ALL_TLBS)
- do_invalidate_BAT(env, env->IBAT[0][nr], mask);
-#else
- do_inval = 1;
-#endif
- }
- /*
- * When storing valid upper BAT, mask BEPI and BRPN and
- * invalidate all TLBs covered by this BAT
- */
- env->IBAT[0][nr] = (value & 0x00001FFFUL) |
- (value & ~0x0001FFFFUL & ~mask);
- env->DBAT[0][nr] = env->IBAT[0][nr];
- if (env->IBAT[1][nr] & 0x40) {
-#if !defined(FLUSH_ALL_TLBS)
- do_invalidate_BAT(env, env->IBAT[0][nr], mask);
-#else
- do_inval = 1;
-#endif
- }
-#if defined(FLUSH_ALL_TLBS)
- if (do_inval) {
- tlb_flush(env_cpu(env));
- }
-#endif
- }
-}
-
-void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
-{
-#if !defined(FLUSH_ALL_TLBS)
- target_ulong mask;
-#else
- int do_inval;
-#endif
-
- dump_store_bat(env, 'I', 1, nr, value);
- if (env->IBAT[1][nr] != value) {
-#if defined(FLUSH_ALL_TLBS)
- do_inval = 0;
-#endif
- if (env->IBAT[1][nr] & 0x40) {
-#if !defined(FLUSH_ALL_TLBS)
- mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
- do_invalidate_BAT(env, env->IBAT[0][nr], mask);
-#else
- do_inval = 1;
-#endif
- }
- if (value & 0x40) {
-#if !defined(FLUSH_ALL_TLBS)
- mask = (value << 17) & 0x0FFE0000UL;
- do_invalidate_BAT(env, env->IBAT[0][nr], mask);
-#else
- do_inval = 1;
-#endif
- }
- env->IBAT[1][nr] = value;
- env->DBAT[1][nr] = value;
-#if defined(FLUSH_ALL_TLBS)
- if (do_inval) {
- tlb_flush(env_cpu(env));
- }
-#endif
- }
-}
-
/*****************************************************************************/
/* TLB management */
void ppc_tlb_invalidate_all(CPUPPCState *env)
@@ -392,7 +310,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
booke206_flush_tlb(env, -1, 0);
break;
case POWERPC_MMU_32B:
- case POWERPC_MMU_601:
env->tlb_need_flush = 0;
tlb_flush(env_cpu(env));
break;
@@ -426,7 +343,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
}
break;
case POWERPC_MMU_32B:
- case POWERPC_MMU_601:
/*
* Actual CPUs invalidate entire congruence classes based on
* the geometry of their TLBs and some OSes take that into
diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h
index 89ff111..df2abac 100644
--- a/target/ppc/spr_tcg.h
+++ b/target/ppc/spr_tcg.h
@@ -45,8 +45,6 @@ void spr_read_tbl(DisasContext *ctx, int gprn, int sprn);
void spr_read_tbu(DisasContext *ctx, int gprn, int sprn);
void spr_read_atbl(DisasContext *ctx, int gprn, int sprn);
void spr_read_atbu(DisasContext *ctx, int gprn, int sprn);
-void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn);
-void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn);
void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn);
void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn);
@@ -77,12 +75,6 @@ void spr_write_dbatu_h(DisasContext *ctx, int sprn, int gprn);
void spr_write_dbatl(DisasContext *ctx, int sprn, int gprn);
void spr_write_dbatl_h(DisasContext *ctx, int sprn, int gprn);
void spr_write_sdr1(DisasContext *ctx, int sprn, int gprn);
-void spr_write_601_rtcu(DisasContext *ctx, int sprn, int gprn);
-void spr_write_601_rtcl(DisasContext *ctx, int sprn, int gprn);
-void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn);
-void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn);
-void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn);
-void spr_write_601_ubatl(DisasContext *ctx, int sprn, int gprn);
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn);
void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn);
void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn);
diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c
index af37831..86d01d6 100644
--- a/target/ppc/timebase_helper.c
+++ b/target/ppc/timebase_helper.c
@@ -63,16 +63,6 @@ void helper_store_purr(CPUPPCState *env, target_ulong val)
}
#endif
-target_ulong helper_load_601_rtcl(CPUPPCState *env)
-{
- return cpu_ppc601_load_rtcl(env);
-}
-
-target_ulong helper_load_601_rtcu(CPUPPCState *env)
-{
- return cpu_ppc601_load_rtcu(env);
-}
-
#if !defined(CONFIG_USER_ONLY)
void helper_store_tbl(CPUPPCState *env, target_ulong val)
{
@@ -94,16 +84,6 @@ void helper_store_atbu(CPUPPCState *env, target_ulong val)
cpu_ppc_store_atbu(env, val);
}
-void helper_store_601_rtcl(CPUPPCState *env, target_ulong val)
-{
- cpu_ppc601_store_rtcl(env, val);
-}
-
-void helper_store_601_rtcu(CPUPPCState *env, target_ulong val)
-{
- cpu_ppc601_store_rtcu(env, val);
-}
-
target_ulong helper_load_decr(CPUPPCState *env)
{
return cpu_ppc_load_decr(env);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c2f436f..2eaffd4 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -794,61 +794,6 @@ void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
#endif
#endif
-/* PowerPC 601 specific registers */
-/* RTC */
-void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn)
-{
- gen_helper_load_601_rtcl(cpu_gpr[gprn], cpu_env);
-}
-
-void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn)
-{
- gen_helper_load_601_rtcu(cpu_gpr[gprn], cpu_env);
-}
-
-#if !defined(CONFIG_USER_ONLY)
-void spr_write_601_rtcu(DisasContext *ctx, int sprn, int gprn)
-{
- gen_helper_store_601_rtcu(cpu_env, cpu_gpr[gprn]);
-}
-
-void spr_write_601_rtcl(DisasContext *ctx, int sprn, int gprn)
-{
- gen_helper_store_601_rtcl(cpu_env, cpu_gpr[gprn]);
-}
-
-void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn)
-{
- gen_helper_store_hid0_601(cpu_env, cpu_gpr[gprn]);
- /* Must stop the translation as endianness may have changed */
- ctx->base.is_jmp = DISAS_EXIT_UPDATE;
-}
-#endif
-
-/* Unified bats */
-#if !defined(CONFIG_USER_ONLY)
-void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn)
-{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
- offsetof(CPUPPCState,
- IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
-}
-
-void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn)
-{
- TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
- gen_helper_store_601_batl(cpu_env, t0, cpu_gpr[gprn]);
- tcg_temp_free_i32(t0);
-}
-
-void spr_write_601_ubatl(DisasContext *ctx, int sprn, int gprn)
-{
- TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
- gen_helper_store_601_batu(cpu_env, t0, cpu_gpr[gprn]);
- tcg_temp_free_i32(t0);
-}
-#endif
-
/* PowerPC 40x specific registers */
#if !defined(CONFIG_USER_ONLY)
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
@@ -5609,669 +5554,6 @@ static void gen_ecowx(DisasContext *ctx)
tcg_temp_free(t0);
}
-/* PowerPC 601 specific instructions */
-
-/* abs - abs. */
-static void gen_abs(DisasContext *ctx)
-{
- TCGv d = cpu_gpr[rD(ctx->opcode)];
- TCGv a = cpu_gpr[rA(ctx->opcode)];
-
- tcg_gen_abs_tl(d, a);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, d);
- }
-}
-
-/* abso - abso. */
-static void gen_abso(DisasContext *ctx)
-{
- TCGv d = cpu_gpr[rD(ctx->opcode)];
- TCGv a = cpu_gpr[rA(ctx->opcode)];
-
- tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_ov, a, 0x80000000);
- tcg_gen_abs_tl(d, a);
- tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, d);
- }
-}
-
-/* clcs */
-static void gen_clcs(DisasContext *ctx)
-{
- TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
- gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
- tcg_temp_free_i32(t0);
- /* Rc=1 sets CR0 to an undefined state */
-}
-
-/* div - div. */
-static void gen_div(DisasContext *ctx)
-{
- gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
- cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* divo - divo. */
-static void gen_divo(DisasContext *ctx)
-{
- gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
- cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* divs - divs. */
-static void gen_divs(DisasContext *ctx)
-{
- gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
- cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* divso - divso. */
-static void gen_divso(DisasContext *ctx)
-{
- gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
- cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* doz - doz. */
-static void gen_doz(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
- cpu_gpr[rA(ctx->opcode)], l1);
- tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
- cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
- gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* dozo - dozo. */
-static void gen_dozo(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
- /* Start with XER OV disabled, the most likely case */
- tcg_gen_movi_tl(cpu_ov, 0);
- tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
- cpu_gpr[rA(ctx->opcode)], l1);
- tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
- tcg_gen_andc_tl(t1, t1, t2);
- tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
- tcg_gen_movi_tl(cpu_ov, 1);
- tcg_gen_movi_tl(cpu_so, 1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
- gen_set_label(l2);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* dozi */
-static void gen_dozi(DisasContext *ctx)
-{
- target_long simm = SIMM(ctx->opcode);
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
- tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
- gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* lscbx - lscbx. */
-static void gen_lscbx(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
- TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
- TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
-
- gen_addr_reg_index(ctx, t0);
- gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
- tcg_temp_free_i32(t1);
- tcg_temp_free_i32(t2);
- tcg_temp_free_i32(t3);
- tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
- tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, t0);
- }
- tcg_temp_free(t0);
-}
-
-/* maskg - maskg. */
-static void gen_maskg(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
- TCGv t3 = tcg_temp_new();
- tcg_gen_movi_tl(t3, 0xFFFFFFFF);
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
- tcg_gen_addi_tl(t2, t0, 1);
- tcg_gen_shr_tl(t2, t3, t2);
- tcg_gen_shr_tl(t3, t3, t1);
- tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
- tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
- tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- gen_set_label(l1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- tcg_temp_free(t3);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* maskir - maskir. */
-static void gen_maskir(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* mul - mul. */
-static void gen_mul(DisasContext *ctx)
-{
- TCGv_i64 t0 = tcg_temp_new_i64();
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv t2 = tcg_temp_new();
- tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_mul_i64(t0, t0, t1);
- tcg_gen_trunc_i64_tl(t2, t0);
- gen_store_spr(SPR_MQ, t2);
- tcg_gen_shri_i64(t1, t0, 32);
- tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* mulo - mulo. */
-static void gen_mulo(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGv_i64 t0 = tcg_temp_new_i64();
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv t2 = tcg_temp_new();
- /* Start with XER OV disabled, the most likely case */
- tcg_gen_movi_tl(cpu_ov, 0);
- tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
- tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
- tcg_gen_mul_i64(t0, t0, t1);
- tcg_gen_trunc_i64_tl(t2, t0);
- gen_store_spr(SPR_MQ, t2);
- tcg_gen_shri_i64(t1, t0, 32);
- tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
- tcg_gen_ext32s_i64(t1, t0);
- tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
- tcg_gen_movi_tl(cpu_ov, 1);
- tcg_gen_movi_tl(cpu_so, 1);
- gen_set_label(l1);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
- }
-}
-
-/* nabs - nabs. */
-static void gen_nabs(DisasContext *ctx)
-{
- TCGv d = cpu_gpr[rD(ctx->opcode)];
- TCGv a = cpu_gpr[rA(ctx->opcode)];
-
- tcg_gen_abs_tl(d, a);
- tcg_gen_neg_tl(d, d);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, d);
- }
-}
-
-/* nabso - nabso. */
-static void gen_nabso(DisasContext *ctx)
-{
- TCGv d = cpu_gpr[rD(ctx->opcode)];
- TCGv a = cpu_gpr[rA(ctx->opcode)];
-
- tcg_gen_abs_tl(d, a);
- tcg_gen_neg_tl(d, d);
- /* nabs never overflows */
- tcg_gen_movi_tl(cpu_ov, 0);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, d);
- }
-}
-
-/* rlmi - rlmi. */
-static void gen_rlmi(DisasContext *ctx)
-{
- uint32_t mb = MB(ctx->opcode);
- uint32_t me = ME(ctx->opcode);
- TCGv t0 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
- tcg_gen_andi_tl(t0, t0, MASK(mb, me));
- tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
- ~MASK(mb, me));
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
- tcg_temp_free(t0);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* rrib - rrib. */
-static void gen_rrib(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_movi_tl(t1, 0x80000000);
- tcg_gen_shr_tl(t1, t1, t0);
- tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
- tcg_gen_and_tl(t0, t0, t1);
- tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sle - sle. */
-static void gen_sle(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_subfi_tl(t1, 32, t1);
- tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_or_tl(t1, t0, t1);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- gen_store_spr(SPR_MQ, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sleq - sleq. */
-static void gen_sleq(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_movi_tl(t2, 0xFFFFFFFF);
- tcg_gen_shl_tl(t2, t2, t0);
- tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
- gen_load_spr(t1, SPR_MQ);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_and_tl(t0, t0, t2);
- tcg_gen_andc_tl(t1, t1, t2);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sliq - sliq. */
-static void gen_sliq(DisasContext *ctx)
-{
- int sh = SH(ctx->opcode);
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
- tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
- tcg_gen_or_tl(t1, t0, t1);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- gen_store_spr(SPR_MQ, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* slliq - slliq. */
-static void gen_slliq(DisasContext *ctx)
-{
- int sh = SH(ctx->opcode);
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
- gen_load_spr(t1, SPR_MQ);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
- tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sllq - sllq. */
-static void gen_sllq(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGv t0 = tcg_temp_local_new();
- TCGv t1 = tcg_temp_local_new();
- TCGv t2 = tcg_temp_local_new();
- tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_movi_tl(t1, 0xFFFFFFFF);
- tcg_gen_shl_tl(t1, t1, t2);
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
- gen_load_spr(t0, SPR_MQ);
- tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
- gen_load_spr(t2, SPR_MQ);
- tcg_gen_andc_tl(t1, t2, t1);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- gen_set_label(l2);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* slq - slq. */
-static void gen_slq(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_subfi_tl(t1, 32, t1);
- tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_or_tl(t1, t0, t1);
- gen_store_spr(SPR_MQ, t1);
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
- gen_set_label(l1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sraiq - sraiq. */
-static void gen_sraiq(DisasContext *ctx)
-{
- int sh = SH(ctx->opcode);
- TCGLabel *l1 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
- tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
- tcg_gen_or_tl(t0, t0, t1);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_movi_tl(cpu_ca, 0);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
- tcg_gen_movi_tl(cpu_ca, 1);
- gen_set_label(l1);
- tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sraq - sraq. */
-static void gen_sraq(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_local_new();
- TCGv t2 = tcg_temp_local_new();
- tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
- tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
- tcg_gen_subfi_tl(t2, 32, t2);
- tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
- tcg_gen_or_tl(t0, t0, t2);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
- tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
- tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
- gen_set_label(l1);
- tcg_temp_free(t0);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
- tcg_gen_movi_tl(cpu_ca, 0);
- tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
- tcg_gen_movi_tl(cpu_ca, 1);
- gen_set_label(l2);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sre - sre. */
-static void gen_sre(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_subfi_tl(t1, 32, t1);
- tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_or_tl(t1, t0, t1);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- gen_store_spr(SPR_MQ, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* srea - srea. */
-static void gen_srea(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sreq */
-static void gen_sreq(DisasContext *ctx)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- TCGv t2 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_movi_tl(t1, 0xFFFFFFFF);
- tcg_gen_shr_tl(t1, t1, t0);
- tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
- gen_load_spr(t2, SPR_MQ);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_and_tl(t0, t0, t1);
- tcg_gen_andc_tl(t2, t2, t1);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* sriq */
-static void gen_sriq(DisasContext *ctx)
-{
- int sh = SH(ctx->opcode);
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
- tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
- tcg_gen_or_tl(t1, t0, t1);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- gen_store_spr(SPR_MQ, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* srliq */
-static void gen_srliq(DisasContext *ctx)
-{
- int sh = SH(ctx->opcode);
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
- gen_load_spr(t1, SPR_MQ);
- gen_store_spr(SPR_MQ, t0);
- tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
- tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* srlq */
-static void gen_srlq(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGv t0 = tcg_temp_local_new();
- TCGv t1 = tcg_temp_local_new();
- TCGv t2 = tcg_temp_local_new();
- tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_movi_tl(t1, 0xFFFFFFFF);
- tcg_gen_shr_tl(t2, t1, t2);
- tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
- gen_load_spr(t0, SPR_MQ);
- tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
- tcg_gen_and_tl(t0, t0, t2);
- gen_load_spr(t1, SPR_MQ);
- tcg_gen_andc_tl(t1, t1, t2);
- tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
- gen_set_label(l2);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
-/* srq */
-static void gen_srq(DisasContext *ctx)
-{
- TCGLabel *l1 = gen_new_label();
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
- tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_subfi_tl(t1, 32, t1);
- tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
- tcg_gen_or_tl(t1, t0, t1);
- gen_store_spr(SPR_MQ, t1);
- tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
- gen_set_label(l1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
- gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
- }
-}
-
/* 602 - 603 - G2 TLB management */
/* tlbld */
@@ -6296,81 +5578,6 @@ static void gen_tlbli_6xx(DisasContext *ctx)
#endif /* defined(CONFIG_USER_ONLY) */
}
-/* POWER instructions not in PowerPC 601 */
-
-/* clf */
-static void gen_clf(DisasContext *ctx)
-{
- /* Cache line flush: implemented as no-op */
-}
-
-/* cli */
-static void gen_cli(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
- GEN_PRIV;
-#else
- /* Cache line invalidate: privileged and treated as no-op */
- CHK_SV;
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
-/* dclst */
-static void gen_dclst(DisasContext *ctx)
-{
- /* Data cache line store: treated as no-op */
-}
-
-static void gen_mfsri(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
- GEN_PRIV;
-#else
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0;
-
- CHK_SV;
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- tcg_gen_extract_tl(t0, t0, 28, 4);
- gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
- tcg_temp_free(t0);
- if (ra != 0 && ra != rd) {
- tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
- }
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
-static void gen_rac(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
- GEN_PRIV;
-#else
- TCGv t0;
-
- CHK_SV;
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
- tcg_temp_free(t0);
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
-static void gen_rfsvc(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
- GEN_PRIV;
-#else
- CHK_SV;
-
- gen_helper_rfsvc(cpu_env);
- ctx->base.is_jmp = DISAS_EXIT;
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
-/* svc is not implemented for now */
-
/* BookE specific instructions */
/* XXX: not implemented on 440 ? */
@@ -7718,56 +6925,8 @@ GEN_HANDLER_E(slbsync, 0x1F, 0x12, 0x0A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
#endif
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
-GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
-GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
-GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
-GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
-GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
-GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
-GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
-GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
-GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
-GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
-GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
-GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
-GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
-GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
-GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
-GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
-GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
-GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
-GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
@@ -8463,7 +7622,6 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
#endif
ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
- || env->mmu_model == POWERPC_MMU_601
|| env->mmu_model & POWERPC_MMU_64;
ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1;
diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc
index c967697..cfb27bd 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -1105,185 +1105,6 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
/* stfiwx */
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
-/* POWER2 specific instructions */
-/* Quad manipulation (load/store two floats at a time) */
-
-/* lfq */
-static void gen_lfq(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr(rd, t1);
- gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr((rd + 1) % 32, t1);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
-
-/* lfqu */
-static void gen_lfqu(DisasContext *ctx)
-{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- t2 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, t2, t0);
- set_fpr(rd, t2);
- gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, t2, t1);
- set_fpr((rd + 1) % 32, t2);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
- }
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free_i64(t2);
-}
-
-/* lfqux */
-static void gen_lfqux(DisasContext *ctx)
-{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- gen_set_access_type(ctx, ACCESS_FLOAT);
- TCGv t0, t1;
- TCGv_i64 t2;
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, t2, t0);
- set_fpr(rd, t2);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, t2, t1);
- set_fpr((rd + 1) % 32, t2);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
- }
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
-}
-
-/* lfqx */
-static void gen_lfqx(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr(rd, t1);
- gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr((rd + 1) % 32, t1);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
-
-/* stfq */
-static void gen_stfq(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- get_fpr(t1, rd);
- gen_qemu_st64_i64(ctx, t1, t0);
- gen_addr_add(ctx, t0, t0, 8);
- get_fpr(t1, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t1, t0);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
-
-/* stfqu */
-static void gen_stfqu(DisasContext *ctx)
-{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_imm_index(ctx, t0, 0);
- get_fpr(t2, rd);
- gen_qemu_st64_i64(ctx, t2, t0);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- get_fpr(t2, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t2, t1);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
- }
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
-}
-
-/* stfqux */
-static void gen_stfqux(DisasContext *ctx)
-{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- get_fpr(t2, rd);
- gen_qemu_st64_i64(ctx, t2, t0);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- get_fpr(t2, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t2, t1);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
- }
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
-}
-
-/* stfqx */
-static void gen_stfqx(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t1 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- get_fpr(t1, rd);
- gen_qemu_st64_i64(ctx, t1, t0);
- gen_addr_add(ctx, t0, t0, 8);
- get_fpr(t1, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t1, t0);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
-
/* Floating-point Load/Store Instructions */
static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
bool update, bool store, bool single)
diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
index c636e38..128968b 100644
--- a/target/ppc/translate/vsx-impl.c.inc
+++ b/target/ppc/translate/vsx-impl.c.inc
@@ -747,6 +747,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
} \
set_cpu_vsr(xT(ctx->opcode), xb, true); \
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
tcg_temp_free_i64(xb); \
tcg_temp_free_i64(sgm); \
}
@@ -1073,6 +1074,7 @@ static void gen_##name(DisasContext *ctx) \
get_cpu_vsr(t0, xB(ctx->opcode), true); \
gen_helper_##name(t1, cpu_env, t0); \
set_cpu_vsr(xT(ctx->opcode), t1, true); \
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
tcg_temp_free_i64(t0); \
tcg_temp_free_i64(t1); \
}
@@ -1700,7 +1702,7 @@ static void gen_xsiexpdp(DisasContext *ctx)
tcg_gen_shli_i64(t0, t0, 52);
tcg_gen_or_i64(xth, xth, t0);
set_cpu_vsr(xT(ctx->opcode), xth, true);
- /* dword[1] is undefined */
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(xth);
}