From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:56933) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S7sP2-00074V-QV for qemu-devel@nongnu.org; Wed, 14 Mar 2012 13:54:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S7sOP-0002eI-7K for qemu-devel@nongnu.org; Wed, 14 Mar 2012 13:54:24 -0400 Received: from cantor2.suse.de ([195.135.220.15]:51049 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S7sOO-0002dK-Fv for qemu-devel@nongnu.org; Wed, 14 Mar 2012 13:53:45 -0400 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 14 Mar 2012 18:53:26 +0100 Message-Id: <1331747617-7837-3-git-send-email-afaerber@suse.de> In-Reply-To: <1331747617-7837-1-git-send-email-afaerber@suse.de> References: <1330893156-26569-1-git-send-email-afaerber@suse.de> <1331747617-7837-1-git-send-email-afaerber@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [RFC 02/12] target-mips: QOM'ify CPU List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Meador Inge , Jia Liu , Stefan Weil , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Khansa Butt , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Aurelien Jarno MIPS was very close to QOM in referencing a CPU definition from CPUMIPSState. Turn those structs into classes. This moves most of translate_init.c into cpu.c; move the remainder into translate.c so that we no longer #include "translate_init.c" there. Embed CPUMIPSState into MIPSCPU. Let cpu_state_reset() call cpu_reset(). Let mips_cpu_list() enumerate available CPU classes in alphabetical order. Signed-off-by: Andreas F=C3=A4rber Cc: Herv=C3=A9 Poussineau Cc: Stefan Weil Cc: Khansa Butt Cc: Meador Inge Cc: Jia Liu --- Makefile.target | 3 + target-mips/cpu-qom.h | 110 ++++++ target-mips/cpu.c | 806 ++++++++++++++++++++++++++++++++++++= ++++++ target-mips/cpu.h | 2 +- target-mips/translate.c | 183 +++------- target-mips/translate_init.c | 594 ------------------------------- 6 files changed, 965 insertions(+), 733 deletions(-) create mode 100644 target-mips/cpu-qom.h create mode 100644 target-mips/cpu.c delete mode 100644 target-mips/translate_init.c diff --git a/Makefile.target b/Makefile.target index 737c1e5..878807b 100644 --- a/Makefile.target +++ b/Makefile.target @@ -88,6 +88,9 @@ libobj-$(TARGET_SPARC64) +=3D vis_helper.o libobj-$(CONFIG_NEED_MMU) +=3D mmu.o libobj-$(TARGET_ARM) +=3D neon_helper.o iwmmxt_helper.o libobj-$(TARGET_ARM) +=3D cpu.o +ifeq ($(TARGET_BASE_ARCH), mips) +libobj-y +=3D cpu.o +endif libobj-$(TARGET_S390X) +=3D cpu.o libobj-$(TARGET_SH4) +=3D cpu.o ifeq ($(TARGET_BASE_ARCH), sparc) diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h new file mode 100644 index 0000000..3af1b9e --- /dev/null +++ b/target-mips/cpu-qom.h @@ -0,0 +1,110 @@ +/* + * QEMU MIPS CPU + * + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see + * + */ +#ifndef QEMU_MIPS_CPU_QOM_H +#define QEMU_MIPS_CPU_QOM_H + +#include "qemu-common.h" +#include "qemu/cpu.h" +#include "cpu.h" + +#define TYPE_MIPS_CPU "mips-cpu" + +/** + * MIPSMMUTypes: + * + * MMU types, the first four entries have the same layout as the + * CP0C0_MT field. + */ +enum MIPSMMUTypes { + MMU_TYPE_NONE, + MMU_TYPE_R4000, + MMU_TYPE_RESERVED, + MMU_TYPE_FMT, + MMU_TYPE_R3000, + MMU_TYPE_R6000, + MMU_TYPE_R8000 +}; + +#define MIPS_CPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU) +#define MIPS_CPU(obj) \ + OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU) +#define MIPS_CPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU) + +/** + * MIPSCPUClass: + * @parent_reset: The parent class' reset handler. + * + * A MIPS CPU model. + */ +typedef struct MIPSCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + void (*parent_reset)(CPUState *cpu); + + int32_t cp0_prid; + int32_t cp0_config0; + int32_t cp0_config1; + int32_t cp0_config2; + int32_t cp0_config3; + int32_t cp0_config6; + int32_t cp0_config7; + target_ulong cp0_lladdr_rw_bitmask; + int cp0_lladdr_shift; + int32_t synci_step; + int32_t ccres; + int32_t cp0_status_rw_bitmask; + int32_t cp0_tcstatus_rw_bitmask; + int32_t cp0_srsctl; + int32_t cp1_fcr0; + int32_t segbits; + int32_t pabits; + int32_t cp0_srsconf_rw_bitmask[5]; + int32_t cp0_srsconf[5]; + int insn_flags; + enum MIPSMMUTypes mmu_type; +} MIPSCPUClass; + +/** + * MIPSCPU: + * @env: Legacy CPU state. + * + * A MIPS CPU. + */ +typedef struct MIPSCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUMIPSState env; +} MIPSCPU; + +static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env) +{ + return MIPS_CPU(container_of(env, MIPSCPU, env)); +} + +#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e)) + + +#endif diff --git a/target-mips/cpu.c b/target-mips/cpu.c new file mode 100644 index 0000000..f692134 --- /dev/null +++ b/target-mips/cpu.c @@ -0,0 +1,806 @@ +/* + * QEMU MIPS CPU + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2007 Herve Poussineau + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see + * + */ + +#include "cpu-qom.h" +#include "qemu-common.h" + +#ifndef CONFIG_USER_ONLY +static void no_mmu_init(MIPSCPU *cpu) +{ + CPUMIPSState *env =3D &cpu->env; + + env->tlb->nb_tlb =3D 1; + env->tlb->map_address =3D &no_mmu_map_address; +} + +static void fixed_mmu_init(MIPSCPU *cpu) +{ + CPUMIPSState *env =3D &cpu->env; + + env->tlb->nb_tlb =3D 1; + env->tlb->map_address =3D &fixed_mmu_map_address; +} + +static void r4k_mmu_init(MIPSCPU *cpu) +{ + MIPSCPUClass *cpu_class =3D MIPS_CPU_GET_CLASS(cpu); + CPUMIPSState *env =3D &cpu->env; + + env->tlb->nb_tlb =3D 1 + ((cpu_class->cp0_config1 >> CP0C1_MMU) & 63= ); + env->tlb->map_address =3D &r4k_map_address; + env->tlb->helper_tlbwi =3D r4k_helper_tlbwi; + env->tlb->helper_tlbwr =3D r4k_helper_tlbwr; + env->tlb->helper_tlbp =3D r4k_helper_tlbp; + env->tlb->helper_tlbr =3D r4k_helper_tlbr; +} + +static void mmu_init(MIPSCPU *cpu) +{ + MIPSCPUClass *cpu_class =3D MIPS_CPU_GET_CLASS(cpu); + CPUMIPSState *env =3D &cpu->env; + + env->tlb =3D g_malloc0(sizeof(CPUMIPSTLBContext)); + + switch (cpu_class->mmu_type) { + case MMU_TYPE_NONE: + no_mmu_init(cpu); + break; + case MMU_TYPE_R4000: + r4k_mmu_init(cpu); + break; + case MMU_TYPE_FMT: + fixed_mmu_init(cpu); + break; + case MMU_TYPE_R3000: + case MMU_TYPE_R6000: + case MMU_TYPE_R8000: + default: + cpu_abort(env, "MMU type not supported\n"); + } +} +#endif /* CONFIG_USER_ONLY */ + +static void fpu_init(MIPSCPU *cpu) +{ + MIPSCPUClass *cpu_class =3D MIPS_CPU_GET_CLASS(cpu); + CPUMIPSState *env =3D &cpu->env; + int i; + + for (i =3D 0; i < MIPS_FPU_MAX; i++) { + env->fpus[i].fcr0 =3D cpu_class->cp1_fcr0; + } + + memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); +} + +static void mvp_init(MIPSCPU *cpu) +{ + CPUMIPSState *env =3D &cpu->env; + env->mvp =3D g_malloc0(sizeof(CPUMIPSMVPContext)); + + /* MVPConf1 implemented, TLB sharable, no gating storage support, + programmable cache partitioning implemented, number of allocatabl= e + and sharable TLB entries, MVP has allocatable TCs, 2 VPEs + implemented, 5 TCs implemented. */ + env->mvp->CP0_MVPConf0 =3D (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) = | + (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | +/* TODO: actually do 2 VPEs. + * (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE= ) | + * (0x04 << CP0MVPC0_PTC); + */ + (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE= ) | + (0x00 << CP0MVPC0_PTC); +#if !defined(CONFIG_USER_ONLY) + /* Usermode has no TLB support */ + env->mvp->CP0_MVPConf0 |=3D (env->tlb->nb_tlb << CP0MVPC0_PTLBE); +#endif + + /* Allocatable CP1 have media extensions, allocatable CP1 have FP su= pport, + no UDI implemented, no CP2 implemented, 1 CP1 implemented. */ + env->mvp->CP0_MVPConf1 =3D (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF)= | + (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PC= P2) | + (0x1 << CP0MVPC1_PCP1); +} + +static void mips_cpu_reset(CPUState *c) +{ + MIPSCPU *cpu =3D MIPS_CPU(c); + MIPSCPUClass *cpu_class =3D MIPS_CPU_GET_CLASS(cpu); + CPUMIPSState *env =3D &cpu->env; + + if (qemu_loglevel_mask(CPU_LOG_RESET)) { + qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); + log_cpu_state(env, 0); + } + + cpu_class->parent_reset(c); + + memset(env, 0, offsetof(CPUMIPSState, breakpoints)); + tlb_flush(env, 1); + + /* Reset registers to their default values */ + env->CP0_PRid =3D cpu_class->cp0_prid; + env->CP0_Config0 =3D cpu_class->cp0_config0; +#ifdef TARGET_WORDS_BIGENDIAN + env->CP0_Config0 |=3D (1 << CP0C0_BE); +#endif + env->CP0_Config1 =3D cpu_class->cp0_config1; + env->CP0_Config2 =3D cpu_class->cp0_config2; + env->CP0_Config3 =3D cpu_class->cp0_config3; + env->CP0_Config6 =3D cpu_class->cp0_config6; + env->CP0_Config7 =3D cpu_class->cp0_config7; + env->CP0_LLAddr_rw_bitmask =3D cpu_class->cp0_lladdr_rw_bitmask + << cpu_class->cp0_lladdr_shift; + env->CP0_LLAddr_shift =3D cpu_class->cp0_lladdr_shift; + env->SYNCI_Step =3D cpu_class->synci_step; + env->CCRes =3D cpu_class->ccres; + env->CP0_Status_rw_bitmask =3D cpu_class->cp0_status_rw_bitmask; + env->CP0_TCStatus_rw_bitmask =3D cpu_class->cp0_tcstatus_rw_bitmask; + env->CP0_SRSCtl =3D cpu_class->cp0_srsctl; + env->current_tc =3D 0; + env->SEGBITS =3D cpu_class->segbits; + env->SEGMask =3D (target_ulong)((1ULL << cpu_class->segbits) - 1); +#if defined(TARGET_MIPS64) + if (cpu_class->insn_flags & ISA_MIPS3) { + env->SEGMask |=3D 3ULL << 62; + } +#endif + env->PABITS =3D cpu_class->pabits; + env->PAMask =3D (target_ulong)((1ULL << cpu_class->pabits) - 1); + env->CP0_SRSConf0_rw_bitmask =3D cpu_class->cp0_srsconf_rw_bitmask[0= ]; + env->CP0_SRSConf0 =3D cpu_class->cp0_srsconf[0]; + env->CP0_SRSConf1_rw_bitmask =3D cpu_class->cp0_srsconf_rw_bitmask[1= ]; + env->CP0_SRSConf1 =3D cpu_class->cp0_srsconf[1]; + env->CP0_SRSConf2_rw_bitmask =3D cpu_class->cp0_srsconf_rw_bitmask[2= ]; + env->CP0_SRSConf2 =3D cpu_class->cp0_srsconf[2]; + env->CP0_SRSConf3_rw_bitmask =3D cpu_class->cp0_srsconf_rw_bitmask[3= ]; + env->CP0_SRSConf3 =3D cpu_class->cp0_srsconf[3]; + env->CP0_SRSConf4_rw_bitmask =3D cpu_class->cp0_srsconf_rw_bitmask[4= ]; + env->CP0_SRSConf4 =3D cpu_class->cp0_srsconf[4]; + env->insn_flags =3D cpu_class->insn_flags; + +#if defined(CONFIG_USER_ONLY) + env->hflags =3D MIPS_HFLAG_UM; + /* Enable access to the SYNCI_Step register. */ + env->CP0_HWREna |=3D (1 << 1); + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + env->hflags |=3D MIPS_HFLAG_FPU; + } +#ifdef TARGET_MIPS64 + if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { + env->hflags |=3D MIPS_HFLAG_F64; + } +#endif +#else + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, + come back to the jump. */ + env->CP0_ErrorEPC =3D env->active_tc.PC - 4; + } else { + env->CP0_ErrorEPC =3D env->active_tc.PC; + } + env->active_tc.PC =3D (int32_t)0xBFC00000; + env->CP0_Random =3D env->tlb->nb_tlb - 1; + env->tlb->tlb_in_use =3D env->tlb->nb_tlb; + env->CP0_Wired =3D 0; + env->CP0_EBase =3D 0x80000000 | (env->cpu_index & 0x3FF); + env->CP0_Status =3D (1 << CP0St_BEV) | (1 << CP0St_ERL); + /* vectored interrupts not implemented, timer on int 7, + no performance counters. */ + env->CP0_IntCtl =3D 0xe0000000; + { + int i; + + for (i =3D 0; i < 7; i++) { + env->CP0_WatchLo[i] =3D 0; + env->CP0_WatchHi[i] =3D 0x80000000; + } + env->CP0_WatchLo[7] =3D 0; + env->CP0_WatchHi[7] =3D 0; + } + /* Count register increments in debug mode, EJTAG version 1 */ + env->CP0_Debug =3D (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); + env->hflags =3D MIPS_HFLAG_CP0; + + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + int i; + + /* Only TC0 on VPE 0 starts as active. */ + for (i =3D 0; i < ARRAY_SIZE(env->tcs); i++) { + env->tcs[i].CP0_TCBind =3D env->cpu_index << CP0TCBd_CurVPE; + env->tcs[i].CP0_TCHalt =3D 1; + } + env->active_tc.CP0_TCHalt =3D 1; + env->halted =3D 1; + + if (!env->cpu_index) { + /* VPE0 starts up enabled. */ + env->mvp->CP0_MVPControl |=3D (1 << CP0MVPCo_EVP); + env->CP0_VPEConf0 |=3D (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_= VPA); + + /* TC0 starts up unhalted. */ + env->halted =3D 0; + env->active_tc.CP0_TCHalt =3D 0; + env->tcs[0].CP0_TCHalt =3D 0; + /* With thread 0 active. */ + env->active_tc.CP0_TCStatus =3D (1 << CP0TCSt_A); + env->tcs[0].CP0_TCStatus =3D (1 << CP0TCSt_A); + } + } +#endif +#if defined(TARGET_MIPS64) + if (cpu_class->insn_flags & ISA_MIPS3) { + env->hflags |=3D MIPS_HFLAG_64; + } +#endif + env->exception_index =3D EXCP_NONE; +} + +/* CPU / CPU family specific config register values. */ + +/* Have config1, uncached coherency */ +#define MIPS_CONFIG0 \ + ((1 << CP0C0_M) | (0x2 << CP0C0_K0)) + +/* Have config2, no coprocessor2 attached, no MDMX support attached, + no performance counters, watch registers present, + no code compression, EJTAG present, no FPU */ +#define MIPS_CONFIG1 \ +((1 << CP0C1_M) | \ + (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ + (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \ + (0 << CP0C1_FP)) + +/* Have config3, no tertiary/secondary caches implemented */ +#define MIPS_CONFIG2 \ +((1 << CP0C2_M)) + +/* No config4, no DSP ASE, no large physaddr (PABITS), + no external interrupt controller, no vectored interrupts, + no 1kb pages, no SmartMIPS ASE, no trace logic */ +#define MIPS_CONFIG3 \ +((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ + (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ + (0 << CP0C3_SM) | (0 << CP0C3_TL)) + +typedef struct MIPSCPUInfo { + const char *name; + int32_t CP0_PRid; + int32_t CP0_Config0; + int32_t CP0_Config1; + int32_t CP0_Config2; + int32_t CP0_Config3; + int32_t CP0_Config6; + int32_t CP0_Config7; + target_ulong CP0_LLAddr_rw_bitmask; + int CP0_LLAddr_shift; + int32_t SYNCI_Step; + int32_t CCRes; + int32_t CP0_Status_rw_bitmask; + int32_t CP0_TCStatus_rw_bitmask; + int32_t CP0_SRSCtl; + int32_t CP1_fcr0; + int32_t SEGBITS; + int32_t PABITS; + int32_t CP0_SRSConf0_rw_bitmask; + int32_t CP0_SRSConf0; + int32_t CP0_SRSConf1_rw_bitmask; + int32_t CP0_SRSConf1; + int32_t CP0_SRSConf2_rw_bitmask; + int32_t CP0_SRSConf2; + int32_t CP0_SRSConf3_rw_bitmask; + int32_t CP0_SRSConf3; + int32_t CP0_SRSConf4_rw_bitmask; + int32_t CP0_SRSConf4; + int insn_flags; + enum MIPSMMUTypes mmu_type; +} MIPSCPUInfo; + +/***********************************************************************= ******/ +/* MIPS CPU definitions */ +static const MIPSCPUInfo mips_cpus[] =3D { + { + .name =3D "4Kc", + .CP0_PRid =3D 0x00018000, + .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (0 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1278FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "4Km", + .CP0_PRid =3D 0x00018300, + /* Config1 implemented, fixed mapping MMU, + no virtual icache, uncached coherency. */ + .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1258FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32 | ASE_MIPS16, + .mmu_type =3D MMU_TYPE_FMT, + }, + { + .name =3D "4KEcR1", + .CP0_PRid =3D 0x00018400, + .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (0 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1278FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "4KEmR1", + .CP0_PRid =3D 0x00018500, + .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1258FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32 | ASE_MIPS16, + .mmu_type =3D MMU_TYPE_FMT, + }, + { + .name =3D "4KEc", + .CP0_PRid =3D 0x00019000, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (0 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1278FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32R2, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "4KEm", + .CP0_PRid =3D 0x00019100, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_FMT << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x1258FF17, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, + .mmu_type =3D MMU_TYPE_FMT, + }, + { + .name =3D "24Kc", + .CP0_PRid =3D 0x00019300, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + /* No DSP implemented. */ + .CP0_Status_rw_bitmask =3D 0x1278FF1F, + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "24Kf", + .CP0_PRid =3D 0x00019300, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_M= MU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + /* No DSP implemented. */ + .CP0_Status_rw_bitmask =3D 0x3678FF1F, + .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "34Kf", + .CP0_PRid =3D 0x00019500, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_M= MU) | + (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | + (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_CA), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_= MT), + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 0, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + /* No DSP implemented. */ + .CP0_Status_rw_bitmask =3D 0x3678FF1F, + /* No DSP implemented. */ + .CP0_TCStatus_rw_bitmask =3D (0 << CP0TCSt_TCU3) | (0 << CP0TCSt= _TCU2) | + (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | + (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | + (1 << CP0TCSt_DA) | (1 << CP0TCSt_A) | + (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) | + (0xff << CP0TCSt_TASID), + .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID), + .CP0_SRSCtl =3D (0xf << CP0SRSCtl_HSS), + .CP0_SRSConf0_rw_bitmask =3D 0x3fffffff, + .CP0_SRSConf0 =3D (1 << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) | + (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1), + .CP0_SRSConf1_rw_bitmask =3D 0x3fffffff, + .CP0_SRSConf1 =3D (1 << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) | + (0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4), + .CP0_SRSConf2_rw_bitmask =3D 0x3fffffff, + .CP0_SRSConf2 =3D (1 << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) | + (0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7), + .CP0_SRSConf3_rw_bitmask =3D 0x3fffffff, + .CP0_SRSConf3 =3D (1 << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) = | + (0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10= ), + .CP0_SRSConf4_rw_bitmask =3D 0x3fffffff, + .CP0_SRSConf4 =3D (0x3fe << CP0SRSC4_SRS15) | + (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13= ), + .SEGBITS =3D 32, + .PABITS =3D 32, + .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT, + .mmu_type =3D MMU_TYPE_R4000, + }, +#if defined(TARGET_MIPS64) + { + .name =3D "R4000", + .CP0_PRid =3D 0x00000400, + /* No L2 cache, icache size 8k, dcache size 8k, uncached coheren= cy. */ + .CP0_Config0 =3D (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << C= P0C0_K0), + /* Note: Config1 is only used internally, the R4000 has only Con= fig0. */ + .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), + .CP0_LLAddr_rw_bitmask =3D 0xFFFFFFFF, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 16, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x3678FFFF, + /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits.= */ + .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), + .SEGBITS =3D 40, + .PABITS =3D 36, + .insn_flags =3D CPU_MIPS3, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "VR5432", + .CP0_PRid =3D 0x00005400, + /* No L2 cache, icache size 8k, dcache size 8k, uncached coheren= cy. */ + .CP0_Config0 =3D (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << C= P0C0_K0), + .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), + .CP0_LLAddr_rw_bitmask =3D 0xFFFFFFFFL, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 16, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x3678FFFF, + /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits= . */ + .CP1_fcr0 =3D (0x54 << FCR0_PRID) | (0x0 << FCR0_REV), + .SEGBITS =3D 40, + .PABITS =3D 32, + .insn_flags =3D CPU_VR54XX, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "5Kc", + .CP0_PRid =3D 0x00018100, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (31 << CP0C1_MMU) | + (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_I= A) | + (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x32F8FFFF, + .SEGBITS =3D 42, + .PABITS =3D 36, + .insn_flags =3D CPU_MIPS64, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "5Kf", + .CP0_PRid =3D 0x00018100, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_M= MU) | + (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_I= A) | + (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_D= A) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x36F8FFFF, + /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ + .CP1_fcr0 =3D (1 << FCR0_D) | (1 << FCR0_S) | + (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), + .SEGBITS =3D 42, + .PABITS =3D 36, + .insn_flags =3D CPU_MIPS64, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "20Kc", + /* We emulate a later version of the 20Kc, earlier ones had a br= oken + WAIT instruction. */ + .CP0_PRid =3D 0x000182a0, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_M= MU) | + (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_I= A) | + (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_D= A) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 0, + .SYNCI_Step =3D 32, + .CCRes =3D 1, + .CP0_Status_rw_bitmask =3D 0x36FBFFFF, + /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */ + .CP1_fcr0 =3D (1 << FCR0_3D) | (1 << FCR0_PS) | + (1 << FCR0_D) | (1 << FCR0_S) | + (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), + .SEGBITS =3D 40, + .PABITS =3D 36, + .insn_flags =3D CPU_MIPS64 | ASE_MIPS3D, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + /* A generic CPU providing MIPS64 Release 2 features. + FIXME: Eventually this should be replaced by a real CPU model= . */ + .name =3D "MIPS64R2-generic", + .CP0_PRid =3D 0x00010000, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C= 0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_M= MU) | + (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_I= A) | + (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_D= A) | + (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), + .CP0_Config2 =3D MIPS_CONFIG2, + .CP0_Config3 =3D MIPS_CONFIG3 | (1 << CP0C3_LPA), + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 0, + .SYNCI_Step =3D 32, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x36FBFFFF, + .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) = | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_R= EV), + .SEGBITS =3D 42, + /* The architectural limit is 59, but we have hardcoded 36 bit + in some places... + .PABITS =3D 59, */ /* the architectural limit */ + .PABITS =3D 36, + .insn_flags =3D CPU_MIPS64R2 | ASE_MIPS3D, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "Loongson-2E", + .CP0_PRid =3D 0x6302, + /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/ + .CP0_Config0 =3D (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | = (0x1<<5) | + (0x1<<4) | (0x1<<1), + /* Note: Config1 is only used internally, + Loongson-2E has only Config0. */ + .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), + .SYNCI_Step =3D 16, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0x35D0FFFF, + .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + .SEGBITS =3D 40, + .PABITS =3D 40, + .insn_flags =3D CPU_LOONGSON2E, + .mmu_type =3D MMU_TYPE_R4000, + }, + { + .name =3D "Loongson-2F", + .CP0_PRid =3D 0x6303, + /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/ + .CP0_Config0 =3D (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0= x1<<5) | + (0x1<<4) | (0x1<<1), + /* Note: Config1 is only used internally, Loongson-2F has only Con= fig0. */ + .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), + .SYNCI_Step =3D 16, + .CCRes =3D 2, + .CP0_Status_rw_bitmask =3D 0xF5D0FF1F, /*bit5:7 not writable*/ + .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), + .SEGBITS =3D 40, + .PABITS =3D 40, + .insn_flags =3D CPU_LOONGSON2F, + .mmu_type =3D MMU_TYPE_R4000, + }, + +#endif +}; + +static void mips_cpu_initfn(Object *obj) +{ + MIPSCPU *cpu =3D MIPS_CPU(obj); + CPUMIPSState *env =3D &cpu->env; + + memset(env, 0, sizeof(CPUMIPSState)); + env->cpu_model_str =3D object_get_typename(obj); + cpu_exec_init(env); + +#ifndef CONFIG_USER_ONLY + mmu_init(cpu); +#endif + fpu_init(cpu); + mvp_init(cpu); + CPU_CLASS(MIPS_CPU_GET_CLASS(cpu))->reset(CPU(cpu)); +} + +static void mips_cpu_class_init(ObjectClass *klass, void *data) +{ + CPUClass *cpu_class =3D CPU_CLASS(klass); + MIPSCPUClass *k =3D MIPS_CPU_CLASS(klass); + const MIPSCPUInfo *info =3D data; + + k->parent_reset =3D cpu_class->reset; + cpu_class->reset =3D mips_cpu_reset; + + k->cp0_prid =3D info->CP0_PRid; + k->cp0_config0 =3D info->CP0_Config0; + k->cp0_config1 =3D info->CP0_Config1; + k->cp0_config2 =3D info->CP0_Config2; + k->cp0_config3 =3D info->CP0_Config3; + k->cp0_config6 =3D info->CP0_Config6; + k->cp0_config7 =3D info->CP0_Config7; + k->cp0_lladdr_rw_bitmask =3D info->CP0_LLAddr_rw_bitmask; + k->cp0_lladdr_shift =3D info->CP0_LLAddr_shift; + k->synci_step =3D info->SYNCI_Step; + k->ccres =3D info->CCRes; + k->cp0_status_rw_bitmask =3D info->CP0_Status_rw_bitmask; + k->cp0_tcstatus_rw_bitmask =3D info->CP0_TCStatus_rw_bitmask; + k->cp0_srsctl =3D info->CP0_SRSCtl; + k->cp1_fcr0 =3D info->CP1_fcr0; + k->segbits =3D info->SEGBITS; + k->pabits =3D info->PABITS; + k->cp0_srsconf_rw_bitmask[0] =3D info->CP0_SRSConf0_rw_bitmask; + k->cp0_srsconf_rw_bitmask[1] =3D info->CP0_SRSConf1_rw_bitmask; + k->cp0_srsconf_rw_bitmask[2] =3D info->CP0_SRSConf2_rw_bitmask; + k->cp0_srsconf_rw_bitmask[3] =3D info->CP0_SRSConf3_rw_bitmask; + k->cp0_srsconf_rw_bitmask[4] =3D info->CP0_SRSConf4_rw_bitmask; + k->cp0_srsconf[0] =3D info->CP0_SRSConf0; + k->cp0_srsconf[1] =3D info->CP0_SRSConf1; + k->cp0_srsconf[2] =3D info->CP0_SRSConf2; + k->cp0_srsconf[3] =3D info->CP0_SRSConf3; + k->cp0_srsconf[4] =3D info->CP0_SRSConf4; + k->insn_flags =3D info->insn_flags; + k->mmu_type =3D info->mmu_type; +} + +static void mips_register_cpu(const MIPSCPUInfo *info) +{ + TypeInfo type =3D { + .name =3D info->name, + .parent =3D TYPE_MIPS_CPU, + .instance_size =3D sizeof(MIPSCPU), + .instance_init =3D mips_cpu_initfn, + .class_size =3D sizeof(MIPSCPUClass), + .class_init =3D mips_cpu_class_init, + .class_data =3D (void *)info, + }; + + type_register_static(&type); +} + +static const TypeInfo mips_cpu_info =3D { + .name =3D TYPE_MIPS_CPU, + .parent =3D TYPE_CPU, + .instance_size =3D sizeof(MIPSCPU), + .abstract =3D true, + .class_size =3D sizeof(MIPSCPUClass), +}; + +static void mips_cpu_register_types(void) +{ + int i; + + type_register_static(&mips_cpu_info); + for (i =3D 0; i < ARRAY_SIZE(mips_cpus); i++) { + mips_register_cpu(&mips_cpus[i]); + } +} + +type_init(mips_cpu_register_types) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 7430aa5..12e9d6f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -478,7 +478,6 @@ struct CPUMIPSState { CPUMIPSTLBContext *tlb; #endif =20 - const mips_def_t *cpu_model; void *irq[8]; struct QEMUTimer *timer; /* Internal timer */ }; @@ -729,6 +728,7 @@ static inline int cpu_has_work(CPUMIPSState *env) } =20 #include "exec-all.h" +#include "cpu-qom.h" =20 static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *t= b) { diff --git a/target-mips/translate.c b/target-mips/translate.c index a663b74..db0ebda 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4,6 +4,7 @@ * Copyright (c) 2004-2005 Jocelyn Mayer * Copyright (c) 2006 Marius Groeger (FPU operations) * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2007 Herv=C3=A9 Poussineau * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) * * This library is free software; you can redistribute it and/or @@ -12687,158 +12688,64 @@ static void mips_tcg_init(void) inited =3D 1; } =20 -#include "translate_init.c" +struct MIPSCPUListState { + fprintf_function cpu_fprintf; + FILE *file; +}; =20 -CPUMIPSState *cpu_mips_init (const char *cpu_model) +/* Sort alphabetically. */ +static gint mips_cpu_list_compare(gconstpointer a, gconstpointer b) { - CPUMIPSState *env; - const mips_def_t *def; - - def =3D cpu_mips_find_by_name(cpu_model); - if (!def) - return NULL; - env =3D g_malloc0(sizeof(CPUMIPSState)); - env->cpu_model =3D def; - env->cpu_model_str =3D cpu_model; + ObjectClass *class_a =3D (ObjectClass *)a; + ObjectClass *class_b =3D (ObjectClass *)b; =20 - cpu_exec_init(env); -#ifndef CONFIG_USER_ONLY - mmu_init(env, def); -#endif - fpu_init(env, def); - mvp_init(env, def); - mips_tcg_init(); - cpu_state_reset(env); - qemu_init_vcpu(env); - return env; + return strcasecmp(object_class_get_name(class_a), + object_class_get_name(class_b)); } =20 -void cpu_state_reset(CPUMIPSState *env) +static void mips_cpu_list_entry(gpointer data, gpointer user_data) { - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); - log_cpu_state(env, 0); - } + ObjectClass *klass =3D data; + struct MIPSCPUListState *s =3D user_data; =20 - memset(env, 0, offsetof(CPUMIPSState, breakpoints)); - tlb_flush(env, 1); + (*s->cpu_fprintf)(s->file, "MIPS '%s'\n", + object_class_get_name(klass)); +} =20 - /* Reset registers to their default values */ - env->CP0_PRid =3D env->cpu_model->CP0_PRid; - env->CP0_Config0 =3D env->cpu_model->CP0_Config0; -#ifdef TARGET_WORDS_BIGENDIAN - env->CP0_Config0 |=3D (1 << CP0C0_BE); -#endif - env->CP0_Config1 =3D env->cpu_model->CP0_Config1; - env->CP0_Config2 =3D env->cpu_model->CP0_Config2; - env->CP0_Config3 =3D env->cpu_model->CP0_Config3; - env->CP0_Config6 =3D env->cpu_model->CP0_Config6; - env->CP0_Config7 =3D env->cpu_model->CP0_Config7; - env->CP0_LLAddr_rw_bitmask =3D env->cpu_model->CP0_LLAddr_rw_bitmask - << env->cpu_model->CP0_LLAddr_shift; - env->CP0_LLAddr_shift =3D env->cpu_model->CP0_LLAddr_shift; - env->SYNCI_Step =3D env->cpu_model->SYNCI_Step; - env->CCRes =3D env->cpu_model->CCRes; - env->CP0_Status_rw_bitmask =3D env->cpu_model->CP0_Status_rw_bitmask= ; - env->CP0_TCStatus_rw_bitmask =3D env->cpu_model->CP0_TCStatus_rw_bit= mask; - env->CP0_SRSCtl =3D env->cpu_model->CP0_SRSCtl; - env->current_tc =3D 0; - env->SEGBITS =3D env->cpu_model->SEGBITS; - env->SEGMask =3D (target_ulong)((1ULL << env->cpu_model->SEGBITS) - = 1); -#if defined(TARGET_MIPS64) - if (env->cpu_model->insn_flags & ISA_MIPS3) { - env->SEGMask |=3D 3ULL << 62; - } -#endif - env->PABITS =3D env->cpu_model->PABITS; - env->PAMask =3D (target_ulong)((1ULL << env->cpu_model->PABITS) - 1)= ; - env->CP0_SRSConf0_rw_bitmask =3D env->cpu_model->CP0_SRSConf0_rw_bit= mask; - env->CP0_SRSConf0 =3D env->cpu_model->CP0_SRSConf0; - env->CP0_SRSConf1_rw_bitmask =3D env->cpu_model->CP0_SRSConf1_rw_bit= mask; - env->CP0_SRSConf1 =3D env->cpu_model->CP0_SRSConf1; - env->CP0_SRSConf2_rw_bitmask =3D env->cpu_model->CP0_SRSConf2_rw_bit= mask; - env->CP0_SRSConf2 =3D env->cpu_model->CP0_SRSConf2; - env->CP0_SRSConf3_rw_bitmask =3D env->cpu_model->CP0_SRSConf3_rw_bit= mask; - env->CP0_SRSConf3 =3D env->cpu_model->CP0_SRSConf3; - env->CP0_SRSConf4_rw_bitmask =3D env->cpu_model->CP0_SRSConf4_rw_bit= mask; - env->CP0_SRSConf4 =3D env->cpu_model->CP0_SRSConf4; - env->insn_flags =3D env->cpu_model->insn_flags; +void mips_cpu_list(FILE *f, fprintf_function cpu_fprintf) +{ + struct MIPSCPUListState s =3D { + .cpu_fprintf =3D cpu_fprintf, + .file =3D f, + }; + GSList *list; =20 -#if defined(CONFIG_USER_ONLY) - env->hflags =3D MIPS_HFLAG_UM; - /* Enable access to the SYNCI_Step register. */ - env->CP0_HWREna |=3D (1 << 1); - if (env->CP0_Config1 & (1 << CP0C1_FP)) { - env->hflags |=3D MIPS_HFLAG_FPU; - } -#ifdef TARGET_MIPS64 - if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { - env->hflags |=3D MIPS_HFLAG_F64; - } -#endif -#else - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_ErrorEPC =3D env->active_tc.PC - 4; - } else { - env->CP0_ErrorEPC =3D env->active_tc.PC; - } - env->active_tc.PC =3D (int32_t)0xBFC00000; - env->CP0_Random =3D env->tlb->nb_tlb - 1; - env->tlb->tlb_in_use =3D env->tlb->nb_tlb; - env->CP0_Wired =3D 0; - env->CP0_EBase =3D 0x80000000 | (env->cpu_index & 0x3FF); - env->CP0_Status =3D (1 << CP0St_BEV) | (1 << CP0St_ERL); - /* vectored interrupts not implemented, timer on int 7, - no performance counters. */ - env->CP0_IntCtl =3D 0xe0000000; - { - int i; + list =3D object_class_get_list(TYPE_MIPS_CPU, false); + list =3D g_slist_sort(list, mips_cpu_list_compare); + g_slist_foreach(list, mips_cpu_list_entry, &s); + g_slist_free(list); +} =20 - for (i =3D 0; i < 7; i++) { - env->CP0_WatchLo[i] =3D 0; - env->CP0_WatchHi[i] =3D 0x80000000; - } - env->CP0_WatchLo[7] =3D 0; - env->CP0_WatchHi[7] =3D 0; - } - /* Count register increments in debug mode, EJTAG version 1 */ - env->CP0_Debug =3D (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); - env->hflags =3D MIPS_HFLAG_CP0; +CPUMIPSState *cpu_mips_init(const char *cpu_model) +{ + MIPSCPU *cpu; + CPUMIPSState *env; =20 - if (env->CP0_Config3 & (1 << CP0C3_MT)) { - int i; + if (object_class_by_name(cpu_model) =3D=3D NULL) { + return NULL; + } + cpu =3D MIPS_CPU(object_new(cpu_model)); + env =3D &cpu->env; =20 - /* Only TC0 on VPE 0 starts as active. */ - for (i =3D 0; i < ARRAY_SIZE(env->tcs); i++) { - env->tcs[i].CP0_TCBind =3D env->cpu_index << CP0TCBd_CurVPE; - env->tcs[i].CP0_TCHalt =3D 1; - } - env->active_tc.CP0_TCHalt =3D 1; - env->halted =3D 1; + mips_tcg_init(); =20 - if (!env->cpu_index) { - /* VPE0 starts up enabled. */ - env->mvp->CP0_MVPControl |=3D (1 << CP0MVPCo_EVP); - env->CP0_VPEConf0 |=3D (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_= VPA); + qemu_init_vcpu(env); + return env; +} =20 - /* TC0 starts up unhalted. */ - env->halted =3D 0; - env->active_tc.CP0_TCHalt =3D 0; - env->tcs[0].CP0_TCHalt =3D 0; - /* With thread 0 active. */ - env->active_tc.CP0_TCStatus =3D (1 << CP0TCSt_A); - env->tcs[0].CP0_TCStatus =3D (1 << CP0TCSt_A); - } - } -#endif -#if defined(TARGET_MIPS64) - if (env->cpu_model->insn_flags & ISA_MIPS3) { - env->hflags |=3D MIPS_HFLAG_64; - } -#endif - env->exception_index =3D EXCP_NONE; +void cpu_state_reset(CPUMIPSState *env) +{ + cpu_reset(ENV_GET_CPU(env)); } =20 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int p= c_pos) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c deleted file mode 100644 index c39138f..0000000 --- a/target-mips/translate_init.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * MIPS emulation for qemu: CPU initialisation routines. - * - * Copyright (c) 2004-2005 Jocelyn Mayer - * Copyright (c) 2007 Herve Poussineau - * - * 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, see . - */ - -/* CPU / CPU family specific config register values. */ - -/* Have config1, uncached coherency */ -#define MIPS_CONFIG0 \ - ((1 << CP0C0_M) | (0x2 << CP0C0_K0)) - -/* Have config2, no coprocessor2 attached, no MDMX support attached, - no performance counters, watch registers present, - no code compression, EJTAG present, no FPU */ -#define MIPS_CONFIG1 \ -((1 << CP0C1_M) | \ - (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ - (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \ - (0 << CP0C1_FP)) - -/* Have config3, no tertiary/secondary caches implemented */ -#define MIPS_CONFIG2 \ -((1 << CP0C2_M)) - -/* No config4, no DSP ASE, no large physaddr (PABITS), - no external interrupt controller, no vectored interrupts, - no 1kb pages, no SmartMIPS ASE, no trace logic */ -#define MIPS_CONFIG3 \ -((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ - (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ - (0 << CP0C3_SM) | (0 << CP0C3_TL)) - -/* MMU types, the first four entries have the same layout as the - CP0C0_MT field. */ -enum mips_mmu_types { - MMU_TYPE_NONE, - MMU_TYPE_R4000, - MMU_TYPE_RESERVED, - MMU_TYPE_FMT, - MMU_TYPE_R3000, - MMU_TYPE_R6000, - MMU_TYPE_R8000 -}; - -struct mips_def_t { - const char *name; - int32_t CP0_PRid; - int32_t CP0_Config0; - int32_t CP0_Config1; - int32_t CP0_Config2; - int32_t CP0_Config3; - int32_t CP0_Config6; - int32_t CP0_Config7; - target_ulong CP0_LLAddr_rw_bitmask; - int CP0_LLAddr_shift; - int32_t SYNCI_Step; - int32_t CCRes; - int32_t CP0_Status_rw_bitmask; - int32_t CP0_TCStatus_rw_bitmask; - int32_t CP0_SRSCtl; - int32_t CP1_fcr0; - int32_t SEGBITS; - int32_t PABITS; - int32_t CP0_SRSConf0_rw_bitmask; - int32_t CP0_SRSConf0; - int32_t CP0_SRSConf1_rw_bitmask; - int32_t CP0_SRSConf1; - int32_t CP0_SRSConf2_rw_bitmask; - int32_t CP0_SRSConf2; - int32_t CP0_SRSConf3_rw_bitmask; - int32_t CP0_SRSConf3; - int32_t CP0_SRSConf4_rw_bitmask; - int32_t CP0_SRSConf4; - int insn_flags; - enum mips_mmu_types mmu_type; -}; - -/***********************************************************************= ******/ -/* MIPS CPU definitions */ -static const mips_def_t mips_defs[] =3D -{ - { - .name =3D "4Kc", - .CP0_PRid =3D 0x00018000, - .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (0 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1278FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "4Km", - .CP0_PRid =3D 0x00018300, - /* Config1 implemented, fixed mapping MMU, - no virtual icache, uncached coherency. */ - .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1258FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32 | ASE_MIPS16, - .mmu_type =3D MMU_TYPE_FMT, - }, - { - .name =3D "4KEcR1", - .CP0_PRid =3D 0x00018400, - .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (0 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1278FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "4KEmR1", - .CP0_PRid =3D 0x00018500, - .CP0_Config0 =3D MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1258FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32 | ASE_MIPS16, - .mmu_type =3D MMU_TYPE_FMT, - }, - { - .name =3D "4KEc", - .CP0_PRid =3D 0x00019000, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (0 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1278FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32R2, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "4KEm", - .CP0_PRid =3D 0x00019100, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | - (MMU_TYPE_FMT << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x1258FF17, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, - .mmu_type =3D MMU_TYPE_FMT, - }, - { - .name =3D "24Kc", - .CP0_PRid =3D 0x00019300, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (15 << CP0C1_MMU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - /* No DSP implemented. */ - .CP0_Status_rw_bitmask =3D 0x1278FF1F, - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "24Kf", - .CP0_PRid =3D 0x00019300, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_M= MU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3 | (0 << CP0C3_VInt), - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - /* No DSP implemented. */ - .CP0_Status_rw_bitmask =3D 0x3678FF1F, - .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | - (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "34Kf", - .CP0_PRid =3D 0x00019500, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_M= MU) | - (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_I= A) | - (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_CA), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_= MT), - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 0, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - /* No DSP implemented. */ - .CP0_Status_rw_bitmask =3D 0x3678FF1F, - /* No DSP implemented. */ - .CP0_TCStatus_rw_bitmask =3D (0 << CP0TCSt_TCU3) | (0 << CP0TCSt= _TCU2) | - (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | - (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | - (1 << CP0TCSt_DA) | (1 << CP0TCSt_A) | - (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) | - (0xff << CP0TCSt_TASID), - .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | - (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID), - .CP0_SRSCtl =3D (0xf << CP0SRSCtl_HSS), - .CP0_SRSConf0_rw_bitmask =3D 0x3fffffff, - .CP0_SRSConf0 =3D (1 << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) | - (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1), - .CP0_SRSConf1_rw_bitmask =3D 0x3fffffff, - .CP0_SRSConf1 =3D (1 << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) | - (0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4), - .CP0_SRSConf2_rw_bitmask =3D 0x3fffffff, - .CP0_SRSConf2 =3D (1 << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) | - (0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7), - .CP0_SRSConf3_rw_bitmask =3D 0x3fffffff, - .CP0_SRSConf3 =3D (1 << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) = | - (0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10= ), - .CP0_SRSConf4_rw_bitmask =3D 0x3fffffff, - .CP0_SRSConf4 =3D (0x3fe << CP0SRSC4_SRS15) | - (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13= ), - .SEGBITS =3D 32, - .PABITS =3D 32, - .insn_flags =3D CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT, - .mmu_type =3D MMU_TYPE_R4000, - }, -#if defined(TARGET_MIPS64) - { - .name =3D "R4000", - .CP0_PRid =3D 0x00000400, - /* No L2 cache, icache size 8k, dcache size 8k, uncached coheren= cy. */ - .CP0_Config0 =3D (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << C= P0C0_K0), - /* Note: Config1 is only used internally, the R4000 has only Con= fig0. */ - .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), - .CP0_LLAddr_rw_bitmask =3D 0xFFFFFFFF, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 16, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x3678FFFF, - /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits.= */ - .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), - .SEGBITS =3D 40, - .PABITS =3D 36, - .insn_flags =3D CPU_MIPS3, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "VR5432", - .CP0_PRid =3D 0x00005400, - /* No L2 cache, icache size 8k, dcache size 8k, uncached coheren= cy. */ - .CP0_Config0 =3D (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << C= P0C0_K0), - .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), - .CP0_LLAddr_rw_bitmask =3D 0xFFFFFFFFL, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 16, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x3678FFFF, - /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits= . */ - .CP1_fcr0 =3D (0x54 << FCR0_PRID) | (0x0 << FCR0_REV), - .SEGBITS =3D 40, - .PABITS =3D 32, - .insn_flags =3D CPU_VR54XX, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "5Kc", - .CP0_PRid =3D 0x00018100, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (31 << CP0C1_MMU) | - (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_I= A) | - (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x32F8FFFF, - .SEGBITS =3D 42, - .PABITS =3D 36, - .insn_flags =3D CPU_MIPS64, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "5Kf", - .CP0_PRid =3D 0x00018100, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_M= MU) | - (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_I= A) | - (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_D= A) | - (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 4, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x36F8FFFF, - /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ - .CP1_fcr0 =3D (1 << FCR0_D) | (1 << FCR0_S) | - (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), - .SEGBITS =3D 42, - .PABITS =3D 36, - .insn_flags =3D CPU_MIPS64, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "20Kc", - /* We emulate a later version of the 20Kc, earlier ones had a br= oken - WAIT instruction. */ - .CP0_PRid =3D 0x000182a0, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x2 << CP0C0_AT) | - (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI), - .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_M= MU) | - (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_I= A) | - (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_D= A) | - (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3, - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 0, - .SYNCI_Step =3D 32, - .CCRes =3D 1, - .CP0_Status_rw_bitmask =3D 0x36FBFFFF, - /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */ - .CP1_fcr0 =3D (1 << FCR0_3D) | (1 << FCR0_PS) | - (1 << FCR0_D) | (1 << FCR0_S) | - (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), - .SEGBITS =3D 40, - .PABITS =3D 36, - .insn_flags =3D CPU_MIPS64 | ASE_MIPS3D, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - /* A generic CPU providing MIPS64 Release 2 features. - FIXME: Eventually this should be replaced by a real CPU model= . */ - .name =3D "MIPS64R2-generic", - .CP0_PRid =3D 0x00010000, - .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C= 0_AT) | - (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_M= MU) | - (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_I= A) | - (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_D= A) | - (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_E= P), - .CP0_Config2 =3D MIPS_CONFIG2, - .CP0_Config3 =3D MIPS_CONFIG3 | (1 << CP0C3_LPA), - .CP0_LLAddr_rw_bitmask =3D 0, - .CP0_LLAddr_shift =3D 0, - .SYNCI_Step =3D 32, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x36FBFFFF, - .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) = | - (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | - (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_R= EV), - .SEGBITS =3D 42, - /* The architectural limit is 59, but we have hardcoded 36 bit - in some places... - .PABITS =3D 59, */ /* the architectural limit */ - .PABITS =3D 36, - .insn_flags =3D CPU_MIPS64R2 | ASE_MIPS3D, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "Loongson-2E", - .CP0_PRid =3D 0x6302, - /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/ - .CP0_Config0 =3D (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | = (0x1<<5) | - (0x1<<4) | (0x1<<1), - /* Note: Config1 is only used internally, Loongson-2E has only C= onfig0. */ - .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), - .SYNCI_Step =3D 16, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x35D0FFFF, - .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), - .SEGBITS =3D 40, - .PABITS =3D 40, - .insn_flags =3D CPU_LOONGSON2E, - .mmu_type =3D MMU_TYPE_R4000, - }, - { - .name =3D "Loongson-2F", - .CP0_PRid =3D 0x6303, - /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/ - .CP0_Config0 =3D (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0= x1<<5) | - (0x1<<4) | (0x1<<1), - /* Note: Config1 is only used internally, Loongson-2F has only Con= fig0. */ - .CP0_Config1 =3D (1 << CP0C1_FP) | (47 << CP0C1_MMU), - .SYNCI_Step =3D 16, - .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0xF5D0FF1F, /*bit5:7 not writable*/ - .CP1_fcr0 =3D (0x5 << FCR0_PRID) | (0x1 << FCR0_REV), - .SEGBITS =3D 40, - .PABITS =3D 40, - .insn_flags =3D CPU_LOONGSON2F, - .mmu_type =3D MMU_TYPE_R4000, - }, - -#endif -}; - -static const mips_def_t *cpu_mips_find_by_name (const char *name) -{ - int i; - - for (i =3D 0; i < ARRAY_SIZE(mips_defs); i++) { - if (strcasecmp(name, mips_defs[i].name) =3D=3D 0) { - return &mips_defs[i]; - } - } - return NULL; -} - -void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf) -{ - int i; - - for (i =3D 0; i < ARRAY_SIZE(mips_defs); i++) { - (*cpu_fprintf)(f, "MIPS '%s'\n", - mips_defs[i].name); - } -} - -#ifndef CONFIG_USER_ONLY -static void no_mmu_init (CPUMIPSState *env, const mips_def_t *def) -{ - env->tlb->nb_tlb =3D 1; - env->tlb->map_address =3D &no_mmu_map_address; -} - -static void fixed_mmu_init (CPUMIPSState *env, const mips_def_t *def) -{ - env->tlb->nb_tlb =3D 1; - env->tlb->map_address =3D &fixed_mmu_map_address; -} - -static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def) -{ - env->tlb->nb_tlb =3D 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); - env->tlb->map_address =3D &r4k_map_address; - env->tlb->helper_tlbwi =3D r4k_helper_tlbwi; - env->tlb->helper_tlbwr =3D r4k_helper_tlbwr; - env->tlb->helper_tlbp =3D r4k_helper_tlbp; - env->tlb->helper_tlbr =3D r4k_helper_tlbr; -} - -static void mmu_init (CPUMIPSState *env, const mips_def_t *def) -{ - env->tlb =3D g_malloc0(sizeof(CPUMIPSTLBContext)); - - switch (def->mmu_type) { - case MMU_TYPE_NONE: - no_mmu_init(env, def); - break; - case MMU_TYPE_R4000: - r4k_mmu_init(env, def); - break; - case MMU_TYPE_FMT: - fixed_mmu_init(env, def); - break; - case MMU_TYPE_R3000: - case MMU_TYPE_R6000: - case MMU_TYPE_R8000: - default: - cpu_abort(env, "MMU type not supported\n"); - } -} -#endif /* CONFIG_USER_ONLY */ - -static void fpu_init (CPUMIPSState *env, const mips_def_t *def) -{ - int i; - - for (i =3D 0; i < MIPS_FPU_MAX; i++) - env->fpus[i].fcr0 =3D def->CP1_fcr0; - - memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); -} - -static void mvp_init (CPUMIPSState *env, const mips_def_t *def) -{ - env->mvp =3D g_malloc0(sizeof(CPUMIPSMVPContext)); - - /* MVPConf1 implemented, TLB sharable, no gating storage support, - programmable cache partitioning implemented, number of allocatabl= e - and sharable TLB entries, MVP has allocatable TCs, 2 VPEs - implemented, 5 TCs implemented. */ - env->mvp->CP0_MVPConf0 =3D (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) = | - (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | -// TODO: actually do 2 VPEs. -// (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PV= PE) | -// (0x04 << CP0MVPC0_PTC); - (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE= ) | - (0x00 << CP0MVPC0_PTC); -#if !defined(CONFIG_USER_ONLY) - /* Usermode has no TLB support */ - env->mvp->CP0_MVPConf0 |=3D (env->tlb->nb_tlb << CP0MVPC0_PTLBE); -#endif - - /* Allocatable CP1 have media extensions, allocatable CP1 have FP su= pport, - no UDI implemented, no CP2 implemented, 1 CP1 implemented. */ - env->mvp->CP0_MVPConf1 =3D (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF)= | - (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PC= P2) | - (0x1 << CP0MVPC1_PCP1); -} --=20 1.7.7