2662a059aa
Check that at least instructions set and SPRs are correct for PowerPC 401, 403, 405 and 440 cores. Implement PowerPC 401 MMU model (real-mode only). Improve INSNs and SPRs dump to ease parse with standard shell tools. Add more precise status for most PowerPC cores families. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3201 c046a42c-6fe2-441c-8c8c-71466251a162
4384 lines
138 KiB
C
4384 lines
138 KiB
C
/*
|
|
* PowerPC CPU initialization for qemu.
|
|
*
|
|
* Copyright (c) 2003-2007 Jocelyn Mayer
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/* A lot of PowerPC definition have been included here.
|
|
* Most of them are not usable for now but have been kept
|
|
* inside "#if defined(TODO) ... #endif" statements to make tests easier.
|
|
*/
|
|
|
|
//#define PPC_DUMP_CPU
|
|
//#define PPC_DEBUG_SPR
|
|
//#define PPC_DEBUG_IRQ
|
|
|
|
struct ppc_def_t {
|
|
const unsigned char *name;
|
|
uint32_t pvr;
|
|
uint32_t pvr_mask;
|
|
uint64_t insns_flags;
|
|
uint32_t flags;
|
|
uint64_t msr_mask;
|
|
};
|
|
|
|
/* For user-mode emulation, we don't emulate any IRQ controller */
|
|
#if defined(CONFIG_USER_ONLY)
|
|
#define PPC_IRQ_INIT_FN(name) \
|
|
static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \
|
|
{ \
|
|
}
|
|
#else
|
|
#define PPC_IRQ_INIT_FN(name) \
|
|
void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
|
|
#endif
|
|
PPC_IRQ_INIT_FN(405);
|
|
PPC_IRQ_INIT_FN(6xx);
|
|
PPC_IRQ_INIT_FN(970);
|
|
|
|
/* Generic callbacks:
|
|
* do nothing but store/retrieve spr value
|
|
*/
|
|
#ifdef PPC_DUMP_SPR_ACCESSES
|
|
static void spr_read_generic (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_dump_spr(sprn);
|
|
}
|
|
|
|
static void spr_write_generic (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_dump_spr(sprn);
|
|
}
|
|
#else
|
|
static void spr_read_generic (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_spr(sprn);
|
|
}
|
|
|
|
static void spr_write_generic (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_spr(sprn);
|
|
}
|
|
#endif
|
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_write_clear (void *opaque, int sprn)
|
|
{
|
|
gen_op_mask_spr(sprn);
|
|
}
|
|
#endif
|
|
|
|
/* SPR common to all PowerPC */
|
|
/* XER */
|
|
static void spr_read_xer (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_xer();
|
|
}
|
|
|
|
static void spr_write_xer (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_xer();
|
|
}
|
|
|
|
/* LR */
|
|
static void spr_read_lr (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_lr();
|
|
}
|
|
|
|
static void spr_write_lr (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_lr();
|
|
}
|
|
|
|
/* CTR */
|
|
static void spr_read_ctr (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_ctr();
|
|
}
|
|
|
|
static void spr_write_ctr (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_ctr();
|
|
}
|
|
|
|
/* User read access to SPR */
|
|
/* USPRx */
|
|
/* UMMCRx */
|
|
/* UPMCx */
|
|
/* USIA */
|
|
/* UDECR */
|
|
static void spr_read_ureg (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_spr(sprn + 0x10);
|
|
}
|
|
|
|
/* SPR common to all non-embedded PowerPC */
|
|
/* DECR */
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_read_decr (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_decr();
|
|
}
|
|
|
|
static void spr_write_decr (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_decr();
|
|
}
|
|
#endif
|
|
|
|
/* SPR common to all non-embedded PowerPC, except 601 */
|
|
/* Time base */
|
|
static void spr_read_tbl (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_tbl();
|
|
}
|
|
|
|
static void spr_read_tbu (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_tbu();
|
|
}
|
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_write_tbl (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_tbl();
|
|
}
|
|
|
|
static void spr_write_tbu (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_tbu();
|
|
}
|
|
#endif
|
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
/* IBAT0U...IBAT0U */
|
|
/* IBAT0L...IBAT7L */
|
|
static void spr_read_ibat (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
|
|
}
|
|
|
|
static void spr_read_ibat_h (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT4U) / 2);
|
|
}
|
|
|
|
static void spr_write_ibatu (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_ibatu_h (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_ibatl (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_ibatl_h (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
/* DBAT0U...DBAT7U */
|
|
/* DBAT0L...DBAT7L */
|
|
static void spr_read_dbat (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT0U) / 2);
|
|
}
|
|
|
|
static void spr_read_dbat_h (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT4U) / 2);
|
|
}
|
|
|
|
static void spr_write_dbatu (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_dbatu_h (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_dbatl (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_dbatl_h (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
/* SDR1 */
|
|
static void spr_read_sdr1 (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_sdr1();
|
|
}
|
|
|
|
static void spr_write_sdr1 (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_sdr1();
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
/* 64 bits PowerPC specific SPRs */
|
|
/* ASR */
|
|
/* Currently unused */
|
|
#if 0 && defined(TARGET_PPC64)
|
|
static void spr_read_asr (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_asr();
|
|
}
|
|
|
|
static void spr_write_asr (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_asr();
|
|
RET_STOP(ctx);
|
|
}
|
|
#endif
|
|
#endif /* !defined(CONFIG_USER_ONLY) */
|
|
|
|
/* PowerPC 601 specific registers */
|
|
/* RTC */
|
|
static void spr_read_601_rtcl (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_601_rtcl();
|
|
}
|
|
|
|
static void spr_read_601_rtcu (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_601_rtcu();
|
|
}
|
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_write_601_rtcu (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_601_rtcu();
|
|
}
|
|
|
|
static void spr_write_601_rtcl (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_601_rtcl();
|
|
}
|
|
#endif
|
|
|
|
/* Unified bats */
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_read_601_ubat (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_601_bat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
|
|
}
|
|
|
|
static void spr_write_601_ubatu (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_601_ubatl (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2);
|
|
RET_STOP(ctx);
|
|
}
|
|
#endif
|
|
|
|
/* PowerPC 40x specific registers */
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_read_40x_pit (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_40x_pit();
|
|
}
|
|
|
|
static void spr_write_40x_pit (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_40x_pit();
|
|
}
|
|
|
|
static void spr_write_40x_dbcr0 (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_40x_dbcr0();
|
|
/* We must stop translation as we may have rebooted */
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_40x_sler (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_40x_sler();
|
|
/* We must stop the translation as we may have changed
|
|
* some regions endianness
|
|
*/
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_booke_tcr (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_booke_tcr();
|
|
}
|
|
|
|
static void spr_write_booke_tsr (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_booke_tsr();
|
|
}
|
|
#endif
|
|
|
|
/* PowerPC 403 specific registers */
|
|
/* PBL1 / PBU1 / PBL2 / PBU2 */
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
static void spr_read_403_pbr (void *opaque, int sprn)
|
|
{
|
|
gen_op_load_403_pb(sprn - SPR_403_PBL1);
|
|
}
|
|
|
|
static void spr_write_403_pbr (void *opaque, int sprn)
|
|
{
|
|
DisasContext *ctx = opaque;
|
|
|
|
gen_op_store_403_pb(sprn - SPR_403_PBL1);
|
|
RET_STOP(ctx);
|
|
}
|
|
|
|
static void spr_write_pir (void *opaque, int sprn)
|
|
{
|
|
gen_op_store_pir();
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_USER_ONLY)
|
|
#define spr_register(env, num, name, uea_read, uea_write, \
|
|
oea_read, oea_write, initial_value) \
|
|
do { \
|
|
_spr_register(env, num, name, uea_read, uea_write, initial_value); \
|
|
} while (0)
|
|
static inline void _spr_register (CPUPPCState *env, int num,
|
|
const unsigned char *name,
|
|
void (*uea_read)(void *opaque, int sprn),
|
|
void (*uea_write)(void *opaque, int sprn),
|
|
target_ulong initial_value)
|
|
#else
|
|
static inline void spr_register (CPUPPCState *env, int num,
|
|
const unsigned char *name,
|
|
void (*uea_read)(void *opaque, int sprn),
|
|
void (*uea_write)(void *opaque, int sprn),
|
|
void (*oea_read)(void *opaque, int sprn),
|
|
void (*oea_write)(void *opaque, int sprn),
|
|
target_ulong initial_value)
|
|
#endif
|
|
{
|
|
ppc_spr_t *spr;
|
|
|
|
spr = &env->spr_cb[num];
|
|
if (spr->name != NULL ||env-> spr[num] != 0x00000000 ||
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
spr->oea_read != NULL || spr->oea_write != NULL ||
|
|
#endif
|
|
spr->uea_read != NULL || spr->uea_write != NULL) {
|
|
printf("Error: Trying to register SPR %d (%03x) twice !\n", num, num);
|
|
exit(1);
|
|
}
|
|
#if defined(PPC_DEBUG_SPR)
|
|
printf("*** register spr %d (%03x) %s val " ADDRX "\n", num, num, name,
|
|
initial_value);
|
|
#endif
|
|
spr->name = name;
|
|
spr->uea_read = uea_read;
|
|
spr->uea_write = uea_write;
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
spr->oea_read = oea_read;
|
|
spr->oea_write = oea_write;
|
|
#endif
|
|
env->spr[num] = initial_value;
|
|
}
|
|
|
|
/* Generic PowerPC SPRs */
|
|
static void gen_spr_generic (CPUPPCState *env)
|
|
{
|
|
/* Integer processing */
|
|
spr_register(env, SPR_XER, "XER",
|
|
&spr_read_xer, &spr_write_xer,
|
|
&spr_read_xer, &spr_write_xer,
|
|
0x00000000);
|
|
/* Branch contol */
|
|
spr_register(env, SPR_LR, "LR",
|
|
&spr_read_lr, &spr_write_lr,
|
|
&spr_read_lr, &spr_write_lr,
|
|
0x00000000);
|
|
spr_register(env, SPR_CTR, "CTR",
|
|
&spr_read_ctr, &spr_write_ctr,
|
|
&spr_read_ctr, &spr_write_ctr,
|
|
0x00000000);
|
|
/* Interrupt processing */
|
|
spr_register(env, SPR_SRR0, "SRR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SRR1, "SRR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Processor control */
|
|
spr_register(env, SPR_SPRG0, "SPRG0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG1, "SPRG1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG2, "SPRG2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG3, "SPRG3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR common to all non-embedded PowerPC, including 601 */
|
|
static void gen_spr_ne_601 (CPUPPCState *env)
|
|
{
|
|
/* Exception processing */
|
|
spr_register(env, SPR_DSISR, "DSISR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_DAR, "DAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Timer */
|
|
spr_register(env, SPR_DECR, "DECR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_decr, &spr_write_decr,
|
|
0x00000000);
|
|
/* Memory management */
|
|
spr_register(env, SPR_SDR1, "SDR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_sdr1, &spr_write_sdr1,
|
|
0x00000000);
|
|
}
|
|
|
|
/* BATs 0-3 */
|
|
static void gen_low_BATs (CPUPPCState *env)
|
|
{
|
|
spr_register(env, SPR_IBAT0U, "IBAT0U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT0L, "IBAT0L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT1U, "IBAT1U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT1L, "IBAT1L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT2U, "IBAT2U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT2L, "IBAT2L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT3U, "IBAT3U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT3L, "IBAT3L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat, &spr_write_ibatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT0U, "DBAT0U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT0L, "DBAT0L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT1U, "DBAT1U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT1L, "DBAT1L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT2U, "DBAT2U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT2L, "DBAT2L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatl,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT3U, "DBAT3U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatu,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT3L, "DBAT3L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat, &spr_write_dbatl,
|
|
0x00000000);
|
|
env->nb_BATs = 4;
|
|
}
|
|
|
|
/* BATs 4-7 */
|
|
static void gen_high_BATs (CPUPPCState *env)
|
|
{
|
|
spr_register(env, SPR_IBAT4U, "IBAT4U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT4L, "IBAT4L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT5U, "IBAT5U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT5L, "IBAT5L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT6U, "IBAT6U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT6L, "IBAT6L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT7U, "IBAT7U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_IBAT7L, "IBAT7L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_ibat_h, &spr_write_ibatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT4U, "DBAT4U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT4L, "DBAT4L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT5U, "DBAT5U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT5L, "DBAT5L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT6U, "DBAT6U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT6L, "DBAT6L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatl_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT7U, "DBAT7U",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatu_h,
|
|
0x00000000);
|
|
spr_register(env, SPR_DBAT7L, "DBAT7L",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_dbat_h, &spr_write_dbatl_h,
|
|
0x00000000);
|
|
env->nb_BATs = 8;
|
|
}
|
|
|
|
/* Generic PowerPC time base */
|
|
static void gen_tbl (CPUPPCState *env)
|
|
{
|
|
spr_register(env, SPR_VTBL, "TBL",
|
|
&spr_read_tbl, SPR_NOACCESS,
|
|
&spr_read_tbl, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_TBL, "TBL",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
SPR_NOACCESS, &spr_write_tbl,
|
|
0x00000000);
|
|
spr_register(env, SPR_VTBU, "TBU",
|
|
&spr_read_tbu, SPR_NOACCESS,
|
|
&spr_read_tbu, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_TBU, "TBU",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
SPR_NOACCESS, &spr_write_tbu,
|
|
0x00000000);
|
|
}
|
|
|
|
/* Softare table search registers */
|
|
static void gen_6xx_7xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
|
|
{
|
|
env->nb_tlb = nb_tlbs;
|
|
env->nb_ways = nb_ways;
|
|
env->id_tlbs = 1;
|
|
spr_register(env, SPR_DMISS, "DMISS",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_DCMP, "DCMP",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_HASH1, "HASH1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_HASH2, "HASH2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_IMISS, "IMISS",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_ICMP, "ICMP",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_RPA, "RPA",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR common to MPC755 and G2 */
|
|
static void gen_spr_G2_755 (CPUPPCState *env)
|
|
{
|
|
/* SGPRs */
|
|
spr_register(env, SPR_SPRG4, "SPRG4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG5, "SPRG5",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG6, "SPRG6",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG7, "SPRG7",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* External access control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_EAR, "EAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR common to all 7xx PowerPC implementations */
|
|
static void gen_spr_7xx (CPUPPCState *env)
|
|
{
|
|
/* Breakpoints */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_DABR, "DABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_IABR, "IABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Cache management */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_ICTC, "ICTC",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_L2CR, "L2CR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Performance monitors */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_MMCR0, "MMCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_MMCR1, "MMCR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC1, "PMC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC2, "PMC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC3, "PMC3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC4, "PMC4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SIA, "SIA",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UMMCR0, "UMMCR0",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UMMCR1, "UMMCR1",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UPMC1, "UPMC1",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UPMC2, "UPMC2",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UPMC3, "UPMC3",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_UPMC4, "UPMC4",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_USIA, "USIA",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* Thermal management */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_THRM1, "THRM1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_THRM2, "THRM2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_THRM3, "THRM3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* External access control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_EAR, "EAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 604 implementation */
|
|
static void gen_spr_604 (CPUPPCState *env)
|
|
{
|
|
/* Processor identification */
|
|
spr_register(env, SPR_PIR, "PIR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_pir,
|
|
0x00000000);
|
|
/* Breakpoints */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_IABR, "IABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_DABR, "DABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Performance counters */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_MMCR0, "MMCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_MMCR1, "MMCR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC1, "PMC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC2, "PMC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC3, "PMC3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_PMC4, "PMC4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SIA, "SIA",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SDA, "SDA",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* External access control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_EAR, "EAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 603 implementation */
|
|
static void gen_spr_603 (CPUPPCState *env)
|
|
{
|
|
/* External access control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_EAR, "EAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC G2 implementation */
|
|
static void gen_spr_G2 (CPUPPCState *env)
|
|
{
|
|
/* Memory base address */
|
|
/* MBAR */
|
|
spr_register(env, SPR_MBAR, "MBAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* System version register */
|
|
/* SVR */
|
|
spr_register(env, SPR_SVR, "SVR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* Exception processing */
|
|
spr_register(env, SPR_BOOKE_CSRR0, "CSRR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_CSRR1, "CSRR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Breakpoints */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_DABR, "DABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_DABR2, "DABR2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_IABR, "IABR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_IABR2, "IABR2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_IBCR, "IBCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_DBCR, "DBCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 602 implementation */
|
|
static void gen_spr_602 (CPUPPCState *env)
|
|
{
|
|
/* ESA registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SER, "SER",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SEBR, "SEBR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_ESASR, "ESASR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Floating point status */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_SP, "SP",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_LT, "LT",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Watchdog timer */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_TCR, "TCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Interrupt base */
|
|
spr_register(env, SPR_IBR, "IBR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 601 implementation */
|
|
static void gen_spr_601 (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 */
|
|
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);
|
|
}
|
|
|
|
/* PowerPC BookE SPR */
|
|
static void gen_spr_BookE (CPUPPCState *env)
|
|
{
|
|
/* Processor identification */
|
|
spr_register(env, SPR_BOOKE_PIR, "PIR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_pir,
|
|
0x00000000);
|
|
/* Interrupt processing */
|
|
spr_register(env, SPR_BOOKE_CSRR0, "CSRR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_CSRR1, "CSRR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
#if 0
|
|
spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_DSRR1, "DSRR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
#endif
|
|
/* Debug */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_IAC1, "IAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_IAC2, "IAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_IAC3, "IAC3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_IAC4, "IAC4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DAC1, "DAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DAC2, "DAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DVC1, "DVC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DVC2, "DVC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DBCR0, "DBCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DBCR1, "DBCR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DBCR2, "DBCR2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DBSR, "DBSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_clear,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_DEAR, "DEAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_ESR, "ESR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVPR, "IVPR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Exception vectors */
|
|
spr_register(env, SPR_BOOKE_IVOR0, "IVOR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR1, "IVOR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR2, "IVOR2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR3, "IVOR3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR4, "IVOR4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR5, "IVOR5",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR6, "IVOR6",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR7, "IVOR7",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR8, "IVOR8",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR9, "IVOR9",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR10, "IVOR10",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR11, "IVOR11",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR12, "IVOR12",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR13, "IVOR13",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR14, "IVOR14",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR15, "IVOR15",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
#if 0
|
|
spr_register(env, SPR_BOOKE_IVOR32, "IVOR32",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR33, "IVOR33",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR34, "IVOR34",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR35, "IVOR35",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR36, "IVOR36",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_IVOR37, "IVOR37",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
#endif
|
|
spr_register(env, SPR_BOOKE_PID, "PID",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_TCR, "TCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_booke_tcr,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_TSR, "TSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_booke_tsr,
|
|
0x00000000);
|
|
/* Timer */
|
|
spr_register(env, SPR_DECR, "DECR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_decr, &spr_write_decr,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_DECAR, "DECAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
SPR_NOACCESS, &spr_write_generic,
|
|
0x00000000);
|
|
/* SPRGs */
|
|
spr_register(env, SPR_USPRG0, "USPRG0",
|
|
&spr_read_generic, &spr_write_generic,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG4, "SPRG4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG4, "USPRG4",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG5, "SPRG5",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG5, "USPRG5",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG6, "SPRG6",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG6, "USPRG6",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG7, "SPRG7",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG7, "USPRG7",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
}
|
|
|
|
/* FSL storage control registers */
|
|
static void gen_spr_BookE_FSL (CPUPPCState *env)
|
|
{
|
|
/* TLB assist registers */
|
|
spr_register(env, SPR_BOOKE_MAS0, "MAS0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS1, "MAS2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS2, "MAS3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS3, "MAS4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS4, "MAS5",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS6, "MAS6",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_BOOKE_MAS7, "MAS7",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
if (env->nb_pids > 1) {
|
|
spr_register(env, SPR_BOOKE_PID1, "PID1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
if (env->nb_pids > 2) {
|
|
spr_register(env, SPR_BOOKE_PID2, "PID2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
spr_register(env, SPR_BOOKE_MMUCFG, "MMUCFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000); /* TOFIX */
|
|
spr_register(env, SPR_BOOKE_MMUCSR0, "MMUCSR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000); /* TOFIX */
|
|
switch (env->nb_ways) {
|
|
case 4:
|
|
spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000); /* TOFIX */
|
|
/* Fallthru */
|
|
case 3:
|
|
spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000); /* TOFIX */
|
|
/* Fallthru */
|
|
case 2:
|
|
spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000); /* TOFIX */
|
|
/* Fallthru */
|
|
case 1:
|
|
spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000); /* TOFIX */
|
|
/* Fallthru */
|
|
case 0:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* SPR specific to PowerPC 440 implementation */
|
|
static void gen_spr_440 (CPUPPCState *env)
|
|
{
|
|
/* Cache control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DNV0, "DNV0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DNV1, "DNV1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DNV2, "DNV2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DNV3, "DNV3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DTV0, "DTV0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DTV1, "DTV1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DTV2, "DTV2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DTV3, "DTV3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DVLIM, "DVLIM",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_INV0, "INV0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_INV1, "INV1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_INV2, "INV2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_INV3, "INV3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_ITV0, "ITV0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_ITV1, "ITV1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_ITV2, "ITV2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_ITV3, "ITV3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_IVLIM, "IVLIM",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Cache debug */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DCDBTRH, "DCDBTRH",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_DCDBTRL, "DCDBTRL",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_ICDBTRH, "ICDBTRH",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_ICDBTRL, "ICDBTRL",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_440_DBDR, "DBDR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Processor control */
|
|
spr_register(env, SPR_4xx_CCR0, "CCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_440_RSTCFG, "RSTCFG",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* Storage control */
|
|
spr_register(env, SPR_440_MMUCR, "MMUCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR shared between PowerPC 40x implementations */
|
|
static void gen_spr_40x (CPUPPCState *env)
|
|
{
|
|
/* Cache */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DCCR, "DCCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DCWR, "DCWR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_ICCR, "ICCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
0x00000000);
|
|
/* Bus access control */
|
|
spr_register(env, SPR_40x_SGR, "SGR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0xFFFFFFFF);
|
|
/* Exception */
|
|
spr_register(env, SPR_40x_DEAR, "DEAR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_ESR, "ESR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_EVPR, "EVPR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_SRR2, "SRR2",
|
|
&spr_read_generic, &spr_write_generic,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_SRR3, "SRR3",
|
|
&spr_read_generic, &spr_write_generic,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Timers */
|
|
spr_register(env, SPR_40x_PIT, "PIT",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_40x_pit, &spr_write_40x_pit,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_TCR, "TCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_booke_tcr,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_TSR, "TSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_booke_tsr,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 405 implementation */
|
|
static void gen_spr_405 (CPUPPCState *env)
|
|
{
|
|
/* MMU */
|
|
spr_register(env, SPR_40x_PID, "PID",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_4xx_CCR0, "CCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00700000);
|
|
/* Debug interface */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBCR0, "DBCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_40x_dbcr0,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_DBCR1, "DBCR1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBSR, "DBSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_clear,
|
|
/* Last reset was system reset */
|
|
0x00000300);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DAC1, "DAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_DAC2, "DAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_DVC1, "DVC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_DVC2, "DVC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_IAC1, "IAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_IAC2, "IAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_IAC3, "IAC3",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_IAC4, "IAC4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Storage control */
|
|
spr_register(env, SPR_405_SLER, "SLER",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_40x_sler,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_ZPR, "ZPR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_405_SU0R, "SU0R",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* SPRG */
|
|
spr_register(env, SPR_USPRG0, "USPRG0",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG4, "SPRG4",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG4, "USPRG4",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG5, "SPRG5",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG5, "USPRG5",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG6, "SPRG6",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG6, "USPRG6",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_SPRG7, "SPRG7",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_USPRG7, "USPRG7",
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
&spr_read_ureg, SPR_NOACCESS,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR shared between PowerPC 401 & 403 implementations */
|
|
static void gen_spr_401_403 (CPUPPCState *env)
|
|
{
|
|
/* Time base */
|
|
spr_register(env, SPR_403_VTBL, "TBL",
|
|
&spr_read_tbl, SPR_NOACCESS,
|
|
&spr_read_tbl, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_TBL, "TBL",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
SPR_NOACCESS, &spr_write_tbl,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_VTBU, "TBU",
|
|
&spr_read_tbu, SPR_NOACCESS,
|
|
&spr_read_tbu, SPR_NOACCESS,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_TBU, "TBU",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
SPR_NOACCESS, &spr_write_tbu,
|
|
0x00000000);
|
|
/* Debug */
|
|
/* XXX: not implemented */
|
|
spr_register(env, SPR_403_CDBCR, "CDBCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 401 implementation */
|
|
static void gen_spr_401 (CPUPPCState *env)
|
|
{
|
|
/* Debug interface */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBCR0, "DBCR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_40x_dbcr0,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBSR, "DBSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_clear,
|
|
/* Last reset was system reset */
|
|
0x00000300);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DAC1, "DAC",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_IAC1, "IAC",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Storage control */
|
|
spr_register(env, SPR_405_SLER, "SLER",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_40x_sler,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC 403 implementation */
|
|
static void gen_spr_403 (CPUPPCState *env)
|
|
{
|
|
/* Debug interface */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBCR0, "DBCR0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_40x_dbcr0,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DBSR, "DBSR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_clear,
|
|
/* Last reset was system reset */
|
|
0x00000300);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_DAC1, "DAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_DAC2, "DAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_40x_IAC1, "IAC1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_IAC2, "IAC2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* MMU */
|
|
spr_register(env, SPR_40x_PID, "PID",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_PBL1, "PBL1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_403_pbr, &spr_write_403_pbr,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_PBU1, "PBU1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_403_pbr, &spr_write_403_pbr,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_PBL2, "PBL2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_403_pbr, &spr_write_403_pbr,
|
|
0x00000000);
|
|
spr_register(env, SPR_403_PBU2, "PBU2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_403_pbr, &spr_write_403_pbr,
|
|
0x00000000);
|
|
spr_register(env, SPR_40x_ZPR, "ZPR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
|
|
/* SPR specific to PowerPC compression coprocessor extension */
|
|
#if defined (TODO)
|
|
static void gen_spr_compress (CPUPPCState *env)
|
|
{
|
|
spr_register(env, SPR_401_SKR, "SKR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
}
|
|
#endif
|
|
|
|
// XXX: TODO
|
|
/*
|
|
* AMR => SPR 29 (Power 2.04)
|
|
* CTRL => SPR 136 (Power 2.04)
|
|
* CTRL => SPR 152 (Power 2.04)
|
|
* VRSAVE => SPR 256 (Altivec)
|
|
* SCOMC => SPR 276 (64 bits ?)
|
|
* SCOMD => SPR 277 (64 bits ?)
|
|
* ASR => SPR 280 (64 bits)
|
|
* TBU40 => SPR 286 (Power 2.04 hypv)
|
|
* HSPRG0 => SPR 304 (Power 2.04 hypv)
|
|
* HSPRG1 => SPR 305 (Power 2.04 hypv)
|
|
* HDSISR => SPR 306 (Power 2.04 hypv)
|
|
* HDAR => SPR 307 (Power 2.04 hypv)
|
|
* PURR => SPR 309 (Power 2.04 hypv)
|
|
* HDEC => SPR 310 (Power 2.04 hypv)
|
|
* HIOR => SPR 311 (hypv)
|
|
* RMOR => SPR 312 (970)
|
|
* HRMOR => SPR 313 (Power 2.04 hypv)
|
|
* HSRR0 => SPR 314 (Power 2.04 hypv)
|
|
* HSRR1 => SPR 315 (Power 2.04 hypv)
|
|
* LPCR => SPR 316 (970)
|
|
* LPIDR => SPR 317 (970)
|
|
* SPEFSCR => SPR 512 (Power 2.04 emb)
|
|
* ATBL => SPR 526 (Power 2.04 emb)
|
|
* ATBU => SPR 527 (Power 2.04 emb)
|
|
* EPR => SPR 702 (Power 2.04 emb)
|
|
* perf => 768-783 (Power 2.04)
|
|
* perf => 784-799 (Power 2.04)
|
|
* PPR => SPR 896 (Power 2.04)
|
|
* EPLC => SPR 947 (Power 2.04 emb)
|
|
* EPSC => SPR 948 (Power 2.04 emb)
|
|
* DABRX => 1015 (Power 2.04 hypv)
|
|
* FPECR => SPR 1022 (?)
|
|
* ... and more (thermal management, performance counters, ...)
|
|
*/
|
|
|
|
static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
|
|
{
|
|
env->reserve = -1;
|
|
/* Default MMU definitions */
|
|
env->nb_BATs = -1;
|
|
env->nb_tlb = 0;
|
|
env->nb_ways = 0;
|
|
/* XXX: missing:
|
|
* 32 bits PowerPC:
|
|
* - MPC5xx(x)
|
|
* - MPC8xx(x)
|
|
* - RCPU (same as MPC5xx ?)
|
|
*/
|
|
spr_register(env, SPR_PVR, "PVR",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, SPR_NOACCESS,
|
|
def->pvr);
|
|
printf("%s: PVR %08x mask %08x => %08x\n", __func__,
|
|
def->pvr, def->pvr_mask, def->pvr & def->pvr_mask);
|
|
switch (def->pvr) {
|
|
/* Embedded PowerPC from IBM */
|
|
case CPU_PPC_401A1: /* 401 A1 family */
|
|
case CPU_PPC_401B2: /* 401 B2 family */
|
|
#if 0
|
|
case CPU_PPC_401B3: /* 401 B3 family */
|
|
#endif
|
|
case CPU_PPC_401C2: /* 401 C2 family */
|
|
case CPU_PPC_401D2: /* 401 D2 family */
|
|
case CPU_PPC_401E2: /* 401 E2 family */
|
|
case CPU_PPC_401F2: /* 401 F2 family */
|
|
case CPU_PPC_401G2: /* 401 G2 family */
|
|
case CPU_PPC_IOP480: /* IOP 480 family */
|
|
case CPU_PPC_COBRA: /* IBM Processor for Network Resources */
|
|
gen_spr_generic(env);
|
|
gen_spr_40x(env);
|
|
gen_spr_401_403(env);
|
|
gen_spr_401(env);
|
|
#if defined (TODO)
|
|
/* XXX: optional ? */
|
|
gen_spr_compress(env);
|
|
#endif
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
|
|
case CPU_PPC_403GA: /* 403 GA family */
|
|
case CPU_PPC_403GB: /* 403 GB family */
|
|
case CPU_PPC_403GC: /* 403 GC family */
|
|
case CPU_PPC_403GCX: /* 403 GCX family */
|
|
gen_spr_generic(env);
|
|
gen_spr_40x(env);
|
|
gen_spr_401_403(env);
|
|
gen_spr_403(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
|
|
case CPU_PPC_405CR: /* 405 GP/CR family */
|
|
case CPU_PPC_405EP: /* 405 EP family */
|
|
case CPU_PPC_405GPR: /* 405 GPR family */
|
|
case CPU_PPC_405D2: /* 405 D2 family */
|
|
case CPU_PPC_405D4: /* 405 D4 family */
|
|
gen_spr_generic(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_40x(env);
|
|
gen_spr_405(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* Allocate hardware IRQ controller */
|
|
ppc405_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_NPE405H: /* NPe405 H family */
|
|
case CPU_PPC_NPE405H2:
|
|
case CPU_PPC_NPE405L: /* Npe405 L family */
|
|
gen_spr_generic(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_40x(env);
|
|
gen_spr_405(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* Allocate hardware IRQ controller */
|
|
ppc405_irq_init(env);
|
|
break;
|
|
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB01000:
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB01010:
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB0210:
|
|
#endif
|
|
case CPU_PPC_STB03: /* STB03 family */
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB043: /* STB043 family */
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB045: /* STB045 family */
|
|
#endif
|
|
case CPU_PPC_STB25: /* STB25 family */
|
|
#if defined (TODO)
|
|
case CPU_PPC_STB130: /* STB130 family */
|
|
#endif
|
|
gen_spr_generic(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_40x(env);
|
|
gen_spr_405(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* Allocate hardware IRQ controller */
|
|
ppc405_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_440EP: /* 440 EP family */
|
|
case CPU_PPC_440GP: /* 440 GP family */
|
|
case CPU_PPC_440GX: /* 440 GX family */
|
|
case CPU_PPC_440GXc: /* 440 GXc family */
|
|
case CPU_PPC_440GXf: /* 440 GXf family */
|
|
case CPU_PPC_440SP: /* 440 SP family */
|
|
case CPU_PPC_440SP2:
|
|
case CPU_PPC_440SPE: /* 440 SPE family */
|
|
gen_spr_generic(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_BookE(env);
|
|
gen_spr_440(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
|
|
/* Embedded PowerPC from Freescale */
|
|
#if defined (TODO)
|
|
case CPU_PPC_5xx:
|
|
break;
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_8xx: /* MPC821 / 823 / 850 / 860 */
|
|
break;
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_82xx_HIP3: /* MPC8240 / 8260 */
|
|
case CPU_PPC_82xx_HIP4: /* MPC8240 / 8260 */
|
|
break;
|
|
#endif
|
|
#if defined (TODO)
|
|
case CPU_PPC_827x: /* MPC 827x / 828x */
|
|
break;
|
|
#endif
|
|
|
|
/* XXX: Use MPC8540 PVR to implement a test PowerPC BookE target */
|
|
case CPU_PPC_e500v110:
|
|
case CPU_PPC_e500v120:
|
|
case CPU_PPC_e500v210:
|
|
case CPU_PPC_e500v220:
|
|
gen_spr_generic(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_BookE(env);
|
|
gen_spr_BookE_FSL(env);
|
|
env->nb_BATs = 0;
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 1;
|
|
env->id_tlbs = 0;
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
|
|
#if defined (TODO)
|
|
case CPU_PPC_e600:
|
|
break;
|
|
#endif
|
|
|
|
/* 32 bits PowerPC */
|
|
case CPU_PPC_601: /* PowerPC 601 */
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
gen_spr_601(env);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* 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);
|
|
/* XXX : not implemented */
|
|
#if 0 /* ? */
|
|
spr_register(env, SPR_601_HID15, "HID15",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
#endif
|
|
env->nb_tlb = 64;
|
|
env->nb_ways = 2;
|
|
env->id_tlbs = 0;
|
|
env->id_tlbs = 0;
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
|
|
case CPU_PPC_602: /* PowerPC 602 */
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
|
gen_spr_602(env);
|
|
/* hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID1, "HID1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_603: /* PowerPC 603 */
|
|
case CPU_PPC_603E: /* PowerPC 603e */
|
|
case CPU_PPC_603E7v:
|
|
case CPU_PPC_603E7v2:
|
|
case CPU_PPC_603P: /* PowerPC 603p */
|
|
case CPU_PPC_603R: /* PowerPC 603r */
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
|
gen_spr_603(env);
|
|
/* hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID1, "HID1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_G2: /* PowerPC G2 family */
|
|
case CPU_PPC_G2H4:
|
|
case CPU_PPC_G2gp:
|
|
case CPU_PPC_G2ls:
|
|
case CPU_PPC_G2LE: /* PowerPC G2LE family */
|
|
case CPU_PPC_G2LEgp:
|
|
case CPU_PPC_G2LEls:
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
/* Memory management */
|
|
gen_high_BATs(env);
|
|
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
|
gen_spr_G2_755(env);
|
|
gen_spr_G2(env);
|
|
/* Hardware implementation register */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* 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_HID2, "HID2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_604: /* PowerPC 604 */
|
|
case CPU_PPC_604E: /* PowerPC 604e */
|
|
case CPU_PPC_604R: /* PowerPC 604r */
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_604(env);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID1, "HID1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_74x: /* PowerPC 740 / 750 */
|
|
case CPU_PPC_740E:
|
|
case CPU_PPC_750E:
|
|
case CPU_PPC_74xP: /* PowerPC 740P / 750P */
|
|
case CPU_PPC_750CXE21: /* IBM PowerPC 750cxe */
|
|
case CPU_PPC_750CXE22:
|
|
case CPU_PPC_750CXE23:
|
|
case CPU_PPC_750CXE24:
|
|
case CPU_PPC_750CXE24b:
|
|
case CPU_PPC_750CXE31:
|
|
case CPU_PPC_750CXE31b:
|
|
case CPU_PPC_750CXR:
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_7xx(env);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID1, "HID1",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_750FX10: /* IBM PowerPC 750 FX */
|
|
case CPU_PPC_750FX20:
|
|
case CPU_PPC_750FX21:
|
|
case CPU_PPC_750FX22:
|
|
case CPU_PPC_750FX23:
|
|
case CPU_PPC_750GX10: /* IBM PowerPC 750 GX */
|
|
case CPU_PPC_750GX11:
|
|
case CPU_PPC_750GX12:
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
|
|
gen_high_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_7xx(env);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* 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_750_HID2, "HID2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
case CPU_PPC_755_10: /* PowerPC 755 */
|
|
case CPU_PPC_755_11:
|
|
case CPU_PPC_755_20:
|
|
case CPU_PPC_755D:
|
|
case CPU_PPC_755E:
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* Memory management */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
/* Memory management */
|
|
gen_high_BATs(env);
|
|
gen_6xx_7xx_soft_tlb(env, 64, 2);
|
|
gen_spr_G2_755(env);
|
|
/* L2 cache control */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_ICTC, "ICTC",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_L2PM, "L2PM",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* 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_HID2, "HID2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc6xx_irq_init(env);
|
|
break;
|
|
|
|
#if defined (TODO)
|
|
/* G4 family */
|
|
case CPU_PPC_7400: /* PowerPC 7400 */
|
|
case CPU_PPC_7410C: /* PowerPC 7410 */
|
|
case CPU_PPC_7410D:
|
|
case CPU_PPC_7410E:
|
|
case CPU_PPC_7441: /* PowerPC 7441 */
|
|
case CPU_PPC_7445: /* PowerPC 7445 */
|
|
case CPU_PPC_7447: /* PowerPC 7447 */
|
|
case CPU_PPC_7447A: /* PowerPC 7447A */
|
|
case CPU_PPC_7448: /* PowerPC 7448 */
|
|
case CPU_PPC_7450: /* PowerPC 7450 */
|
|
case CPU_PPC_7450b:
|
|
case CPU_PPC_7451: /* PowerPC 7451 */
|
|
case CPU_PPC_7451G:
|
|
case CPU_PPC_7455: /* PowerPC 7455 */
|
|
case CPU_PPC_7455F:
|
|
case CPU_PPC_7455G:
|
|
case CPU_PPC_7457: /* PowerPC 7457 */
|
|
case CPU_PPC_7457C:
|
|
case CPU_PPC_7457A: /* PowerPC 7457A */
|
|
break;
|
|
#endif
|
|
|
|
/* 64 bits PowerPC */
|
|
#if defined (TARGET_PPC64)
|
|
#if defined (TODO)
|
|
case CPU_PPC_620: /* PowerPC 620 */
|
|
case CPU_PPC_630: /* PowerPC 630 (Power 3) */
|
|
case CPU_PPC_631: /* PowerPC 631 (Power 3+) */
|
|
case CPU_PPC_POWER4: /* Power 4 */
|
|
case CPU_PPC_POWER4P: /* Power 4+ */
|
|
case CPU_PPC_POWER5: /* Power 5 */
|
|
case CPU_PPC_POWER5P: /* Power 5+ */
|
|
#endif
|
|
break;
|
|
|
|
case CPU_PPC_970: /* PowerPC 970 */
|
|
case CPU_PPC_970FX10: /* PowerPC 970 FX */
|
|
case CPU_PPC_970FX20:
|
|
case CPU_PPC_970FX21:
|
|
case CPU_PPC_970FX30:
|
|
case CPU_PPC_970FX31:
|
|
case CPU_PPC_970MP10: /* PowerPC 970 MP */
|
|
case CPU_PPC_970MP11:
|
|
gen_spr_generic(env);
|
|
gen_spr_ne_601(env);
|
|
/* XXX: not correct */
|
|
gen_low_BATs(env);
|
|
/* Time base */
|
|
gen_tbl(env);
|
|
gen_spr_7xx(env);
|
|
/* Hardware implementation registers */
|
|
/* XXX : not implemented */
|
|
spr_register(env, SPR_HID0, "HID0",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* 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_750_HID2, "HID2",
|
|
SPR_NOACCESS, SPR_NOACCESS,
|
|
&spr_read_generic, &spr_write_generic,
|
|
0x00000000);
|
|
/* Allocate hardware IRQ controller */
|
|
ppc970_irq_init(env);
|
|
break;
|
|
|
|
#if defined (TODO)
|
|
case CPU_PPC_CELL10: /* Cell family */
|
|
case CPU_PPC_CELL20:
|
|
case CPU_PPC_CELL30:
|
|
case CPU_PPC_CELL31:
|
|
#endif
|
|
break;
|
|
|
|
#if defined (TODO)
|
|
case CPU_PPC_RS64: /* Apache (RS64/A35) */
|
|
case CPU_PPC_RS64II: /* NorthStar (RS64-II/A50) */
|
|
case CPU_PPC_RS64III: /* Pulsar (RS64-III) */
|
|
case CPU_PPC_RS64IV: /* IceStar/IStar/SStar (RS64-IV) */
|
|
#endif
|
|
break;
|
|
#endif /* defined (TARGET_PPC64) */
|
|
|
|
#if defined (TODO)
|
|
/* POWER */
|
|
case CPU_POWER: /* POWER */
|
|
case CPU_POWER2: /* POWER2 */
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
gen_spr_generic(env);
|
|
/* XXX: TODO: allocate internal IRQ controller */
|
|
break;
|
|
}
|
|
if (env->nb_BATs == -1)
|
|
env->nb_BATs = 4;
|
|
/* Allocate TLBs buffer when needed */
|
|
if (env->nb_tlb != 0) {
|
|
int nb_tlb = env->nb_tlb;
|
|
if (env->id_tlbs != 0)
|
|
nb_tlb *= 2;
|
|
env->tlb = qemu_mallocz(nb_tlb * sizeof(ppc_tlb_t));
|
|
/* Pre-compute some useful values */
|
|
env->tlb_per_way = env->nb_tlb / env->nb_ways;
|
|
}
|
|
}
|
|
|
|
#if defined(PPC_DUMP_CPU)
|
|
static void dump_sprs (CPUPPCState *env)
|
|
{
|
|
ppc_spr_t *spr;
|
|
uint32_t pvr = env->spr[SPR_PVR];
|
|
uint32_t sr, sw, ur, uw;
|
|
int i, j, n;
|
|
|
|
printf("* SPRs for PVR=%08x\n", pvr);
|
|
for (i = 0; i < 32; i++) {
|
|
for (j = 0; j < 32; j++) {
|
|
n = (i << 5) | j;
|
|
spr = &env->spr_cb[n];
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
sw = spr->oea_write != NULL && spr->oea_write != SPR_NOACCESS;
|
|
sr = spr->oea_read != NULL && spr->oea_read != SPR_NOACCESS;
|
|
#else
|
|
sw = 0;
|
|
sr = 0;
|
|
#endif
|
|
uw = spr->uea_write != NULL && spr->uea_write != SPR_NOACCESS;
|
|
ur = spr->uea_read != NULL && spr->uea_read != SPR_NOACCESS;
|
|
if (sw || sr || uw || ur) {
|
|
printf("SPR: %4d (%03x) %-8s s%c%c u%c%c\n",
|
|
(i << 5) | j, (i << 5) | j, spr->name,
|
|
sw ? 'w' : '-', sr ? 'r' : '-',
|
|
uw ? 'w' : '-', ur ? 'r' : '-');
|
|
}
|
|
}
|
|
}
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
int fflush (FILE *stream);
|
|
|
|
/* Opcode types */
|
|
enum {
|
|
PPC_DIRECT = 0, /* Opcode routine */
|
|
PPC_INDIRECT = 1, /* Indirect opcode table */
|
|
};
|
|
|
|
static inline int is_indirect_opcode (void *handler)
|
|
{
|
|
return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
|
|
}
|
|
|
|
static inline opc_handler_t **ind_table(void *handler)
|
|
{
|
|
return (opc_handler_t **)((unsigned long)handler & ~3);
|
|
}
|
|
|
|
/* Instruction table creation */
|
|
/* Opcodes tables creation */
|
|
static void fill_new_table (opc_handler_t **table, int len)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++)
|
|
table[i] = &invalid_handler;
|
|
}
|
|
|
|
static int create_new_table (opc_handler_t **table, unsigned char idx)
|
|
{
|
|
opc_handler_t **tmp;
|
|
|
|
tmp = malloc(0x20 * sizeof(opc_handler_t));
|
|
if (tmp == NULL)
|
|
return -1;
|
|
fill_new_table(tmp, 0x20);
|
|
table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int insert_in_table (opc_handler_t **table, unsigned char idx,
|
|
opc_handler_t *handler)
|
|
{
|
|
if (table[idx] != &invalid_handler)
|
|
return -1;
|
|
table[idx] = handler;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int register_direct_insn (opc_handler_t **ppc_opcodes,
|
|
unsigned char idx, opc_handler_t *handler)
|
|
{
|
|
if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
|
|
printf("*** ERROR: opcode %02x already assigned in main "
|
|
"opcode table\n", idx);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int register_ind_in_table (opc_handler_t **table,
|
|
unsigned char idx1, unsigned char idx2,
|
|
opc_handler_t *handler)
|
|
{
|
|
if (table[idx1] == &invalid_handler) {
|
|
if (create_new_table(table, idx1) < 0) {
|
|
printf("*** ERROR: unable to create indirect table "
|
|
"idx=%02x\n", idx1);
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (!is_indirect_opcode(table[idx1])) {
|
|
printf("*** ERROR: idx %02x already assigned to a direct "
|
|
"opcode\n", idx1);
|
|
return -1;
|
|
}
|
|
}
|
|
if (handler != NULL &&
|
|
insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
|
|
printf("*** ERROR: opcode %02x already assigned in "
|
|
"opcode table %02x\n", idx2, idx1);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int register_ind_insn (opc_handler_t **ppc_opcodes,
|
|
unsigned char idx1, unsigned char idx2,
|
|
opc_handler_t *handler)
|
|
{
|
|
int ret;
|
|
|
|
ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int register_dblind_insn (opc_handler_t **ppc_opcodes,
|
|
unsigned char idx1, unsigned char idx2,
|
|
unsigned char idx3, opc_handler_t *handler)
|
|
{
|
|
if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
|
|
printf("*** ERROR: unable to join indirect table idx "
|
|
"[%02x-%02x]\n", idx1, idx2);
|
|
return -1;
|
|
}
|
|
if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
|
|
handler) < 0) {
|
|
printf("*** ERROR: unable to insert opcode "
|
|
"[%02x-%02x-%02x]\n", idx1, idx2, idx3);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int register_insn (opc_handler_t **ppc_opcodes, opcode_t *insn)
|
|
{
|
|
if (insn->opc2 != 0xFF) {
|
|
if (insn->opc3 != 0xFF) {
|
|
if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
|
|
insn->opc3, &insn->handler) < 0)
|
|
return -1;
|
|
} else {
|
|
if (register_ind_insn(ppc_opcodes, insn->opc1,
|
|
insn->opc2, &insn->handler) < 0)
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_opcode_table (opc_handler_t **table, int len)
|
|
{
|
|
int i, count, tmp;
|
|
|
|
for (i = 0, count = 0; i < len; i++) {
|
|
/* Consistency fixup */
|
|
if (table[i] == NULL)
|
|
table[i] = &invalid_handler;
|
|
if (table[i] != &invalid_handler) {
|
|
if (is_indirect_opcode(table[i])) {
|
|
tmp = test_opcode_table(ind_table(table[i]), 0x20);
|
|
if (tmp == 0) {
|
|
free(table[i]);
|
|
table[i] = &invalid_handler;
|
|
} else {
|
|
count++;
|
|
}
|
|
} else {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
|
|
{
|
|
if (test_opcode_table(ppc_opcodes, 0x40) == 0)
|
|
printf("*** WARNING: no opcode defined !\n");
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int create_ppc_opcodes (CPUPPCState *env, ppc_def_t *def)
|
|
{
|
|
opcode_t *opc, *start, *end;
|
|
|
|
fill_new_table(env->opcodes, 0x40);
|
|
#if defined(PPC_DUMP_CPU)
|
|
printf("* PowerPC instructions for PVR %08x: %s flags %016" PRIx64
|
|
" %08x\n",
|
|
def->pvr, def->name, def->insns_flags, def->flags);
|
|
#endif
|
|
if (&opc_start < &opc_end) {
|
|
start = &opc_start;
|
|
end = &opc_end;
|
|
} else {
|
|
start = &opc_end;
|
|
end = &opc_start;
|
|
}
|
|
for (opc = start + 1; opc != end; opc++) {
|
|
if ((opc->handler.type & def->insns_flags) != 0) {
|
|
if (register_insn(env->opcodes, opc) < 0) {
|
|
printf("*** ERROR initializing PowerPC instruction "
|
|
"0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
|
|
opc->opc3);
|
|
return -1;
|
|
}
|
|
#if defined(PPC_DUMP_CPU)
|
|
if (opc1 != 0x00) {
|
|
if (opc->opc3 == 0xFF) {
|
|
if (opc->opc2 == 0xFF) {
|
|
printf("INSN: %02x -- -- (%02d ----) : %s\n",
|
|
opc->opc1, opc->opc1, opc->oname);
|
|
} else {
|
|
printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
|
|
opc->opc1, opc->opc2, opc->opc1, opc->opc2,
|
|
opc->oname);
|
|
}
|
|
} else {
|
|
printf("INSN: %02x %02x %02x (%02d %04d) : %s\n",
|
|
opc->opc1, opc->opc2, opc->opc3,
|
|
opc->opc1, (opc->opc3 << 5) | opc->opc2,
|
|
opc->oname);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
fix_opcode_tables(env->opcodes);
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def)
|
|
{
|
|
env->msr_mask = def->msr_mask;
|
|
env->flags = def->flags;
|
|
if (create_ppc_opcodes(env, def) < 0)
|
|
return -1;
|
|
init_ppc_proc(env, def);
|
|
#if defined(PPC_DUMP_CPU)
|
|
dump_sprs(env);
|
|
if (env->tlb != NULL) {
|
|
printf("%d %s TLB in %d ways\n", env->nb_tlb,
|
|
env->id_tlbs ? "splitted" : "merged", env->nb_ways);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* PowerPC CPU definitions */
|
|
static ppc_def_t ppc_defs[] = {
|
|
/* Embedded PowerPC */
|
|
/* Generic PowerPC 401 */
|
|
{
|
|
.name = "401",
|
|
.pvr = CPU_PPC_401,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401A1 */
|
|
{
|
|
.name = "401a1",
|
|
.pvr = CPU_PPC_401A1,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401B2 */
|
|
{
|
|
.name = "401b2",
|
|
.pvr = CPU_PPC_401B2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 401B3 */
|
|
{
|
|
.name = "401b3",
|
|
.pvr = CPU_PPC_401B3,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#endif
|
|
/* PowerPC 401C2 */
|
|
{
|
|
.name = "401c2",
|
|
.pvr = CPU_PPC_401C2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401D2 */
|
|
{
|
|
.name = "401d2",
|
|
.pvr = CPU_PPC_401D2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401E2 */
|
|
{
|
|
.name = "401e2",
|
|
.pvr = CPU_PPC_401E2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401F2 */
|
|
{
|
|
.name = "401f2",
|
|
.pvr = CPU_PPC_401F2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
/* PowerPC 401G2 */
|
|
{
|
|
.name = "401g2",
|
|
.pvr = CPU_PPC_401G2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 401G2 */
|
|
{
|
|
.name = "401gf",
|
|
.pvr = CPU_PPC_401GF,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* IOP480 (401 microcontroler) */
|
|
{
|
|
.name = "iop480",
|
|
.pvr = CPU_PPC_IOP480,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* IBM Processor for Network Resources */
|
|
{
|
|
.name = "Cobra",
|
|
.pvr = CPU_PPC_COBRA,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_401,
|
|
.flags = PPC_FLAGS_401,
|
|
.msr_mask = 0x000FD201,
|
|
},
|
|
#endif
|
|
/* Generic PowerPC 403 */
|
|
{
|
|
.name = "403",
|
|
.pvr = CPU_PPC_403,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
/* PowerPC 403 GA */
|
|
{
|
|
.name = "403ga",
|
|
.pvr = CPU_PPC_403GA,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
/* PowerPC 403 GB */
|
|
{
|
|
.name = "403gb",
|
|
.pvr = CPU_PPC_403GB,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
/* PowerPC 403 GC */
|
|
{
|
|
.name = "403gc",
|
|
.pvr = CPU_PPC_403GC,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
/* PowerPC 403 GCX */
|
|
{
|
|
.name = "403gcx",
|
|
.pvr = CPU_PPC_403GCX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 403 GP */
|
|
{
|
|
.name = "403gp",
|
|
.pvr = CPU_PPC_403GP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_403,
|
|
.flags = PPC_FLAGS_403,
|
|
.msr_mask = 0x000000000007D23DULL,
|
|
},
|
|
#endif
|
|
/* Generic PowerPC 405 */
|
|
{
|
|
.name = "405",
|
|
.pvr = CPU_PPC_405,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 405 A3 */
|
|
{
|
|
.name = "405a3",
|
|
.pvr = CPU_PPC_405A3,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 405 A4 */
|
|
{
|
|
.name = "405a4",
|
|
.pvr = CPU_PPC_405A4,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 405 B3 */
|
|
{
|
|
.name = "405b3",
|
|
.pvr = CPU_PPC_405B3,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
/* PowerPC 405 D2 */
|
|
{
|
|
.name = "405d2",
|
|
.pvr = CPU_PPC_405D2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* PowerPC 405 D4 */
|
|
{
|
|
.name = "405d4",
|
|
.pvr = CPU_PPC_405D4,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* PowerPC 405 CR */
|
|
{
|
|
.name = "405cr",
|
|
.pvr = CPU_PPC_405CR,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* PowerPC 405 GP */
|
|
{
|
|
.name = "405gp",
|
|
.pvr = CPU_PPC_405GP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* PowerPC 405 EP */
|
|
{
|
|
.name = "405ep",
|
|
.pvr = CPU_PPC_405EP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000000ED630ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 405 EZ */
|
|
{
|
|
.name = "405ez",
|
|
.pvr = CPU_PPC_405EZ,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 405 GPR */
|
|
{
|
|
.name = "405gpr",
|
|
.pvr = CPU_PPC_405GPR,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 405 LP */
|
|
{
|
|
.name = "405lp",
|
|
.pvr = CPU_PPC_405EZ,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
/* Npe405 H */
|
|
{
|
|
.name = "Npe405H",
|
|
.pvr = CPU_PPC_NPE405H,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* Npe405 H2 */
|
|
{
|
|
.name = "Npe405H2",
|
|
.pvr = CPU_PPC_NPE405H2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
/* Npe405 L */
|
|
{
|
|
.name = "Npe405L",
|
|
.pvr = CPU_PPC_NPE405L,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC LP777000 */
|
|
{
|
|
.name = "lp777000",
|
|
.pvr = CPU_PPC_LP777000,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB010000 */
|
|
{
|
|
.name = "STB01000",
|
|
.pvr = CPU_PPC_STB01000,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB01010 */
|
|
{
|
|
.name = "STB01010",
|
|
.pvr = CPU_PPC_STB01010,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB0210 */
|
|
{
|
|
.name = "STB0210",
|
|
.pvr = CPU_PPC_STB0210,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB03xx */
|
|
{
|
|
.name = "STB03",
|
|
.pvr = CPU_PPC_STB03,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB043x */
|
|
{
|
|
.name = "STB043",
|
|
.pvr = CPU_PPC_STB043,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB045x */
|
|
{
|
|
.name = "STB045",
|
|
.pvr = CPU_PPC_STB045,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO) || 1
|
|
/* STB25xx */
|
|
{
|
|
.name = "STB25",
|
|
.pvr = CPU_PPC_STB25,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* STB130 */
|
|
{
|
|
.name = "STB130",
|
|
.pvr = CPU_PPC_STB130,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
/* Xilinx PowerPC 405 cores */
|
|
#if defined (TODO)
|
|
{
|
|
.name = "x2vp4",
|
|
.pvr = CPU_PPC_X2VP4,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
{
|
|
.name = "x2vp7",
|
|
.pvr = CPU_PPC_X2VP7,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
{
|
|
.name = "x2vp20",
|
|
.pvr = CPU_PPC_X2VP20,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
{
|
|
.name = "x2vp50",
|
|
.pvr = CPU_PPC_X2VP50,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_405,
|
|
.flags = PPC_FLAGS_405,
|
|
.msr_mask = 0x00000000020EFF30ULL,
|
|
},
|
|
#endif
|
|
/* PowerPC 440 EP */
|
|
{
|
|
.name = "440ep",
|
|
.pvr = CPU_PPC_440EP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 GR */
|
|
{
|
|
.name = "440gr",
|
|
.pvr = CPU_PPC_440GR,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 GP */
|
|
{
|
|
.name = "440gp",
|
|
.pvr = CPU_PPC_440GP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* PowerPC 440 GRX */
|
|
{
|
|
.name = "440grx",
|
|
.pvr = CPU_PPC_440GRX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
#endif
|
|
/* PowerPC 440 GX */
|
|
{
|
|
.name = "440gx",
|
|
.pvr = CPU_PPC_440GX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 GXc */
|
|
{
|
|
.name = "440gxc",
|
|
.pvr = CPU_PPC_440GXc,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 GXf */
|
|
{
|
|
.name = "440gxf",
|
|
.pvr = CPU_PPC_440GXf,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 SP */
|
|
{
|
|
.name = "440sp",
|
|
.pvr = CPU_PPC_440SP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 SP2 */
|
|
{
|
|
.name = "440sp2",
|
|
.pvr = CPU_PPC_440SP2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 440 SPE */
|
|
{
|
|
.name = "440spe",
|
|
.pvr = CPU_PPC_440SPE,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_440,
|
|
.flags = PPC_FLAGS_440,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* Fake generic BookE PowerPC */
|
|
{
|
|
.name = "BookE",
|
|
.pvr = CPU_PPC_e500,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_BOOKE,
|
|
.flags = PPC_FLAGS_BOOKE,
|
|
.msr_mask = 0x000000000006D630ULL,
|
|
},
|
|
/* PowerPC 460 cores - TODO */
|
|
/* PowerPC MPC 5xx cores - TODO */
|
|
/* PowerPC MPC 8xx cores - TODO */
|
|
/* PowerPC MPC 8xxx cores - TODO */
|
|
/* e200 cores - TODO */
|
|
/* e500 cores - TODO */
|
|
/* e600 cores - TODO */
|
|
|
|
/* 32 bits "classic" PowerPC */
|
|
#if defined (TODO)
|
|
/* PowerPC 601 */
|
|
{
|
|
.name = "601",
|
|
.pvr = CPU_PPC_601,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_601,
|
|
.flags = PPC_FLAGS_601,
|
|
.msr_mask = 0x000000000000FD70ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 602 */
|
|
{
|
|
.name = "602",
|
|
.pvr = CPU_PPC_602,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_602,
|
|
.flags = PPC_FLAGS_602,
|
|
.msr_mask = 0x0000000000C7FF73ULL,
|
|
},
|
|
#endif
|
|
/* PowerPC 603 */
|
|
{
|
|
.name = "603",
|
|
.pvr = CPU_PPC_603,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603e */
|
|
{
|
|
.name = "603e",
|
|
.pvr = CPU_PPC_603E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
{
|
|
.name = "Stretch",
|
|
.pvr = CPU_PPC_603E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603p */
|
|
{
|
|
.name = "603p",
|
|
.pvr = CPU_PPC_603P,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603e7 */
|
|
{
|
|
.name = "603e7",
|
|
.pvr = CPU_PPC_603E7,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603e7v */
|
|
{
|
|
.name = "603e7v",
|
|
.pvr = CPU_PPC_603E7v,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603e7v2 */
|
|
{
|
|
.name = "603e7v2",
|
|
.pvr = CPU_PPC_603E7v2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
/* PowerPC 603r */
|
|
{
|
|
.name = "603r",
|
|
.pvr = CPU_PPC_603R,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
{
|
|
.name = "Goldeneye",
|
|
.pvr = CPU_PPC_603R,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_603,
|
|
.flags = PPC_FLAGS_603,
|
|
.msr_mask = 0x000000000007FF73ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* XXX: TODO: according to Motorola UM, this is a derivative to 603e */
|
|
{
|
|
.name = "G2",
|
|
.pvr = CPU_PPC_G2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000006FFF2ULL,
|
|
},
|
|
{
|
|
.name = "G2h4",
|
|
.pvr = CPU_PPC_G2H4,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000006FFF2ULL,
|
|
},
|
|
{
|
|
.name = "G2gp",
|
|
.pvr = CPU_PPC_G2gp,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000006FFF2ULL,
|
|
},
|
|
{
|
|
.name = "G2ls",
|
|
.pvr = CPU_PPC_G2ls,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000006FFF2ULL,
|
|
},
|
|
{ /* Same as G2, with LE mode support */
|
|
.name = "G2le",
|
|
.pvr = CPU_PPC_G2LE,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000007FFF3ULL,
|
|
},
|
|
{
|
|
.name = "G2legp",
|
|
.pvr = CPU_PPC_G2LEgp,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000007FFF3ULL,
|
|
},
|
|
{
|
|
.name = "G2lels",
|
|
.pvr = CPU_PPC_G2LEls,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_G2,
|
|
.flags = PPC_FLAGS_G2,
|
|
.msr_mask = 0x000000000007FFF3ULL,
|
|
},
|
|
#endif
|
|
/* PowerPC 604 */
|
|
{
|
|
.name = "604",
|
|
.pvr = CPU_PPC_604,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_604,
|
|
.flags = PPC_FLAGS_604,
|
|
.msr_mask = 0x000000000005FF77ULL,
|
|
},
|
|
/* PowerPC 604e */
|
|
{
|
|
.name = "604e",
|
|
.pvr = CPU_PPC_604E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_604,
|
|
.flags = PPC_FLAGS_604,
|
|
.msr_mask = 0x000000000005FF77ULL,
|
|
},
|
|
/* PowerPC 604r */
|
|
{
|
|
.name = "604r",
|
|
.pvr = CPU_PPC_604R,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_604,
|
|
.flags = PPC_FLAGS_604,
|
|
.msr_mask = 0x000000000005FF77ULL,
|
|
},
|
|
/* generic G3 */
|
|
{
|
|
.name = "G3",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* MPC740 (G3) */
|
|
{
|
|
.name = "740",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
{
|
|
.name = "Arthur",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* 740E (G3) */
|
|
{
|
|
.name = "740e",
|
|
.pvr = CPU_PPC_740E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* MPC740P (G3) */
|
|
{
|
|
.name = "740p",
|
|
.pvr = CPU_PPC_74xP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
{
|
|
.name = "Conan/Doyle",
|
|
.pvr = CPU_PPC_74xP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* MPC745 (G3) */
|
|
{
|
|
.name = "745",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
{
|
|
.name = "Goldfinger",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* MPC745P (G3) */
|
|
{
|
|
.name = "745p",
|
|
.pvr = CPU_PPC_74xP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
/* MPC750 (G3) */
|
|
{
|
|
.name = "750",
|
|
.pvr = CPU_PPC_74x,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* MPC750P (G3) */
|
|
{
|
|
.name = "750p",
|
|
.pvr = CPU_PPC_74xP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* 750E (G3) */
|
|
{
|
|
.name = "750e",
|
|
.pvr = CPU_PPC_750E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750CXe (G3 embedded) */
|
|
{
|
|
.name = "750cxe",
|
|
.pvr = CPU_PPC_750CXE,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750CXr (G3 embedded) */
|
|
{
|
|
.name = "750cxr",
|
|
.pvr = CPU_PPC_750CXR,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750FX (G3 embedded) */
|
|
{
|
|
.name = "750fx",
|
|
.pvr = CPU_PPC_750FX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750FL (G3 embedded) */
|
|
{
|
|
.name = "750fl",
|
|
.pvr = CPU_PPC_750FL,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750GX (G3 embedded) */
|
|
{
|
|
.name = "750gx",
|
|
.pvr = CPU_PPC_750GX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750L (G3 embedded) */
|
|
{
|
|
.name = "750l",
|
|
.pvr = CPU_PPC_750L,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
/* IBM 750CL (G3 embedded) */
|
|
{
|
|
.name = "750cl",
|
|
.pvr = CPU_PPC_750CL,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x0,
|
|
.flags = PPC_FLAGS_7x0,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#if defined (TODO)
|
|
/* MPC755 (G3) */
|
|
{
|
|
.name = "755",
|
|
.pvr = CPU_PPC_755,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* MPC755D (G3) */
|
|
{
|
|
.name = "755d",
|
|
.pvr = CPU_PPC_755D,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* MPC755E (G3) */
|
|
{
|
|
.name = "755e",
|
|
.pvr = CPU_PPC_755E,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* MPC755P (G3) */
|
|
{
|
|
.name = "755p",
|
|
.pvr = CPU_PPC_74xP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_7x5,
|
|
.flags = PPC_FLAGS_7x5,
|
|
.msr_mask = 0x000000000007FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* generic G4 */
|
|
{
|
|
.name = "G4",
|
|
.pvr = CPU_PPC_7400,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7400 (G4) */
|
|
{
|
|
.name = "7400",
|
|
.pvr = CPU_PPC_7400,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Max",
|
|
.pvr = CPU_PPC_7400,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7410 (G4) */
|
|
{
|
|
.name = "7410",
|
|
.pvr = CPU_PPC_7410,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Nitro",
|
|
.pvr = CPU_PPC_7410,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7441 (G4) */
|
|
{
|
|
.name = "7441",
|
|
.pvr = CPU_PPC_7441,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7445 (G4) */
|
|
{
|
|
.name = "7445",
|
|
.pvr = CPU_PPC_7445,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7447 (G4) */
|
|
{
|
|
.name = "7447",
|
|
.pvr = CPU_PPC_7447,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7447A (G4) */
|
|
{
|
|
.name = "7447A",
|
|
.pvr = CPU_PPC_7447A,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7448 (G4) */
|
|
{
|
|
.name = "7448",
|
|
.pvr = CPU_PPC_7448,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7450 (G4) */
|
|
{
|
|
.name = "7450",
|
|
.pvr = CPU_PPC_7450,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Vger",
|
|
.pvr = CPU_PPC_7450,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7450b (G4) */
|
|
{
|
|
.name = "7450b",
|
|
.pvr = CPU_PPC_7450B,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7451 (G4) */
|
|
{
|
|
.name = "7451",
|
|
.pvr = CPU_PPC_7451,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7451g (G4) */
|
|
{
|
|
.name = "7451g",
|
|
.pvr = CPU_PPC_7451G,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7455 (G4) */
|
|
{
|
|
.name = "7455",
|
|
.pvr = CPU_PPC_7455,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Apollo 6",
|
|
.pvr = CPU_PPC_7455,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7455F (G4) */
|
|
{
|
|
.name = "7455f",
|
|
.pvr = CPU_PPC_7455F,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7455G (G4) */
|
|
{
|
|
.name = "7455g",
|
|
.pvr = CPU_PPC_7455G,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7457 (G4) */
|
|
{
|
|
.name = "7457",
|
|
.pvr = CPU_PPC_7457,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Apollo 7",
|
|
.pvr = CPU_PPC_7457,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7457A (G4) */
|
|
{
|
|
.name = "7457A",
|
|
.pvr = CPU_PPC_7457A,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
{
|
|
.name = "Apollo 7 PM",
|
|
.pvr = CPU_PPC_7457A,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 7457C (G4) */
|
|
{
|
|
.name = "7457c",
|
|
.pvr = CPU_PPC_7457C,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_74xx,
|
|
.flags = PPC_FLAGS_74xx,
|
|
.msr_mask = 0x000000000205FF77ULL,
|
|
},
|
|
#endif
|
|
/* 64 bits PowerPC */
|
|
#if defined (TARGET_PPC64)
|
|
#if defined (TODO)
|
|
/* PowerPC 620 */
|
|
{
|
|
.name = "620",
|
|
.pvr = CPU_PPC_620,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_620,
|
|
.flags = PPC_FLAGS_620,
|
|
.msr_mask = 0x800000000005FF73ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 630 (POWER3) */
|
|
{
|
|
.name = "630",
|
|
.pvr = CPU_PPC_630,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_630,
|
|
.flags = PPC_FLAGS_630,
|
|
.msr_mask = xxx,
|
|
}
|
|
{
|
|
.name = "POWER3",
|
|
.pvr = CPU_PPC_630,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_630,
|
|
.flags = PPC_FLAGS_630,
|
|
.msr_mask = xxx,
|
|
}
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 631 (Power 3+)*/
|
|
{
|
|
.name = "631",
|
|
.pvr = CPU_PPC_631,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_631,
|
|
.flags = PPC_FLAGS_631,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "POWER3+",
|
|
.pvr = CPU_PPC_631,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_631,
|
|
.flags = PPC_FLAGS_631,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* POWER4 */
|
|
{
|
|
.name = "POWER4",
|
|
.pvr = CPU_PPC_POWER4,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER4,
|
|
.flags = PPC_FLAGS_POWER4,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* POWER4p */
|
|
{
|
|
.name = "POWER4+",
|
|
.pvr = CPU_PPC_POWER4P,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER4,
|
|
.flags = PPC_FLAGS_POWER4,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* POWER5 */
|
|
{
|
|
.name = "POWER5",
|
|
.pvr = CPU_PPC_POWER5,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER5,
|
|
.flags = PPC_FLAGS_POWER5,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* POWER5+ */
|
|
{
|
|
.name = "POWER5+",
|
|
.pvr = CPU_PPC_POWER5P,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER5,
|
|
.flags = PPC_FLAGS_POWER5,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* POWER6 */
|
|
{
|
|
.name = "POWER6",
|
|
.pvr = CPU_PPC_POWER6,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER6,
|
|
.flags = PPC_FLAGS_POWER6,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 970 */
|
|
{
|
|
.name = "970",
|
|
.pvr = CPU_PPC_970,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_970,
|
|
.flags = PPC_FLAGS_970,
|
|
.msr_mask = 0x900000000204FF36ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 970FX (G5) */
|
|
{
|
|
.name = "970fx",
|
|
.pvr = CPU_PPC_970FX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_970FX,
|
|
.flags = PPC_FLAGS_970FX,
|
|
.msr_mask = 0x800000000204FF36ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC 970MP */
|
|
{
|
|
.name = "970MP",
|
|
.pvr = CPU_PPC_970MP,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_970,
|
|
.flags = PPC_FLAGS_970,
|
|
.msr_mask = 0x900000000204FF36ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* PowerPC Cell */
|
|
{
|
|
.name = "Cell",
|
|
.pvr = CPU_PPC_CELL,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_970,
|
|
.flags = PPC_FLAGS_970,
|
|
.msr_mask = 0x900000000204FF36ULL,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* RS64 (Apache/A35) */
|
|
/* This one seems to support the whole POWER2 instruction set
|
|
* and the PowerPC 64 one.
|
|
*/
|
|
{
|
|
.name = "RS64",
|
|
.pvr = CPU_PPC_RS64,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "Apache",
|
|
.pvr = CPU_PPC_RS64,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "A35",
|
|
.pvr = CPU_PPC_RS64,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* RS64-II (NorthStar/A50) */
|
|
{
|
|
.name = "RS64-II",
|
|
.pvr = CPU_PPC_RS64II,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "NortStar",
|
|
.pvr = CPU_PPC_RS64II,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "A50",
|
|
.pvr = CPU_PPC_RS64II,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* RS64-III (Pulsar) */
|
|
{
|
|
.name = "RS64-III",
|
|
.pvr = CPU_PPC_RS64III,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "Pulsar",
|
|
.pvr = CPU_PPC_RS64III,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#if defined (TODO)
|
|
/* RS64-IV (IceStar/IStar/SStar) */
|
|
{
|
|
.name = "RS64-IV",
|
|
.pvr = CPU_PPC_RS64IV,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "IceStar",
|
|
.pvr = CPU_PPC_RS64IV,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "IStar",
|
|
.pvr = CPU_PPC_RS64IV,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
{
|
|
.name = "SStar",
|
|
.pvr = CPU_PPC_RS64IV,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_RS64,
|
|
.flags = PPC_FLAGS_RS64,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
/* POWER */
|
|
#if defined (TODO)
|
|
/* Original POWER */
|
|
{
|
|
.name = "POWER",
|
|
.pvr = CPU_POWER,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER,
|
|
.flags = PPC_FLAGS_POWER,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
#endif /* defined (TARGET_PPC64) */
|
|
#if defined (TODO)
|
|
/* POWER2 */
|
|
{
|
|
.name = "POWER2",
|
|
.pvr = CPU_POWER2,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_POWER,
|
|
.flags = PPC_FLAGS_POWER,
|
|
.msr_mask = xxx,
|
|
},
|
|
#endif
|
|
/* Generic PowerPCs */
|
|
#if defined (TODO)
|
|
{
|
|
.name = "ppc64",
|
|
.pvr = CPU_PPC_970FX,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_PPC64,
|
|
.flags = PPC_FLAGS_PPC64,
|
|
.msr_mask = 0xA00000000204FF36ULL,
|
|
},
|
|
#endif
|
|
{
|
|
.name = "ppc32",
|
|
.pvr = CPU_PPC_604,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_PPC32,
|
|
.flags = PPC_FLAGS_PPC32,
|
|
.msr_mask = 0x000000000005FF77ULL,
|
|
},
|
|
/* Fallback */
|
|
{
|
|
.name = "ppc",
|
|
.pvr = CPU_PPC_604,
|
|
.pvr_mask = 0xFFFFFFFF,
|
|
.insns_flags = PPC_INSNS_PPC32,
|
|
.flags = PPC_FLAGS_PPC32,
|
|
.msr_mask = 0x000000000005FF77ULL,
|
|
},
|
|
};
|
|
|
|
int ppc_find_by_name (const unsigned char *name, ppc_def_t **def)
|
|
{
|
|
int i, ret;
|
|
|
|
ret = -1;
|
|
*def = NULL;
|
|
for (i = 0; strcmp(ppc_defs[i].name, "ppc") != 0; i++) {
|
|
if (strcasecmp(name, ppc_defs[i].name) == 0) {
|
|
*def = &ppc_defs[i];
|
|
ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ppc_find_by_pvr (uint32_t pvr, ppc_def_t **def)
|
|
{
|
|
int i, ret;
|
|
|
|
ret = -1;
|
|
*def = NULL;
|
|
for (i = 0; ppc_defs[i].name != NULL; i++) {
|
|
if ((pvr & ppc_defs[i].pvr_mask) ==
|
|
(ppc_defs[i].pvr & ppc_defs[i].pvr_mask)) {
|
|
*def = &ppc_defs[i];
|
|
ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; ; i++) {
|
|
(*cpu_fprintf)(f, "PowerPC %16s PVR %08x mask %08x\n",
|
|
ppc_defs[i].name,
|
|
ppc_defs[i].pvr, ppc_defs[i].pvr_mask);
|
|
if (strcmp(ppc_defs[i].name, "ppc") == 0)
|
|
break;
|
|
}
|
|
}
|