ppc-7.0 queue

* Exception model rework (Fabiano)
 * Unused CPU models removal (Fabiano and Cédric)
 * Fix for VOF installation (Alexey)
 * Misc fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmIFDBsACgkQUaNDx8/7
 7KHmmg//RjCaqbubw8nc58stxGvwf30tcLzPKbQzoz4rZ/hxMaXDKTzh7BA16qJO
 fJDrnQCcYa1dpLWXCygY/5G7+DbaGYRava/3BqBv2qAO0wDdKbnxKGuFSSbqgeca
 skTQK1R5hSYclFNI13yFLJrAkwiTSZjI+UhCkUqW6wZS1qeZ1ClBwoCMIZ8dP4vE
 cshD78lFRSCLhScrhhQqeQymEWk6eUmv4TY2gSiVpCZCaR1wlXxy3/YOd5i2w2B1
 A+JAwvCOknKaGzCftbZN0Po8orcdXyQ96YZNQxjL9Wu58zZllqzolF2pJi0Qph2h
 3ZW7Bw3BbnUl6ceWg/J/e+gVkGLKyPGJ6eD556HxccJZPXgtEC8QyP8ACzl3mJ1E
 13abW4yX7XwtgmVoXQQu0vaKKM4AamIkqYgn/kGP1TQO5s+CMf61+WYy1HzIio1Z
 9jUhpRWBiEsuhigy/kFejU9dYVHYJ0rcr7pwRa+Nhet+8Rzv5Klr6rQExsftkZmc
 0KcJDhpGVrmdO/qU8BYh/lhyOvx9+9qI8gG/g2PJtR4VSTHRUqxZ+VzuIC2tVpD0
 XJnCNSBgJs59kybPX3Pn1f8BmVoZBq+oJBScrOJne3finBbxioo4JiKReBD12y1A
 LxE+JTV0N/aPjkMzuw+VXPMZ1suxrd2doiyDKXv/eijleGtdsPg=
 =/0n8
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2022-02-13 20:33:28 +00:00
commit cc5ce8b8b6
32 changed files with 717 additions and 2375 deletions

View File

@ -408,7 +408,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com> M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org L: kvm@vger.kernel.org
S: Supported S: Supported
F: docs/amd-memory-encryption.txt F: docs/system/i386/amd-memory-encryption.rst
F: docs/system/i386/sgx.rst F: docs/system/i386/sgx.rst
F: target/i386/kvm/ F: target/i386/kvm/
F: target/i386/sev* F: target/i386/sev*

View File

@ -19,10 +19,10 @@ Running a Confidential Guest
To run a confidential guest you need to add two command line parameters: 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 type and parameters will vary with the specific mechanism to be
used 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). the object from (1).
Example (for AMD SEV):: Example (for AMD SEV)::
@ -37,13 +37,8 @@ Supported mechanisms
Currently supported confidential guest mechanisms are: Currently supported confidential guest mechanisms are:
AMD Secure Encrypted Virtualization (SEV) * AMD Secure Encrypted Virtualization (SEV) (see :doc:`i386/amd-memory-encryption`)
docs/amd-memory-encryption.txt * POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`)
* s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`)
POWER Protected Execution Facility (PEF)
docs/papr-pef.txt
s390x Protected Virtualization (PV)
docs/system/s390x/protvirt.rst
Other mechanisms may be supported in future. Other mechanisms may be supported in future.

View File

