Great rework and cleanups to ease PowerPC implementations definitions.

* cleanup cpu.h, removing definitions used only in translate.c/translate_init.c
* add new flags to define instructions sets more precisely
* various changes in MMU models definitions
* add definitions for PowerPC 440/460 support (insns and SPRs).
* add definitions for PowerPC 401/403 and 620 input pins model
* Fix definitions for most PowerPC 401, 403, 405, 440, 601, 602, 603 and 7x0
* Preliminary support for PowerPC 74xx (aka G4) without altivec.
* Code provision for other PowerPC support (7x5, 970, ...).
* New SPR and PVR defined, from PowerPC 2.04 specification and other sources
* Misc code bugs, error messages and styles fixes.
* Update status files for PowerPC cores support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3244 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
j_mayer 2007-09-26 23:54:22 +00:00
parent 08fa4bab83
commit a750fc0b91
11 changed files with 4346 additions and 3189 deletions

View File

@ -376,11 +376,11 @@ static void ppc405_set_irq (void *opaque, int pin, int level)
/* Level sensitive - active high */ /* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ) #if defined(PPC_DEBUG_IRQ)
if (loglevel & CPU_LOG_INT) { if (loglevel & CPU_LOG_INT) {
fprintf(logfile, "%s: set the external IRQ state to %d\n", fprintf(logfile, "%s: set the debug pin state to %d\n",
__func__, level); __func__, level);
} }
#endif #endif
ppc_set_irq(env, EXCP_40x_DEBUG, level); ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
break; break;
default: default:
/* Unknown pin - do nothing */ /* Unknown pin - do nothing */
@ -904,6 +904,9 @@ struct ppc_dcrn_t {
void *opaque; void *opaque;
}; };
/* XXX: on 460, DCR addresses are 32 bits wide,
* using DCRIPR to get the 22 upper bits of the DCR address
*/
#define DCRN_NB 1024 #define DCRN_NB 1024
struct ppc_dcr_t { struct ppc_dcr_t {
ppc_dcrn_t dcrn[DCRN_NB]; ppc_dcrn_t dcrn[DCRN_NB];

View File

@ -712,6 +712,17 @@ uint32_t cpu_ppc601_load_rtcl (CPUState *env)
return cpu_ppc_load_tbl(env) & 0x3FFFFF80; return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
} }
/* XXX: to be fixed */
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
{
return -1;
}
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
{
return -1;
}
void cpu_loop(CPUPPCState *env) void cpu_loop(CPUPPCState *env)
{ {
target_siginfo_t info; target_siginfo_t info;
@ -761,7 +772,7 @@ void cpu_loop(CPUPPCState *env)
case EXCP_MACHINE_CHECK: case EXCP_MACHINE_CHECK:
fprintf(stderr, "Machine check exeption... Stop emulation\n"); fprintf(stderr, "Machine check exeption... Stop emulation\n");
if (loglevel) if (loglevel)
fprintf(logfile, "RESET asked... Stop emulation\n"); fprintf(logfile, "Machine check exception. Stop emulation\n");
info.si_signo = TARGET_SIGBUS; info.si_signo = TARGET_SIGBUS;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_BUS_OBJERR; info.si_code = TARGET_BUS_OBJERR;
@ -914,7 +925,7 @@ void cpu_loop(CPUPPCState *env)
info.si_code = TARGET_ILL_ILLOPC; info.si_code = TARGET_ILL_ILLOPC;
break; break;
case EXCP_INVAL_LSWX: case EXCP_INVAL_LSWX:
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
break; break;
case EXCP_INVAL_SPR: case EXCP_INVAL_SPR:
info.si_code = TARGET_ILL_PRVREG; info.si_code = TARGET_ILL_PRVREG;
@ -1003,7 +1014,7 @@ void cpu_loop(CPUPPCState *env)
if (loglevel) if (loglevel)
fprintf(logfile, "Tried to go into supervisor mode !\n"); fprintf(logfile, "Tried to go into supervisor mode !\n");
abort(); abort();
} }
break; break;
case EXCP_BRANCH: case EXCP_BRANCH:
/* We stopped because of a jump... */ /* We stopped because of a jump... */

View File

@ -4,268 +4,463 @@ The goal of this file is to provide a reference status to avoid regressions.
=============================================================================== ===============================================================================
PowerPC core emulation status PowerPC core emulation status
32 bits PowerPC INSN: instruction set.
PowerPC 601: OK => all instructions are emulated
INSN KO => some insns are missing or some should be removed
SPR ? => unchecked
MMU SPR: special purpose registers set
EXCP OK => all SPR registered (but some may be fake)
KO => some SPR are missing or should be removed
PowerPC 602: ? => uncheked
INSN MSR: MSR bits definitions
SPR OK => all MSR bits properly defined
MMU KO => MSR definition is incorrect
EXCP ? => unchecked
IRQ: input signals definitions (mostly interrupts)
PowerPC 603: OK => input signals are properly defined
INSN OK KO => input signals are not implemented (system emulation does not work)
SPR OK ? => input signals definitions may be incorrect
MMU OK MMU: MMU model implementation
EXCP OK OK => MMU model is implemented and Linux is able to boot
KO => MMU model not implemented or bugged
PowerPC 604: ? => MMU model not tested
INSN OK EXCP: exceptions model implementation
SPR OK OK => exception model is implemented and Linux is able to boot
MMU OK KO => exception model not implemented or known to be buggy
EXCP OK ? => exception model may be incorrect or is untested
PowerPC 740:
INSN OK
SPR OK
MMU OK
EXCP OK
PowerPC 745:
INSN
SPR
MMU
EXCP
PowerPC 750:
INSN OK
SPR OK
MMU OK
EXCP OK
PowerPC 755:
INSN
SPR
MMU
EXCP
PowerPC 7400:
INSN KO
SPR KO
MMU OK
EXCP OK
PowerPC 7410:
INSN KO
SPR KO
MMU OK
EXCP OK
PowerPC 7450:
INSN KO
SPR KO
MMU OK
EXCP OK
PowerPC 7455:
INSN KO
SPR KO
MMU OK
EXCP OK
PowerPC 7457:
INSN KO
SPR KO
MMU OK
EXCP OK
PowerPC 7457A:
INSN KO
SPR KO
MMU OK
EXCP OK
64 bits PowerPC
PowerPC 970:
INSN KO
SPR KO
MMU KO
EXCP KO
PowerPC 620: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
PowerPC 630: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
PowerPC 631: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
POWER4: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
POWER4+: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
POWER5: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
POWER5+: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
POWER6: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
RS64: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
RS64-II: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
RS64-III: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
RS64-IV: (lack of precise informations)
INSN KO
SPR KO
MMU KO
EXCP KO
Embedded PowerPC cores Embedded PowerPC cores
***
PowerPC 401: PowerPC 401:
INSN OK INSN OK
SPR OK SPR OK 401A1
MMU OK MSR OK
EXCP ? IRQ KO partially implemented
MMU OK
EXCP ?
PowerPC 401x2:
INSN OK
SPR OK 401B2 401C2 401D2 401E2 401F2
MSR OK
IRQ KO partially implemented
MMU OK
EXCP ?
PowerPC IOP480:
INSN OK
SPR OK IOP480
MSR OK
IRQ KO partially implemented
MMU OK
EXCP ?
To be checked: 401G2 401B3 Cobra
***
PowerPC 403: PowerPC 403:
INSN OK INSN OK
SPR OK SPR OK 403GA 403GB
MMU OK MMU OK
EXCP ? MSR OK
IRQ KO not implemented
EXCP ?
PowerPC 403GCX:
INSN OK
SPR OK 403GCX
MMU OK
MSR OK
IRQ KO not implemented
EXCP ?
To be checked: 403GC
***
PowerPC 405: PowerPC 405:
INSN OK Checked: 405CRa 405CRb 405CRc 405EP 405GPa 405GPb 405GPc 405GPd 405GPe 405GPR
SPR OK Npe405H Npe405H2 Npe405L
MMU OK
EXCP OK
PowerPC 440:
INSN OK INSN OK
SPR OK SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
=> Linux 2.4 boots (at least 1 proprietary firmware).
To be checked: 405D2 405D4 405EZ 405LP Npe4GS3 STB03 STB04 STB25
x2vp4 x2vp7 x2vp20 x2vp50
XXX: find what is IBM e407b4
***
PowerPC 440:
Checked: 440EPa 440EPb 440GXa 440GXb 440GXc 440GXf 440SP 440SP2
INSN OK
SPR OK
MSR OK
IRQ KO not implemented
MMU ? MMU ?
EXCP ? EXCP ?
PowerPC 460: (lack of precise informations) PowerPC 440GP:
Checked: 440GPb 440GPc
INSN OK
SPR OK
MSR OK
IRQ KO not implemented
MMU ?
EXCP ?
PowerPC 440x4:
Checked: 440A4 440B4 440G4 440H4
INSN OK
SPR OK
MSR OK
IRQ KO not implemented
MMU ?
EXCP ?
PowerPC 440x5:
Checked: 440A5 440F5 440G5 440H6 440GRa
INSN OK
SPR OK
MSR OK
IRQ KO not implemented
MMU ?
EXCP ?
To be checked: 440EPx 440GRx 440SPE
***
PowerPC 460: (disabled: lack of detailed specifications)
INSN KO INSN KO
SPR KO SPR KO
MSR KO
IRQ KO
MMU KO MMU KO
EXCP KO EXCP KO
Freescale (to be completed) ... PowerPC 460F: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
***
PowerPC e200: (not implemented)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
***
PowerPC e300: (not implemented)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
***
PowerPC e500: (not implemented)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
***
PowerPC e600: (not implemented)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
***
32 bits PowerPC
PowerPC 601: (601 601v2)
INSN OK
SPR OK is HID15 only on 601v2 ?
MSR OK
IRQ KO not implemented
MMU ?
EXCP ?
Remarks: some instructions should have a specific behavior (not implemented)
PowerPC 602: 602
INSN OK
SPR OK
MSR OK
IRQ OK
MMU ?
EXCP ? at least timer and external interrupt are OK
Remarks: Linux crashes when entering user-mode. But it seems it does not
know about this CPU. As this CPU is close to 603e, it should be OK.
PowerPC 603: (603)
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots and properly recognizes the CPU
PowerPC 603e: (603e11)
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots and properly recognizes the CPU
PowerPC G2:
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots, recognizes the CPU as a 82xx.
PowerPC G2le:
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 does not boots. Same symptoms as 602.
PowerPC 604:
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots and properly recognizes the CPU.
PowerPC 7x0:
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots and properly recognizes the CPU.
PowerPC 750fx:
INSN OK
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP OK
Remarks: Linux 2.4 boots but does not properly recognizes the CPU.
PowerPC 7x5:
INSN ?
SPR ?
MSR ?
IRQ OK
MMU ?
EXCP OK
=> Linux 2.4 does not boot.
PowerPC 7400:
INSN KO Altivec missing
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP ? Altivec, ...
=> Linux 2.4 boots and properly recognize the CPU.
PowerPC 7410:
INSN KO Altivec missing
SPR OK
MSR OK
IRQ OK
MMU OK
EXCP ? Altivec, ...
=> Linux 2.4 boots and properly recognize the CPU.
Note that UM says tlbld & tlbli are implemented bus this may be a mistake
as TLB load are managed by the hardware and it does not implement the
needed registers.
PowerPC 7441:
INSN KO Altivec missing + TLB load insns missing
SPR OK
MSR OK
IRQ OK
MMU KO not implemented
EXCP ? Altivec, ...
PowerPC 7450/7451:
INSN KO Altivec missing + TLB load insns missing
SPR OK
MSR OK
IRQ OK
MMU KO not implemented
EXCP ? Altivec, ...
PowerPC 7445/7447:
INSN KO Altivec missing + TLB load insns missing
SPR OK
MSR OK
IRQ OK
MMU KO not implemented
EXCP ? Altivec, ...
PowerPC 7455/7457:
INSN KO Altivec missing + TLB load insns missing
SPR OK
MSR OK
IRQ OK
MMU KO not implemented
EXCP ? Altivec, ...
64 bits PowerPC
PowerPC 620: (disabled)
INSN KO
SPR KO
MSR ?
IRQ KO
MMU KO
EXCP KO
PowerPC 970: (disabled)
INSN KO Altivec missing and more
SPR KO
MSR ?
IRQ OK
MMU KO partially implemented
EXCP KO
PowerPC 970FX: (disabled)
INSN KO Altivec missing and more
SPR KO
MSR ?
IRQ OK
MMU KO partially implemented
EXCP KO
PowerPC 630: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
PowerPC 631: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
POWER4: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
POWER4+: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
POWER5: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
POWER5+: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
POWER6: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
RS64: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
RS64-II: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
RS64-III: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
RS64-IV: (disabled: lack of detailed specifications)
INSN KO
SPR KO
MSR KO
IRQ KO
MMU KO
EXCP KO
Original POWER Original POWER
POWER: (lack of precise informations) POWER: (disabled: lack of detailed specifications)
INSN KO INSN KO
SPR KO SPR KO
MSR KO
IRQ KO
MMU KO MMU KO
EXCP KO EXCP KO
POWER2: (lack of precise informations) POWER2: (disabled: lack of detailed specifications)
INSN KO INSN KO
SPR KO SPR KO
MSR KO
IRQ KO
MMU KO MMU KO
EXCP KO EXCP KO
PowerPC CPU known to work (ie booting at least Linux 2.4):
* main stream PowerPC cores
- PowerPC 603 & derivatives
- PowerPC 604 & derivatives
- PowerPC 740 & derivatives
- PowerPC 750 & derivatives
- PowerPC 405
PowerPC that should work but are not supported by standard Linux kernel
(then remain mostly untested)
- PowerPC 745
- PowerPC 755
Work in progress:
* embedded PowerPC cores
- BookE PowerPC
- e500 core (Freescale PowerQUICC)
* main stream PowerPC cores
- PowerPC 601
- PowerPC 602
TODO:
* embedded PowerPC cores
- PowerPC 401
- PowerPC 403
- PowerPC 440
- PowerPC 460
* main stream PowerPC cores
- PowerPC 7400 (aka G4)
- PowerPC 7410
- PowerPC 7450
- PowerPC 7455
- PowerPC 7457
- PowerPC 7457A
* original POWER
- POWER
- POWER2
* 64 bits PowerPC cores
- PowerPC 620
- PowerPC 630 (aka POWER3)
- PowerPC 631 (aka POWER3+)
- POWER4
- POWER4+
- POWER5
- POWER5+
- PowerPC 970
* RS64 series
- RS64
- RS64-II
- RS64-III
- RS64-IV
=============================================================================== ===============================================================================
PowerPC microcontrollers emulation status PowerPC microcontrollers emulation status

