target/ppc: Remove PowerPC 601 CPUs
The PowerPC 601 processor is the first generation of processors to implement the PowerPC architecture. It was designed as a bridge processor and also could execute most of the instructions of the previous POWER architecture. It was found on the first Macs and IBM RS/6000 workstations. There is not much interest in keeping the CPU model of this POWER-PowerPC bridge processor. We have the 603 and 604 CPU models of the 60x family which implement the complete PowerPC instruction set. Cc: "Hervé Poussineau" <hpoussin@reactos.org> Cc: Laurent Vivier <laurent@vivier.eu> Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com> Message-Id: <20220203142756.1302515-1-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
parent
36387ca51c
commit
005b69fdcc
21
hw/ppc/ppc.c
21
hw/ppc/ppc.c
@ -1083,27 +1083,6 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
|
||||
return &cpu_ppc_set_tb_clk;
|
||||
}
|
||||
|
||||
/* Specific helpers for POWER & PowerPC 601 RTC */
|
||||
void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
_cpu_ppc_store_tbu(env, value);
|
||||
}
|
||||
|
||||
uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
|
||||
{
|
||||
return _cpu_ppc_load_tbu(env);
|
||||
}
|
||||
|
||||
void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
|
||||
}
|
||||
|
||||
uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
|
||||
{
|
||||
return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PowerPC 40x timers */
|
||||
|
||||
|
@ -255,13 +255,8 @@ static void ibm_40p_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (env->flags & POWERPC_FLAG_RTC_CLK) {
|
||||
/* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */
|
||||
cpu_ppc_tb_init(env, 7812500UL);
|
||||
} else {
|
||||
/* Set time-base frequency to 100 Mhz */
|
||||
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
|
||||
}
|
||||
/* Set time-base frequency to 100 Mhz */
|
||||
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
|
||||
qemu_register_reset(ppc_prep_reset, cpu);
|
||||
|
||||
/* PCI host */
|
||||
|
@ -54,14 +54,6 @@ uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
|
||||
return cpu_ppc_get_tb(env);
|
||||
}
|
||||
|
||||
uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
|
||||
__attribute__ (( alias ("cpu_ppc_load_tbu") ));
|
||||
|
||||
uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
|
||||
{
|
||||
return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
|
||||
}
|
||||
|
||||
/* XXX: to be fixed */
|
||||
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
|
||||
{
|
||||
@ -289,14 +281,6 @@ void cpu_loop(CPUPPCState *env)
|
||||
cpu_abort(cs, "Programmable interval timer interrupt "
|
||||
"while in user mode. Aborting\n");
|
||||
break;
|
||||
case POWERPC_EXCP_IO: /* IO error exception */
|
||||
cpu_abort(cs, "IO error exception while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
case POWERPC_EXCP_RUNM: /* Run mode exception */
|
||||
cpu_abort(cs, "Run mode exception while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
case POWERPC_EXCP_EMUL: /* Emulation trap exception */
|
||||
cpu_abort(cs, "Emulation trap exception not handled\n");
|
||||
break;
|
||||
|
@ -422,12 +422,6 @@
|
||||
CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, e600)
|
||||
/* 32 bits "classic" PowerPC */
|
||||
/* PowerPC 6xx family */
|
||||
POWERPC_DEF("601_v0", CPU_POWERPC_601_v0, 601,
|
||||
"PowerPC 601v0")
|
||||
POWERPC_DEF("601_v1", CPU_POWERPC_601_v1, 601,
|
||||
"PowerPC 601v1")
|
||||
POWERPC_DEF("601_v2", CPU_POWERPC_601_v2, 601v,
|
||||
"PowerPC 601v2")
|
||||
POWERPC_DEF("603", CPU_POWERPC_603, 603,
|
||||
"PowerPC 603")
|
||||
POWERPC_DEF("603e_v1.1", CPU_POWERPC_603E_v11, 603E,
|
||||
@ -859,8 +853,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||
{ "mpc8555", "mpc8555_v11" },
|
||||
{ "mpc8555e", "mpc8555e_v11" },
|
||||
{ "mpc8560", "mpc8560_v21" },
|
||||
{ "601", "601_v2" },
|
||||
{ "601v", "601_v2" },
|
||||
{ "vanilla", "603" },
|
||||
{ "603e", "603e_v4.1" },
|
||||
{ "stretch", "603e_v4.1" },
|
||||
|
@ -205,9 +205,6 @@ enum {
|
||||
#define CPU_POWERPC_MPC8641 CPU_POWERPC_e600
|
||||
#define CPU_POWERPC_MPC8641D CPU_POWERPC_e600
|
||||
/* PowerPC 6xx cores */
|
||||
CPU_POWERPC_601_v0 = 0x00010001,
|
||||
CPU_POWERPC_601_v1 = 0x00010001,
|
||||
CPU_POWERPC_601_v2 = 0x00010002,
|
||||
CPU_POWERPC_603 = 0x00030100,
|
||||
CPU_POWERPC_603E_v11 = 0x00060101,
|
||||
CPU_POWERPC_603E_v12 = 0x00060102,
|
||||
|
@ -61,8 +61,6 @@ enum powerpc_mmu_t {
|
||||
POWERPC_MMU_BOOKE = 0x00000008,
|
||||
/* BookE 2.06 MMU model */
|
||||
POWERPC_MMU_BOOKE206 = 0x00000009,
|
||||
/* PowerPC 601 MMU model (specific BATs format) */
|
||||
POWERPC_MMU_601 = 0x0000000A,
|
||||
#define POWERPC_MMU_64 0x00010000
|
||||
/* 64 bits PowerPC MMU */
|
||||
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
|
||||
@ -90,10 +88,6 @@ enum powerpc_excp_t {
|
||||
POWERPC_EXCP_STD,
|
||||
/* PowerPC 40x exception model */
|
||||
POWERPC_EXCP_40x,
|
||||
/* PowerPC 601 exception model */
|
||||
POWERPC_EXCP_601,
|
||||
/* PowerPC 602 exception model */
|
||||
POWERPC_EXCP_602,
|
||||
/* PowerPC 603 exception model */
|
||||
POWERPC_EXCP_603,
|
||||
/* PowerPC G2 exception model */
|
||||
|
@ -89,11 +89,9 @@ enum {
|
||||
POWERPC_EXCP_VPU = 73, /* Vector unavailable exception */
|
||||
/* 40x specific exceptions */
|
||||
POWERPC_EXCP_PIT = 74, /* Programmable interval timer interrupt */
|
||||
/* 601 specific exceptions */
|
||||
POWERPC_EXCP_IO = 75, /* IO error exception */
|
||||
POWERPC_EXCP_RUNM = 76, /* Run mode exception */
|
||||
/* Vectors 75-76 are 601 specific exceptions */
|
||||
/* 602 specific exceptions */
|
||||
POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
|
||||
POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
|
||||
/* 602/603 specific exceptions */
|
||||
POWERPC_EXCP_IFTLB = 78, /* Instruction fetch TLB miss */
|
||||
POWERPC_EXCP_DLTLB = 79, /* Data load TLB miss */
|
||||
@ -632,8 +630,7 @@ enum {
|
||||
POWERPC_FLAG_PX = 0x00000200,
|
||||
POWERPC_FLAG_PMM = 0x00000400,
|
||||
/* Flag for special features */
|
||||
/* Decrementer clock: RTC clock (POWER, 601) or bus clock */
|
||||
POWERPC_FLAG_RTC_CLK = 0x00010000,
|
||||
/* Decrementer clock */
|
||||
POWERPC_FLAG_BUS_CLK = 0x00020000,
|
||||
/* Has CFAR */
|
||||
POWERPC_FLAG_CFAR = 0x00040000,
|
||||
@ -643,8 +640,6 @@ enum {
|
||||
POWERPC_FLAG_TM = 0x00100000,
|
||||
/* Has SCV (ISA 3.00) */
|
||||
POWERPC_FLAG_SCV = 0x00200000,
|
||||
/* Has HID0 for LE bit (601) */
|
||||
POWERPC_FLAG_HID0_LE = 0x00400000,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -655,7 +650,7 @@ enum {
|
||||
* the MSR are validated in hreg_compute_hflags.
|
||||
*/
|
||||
enum {
|
||||
HFLAGS_LE = 0, /* MSR_LE -- comes from elsewhere on 601 */
|
||||
HFLAGS_LE = 0, /* MSR_LE */
|
||||
HFLAGS_HV = 1, /* computed from MSR_HV and other state */
|
||||
HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */
|
||||
HFLAGS_GTSE = 3, /* computed from SPR_LPCR[GTSE] */
|
||||
@ -1389,11 +1384,7 @@ void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
|
||||
void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value);
|
||||
uint64_t cpu_ppc_load_purr(CPUPPCState *env);
|
||||
void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value);
|
||||
uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env);
|
||||
uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void cpu_ppc601_store_rtcl(CPUPPCState *env, uint32_t value);
|
||||
void cpu_ppc601_store_rtcu(CPUPPCState *env, uint32_t value);
|
||||
target_ulong load_40x_pit(CPUPPCState *env);
|
||||
void store_40x_pit(CPUPPCState *env, target_ulong val);
|
||||
void store_40x_dbcr0(CPUPPCState *env, uint32_t val);
|
||||
@ -1516,17 +1507,12 @@ typedef PowerPCCPU ArchCPU;
|
||||
/* SPR definitions */
|
||||
#define SPR_MQ (0x000)
|
||||
#define SPR_XER (0x001)
|
||||
#define SPR_601_VRTCU (0x004)
|
||||
#define SPR_601_VRTCL (0x005)
|
||||
#define SPR_601_UDECR (0x006)
|
||||
#define SPR_LR (0x008)
|
||||
#define SPR_CTR (0x009)
|
||||
#define SPR_UAMR (0x00D)
|
||||
#define SPR_DSCR (0x011)
|
||||
#define SPR_DSISR (0x012)
|
||||
#define SPR_DAR (0x013) /* DAE for PowerPC 601 */
|
||||
#define SPR_601_RTCU (0x014)
|
||||
#define SPR_601_RTCL (0x015)
|
||||
#define SPR_DAR (0x013)
|
||||
#define SPR_DECR (0x016)
|
||||
#define SPR_SDR1 (0x019)
|
||||
#define SPR_SRR0 (0x01A)
|
||||
@ -2003,7 +1989,6 @@ typedef PowerPCCPU ArchCPU;
|
||||
#define SPR_HID1 (0x3F1)
|
||||
#define SPR_IABR (0x3F2)
|
||||
#define SPR_40x_DBCR0 (0x3F2)
|
||||
#define SPR_601_HID2 (0x3F2)
|
||||
#define SPR_Exxx_L1CSR0 (0x3F2)
|
||||
#define SPR_ICTRL (0x3F3)
|
||||
#define SPR_HID2 (0x3F3)
|
||||
@ -2019,7 +2004,6 @@ typedef PowerPCCPU ArchCPU;
|
||||
#define DABR_MASK (~(target_ulong)0x7)
|
||||
#define SPR_Exxx_BUCSR (0x3F5)
|
||||
#define SPR_40x_IAC2 (0x3F5)
|
||||
#define SPR_601_HID5 (0x3F5)
|
||||
#define SPR_40x_DAC1 (0x3F6)
|
||||
#define SPR_MSSCR0 (0x3F6)
|
||||
#define SPR_970_HID5 (0x3F6)
|
||||
@ -2052,7 +2036,6 @@ typedef PowerPCCPU ArchCPU;
|
||||
#define SPR_403_PBL2 (0x3FE)
|
||||
#define SPR_PIR (0x3FF)
|
||||
#define SPR_403_PBU2 (0x3FF)
|
||||
#define SPR_601_HID15 (0x3FF)
|
||||
#define SPR_604_HID15 (0x3FF)
|
||||
#define SPR_E500_SVR (0x3FF)
|
||||
|
||||
@ -2117,15 +2100,6 @@ enum {
|
||||
#define PPC_RES PPC_INSNS_BASE
|
||||
/* spr/msr access instructions */
|
||||
#define PPC_MISC PPC_INSNS_BASE
|
||||
/* Deprecated instruction sets */
|
||||
/* Original POWER instruction set */
|
||||
PPC_POWER = 0x0000000000000002ULL,
|
||||
/* POWER2 instruction set extension */
|
||||
PPC_POWER2 = 0x0000000000000004ULL,
|
||||
/* Power RTC support */
|
||||
PPC_POWER_RTC = 0x0000000000000008ULL,
|
||||
/* Power-to-PowerPC bridge (601) */
|
||||
PPC_POWER_BR = 0x0000000000000010ULL,
|
||||
/* 64 bits PowerPC instruction set */
|
||||
PPC_64B = 0x0000000000000020ULL,
|
||||
/* New 64 bits extensions (PowerPC 2.0x) */
|
||||
@ -2236,8 +2210,7 @@ enum {
|
||||
/* popcntw and popcntd instructions */
|
||||
PPC_POPCNTWD = 0x8000000000000000ULL,
|
||||
|
||||
#define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_POWER | PPC_POWER2 \
|
||||
| PPC_POWER_RTC | PPC_POWER_BR | PPC_64B \
|
||||
#define PPC_TCG_INSNS (PPC_INSNS_BASE | PPC_64B \
|
||||
| PPC_64BX | PPC_64H | PPC_WAIT | PPC_MFTB \
|
||||
| PPC_ISEL | PPC_POPCNTB \
|
||||
| PPC_STRING | PPC_FLOAT | PPC_FLOAT_EXT \
|
||||
|
@ -749,83 +749,6 @@ static void register_G2_sprs(CPUPPCState *env)
|
||||
0x00000000);
|
||||
}
|
||||
|
||||
/* SPR specific to PowerPC 601 implementation */
|
||||
static void register_601_sprs(CPUPPCState *env)
|
||||
{
|
||||
/* Multiplication/division register */
|
||||
/* MQ */
|
||||
spr_register(env, SPR_MQ, "MQ",
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
/* RTC registers */
|
||||
spr_register(env, SPR_601_RTCU, "RTCU",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, &spr_write_601_rtcu,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_601_VRTCU, "RTCU",
|
||||
&spr_read_601_rtcu, SPR_NOACCESS,
|
||||
&spr_read_601_rtcu, SPR_NOACCESS,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_601_RTCL, "RTCL",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, &spr_write_601_rtcl,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_601_VRTCL, "RTCL",
|
||||
&spr_read_601_rtcl, SPR_NOACCESS,
|
||||
&spr_read_601_rtcl, SPR_NOACCESS,
|
||||
0x00000000);
|
||||
/* Timer */
|
||||
#if 0 /* ? */
|
||||
spr_register(env, SPR_601_UDECR, "UDECR",
|
||||
&spr_read_decr, SPR_NOACCESS,
|
||||
&spr_read_decr, SPR_NOACCESS,
|
||||
0x00000000);
|
||||
#endif
|
||||
/* External access control */
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_EAR, "EAR",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
/* Memory management */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
spr_register(env, SPR_IBAT0U, "IBAT0U",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatu,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT0L, "IBAT0L",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatl,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT1U, "IBAT1U",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatu,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT1L, "IBAT1L",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatl,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT2U, "IBAT2U",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatu,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT2L, "IBAT2L",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatl,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT3U, "IBAT3U",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatu,
|
||||
0x00000000);
|
||||
spr_register(env, SPR_IBAT3L, "IBAT3L",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_601_ubat, &spr_write_601_ubatl,
|
||||
0x00000000);
|
||||
env->nb_BATs = 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void register_74xx_sprs(CPUPPCState *env)
|
||||
{
|
||||
/* Processor identification */
|
||||
@ -2060,26 +1983,6 @@ static void init_excp_BookE(CPUPPCState *env)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_excp_601(CPUPPCState *env)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
|
||||
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
|
||||
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
|
||||
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
|
||||
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
|
||||
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
|
||||
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
|
||||
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
|
||||
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
|
||||
env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00;
|
||||
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
|
||||
env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000;
|
||||
/* Hardware reset vector */
|
||||
env->hreset_vector = 0x00000100UL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_excp_603(CPUPPCState *env)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
@ -3809,120 +3712,6 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
|
||||
#endif
|
||||
|
||||
/* Non-embedded PowerPC */
|
||||
|
||||
#define POWERPC_MSRR_601 (0x0000000000001040ULL)
|
||||
|
||||
static void init_proc_601(CPUPPCState *env)
|
||||
{
|
||||
register_ne_601_sprs(env);
|
||||
register_sdr1_sprs(env);
|
||||
register_601_sprs(env);
|
||||
/* Hardware implementation registers */
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_HID0, "HID0",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_hid0_601,
|
||||
0x80010080);
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_HID1, "HID1",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_601_HID2, "HID2",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_601_HID5, "HID5",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
/* Memory management */
|
||||
init_excp_601(env);
|
||||
/*
|
||||
* XXX: beware that dcache line size is 64
|
||||
* but dcbz uses 32 bytes "sectors"
|
||||
* XXX: this breaks clcs instruction !
|
||||
*/
|
||||
env->dcache_line_size = 32;
|
||||
env->icache_line_size = 64;
|
||||
/* Allocate hardware IRQ controller */
|
||||
ppc6xx_irq_init(env_archcpu(env));
|
||||
}
|
||||
|
||||
POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
|
||||
|
||||
dc->desc = "PowerPC 601";
|
||||
pcc->init_proc = init_proc_601;
|
||||
pcc->check_pow = check_pow_none;
|
||||
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
|
||||
PPC_FLOAT |
|
||||
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
|
||||
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
|
||||
PPC_SEGMENT | PPC_EXTERN;
|
||||
pcc->msr_mask = (1ull << MSR_EE) |
|
||||
(1ull << MSR_PR) |
|
||||
(1ull << MSR_FP) |
|
||||
(1ull << MSR_ME) |
|
||||
(1ull << MSR_FE0) |
|
||||
(1ull << MSR_SE) |
|
||||
(1ull << MSR_FE1) |
|
||||
(1ull << MSR_EP) |
|
||||
(1ull << MSR_IR) |
|
||||
(1ull << MSR_DR);
|
||||
pcc->mmu_model = POWERPC_MMU_601;
|
||||
pcc->excp_model = POWERPC_EXCP_601;
|
||||
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
|
||||
pcc->bfd_mach = bfd_mach_ppc_601;
|
||||
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE;
|
||||
}
|
||||
|
||||
#define POWERPC_MSRR_601v (0x0000000000001040ULL)
|
||||
|
||||
static void init_proc_601v(CPUPPCState *env)
|
||||
{
|
||||
init_proc_601(env);
|
||||
/* XXX : not implemented */
|
||||
spr_register(env, SPR_601_HID15, "HID15",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
0x00000000);
|
||||
}
|
||||
|
||||
POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
|
||||
|
||||
dc->desc = "PowerPC 601v";
|
||||
pcc->init_proc = init_proc_601v;
|
||||
pcc->check_pow = check_pow_none;
|
||||
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
|
||||
PPC_FLOAT |
|
||||
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
|
||||
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
|
||||
PPC_SEGMENT | PPC_EXTERN;
|
||||
pcc->msr_mask = (1ull << MSR_EE) |
|
||||
(1ull << MSR_PR) |
|
||||
(1ull << MSR_FP) |
|
||||
(1ull << MSR_ME) |
|
||||
(1ull << MSR_FE0) |
|
||||
(1ull << MSR_SE) |
|
||||
(1ull << MSR_FE1) |
|
||||
(1ull << MSR_EP) |
|
||||
(1ull << MSR_IR) |
|
||||
(1ull << MSR_DR);
|
||||
pcc->mmu_model = POWERPC_MMU_601;
|
||||
pcc->excp_model = POWERPC_EXCP_601;
|
||||
pcc->bus_model = PPC_FLAGS_INPUT_6xx;
|
||||
pcc->bfd_mach = bfd_mach_ppc_601;
|
||||
pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE;
|
||||
}
|
||||
|
||||
static void init_proc_603(CPUPPCState *env)
|
||||
{
|
||||
register_ne_601_sprs(env);
|
||||
@ -7677,7 +7466,7 @@ static void init_ppc_proc(PowerPCCPU *cpu)
|
||||
"Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((env->flags & (POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_BUS_CLK)) == 0) {
|
||||
if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
|
||||
fprintf(stderr, "PowerPC flags inconsistency\n"
|
||||
"Should define the time-base and decrementer clock source\n");
|
||||
exit(1);
|
||||
@ -8491,7 +8280,6 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
|
||||
switch (env->mmu_model) {
|
||||
case POWERPC_MMU_32B:
|
||||
case POWERPC_MMU_601:
|
||||
case POWERPC_MMU_SOFT_6xx:
|
||||
#if defined(TARGET_PPC64)
|
||||
case POWERPC_MMU_64B:
|
||||
|
@ -73,8 +73,6 @@ static const char *powerpc_excp_name(int excp)
|
||||
case POWERPC_EXCP_HISEG: return "HISEG";
|
||||
case POWERPC_EXCP_VPU: return "VPU";
|
||||
case POWERPC_EXCP_PIT: return "PIT";
|
||||
case POWERPC_EXCP_IO: return "IO";
|
||||
case POWERPC_EXCP_RUNM: return "RUNM";
|
||||
case POWERPC_EXCP_EMUL: return "EMUL";
|
||||
case POWERPC_EXCP_IFTLB: return "IFTLB";
|
||||
case POWERPC_EXCP_DLTLB: return "DLTLB";
|
||||
@ -1671,9 +1669,6 @@ static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp)
|
||||
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
|
||||
case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
|
||||
case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
|
||||
case POWERPC_EXCP_IO: /* IO error exception */
|
||||
case POWERPC_EXCP_RUNM: /* Run mode exception */
|
||||
case POWERPC_EXCP_EMUL: /* Emulation trap exception */
|
||||
case POWERPC_EXCP_FPA: /* Floating-point assist exception */
|
||||
case POWERPC_EXCP_DABR: /* Data address breakpoint */
|
||||
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
|
||||
@ -2202,14 +2197,8 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/*****************************************************************************/
|
||||
/* PowerPC 601 specific instructions (POWER bridge) */
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
void helper_rfsvc(CPUPPCState *env)
|
||||
{
|
||||
do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
|
||||
}
|
||||
|
||||
/* Embedded.Processor Control */
|
||||
static int dbell2irq(target_ulong rb)
|
||||
|
@ -7,7 +7,6 @@ DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
DEF_HELPER_2(store_msr, void, env, tl)
|
||||
DEF_HELPER_1(rfi, void, env)
|
||||
DEF_HELPER_1(rfsvc, void, env)
|
||||
DEF_HELPER_1(40x_rfci, void, env)
|
||||
DEF_HELPER_1(rfci, void, env)
|
||||
DEF_HELPER_1(rfdi, void, env)
|
||||
@ -653,14 +652,9 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_2(clcs, TCG_CALL_NO_RWG_SE, tl, env, i32)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
DEF_HELPER_2(rac, tl, env, tl)
|
||||
#endif
|
||||
DEF_HELPER_3(div, tl, env, tl, tl)
|
||||
DEF_HELPER_3(divo, tl, env, tl, tl)
|
||||
DEF_HELPER_3(divs, tl, env, tl, tl)
|
||||
DEF_HELPER_3(divso, tl, env, tl, tl)
|
||||
|
||||
DEF_HELPER_2(load_dcr, tl, env, tl)
|
||||
DEF_HELPER_3(store_dcr, void, env, tl, tl)
|
||||
@ -674,8 +668,6 @@ DEF_HELPER_FLAGS_1(load_tbu, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_1(load_atbl, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_1(load_atbu, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_1(load_vtb, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_1(load_601_rtcl, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
|
||||
@ -693,15 +685,12 @@ DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_atbu, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_601_rtcl, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_601_rtcu, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(load_decr, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_2(store_decr, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(load_hdecr, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_tbu40, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_2(store_hid0_601, void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl)
|
||||
@ -715,8 +704,6 @@ DEF_HELPER_3(store_ibatl, void, env, i32, tl)
|
||||
DEF_HELPER_3(store_ibatu, void, env, i32, tl)
|
||||
DEF_HELPER_3(store_dbatl, void, env, i32, tl)
|
||||
DEF_HELPER_3(store_dbatu, void, env, i32, tl)
|
||||
DEF_HELPER_3(store_601_batl, void, env, i32, tl)
|
||||
DEF_HELPER_3(store_601_batu, void, env, i32, tl)
|
||||
#endif
|
||||
|
||||
#define dh_alias_fprp ptr
|
||||
|
@ -59,15 +59,6 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
|
||||
msr_mask = ((1 << MSR_LE) | (1 << MSR_PR) |
|
||||
(1 << MSR_DR) | (1 << MSR_FP));
|
||||
|
||||
if (ppc_flags & POWERPC_FLAG_HID0_LE) {
|
||||
/*
|
||||
* Note that MSR_LE is not set in env->msr_mask for this cpu,
|
||||
* and so will never be set in msr.
|
||||
*/
|
||||
uint32_t le = extract32(env->spr[SPR_HID0], 3, 1);
|
||||
hflags |= le << MSR_LE;
|
||||
}
|
||||
|
||||
if (ppc_flags & POWERPC_FLAG_DE) {
|
||||
target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0];
|
||||
if (dbcr0 & DBCR0_ICMP) {
|
||||
@ -249,7 +240,6 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
|
||||
hreg_swap_gpr_tgpr(env);
|
||||
}
|
||||
if (unlikely((value >> MSR_EP) & 1) != msr_ep) {
|
||||
/* Change the exception prefix on PowerPC 601 */
|
||||
env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
|
||||
}
|
||||
/*
|
||||
|
@ -422,72 +422,6 @@ uint64_t helper_PEXTD(uint64_t src, uint64_t mask)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PowerPC 601 specific instructions (POWER bridge) */
|
||||
target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
|
||||
{
|
||||
uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
|
||||
|
||||
if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
|
||||
(int32_t)arg2 == 0) {
|
||||
env->spr[SPR_MQ] = 0;
|
||||
return INT32_MIN;
|
||||
} else {
|
||||
env->spr[SPR_MQ] = tmp % arg2;
|
||||
return tmp / (int32_t)arg2;
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
|
||||
target_ulong arg2)
|
||||
{
|
||||
uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
|
||||
|
||||
if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
|
||||
(int32_t)arg2 == 0) {
|
||||
env->so = env->ov = 1;
|
||||
env->spr[SPR_MQ] = 0;
|
||||
return INT32_MIN;
|
||||
} else {
|
||||
env->spr[SPR_MQ] = tmp % arg2;
|
||||
tmp /= (int32_t)arg2;
|
||||
if ((int32_t)tmp != tmp) {
|
||||
env->so = env->ov = 1;
|
||||
} else {
|
||||
env->ov = 0;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
|
||||
target_ulong arg2)
|
||||
{
|
||||
if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
|
||||
(int32_t)arg2 == 0) {
|
||||
env->spr[SPR_MQ] = 0;
|
||||
return INT32_MIN;
|
||||
} else {
|
||||
env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
|
||||
return (int32_t)arg1 / (int32_t)arg2;
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
|
||||
target_ulong arg2)
|
||||
{
|
||||
if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
|
||||
(int32_t)arg2 == 0) {
|
||||
env->so = env->ov = 1;
|
||||
env->spr[SPR_MQ] = 0;
|
||||
return INT32_MIN;
|
||||
} else {
|
||||
env->ov = 0;
|
||||
env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
|
||||
return (int32_t)arg1 / (int32_t)arg2;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Altivec extension helpers */
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
|
@ -205,9 +205,8 @@ static int cpu_pre_save(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
/* Retain migration compatibility for pre 6.0 for 601 machines. */
|
||||
env->hflags_compat_nmsr = (env->flags & POWERPC_FLAG_HID0_LE
|
||||
? env->hflags & MSR_LE : 0);
|
||||
/* Used to retain migration compatibility for pre 6.0 for 601 machines. */
|
||||
env->hflags_compat_nmsr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,21 +211,6 @@ void helper_store_lpidr(CPUPPCState *env, target_ulong val)
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
|
||||
void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
target_ulong hid0;
|
||||
|
||||
hid0 = env->spr[SPR_HID0];
|
||||
env->spr[SPR_HID0] = (uint32_t)val;
|
||||
|
||||
if ((val ^ hid0) & 0x00000008) {
|
||||
/* Change current endianness */
|
||||
hreg_compute_hflags(env);
|
||||
qemu_log("%s: set endianness to %c => %08x\n", __func__,
|
||||
val & 0x8 ? 'l' : 'b', env->hflags);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
/* Bits 26 & 27 affect single-stepping. */
|
||||
@ -239,31 +224,6 @@ void helper_store_40x_sler(CPUPPCState *env, target_ulong val)
|
||||
store_40x_sler(env, val);
|
||||
}
|
||||
#endif
|
||||
/*****************************************************************************/
|
||||
/* PowerPC 601 specific instructions (POWER bridge) */
|
||||
|
||||
target_ulong helper_clcs(CPUPPCState *env, uint32_t arg)
|
||||
{
|
||||
switch (arg) {
|
||||
case 0x0CUL:
|
||||
/* Instruction cache line size */
|
||||
return env->icache_line_size;
|
||||
case 0x0DUL:
|
||||
/* Data cache line size */
|
||||
return env->dcache_line_size;
|
||||
case 0x0EUL:
|
||||
/* Minimum cache line size */
|
||||
return (env->icache_line_size < env->dcache_line_size) ?
|
||||
env->icache_line_size : env->dcache_line_size;
|
||||
case 0x0FUL:
|
||||
/* Maximum cache line size */
|
||||
return (env->icache_line_size > env->dcache_line_size) ?
|
||||
env->icache_line_size : env->dcache_line_size;
|
||||
default:
|
||||
/* Undefined */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Special registers manipulation */
|
||||
|
@ -125,30 +125,6 @@ static int hash32_bat_prot(PowerPCCPU *cpu,
|
||||
return prot;
|
||||
}
|
||||
|
||||
static target_ulong hash32_bat_601_size(PowerPCCPU *cpu,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
if (!(batl & BATL32_601_V)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
|
||||
}
|
||||
|
||||
static int hash32_bat_601_prot(int mmu_idx,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
int key, pp;
|
||||
|
||||
pp = batu & BATU32_601_PP;
|
||||
if (mmuidx_pr(mmu_idx) == 0) {
|
||||
key = !!(batu & BATU32_601_KS);
|
||||
} else {
|
||||
key = !!(batu & BATU32_601_KP);
|
||||
}
|
||||
return ppc_hash32_pp_prot(key, pp, 0);
|
||||
}
|
||||
|
||||
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
|
||||
MMUAccessType access_type, int *prot,
|
||||
int mmu_idx)
|
||||
@ -172,11 +148,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
|
||||
target_ulong batl = BATlt[i];
|
||||
target_ulong mask;
|
||||
|
||||
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
||||
mask = hash32_bat_601_size(cpu, batu, batl);
|
||||
} else {
|
||||
mask = hash32_bat_size(mmu_idx, batu, batl);
|
||||
}
|
||||
mask = hash32_bat_size(mmu_idx, batu, batl);
|
||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||
" BATl " TARGET_FMT_lx "\n", __func__,
|
||||
ifetch ? 'I' : 'D', i, ea, batu, batl);
|
||||
@ -184,11 +156,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
|
||||
if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
|
||||
hwaddr raddr = (batl & mask) | (ea & ~mask);
|
||||
|
||||
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
||||
*prot = hash32_bat_601_prot(mmu_idx, batu, batl);
|
||||
} else {
|
||||
*prot = hash32_bat_prot(cpu, batu, batl);
|
||||
}
|
||||
*prot = hash32_bat_prot(cpu, batu, batl);
|
||||
|
||||
return raddr & TARGET_PAGE_MASK;
|
||||
}
|
||||
@ -231,18 +199,6 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
|
||||
|
||||
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
|
||||
/*
|
||||
* Memory-forced I/O controller interface access
|
||||
*
|
||||
* If T=1 and BUID=x'07F', the 601 performs a memory access
|
||||
* to SR[28-31] LA[4-31], bypassing all protection mechanisms.
|
||||
*/
|
||||
*raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (access_type == MMU_INST_FETCH) {
|
||||
/* No code fetch is allowed in direct-store areas */
|
||||
if (guest_visible) {
|
||||
|
@ -34,15 +34,6 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
|
||||
#define BATL32_WIMG 0x00000078
|
||||
#define BATL32_PP 0x00000003
|
||||
|
||||
/* PowerPC 601 has slightly different BAT registers */
|
||||
|
||||
#define BATU32_601_KS 0x00000008
|
||||
#define BATU32_601_KP 0x00000004
|
||||
#define BATU32_601_PP 0x00000003
|
||||
|
||||
#define BATL32_601_V 0x00000040
|
||||
#define BATL32_601_BL 0x0000003f
|
||||
|
||||
/*
|
||||
* Hash page table definitions
|
||||
*/
|
||||
|
@ -441,29 +441,9 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
|
||||
ret = -3;
|
||||
}
|
||||
} else {
|
||||
target_ulong sr;
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
|
||||
/* Direct-store segment : absolutely *BUGGY* for now */
|
||||
|
||||
/*
|
||||
* Direct-store implies a 32-bit MMU.
|
||||
* Check the Segment Register's bus unit ID (BUID).
|
||||
*/
|
||||
sr = env->sr[eaddr >> 28];
|
||||
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
|
||||
/*
|
||||
* Memory-forced I/O controller interface access
|
||||
*
|
||||
* If T=1 and BUID=x'07F', the 601 performs a memory
|
||||
* access to SR[28-31] LA[4-31], bypassing all protection
|
||||
* mechanisms.
|
||||
*/
|
||||
ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
|
||||
ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ACCESS_INT:
|
||||
/* Integer load/store : only access allowed */
|
||||
@ -1539,7 +1519,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
|
||||
#endif
|
||||
|
||||
case POWERPC_MMU_32B:
|
||||
case POWERPC_MMU_601:
|
||||
return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
|
||||
psizep, protp, mmu_idx, guest_visible);
|
||||
|
||||
|
@ -279,88 +279,6 @@ void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
|
||||
env->DBAT[1][nr] = value;
|
||||
}
|
||||
|
||||
void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
|
||||
{
|
||||
target_ulong mask;
|
||||
#if defined(FLUSH_ALL_TLBS)
|
||||
int do_inval;
|
||||
#endif
|
||||
|
||||
dump_store_bat(env, 'I', 0, nr, value);
|
||||
if (env->IBAT[0][nr] != value) {
|
||||
#if defined(FLUSH_ALL_TLBS)
|
||||
do_inval = 0;
|
||||
#endif
|
||||
mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
|
||||
if (env->IBAT[1][nr] & 0x40) {
|
||||
/* Invalidate BAT only if it is valid */
|
||||
#if !defined(FLUSH_ALL_TLBS)
|
||||
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
|
||||
#else
|
||||
do_inval = 1;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* When storing valid upper BAT, mask BEPI and BRPN and
|
||||
* invalidate all TLBs covered by this BAT
|
||||
*/
|
||||
env->IBAT[0][nr] = (value & 0x00001FFFUL) |
|
||||
(value & ~0x0001FFFFUL & ~mask);
|
||||
env->DBAT[0][nr] = env->IBAT[0][nr];
|
||||
if (env->IBAT[1][nr] & 0x40) {
|
||||
#if !defined(FLUSH_ALL_TLBS)
|
||||
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
|
||||
#else
|
||||
do_inval = 1;
|
||||
#endif
|
||||
}
|
||||
#if defined(FLUSH_ALL_TLBS)
|
||||
if (do_inval) {
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
|
||||
{
|
||||
#if !defined(FLUSH_ALL_TLBS)
|
||||
target_ulong mask;
|
||||
#else
|
||||
int do_inval;
|
||||
#endif
|
||||
|
||||
dump_store_bat(env, 'I', 1, nr, value);
|
||||
if (env->IBAT[1][nr] != value) {
|
||||
#if defined(FLUSH_ALL_TLBS)
|
||||
do_inval = 0;
|
||||
#endif
|
||||
if (env->IBAT[1][nr] & 0x40) {
|
||||
#if !defined(FLUSH_ALL_TLBS)
|
||||
mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
|
||||
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
|
||||
#else
|
||||
do_inval = 1;
|
||||
#endif
|
||||
}
|
||||
if (value & 0x40) {
|
||||
#if !defined(FLUSH_ALL_TLBS)
|
||||
mask = (value << 17) & 0x0FFE0000UL;
|
||||
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
|
||||
#else
|
||||
do_inval = 1;
|
||||
#endif
|
||||
}
|
||||
env->IBAT[1][nr] = value;
|
||||
env->DBAT[1][nr] = value;
|
||||
#if defined(FLUSH_ALL_TLBS)
|
||||
if (do_inval) {
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* TLB management */
|
||||
void ppc_tlb_invalidate_all(CPUPPCState *env)
|
||||
@ -392,7 +310,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
|
||||
booke206_flush_tlb(env, -1, 0);
|
||||
break;
|
||||
case POWERPC_MMU_32B:
|
||||
case POWERPC_MMU_601:
|
||||
env->tlb_need_flush = 0;
|
||||
tlb_flush(env_cpu(env));
|
||||
break;
|
||||
@ -426,7 +343,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
|
||||
}
|
||||
break;
|
||||
case POWERPC_MMU_32B:
|
||||
case POWERPC_MMU_601:
|
||||
/*
|
||||
* Actual CPUs invalidate entire congruence classes based on
|
||||
* the geometry of their TLBs and some OSes take that into
|
||||
|
@ -45,8 +45,6 @@ void spr_read_tbl(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_tbu(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_atbl(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_atbu(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn);
|
||||
@ -77,12 +75,6 @@ void spr_write_dbatu_h(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_dbatl(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_dbatl_h(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_sdr1(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_601_rtcu(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_601_rtcl(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_601_ubatl(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn);
|
||||
void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn);
|
||||
void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn);
|
||||
|
@ -63,16 +63,6 @@ void helper_store_purr(CPUPPCState *env, target_ulong val)
|
||||
}
|
||||
#endif
|
||||
|
||||
target_ulong helper_load_601_rtcl(CPUPPCState *env)
|
||||
{
|
||||
return cpu_ppc601_load_rtcl(env);
|
||||
}
|
||||
|
||||
target_ulong helper_load_601_rtcu(CPUPPCState *env)
|
||||
{
|
||||
return cpu_ppc601_load_rtcu(env);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void helper_store_tbl(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
@ -94,16 +84,6 @@ void helper_store_atbu(CPUPPCState *env, target_ulong val)
|
||||
cpu_ppc_store_atbu(env, val);
|
||||
}
|
||||
|
||||
void helper_store_601_rtcl(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
cpu_ppc601_store_rtcl(env, val);
|
||||
}
|
||||
|
||||
void helper_store_601_rtcu(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
cpu_ppc601_store_rtcu(env, val);
|
||||
}
|
||||
|
||||
target_ulong helper_load_decr(CPUPPCState *env)
|
||||
{
|
||||
return cpu_ppc_load_decr(env);
|
||||
|
@ -794,61 +794,6 @@ void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* PowerPC 601 specific registers */
|
||||
/* RTC */
|
||||
void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn)
|
||||
{
|
||||
gen_helper_load_601_rtcl(cpu_gpr[gprn], cpu_env);
|
||||
}
|
||||
|
||||
void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn)
|
||||
{
|
||||
gen_helper_load_601_rtcu(cpu_gpr[gprn], cpu_env);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void spr_write_601_rtcu(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_store_601_rtcu(cpu_env, cpu_gpr[gprn]);
|
||||
}
|
||||
|
||||
void spr_write_601_rtcl(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_store_601_rtcl(cpu_env, cpu_gpr[gprn]);
|
||||
}
|
||||
|
||||
void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_store_hid0_601(cpu_env, cpu_gpr[gprn]);
|
||||
/* Must stop the translation as endianness may have changed */
|
||||
ctx->base.is_jmp = DISAS_EXIT_UPDATE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unified bats */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn)
|
||||
{
|
||||
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
|
||||
offsetof(CPUPPCState,
|
||||
IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
|
||||
}
|
||||
|
||||
void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
|
||||
gen_helper_store_601_batl(cpu_env, t0, cpu_gpr[gprn]);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
void spr_write_601_ubatl(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
|
||||
gen_helper_store_601_batu(cpu_env, t0, cpu_gpr[gprn]);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PowerPC 40x specific registers */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
|
||||
@ -5609,669 +5554,6 @@ static void gen_ecowx(DisasContext *ctx)
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
/* PowerPC 601 specific instructions */
|
||||
|
||||
/* abs - abs. */
|
||||
static void gen_abs(DisasContext *ctx)
|
||||
{
|
||||
TCGv d = cpu_gpr[rD(ctx->opcode)];
|
||||
TCGv a = cpu_gpr[rA(ctx->opcode)];
|
||||
|
||||
tcg_gen_abs_tl(d, a);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, d);
|
||||
}
|
||||
}
|
||||
|
||||
/* abso - abso. */
|
||||
static void gen_abso(DisasContext *ctx)
|
||||
{
|
||||
TCGv d = cpu_gpr[rD(ctx->opcode)];
|
||||
TCGv a = cpu_gpr[rA(ctx->opcode)];
|
||||
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_ov, a, 0x80000000);
|
||||
tcg_gen_abs_tl(d, a);
|
||||
tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, d);
|
||||
}
|
||||
}
|
||||
|
||||
/* clcs */
|
||||
static void gen_clcs(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
|
||||
gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
|
||||
tcg_temp_free_i32(t0);
|
||||
/* Rc=1 sets CR0 to an undefined state */
|
||||
}
|
||||
|
||||
/* div - div. */
|
||||
static void gen_div(DisasContext *ctx)
|
||||
{
|
||||
gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
|
||||
cpu_gpr[rB(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* divo - divo. */
|
||||
static void gen_divo(DisasContext *ctx)
|
||||
{
|
||||
gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
|
||||
cpu_gpr[rB(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* divs - divs. */
|
||||
static void gen_divs(DisasContext *ctx)
|
||||
{
|
||||
gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
|
||||
cpu_gpr[rB(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* divso - divso. */
|
||||
static void gen_divso(DisasContext *ctx)
|
||||
{
|
||||
gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
|
||||
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* doz - doz. */
|
||||
static void gen_doz(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
|
||||
cpu_gpr[rA(ctx->opcode)], l1);
|
||||
tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
|
||||
cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_br(l2);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
|
||||
gen_set_label(l2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* dozo - dozo. */
|
||||
static void gen_dozo(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
/* Start with XER OV disabled, the most likely case */
|
||||
tcg_gen_movi_tl(cpu_ov, 0);
|
||||
tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
|
||||
cpu_gpr[rA(ctx->opcode)], l1);
|
||||
tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
|
||||
tcg_gen_andc_tl(t1, t1, t2);
|
||||
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
||||
tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
|
||||
tcg_gen_movi_tl(cpu_ov, 1);
|
||||
tcg_gen_movi_tl(cpu_so, 1);
|
||||
tcg_gen_br(l2);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
|
||||
gen_set_label(l2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* dozi */
|
||||
static void gen_dozi(DisasContext *ctx)
|
||||
{
|
||||
target_long simm = SIMM(ctx->opcode);
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
|
||||
tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_br(l2);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
|
||||
gen_set_label(l2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* lscbx - lscbx. */
|
||||
static void gen_lscbx(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
|
||||
TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
|
||||
TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
|
||||
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t3);
|
||||
tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
|
||||
tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, t0);
|
||||
}
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
/* maskg - maskg. */
|
||||
static void gen_maskg(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
TCGv t3 = tcg_temp_new();
|
||||
tcg_gen_movi_tl(t3, 0xFFFFFFFF);
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
|
||||
tcg_gen_addi_tl(t2, t0, 1);
|
||||
tcg_gen_shr_tl(t2, t3, t2);
|
||||
tcg_gen_shr_tl(t3, t3, t1);
|
||||
tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
|
||||
tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
|
||||
tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||
gen_set_label(l1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
tcg_temp_free(t3);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* maskir - maskir. */
|
||||
static void gen_maskir(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
|
||||
tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* mul - mul. */
|
||||
static void gen_mul(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
|
||||
tcg_gen_mul_i64(t0, t0, t1);
|
||||
tcg_gen_trunc_i64_tl(t2, t0);
|
||||
gen_store_spr(SPR_MQ, t2);
|
||||
tcg_gen_shri_i64(t1, t0, 32);
|
||||
tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* mulo - mulo. */
|
||||
static void gen_mulo(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
/* Start with XER OV disabled, the most likely case */
|
||||
tcg_gen_movi_tl(cpu_ov, 0);
|
||||
tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
|
||||
tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
|
||||
tcg_gen_mul_i64(t0, t0, t1);
|
||||
tcg_gen_trunc_i64_tl(t2, t0);
|
||||
gen_store_spr(SPR_MQ, t2);
|
||||
tcg_gen_shri_i64(t1, t0, 32);
|
||||
tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
|
||||
tcg_gen_ext32s_i64(t1, t0);
|
||||
tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
|
||||
tcg_gen_movi_tl(cpu_ov, 1);
|
||||
tcg_gen_movi_tl(cpu_so, 1);
|
||||
gen_set_label(l1);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* nabs - nabs. */
|
||||
static void gen_nabs(DisasContext *ctx)
|
||||
{
|
||||
TCGv d = cpu_gpr[rD(ctx->opcode)];
|
||||
TCGv a = cpu_gpr[rA(ctx->opcode)];
|
||||
|
||||
tcg_gen_abs_tl(d, a);
|
||||
tcg_gen_neg_tl(d, d);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, d);
|
||||
}
|
||||
}
|
||||
|
||||
/* nabso - nabso. */
|
||||
static void gen_nabso(DisasContext *ctx)
|
||||
{
|
||||
TCGv d = cpu_gpr[rD(ctx->opcode)];
|
||||
TCGv a = cpu_gpr[rA(ctx->opcode)];
|
||||
|
||||
tcg_gen_abs_tl(d, a);
|
||||
tcg_gen_neg_tl(d, d);
|
||||
/* nabs never overflows */
|
||||
tcg_gen_movi_tl(cpu_ov, 0);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, d);
|
||||
}
|
||||
}
|
||||
|
||||
/* rlmi - rlmi. */
|
||||
static void gen_rlmi(DisasContext *ctx)
|
||||
{
|
||||
uint32_t mb = MB(ctx->opcode);
|
||||
uint32_t me = ME(ctx->opcode);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
|
||||
tcg_gen_andi_tl(t0, t0, MASK(mb, me));
|
||||
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
|
||||
~MASK(mb, me));
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
|
||||
tcg_temp_free(t0);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* rrib - rrib. */
|
||||
static void gen_rrib(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_movi_tl(t1, 0x80000000);
|
||||
tcg_gen_shr_tl(t1, t1, t0);
|
||||
tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
|
||||
tcg_gen_and_tl(t0, t0, t1);
|
||||
tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sle - sle. */
|
||||
static void gen_sle(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_subfi_tl(t1, 32, t1);
|
||||
tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sleq - sleq. */
|
||||
static void gen_sleq(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_movi_tl(t2, 0xFFFFFFFF);
|
||||
tcg_gen_shl_tl(t2, t2, t0);
|
||||
tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
|
||||
gen_load_spr(t1, SPR_MQ);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_and_tl(t0, t0, t2);
|
||||
tcg_gen_andc_tl(t1, t1, t2);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sliq - sliq. */
|
||||
static void gen_sliq(DisasContext *ctx)
|
||||
{
|
||||
int sh = SH(ctx->opcode);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
|
||||
tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* slliq - slliq. */
|
||||
static void gen_slliq(DisasContext *ctx)
|
||||
{
|
||||
int sh = SH(ctx->opcode);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
|
||||
gen_load_spr(t1, SPR_MQ);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
|
||||
tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sllq - sllq. */
|
||||
static void gen_sllq(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_local_new();
|
||||
TCGv t1 = tcg_temp_local_new();
|
||||
TCGv t2 = tcg_temp_local_new();
|
||||
tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_movi_tl(t1, 0xFFFFFFFF);
|
||||
tcg_gen_shl_tl(t1, t1, t2);
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
|
||||
gen_load_spr(t0, SPR_MQ);
|
||||
tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_gen_br(l2);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
|
||||
gen_load_spr(t2, SPR_MQ);
|
||||
tcg_gen_andc_tl(t1, t2, t1);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
gen_set_label(l2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* slq - slq. */
|
||||
static void gen_slq(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_subfi_tl(t1, 32, t1);
|
||||
tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
|
||||
tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
|
||||
gen_set_label(l1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sraiq - sraiq. */
|
||||
static void gen_sraiq(DisasContext *ctx)
|
||||
{
|
||||
int sh = SH(ctx->opcode);
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
|
||||
tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
|
||||
tcg_gen_or_tl(t0, t0, t1);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_movi_tl(cpu_ca, 0);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
|
||||
tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
|
||||
tcg_gen_movi_tl(cpu_ca, 1);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sraq - sraq. */
|
||||
static void gen_sraq(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_local_new();
|
||||
TCGv t2 = tcg_temp_local_new();
|
||||
tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
|
||||
tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
|
||||
tcg_gen_subfi_tl(t2, 32, t2);
|
||||
tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
|
||||
tcg_gen_or_tl(t0, t0, t2);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
|
||||
tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
|
||||
tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
|
||||
gen_set_label(l1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
|
||||
tcg_gen_movi_tl(cpu_ca, 0);
|
||||
tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
|
||||
tcg_gen_movi_tl(cpu_ca, 1);
|
||||
gen_set_label(l2);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sre - sre. */
|
||||
static void gen_sre(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_subfi_tl(t1, 32, t1);
|
||||
tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* srea - srea. */
|
||||
static void gen_srea(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sreq */
|
||||
static void gen_sreq(DisasContext *ctx)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_movi_tl(t1, 0xFFFFFFFF);
|
||||
tcg_gen_shr_tl(t1, t1, t0);
|
||||
tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
|
||||
gen_load_spr(t2, SPR_MQ);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_and_tl(t0, t0, t1);
|
||||
tcg_gen_andc_tl(t2, t2, t1);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sriq */
|
||||
static void gen_sriq(DisasContext *ctx)
|
||||
{
|
||||
int sh = SH(ctx->opcode);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
|
||||
tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* srliq */
|
||||
static void gen_srliq(DisasContext *ctx)
|
||||
{
|
||||
int sh = SH(ctx->opcode);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
|
||||
gen_load_spr(t1, SPR_MQ);
|
||||
gen_store_spr(SPR_MQ, t0);
|
||||
tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
|
||||
tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* srlq */
|
||||
static void gen_srlq(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_local_new();
|
||||
TCGv t1 = tcg_temp_local_new();
|
||||
TCGv t2 = tcg_temp_local_new();
|
||||
tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_movi_tl(t1, 0xFFFFFFFF);
|
||||
tcg_gen_shr_tl(t2, t1, t2);
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
|
||||
gen_load_spr(t0, SPR_MQ);
|
||||
tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
|
||||
tcg_gen_br(l2);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
|
||||
tcg_gen_and_tl(t0, t0, t2);
|
||||
gen_load_spr(t1, SPR_MQ);
|
||||
tcg_gen_andc_tl(t1, t1, t2);
|
||||
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
|
||||
gen_set_label(l2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* srq */
|
||||
static void gen_srq(DisasContext *ctx)
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
|
||||
tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_subfi_tl(t1, 32, t1);
|
||||
tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
|
||||
tcg_gen_or_tl(t1, t0, t1);
|
||||
gen_store_spr(SPR_MQ, t1);
|
||||
tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
|
||||
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
|
||||
tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
|
||||
gen_set_label(l1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 602 - 603 - G2 TLB management */
|
||||
|
||||
/* tlbld */
|
||||
@ -6296,81 +5578,6 @@ static void gen_tlbli_6xx(DisasContext *ctx)
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
}
|
||||
|
||||
/* POWER instructions not in PowerPC 601 */
|
||||
|
||||
/* clf */
|
||||
static void gen_clf(DisasContext *ctx)
|
||||
{
|
||||
/* Cache line flush: implemented as no-op */
|
||||
}
|
||||
|
||||
/* cli */
|
||||
static void gen_cli(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
GEN_PRIV;
|
||||
#else
|
||||
/* Cache line invalidate: privileged and treated as no-op */
|
||||
CHK_SV;
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
}
|
||||
|
||||
/* dclst */
|
||||
static void gen_dclst(DisasContext *ctx)
|
||||
{
|
||||
/* Data cache line store: treated as no-op */
|
||||
}
|
||||
|
||||
static void gen_mfsri(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
GEN_PRIV;
|
||||
#else
|
||||
int ra = rA(ctx->opcode);
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0;
|
||||
|
||||
CHK_SV;
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
tcg_gen_extract_tl(t0, t0, 28, 4);
|
||||
gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
|
||||
tcg_temp_free(t0);
|
||||
if (ra != 0 && ra != rd) {
|
||||
tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
|
||||
}
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
}
|
||||
|
||||
static void gen_rac(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
GEN_PRIV;
|
||||
#else
|
||||
TCGv t0;
|
||||
|
||||
CHK_SV;
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
|
||||
tcg_temp_free(t0);
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
}
|
||||
|
||||
static void gen_rfsvc(DisasContext *ctx)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
GEN_PRIV;
|
||||
#else
|
||||
CHK_SV;
|
||||
|
||||
gen_helper_rfsvc(cpu_env);
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
}
|
||||
|
||||
/* svc is not implemented for now */
|
||||
|
||||
/* BookE specific instructions */
|
||||
|
||||
/* XXX: not implemented on 440 ? */
|
||||
@ -7718,56 +6925,8 @@ GEN_HANDLER_E(slbsync, 0x1F, 0x12, 0x0A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
|
||||
#endif
|
||||
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
|
||||
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
|
||||
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
|
||||
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
|
||||
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
|
||||
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
|
||||
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
|
||||
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
|
||||
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
|
||||
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
|
||||
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
|
||||
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
|
||||
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
|
||||
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
|
||||
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
|
||||
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
|
||||
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
|
||||
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
|
||||
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
|
||||
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
|
||||
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
|
||||
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
|
||||
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
|
||||
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
|
||||
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
|
||||
@ -8463,7 +7622,6 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||
ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
|
||||
#endif
|
||||
ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
|
||||
|| env->mmu_model == POWERPC_MMU_601
|
||||
|| env->mmu_model & POWERPC_MMU_64;
|
||||
|
||||
ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1;
|
||||
|
@ -1105,185 +1105,6 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
|
||||
/* stfiwx */
|
||||
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
|
||||
|
||||
/* POWER2 specific instructions */
|
||||
/* Quad manipulation (load/store two floats at a time) */
|
||||
|
||||
/* lfq */
|
||||
static void gen_lfq(DisasContext *ctx)
|
||||
{
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0;
|
||||
TCGv_i64 t1;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new_i64();
|
||||
gen_addr_imm_index(ctx, t0, 0);
|
||||
gen_qemu_ld64_i64(ctx, t1, t0);
|
||||
set_fpr(rd, t1);
|
||||
gen_addr_add(ctx, t0, t0, 8);
|
||||
gen_qemu_ld64_i64(ctx, t1, t0);
|
||||
set_fpr((rd + 1) % 32, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
/* lfqu */
|
||||
static void gen_lfqu(DisasContext *ctx)
|
||||
{
|
||||
int ra = rA(ctx->opcode);
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0, t1;
|
||||
TCGv_i64 t2;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new();
|
||||
t2 = tcg_temp_new_i64();
|
||||
gen_addr_imm_index(ctx, t0, 0);
|
||||
gen_qemu_ld64_i64(ctx, t2, t0);
|
||||
set_fpr(rd, t2);
|
||||
gen_addr_add(ctx, t1, t0, 8);
|
||||
gen_qemu_ld64_i64(ctx, t2, t1);
|
||||
set_fpr((rd + 1) % 32, t2);
|
||||
if (ra != 0) {
|
||||
tcg_gen_mov_tl(cpu_gpr[ra], t0);
|
||||
}
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
|
||||
/* lfqux */
|
||||
static void gen_lfqux(DisasContext *ctx)
|
||||
{
|
||||
int ra = rA(ctx->opcode);
|
||||
int rd = rD(ctx->opcode);
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
TCGv t0, t1;
|
||||
TCGv_i64 t2;
|
||||
t2 = tcg_temp_new_i64();
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
gen_qemu_ld64_i64(ctx, t2, t0);
|
||||
set_fpr(rd, t2);
|
||||
t1 = tcg_temp_new();
|
||||
gen_addr_add(ctx, t1, t0, 8);
|
||||
gen_qemu_ld64_i64(ctx, t2, t1);
|
||||
set_fpr((rd + 1) % 32, t2);
|
||||
tcg_temp_free(t1);
|
||||
if (ra != 0) {
|
||||
tcg_gen_mov_tl(cpu_gpr[ra], t0);
|
||||
}
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
|
||||
/* lfqx */
|
||||
static void gen_lfqx(DisasContext *ctx)
|
||||
{
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0;
|
||||
TCGv_i64 t1;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new_i64();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
gen_qemu_ld64_i64(ctx, t1, t0);
|
||||
set_fpr(rd, t1);
|
||||
gen_addr_add(ctx, t0, t0, 8);
|
||||
gen_qemu_ld64_i64(ctx, t1, t0);
|
||||
set_fpr((rd + 1) % 32, t1);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
/* stfq */
|
||||
static void gen_stfq(DisasContext *ctx)
|
||||
{
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0;
|
||||
TCGv_i64 t1;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t0 = tcg_temp_new();
|
||||
t1 = tcg_temp_new_i64();
|
||||
gen_addr_imm_index(ctx, t0, 0);
|
||||
get_fpr(t1, rd);
|
||||
gen_qemu_st64_i64(ctx, t1, t0);
|
||||
gen_addr_add(ctx, t0, t0, 8);
|
||||
get_fpr(t1, (rd + 1) % 32);
|
||||
gen_qemu_st64_i64(ctx, t1, t0);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
/* stfqu */
|
||||
static void gen_stfqu(DisasContext *ctx)
|
||||
{
|
||||
int ra = rA(ctx->opcode);
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0, t1;
|
||||
TCGv_i64 t2;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t2 = tcg_temp_new_i64();
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_imm_index(ctx, t0, 0);
|
||||
get_fpr(t2, rd);
|
||||
gen_qemu_st64_i64(ctx, t2, t0);
|
||||
t1 = tcg_temp_new();
|
||||
gen_addr_add(ctx, t1, t0, 8);
|
||||
get_fpr(t2, (rd + 1) % 32);
|
||||
gen_qemu_st64_i64(ctx, t2, t1);
|
||||
tcg_temp_free(t1);
|
||||
if (ra != 0) {
|
||||
tcg_gen_mov_tl(cpu_gpr[ra], t0);
|
||||
}
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
|
||||
/* stfqux */
|
||||
static void gen_stfqux(DisasContext *ctx)
|
||||
{
|
||||
int ra = rA(ctx->opcode);
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0, t1;
|
||||
TCGv_i64 t2;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t2 = tcg_temp_new_i64();
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
get_fpr(t2, rd);
|
||||
gen_qemu_st64_i64(ctx, t2, t0);
|
||||
t1 = tcg_temp_new();
|
||||
gen_addr_add(ctx, t1, t0, 8);
|
||||
get_fpr(t2, (rd + 1) % 32);
|
||||
gen_qemu_st64_i64(ctx, t2, t1);
|
||||
tcg_temp_free(t1);
|
||||
if (ra != 0) {
|
||||
tcg_gen_mov_tl(cpu_gpr[ra], t0);
|
||||
}
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
|
||||
/* stfqx */
|
||||
static void gen_stfqx(DisasContext *ctx)
|
||||
{
|
||||
int rd = rD(ctx->opcode);
|
||||
TCGv t0;
|
||||
TCGv_i64 t1;
|
||||
gen_set_access_type(ctx, ACCESS_FLOAT);
|
||||
t1 = tcg_temp_new_i64();
|
||||
t0 = tcg_temp_new();
|
||||
gen_addr_reg_index(ctx, t0);
|
||||
get_fpr(t1, rd);
|
||||
gen_qemu_st64_i64(ctx, t1, t0);
|
||||
gen_addr_add(ctx, t0, t0, 8);
|
||||
get_fpr(t1, (rd + 1) % 32);
|
||||
gen_qemu_st64_i64(ctx, t1, t0);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
/* Floating-point Load/Store Instructions */
|
||||
static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
|
||||
bool update, bool store, bool single)
|
||||
|
Loading…
Reference in New Issue
Block a user