@ -1,3 +1,6 @@
AMD Secure Encrypted Virtualization (SEV)
=========================================
Secure Encrypted Virtualization (SEV) is a feature found on AMD processors. Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
SEV is an extension to the AMD-V architecture which supports running encrypted 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 Launching
--------- ---------
Boot images (such as bios) must be encrypted before a guest can be booted. The 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, ``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images: ``LAUNCH_START``,
LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands ``LAUNCH_UPDATE_DATA``, ``LAUNCH_MEASURE`` and ``LAUNCH_FINISH``. These four commands
together generate a fresh memory encryption key for the VM, encrypt the boot 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 images and provide a measurement than can be used as an attestation of a
successful launch. 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. 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, the firmware. To create this context, guest owner must provide a guest policy,
its public Diffie-Hellman key (PDH) and session parameters. These inputs 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. 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. several flags that restricts what can be done on a running SEV guest.
See KM Spec section 3 and 6.2 for more details. 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} \ # ${QEMU} \
sev-guest,id=sev0,policy=0x1...\ sev-guest,id=sev0,policy=0x1...\
Setting the "SEV-ES required" policy bit (bit 2) will launch the guest as a Setting the "SEV-ES required" policy bit (bit 2) will launch the guest as a
SEV-ES guest (see below) SEV-ES guest::
# ${QEMU} \ # ${QEMU} \
sev-guest,id=sev0,policy=0x5...\ sev-guest,id=sev0,policy=0x5...\
The guest owner provided DH certificate and session parameters will be used to 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 establish a cryptographic session with the guest owner to negotiate keys used
for the attestation. for the attestation.
The DH certificate and session blob can be provided via the 'dh-cert-file' and The DH certificate and session blob can be provided via the ``dh-cert-file`` and
'session-file' properties (see below) ``session-file`` properties::
# ${QEMU} \ # ${QEMU} \
sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2> sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context ``LAUNCH_UPDATE_DATA`` encrypts the memory region using the cryptographic context
created via the LAUNCH_START command. If required, this command can be called created via the ``LAUNCH_START`` command. If required, this command can be called
multiple times to encrypt different memory regions. The command also calculates multiple times to encrypt different memory regions. The command also calculates
the measurement of the memory contents as it encrypts. the measurement of the memory contents as it encrypts.
LAUNCH_UPDATE_VMSA encrypts all the vCPU VMSAs for a SEV-ES guest using the ``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 cryptographic context created via the ``LAUNCH_START`` command. The command also
calculates the measurement of the VMSAs as it encrypts them. 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 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 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 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 attestation measurement can be verified by comparing it to what the guest owner
expects. expects.
LAUNCH_FINISH finalizes the guest launch and destroys the cryptographic ``LAUNCH_FINISH`` finalizes the guest launch and destroys the cryptographic
context. 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. complete flow chart.
To launch a SEV guest To launch a SEV guest::
# ${QEMU} \ # ${QEMU} \
-machine ...,confidential-guest-support=sev0 \ -machine ...,confidential-guest-support=sev0 \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1 -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
To launch a SEV-ES guest To launch a SEV-ES guest::
# ${QEMU} \ # ${QEMU} \
-machine ...,confidential-guest-support=sev0 \ -machine ...,confidential-guest-support=sev0 \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x5 -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 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, guest register state is encrypted and cannot be updated by the VMM/hypervisor,
a SEV-ES guest: a SEV-ES guest:
- Does not support SMM - SMM support requires updating the guest register - Does not support SMM - SMM support requires updating the guest register
state. state.
- Does not support reboot - a system reset requires updating the guest register - Does not support reboot - a system reset requires updating the guest register
@ -114,35 +119,42 @@ a SEV-ES guest:
manage booting APs. manage booting APs.
Debugging Debugging
----------- ---------
Since the memory contents of a SEV guest are encrypted, hypervisor access to 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, 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 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. the guest memory region for debug purposes. This is not supported in QEMU yet.
Snapshot/Restore Snapshot/Restore
----------------- ----------------
TODO TODO
Live Migration Live Migration
---------------- ---------------
TODO TODO
References References
----------------- ----------
AMD Memory Encryption whitepaper: `AMD Memory Encryption whitepaper
https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf <https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf>`_
Secure Encrypted Virtualization Key Management: .. [SEVKM] `Secure Encrypted Virtualization Key Management
[1] http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf <http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf>`_
KVM Forum slides: 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: * `AMDs Virtualization Memory Encryption (2016)
http://support.amd.com/TechDocs/24593.pdf <http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf>`_
SME is section 7.10 * `Extending Secure Encrypted Virtualization With SEV-ES (2018)
SEV is section 15.34 <https://www.linux-kvm.org/images/9/94/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf>`_
SEV-ES is section 15.35
`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

View File

@ -34,3 +34,4 @@ or Hypervisor.Framework.
targets targets
security security
multi-process multi-process
confidential-guest-support

View File

@ -224,6 +224,8 @@ nested. Combinations not shown in the table are not available.
.. [3] Introduced on Power10 machines. .. [3] Introduced on Power10 machines.
.. _power-papr-protected-execution-facility-pef:
POWER (PAPR) Protected Execution Facility (PEF) POWER (PAPR) Protected Execution Facility (PEF)
----------------------------------------------- -----------------------------------------------

View File

@ -28,6 +28,7 @@ Architectural features
i386/cpu i386/cpu
i386/kvm-pv i386/kvm-pv
i386/sgx i386/sgx
i386/amd-memory-encryption
.. _pcsys_005freq: .. _pcsys_005freq:

View File

@ -1083,27 +1083,6 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
return &cpu_ppc_set_tb_clk; 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 */ /* PowerPC 40x timers */

View File

@ -255,13 +255,8 @@ static void ibm_40p_init(MachineState *machine)
exit(1); exit(1);
} }
if (env->flags & POWERPC_FLAG_RTC_CLK) { /* Set time-base frequency to 100 Mhz */
/* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
cpu_ppc_tb_init(env, 7812500UL);
} else {
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
}
qemu_register_reset(ppc_prep_reset, cpu); qemu_register_reset(ppc_prep_reset, cpu);
/* PCI host */ /* PCI host */

View File

@ -54,14 +54,6 @@ uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
return cpu_ppc_get_tb(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 */ /* XXX: to be fixed */
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 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 " cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n"); "while in user mode. Aborting\n");
break; 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 */ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
cpu_abort(cs, "Emulation trap exception not handled\n"); cpu_abort(cs, "Emulation trap exception not handled\n");
break; break;

View File

@ -81,6 +81,8 @@ blobs = files(
'opensbi-riscv32-generic-fw_dynamic.bin', 'opensbi-riscv32-generic-fw_dynamic.bin',
'opensbi-riscv64-generic-fw_dynamic.bin', 'opensbi-riscv64-generic-fw_dynamic.bin',
'npcm7xx_bootrom.bin', 'npcm7xx_bootrom.bin',
'vof.bin',
'vof-nvram.bin',
) )
if get_option('install_blobs') if get_option('install_blobs')

View File

@ -422,12 +422,6 @@
CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, e600) CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, e600)
/* 32 bits "classic" PowerPC */ /* 32 bits "classic" PowerPC */
/* PowerPC 6xx family */ /* 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_DEF("603", CPU_POWERPC_603, 603,
"PowerPC 603") "PowerPC 603")
POWERPC_DEF("603e_v1.1", CPU_POWERPC_603E_v11, 603E, POWERPC_DEF("603e_v1.1", CPU_POWERPC_603E_v11, 603E,
@ -859,8 +853,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "mpc8555", "mpc8555_v11" }, { "mpc8555", "mpc8555_v11" },
{ "mpc8555e", "mpc8555e_v11" }, { "mpc8555e", "mpc8555e_v11" },
{ "mpc8560", "mpc8560_v21" }, { "mpc8560", "mpc8560_v21" },
{ "601", "601_v2" },
{ "601v", "601_v2" },
{ "vanilla", "603" }, { "vanilla", "603" },
{ "603e", "603e_v4.1" }, { "603e", "603e_v4.1" },
{ "stretch", "603e_v4.1" }, { "stretch", "603e_v4.1" },

View File

@ -205,9 +205,6 @@ enum {
#define CPU_POWERPC_MPC8641 CPU_POWERPC_e600 #define CPU_POWERPC_MPC8641 CPU_POWERPC_e600
#define CPU_POWERPC_MPC8641D CPU_POWERPC_e600 #define CPU_POWERPC_MPC8641D CPU_POWERPC_e600
/* PowerPC 6xx cores */ /* PowerPC 6xx cores */
CPU_POWERPC_601_v0 = 0x00010001,
CPU_POWERPC_601_v1 = 0x00010001,
CPU_POWERPC_601_v2 = 0x00010002,
CPU_POWERPC_603 = 0x00030100, CPU_POWERPC_603 = 0x00030100,
CPU_POWERPC_603E_v11 = 0x00060101, CPU_POWERPC_603E_v11 = 0x00060101,
CPU_POWERPC_603E_v12 = 0x00060102, CPU_POWERPC_603E_v12 = 0x00060102,

View File

@ -61,8 +61,6 @@ enum powerpc_mmu_t {
POWERPC_MMU_BOOKE = 0x00000008, POWERPC_MMU_BOOKE = 0x00000008,
/* BookE 2.06 MMU model */ /* BookE 2.06 MMU model */
POWERPC_MMU_BOOKE206 = 0x00000009, POWERPC_MMU_BOOKE206 = 0x00000009,
/* PowerPC 601 MMU model (specific BATs format) */
POWERPC_MMU_601 = 0x0000000A,
#define POWERPC_MMU_64 0x00010000 #define POWERPC_MMU_64 0x00010000
/* 64 bits PowerPC MMU */ /* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001, POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
@ -90,20 +88,10 @@ enum powerpc_excp_t {
POWERPC_EXCP_STD, POWERPC_EXCP_STD,
/* PowerPC 40x exception model */ /* PowerPC 40x exception model */
POWERPC_EXCP_40x, POWERPC_EXCP_40x,
/* PowerPC 601 exception model */ /* PowerPC 603/604/G2 exception model */
POWERPC_EXCP_601, POWERPC_EXCP_6xx,
/* PowerPC 602 exception model */ /* PowerPC 7xx exception model */
POWERPC_EXCP_602, POWERPC_EXCP_7xx,
/* 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 74xx exception model */ /* PowerPC 74xx exception model */
POWERPC_EXCP_74xx, POWERPC_EXCP_74xx,
/* BookE exception model */ /* BookE exception model */

View File

@ -89,11 +89,9 @@ enum {
POWERPC_EXCP_VPU = 73, /* Vector unavailable exception */ POWERPC_EXCP_VPU = 73, /* Vector unavailable exception */
/* 40x specific exceptions */ /* 40x specific exceptions */
POWERPC_EXCP_PIT = 74, /* Programmable interval timer interrupt */ POWERPC_EXCP_PIT = 74, /* Programmable interval timer interrupt */
/* 601 specific exceptions */ /* Vectors 75-76 are 601 specific exceptions */
POWERPC_EXCP_IO = 75, /* IO error exception */
POWERPC_EXCP_RUNM = 76, /* Run mode exception */
/* 602 specific exceptions */ /* 602 specific exceptions */
POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */ POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
/* 602/603 specific exceptions */ /* 602/603 specific exceptions */
POWERPC_EXCP_IFTLB = 78, /* Instruction fetch TLB miss */ POWERPC_EXCP_IFTLB = 78, /* Instruction fetch TLB miss */
POWERPC_EXCP_DLTLB = 79, /* Data load TLB miss */ POWERPC_EXCP_DLTLB = 79, /* Data load TLB miss */
@ -632,8 +630,7 @@ enum {
POWERPC_FLAG_PX = 0x00000200, POWERPC_FLAG_PX = 0x00000200,
POWERPC_FLAG_PMM = 0x00000400, POWERPC_FLAG_PMM = 0x00000400,
/* Flag for special features */ /* Flag for special features */
/* Decrementer clock: RTC clock (POWER, 601) or bus clock */ /* Decrementer clock */
POWERPC_FLAG_RTC_CLK = 0x00010000,
POWERPC_FLAG_BUS_CLK = 0x00020000, POWERPC_FLAG_BUS_CLK = 0x00020000,
/* Has CFAR */ /* Has CFAR */
POWERPC_FLAG_CFAR = 0x00040000, POWERPC_FLAG_CFAR = 0x00040000,
@ -643,8 +640,6 @@ enum {
POWERPC_FLAG_TM = 0x00100000, POWERPC_FLAG_TM = 0x00100000,
/* Has SCV (ISA 3.00) */ /* Has SCV (ISA 3.00) */
POWERPC_FLAG_SCV = 0x00200000, 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. * the MSR are validated in hreg_compute_hflags.
*/ */
enum { 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_HV = 1, /* computed from MSR_HV and other state */
HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */ HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */
HFLAGS_GTSE = 3, /* computed from SPR_LPCR[GTSE] */ 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); void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value);
uint64_t cpu_ppc_load_purr(CPUPPCState *env); uint64_t cpu_ppc_load_purr(CPUPPCState *env);
void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value); 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) #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); target_ulong load_40x_pit(CPUPPCState *env);
void store_40x_pit(CPUPPCState *env, target_ulong val); void store_40x_pit(CPUPPCState *env, target_ulong val);
void store_40x_dbcr0(CPUPPCState *env, uint32_t val); void store_40x_dbcr0(CPUPPCState *env, uint32_t val);
@ -1516,17 +1507,12 @@ typedef PowerPCCPU ArchCPU;
/* SPR definitions */ /* SPR definitions */
#define SPR_MQ (0x000) #define SPR_MQ (0x000)
#define SPR_XER (0x001) #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_LR (0x008)
#define SPR_CTR (0x009) #define SPR_CTR (0x009)
#define SPR_UAMR (0x00D) #define SPR_UAMR (0x00D)
#define SPR_DSCR (0x011) #define SPR_DSCR (0x011)
#define SPR_DSISR (0x012) #define SPR_DSISR (0x012)
#define SPR_DAR (0x013) /* DAE for PowerPC 601 */ #define SPR_DAR (0x013)
#define SPR_601_RTCU (0x014)
#define SPR_601_RTCL (0x015)
#define SPR_DECR (0x016) #define SPR_DECR (0x016)
#define SPR_SDR1 (0x019) #define SPR_SDR1 (0x019)
#define SPR_SRR0 (0x01A) #define SPR_SRR0 (0x01A)
@ -2003,7 +1989,6 @@ typedef PowerPCCPU ArchCPU;
#define SPR_HID1 (0x3F1) #define SPR_HID1 (0x3F1)
#define SPR_IABR (0x3F2) #define SPR_IABR (0x3F2)
#define SPR_40x_DBCR0 (0x3F2) #define SPR_40x_DBCR0 (0x3F2)
#define SPR_601_HID2 (0x3F2)
#define SPR_Exxx_L1CSR0 (0x3F2) #define SPR_Exxx_L1CSR0 (0x3F2)
#define SPR_ICTRL (0x3F3) #define SPR_ICTRL (0x3F3)
#define SPR_HID2 (0x3F3) #define SPR_HID2 (0x3F3)
@ -2019,7 +2004,6 @@ typedef PowerPCCPU ArchCPU;
#define DABR_MASK (~(target_ulong)0x7) #define DABR_MASK (~(target_ulong)0x7)
#define SPR_Exxx_BUCSR (0x3F5) #define SPR_Exxx_BUCSR (0x3F5)
#define SPR_40x_IAC2 (0x3F5) #define SPR_40x_IAC2 (0x3F5)
#define SPR_601_HID5 (0x3F5)
#define SPR_40x_DAC1 (0x3F6) #define SPR_40x_DAC1 (0x3F6)
#define SPR_MSSCR0 (0x3F6) #define SPR_MSSCR0 (0x3F6)
#define SPR_970_HID5 (0x3F6) #define SPR_970_HID5 (0x3F6)
@ -2052,7 +2036,6 @@ typedef PowerPCCPU ArchCPU;
#define SPR_403_PBL2 (0x3FE) #define SPR_403_PBL2 (0x3FE)
#define SPR_PIR (0x3FF) #define SPR_PIR (0x3FF)
#define SPR_403_PBU2 (0x3FF) #define SPR_403_PBU2 (0x3FF)
#define SPR_601_HID15 (0x3FF)
#define SPR_604_HID15 (0x3FF) #define SPR_604_HID15 (0x3FF)
#define SPR_E500_SVR (0x3FF) #define SPR_E500_SVR (0x3FF)
@ -2117,15 +2100,6 @@ enum {
#define PPC_RES PPC_INSNS_BASE #define PPC_RES PPC_INSNS_BASE
/* spr/msr access instructions */ /* spr/msr access instructions */
#define PPC_MISC PPC_INSNS_BASE #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 */ /* 64 bits PowerPC instruction set */
PPC_64B = 0x0000000000000020ULL, PPC_64B = 0x0000000000000020ULL,
/* New 64 bits extensions (PowerPC 2.0x) */ /* New 64 bits extensions (PowerPC 2.0x) */
@ -2236,8 +2210,7 @@ enum {
/* popcntw and popcntd instructions */ /* popcntw and popcntd instructions */
PPC_POPCNTWD = 0x8000000000000000ULL, PPC_POPCNTWD = 0x8000000000000000ULL,
#define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_POWER | PPC_POWER2 \ #define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_64B \
| PPC_POWER_RTC | PPC_POWER_BR | PPC_64B \
| PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \ | PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \
| PPC_ISEL | PPC_POPCNTB \ | PPC_ISEL | PPC_POPCNTB \
| PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \ | PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \

View File

@ -749,83 +749,6 @@ static void register_G2_sprs(CPUPPCState *env)
0x00000000); 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) static void register_74xx_sprs(CPUPPCState *env)
{ {
/* Processor identification */ /* Processor identification */
@ -2060,26 +1983,6 @@ static void init_excp_BookE(CPUPPCState *env)
#endif #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) static void init_excp_603(CPUPPCState *env)
{ {
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
@ -2703,89 +2606,6 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; 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) static void init_proc_440x5(CPUPPCState *env)
{ {
/* Time base */ /* Time base */
@ -2962,7 +2782,7 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_REAL; 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->bus_model = PPC_FLAGS_INPUT_RCPU;
pcc->bfd_mach = bfd_mach_ppc_505; pcc->bfd_mach = bfd_mach_ppc_505;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -3005,7 +2825,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_MPC8xx; 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->bus_model = PPC_FLAGS_INPUT_RCPU;
pcc->bfd_mach = bfd_mach_ppc_860; pcc->bfd_mach = bfd_mach_ppc_860;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -3086,7 +2906,7 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
(1ull << MSR_DR) | (1ull << MSR_DR) |
(1ull << MSR_RI); (1ull << MSR_RI);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e; pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@ -3168,7 +2988,7 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e; pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@ -3423,7 +3243,7 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_603; pcc->bfd_mach = bfd_mach_ppc_603;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@ -3892,120 +3712,6 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
#endif #endif
/* Non-embedded PowerPC */ /* 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) static void init_proc_603(CPUPPCState *env)
{ {
register_ne_601_sprs(env); register_ne_601_sprs(env);
@ -4066,7 +3772,7 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_603; pcc->bfd_mach = bfd_mach_ppc_603;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@ -4105,7 +3811,7 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_ec603e; pcc->bfd_mach = bfd_mach_ppc_ec603e;
pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE | pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
@ -4166,7 +3872,7 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604; pcc->bfd_mach = bfd_mach_ppc_604;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4247,7 +3953,7 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_604; pcc->bfd_mach = bfd_mach_ppc_604;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4315,7 +4021,7 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4392,7 +4098,7 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4592,7 +4298,7 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4672,7 +4378,7 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4757,7 +4463,7 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4842,7 +4548,7 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_32B; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -4918,7 +4624,7 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
@ -5005,7 +4711,7 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
(1ull << MSR_RI) | (1ull << MSR_RI) |
(1ull << MSR_LE); (1ull << MSR_LE);
pcc->mmu_model = POWERPC_MMU_SOFT_6xx; 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->bus_model = PPC_FLAGS_INPUT_6xx;
pcc->bfd_mach = bfd_mach_ppc_750; pcc->bfd_mach = bfd_mach_ppc_750;
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE | 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"); "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
exit(1); 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" fprintf(stderr, "PowerPC flags inconsistency\n"
"Should define the time-base and decrementer clock source\n"); "Should define the time-base and decrementer clock source\n");
exit(1); exit(1);
@ -8574,7 +8280,6 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
switch (env->mmu_model) { switch (env->mmu_model) {
case POWERPC_MMU_32B: case POWERPC_MMU_32B:
case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case POWERPC_MMU_64B: case POWERPC_MMU_64B:

File diff suppressed because it is too large Load Diff

View File

@ -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, \ void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \ ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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, \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \ ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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, \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \ ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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) \ #define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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) \ #define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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) \ #define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
helper_reset_fpstatus(env); \ 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, \ void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \ ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
for (i = 0; i < nels; 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, \ void helper_##name(CPUPPCState *env, \
ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \ 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; \ bool vxsnan_flag = false, vex_flag = false; \
\ \
if (unlikely(float64_is_any_nan(xa->VsrD(0)) || \ if (unlikely(float64_is_any_nan(xa->VsrD(0)) || \
@ -2533,7 +2533,7 @@ VSX_MAX_MINC(xsmincdp, 0);
void helper_##name(CPUPPCState *env, \ void helper_##name(CPUPPCState *env, \
ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \ 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; \ bool vxsnan_flag = false, vex_flag = false; \
\ \
if (unlikely(float64_is_any_nan(xa->VsrD(0)))) { \ 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) \ #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) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
for (i = 0; i < nels; 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) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
int all_flags = env->fp_status.float_exception_flags, flags; \ int all_flags = env->fp_status.float_exception_flags, flags; \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
for (i = 0; i < nels; 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) \ #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) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
\ \
for (i = 0; i < nels; 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) \ #define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \ { \
ppc_vsr_t t = *xt; \ ppc_vsr_t t = { }; \
int i; \ int i; \
FloatRoundMode curr_rounding_mode; \ FloatRoundMode curr_rounding_mode; \
\ \

View File

@ -7,7 +7,6 @@ DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(store_msr, void, env, tl) DEF_HELPER_2(store_msr, void, env, tl)
DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi, void, env)
DEF_HELPER_1(rfsvc, void, env)
DEF_HELPER_1(40x_rfci, void, env) DEF_HELPER_1(40x_rfci, void, env)
DEF_HELPER_1(rfci, void, env) DEF_HELPER_1(rfci, void, env)
DEF_HELPER_1(rfdi, void, env) DEF_HELPER_1(rfdi, void, env)
@ -653,14 +652,9 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
#endif #endif
DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32) 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) #if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(rac, tl, env, tl) DEF_HELPER_2(rac, tl, env, tl)
#endif #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_2(load_dcr, tl, env, tl)
DEF_HELPER_3(store_dcr, void, env, tl, 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_atbl, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_atbu, 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_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(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env) 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_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_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_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_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_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_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_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_vtb, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbu40, 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_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_pit, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_40x_tcr, 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_ibatu, void, env, i32, tl)
DEF_HELPER_3(store_dbatl, 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_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 #endif
#define dh_alias_fprp ptr #define dh_alias_fprp ptr

View File

@ -59,15 +59,6 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
msr_mask = ((1 << MSR_LE) | (1 << MSR_PR) | msr_mask = ((1 << MSR_LE) | (1 << MSR_PR) |
(1 << MSR_DR) | (1 << MSR_FP)); (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) { if (ppc_flags & POWERPC_FLAG_DE) {
target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0]; target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0];
if (dbcr0 & DBCR0_ICMP) { 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); hreg_swap_gpr_tgpr(env);
} }
if (unlikely((value >> MSR_EP) & 1) != msr_ep) { if (unlikely((value >> MSR_EP) & 1) != msr_ep) {
/* Change the exception prefix on PowerPC 601 */
env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000; env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
} }
/* /*

View File

@ -422,72 +422,6 @@ uint64_t helper_PEXTD(uint64_t src, uint64_t mask)
return result; return result;
} }
/*****************************************************************************/
/* 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 */ /* Altivec extension helpers */
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)

View File

@ -205,9 +205,8 @@ static int cpu_pre_save(void *opaque)
} }
} }
/* Retain migration compatibility for pre 6.0 for 601 machines. */ /* Used to retain migration compatibility for pre 6.0 for 601 machines. */
env->hflags_compat_nmsr = (env->flags & POWERPC_FLAG_HID0_LE env->hflags_compat_nmsr = 0;
? env->hflags & MSR_LE : 0);
return 0; return 0;
} }

View File

@ -211,21 +211,6 @@ void helper_store_lpidr(CPUPPCState *env, target_ulong val)
tlb_flush(env_cpu(env)); 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) void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val)
{ {
/* Bits 26 & 27 affect single-stepping. */ /* 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); store_40x_sler(env, val);
} }
#endif #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 */ /* Special registers manipulation */

View File

@ -125,30 +125,6 @@ static int hash32_bat_prot(PowerPCCPU *cpu,
return prot; 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, static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
MMUAccessType access_type, int *prot, MMUAccessType access_type, int *prot,
int mmu_idx) 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 batl = BATlt[i];
target_ulong mask; target_ulong mask;
if (unlikely(env->mmu_model == POWERPC_MMU_601)) { mask = hash32_bat_size(mmu_idx, batu, batl);
mask = hash32_bat_601_size(cpu, batu, batl);
} else {
mask = hash32_bat_size(mmu_idx, batu, batl);
}
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
" BATl " TARGET_FMT_lx "\n", __func__, " BATl " TARGET_FMT_lx "\n", __func__,
ifetch ? 'I' : 'D', i, ea, batu, batl); 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))) { if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
hwaddr raddr = (batl & mask) | (ea & ~mask); hwaddr raddr = (batl & mask) | (ea & ~mask);
if (unlikely(env->mmu_model == POWERPC_MMU_601)) { *prot = hash32_bat_prot(cpu, batu, batl);
*prot = hash32_bat_601_prot(mmu_idx, batu, batl);
} else {
*prot = hash32_bat_prot(cpu, batu, batl);
}
return raddr & TARGET_PAGE_MASK; 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"); 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) { if (access_type == MMU_INST_FETCH) {
/* No code fetch is allowed in direct-store areas */ /* No code fetch is allowed in direct-store areas */
if (guest_visible) { if (guest_visible) {

View File

@ -34,15 +34,6 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
#define BATL32_WIMG 0x00000078 #define BATL32_WIMG 0x00000078
#define BATL32_PP 0x00000003 #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 * Hash page table definitions
*/ */

View File

@ -327,13 +327,9 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu,
uint64_t pte; uint64_t pte;
qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx 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), __func__, access_str(access_type),
eaddr, mmu_idx, eaddr, mmu_idx, g_raddr);
*h_prot & PAGE_READ ? 'r' : '-',
*h_prot & PAGE_WRITE ? 'w' : '-',
*h_prot & PAGE_EXEC ? 'x' : '-',
g_raddr);
*h_page_size = PRTBE_R_GET_RTS(pate.dw0); *h_page_size = PRTBE_R_GET_RTS(pate.dw0);
/* No valid pte or access denied due to protection */ /* No valid pte or access denied due to protection */

View File

@ -441,29 +441,9 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
ret = -3; ret = -3;
} }
} else { } else {
target_ulong sr;
qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
/* Direct-store segment : absolutely *BUGGY* for now */ /* 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) { switch (type) {
case ACCESS_INT: case ACCESS_INT:
/* Integer load/store : only access allowed */ /* Integer load/store : only access allowed */
@ -1539,7 +1519,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
#endif #endif
case POWERPC_MMU_32B: case POWERPC_MMU_32B:
case POWERPC_MMU_601:
return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp, return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
psizep, protp, mmu_idx, guest_visible); psizep, protp, mmu_idx, guest_visible);

View File

@ -279,88 +279,6 @@ void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
env->DBAT[1][nr] = 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 */ /* TLB management */
void ppc_tlb_invalidate_all(CPUPPCState *env) void ppc_tlb_invalidate_all(CPUPPCState *env)
@ -392,7 +310,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
booke206_flush_tlb(env, -1, 0); booke206_flush_tlb(env, -1, 0);
break; break;
case POWERPC_MMU_32B: case POWERPC_MMU_32B:
case POWERPC_MMU_601:
env->tlb_need_flush = 0; env->tlb_need_flush = 0;
tlb_flush(env_cpu(env)); tlb_flush(env_cpu(env));
break; break;
@ -426,7 +343,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
} }
break; break;
case POWERPC_MMU_32B: case POWERPC_MMU_32B:
case POWERPC_MMU_601:
/* /*
* Actual CPUs invalidate entire congruence classes based on * Actual CPUs invalidate entire congruence classes based on
* the geometry of their TLBs and some OSes take that into * the geometry of their TLBs and some OSes take that into

View File

@ -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_tbu(DisasContext *ctx, int gprn, int sprn);
void spr_read_atbl(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_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_read_spefscr(DisasContext *ctx, int gprn, int sprn);
void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn); void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0_ureg(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(DisasContext *ctx, int sprn, int gprn);
void spr_write_dbatl_h(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_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_read_40x_pit(DisasContext *ctx, int gprn, int sprn);
void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn);
void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn);

View File

@ -63,16 +63,6 @@ void helper_store_purr(CPUPPCState *env, target_ulong val)
} }
#endif #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) #if !defined(CONFIG_USER_ONLY)
void helper_store_tbl(CPUPPCState *env, target_ulong val) 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); 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) target_ulong helper_load_decr(CPUPPCState *env)
{ {
return cpu_ppc_load_decr(env); return cpu_ppc_load_decr(env);

View File

@ -794,61 +794,6 @@ void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
#endif #endif
#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 */ /* PowerPC 40x specific registers */
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn) 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); 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 */ /* 602 - 603 - G2 TLB management */
/* tlbld */ /* tlbld */
@ -6296,81 +5578,6 @@ static void gen_tlbli_6xx(DisasContext *ctx)
#endif /* defined(CONFIG_USER_ONLY) */ #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 */ /* BookE specific instructions */
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
@ -7718,56 +6925,8 @@ GEN_HANDLER_E(slbsync, 0x1F, 0x12, 0x0A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
#endif #endif
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN), GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 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(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 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(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA), GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR), 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); ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
#endif #endif
ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
|| env->mmu_model == POWERPC_MMU_601
|| env->mmu_model & POWERPC_MMU_64; || env->mmu_model & POWERPC_MMU_64;
ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1; ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1;

View File

@ -1105,185 +1105,6 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
/* stfiwx */ /* stfiwx */
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_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 */ /* Floating-point Load/Store Instructions */
static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ, static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
bool update, bool store, bool single) bool update, bool store, bool single)

View File

@ -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), xb, true); \
set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
tcg_temp_free_i64(xb); \ tcg_temp_free_i64(xb); \
tcg_temp_free_i64(sgm); \ tcg_temp_free_i64(sgm); \
} }
@ -1073,6 +1074,7 @@ static void gen_##name(DisasContext *ctx) \
get_cpu_vsr(t0, xB(ctx->opcode), true); \ get_cpu_vsr(t0, xB(ctx->opcode), true); \
gen_helper_##name(t1, cpu_env, t0); \ gen_helper_##name(t1, cpu_env, t0); \
set_cpu_vsr(xT(ctx->opcode), t1, true); \ 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(t0); \
tcg_temp_free_i64(t1); \ tcg_temp_free_i64(t1); \
} }
@ -1700,7 +1702,7 @@ static void gen_xsiexpdp(DisasContext *ctx)
tcg_gen_shli_i64(t0, t0, 52); tcg_gen_shli_i64(t0, t0, 52);
tcg_gen_or_i64(xth, xth, t0); tcg_gen_or_i64(xth, xth, t0);
set_cpu_vsr(xT(ctx->opcode), xth, true); 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(t0);
tcg_temp_free_i64(xth); tcg_temp_free_i64(xth);
} }