View File

@ -89,528 +89,89 @@ typedef uint32_t ppc_gpr_t;
#define DCACHE_LINE_SIZE 32 #define DCACHE_LINE_SIZE 32
/*****************************************************************************/ /*****************************************************************************/
/* PVR definitions for most known PowerPC */ /* MMU model */
enum { enum {
/* PowerPC 401 cores */ POWERPC_MMU_UNKNOWN = 0,
CPU_PPC_401A1 = 0x00210000, /* Standard 32 bits PowerPC MMU */
CPU_PPC_401B2 = 0x00220000, POWERPC_MMU_32B,
#if 0 /* Standard 64 bits PowerPC MMU */
CPU_PPC_401B3 = xxx, POWERPC_MMU_64B,
#endif /* PowerPC 601 MMU */
CPU_PPC_401C2 = 0x00230000, POWERPC_MMU_601,
CPU_PPC_401D2 = 0x00240000, /* PowerPC 6xx MMU with software TLB */
CPU_PPC_401E2 = 0x00250000, POWERPC_MMU_SOFT_6xx,
CPU_PPC_401F2 = 0x00260000, /* PowerPC 74xx MMU with software TLB */
CPU_PPC_401G2 = 0x00270000, POWERPC_MMU_SOFT_74xx,
#if 0 /* PowerPC 4xx MMU with software TLB */
CPU_PPC_401GF = xxx, POWERPC_MMU_SOFT_4xx,
#endif /* PowerPC 4xx MMU with software TLB and zones protections */
#define CPU_PPC_401 CPU_PPC_401G2 POWERPC_MMU_SOFT_4xx_Z,
CPU_PPC_IOP480 = 0x40100000, /* 401B2 ? */ /* PowerPC 4xx MMU in real mode only */
CPU_PPC_COBRA = 0x10100000, /* IBM Processor for Network Resources */ POWERPC_MMU_REAL_4xx,
/* PowerPC 403 cores */ /* BookE MMU model */
CPU_PPC_403GA = 0x00200011, POWERPC_MMU_BOOKE,
CPU_PPC_403GB = 0x00200100, /* BookE FSL MMU model */
CPU_PPC_403GC = 0x00200200, POWERPC_MMU_BOOKE_FSL,
CPU_PPC_403GCX = 0x00201400, /* 64 bits "bridge" PowerPC MMU */
#if 0 POWERPC_MMU_64BRIDGE,
CPU_PPC_403GP = xxx,
#endif
#define CPU_PPC_403 CPU_PPC_403GCX
/* PowerPC 405 cores */
#if 0
CPU_PPC_405A3 = xxx,
#endif
#if 0
CPU_PPC_405A4 = xxx,
#endif
#if 0
CPU_PPC_405B3 = xxx,
#endif
CPU_PPC_405D2 = 0x20010000,
CPU_PPC_405D4 = 0x41810000,
CPU_PPC_405CR = 0x40110145,
#define CPU_PPC_405GP CPU_PPC_405CR
CPU_PPC_405EP = 0x51210950,
#if 0
CPU_PPC_405EZ = xxx,
#endif
CPU_PPC_405GPR = 0x50910951,
#if 0
CPU_PPC_405LP = xxx,
#endif
#define CPU_PPC_405 CPU_PPC_405D4
CPU_PPC_NPE405H = 0x414100C0,
CPU_PPC_NPE405H2 = 0x41410140,
CPU_PPC_NPE405L = 0x416100C0,
#if 0
CPU_PPC_LC77700 = xxx,
#endif
/* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
#if 0
CPU_PPC_STB01000 = xxx,
#endif
#if 0
CPU_PPC_STB01010 = xxx,
#endif
#if 0
CPU_PPC_STB0210 = xxx,
#endif
CPU_PPC_STB03 = 0x40310000,
#if 0
CPU_PPC_STB043 = xxx,
#endif
#if 0
CPU_PPC_STB045 = xxx,
#endif
CPU_PPC_STB25 = 0x51510950,
#if 0
CPU_PPC_STB130 = xxx,
#endif
/* Xilinx cores */
CPU_PPC_X2VP4 = 0x20010820,
#define CPU_PPC_X2VP7 CPU_PPC_X2VP4
CPU_PPC_X2VP20 = 0x20010860,
#define CPU_PPC_X2VP50 CPU_PPC_X2VP20
/* PowerPC 440 cores */
CPU_PPC_440EP = 0x422218D3,
#define CPU_PPC_440GR CPU_PPC_440EP
CPU_PPC_440GP = 0x40120481,
#if 0
CPU_PPC_440GRX = xxx,
#endif
CPU_PPC_440GX = 0x51B21850,
CPU_PPC_440GXc = 0x51B21892,
CPU_PPC_440GXf = 0x51B21894,
CPU_PPC_440SP = 0x53221850,
CPU_PPC_440SP2 = 0x53221891,
CPU_PPC_440SPE = 0x53421890,
/* PowerPC 460 cores */
#if 0
CPU_PPC_464H90 = xxx,
#endif
#if 0
CPU_PPC_464H90FP = xxx,
#endif
/* PowerPC MPC 5xx cores */
CPU_PPC_5xx = 0x00020020,
/* PowerPC MPC 8xx cores (aka PowerQUICC) */
CPU_PPC_8xx = 0x00500000,
/* PowerPC MPC 8xxx cores (aka PowerQUICC-II) */
CPU_PPC_82xx_HIP3 = 0x00810101,
CPU_PPC_82xx_HIP4 = 0x80811014,
CPU_PPC_827x = 0x80822013,
/* eCores */
CPU_PPC_e200 = 0x81120000,
CPU_PPC_e500v110 = 0x80200010,
CPU_PPC_e500v120 = 0x80200020,
CPU_PPC_e500v210 = 0x80210010,
CPU_PPC_e500v220 = 0x80210020,
#define CPU_PPC_e500 CPU_PPC_e500v220
CPU_PPC_e600 = 0x80040010,
/* PowerPC 6xx cores */
CPU_PPC_601 = 0x00010001,
CPU_PPC_602 = 0x00050100,
CPU_PPC_603 = 0x00030100,
CPU_PPC_603E = 0x00060101,
CPU_PPC_603P = 0x00070000,
CPU_PPC_603E7v = 0x00070100,
CPU_PPC_603E7v2 = 0x00070201,
CPU_PPC_603E7 = 0x00070200,
CPU_PPC_603R = 0x00071201,
CPU_PPC_G2 = 0x00810011,
CPU_PPC_G2H4 = 0x80811010,
CPU_PPC_G2gp = 0x80821010,
CPU_PPC_G2ls = 0x90810010,
CPU_PPC_G2LE = 0x80820010,
CPU_PPC_G2LEgp = 0x80822010,
CPU_PPC_G2LEls = 0xA0822010,
CPU_PPC_604 = 0x00040000,
CPU_PPC_604E = 0x00090100, /* Also 2110 & 2120 */
CPU_PPC_604R = 0x000a0101,
/* PowerPC 74x/75x cores (aka G3) */
CPU_PPC_74x = 0x00080000,
CPU_PPC_740E = 0x00080100,
CPU_PPC_74xP = 0x10080000,
CPU_PPC_750E = 0x00080200,
CPU_PPC_750CXE21 = 0x00082201,
CPU_PPC_750CXE22 = 0x00082212,
CPU_PPC_750CXE23 = 0x00082203,
CPU_PPC_750CXE24 = 0x00082214,
CPU_PPC_750CXE24b = 0x00083214,
CPU_PPC_750CXE31 = 0x00083211,
CPU_PPC_750CXE31b = 0x00083311,
#define CPU_PPC_750CXE CPU_PPC_750CXE31b
CPU_PPC_750CXR = 0x00083410,
CPU_PPC_750FX10 = 0x70000100,
CPU_PPC_750FX20 = 0x70000200,
CPU_PPC_750FX21 = 0x70000201,
CPU_PPC_750FX22 = 0x70000202,
CPU_PPC_750FX23 = 0x70000203,
#define CPU_PPC_750FX CPU_PPC_750FX23
CPU_PPC_750FL = 0x700A0203,
CPU_PPC_750GX10 = 0x70020100,
CPU_PPC_750GX11 = 0x70020101,
CPU_PPC_750GX12 = 0x70020102,
#define CPU_PPC_750GX CPU_PPC_750GX12
CPU_PPC_750GL = 0x70020102,
CPU_PPC_750L30 = 0x00088300,
CPU_PPC_750L32 = 0x00088302,
#define CPU_PPC_750L CPU_PPC_750L32
CPU_PPC_750CL = 0x00087200,
CPU_PPC_755_10 = 0x00083100,
CPU_PPC_755_11 = 0x00083101,
CPU_PPC_755_20 = 0x00083200,
CPU_PPC_755D = 0x00083202,
CPU_PPC_755E = 0x00083203,
#define CPU_PPC_755 CPU_PPC_755E
/* PowerPC 74xx cores (aka G4) */
CPU_PPC_7400 = 0x000C0100,
CPU_PPC_7410C = 0x800C1102,
CPU_PPC_7410D = 0x800C1103,
CPU_PPC_7410E = 0x800C1104,
#define CPU_PPC_7410 CPU_PPC_7410E
CPU_PPC_7441 = 0x80000210,
CPU_PPC_7445 = 0x80010100,
CPU_PPC_7447 = 0x80020100,
CPU_PPC_7447A = 0x80030101,
CPU_PPC_7448 = 0x80040100,
CPU_PPC_7450 = 0x80000200,
CPU_PPC_7450b = 0x80000201,
CPU_PPC_7451 = 0x80000203,
CPU_PPC_7451G = 0x80000210,
CPU_PPC_7455 = 0x80010201,
CPU_PPC_7455F = 0x80010303,
CPU_PPC_7455G = 0x80010304,
CPU_PPC_7457 = 0x80020101,
CPU_PPC_7457C = 0x80020102,
CPU_PPC_7457A = 0x80030000,
/* 64 bits PowerPC */
CPU_PPC_620 = 0x00140000,
CPU_PPC_630 = 0x00400000,
CPU_PPC_631 = 0x00410000,
CPU_PPC_POWER4 = 0x00350000,
CPU_PPC_POWER4P = 0x00380000,
CPU_PPC_POWER5 = 0x003A0000,
CPU_PPC_POWER5P = 0x003B0000,
#if 0
CPU_PPC_POWER6 = xxx,
#endif
CPU_PPC_970 = 0x00390000,
CPU_PPC_970FX10 = 0x00391100,
CPU_PPC_970FX20 = 0x003C0200,
CPU_PPC_970FX21 = 0x003C0201,
CPU_PPC_970FX30 = 0x003C0300,
CPU_PPC_970FX31 = 0x003C0301,
#define CPU_PPC_970FX CPU_PPC_970FX31
CPU_PPC_970MP10 = 0x00440100,
CPU_PPC_970MP11 = 0x00440101,
#define CPU_PPC_970MP CPU_PPC_970MP11
CPU_PPC_CELL10 = 0x00700100,
CPU_PPC_CELL20 = 0x00700400,
CPU_PPC_CELL30 = 0x00700500,
CPU_PPC_CELL31 = 0x00700501,
#define CPU_PPC_CELL32 CPU_PPC_CELL31
#define CPU_PPC_CELL CPU_PPC_CELL32
CPU_PPC_RS64 = 0x00330000,
CPU_PPC_RS64II = 0x00340000,
CPU_PPC_RS64III = 0x00360000,
CPU_PPC_RS64IV = 0x00370000,
/* Original POWER */
/* XXX: should be POWER (RIOS), RSC3308, RSC4608,
* POWER2 (RIOS2) & RSC2 (P2SC) here
*/
#if 0
CPU_POWER = xxx,
#endif
#if 0
CPU_POWER2 = xxx,
#endif
};
/* System version register (used on MPC 8xxx) */
enum {
PPC_SVR_8540 = 0x80300000,
PPC_SVR_8541E = 0x807A0010,
PPC_SVR_8543v10 = 0x80320010,
PPC_SVR_8543v11 = 0x80320011,
PPC_SVR_8543v20 = 0x80320020,
PPC_SVR_8543Ev10 = 0x803A0010,
PPC_SVR_8543Ev11 = 0x803A0011,
PPC_SVR_8543Ev20 = 0x803A0020,
PPC_SVR_8545 = 0x80310220,
PPC_SVR_8545E = 0x80390220,
PPC_SVR_8547E = 0x80390120,
PPC_SCR_8548v10 = 0x80310010,
PPC_SCR_8548v11 = 0x80310011,
PPC_SCR_8548v20 = 0x80310020,
PPC_SVR_8548Ev10 = 0x80390010,
PPC_SVR_8548Ev11 = 0x80390011,
PPC_SVR_8548Ev20 = 0x80390020,
PPC_SVR_8555E = 0x80790010,
PPC_SVR_8560v10 = 0x80700010,
PPC_SVR_8560v20 = 0x80700020,
}; };
/*****************************************************************************/ /*****************************************************************************/
/* Instruction types */ /* Exception model */
enum { enum {
PPC_NONE = 0x00000000, POWERPC_EXCP_UNKNOWN = 0,
/* integer operations instructions */
/* flow control instructions */
/* virtual memory instructions */
/* ld/st with reservation instructions */
/* cache control instructions */
/* spr/msr access instructions */
PPC_INSNS_BASE = 0x0000000000000001ULL,
#define PPC_INTEGER PPC_INSNS_BASE
#define PPC_FLOW PPC_INSNS_BASE
#define PPC_MEM PPC_INSNS_BASE
#define PPC_RES PPC_INSNS_BASE
#define PPC_CACHE PPC_INSNS_BASE
#define PPC_MISC PPC_INSNS_BASE
/* floating point operations instructions */
PPC_FLOAT = 0x0000000000000002ULL,
/* more floating point operations instructions */
PPC_FLOAT_EXT = 0x0000000000000004ULL,
/* external control instructions */
PPC_EXTERN = 0x0000000000000008ULL,
/* segment register access instructions */
PPC_SEGMENT = 0x0000000000000010ULL,
/* Optional cache control instructions */
PPC_CACHE_OPT = 0x0000000000000020ULL,
/* Optional floating point op instructions */
PPC_FLOAT_OPT = 0x0000000000000040ULL,
/* Optional memory control instructions */
PPC_MEM_TLBIA = 0x0000000000000080ULL,
PPC_MEM_TLBIE = 0x0000000000000100ULL,
PPC_MEM_TLBSYNC = 0x0000000000000200ULL,
/* eieio & sync */
PPC_MEM_SYNC = 0x0000000000000400ULL,
/* PowerPC 6xx TLB management instructions */
PPC_6xx_TLB = 0x0000000000000800ULL,
/* Altivec support */
PPC_ALTIVEC = 0x0000000000001000ULL,
/* Time base support */
PPC_TB = 0x0000000000002000ULL,
/* Embedded PowerPC dedicated instructions */
PPC_EMB_COMMON = 0x0000000000004000ULL,
/* PowerPC 40x exception model */
PPC_40x_EXCP = 0x0000000000008000ULL,
/* PowerPC 40x specific instructions */
PPC_40x_SPEC = 0x0000000000010000ULL,
/* PowerPC 405 Mac instructions */
PPC_405_MAC = 0x0000000000020000ULL,
/* PowerPC 440 specific instructions */
PPC_440_SPEC = 0x0000000000040000ULL,
/* Specific extensions */
/* Power-to-PowerPC bridge (601) */
PPC_POWER_BR = 0x0000000000080000ULL,
/* PowerPC 602 specific */
PPC_602_SPEC = 0x0000000000100000ULL,
/* Deprecated instructions */
/* Original POWER instruction set */
PPC_POWER = 0x0000000000200000ULL,
/* POWER2 instruction set extension */
PPC_POWER2 = 0x0000000000400000ULL,
/* Power RTC support */
PPC_POWER_RTC = 0x0000000000800000ULL,
/* 64 bits PowerPC instructions */
/* 64 bits PowerPC instruction set */
PPC_64B = 0x0000000001000000ULL,
/* 64 bits hypervisor extensions */
PPC_64H = 0x0000000002000000ULL,
/* 64 bits PowerPC "bridge" features */
PPC_64_BRIDGE = 0x0000000004000000ULL,
/* BookE (embedded) PowerPC specification */
PPC_BOOKE = 0x0000000008000000ULL,
/* eieio */
PPC_MEM_EIEIO = 0x0000000010000000ULL,
/* e500 vector instructions */
PPC_E500_VECTOR = 0x0000000020000000ULL,
/* PowerPC 4xx dedicated instructions */
PPC_4xx_COMMON = 0x0000000040000000ULL,
/* PowerPC 2.03 specification extensions */
PPC_203 = 0x0000000080000000ULL,
/* PowerPC 2.03 SPE extension */
PPC_SPE = 0x0000000100000000ULL,
/* PowerPC 2.03 SPE floating-point extension */
PPC_SPEFPU = 0x0000000200000000ULL,
/* SLB management */
PPC_SLBI = 0x0000000400000000ULL,
/* PowerPC 40x ibct instructions */
PPC_40x_ICBT = 0x0000000800000000ULL,
};
/* CPU run-time flags (MMU and exception model) */
enum {
/* MMU model */
PPC_FLAGS_MMU_MASK = 0x000000FF,
/* Standard 32 bits PowerPC MMU */
PPC_FLAGS_MMU_32B = 0x00000000,
/* Standard 64 bits PowerPC MMU */
PPC_FLAGS_MMU_64B = 0x00000001,
/* PowerPC 601 MMU */
PPC_FLAGS_MMU_601 = 0x00000002,
/* PowerPC 6xx MMU with software TLB */
PPC_FLAGS_MMU_SOFT_6xx = 0x00000003,
/* PowerPC 4xx MMU with software TLB */
PPC_FLAGS_MMU_SOFT_4xx = 0x00000004,
/* PowerPC 403 MMU */
PPC_FLAGS_MMU_403 = 0x00000005,
/* BookE FSL MMU model */
PPC_FLAGS_MMU_BOOKE_FSL = 0x00000006,
/* BookE MMU model */
PPC_FLAGS_MMU_BOOKE = 0x00000007,
/* 64 bits "bridge" PowerPC MMU */
PPC_FLAGS_MMU_64BRIDGE = 0x00000008,
/* PowerPC 401 MMU (real mode only) */
PPC_FLAGS_MMU_401 = 0x00000009,
/* Exception model */
PPC_FLAGS_EXCP_MASK = 0x0000FF00,
/* Standard PowerPC exception model */ /* Standard PowerPC exception model */
PPC_FLAGS_EXCP_STD = 0x00000000, POWERPC_EXCP_STD,
/* PowerPC 40x exception model */ /* PowerPC 40x exception model */
PPC_FLAGS_EXCP_40x = 0x00000100, POWERPC_EXCP_40x,
/* PowerPC 601 exception model */ /* PowerPC 601 exception model */
PPC_FLAGS_EXCP_601 = 0x00000200, POWERPC_EXCP_601,
/* PowerPC 602 exception model */ /* PowerPC 602 exception model */
PPC_FLAGS_EXCP_602 = 0x00000300, POWERPC_EXCP_602,
/* PowerPC 603 exception model */ /* PowerPC 603 exception model */
PPC_FLAGS_EXCP_603 = 0x00000400, POWERPC_EXCP_603,
/* PowerPC 603e exception model */
POWERPC_EXCP_603E,
/* PowerPC G2 exception model */
POWERPC_EXCP_G2,
/* PowerPC 604 exception model */ /* PowerPC 604 exception model */
PPC_FLAGS_EXCP_604 = 0x00000500, POWERPC_EXCP_604,
/* PowerPC 7x0 exception model */ /* PowerPC 7x0 exception model */
PPC_FLAGS_EXCP_7x0 = 0x00000600, POWERPC_EXCP_7x0,
/* PowerPC 7x5 exception model */ /* PowerPC 7x5 exception model */
PPC_FLAGS_EXCP_7x5 = 0x00000700, POWERPC_EXCP_7x5,
/* PowerPC 74xx exception model */ /* PowerPC 74xx exception model */
PPC_FLAGS_EXCP_74xx = 0x00000800, POWERPC_EXCP_74xx,
/* PowerPC 970 exception model */ /* PowerPC 970 exception model */
PPC_FLAGS_EXCP_970 = 0x00000900, POWERPC_EXCP_970,
/* BookE exception model */ /* BookE exception model */
PPC_FLAGS_EXCP_BOOKE = 0x00000A00, POWERPC_EXCP_BOOKE,
/* Input pins model */
PPC_FLAGS_INPUT_MASK = 0x000F0000,
/* PowerPC 6xx bus */
PPC_FLAGS_INPUT_6xx = 0x00000000,
/* BookE bus */
PPC_FLAGS_INPUT_BookE = 0x00010000,
/* PowerPC 4xx bus */
PPC_FLAGS_INPUT_40x = 0x00020000,
/* PowerPC 970 bus */
PPC_FLAGS_INPUT_970 = 0x00030000,
}; };
#define PPC_MMU(env) (env->flags & PPC_FLAGS_MMU_MASK)
#define PPC_EXCP(env) (env->flags & PPC_FLAGS_EXCP_MASK)
#define PPC_INPUT(env) (env->flags & PPC_FLAGS_INPUT_MASK)
/*****************************************************************************/ /*****************************************************************************/
/* Supported instruction set definitions */ /* Input pins model */
/* This generates an empty opcode table... */ enum {
#define PPC_INSNS_TODO (PPC_NONE) PPC_FLAGS_INPUT_UNKNOWN = 0,
#define PPC_FLAGS_TODO (0x00000000) /* PowerPC 6xx bus */
PPC_FLAGS_INPUT_6xx,
/* BookE bus */
PPC_FLAGS_INPUT_BookE,
/* PowerPC 405 bus */
PPC_FLAGS_INPUT_405,
/* PowerPC 970 bus */
PPC_FLAGS_INPUT_970,
/* PowerPC 401 bus */
PPC_FLAGS_INPUT_401,
};
/* PowerPC 40x instruction set */ #define PPC_INPUT(env) (env->bus_model)
#define PPC_INSNS_EMB (PPC_INSNS_BASE | PPC_EMB_COMMON)
/* PowerPC 401 */
#define PPC_INSNS_401 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
#define PPC_FLAGS_401 (PPC_FLAGS_MMU_401 | PPC_FLAGS_EXCP_40x | \
PPC_FLAGS_INPUT_40x)
/* PowerPC 403 */
#define PPC_INSNS_403 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | \
PPC_40x_EXCP | PPC_40x_SPEC | PPC_40x_ICBT)
#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x | \
PPC_FLAGS_INPUT_40x)
/* PowerPC 405 */
#define PPC_INSNS_405 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_CACHE_OPT | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_TB | PPC_4xx_COMMON | PPC_40x_SPEC | \
PPC_40x_ICBT | PPC_40x_EXCP | PPC_405_MAC)
#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x | \
PPC_FLAGS_INPUT_40x)
/* PowerPC 440 */
#define PPC_INSNS_440 (PPC_INSNS_EMB | PPC_CACHE_OPT | PPC_BOOKE | \
PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE | \
PPC_FLAGS_INPUT_BookE)
/* Generic BookE PowerPC */
#define PPC_INSNS_BOOKE (PPC_INSNS_EMB | PPC_MEM_TLBSYNC | PPC_BOOKE | \
PPC_MEM_EIEIO | PPC_FLOAT | PPC_FLOAT_OPT | \
PPC_CACHE_OPT)
#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE | \
PPC_FLAGS_INPUT_BookE)
/* e500 core */
#define PPC_INSNS_E500 (PPC_INSNS_EMB | PPC_MEM_TLBSYNC | PPC_BOOKE | \
PPC_MEM_EIEIO | PPC_CACHE_OPT | PPC_E500_VECTOR)
#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x | \
PPC_FLAGS_INPUT_BookE)
/* Non-embedded PowerPC */
#define PPC_INSNS_COMMON (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \
PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE)
/* PowerPC 601 */
#define PPC_INSNS_601 (PPC_INSNS_COMMON | PPC_EXTERN | PPC_POWER_BR)
#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 602 */
#define PPC_INSNS_602 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \
PPC_MEM_TLBSYNC | PPC_TB | PPC_602_SPEC)
#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 603 */
#define PPC_INSNS_603 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \
PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC G2 */
#define PPC_INSNS_G2 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB | \
PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 604 */
#define PPC_INSNS_604 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \
PPC_MEM_TLBSYNC | PPC_TB)
#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 740/750 (aka G3) */
#define PPC_INSNS_7x0 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \
PPC_MEM_TLBSYNC | PPC_TB)
#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 745/755 */
#define PPC_INSNS_7x5 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN | \
PPC_MEM_TLBSYNC | PPC_TB | PPC_6xx_TLB)
#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5 | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 74xx (aka G4) */
#define PPC_INSNS_74xx (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_ALTIVEC | \
PPC_MEM_TLBSYNC | PPC_TB)
#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx | \
PPC_FLAGS_INPUT_6xx)
/* PowerPC 970 (aka G5) */
#define PPC_INSNS_970 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_FLOAT_OPT | \
PPC_ALTIVEC | PPC_MEM_TLBSYNC | PPC_TB | \
PPC_64B | PPC_64_BRIDGE | PPC_SLBI)
#define PPC_FLAGS_970 (PPC_FLAGS_MMU_64BRIDGE | PPC_FLAGS_EXCP_970 | \
PPC_FLAGS_INPUT_970)
/* Default PowerPC will be 604/970 */
#define PPC_INSNS_PPC32 PPC_INSNS_604
#define PPC_FLAGS_PPC32 PPC_FLAGS_604
#define PPC_INSNS_PPC64 PPC_INSNS_970
#define PPC_FLAGS_PPC64 PPC_FLAGS_970
#define PPC_INSNS_DEFAULT PPC_INSNS_604
#define PPC_FLAGS_DEFAULT PPC_FLAGS_604
typedef struct ppc_def_t ppc_def_t; typedef struct ppc_def_t ppc_def_t;
typedef struct opc_handler_t opc_handler_t;
/*****************************************************************************/ /*****************************************************************************/
/* Types used to describe some PowerPC registers */ /* Types used to describe some PowerPC registers */
typedef struct CPUPPCState CPUPPCState; typedef struct CPUPPCState CPUPPCState;
typedef struct opc_handler_t opc_handler_t;
typedef struct ppc_tb_t ppc_tb_t; typedef struct ppc_tb_t ppc_tb_t;
typedef struct ppc_spr_t ppc_spr_t; typedef struct ppc_spr_t ppc_spr_t;
typedef struct ppc_dcr_t ppc_dcr_t; typedef struct ppc_dcr_t ppc_dcr_t;
@ -832,7 +393,11 @@ struct CPUPPCState {
/* Those resources are used during exception processing */ /* Those resources are used during exception processing */
/* CPU model definition */ /* CPU model definition */
uint64_t msr_mask; target_ulong msr_mask;
uint8_t mmu_model;
uint8_t excp_model;
uint8_t bus_model;
uint8_t pad;
uint32_t flags; uint32_t flags;
int exception_index; int exception_index;
@ -985,7 +550,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_LR (0x008) #define SPR_LR (0x008)
#define SPR_CTR (0x009) #define SPR_CTR (0x009)
#define SPR_DSISR (0x012) #define SPR_DSISR (0x012)
#define SPR_DAR (0x013) #define SPR_DAR (0x013) /* DAE for PowerPC 601 */
#define SPR_601_RTCU (0x014) #define SPR_601_RTCU (0x014)
#define SPR_601_RTCL (0x015) #define SPR_601_RTCL (0x015)
#define SPR_DECR (0x016) #define SPR_DECR (0x016)
@ -1203,6 +768,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_440_ITV1 (0x375) #define SPR_440_ITV1 (0x375)
#define SPR_440_ITV2 (0x376) #define SPR_440_ITV2 (0x376)
#define SPR_440_ITV3 (0x377) #define SPR_440_ITV3 (0x377)
#define SPR_440_CCR1 (0x378)
#define SPR_DCRIPR (0x37B)
#define SPR_PPR (0x380) #define SPR_PPR (0x380)
#define SPR_440_DNV0 (0x390) #define SPR_440_DNV0 (0x390)
#define SPR_440_DNV1 (0x391) #define SPR_440_DNV1 (0x391)
@ -1219,38 +786,63 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_BOOKE_DCDBTRH (0x39D) #define SPR_BOOKE_DCDBTRH (0x39D)
#define SPR_BOOKE_ICDBTRL (0x39E) #define SPR_BOOKE_ICDBTRL (0x39E)
#define SPR_BOOKE_ICDBTRH (0x39F) #define SPR_BOOKE_ICDBTRH (0x39F)
#define SPR_UMMCR2 (0x3A0)
#define SPR_UPMC5 (0x3A1)
#define SPR_UPMC6 (0x3A2)
#define SPR_UBAMR (0x3A7)
#define SPR_UMMCR0 (0x3A8) #define SPR_UMMCR0 (0x3A8)
#define SPR_UPMC1 (0x3A9) #define SPR_UPMC1 (0x3A9)
#define SPR_UPMC2 (0x3AA) #define SPR_UPMC2 (0x3AA)
#define SPR_USIA (0x3AB) #define SPR_USIAR (0x3AB)
#define SPR_UMMCR1 (0x3AC) #define SPR_UMMCR1 (0x3AC)
#define SPR_UPMC3 (0x3AD) #define SPR_UPMC3 (0x3AD)
#define SPR_UPMC4 (0x3AE) #define SPR_UPMC4 (0x3AE)
#define SPR_USDA (0x3AF) #define SPR_USDA (0x3AF)
#define SPR_40x_ZPR (0x3B0) #define SPR_40x_ZPR (0x3B0)
#define SPR_BOOKE_MAS7 (0x3B0) #define SPR_BOOKE_MAS7 (0x3B0)
#define SPR_620_PMR0 (0x3B0)
#define SPR_MMCR2 (0x3B0)
#define SPR_PMC5 (0x3B1)
#define SPR_40x_PID (0x3B1) #define SPR_40x_PID (0x3B1)
#define SPR_620_PMR1 (0x3B1)
#define SPR_PMC6 (0x3B2)
#define SPR_440_MMUCR (0x3B2) #define SPR_440_MMUCR (0x3B2)
#define SPR_620_PMR2 (0x3B2)
#define SPR_4xx_CCR0 (0x3B3) #define SPR_4xx_CCR0 (0x3B3)
#define SPR_BOOKE_EPLC (0x3B3) #define SPR_BOOKE_EPLC (0x3B3)
#define SPR_620_PMR3 (0x3B3)
#define SPR_405_IAC3 (0x3B4) #define SPR_405_IAC3 (0x3B4)
#define SPR_BOOKE_EPSC (0x3B4) #define SPR_BOOKE_EPSC (0x3B4)
#define SPR_620_PMR4 (0x3B4)
#define SPR_405_IAC4 (0x3B5) #define SPR_405_IAC4 (0x3B5)
#define SPR_620_PMR5 (0x3B5)
#define SPR_405_DVC1 (0x3B6) #define SPR_405_DVC1 (0x3B6)
#define SPR_620_PMR6 (0x3B6)
#define SPR_405_DVC2 (0x3B7) #define SPR_405_DVC2 (0x3B7)
#define SPR_620_PMR7 (0x3B7)
#define SPR_BAMR (0x3B7)
#define SPR_MMCR0 (0x3B8) #define SPR_MMCR0 (0x3B8)
#define SPR_620_PMR8 (0x3B8)
#define SPR_PMC1 (0x3B9) #define SPR_PMC1 (0x3B9)
#define SPR_40x_SGR (0x3B9) #define SPR_40x_SGR (0x3B9)
#define SPR_620_PMR9 (0x3B9)
#define SPR_PMC2 (0x3BA) #define SPR_PMC2 (0x3BA)
#define SPR_40x_DCWR (0x3BA) #define SPR_40x_DCWR (0x3BA)
#define SPR_SIA (0x3BB) #define SPR_620_PMRA (0x3BA)
#define SPR_SIAR (0x3BB)
#define SPR_405_SLER (0x3BB) #define SPR_405_SLER (0x3BB)
#define SPR_620_PMRB (0x3BB)
#define SPR_MMCR1 (0x3BC) #define SPR_MMCR1 (0x3BC)
#define SPR_405_SU0R (0x3BC) #define SPR_405_SU0R (0x3BC)
#define SPR_620_PMRC (0x3BC)
#define SPR_401_SKR (0x3BC)
#define SPR_PMC3 (0x3BD) #define SPR_PMC3 (0x3BD)
#define SPR_405_DBCR1 (0x3BD) #define SPR_405_DBCR1 (0x3BD)
#define SPR_620_PMRD (0x3BD)
#define SPR_PMC4 (0x3BE) #define SPR_PMC4 (0x3BE)
#define SPR_620_PMRE (0x3BE)
#define SPR_SDA (0x3BF) #define SPR_SDA (0x3BF)
#define SPR_620_PMRF (0x3BF)
#define SPR_403_VTBL (0x3CC) #define SPR_403_VTBL (0x3CC)
#define SPR_403_VTBU (0x3CD) #define SPR_403_VTBU (0x3CD)
#define SPR_DMISS (0x3D0) #define SPR_DMISS (0x3D0)
@ -1258,18 +850,23 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_HASH1 (0x3D2) #define SPR_HASH1 (0x3D2)
#define SPR_HASH2 (0x3D3) #define SPR_HASH2 (0x3D3)
#define SPR_BOOKE_ICDBDR (0x3D3) #define SPR_BOOKE_ICDBDR (0x3D3)
#define SPR_TLBMISS (0x3D4)
#define SPR_IMISS (0x3D4) #define SPR_IMISS (0x3D4)
#define SPR_40x_ESR (0x3D4) #define SPR_40x_ESR (0x3D4)
#define SPR_PTEHI (0x3D5)
#define SPR_ICMP (0x3D5) #define SPR_ICMP (0x3D5)
#define SPR_40x_DEAR (0x3D5) #define SPR_40x_DEAR (0x3D5)
#define SPR_PTELO (0x3D6)
#define SPR_RPA (0x3D6) #define SPR_RPA (0x3D6)
#define SPR_40x_EVPR (0x3D6) #define SPR_40x_EVPR (0x3D6)
#define SPR_L3PM (0x3D7)
#define SPR_403_CDBCR (0x3D7) #define SPR_403_CDBCR (0x3D7)
#define SPR_L3OHCR (0x3D8)
#define SPR_TCR (0x3D8) #define SPR_TCR (0x3D8)
#define SPR_40x_TSR (0x3D8) #define SPR_40x_TSR (0x3D8)
#define SPR_IBR (0x3DA) #define SPR_IBR (0x3DA)
#define SPR_40x_TCR (0x3DA) #define SPR_40x_TCR (0x3DA)
#define SPR_ESASR (0x3DB) #define SPR_ESASRR (0x3DB)
#define SPR_40x_PIT (0x3DB) #define SPR_40x_PIT (0x3DB)
#define SPR_403_TBL (0x3DC) #define SPR_403_TBL (0x3DC)
#define SPR_403_TBU (0x3DD) #define SPR_403_TBU (0x3DD)
@ -1277,6 +874,10 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_40x_SRR2 (0x3DE) #define SPR_40x_SRR2 (0x3DE)
#define SPR_SER (0x3DF) #define SPR_SER (0x3DF)
#define SPR_40x_SRR3 (0x3DF) #define SPR_40x_SRR3 (0x3DF)
#define SPR_L3ITCR0 (0x3E8)
#define SPR_L3ITCR1 (0x3E9)
#define SPR_L3ITCR2 (0x3EA)
#define SPR_L3ITCR3 (0x3EB)
#define SPR_HID0 (0x3F0) #define SPR_HID0 (0x3F0)
#define SPR_40x_DBSR (0x3F0) #define SPR_40x_DBSR (0x3F0)
#define SPR_HID1 (0x3F1) #define SPR_HID1 (0x3F1)
@ -1284,9 +885,11 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_40x_DBCR0 (0x3F2) #define SPR_40x_DBCR0 (0x3F2)
#define SPR_601_HID2 (0x3F2) #define SPR_601_HID2 (0x3F2)
#define SPR_E500_L1CSR0 (0x3F2) #define SPR_E500_L1CSR0 (0x3F2)
#define SPR_ICTRL (0x3F3)
#define SPR_HID2 (0x3F3) #define SPR_HID2 (0x3F3)
#define SPR_E500_L1CSR1 (0x3F3) #define SPR_E500_L1CSR1 (0x3F3)
#define SPR_440_DBDR (0x3F3) #define SPR_440_DBDR (0x3F3)
#define SPR_LDSTDB (0x3F4)
#define SPR_40x_IAC1 (0x3F4) #define SPR_40x_IAC1 (0x3F4)
#define SPR_BOOKE_MMUCSR0 (0x3F4) #define SPR_BOOKE_MMUCSR0 (0x3F4)
#define SPR_DABR (0x3F5) #define SPR_DABR (0x3F5)
@ -1295,12 +898,18 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_40x_IAC2 (0x3F5) #define SPR_40x_IAC2 (0x3F5)
#define SPR_601_HID5 (0x3F5) #define SPR_601_HID5 (0x3F5)
#define SPR_40x_DAC1 (0x3F6) #define SPR_40x_DAC1 (0x3F6)
#define SPR_MSSCR0 (0x3F6)
#define SPR_MSSSR0 (0x3F7)
#define SPR_DABRX (0x3F7) #define SPR_DABRX (0x3F7)
#define SPR_40x_DAC2 (0x3F7) #define SPR_40x_DAC2 (0x3F7)
#define SPR_BOOKE_MMUCFG (0x3F7) #define SPR_BOOKE_MMUCFG (0x3F7)
#define SPR_L2PM (0x3F8) #define SPR_LDSTCR (0x3F8)
#define SPR_L2PMCR (0x3F8)
#define SPR_750_HID2 (0x3F8) #define SPR_750_HID2 (0x3F8)
#define SPR_620_HID8 (0x3F8)
#define SPR_L2CR (0x3F9) #define SPR_L2CR (0x3F9)
#define SPR_620_HID9 (0x3F9)
#define SPR_L3CR (0x3FA)
#define SPR_IABR2 (0x3FA) #define SPR_IABR2 (0x3FA)
#define SPR_40x_DCCR (0x3FA) #define SPR_40x_DCCR (0x3FA)
#define SPR_ICTC (0x3FB) #define SPR_ICTC (0x3FB)
@ -1310,6 +919,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_SP (0x3FD) #define SPR_SP (0x3FD)
#define SPR_THRM2 (0x3FD) #define SPR_THRM2 (0x3FD)
#define SPR_403_PBU1 (0x3FD) #define SPR_403_PBU1 (0x3FD)
#define SPR_604_HID13 (0x3FD)
#define SPR_LT (0x3FE) #define SPR_LT (0x3FE)
#define SPR_THRM3 (0x3FE) #define SPR_THRM3 (0x3FE)
#define SPR_FPECR (0x3FE) #define SPR_FPECR (0x3FE)
@ -1317,6 +927,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#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_601_HID15 (0x3FF)
#define SPR_604_HID15 (0x3FF)
#define SPR_E500_SVR (0x3FF) #define SPR_E500_SVR (0x3FF)
/*****************************************************************************/ /*****************************************************************************/
@ -1367,6 +978,11 @@ enum {
#define EXCP_40x_DEBUG 0x2000 /* Debug exception */ #define EXCP_40x_DEBUG 0x2000 /* Debug exception */
/* 405 specific exceptions */ /* 405 specific exceptions */
#define EXCP_405_APU 0x0F20 /* APU unavailable exception */ #define EXCP_405_APU 0x0F20 /* APU unavailable exception */
/* 440 specific exceptions */
#define EXCP_440_CRIT 0x0100 /* Critical interrupt */
#define EXCP_440_SPEU 0x1600 /* SPE unavailable exception */
#define EXCP_440_SPED 0x1700 /* SPE floating-point data exception */
#define EXCP_440_SPER 0x1800 /* SPE floating-point round exception */
/* TLB assist exceptions (602/603) */ /* TLB assist exceptions (602/603) */
#define EXCP_I_TLBMISS 0x1000 /* Instruction TLB miss */ #define EXCP_I_TLBMISS 0x1000 /* Instruction TLB miss */
#define EXCP_DL_TLBMISS 0x1100 /* Data load TLB miss */ #define EXCP_DL_TLBMISS 0x1100 /* Data load TLB miss */
@ -1377,7 +993,7 @@ enum {
/* Altivec related exceptions */ /* Altivec related exceptions */
#define EXCP_VPU 0x0F20 /* VPU unavailable exception */ #define EXCP_VPU 0x0F20 /* VPU unavailable exception */
/* 601 specific exceptions */ /* 601 specific exceptions */
#define EXCP_601_IO 0x0600 /* IO error exception */ #define EXCP_601_IO 0x0A00 /* IO error exception */
#define EXCP_601_RUNM 0x2000 /* Run mode exception */ #define EXCP_601_RUNM 0x2000 /* Run mode exception */
/* 602 specific exceptions */ /* 602 specific exceptions */
#define EXCP_602_WATCHDOG 0x1500 /* Watchdog exception */ #define EXCP_602_WATCHDOG 0x1500 /* Watchdog exception */
@ -1467,6 +1083,15 @@ enum {
PPCBookE_INPUT_CINT = 6, PPCBookE_INPUT_CINT = 6,
}; };
enum {
/* PowerPC 401/403 input pins */
PPC401_INPUT_RESET = 0,
PPC401_INPUT_CINT = 1,
PPC401_INPUT_INT = 2,
PPC401_INPUT_BERR = 3,
PPC401_INPUT_HALT = 4,
};
enum { enum {
/* PowerPC 405 input pins */ /* PowerPC 405 input pins */
PPC405_INPUT_RESET_CORE = 0, PPC405_INPUT_RESET_CORE = 0,
@ -1478,6 +1103,18 @@ enum {
PPC405_INPUT_DEBUG = 6, PPC405_INPUT_DEBUG = 6,
}; };
enum {
/* PowerPC 620 (and probably others) input pins */
PPC620_INPUT_HRESET = 0,
PPC620_INPUT_SRESET = 1,
PPC620_INPUT_CKSTP = 2,
PPC620_INPUT_TBEN = 3,
PPC620_INPUT_WAKEUP = 4,
PPC620_INPUT_MCP = 5,
PPC620_INPUT_SMI = 6,
PPC620_INPUT_INT = 7,
};
enum { enum {
/* PowerPC 970 input pins */ /* PowerPC 970 input pins */
PPC970_INPUT_HRESET = 0, PPC970_INPUT_HRESET = 0,

View File

@ -106,6 +106,8 @@ void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code, void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
target_ulong pte0, target_ulong pte1); target_ulong pte0, target_ulong pte1);
void ppc4xx_tlb_invalidate_all (CPUState *env); void ppc4xx_tlb_invalidate_all (CPUState *env);
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
uint32_t pid);
static inline void env_to_regs (void) static inline void env_to_regs (void)
{ {

View File

@ -586,8 +586,8 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw)
static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw)
{ {
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if (PPC_MMU(env) == PPC_FLAGS_MMU_64B || if (env->mmu_model == POWERPC_MMU_64B ||
PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE) env->mmu_model == POWERPC_MMU_64BRIDGE)
return find_pte64(ctx, h, rw); return find_pte64(ctx, h, rw);
#endif #endif
@ -669,7 +669,7 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
int ret, ret2; int ret, ret2;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if (PPC_MMU(env) == PPC_FLAGS_MMU_64B) { if (env->mmu_model == POWERPC_MMU_64B) {
ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -724,8 +724,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
hash = (~hash) & vsid_mask; hash = (~hash) & vsid_mask;
ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if (PPC_MMU(env) == PPC_FLAGS_MMU_64B || if (env->mmu_model == POWERPC_MMU_64B ||
PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE) { env->mmu_model == POWERPC_MMU_64BRIDGE) {
/* Only 5 bits of the page index are used in the AVPN */ /* Only 5 bits of the page index are used in the AVPN */
ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
} else } else
@ -735,7 +735,7 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
} }
/* Initialize real address with an invalid value */ /* Initialize real address with an invalid value */
ctx->raddr = (target_ulong)-1; ctx->raddr = (target_ulong)-1;
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
/* Software TLB search */ /* Software TLB search */
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
} else { } else {
@ -865,7 +865,7 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
/* Default return value is no match */ /* Default return value is no match */
ret = -1; ret = -1;
for (i = 0; i < 64; i++) { for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb[i].tlbe; tlb = &env->tlb[i].tlbe;
if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) { if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
ret = i; ret = i;
@ -876,6 +876,26 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
return ret; return ret;
} }
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
uint32_t pid)
{
ppcemb_tlb_t *tlb;
target_phys_addr_t raddr;
target_ulong page, end;
int i;
for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb[i].tlbe;
if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
end = tlb->EPN + tlb->size;
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
tlb_flush_page(env, page);
tlb->prot &= ~PAGE_VALID;
break;
}
}
}
/* Helpers specific to PowerPC 40x implementations */ /* Helpers specific to PowerPC 40x implementations */
void ppc4xx_tlb_invalidate_all (CPUState *env) void ppc4xx_tlb_invalidate_all (CPUState *env)
{ {
@ -1069,23 +1089,23 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
ctx->raddr = eaddr; ctx->raddr = eaddr;
ctx->prot = PAGE_READ; ctx->prot = PAGE_READ;
ret = 0; ret = 0;
switch (PPC_MMU(env)) { switch (env->mmu_model) {
case PPC_FLAGS_MMU_32B: case POWERPC_MMU_32B:
case PPC_FLAGS_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
case PPC_FLAGS_MMU_601: case POWERPC_MMU_601:
case PPC_FLAGS_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx:
case PPC_FLAGS_MMU_401: case POWERPC_MMU_REAL_4xx:
ctx->prot |= PAGE_WRITE; ctx->prot |= PAGE_WRITE;
break; break;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case PPC_FLAGS_MMU_64B: case POWERPC_MMU_64B:
case PPC_FLAGS_MMU_64BRIDGE: case POWERPC_MMU_64BRIDGE:
/* Real address are 60 bits long */ /* Real address are 60 bits long */
ctx->raddr &= 0x0FFFFFFFFFFFFFFFUL; ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
ctx->prot |= PAGE_WRITE; ctx->prot |= PAGE_WRITE;
break; break;
#endif #endif
case PPC_FLAGS_MMU_403: case POWERPC_MMU_SOFT_4xx_Z:
if (unlikely(msr_pe != 0)) { if (unlikely(msr_pe != 0)) {
/* 403 family add some particular protections, /* 403 family add some particular protections,
* using PBL/PBU registers for accesses with no translation. * using PBL/PBU registers for accesses with no translation.
@ -1108,10 +1128,10 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
ctx->prot |= PAGE_WRITE; ctx->prot |= PAGE_WRITE;
} }
} }
case PPC_FLAGS_MMU_BOOKE: case POWERPC_MMU_BOOKE:
ctx->prot |= PAGE_WRITE; ctx->prot |= PAGE_WRITE;
break; break;
case PPC_FLAGS_MMU_BOOKE_FSL: case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model not implemented\n"); cpu_abort(env, "BookE FSL MMU model not implemented\n");
break; break;
@ -1138,40 +1158,40 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
ret = check_physical(env, ctx, eaddr, rw); ret = check_physical(env, ctx, eaddr, rw);
} else { } else {
ret = -1; ret = -1;
switch (PPC_MMU(env)) { switch (env->mmu_model) {
case PPC_FLAGS_MMU_32B: case POWERPC_MMU_32B:
case PPC_FLAGS_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
/* Try to find a BAT */ /* Try to find a BAT */
if (check_BATs) if (check_BATs)
ret = get_bat(env, ctx, eaddr, rw, access_type); ret = get_bat(env, ctx, eaddr, rw, access_type);
/* No break here */ /* No break here */
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case PPC_FLAGS_MMU_64B: case POWERPC_MMU_64B:
case PPC_FLAGS_MMU_64BRIDGE: case POWERPC_MMU_64BRIDGE:
#endif #endif
if (ret < 0) { if (ret < 0) {
/* We didn't match any BAT entry or don't have BATs */ /* We didn't match any BAT entry or don't have BATs */
ret = get_segment(env, ctx, eaddr, rw, access_type); ret = get_segment(env, ctx, eaddr, rw, access_type);
} }
break; break;
case PPC_FLAGS_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx:
case PPC_FLAGS_MMU_403: case POWERPC_MMU_SOFT_4xx_Z:
ret = mmu40x_get_physical_address(env, ctx, eaddr, ret = mmu40x_get_physical_address(env, ctx, eaddr,
rw, access_type); rw, access_type);
break; break;
case PPC_FLAGS_MMU_601: case POWERPC_MMU_601:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "601 MMU model not implemented\n"); cpu_abort(env, "601 MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_BOOKE: case POWERPC_MMU_BOOKE:
ret = mmubooke_get_physical_address(env, ctx, eaddr, ret = mmubooke_get_physical_address(env, ctx, eaddr,
rw, access_type); rw, access_type);
break; break;
case PPC_FLAGS_MMU_BOOKE_FSL: case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model not implemented\n"); cpu_abort(env, "BookE FSL MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_401: case POWERPC_MMU_REAL_4xx:
cpu_abort(env, "PowerPC 401 does not do any translation\n"); cpu_abort(env, "PowerPC 401 does not do any translation\n");
return -1; return -1;
default: default:
@ -1234,46 +1254,46 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
switch (ret) { switch (ret) {
case -1: case -1:
/* No matches in page tables or TLB */ /* No matches in page tables or TLB */
switch (PPC_MMU(env)) { switch (env->mmu_model) {
case PPC_FLAGS_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
exception = EXCP_I_TLBMISS; exception = EXCP_I_TLBMISS;
env->spr[SPR_IMISS] = address; env->spr[SPR_IMISS] = address;
env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
error_code = 1 << 18; error_code = 1 << 18;
goto tlb_miss; goto tlb_miss;
case PPC_FLAGS_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx:
case PPC_FLAGS_MMU_403: case POWERPC_MMU_SOFT_4xx_Z:
exception = EXCP_40x_ITLBMISS; exception = EXCP_40x_ITLBMISS;
error_code = 0; error_code = 0;
env->spr[SPR_40x_DEAR] = address; env->spr[SPR_40x_DEAR] = address;
env->spr[SPR_40x_ESR] = 0x00000000; env->spr[SPR_40x_ESR] = 0x00000000;
break; break;
case PPC_FLAGS_MMU_32B: case POWERPC_MMU_32B:
error_code = 0x40000000; error_code = 0x40000000;
break; break;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case PPC_FLAGS_MMU_64B: case POWERPC_MMU_64B:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_64BRIDGE: case POWERPC_MMU_64BRIDGE:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
#endif #endif
case PPC_FLAGS_MMU_601: case POWERPC_MMU_601:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_BOOKE: case POWERPC_MMU_BOOKE:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_BOOKE_FSL: case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_401: case POWERPC_MMU_REAL_4xx:
cpu_abort(env, "PowerPC 401 should never raise any MMU " cpu_abort(env, "PowerPC 401 should never raise any MMU "
"exceptions\n"); "exceptions\n");
return -1; return -1;
@ -1306,8 +1326,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
switch (ret) { switch (ret) {
case -1: case -1:
/* No matches in page tables or TLB */ /* No matches in page tables or TLB */
switch (PPC_MMU(env)) { switch (env->mmu_model) {
case PPC_FLAGS_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
if (rw == 1) { if (rw == 1) {
exception = EXCP_DS_TLBMISS; exception = EXCP_DS_TLBMISS;
error_code = 1 << 16; error_code = 1 << 16;
@ -1323,8 +1343,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->spr[SPR_HASH2] = ctx.pg_addr[1]; env->spr[SPR_HASH2] = ctx.pg_addr[1];
/* Do not alter DAR nor DSISR */ /* Do not alter DAR nor DSISR */
goto out; goto out;
case PPC_FLAGS_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx:
case PPC_FLAGS_MMU_403: case POWERPC_MMU_SOFT_4xx_Z:
exception = EXCP_40x_DTLBMISS; exception = EXCP_40x_DTLBMISS;
error_code = 0; error_code = 0;
env->spr[SPR_40x_DEAR] = address; env->spr[SPR_40x_DEAR] = address;
@ -1333,32 +1353,32 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
else else
env->spr[SPR_40x_ESR] = 0x00000000; env->spr[SPR_40x_ESR] = 0x00000000;
break; break;
case PPC_FLAGS_MMU_32B: case POWERPC_MMU_32B:
error_code = 0x40000000; error_code = 0x40000000;
break; break;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case PPC_FLAGS_MMU_64B: case POWERPC_MMU_64B:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_64BRIDGE: case POWERPC_MMU_64BRIDGE:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
#endif #endif
case PPC_FLAGS_MMU_601: case POWERPC_MMU_601:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_BOOKE: case POWERPC_MMU_BOOKE:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_BOOKE_FSL: case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "MMU model not implemented\n"); cpu_abort(env, "MMU model not implemented\n");
return -1; return -1;
case PPC_FLAGS_MMU_401: case POWERPC_MMU_REAL_4xx:
cpu_abort(env, "PowerPC 401 should never raise any MMU " cpu_abort(env, "PowerPC 401 should never raise any MMU "
"exceptions\n"); "exceptions\n");
return -1; return -1;
@ -1544,9 +1564,9 @@ void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
/* TLB management */ /* TLB management */
void ppc_tlb_invalidate_all (CPUPPCState *env) void ppc_tlb_invalidate_all (CPUPPCState *env)
{ {
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
ppc6xx_tlb_invalidate_all(env); ppc6xx_tlb_invalidate_all(env);
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
ppc4xx_tlb_invalidate_all(env); ppc4xx_tlb_invalidate_all(env);
} else { } else {
tlb_flush(env, 1); tlb_flush(env, 1);
@ -1707,9 +1727,11 @@ void do_store_msr (CPUPPCState *env, target_ulong value)
fprintf(logfile, "%s: T0 %08lx\n", __func__, value); fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
} }
#endif #endif
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case POWERPC_EXCP_603E:
case POWERPC_EXCP_G2:
if (((value >> MSR_TGPR) & 1) != msr_tgpr) { if (((value >> MSR_TGPR) & 1) != msr_tgpr) {
/* Swap temporary saved registers with GPRs */ /* Swap temporary saved registers with GPRs */
swap_gpr_tgpr(env); swap_gpr_tgpr(env);
@ -1750,19 +1772,21 @@ void do_store_msr (CPUPPCState *env, target_ulong value)
do_compute_hflags(env); do_compute_hflags(env);
enter_pm = 0; enter_pm = 0;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case POWERPC_EXCP_603E:
case POWERPC_EXCP_G2:
/* Don't handle SLEEP mode: we should disable all clocks... /* Don't handle SLEEP mode: we should disable all clocks...
* No dynamic power-management. * No dynamic power-management.
*/ */
if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0) if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0)
enter_pm = 1; enter_pm = 1;
break; break;
case PPC_FLAGS_EXCP_604: case POWERPC_EXCP_604:
if (msr_pow == 1) if (msr_pow == 1)
enter_pm = 1; enter_pm = 1;
break; break;
case PPC_FLAGS_EXCP_7x0: case POWERPC_EXCP_7x0:
if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0) if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
enter_pm = 1; enter_pm = 1;
break; break;
@ -1854,12 +1878,12 @@ void do_interrupt (CPUState *env)
switch (excp) { switch (excp) {
/* Generic PowerPC exceptions */ /* Generic PowerPC exceptions */
case EXCP_RESET: /* 0x0100 */ case EXCP_RESET: /* 0x0100 */
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
srr_0 = &env->spr[SPR_40x_SRR2]; srr_0 = &env->spr[SPR_40x_SRR2];
srr_1 = &env->spr[SPR_40x_SRR3]; srr_1 = &env->spr[SPR_40x_SRR3];
break; break;
case PPC_FLAGS_EXCP_BOOKE: case POWERPC_EXCP_BOOKE:
idx = 0; idx = 0;
srr_0 = &env->spr[SPR_BOOKE_CSRR0]; srr_0 = &env->spr[SPR_BOOKE_CSRR0];
srr_1 = &env->spr[SPR_BOOKE_CSRR1]; srr_1 = &env->spr[SPR_BOOKE_CSRR1];
@ -1872,12 +1896,12 @@ void do_interrupt (CPUState *env)
} }
goto store_next; goto store_next;
case EXCP_MACHINE_CHECK: /* 0x0200 */ case EXCP_MACHINE_CHECK: /* 0x0200 */
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
srr_0 = &env->spr[SPR_40x_SRR2]; srr_0 = &env->spr[SPR_40x_SRR2];
srr_1 = &env->spr[SPR_40x_SRR3]; srr_1 = &env->spr[SPR_40x_SRR3];
break; break;
case PPC_FLAGS_EXCP_BOOKE: case POWERPC_EXCP_BOOKE:
idx = 1; idx = 1;
srr_0 = &env->spr[SPR_BOOKE_MCSRR0]; srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
srr_1 = &env->spr[SPR_BOOKE_MCSRR1]; srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
@ -1920,7 +1944,7 @@ void do_interrupt (CPUState *env)
idx = 4; idx = 4;
goto store_next; goto store_next;
case EXCP_ALIGN: /* 0x0600 */ case EXCP_ALIGN: /* 0x0600 */
if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) { if (likely(env->excp_model != POWERPC_EXCP_601)) {
/* Store exception cause */ /* Store exception cause */
idx = 5; idx = 5;
/* Get rS/rD and rA from faulting opcode */ /* Get rS/rD and rA from faulting opcode */
@ -2028,26 +2052,27 @@ void do_interrupt (CPUState *env)
goto store_next; goto store_next;
/* Implementation specific exceptions */ /* Implementation specific exceptions */
case 0x0A00: case 0x0A00:
if (likely(env->spr[SPR_PVR] == CPU_PPC_G2 || switch (env->excp_model) {
env->spr[SPR_PVR] == CPU_PPC_G2LE)) { case POWERPC_EXCP_G2:
/* Critical interrupt on G2 */ /* Critical interrupt on G2 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "G2 critical interrupt is not implemented yet !\n"); cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
goto store_next; goto store_next;
} else { default:
cpu_abort(env, "Invalid exception 0x0A00 !\n"); cpu_abort(env, "Invalid exception 0x0A00 !\n");
break;
} }
return; return;
case 0x0F20: case 0x0F20:
idx = 9; idx = 9;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* APU unavailable on 405 */ /* APU unavailable on 405 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
"APU unavailable exception is not implemented yet !\n"); "APU unavailable exception is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_74xx: case POWERPC_EXCP_74xx:
/* Altivec unavailable */ /* Altivec unavailable */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "Altivec unavailable exception " cpu_abort(env, "Altivec unavailable exception "
@ -2060,8 +2085,8 @@ void do_interrupt (CPUState *env)
return; return;
case 0x1000: case 0x1000:
idx = 10; idx = 10;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* PIT on 4xx */ /* PIT on 4xx */
msr &= ~0xFFFF0000; msr &= ~0xFFFF0000;
#if defined (DEBUG_EXCEPTIONS) #if defined (DEBUG_EXCEPTIONS)
@ -2069,11 +2094,13 @@ void do_interrupt (CPUState *env)
fprintf(logfile, "PIT exception\n"); fprintf(logfile, "PIT exception\n");
#endif #endif
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case POWERPC_EXCP_603E:
case POWERPC_EXCP_G2:
/* ITLBMISS on 602/603 */ /* ITLBMISS on 602/603 */
goto store_gprs; goto store_gprs;
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_7x5:
/* ITLBMISS on 745/755 */ /* ITLBMISS on 745/755 */
goto tlb_miss; goto tlb_miss;
default: default:
@ -2083,8 +2110,8 @@ void do_interrupt (CPUState *env)
return; return;
case 0x1010: case 0x1010:
idx = 11; idx = 11;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* FIT on 4xx */ /* FIT on 4xx */
msr &= ~0xFFFF0000; msr &= ~0xFFFF0000;
#if defined (DEBUG_EXCEPTIONS) #if defined (DEBUG_EXCEPTIONS)
@ -2099,8 +2126,8 @@ void do_interrupt (CPUState *env)
return; return;
case 0x1020: case 0x1020:
idx = 12; idx = 12;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* Watchdog on 4xx */ /* Watchdog on 4xx */
msr &= ~0xFFFF0000; msr &= ~0xFFFF0000;
#if defined (DEBUG_EXCEPTIONS) #if defined (DEBUG_EXCEPTIONS)
@ -2108,7 +2135,7 @@ void do_interrupt (CPUState *env)
fprintf(logfile, "WDT exception\n"); fprintf(logfile, "WDT exception\n");
#endif #endif
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_BOOKE: case POWERPC_EXCP_BOOKE:
srr_0 = &env->spr[SPR_BOOKE_CSRR0]; srr_0 = &env->spr[SPR_BOOKE_CSRR0];
srr_1 = &env->spr[SPR_BOOKE_CSRR1]; srr_1 = &env->spr[SPR_BOOKE_CSRR1];
break; break;
@ -2119,16 +2146,18 @@ void do_interrupt (CPUState *env)
return; return;
case 0x1100: case 0x1100:
idx = 13; idx = 13;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* DTLBMISS on 4xx */ /* DTLBMISS on 4xx */
msr &= ~0xFFFF0000; msr &= ~0xFFFF0000;
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case POWERPC_EXCP_603E:
case POWERPC_EXCP_G2:
/* DLTLBMISS on 602/603 */ /* DLTLBMISS on 602/603 */
goto store_gprs; goto store_gprs;
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_7x5:
/* DLTLBMISS on 745/755 */ /* DLTLBMISS on 745/755 */
goto tlb_miss; goto tlb_miss;
default: default:
@ -2138,13 +2167,15 @@ void do_interrupt (CPUState *env)
return; return;
case 0x1200: case 0x1200:
idx = 14; idx = 14;
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* ITLBMISS on 4xx */ /* ITLBMISS on 4xx */
msr &= ~0xFFFF0000; msr &= ~0xFFFF0000;
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case POWERPC_EXCP_603E:
case POWERPC_EXCP_G2:
/* DSTLBMISS on 602/603 */ /* DSTLBMISS on 602/603 */
store_gprs: store_gprs:
/* Swap temporary saved registers with GPRs */ /* Swap temporary saved registers with GPRs */
@ -2177,7 +2208,7 @@ void do_interrupt (CPUState *env)
} }
#endif #endif
goto tlb_miss; goto tlb_miss;
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_7x5:
/* DSTLBMISS on 745/755 */ /* DSTLBMISS on 745/755 */
tlb_miss: tlb_miss:
msr &= ~0xF83F0000; msr &= ~0xF83F0000;
@ -2192,13 +2223,15 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1300: case 0x1300:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_601: case POWERPC_EXCP_601:
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case PPC_FLAGS_EXCP_604: case POWERPC_EXCP_603E:
case PPC_FLAGS_EXCP_7x0: case POWERPC_EXCP_G2:
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_604:
case POWERPC_EXCP_7x0:
case POWERPC_EXCP_7x5:
/* IABR on 6xx/7xx */ /* IABR on 6xx/7xx */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "IABR exception is not implemented yet !\n"); cpu_abort(env, "IABR exception is not implemented yet !\n");
@ -2209,13 +2242,15 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1400: case 0x1400:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_601: case POWERPC_EXCP_601:
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
case PPC_FLAGS_EXCP_603: case POWERPC_EXCP_603:
case PPC_FLAGS_EXCP_604: case POWERPC_EXCP_603E:
case PPC_FLAGS_EXCP_7x0: case POWERPC_EXCP_G2:
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_604:
case POWERPC_EXCP_7x0:
case POWERPC_EXCP_7x5:
/* SMI on 6xx/7xx */ /* SMI on 6xx/7xx */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "SMI exception is not implemented yet !\n"); cpu_abort(env, "SMI exception is not implemented yet !\n");
@ -2226,20 +2261,20 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1500: case 0x1500:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
/* Watchdog on 602 */ /* Watchdog on 602 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
"602 watchdog exception is not implemented yet !\n"); "602 watchdog exception is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_970: case POWERPC_EXCP_970:
/* Soft patch exception on 970 */ /* Soft patch exception on 970 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
"970 soft-patch exception is not implemented yet !\n"); "970 soft-patch exception is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_74xx: case POWERPC_EXCP_74xx:
/* VPU assist on 74xx */ /* VPU assist on 74xx */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "VPU assist exception is not implemented yet !\n"); cpu_abort(env, "VPU assist exception is not implemented yet !\n");
@ -2250,14 +2285,14 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1600: case 0x1600:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_602: case POWERPC_EXCP_602:
/* Emulation trap on 602 */ /* Emulation trap on 602 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "602 emulation trap exception " cpu_abort(env, "602 emulation trap exception "
"is not implemented yet !\n"); "is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_970: case POWERPC_EXCP_970:
/* Maintenance exception on 970 */ /* Maintenance exception on 970 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
@ -2269,15 +2304,15 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1700: case 0x1700:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_7x0: case POWERPC_EXCP_7x0:
case PPC_FLAGS_EXCP_7x5: case POWERPC_EXCP_7x5:
/* Thermal management interrupt on G3 */ /* Thermal management interrupt on G3 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "G3 thermal management exception " cpu_abort(env, "G3 thermal management exception "
"is not implemented yet !\n"); "is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_970: case POWERPC_EXCP_970:
/* VPU assist on 970 */ /* VPU assist on 970 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
@ -2289,8 +2324,8 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x1800: case 0x1800:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_970: case POWERPC_EXCP_970:
/* Thermal exception on 970 */ /* Thermal exception on 970 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "970 thermal management exception " cpu_abort(env, "970 thermal management exception "
@ -2302,19 +2337,19 @@ void do_interrupt (CPUState *env)
} }
return; return;
case 0x2000: case 0x2000:
switch (PPC_EXCP(env)) { switch (env->excp_model) {
case PPC_FLAGS_EXCP_40x: case POWERPC_EXCP_40x:
/* DEBUG on 4xx */ /* DEBUG on 4xx */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, "40x debug exception is not implemented yet !\n"); cpu_abort(env, "40x debug exception is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_601: case POWERPC_EXCP_601:
/* Run mode exception on 601 */ /* Run mode exception on 601 */
/* XXX: TODO */ /* XXX: TODO */
cpu_abort(env, cpu_abort(env,
"601 run mode exception is not implemented yet !\n"); "601 run mode exception is not implemented yet !\n");
goto store_next; goto store_next;
case PPC_FLAGS_EXCP_BOOKE: case POWERPC_EXCP_BOOKE:
srr_0 = &env->spr[SPR_BOOKE_CSRR0]; srr_0 = &env->spr[SPR_BOOKE_CSRR0];
srr_1 = &env->spr[SPR_BOOKE_CSRR1]; srr_1 = &env->spr[SPR_BOOKE_CSRR1];
break; break;
@ -2361,7 +2396,7 @@ void do_interrupt (CPUState *env)
msr_dr = 0; msr_dr = 0;
msr_ri = 0; msr_ri = 0;
msr_le = msr_ile; msr_le = msr_ile;
if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) { if (env->excp_model == POWERPC_EXCP_BOOKE) {
msr_cm = msr_icm; msr_cm = msr_icm;
if (idx == -1 || (idx >= 16 && idx < 32)) { if (idx == -1 || (idx >= 16 && idx < 32)) {
cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n", cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",

View File

@ -2319,7 +2319,6 @@ void OPPROTO op_405_check_satu (void)
RETURN(); RETURN();
} }
#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_load_dcr (void) void OPPROTO op_load_dcr (void)
{ {
do_load_dcr(); do_load_dcr();
@ -2332,6 +2331,7 @@ void OPPROTO op_store_dcr (void)
RETURN(); RETURN();
} }
#if !defined(CONFIG_USER_ONLY)
/* Return from critical interrupt : /* Return from critical interrupt :
* same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1 * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
*/ */

View File

@ -1206,6 +1206,41 @@ void do_405_check_sat (void)
} }
} }
/* XXX: to be improved to check access rights when in user-mode */
void do_load_dcr (void)
{
target_ulong val;
if (unlikely(env->dcr_env == NULL)) {
if (loglevel != 0) {
fprintf(logfile, "No DCR environment\n");
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
} else {
T0 = val;
}
}
void do_store_dcr (void)
{
if (unlikely(env->dcr_env == NULL)) {
if (loglevel != 0) {
fprintf(logfile, "No DCR environment\n");
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
}
}
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
void do_40x_rfci (void) void do_40x_rfci (void)
{ {
@ -1268,40 +1303,6 @@ void do_rfmci (void)
env->interrupt_request = CPU_INTERRUPT_EXITTB; env->interrupt_request = CPU_INTERRUPT_EXITTB;
} }
void do_load_dcr (void)
{
target_ulong val;
if (unlikely(env->dcr_env == NULL)) {
if (loglevel != 0) {
fprintf(logfile, "No DCR environment\n");
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
} else {
T0 = val;
}
}
void do_store_dcr (void)
{
if (unlikely(env->dcr_env == NULL)) {
if (loglevel != 0) {
fprintf(logfile, "No DCR environment\n");
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
}
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
}
}
void do_load_403_pb (int num) void do_load_403_pb (int num)
{ {
T0 = env->pb[num]; T0 = env->pb[num];
@ -2238,7 +2239,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
if (likely(retaddr)) { if (likely(retaddr)) {
/* now we have a real cpu fault */ /* now we have a real cpu fault */
pc = (target_phys_addr_t)retaddr; pc = (target_phys_addr_t)(unsigned long)retaddr;
tb = tb_find_pc(pc); tb = tb_find_pc(pc);
if (likely(tb)) { if (likely(tb)) {
/* the PC is inside the translated code. It means that we have /* the PC is inside the translated code. It means that we have
@ -2261,16 +2262,14 @@ void do_tlbie (void)
{ {
T0 = (uint32_t)T0; T0 = (uint32_t)T0;
#if !defined(FLUSH_ALL_TLBS) #if !defined(FLUSH_ALL_TLBS)
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { /* XXX: Remove thoses tests */
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0); ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
if (env->id_tlbs == 1) if (env->id_tlbs == 1)
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1); ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
/* XXX: TODO */ ppc4xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
#if 0 env->spr[SPR_40x_PID]);
ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
env->spr[SPR_BOOKE_PID]);
#endif
} else { } else {
/* tlbie invalidate TLBs for all segments */ /* tlbie invalidate TLBs for all segments */
T0 &= TARGET_PAGE_MASK; T0 &= TARGET_PAGE_MASK;
@ -2305,11 +2304,11 @@ void do_tlbie_64 (void)
{ {
T0 = (uint64_t)T0; T0 = (uint64_t)T0;
#if !defined(FLUSH_ALL_TLBS) #if !defined(FLUSH_ALL_TLBS)
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0); ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
if (env->id_tlbs == 1) if (env->id_tlbs == 1)
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1); ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
/* XXX: TODO */ /* XXX: TODO */
#if 0 #if 0
ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
@ -2541,7 +2540,7 @@ void do_4xx_tlbwe_hi (void)
"are not supported (%d)\n", "are not supported (%d)\n",
tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7)); tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
} }
tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1); tlb->EPN = T1 & ~(tlb->size - 1);
if (T1 & 0x40) if (T1 & 0x40)
tlb->prot |= PAGE_VALID; tlb->prot |= PAGE_VALID;
else else
@ -2676,14 +2675,14 @@ void do_440_tlbwe (int word)
void do_440_tlbsx (void) void do_440_tlbsx (void)
{ {
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]); T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
} }
void do_440_tlbsx_ (void) void do_440_tlbsx_ (void)
{ {
int tmp = xer_so; int tmp = xer_so;
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]); T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
if (T0 != -1) if (T0 != -1)
tmp |= 0x02; tmp |= 0x02;
env->crf[0] = tmp; env->crf[0] = tmp;

View File

@ -167,9 +167,9 @@ void do_440_tlbwe (int word);
/* PowerPC 4xx specific helpers */ /* PowerPC 4xx specific helpers */
void do_405_check_ov (void); void do_405_check_ov (void);
void do_405_check_sat (void); void do_405_check_sat (void);
#if !defined(CONFIG_USER_ONLY)
void do_load_dcr (void); void do_load_dcr (void);
void do_store_dcr (void); void do_store_dcr (void);
#if !defined(CONFIG_USER_ONLY)
void do_40x_rfci (void); void do_40x_rfci (void);
void do_rfci (void); void do_rfci (void);
void do_rfdi (void); void do_rfdi (void);

View File

@ -27,11 +27,14 @@
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
/* Include definitions for instructions classes and implementations flags */
//#define DO_SINGLE_STEP //#define DO_SINGLE_STEP
//#define PPC_DEBUG_DISAS //#define PPC_DEBUG_DISAS
//#define DEBUG_MEMORY_ACCESSES //#define DEBUG_MEMORY_ACCESSES
//#define DO_PPC_STATISTICS //#define DO_PPC_STATISTICS
/*****************************************************************************/
/* Code translation helpers */
#if defined(USE_DIRECT_JUMP) #if defined(USE_DIRECT_JUMP)
#define TBPARAM(x) #define TBPARAM(x)
#else #else
@ -175,8 +178,10 @@ struct opc_handler_t {
uint64_t type; uint64_t type;
/* handler */ /* handler */
void (*handler)(DisasContext *ctx); void (*handler)(DisasContext *ctx);
#if defined(DO_PPC_STATISTICS) #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
const unsigned char *oname; const unsigned char *oname;
#endif
#if defined(DO_PPC_STATISTICS)
uint64_t count; uint64_t count;
#endif #endif
}; };
@ -249,6 +254,7 @@ typedef struct opcode_t {
const unsigned char *oname; const unsigned char *oname;
} opcode_t; } opcode_t;
/*****************************************************************************/
/*** Instruction decoding ***/ /*** Instruction decoding ***/
#define EXTRACT_HELPER(name, shift, nb) \ #define EXTRACT_HELPER(name, shift, nb) \
static inline uint32_t name (uint32_t opcode) \ static inline uint32_t name (uint32_t opcode) \
@ -365,6 +371,106 @@ static inline target_ulong MASK (uint32_t start, uint32_t end)
return ret; return ret;
} }
/*****************************************************************************/
/* PowerPC Instructions types definitions */
enum {
PPC_NONE = 0x0000000000000000ULL,
/* integer operations instructions */
/* flow control instructions */
/* virtual memory instructions */
/* ld/st with reservation instructions */
/* cache control instructions */
/* spr/msr access instructions */
PPC_INSNS_BASE = 0x0000000000000001ULL,
#define PPC_INTEGER PPC_INSNS_BASE
#define PPC_FLOW PPC_INSNS_BASE
#define PPC_MEM PPC_INSNS_BASE
#define PPC_RES PPC_INSNS_BASE
#define PPC_CACHE PPC_INSNS_BASE
#define PPC_MISC PPC_INSNS_BASE
/* Optional floating point instructions */
PPC_FLOAT = 0x0000000000000002ULL,
PPC_FLOAT_FSQRT = 0x0000000000000004ULL,
PPC_FLOAT_FRES = 0x0000000000000008ULL,
PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL,
PPC_FLOAT_FSEL = 0x0000000000000020ULL,
PPC_FLOAT_STFIWX = 0x0000000000000040ULL,
/* external control instructions */
PPC_EXTERN = 0x0000000000000080ULL,
/* segment register access instructions */
PPC_SEGMENT = 0x0000000000000100ULL,
/* Optional cache control instruction */
PPC_CACHE_DCBA = 0x0000000000000200ULL,
/* Optional memory control instructions */
PPC_MEM_TLBIA = 0x0000000000000400ULL,
PPC_MEM_TLBIE = 0x0000000000000800ULL,
PPC_MEM_TLBSYNC = 0x0000000000001000ULL,
/* eieio & sync */
PPC_MEM_SYNC = 0x0000000000002000ULL,
/* PowerPC 6xx TLB management instructions */
PPC_6xx_TLB = 0x0000000000004000ULL,
/* Altivec support */
PPC_ALTIVEC = 0x0000000000008000ULL,
/* Time base mftb instruction */
PPC_MFTB = 0x0000000000010000ULL,
/* Embedded PowerPC dedicated instructions */
PPC_EMB_COMMON = 0x0000000000020000ULL,
/* PowerPC 40x exception model */
PPC_40x_EXCP = 0x0000000000040000ULL,
/* PowerPC 40x TLB management instructions */
PPC_40x_TLB = 0x0000000000080000ULL,
/* PowerPC 405 Mac instructions */
PPC_405_MAC = 0x0000000000100000ULL,
/* PowerPC 440 specific instructions */
PPC_440_SPEC = 0x0000000000200000ULL,
/* Power-to-PowerPC bridge (601) */
PPC_POWER_BR = 0x0000000000400000ULL,
/* PowerPC 602 specific */
PPC_602_SPEC = 0x0000000000800000ULL,
/* Deprecated instructions */
/* Original POWER instruction set */
PPC_POWER = 0x0000000001000000ULL,
/* POWER2 instruction set extension */
PPC_POWER2 = 0x0000000002000000ULL,
/* Power RTC support */
PPC_POWER_RTC = 0x0000000004000000ULL,
/* 64 bits PowerPC instructions */
/* 64 bits PowerPC instruction set */
PPC_64B = 0x0000000008000000ULL,
/* 64 bits hypervisor extensions */
PPC_64H = 0x0000000010000000ULL,
/* 64 bits PowerPC "bridge" features */
PPC_64_BRIDGE = 0x0000000020000000ULL,
/* BookE (embedded) PowerPC specification */
PPC_BOOKE = 0x0000000040000000ULL,
/* eieio */
PPC_MEM_EIEIO = 0x0000000080000000ULL,
/* e500 vector instructions */
PPC_E500_VECTOR = 0x0000000100000000ULL,
/* PowerPC 4xx dedicated instructions */
PPC_4xx_COMMON = 0x0000000200000000ULL,
/* PowerPC 2.03 specification extensions */
PPC_203 = 0x0000000400000000ULL,
/* PowerPC 2.03 SPE extension */
PPC_SPE = 0x0000000800000000ULL,
/* PowerPC 2.03 SPE floating-point extension */
PPC_SPEFPU = 0x0000001000000000ULL,
/* SLB management */
PPC_SLBI = 0x0000002000000000ULL,
/* PowerPC 40x ibct instructions */
PPC_40x_ICBT = 0x0000004000000000ULL,
/* PowerPC 74xx TLB management instructions */
PPC_74xx_TLB = 0x0000008000000000ULL,
/* More BookE (embedded) instructions... */
PPC_BOOKE_EXT = 0x0000010000000000ULL,
/* rfmci is not implemented in all BookE PowerPC */
PPC_RFMCI = 0x0000020000000000ULL,
/* user-mode DCR access, implemented in PowerPC 460 */
PPC_DCRUX = 0x0000040000000000ULL,
};
/*****************************************************************************/
/* PowerPC instructions table */
#if HOST_LONG_BITS == 64 #if HOST_LONG_BITS == 64
#define OPC_ALIGN 8 #define OPC_ALIGN 8
#else #else
@ -845,15 +951,15 @@ GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
/* mulhd mulhd. */ /* mulhd mulhd. */
GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_INTEGER); GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_64B);
/* mulhdu mulhdu. */ /* mulhdu mulhdu. */
GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_INTEGER); GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
/* mulld mulld. mulldo mulldo. */ /* mulld mulld. mulldo mulldo. */
GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_INTEGER); GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_64B);
/* divd divd. divdo divdo. */ /* divd divd. divdo divdo. */
GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_INTEGER); GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_64B);
/* divdu divdu. divduo divduo. */ /* divdu divdu. divduo divduo. */
GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_INTEGER); GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B);
#endif #endif
/*** Integer comparison ***/ /*** Integer comparison ***/
@ -1424,8 +1530,8 @@ __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
#endif #endif
/*** Floating-Point arithmetic ***/ /*** Floating-Point arithmetic ***/
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \ #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, type) \
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
{ \ { \
if (unlikely(!ctx->fpu_enabled)) { \ if (unlikely(!ctx->fpu_enabled)) { \
RET_EXCP(ctx, EXCP_NO_FP, 0); \ RET_EXCP(ctx, EXCP_NO_FP, 0); \
@ -1444,9 +1550,9 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \
gen_op_set_Rc1(); \ gen_op_set_Rc1(); \
} }
#define GEN_FLOAT_ACB(name, op2) \ #define GEN_FLOAT_ACB(name, op2, type) \
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \ _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, type); \
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1); _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, type);
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \ #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
@ -1492,8 +1598,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \ _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
#define GEN_FLOAT_B(name, op2, op3) \ #define GEN_FLOAT_B(name, op2, op3, type) \
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
{ \ { \
if (unlikely(!ctx->fpu_enabled)) { \ if (unlikely(!ctx->fpu_enabled)) { \
RET_EXCP(ctx, EXCP_NO_FP, 0); \ RET_EXCP(ctx, EXCP_NO_FP, 0); \
@ -1507,8 +1613,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \
gen_op_set_Rc1(); \ gen_op_set_Rc1(); \
} }
#define GEN_FLOAT_BS(name, op1, op2) \ #define GEN_FLOAT_BS(name, op1, op2, type) \
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
{ \ { \
if (unlikely(!ctx->fpu_enabled)) { \ if (unlikely(!ctx->fpu_enabled)) { \
RET_EXCP(ctx, EXCP_NO_FP, 0); \ RET_EXCP(ctx, EXCP_NO_FP, 0); \
@ -1529,19 +1635,19 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0);
/* fmul - fmuls */ /* fmul - fmuls */
GEN_FLOAT_AC(mul, 0x19, 0x0000F800); GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
/* fres */ /* XXX: not in 601 */ /* fres */
GEN_FLOAT_BS(res, 0x3B, 0x18); GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES);
/* frsqrte */ /* XXX: not in 601 */ /* frsqrte */
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A); GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, PPC_FLOAT_FRSQRTE);
/* fsel */ /* XXX: not in 601 */ /* fsel */
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0); _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, PPC_FLOAT_FSEL);
/* fsub - fsubs */ /* fsub - fsubs */
GEN_FLOAT_AB(sub, 0x14, 0x000007C0); GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
/* Optional: */ /* Optional: */
/* fsqrt */ /* fsqrt */
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
{ {
if (unlikely(!ctx->fpu_enabled)) { if (unlikely(!ctx->fpu_enabled)) {
RET_EXCP(ctx, EXCP_NO_FP, 0); RET_EXCP(ctx, EXCP_NO_FP, 0);
@ -1555,7 +1661,7 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
gen_op_set_Rc1(); gen_op_set_Rc1();
} }
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
{ {
if (unlikely(!ctx->fpu_enabled)) { if (unlikely(!ctx->fpu_enabled)) {
RET_EXCP(ctx, EXCP_NO_FP, 0); RET_EXCP(ctx, EXCP_NO_FP, 0);
@ -1572,28 +1678,28 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
/*** Floating-Point multiply-and-add ***/ /*** Floating-Point multiply-and-add ***/
/* fmadd - fmadds */ /* fmadd - fmadds */
GEN_FLOAT_ACB(madd, 0x1D); GEN_FLOAT_ACB(madd, 0x1D, PPC_FLOAT);
/* fmsub - fmsubs */ /* fmsub - fmsubs */
GEN_FLOAT_ACB(msub, 0x1C); GEN_FLOAT_ACB(msub, 0x1C, PPC_FLOAT);
/* fnmadd - fnmadds */ /* fnmadd - fnmadds */
GEN_FLOAT_ACB(nmadd, 0x1F); GEN_FLOAT_ACB(nmadd, 0x1F, PPC_FLOAT);
/* fnmsub - fnmsubs */ /* fnmsub - fnmsubs */
GEN_FLOAT_ACB(nmsub, 0x1E); GEN_FLOAT_ACB(nmsub, 0x1E, PPC_FLOAT);
/*** Floating-Point round & convert ***/ /*** Floating-Point round & convert ***/
/* fctiw */ /* fctiw */
GEN_FLOAT_B(ctiw, 0x0E, 0x00); GEN_FLOAT_B(ctiw, 0x0E, 0x00, PPC_FLOAT);
/* fctiwz */ /* fctiwz */
GEN_FLOAT_B(ctiwz, 0x0F, 0x00); GEN_FLOAT_B(ctiwz, 0x0F, 0x00, PPC_FLOAT);
/* frsp */ /* frsp */
GEN_FLOAT_B(rsp, 0x0C, 0x00); GEN_FLOAT_B(rsp, 0x0C, 0x00, PPC_FLOAT);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
/* fcfid */ /* fcfid */
GEN_FLOAT_B(cfid, 0x0E, 0x1A); GEN_FLOAT_B(cfid, 0x0E, 0x1A, PPC_64B);
/* fctid */ /* fctid */
GEN_FLOAT_B(ctid, 0x0E, 0x19); GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B);
/* fctidz */ /* fctidz */
GEN_FLOAT_B(ctidz, 0x0F, 0x19); GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B);
#endif #endif
/*** Floating-Point compare ***/ /*** Floating-Point compare ***/
@ -1627,7 +1733,7 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
/*** Floating-point move ***/ /*** Floating-point move ***/
/* fabs */ /* fabs */
GEN_FLOAT_B(abs, 0x08, 0x08); GEN_FLOAT_B(abs, 0x08, 0x08, PPC_FLOAT);
/* fmr - fmr. */ /* fmr - fmr. */
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
@ -1644,9 +1750,9 @@ GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
} }
/* fnabs */ /* fnabs */
GEN_FLOAT_B(nabs, 0x08, 0x04); GEN_FLOAT_B(nabs, 0x08, 0x04, PPC_FLOAT);
/* fneg */ /* fneg */
GEN_FLOAT_B(neg, 0x08, 0x01); GEN_FLOAT_B(neg, 0x08, 0x01, PPC_FLOAT);
/*** Floating-Point status & ctrl register ***/ /*** Floating-Point status & ctrl register ***/
/* mcrfs */ /* mcrfs */
@ -2426,7 +2532,7 @@ static GenOpFunc *gen_op_stdcx[] = {
#endif #endif
/* ldarx */ /* ldarx */
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES) GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
{ {
gen_addr_reg_index(ctx); gen_addr_reg_index(ctx);
op_ldarx(); op_ldarx();
@ -2434,7 +2540,7 @@ GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES)
} }
/* stdcx. */ /* stdcx. */
GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES) GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
{ {
gen_addr_reg_index(ctx); gen_addr_reg_index(ctx);
gen_op_load_gpr_T1(rS(ctx->opcode)); gen_op_load_gpr_T1(rS(ctx->opcode));
@ -2591,7 +2697,7 @@ GEN_STFS(fs, 0x14);
/* Optional: */ /* Optional: */
/* stfiwx */ /* stfiwx */
GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT_STFIWX)
{ {
if (unlikely(!ctx->fpu_enabled)) { if (unlikely(!ctx->fpu_enabled)) {
RET_EXCP(ctx, EXCP_NO_FP, 0); RET_EXCP(ctx, EXCP_NO_FP, 0);
@ -2886,7 +2992,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
} }
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW) GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -3050,7 +3156,7 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
} }
/* mftb */ /* mftb */
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB) GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
{ {
gen_op_mfspr(ctx); gen_op_mfspr(ctx);
} }
@ -3074,7 +3180,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
/* mtmsr */ /* mtmsr */
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC) GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVREG(ctx); RET_PRIVREG(ctx);
@ -3296,7 +3402,7 @@ GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
/* Optional: */ /* Optional: */
/* dcba */ /* dcba */
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT) GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
{ {
} }
@ -3568,7 +3674,7 @@ GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
} }
/* clcs */ /* clcs */
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) /* 601 ? */ GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
{ {
gen_op_load_gpr_T0(rA(ctx->opcode)); gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_POWER_clcs(); gen_op_POWER_clcs();
@ -4222,14 +4328,14 @@ GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
/* BookE specific instructions */ /* BookE specific instructions */
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE) GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT)
{ {
/* XXX: TODO */ /* XXX: TODO */
RET_INVAL(ctx); RET_INVAL(ctx);
} }
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE) GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -4331,99 +4437,98 @@ static inline void gen_405_mulladd_insn (DisasContext *ctx, int opc2, int opc3,
} }
} }
#define GEN_MAC_HANDLER(name, opc2, opc3, is_440) \ #define GEN_MAC_HANDLER(name, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, \ GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
is_440 ? PPC_440_SPEC : PPC_405_MAC) \
{ \ { \
gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \ gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
rD(ctx->opcode), Rc(ctx->opcode)); \ rD(ctx->opcode), Rc(ctx->opcode)); \
} }
/* macchw - macchw. */ /* macchw - macchw. */
GEN_MAC_HANDLER(macchw, 0x0C, 0x05, 0); GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
/* macchwo - macchwo. */ /* macchwo - macchwo. */
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15, 0); GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
/* macchws - macchws. */ /* macchws - macchws. */
GEN_MAC_HANDLER(macchws, 0x0C, 0x07, 0); GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
/* macchwso - macchwso. */ /* macchwso - macchwso. */
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17, 0); GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
/* macchwsu - macchwsu. */ /* macchwsu - macchwsu. */
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06, 0); GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
/* macchwsuo - macchwsuo. */ /* macchwsuo - macchwsuo. */
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16, 0); GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
/* macchwu - macchwu. */ /* macchwu - macchwu. */
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04, 0); GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
/* macchwuo - macchwuo. */ /* macchwuo - macchwuo. */
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14, 0); GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
/* machhw - machhw. */ /* machhw - machhw. */
GEN_MAC_HANDLER(machhw, 0x0C, 0x01, 0); GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
/* machhwo - machhwo. */ /* machhwo - machhwo. */
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11, 0); GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
/* machhws - machhws. */ /* machhws - machhws. */
GEN_MAC_HANDLER(machhws, 0x0C, 0x03, 0); GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
/* machhwso - machhwso. */ /* machhwso - machhwso. */
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13, 0); GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
/* machhwsu - machhwsu. */ /* machhwsu - machhwsu. */
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02, 0); GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
/* machhwsuo - machhwsuo. */ /* machhwsuo - machhwsuo. */
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12, 0); GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
/* machhwu - machhwu. */ /* machhwu - machhwu. */
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00, 0); GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
/* machhwuo - machhwuo. */ /* machhwuo - machhwuo. */
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10, 0); GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
/* maclhw - maclhw. */ /* maclhw - maclhw. */
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D, 0); GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
/* maclhwo - maclhwo. */ /* maclhwo - maclhwo. */
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D, 0); GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
/* maclhws - maclhws. */ /* maclhws - maclhws. */
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F, 0); GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
/* maclhwso - maclhwso. */ /* maclhwso - maclhwso. */
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F, 0); GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
/* maclhwu - maclhwu. */ /* maclhwu - maclhwu. */
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C, 0); GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
/* maclhwuo - maclhwuo. */ /* maclhwuo - maclhwuo. */
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C, 0); GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
/* maclhwsu - maclhwsu. */ /* maclhwsu - maclhwsu. */
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E, 0); GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
/* maclhwsuo - maclhwsuo. */ /* maclhwsuo - maclhwsuo. */
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E, 0); GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
/* nmacchw - nmacchw. */ /* nmacchw - nmacchw. */
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05, 0); GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
/* nmacchwo - nmacchwo. */ /* nmacchwo - nmacchwo. */
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15, 0); GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
/* nmacchws - nmacchws. */ /* nmacchws - nmacchws. */
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07, 0); GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
/* nmacchwso - nmacchwso. */ /* nmacchwso - nmacchwso. */
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17, 0); GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
/* nmachhw - nmachhw. */ /* nmachhw - nmachhw. */
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01, 0); GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
/* nmachhwo - nmachhwo. */ /* nmachhwo - nmachhwo. */
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11, 0); GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
/* nmachhws - nmachhws. */ /* nmachhws - nmachhws. */
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03, 1); GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
/* nmachhwso - nmachhwso. */ /* nmachhwso - nmachhwso. */
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13, 1); GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
/* nmaclhw - nmaclhw. */ /* nmaclhw - nmaclhw. */
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D, 1); GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
/* nmaclhwo - nmaclhwo. */ /* nmaclhwo - nmaclhwo. */
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D, 1); GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
/* nmaclhws - nmaclhws. */ /* nmaclhws - nmaclhws. */
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F, 1); GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
/* nmaclhwso - nmaclhwso. */ /* nmaclhwso - nmaclhwso. */
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F, 1); GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
/* mulchw - mulchw. */ /* mulchw - mulchw. */
GEN_MAC_HANDLER(mulchw, 0x08, 0x05, 0); GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
/* mulchwu - mulchwu. */ /* mulchwu - mulchwu. */
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04, 0); GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
/* mulhhw - mulhhw. */ /* mulhhw - mulhhw. */
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01, 0); GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
/* mulhhwu - mulhhwu. */ /* mulhhwu - mulhhwu. */
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00, 0); GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
/* mullhw - mullhw. */ /* mullhw - mullhw. */
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D, 0); GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
/* mullhwu - mullhwu. */ /* mullhwu - mullhwu. */
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C, 0); GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
/* mfdcr */ /* mfdcr */
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON) GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
@ -4463,7 +4568,7 @@ GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
/* mfdcrx */ /* mfdcrx */
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE) GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVREG(ctx); RET_PRIVREG(ctx);
@ -4475,12 +4580,13 @@ GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
gen_op_load_gpr_T0(rA(ctx->opcode)); gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_dcr(); gen_op_load_dcr();
gen_op_store_T0_gpr(rD(ctx->opcode)); gen_op_store_T0_gpr(rD(ctx->opcode));
/* Note: Rc update flag set leads to undefined state of Rc0 */
#endif #endif
} }
/* mtdcrx */ /* mtdcrx */
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE) GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVREG(ctx); RET_PRIVREG(ctx);
@ -4492,9 +4598,28 @@ GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
gen_op_load_gpr_T0(rA(ctx->opcode)); gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_gpr_T1(rS(ctx->opcode)); gen_op_load_gpr_T1(rS(ctx->opcode));
gen_op_store_dcr(); gen_op_store_dcr();
/* Note: Rc update flag set leads to undefined state of Rc0 */
#endif #endif
} }
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_dcr();
gen_op_store_T0_gpr(rD(ctx->opcode));
/* Note: Rc update flag set leads to undefined state of Rc0 */
}
/* mtdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
{
gen_op_load_gpr_T0(rA(ctx->opcode));
gen_op_load_gpr_T1(rS(ctx->opcode));
gen_op_store_dcr();
/* Note: Rc update flag set leads to undefined state of Rc0 */
}
/* dccci */ /* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON) GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{ {
@ -4595,7 +4720,7 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
/* BookE specific */ /* BookE specific */
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE) GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -4611,7 +4736,7 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
} }
/* XXX: not implemented on 440 ? */ /* XXX: not implemented on 440 ? */
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE) GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -4628,7 +4753,7 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
/* TLB management - PowerPC 405 implementation */ /* TLB management - PowerPC 405 implementation */
/* tlbre */ /* tlbre */
GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC) GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -4656,7 +4781,7 @@ GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
} }
/* tlbsx - tlbsx. */ /* tlbsx - tlbsx. */
GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC) GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -4675,7 +4800,7 @@ GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
} }
/* tlbwe */ /* tlbwe */
GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC) GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
{ {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
RET_PRIVOPC(ctx); RET_PRIVOPC(ctx);
@ -5701,7 +5826,7 @@ void cpu_dump_state (CPUState *env, FILE *f,
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
if ((i & (RGPL - 1)) == 0) if ((i & (RGPL - 1)) == 0)
cpu_fprintf(f, "GPR%02d", i); cpu_fprintf(f, "GPR%02d", i);
cpu_fprintf(f, " " REGX, env->gpr[i]); cpu_fprintf(f, " " REGX, (target_ulong)env->gpr[i]);
if ((i & (RGPL - 1)) == (RGPL - 1)) if ((i & (RGPL - 1)) == (RGPL - 1))
cpu_fprintf(f, "\n"); cpu_fprintf(f, "\n");
} }

File diff suppressed because it is too large Load Diff