diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 4285d1964e..fc97f59af4 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -69,6 +69,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) Error *err = NULL; target_ulong gcr_base; bool itu_present = false; + bool saar_present = false; for (i = 0; i < s->num_vp; i++) { cpu = MIPS_CPU(cpu_create(s->cpu_type)); @@ -82,12 +83,14 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) itu_present = true; /* Attach ITC Tag to the VP */ env->itc_tag = mips_itu_get_tag_region(&s->itu); + env->itu = &s->itu; } qemu_register_reset(main_cpu_reset, cpu); } cpu = MIPS_CPU(first_cpu); env = &cpu->env; + saar_present = (bool)env->saarp; /* Inter-Thread Communication Unit */ if (itu_present) { @@ -96,6 +99,11 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", &err); object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", &err); + object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present", + &err); + if (saar_present) { + qdev_prop_set_ptr(DEVICE(&s->itu), "saar", (void *)&env->CP0_SAAR); + } object_property_set_bool(OBJECT(&s->itu), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c index 43bbec46cf..1257d8fce6 100644 --- a/hw/misc/mips_itu.c +++ b/hw/misc/mips_itu.c @@ -55,9 +55,17 @@ typedef enum ITCView { ITCVIEW_EF_SYNC = 2, ITCVIEW_EF_TRY = 3, ITCVIEW_PV_SYNC = 4, - ITCVIEW_PV_TRY = 5 + ITCVIEW_PV_TRY = 5, + ITCVIEW_PV_ICR0 = 15, } ITCView; +#define ITC_ICR0_CELL_NUM 16 +#define ITC_ICR0_BLK_GRAIN 8 +#define ITC_ICR0_BLK_GRAIN_MASK 0x7 +#define ITC_ICR0_ERR_AXI 2 +#define ITC_ICR0_ERR_PARITY 1 +#define ITC_ICR0_ERR_EXEC 0 + MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu) { return &itu->tag_io; @@ -76,7 +84,7 @@ static uint64_t itc_tag_read(void *opaque, hwaddr addr, unsigned size) return tag->ITCAddressMap[index]; } -static void itc_reconfigure(MIPSITUState *tag) +void itc_reconfigure(MIPSITUState *tag) { uint64_t *am = &tag->ITCAddressMap[0]; MemoryRegion *mr = &tag->storage_io; @@ -84,6 +92,12 @@ static void itc_reconfigure(MIPSITUState *tag) uint64_t size = (1 * KiB) + (am[1] & ITC_AM1_ADDR_MASK_MASK); bool is_enabled = (am[0] & ITC_AM0_EN_MASK) != 0; + if (tag->saar_present) { + address = ((*(uint64_t *) tag->saar) & 0xFFFFFFFFE000ULL) << 4; + size = 1 << ((*(uint64_t *) tag->saar >> 1) & 0x1f); + is_enabled = *(uint64_t *) tag->saar & 1; + } + memory_region_transaction_begin(); if (!(size & (size - 1))) { memory_region_set_size(mr, size); @@ -142,7 +156,12 @@ static inline ITCView get_itc_view(hwaddr addr) static inline int get_cell_stride_shift(const MIPSITUState *s) { /* Minimum interval (for EntryGain = 0) is 128 B */ - return 7 + (s->ITCAddressMap[1] & ITC_AM1_ENTRY_GRAIN_MASK); + if (s->saar_present) { + return 7 + ((s->icr0 >> ITC_ICR0_BLK_GRAIN) & + ITC_ICR0_BLK_GRAIN_MASK); + } else { + return 7 + (s->ITCAddressMap[1] & ITC_AM1_ENTRY_GRAIN_MASK); + } } static inline ITCStorageCell *get_cell(MIPSITUState *s, @@ -356,6 +375,12 @@ static void view_pv_try_write(ITCStorageCell *c) view_pv_common_write(c); } +static void raise_exception(int excp) +{ + current_cpu->exception_index = excp; + cpu_loop_exit(current_cpu); +} + static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size) { MIPSITUState *s = (MIPSITUState *)opaque; @@ -363,6 +388,14 @@ static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size) ITCView view = get_itc_view(addr); uint64_t ret = -1; + switch (size) { + case 1: + case 2: + s->icr0 |= 1 << ITC_ICR0_ERR_AXI; + raise_exception(EXCP_DBE); + return 0; + } + switch (view) { case ITCVIEW_BYPASS: ret = view_bypass_read(cell); @@ -382,6 +415,9 @@ static uint64_t itc_storage_read(void *opaque, hwaddr addr, unsigned size) case ITCVIEW_PV_TRY: ret = view_pv_try_read(cell); break; + case ITCVIEW_PV_ICR0: + ret = s->icr0; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "itc_storage_read: Bad ITC View %d\n", (int)view); @@ -398,6 +434,14 @@ static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data, ITCStorageCell *cell = get_cell(s, addr); ITCView view = get_itc_view(addr); + switch (size) { + case 1: + case 2: + s->icr0 |= 1 << ITC_ICR0_ERR_AXI; + raise_exception(EXCP_DBE); + return; + } + switch (view) { case ITCVIEW_BYPASS: view_bypass_write(cell, data); @@ -417,6 +461,15 @@ static void itc_storage_write(void *opaque, hwaddr addr, uint64_t data, case ITCVIEW_PV_TRY: view_pv_try_write(cell); break; + case ITCVIEW_PV_ICR0: + if (data & 0x7) { + /* clear ERROR bits */ + s->icr0 &= ~(data & 0x7); + } + /* set BLK_GRAIN */ + s->icr0 &= ~0x700; + s->icr0 |= data & 0x700; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "itc_storage_write: Bad ITC View %d\n", (int)view); @@ -479,10 +532,15 @@ static void mips_itu_reset(DeviceState *dev) { MIPSITUState *s = MIPS_ITU(dev); - s->ITCAddressMap[0] = 0; - s->ITCAddressMap[1] = - ((ITC_STORAGE_ADDRSPACE_SZ - 1) & ITC_AM1_ADDR_MASK_MASK) | - (get_num_cells(s) << ITC_AM1_NUMENTRIES_OFS); + if (s->saar_present) { + *(uint64_t *) s->saar = 0x11 << 1; + s->icr0 = get_num_cells(s) << ITC_ICR0_CELL_NUM; + } else { + s->ITCAddressMap[0] = 0; + s->ITCAddressMap[1] = + ((ITC_STORAGE_ADDRSPACE_SZ - 1) & ITC_AM1_ADDR_MASK_MASK) | + (get_num_cells(s) << ITC_AM1_NUMENTRIES_OFS); + } itc_reconfigure(s); itc_reset_cells(s); @@ -493,6 +551,7 @@ static Property mips_itu_properties[] = { ITC_FIFO_NUM_MAX), DEFINE_PROP_INT32("num-semaphores", MIPSITUState, num_semaphores, ITC_SEMAPH_NUM_MAX), + DEFINE_PROP_BOOL("saar-present", MIPSITUState, saar_present, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h index 030eb4ac62..c44e7672b6 100644 --- a/include/hw/misc/mips_itu.h +++ b/include/hw/misc/mips_itu.h @@ -66,6 +66,14 @@ typedef struct MIPSITUState { /* ITC Configuration Tags */ uint64_t ITCAddressMap[ITC_ADDRESSMAP_NUM]; MemoryRegion tag_io; + + /* ITU Control Register */ + uint64_t icr0; + + /* SAAR */ + bool saar_present; + void *saar; + } MIPSITUState; /* Get ITC Configuration Tag memory region. */ diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 03c03fd8c6..c4da7dfbfd 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -123,87 +123,6 @@ typedef struct mips_def_t mips_def_t; #define MIPS_KSCRATCH_NUM 6 #define MIPS_MAAR_MAX 16 /* Must be an even number. */ -typedef struct TCState TCState; -struct TCState { - target_ulong gpr[32]; - target_ulong PC; - target_ulong HI[MIPS_DSP_ACC]; - target_ulong LO[MIPS_DSP_ACC]; - target_ulong ACX[MIPS_DSP_ACC]; - target_ulong DSPControl; - int32_t CP0_TCStatus; -#define CP0TCSt_TCU3 31 -#define CP0TCSt_TCU2 30 -#define CP0TCSt_TCU1 29 -#define CP0TCSt_TCU0 28 -#define CP0TCSt_TMX 27 -#define CP0TCSt_RNST 23 -#define CP0TCSt_TDS 21 -#define CP0TCSt_DT 20 -#define CP0TCSt_DA 15 -#define CP0TCSt_A 13 -#define CP0TCSt_TKSU 11 -#define CP0TCSt_IXMT 10 -#define CP0TCSt_TASID 0 - int32_t CP0_TCBind; -#define CP0TCBd_CurTC 21 -#define CP0TCBd_TBE 17 -#define CP0TCBd_CurVPE 0 - target_ulong CP0_TCHalt; - target_ulong CP0_TCContext; - target_ulong CP0_TCSchedule; - target_ulong CP0_TCScheFBack; - int32_t CP0_Debug_tcstatus; - target_ulong CP0_UserLocal; - - int32_t msacsr; - -#define MSACSR_FS 24 -#define MSACSR_FS_MASK (1 << MSACSR_FS) -#define MSACSR_NX 18 -#define MSACSR_NX_MASK (1 << MSACSR_NX) -#define MSACSR_CEF 2 -#define MSACSR_CEF_MASK (0xffff << MSACSR_CEF) -#define MSACSR_RM 0 -#define MSACSR_RM_MASK (0x3 << MSACSR_RM) -#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \ - MSACSR_FS_MASK) - - float_status msa_fp_status; - -#define NUMBER_OF_MXU_REGISTERS 16 - target_ulong mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; - target_ulong mxu_cr; -#define MXU_CR_LC 31 -#define MXU_CR_RC 30 -#define MXU_CR_BIAS 2 -#define MXU_CR_RD_EN 1 -#define MXU_CR_MXU_EN 0 - -}; - -typedef struct CPUMIPSState CPUMIPSState; -struct CPUMIPSState { - TCState active_tc; - CPUMIPSFPUContext active_fpu; - - uint32_t current_tc; - uint32_t current_fpu; - - uint32_t SEGBITS; - uint32_t PABITS; -#if defined(TARGET_MIPS64) -# define PABITS_BASE 36 -#else -# define PABITS_BASE 32 -#endif - target_ulong SEGMask; - uint64_t PAMask; -#define PAMASK_BASE ((1ULL << PABITS_BASE) - 1) - - int32_t msair; -#define MSAIR_ProcID 8 -#define MSAIR_Rev 0 /* * Summary of CP0 registers @@ -245,8 +164,8 @@ struct CPUMIPSState { * 3 BadInstrX * 4 GuestCtl1 GuestCtl0Ext * 5 GuestCtl2 - * 6 GuestCtl3 - * 7 + * 6 SAARI GuestCtl3 + * 7 SAAR * * * Register 12 Register 13 Register 14 Register 15 @@ -314,6 +233,240 @@ struct CPUMIPSState { * 7 TagLo TagHi KScratch * */ +#define CP0_REGISTER_00 0 +#define CP0_REGISTER_01 1 +#define CP0_REGISTER_02 2 +#define CP0_REGISTER_03 3 +#define CP0_REGISTER_04 4 +#define CP0_REGISTER_05 5 +#define CP0_REGISTER_06 6 +#define CP0_REGISTER_07 7 +#define CP0_REGISTER_08 8 +#define CP0_REGISTER_09 9 +#define CP0_REGISTER_10 10 +#define CP0_REGISTER_11 11 +#define CP0_REGISTER_12 12 +#define CP0_REGISTER_13 13 +#define CP0_REGISTER_14 14 +#define CP0_REGISTER_15 15 +#define CP0_REGISTER_16 16 +#define CP0_REGISTER_17 17 +#define CP0_REGISTER_18 18 +#define CP0_REGISTER_19 19 +#define CP0_REGISTER_20 20 +#define CP0_REGISTER_21 21 +#define CP0_REGISTER_22 22 +#define CP0_REGISTER_23 23 +#define CP0_REGISTER_24 24 +#define CP0_REGISTER_25 25 +#define CP0_REGISTER_26 26 +#define CP0_REGISTER_27 27 +#define CP0_REGISTER_28 28 +#define CP0_REGISTER_29 29 +#define CP0_REGISTER_30 30 +#define CP0_REGISTER_31 31 + + +/* CP0 Register 00 */ +#define CP0_REG00__INDEX 0 +#define CP0_REG00__VPCONTROL 4 +/* CP0 Register 01 */ +/* CP0 Register 02 */ +#define CP0_REG02__ENTRYLO0 0 +/* CP0 Register 03 */ +#define CP0_REG03__ENTRYLO1 0 +#define CP0_REG03__GLOBALNUM 1 +/* CP0 Register 04 */ +#define CP0_REG04__CONTEXT 0 +#define CP0_REG04__USERLOCAL 2 +#define CP0_REG04__DBGCONTEXTID 4 +#define CP0_REG00__MMID 5 +/* CP0 Register 05 */ +#define CP0_REG05__PAGEMASK 0 +#define CP0_REG05__PAGEGRAIN 1 +/* CP0 Register 06 */ +#define CP0_REG06__WIRED 0 +/* CP0 Register 07 */ +#define CP0_REG07__HWRENA 0 +/* CP0 Register 08 */ +#define CP0_REG08__BADVADDR 0 +#define CP0_REG08__BADINSTR 1 +#define CP0_REG08__BADINSTRP 2 +/* CP0 Register 09 */ +#define CP0_REG09__COUNT 0 +#define CP0_REG09__SAARI 6 +#define CP0_REG09__SAAR 7 +/* CP0 Register 10 */ +#define CP0_REG10__ENTRYHI 0 +#define CP0_REG10__GUESTCTL1 4 +#define CP0_REG10__GUESTCTL2 5 +/* CP0 Register 11 */ +#define CP0_REG11__COMPARE 0 +#define CP0_REG11__GUESTCTL0EXT 4 +/* CP0 Register 12 */ +#define CP0_REG12__STATUS 0 +#define CP0_REG12__INTCTL 1 +#define CP0_REG12__SRSCTL 2 +#define CP0_REG12__GUESTCTL0 6 +#define CP0_REG12__GTOFFSET 7 +/* CP0 Register 13 */ +#define CP0_REG13__CAUSE 0 +/* CP0 Register 14 */ +#define CP0_REG14__EPC 0 +/* CP0 Register 15 */ +#define CP0_REG15__PRID 0 +#define CP0_REG15__EBASE 1 +#define CP0_REG15__CDMMBASE 2 +#define CP0_REG15__CMGCRBASE 3 +/* CP0 Register 16 */ +#define CP0_REG16__CONFIG 0 +#define CP0_REG16__CONFIG1 1 +#define CP0_REG16__CONFIG2 2 +#define CP0_REG16__CONFIG3 3 +#define CP0_REG16__CONFIG4 4 +#define CP0_REG16__CONFIG5 5 +#define CP0_REG00__CONFIG7 7 +/* CP0 Register 17 */ +#define CP0_REG17__LLADDR 0 +#define CP0_REG17__MAAR 1 +#define CP0_REG17__MAARI 2 +/* CP0 Register 18 */ +#define CP0_REG18__WATCHLO0 0 +#define CP0_REG18__WATCHLO1 1 +#define CP0_REG18__WATCHLO2 2 +#define CP0_REG18__WATCHLO3 3 +/* CP0 Register 19 */ +#define CP0_REG19__WATCHHI0 0 +#define CP0_REG19__WATCHHI1 1 +#define CP0_REG19__WATCHHI2 2 +#define CP0_REG19__WATCHHI3 3 +/* CP0 Register 20 */ +#define CP0_REG20__XCONTEXT 0 +/* CP0 Register 21 */ +/* CP0 Register 22 */ +/* CP0 Register 23 */ +#define CP0_REG23__DEBUG 0 +/* CP0 Register 24 */ +#define CP0_REG24__DEPC 0 +/* CP0 Register 25 */ +#define CP0_REG25__PERFCTL0 0 +#define CP0_REG25__PERFCNT0 1 +#define CP0_REG25__PERFCTL1 2 +#define CP0_REG25__PERFCNT1 3 +#define CP0_REG25__PERFCTL2 4 +#define CP0_REG25__PERFCNT2 5 +#define CP0_REG25__PERFCTL3 6 +#define CP0_REG25__PERFCNT3 7 +/* CP0 Register 26 */ +#define CP0_REG00__ERRCTL 0 +/* CP0 Register 27 */ +#define CP0_REG27__CACHERR 0 +/* CP0 Register 28 */ +#define CP0_REG28__ITAGLO 0 +#define CP0_REG28__IDATALO 1 +#define CP0_REG28__DTAGLO 2 +#define CP0_REG28__DDATALO 3 +/* CP0 Register 29 */ +#define CP0_REG29__IDATAHI 1 +#define CP0_REG29__DDATAHI 3 +/* CP0 Register 30 */ +#define CP0_REG30__ERROREPC 0 +/* CP0 Register 31 */ +#define CP0_REG31__DESAVE 0 +#define CP0_REG31__KSCRATCH1 2 +#define CP0_REG31__KSCRATCH2 3 +#define CP0_REG31__KSCRATCH3 4 +#define CP0_REG31__KSCRATCH4 5 +#define CP0_REG31__KSCRATCH5 6 +#define CP0_REG31__KSCRATCH6 7 + + +typedef struct TCState TCState; +struct TCState { + target_ulong gpr[32]; + target_ulong PC; + target_ulong HI[MIPS_DSP_ACC]; + target_ulong LO[MIPS_DSP_ACC]; + target_ulong ACX[MIPS_DSP_ACC]; + target_ulong DSPControl; + int32_t CP0_TCStatus; +#define CP0TCSt_TCU3 31 +#define CP0TCSt_TCU2 30 +#define CP0TCSt_TCU1 29 +#define CP0TCSt_TCU0 28 +#define CP0TCSt_TMX 27 +#define CP0TCSt_RNST 23 +#define CP0TCSt_TDS 21 +#define CP0TCSt_DT 20 +#define CP0TCSt_DA 15 +#define CP0TCSt_A 13 +#define CP0TCSt_TKSU 11 +#define CP0TCSt_IXMT 10 +#define CP0TCSt_TASID 0 + int32_t CP0_TCBind; +#define CP0TCBd_CurTC 21 +#define CP0TCBd_TBE 17 +#define CP0TCBd_CurVPE 0 + target_ulong CP0_TCHalt; + target_ulong CP0_TCContext; + target_ulong CP0_TCSchedule; + target_ulong CP0_TCScheFBack; + int32_t CP0_Debug_tcstatus; + target_ulong CP0_UserLocal; + + int32_t msacsr; + +#define MSACSR_FS 24 +#define MSACSR_FS_MASK (1 << MSACSR_FS) +#define MSACSR_NX 18 +#define MSACSR_NX_MASK (1 << MSACSR_NX) +#define MSACSR_CEF 2 +#define MSACSR_CEF_MASK (0xffff << MSACSR_CEF) +#define MSACSR_RM 0 +#define MSACSR_RM_MASK (0x3 << MSACSR_RM) +#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \ + MSACSR_FS_MASK) + + float_status msa_fp_status; + + /* Upper 64-bit MMRs (multimedia registers); the lower 64-bit are GPRs */ + uint64_t mmr[32]; + +#define NUMBER_OF_MXU_REGISTERS 16 + target_ulong mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; + target_ulong mxu_cr; +#define MXU_CR_LC 31 +#define MXU_CR_RC 30 +#define MXU_CR_BIAS 2 +#define MXU_CR_RD_EN 1 +#define MXU_CR_MXU_EN 0 + +}; + +struct MIPSITUState; +typedef struct CPUMIPSState CPUMIPSState; +struct CPUMIPSState { + TCState active_tc; + CPUMIPSFPUContext active_fpu; + + uint32_t current_tc; + uint32_t current_fpu; + + uint32_t SEGBITS; + uint32_t PABITS; +#if defined(TARGET_MIPS64) +# define PABITS_BASE 36 +#else +# define PABITS_BASE 32 +#endif + target_ulong SEGMask; + uint64_t PAMask; +#define PAMASK_BASE ((1ULL << PABITS_BASE) - 1) + + int32_t msair; +#define MSAIR_ProcID 8 +#define MSAIR_Rev 0 + /* * CP0 Register 0 */ @@ -386,6 +539,7 @@ struct CPUMIPSState { */ target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; + int32_t CP0_MemoryMapID; /* * CP0 Register 5 */ @@ -511,6 +665,12 @@ struct CPUMIPSState { * CP0 Register 9 */ int32_t CP0_Count; + uint32_t CP0_SAARI; +#define CP0SAARI_TARGET 0 /* 5..0 */ + uint64_t CP0_SAAR[2]; +#define CP0SAAR_BASE 12 /* 43..12 */ +#define CP0SAAR_SIZE 1 /* 5..1 */ +#define CP0SAAR_EN 0 /* * CP0 Register 10 */ @@ -860,6 +1020,7 @@ struct CPUMIPSState { uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */ uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */ uint64_t insn_flags; /* Supported instruction set */ + int saarp; /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; @@ -875,6 +1036,7 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; QEMUTimer *timer; /* Internal timer */ + struct MIPSITUState *itu; MemoryRegion *itc_tag; /* ITC Configuration Tags */ target_ulong exception_base; /* ExceptionBase input to the core */ }; @@ -1017,6 +1179,9 @@ void cpu_set_exception_base(int vp_index, target_ulong address); /* mips_int.c */ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); +/* mips_itu.c */ +void itc_reconfigure(struct MIPSITUState *tag); + /* helper.c */ target_ulong exception_resume_pc (CPUMIPSState *env); diff --git a/target/mips/helper.h b/target/mips/helper.h index c23e4e5d97..8872c4647b 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -65,6 +65,8 @@ DEF_HELPER_1(mftc0_tcschedule, tl, env) DEF_HELPER_1(mfc0_tcschefback, tl, env) DEF_HELPER_1(mftc0_tcschefback, tl, env) DEF_HELPER_1(mfc0_count, tl, env) +DEF_HELPER_1(mfc0_saar, tl, env) +DEF_HELPER_1(mfhc0_saar, tl, env) DEF_HELPER_1(mftc0_entryhi, tl, env) DEF_HELPER_1(mftc0_status, tl, env) DEF_HELPER_1(mftc0_cause, tl, env) @@ -87,6 +89,7 @@ DEF_HELPER_1(dmfc0_tcschefback, tl, env) DEF_HELPER_1(dmfc0_lladdr, tl, env) DEF_HELPER_1(dmfc0_maar, tl, env) DEF_HELPER_2(dmfc0_watchlo, tl, env, i32) +DEF_HELPER_1(dmfc0_saar, tl, env) #endif /* TARGET_MIPS64 */ DEF_HELPER_2(mtc0_index, void, env, tl) @@ -131,6 +134,9 @@ DEF_HELPER_2(mtc0_srsconf4, void, env, tl) DEF_HELPER_2(mtc0_hwrena, void, env, tl) DEF_HELPER_2(mtc0_pwctl, void, env, tl) DEF_HELPER_2(mtc0_count, void, env, tl) +DEF_HELPER_2(mtc0_saari, void, env, tl) +DEF_HELPER_2(mtc0_saar, void, env, tl) +DEF_HELPER_2(mthc0_saar, void, env, tl) DEF_HELPER_2(mtc0_entryhi, void, env, tl) DEF_HELPER_2(mttc0_entryhi, void, env, tl) DEF_HELPER_2(mtc0_compare, void, env, tl) diff --git a/target/mips/internal.h b/target/mips/internal.h index 8b1b2456af..8f6fc919d5 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -61,6 +61,7 @@ struct mips_def_t { target_ulong CP0_EBaseWG_rw_bitmask; uint64_t insn_flags; enum mips_mmu_types mmu_type; + int32_t SAARP; }; extern const struct mips_def_t mips_defs[]; diff --git a/target/mips/machine.c b/target/mips/machine.c index 704e9c01bf..1341ab1df9 100644 --- a/target/mips/machine.c +++ b/target/mips/machine.c @@ -214,8 +214,8 @@ const VMStateDescription vmstate_tlb = { const VMStateDescription vmstate_mips_cpu = { .name = "cpu", - .version_id = 15, - .minimum_version_id = 15, + .version_id = 17, + .minimum_version_id = 17, .post_load = cpu_post_load, .fields = (VMStateField[]) { /* Active TC */ @@ -253,6 +253,7 @@ const VMStateDescription vmstate_mips_cpu = { VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU), VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU), VMSTATE_UINTTL(env.CP0_Context, MIPSCPU), + VMSTATE_INT32(env.CP0_MemoryMapID, MIPSCPU), VMSTATE_INT32(env.CP0_PageMask, MIPSCPU), VMSTATE_INT32(env.CP0_PageGrain, MIPSCPU), VMSTATE_UINTTL(env.CP0_SegCtl0, MIPSCPU), @@ -274,6 +275,8 @@ const VMStateDescription vmstate_mips_cpu = { VMSTATE_UINT32(env.CP0_BadInstrP, MIPSCPU), VMSTATE_UINT32(env.CP0_BadInstrX, MIPSCPU), VMSTATE_INT32(env.CP0_Count, MIPSCPU), + VMSTATE_UINT32(env.CP0_SAARI, MIPSCPU), + VMSTATE_UINT64_ARRAY(env.CP0_SAAR, MIPSCPU, 2), VMSTATE_UINTTL(env.CP0_EntryHi, MIPSCPU), VMSTATE_INT32(env.CP0_Compare, MIPSCPU), VMSTATE_INT32(env.CP0_Status, MIPSCPU), diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index d1f1d1aa35..aebad24ed6 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -938,6 +938,22 @@ target_ulong helper_mfc0_count(CPUMIPSState *env) return count; } +target_ulong helper_mfc0_saar(CPUMIPSState *env) +{ + if ((env->CP0_SAARI & 0x3f) < 2) { + return (int32_t) env->CP0_SAAR[env->CP0_SAARI & 0x3f]; + } + return 0; +} + +target_ulong helper_mfhc0_saar(CPUMIPSState *env) +{ + if ((env->CP0_SAARI & 0x3f) < 2) { + return env->CP0_SAAR[env->CP0_SAARI & 0x3f] >> 32; + } + return 0; +} + target_ulong helper_mftc0_entryhi(CPUMIPSState *env) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); @@ -1059,6 +1075,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel) { return env->CP0_WatchLo[sel]; } + +target_ulong helper_dmfc0_saar(CPUMIPSState *env) +{ + if ((env->CP0_SAARI & 0x3f) < 2) { + return env->CP0_SAAR[env->CP0_SAARI & 0x3f]; + } + return 0; +} #endif /* TARGET_MIPS64 */ void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1) @@ -1598,6 +1622,46 @@ void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1) qemu_mutex_unlock_iothread(); } +void helper_mtc0_saari(CPUMIPSState *env, target_ulong arg1) +{ + uint32_t target = arg1 & 0x3f; + if (target <= 1) { + env->CP0_SAARI = target; + } +} + +void helper_mtc0_saar(CPUMIPSState *env, target_ulong arg1) +{ + uint32_t target = env->CP0_SAARI & 0x3f; + if (target < 2) { + env->CP0_SAAR[target] = arg1 & 0x00000ffffffff03fULL; + switch (target) { + case 0: + if (env->itu) { + itc_reconfigure(env->itu); + } + break; + } + } +} + +void helper_mthc0_saar(CPUMIPSState *env, target_ulong arg1) +{ + uint32_t target = env->CP0_SAARI & 0x3f; + if (target < 2) { + env->CP0_SAAR[target] = + (((uint64_t) arg1 << 32) & 0x00000fff00000000ULL) | + (env->CP0_SAAR[target] & 0x00000000ffffffffULL); + switch (target) { + case 0: + if (env->itu) { + itc_reconfigure(env->itu); + } + break; + } + } +} + void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) { target_ulong old, val, mask; diff --git a/target/mips/translate.c b/target/mips/translate.c index 057aaf9a44..ab307c410c 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -2455,6 +2455,11 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; static TCGv_i64 msa_wr_d[64]; +#if defined(TARGET_MIPS64) +/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */ +static TCGv_i64 cpu_mmr[32]; +#endif + #if !defined(TARGET_MIPS64) /* MXU registers */ static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; @@ -2537,6 +2542,7 @@ typedef struct DisasContext { bool mrp; bool nan2008; bool abs2008; + bool saar; } DisasContext; #define DISAS_STOP DISAS_TARGET_0 @@ -6567,55 +6573,66 @@ static inline void gen_mtc0_store32 (TCGv arg, target_ulong off) static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; switch (reg) { - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0)); - rn = "EntryLo0"; + register_name = "EntryLo0"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1)); - rn = "EntryLo1"; + register_name = "EntryLo1"; break; default: goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_09: + switch (sel) { + case 7: + CP0_CHECK(ctx->saar); + gen_helper_mfhc0_saar(arg, cpu_env); + register_name = "SAAR"; + break; + default: + goto cp0_unimplemented; + } + break; + case CP0_REGISTER_17: switch (sel) { case 0: gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr), ctx->CP0_LLAddr_shift); - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_mfhc0_maar(arg, cpu_env); - rn = "MAAR"; + register_name = "MAAR"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: case 4: case 6: gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0); - rn = "TagLo"; + register_name = "TagLo"; break; default: goto cp0_unimplemented; @@ -6624,63 +6641,74 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("mfhc0", rn, reg, sel); + trace_mips_translate_c0("mfhc0", register_name, reg, sel); return; cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", + register_name, reg, sel); tcg_gen_movi_tl(arg, 0); } static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; uint64_t mask = ctx->PAMask >> 36; switch (reg) { - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); tcg_gen_andi_tl(arg, arg, mask); gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0)); - rn = "EntryLo0"; + register_name = "EntryLo0"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA); tcg_gen_andi_tl(arg, arg, mask); gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1)); - rn = "EntryLo1"; + register_name = "EntryLo1"; break; default: goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_09: + switch (sel) { + case 7: + CP0_CHECK(ctx->saar); + gen_helper_mthc0_saar(cpu_env, arg); + register_name = "SAAR"; + break; + default: + goto cp0_unimplemented; + } + case CP0_REGISTER_17: switch (sel) { case 0: /* LLAddr is read-only (the only exception is bit 0 if LLB is supported); the CP0_LLAddr_rw_bitmask does not seem to be relevant for modern MIPS cores supporting MTHC0, therefore treating MTHC0 to LLAddr as NOP. */ - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_mthc0_maar(cpu_env, arg); - rn = "MAAR"; + register_name = "MAAR"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: @@ -6688,7 +6716,7 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 6: tcg_gen_andi_tl(arg, arg, mask); gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo)); - rn = "TagLo"; + register_name = "TagLo"; break; default: goto cp0_unimplemented; @@ -6697,10 +6725,11 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("mthc0", rn, reg, sel); + trace_mips_translate_c0("mthc0", register_name, reg, sel); cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", + register_name, reg, sel); } static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg) @@ -6714,89 +6743,89 @@ static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg) static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; if (sel != 0) check_insn(ctx, ISA_MIPS32); switch (reg) { - case 0: + case CP0_REGISTER_00: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index)); - rn = "Index"; + register_name = "Index"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpcontrol(arg, cpu_env); - rn = "MVPControl"; + register_name = "MVPControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf0(arg, cpu_env); - rn = "MVPConf0"; + register_name = "MVPConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf1(arg, cpu_env); - rn = "MVPConf1"; + register_name = "MVPConf1"; break; case 4: CP0_CHECK(ctx->vp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl)); - rn = "VPControl"; + register_name = "VPControl"; break; default: goto cp0_unimplemented; } break; - case 1: + case CP0_REGISTER_01: switch (sel) { case 0: CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); gen_helper_mfc0_random(arg, cpu_env); - rn = "Random"; + register_name = "Random"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl)); - rn = "VPEControl"; + register_name = "VPEControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0)); - rn = "VPEConf0"; + register_name = "VPEConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1)); - rn = "VPEConf1"; + register_name = "VPEConf1"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask)); - rn = "YQMask"; + register_name = "YQMask"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule)); - rn = "VPESchedule"; + register_name = "VPESchedule"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack)); - rn = "VPEScheFBack"; + register_name = "VPEScheFBack"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt)); - rn = "VPEOpt"; + register_name = "VPEOpt"; break; default: goto cp0_unimplemented; } break; - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: { @@ -6813,48 +6842,48 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_move_low32(arg, tmp); tcg_temp_free_i64(tmp); } - rn = "EntryLo0"; + register_name = "EntryLo0"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcstatus(arg, cpu_env); - rn = "TCStatus"; + register_name = "TCStatus"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcbind(arg, cpu_env); - rn = "TCBind"; + register_name = "TCBind"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcrestart(arg, cpu_env); - rn = "TCRestart"; + register_name = "TCRestart"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tchalt(arg, cpu_env); - rn = "TCHalt"; + register_name = "TCHalt"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tccontext(arg, cpu_env); - rn = "TCContext"; + register_name = "TCContext"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcschedule(arg, cpu_env); - rn = "TCSchedule"; + register_name = "TCSchedule"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcschefback(arg, cpu_env); - rn = "TCScheFBack"; + register_name = "TCScheFBack"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: { @@ -6871,166 +6900,166 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_move_low32(arg, tmp); tcg_temp_free_i64(tmp); } - rn = "EntryLo1"; + register_name = "EntryLo1"; break; case 1: CP0_CHECK(ctx->vp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber)); - rn = "GlobalNumber"; + register_name = "GlobalNumber"; break; default: goto cp0_unimplemented; } break; - case 4: + case CP0_REGISTER_04: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context)); tcg_gen_ext32s_tl(arg, arg); - rn = "Context"; + register_name = "Context"; break; case 1: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */ - rn = "ContextConfig"; + register_name = "ContextConfig"; goto cp0_unimplemented; case 2: CP0_CHECK(ctx->ulri); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); tcg_gen_ext32s_tl(arg, arg); - rn = "UserLocal"; + register_name = "UserLocal"; break; default: goto cp0_unimplemented; } break; - case 5: + case CP0_REGISTER_05: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask)); - rn = "PageMask"; + register_name = "PageMask"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain)); - rn = "PageGrain"; + register_name = "PageGrain"; break; case 2: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0)); tcg_gen_ext32s_tl(arg, arg); - rn = "SegCtl0"; + register_name = "SegCtl0"; break; case 3: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1)); tcg_gen_ext32s_tl(arg, arg); - rn = "SegCtl1"; + register_name = "SegCtl1"; break; case 4: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2)); tcg_gen_ext32s_tl(arg, arg); - rn = "SegCtl2"; + register_name = "SegCtl2"; break; case 5: check_pw(ctx); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase)); - rn = "PWBase"; + register_name = "PWBase"; break; case 6: check_pw(ctx); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField)); - rn = "PWField"; + register_name = "PWField"; break; case 7: check_pw(ctx); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize)); - rn = "PWSize"; + register_name = "PWSize"; break; default: goto cp0_unimplemented; } break; - case 6: + case CP0_REGISTER_06: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired)); - rn = "Wired"; + register_name = "Wired"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0)); - rn = "SRSConf0"; + register_name = "SRSConf0"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1)); - rn = "SRSConf1"; + register_name = "SRSConf1"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2)); - rn = "SRSConf2"; + register_name = "SRSConf2"; break; case 4: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3)); - rn = "SRSConf3"; + register_name = "SRSConf3"; break; case 5: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4)); - rn = "SRSConf4"; + register_name = "SRSConf4"; break; case 6: check_pw(ctx); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl)); - rn = "PWCtl"; + register_name = "PWCtl"; break; default: goto cp0_unimplemented; } break; - case 7: + case CP0_REGISTER_07: switch (sel) { case 0: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna)); - rn = "HWREna"; + register_name = "HWREna"; break; default: goto cp0_unimplemented; } break; - case 8: + case CP0_REGISTER_08: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); tcg_gen_ext32s_tl(arg, arg); - rn = "BadVAddr"; + register_name = "BadVAddr"; break; case 1: CP0_CHECK(ctx->bi); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr)); - rn = "BadInstr"; + register_name = "BadInstr"; break; case 2: CP0_CHECK(ctx->bp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); - rn = "BadInstrP"; + register_name = "BadInstrP"; break; case 3: CP0_CHECK(ctx->bi); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX)); tcg_gen_andi_tl(arg, arg, ~0xffff); - rn = "BadInstrX"; + register_name = "BadInstrX"; break; default: goto cp0_unimplemented; } break; - case 9: + case CP0_REGISTER_09: switch (sel) { case 0: /* Mark as an IO operation because we read the time. */ @@ -7046,164 +7075,173 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) ensure we break completely out of translated code. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Count"; + register_name = "Count"; + break; + case 6: + CP0_CHECK(ctx->saar); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI)); + register_name = "SAARI"; + break; + case 7: + CP0_CHECK(ctx->saar); + gen_helper_mfc0_saar(arg, cpu_env); + register_name = "SAAR"; break; - /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 10: + case CP0_REGISTER_10: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi)); tcg_gen_ext32s_tl(arg, arg); - rn = "EntryHi"; + register_name = "EntryHi"; break; default: goto cp0_unimplemented; } break; - case 11: + case CP0_REGISTER_11: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare)); - rn = "Compare"; + register_name = "Compare"; break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 12: + case CP0_REGISTER_12: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status)); - rn = "Status"; + register_name = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl)); - rn = "IntCtl"; + register_name = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl)); - rn = "SRSCtl"; + register_name = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); - rn = "SRSMap"; + register_name = "SRSMap"; break; default: goto cp0_unimplemented; } break; - case 13: + case CP0_REGISTER_13: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause)); - rn = "Cause"; + register_name = "Cause"; break; default: goto cp0_unimplemented; } break; - case 14: + case CP0_REGISTER_14: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC)); tcg_gen_ext32s_tl(arg, arg); - rn = "EPC"; + register_name = "EPC"; break; default: goto cp0_unimplemented; } break; - case 15: + case CP0_REGISTER_15: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid)); - rn = "PRid"; + register_name = "PRid"; break; case 1: check_insn(ctx, ISA_MIPS32R2); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase)); tcg_gen_ext32s_tl(arg, arg); - rn = "EBase"; + register_name = "EBase"; break; case 3: check_insn(ctx, ISA_MIPS32R2); CP0_CHECK(ctx->cmgcr); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase)); tcg_gen_ext32s_tl(arg, arg); - rn = "CMGCRBase"; + register_name = "CMGCRBase"; break; default: goto cp0_unimplemented; } break; - case 16: + case CP0_REGISTER_16: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0)); - rn = "Config"; + register_name = "Config"; break; case 1: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1)); - rn = "Config1"; + register_name = "Config1"; break; case 2: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2)); - rn = "Config2"; + register_name = "Config2"; break; case 3: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3)); - rn = "Config3"; + register_name = "Config3"; break; case 4: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4)); - rn = "Config4"; + register_name = "Config4"; break; case 5: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); - rn = "Config5"; + register_name = "Config5"; break; /* 6,7 are implementation dependent */ case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); - rn = "Config6"; + register_name = "Config6"; break; case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7)); - rn = "Config7"; + register_name = "Config7"; break; default: goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_17: switch (sel) { case 0: gen_helper_mfc0_lladdr(arg, cpu_env); - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_mfc0_maar(arg, cpu_env); - rn = "MAAR"; + register_name = "MAAR"; break; case 2: CP0_CHECK(ctx->mrp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI)); - rn = "MAARI"; + register_name = "MAARI"; break; default: goto cp0_unimplemented; } break; - case 18: + case CP0_REGISTER_18: switch (sel) { case 0: case 1: @@ -7215,13 +7253,13 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_1e0i(mfc0_watchlo, arg, sel); - rn = "WatchLo"; + register_name = "WatchLo"; break; default: goto cp0_unimplemented; } break; - case 19: + case CP0_REGISTER_19: switch (sel) { case 0: case 1: @@ -7233,142 +7271,142 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_1e0i(mfc0_watchhi, arg, sel); - rn = "WatchHi"; + register_name = "WatchHi"; break; default: goto cp0_unimplemented; } break; - case 20: + case CP0_REGISTER_20: switch (sel) { case 0: #if defined(TARGET_MIPS64) check_insn(ctx, ISA_MIPS3); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext)); tcg_gen_ext32s_tl(arg, arg); - rn = "XContext"; + register_name = "XContext"; break; #endif default: goto cp0_unimplemented; } break; - case 21: + case CP0_REGISTER_21: /* Officially reserved, but sel 0 is used for R1x000 framemask */ CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask)); - rn = "Framemask"; + register_name = "Framemask"; break; default: goto cp0_unimplemented; } break; - case 22: + case CP0_REGISTER_22: tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "'Diagnostic"; /* implementation dependent */ + register_name = "'Diagnostic"; /* implementation dependent */ break; - case 23: + case CP0_REGISTER_23: switch (sel) { case 0: gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */ - rn = "Debug"; + register_name = "Debug"; break; case 1: // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */ - rn = "TraceControl"; + register_name = "TraceControl"; goto cp0_unimplemented; case 2: // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */ - rn = "TraceControl2"; + register_name = "TraceControl2"; goto cp0_unimplemented; case 3: // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */ - rn = "UserTraceData"; + register_name = "UserTraceData"; goto cp0_unimplemented; case 4: // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */ - rn = "TraceBPC"; + register_name = "TraceBPC"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 24: + case CP0_REGISTER_24: switch (sel) { case 0: /* EJTAG support */ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC)); tcg_gen_ext32s_tl(arg, arg); - rn = "DEPC"; + register_name = "DEPC"; break; default: goto cp0_unimplemented; } break; - case 25: + case CP0_REGISTER_25: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0)); - rn = "Performance0"; + register_name = "Performance0"; break; case 1: // gen_helper_mfc0_performance1(arg); - rn = "Performance1"; + register_name = "Performance1"; goto cp0_unimplemented; case 2: // gen_helper_mfc0_performance2(arg); - rn = "Performance2"; + register_name = "Performance2"; goto cp0_unimplemented; case 3: // gen_helper_mfc0_performance3(arg); - rn = "Performance3"; + register_name = "Performance3"; goto cp0_unimplemented; case 4: // gen_helper_mfc0_performance4(arg); - rn = "Performance4"; + register_name = "Performance4"; goto cp0_unimplemented; case 5: // gen_helper_mfc0_performance5(arg); - rn = "Performance5"; + register_name = "Performance5"; goto cp0_unimplemented; case 6: // gen_helper_mfc0_performance6(arg); - rn = "Performance6"; + register_name = "Performance6"; goto cp0_unimplemented; case 7: // gen_helper_mfc0_performance7(arg); - rn = "Performance7"; + register_name = "Performance7"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 26: + case CP0_REGISTER_26: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl)); - rn = "ErrCtl"; + register_name = "ErrCtl"; break; default: goto cp0_unimplemented; } break; - case 27: + case CP0_REGISTER_27: switch (sel) { case 0: case 1: case 2: case 3: tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "CacheErr"; + register_name = "CacheErr"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: @@ -7380,56 +7418,56 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_move_low32(arg, tmp); tcg_temp_free_i64(tmp); } - rn = "TagLo"; + register_name = "TagLo"; break; case 1: case 3: case 5: case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo)); - rn = "DataLo"; + register_name = "DataLo"; break; default: goto cp0_unimplemented; } break; - case 29: + case CP0_REGISTER_29: switch (sel) { case 0: case 2: case 4: case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi)); - rn = "TagHi"; + register_name = "TagHi"; break; case 1: case 3: case 5: case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi)); - rn = "DataHi"; + register_name = "DataHi"; break; default: goto cp0_unimplemented; } break; - case 30: + case CP0_REGISTER_30: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC)); tcg_gen_ext32s_tl(arg, arg); - rn = "ErrorEPC"; + register_name = "ErrorEPC"; break; default: goto cp0_unimplemented; } break; - case 31: + case CP0_REGISTER_31: switch (sel) { case 0: /* EJTAG support */ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); - rn = "DESAVE"; + register_name = "DESAVE"; break; case 2: case 3: @@ -7441,7 +7479,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_KScratch[sel-2])); tcg_gen_ext32s_tl(arg, arg); - rn = "KScratch"; + register_name = "KScratch"; break; default: goto cp0_unimplemented; @@ -7450,17 +7488,18 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("mfc0", rn, reg, sel); + trace_mips_translate_c0("mfc0", register_name, reg, sel); return; cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", + register_name, reg, sel); gen_mfc0_unimplemented(ctx, arg); } static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; if (sel != 0) check_insn(ctx, ISA_MIPS32); @@ -7470,316 +7509,325 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) } switch (reg) { - case 0: + case CP0_REGISTER_00: switch (sel) { case 0: gen_helper_mtc0_index(cpu_env, arg); - rn = "Index"; + register_name = "Index"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_mvpcontrol(cpu_env, arg); - rn = "MVPControl"; + register_name = "MVPControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); /* ignored */ - rn = "MVPConf0"; + register_name = "MVPConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); /* ignored */ - rn = "MVPConf1"; + register_name = "MVPConf1"; break; case 4: CP0_CHECK(ctx->vp); /* ignored */ - rn = "VPControl"; + register_name = "VPControl"; break; default: goto cp0_unimplemented; } break; - case 1: + case CP0_REGISTER_01: switch (sel) { case 0: /* ignored */ - rn = "Random"; + register_name = "Random"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpecontrol(cpu_env, arg); - rn = "VPEControl"; + register_name = "VPEControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeconf0(cpu_env, arg); - rn = "VPEConf0"; + register_name = "VPEConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeconf1(cpu_env, arg); - rn = "VPEConf1"; + register_name = "VPEConf1"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_yqmask(cpu_env, arg); - rn = "YQMask"; + register_name = "YQMask"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule)); - rn = "VPESchedule"; + register_name = "VPESchedule"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack)); - rn = "VPEScheFBack"; + register_name = "VPEScheFBack"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeopt(cpu_env, arg); - rn = "VPEOpt"; + register_name = "VPEOpt"; break; default: goto cp0_unimplemented; } break; - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: gen_helper_mtc0_entrylo0(cpu_env, arg); - rn = "EntryLo0"; + register_name = "EntryLo0"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcstatus(cpu_env, arg); - rn = "TCStatus"; + register_name = "TCStatus"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcbind(cpu_env, arg); - rn = "TCBind"; + register_name = "TCBind"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcrestart(cpu_env, arg); - rn = "TCRestart"; + register_name = "TCRestart"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tchalt(cpu_env, arg); - rn = "TCHalt"; + register_name = "TCHalt"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tccontext(cpu_env, arg); - rn = "TCContext"; + register_name = "TCContext"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcschedule(cpu_env, arg); - rn = "TCSchedule"; + register_name = "TCSchedule"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcschefback(cpu_env, arg); - rn = "TCScheFBack"; + register_name = "TCScheFBack"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: gen_helper_mtc0_entrylo1(cpu_env, arg); - rn = "EntryLo1"; + register_name = "EntryLo1"; break; case 1: CP0_CHECK(ctx->vp); /* ignored */ - rn = "GlobalNumber"; + register_name = "GlobalNumber"; break; default: goto cp0_unimplemented; } break; - case 4: + case CP0_REGISTER_04: switch (sel) { case 0: gen_helper_mtc0_context(cpu_env, arg); - rn = "Context"; + register_name = "Context"; break; case 1: // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ - rn = "ContextConfig"; + register_name = "ContextConfig"; goto cp0_unimplemented; case 2: CP0_CHECK(ctx->ulri); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); - rn = "UserLocal"; + register_name = "UserLocal"; break; default: goto cp0_unimplemented; } break; - case 5: + case CP0_REGISTER_05: switch (sel) { case 0: gen_helper_mtc0_pagemask(cpu_env, arg); - rn = "PageMask"; + register_name = "PageMask"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_pagegrain(cpu_env, arg); - rn = "PageGrain"; + register_name = "PageGrain"; ctx->base.is_jmp = DISAS_STOP; break; case 2: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl0(cpu_env, arg); - rn = "SegCtl0"; + register_name = "SegCtl0"; break; case 3: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl1(cpu_env, arg); - rn = "SegCtl1"; + register_name = "SegCtl1"; break; case 4: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl2(cpu_env, arg); - rn = "SegCtl2"; + register_name = "SegCtl2"; break; case 5: check_pw(ctx); gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase)); - rn = "PWBase"; + register_name = "PWBase"; break; case 6: check_pw(ctx); gen_helper_mtc0_pwfield(cpu_env, arg); - rn = "PWField"; + register_name = "PWField"; break; case 7: check_pw(ctx); gen_helper_mtc0_pwsize(cpu_env, arg); - rn = "PWSize"; + register_name = "PWSize"; break; default: goto cp0_unimplemented; } break; - case 6: + case CP0_REGISTER_06: switch (sel) { case 0: gen_helper_mtc0_wired(cpu_env, arg); - rn = "Wired"; + register_name = "Wired"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf0(cpu_env, arg); - rn = "SRSConf0"; + register_name = "SRSConf0"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf1(cpu_env, arg); - rn = "SRSConf1"; + register_name = "SRSConf1"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf2(cpu_env, arg); - rn = "SRSConf2"; + register_name = "SRSConf2"; break; case 4: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf3(cpu_env, arg); - rn = "SRSConf3"; + register_name = "SRSConf3"; break; case 5: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf4(cpu_env, arg); - rn = "SRSConf4"; + register_name = "SRSConf4"; break; case 6: check_pw(ctx); gen_helper_mtc0_pwctl(cpu_env, arg); - rn = "PWCtl"; + register_name = "PWCtl"; break; default: goto cp0_unimplemented; } break; - case 7: + case CP0_REGISTER_07: switch (sel) { case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); ctx->base.is_jmp = DISAS_STOP; - rn = "HWREna"; + register_name = "HWREna"; break; default: goto cp0_unimplemented; } break; - case 8: + case CP0_REGISTER_08: switch (sel) { case 0: /* ignored */ - rn = "BadVAddr"; + register_name = "BadVAddr"; break; case 1: /* ignored */ - rn = "BadInstr"; + register_name = "BadInstr"; break; case 2: /* ignored */ - rn = "BadInstrP"; + register_name = "BadInstrP"; break; case 3: /* ignored */ - rn = "BadInstrX"; + register_name = "BadInstrX"; break; default: goto cp0_unimplemented; } break; - case 9: + case CP0_REGISTER_09: switch (sel) { case 0: gen_helper_mtc0_count(cpu_env, arg); - rn = "Count"; + register_name = "Count"; + break; + case 6: + CP0_CHECK(ctx->saar); + gen_helper_mtc0_saari(cpu_env, arg); + register_name = "SAARI"; + break; + case 7: + CP0_CHECK(ctx->saar); + gen_helper_mtc0_saar(cpu_env, arg); + register_name = "SAAR"; break; - /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 10: + case CP0_REGISTER_10: switch (sel) { case 0: gen_helper_mtc0_entryhi(cpu_env, arg); - rn = "EntryHi"; + register_name = "EntryHi"; break; default: goto cp0_unimplemented; } break; - case 11: + case CP0_REGISTER_11: switch (sel) { case 0: gen_helper_mtc0_compare(cpu_env, arg); - rn = "Compare"; + register_name = "Compare"; break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 12: + case CP0_REGISTER_12: switch (sel) { case 0: save_cpu_state(ctx, 1); @@ -7787,34 +7835,34 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Status"; + register_name = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "IntCtl"; + register_name = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "SRSCtl"; + register_name = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "SRSMap"; + register_name = "SRSMap"; break; default: goto cp0_unimplemented; } break; - case 13: + case CP0_REGISTER_13: switch (sel) { case 0: save_cpu_state(ctx, 1); @@ -7824,107 +7872,107 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) * translated code to check for pending interrupts. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Cause"; + register_name = "Cause"; break; default: goto cp0_unimplemented; } break; - case 14: + case CP0_REGISTER_14: switch (sel) { case 0: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC)); - rn = "EPC"; + register_name = "EPC"; break; default: goto cp0_unimplemented; } break; - case 15: + case CP0_REGISTER_15: switch (sel) { case 0: /* ignored */ - rn = "PRid"; + register_name = "PRid"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_ebase(cpu_env, arg); - rn = "EBase"; + register_name = "EBase"; break; default: goto cp0_unimplemented; } break; - case 16: + case CP0_REGISTER_16: switch (sel) { case 0: gen_helper_mtc0_config0(cpu_env, arg); - rn = "Config"; + register_name = "Config"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 1: /* ignored, read only */ - rn = "Config1"; + register_name = "Config1"; break; case 2: gen_helper_mtc0_config2(cpu_env, arg); - rn = "Config2"; + register_name = "Config2"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 3: gen_helper_mtc0_config3(cpu_env, arg); - rn = "Config3"; + register_name = "Config3"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 4: gen_helper_mtc0_config4(cpu_env, arg); - rn = "Config4"; + register_name = "Config4"; ctx->base.is_jmp = DISAS_STOP; break; case 5: gen_helper_mtc0_config5(cpu_env, arg); - rn = "Config5"; + register_name = "Config5"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; /* 6,7 are implementation dependent */ case 6: /* ignored */ - rn = "Config6"; + register_name = "Config6"; break; case 7: /* ignored */ - rn = "Config7"; + register_name = "Config7"; break; default: - rn = "Invalid config selector"; + register_name = "Invalid config selector"; goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_17: switch (sel) { case 0: gen_helper_mtc0_lladdr(cpu_env, arg); - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_mtc0_maar(cpu_env, arg); - rn = "MAAR"; + register_name = "MAAR"; break; case 2: CP0_CHECK(ctx->mrp); gen_helper_mtc0_maari(cpu_env, arg); - rn = "MAARI"; + register_name = "MAARI"; break; default: goto cp0_unimplemented; } break; - case 18: + case CP0_REGISTER_18: switch (sel) { case 0: case 1: @@ -7936,13 +7984,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_0e1i(mtc0_watchlo, arg, sel); - rn = "WatchLo"; + register_name = "WatchLo"; break; default: goto cp0_unimplemented; } break; - case 19: + case CP0_REGISTER_19: switch (sel) { case 0: case 1: @@ -7954,59 +8002,59 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_0e1i(mtc0_watchhi, arg, sel); - rn = "WatchHi"; + register_name = "WatchHi"; break; default: goto cp0_unimplemented; } break; - case 20: + case CP0_REGISTER_20: switch (sel) { case 0: #if defined(TARGET_MIPS64) check_insn(ctx, ISA_MIPS3); gen_helper_mtc0_xcontext(cpu_env, arg); - rn = "XContext"; + register_name = "XContext"; break; #endif default: goto cp0_unimplemented; } break; - case 21: + case CP0_REGISTER_21: /* Officially reserved, but sel 0 is used for R1x000 framemask */ CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); switch (sel) { case 0: gen_helper_mtc0_framemask(cpu_env, arg); - rn = "Framemask"; + register_name = "Framemask"; break; default: goto cp0_unimplemented; } break; - case 22: + case CP0_REGISTER_22: /* ignored */ - rn = "Diagnostic"; /* implementation dependent */ + register_name = "Diagnostic"; /* implementation dependent */ break; - case 23: + case CP0_REGISTER_23: switch (sel) { case 0: gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Debug"; + register_name = "Debug"; break; case 1: // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ - rn = "TraceControl"; + register_name = "TraceControl"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; case 2: // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ - rn = "TraceControl2"; + register_name = "TraceControl2"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; @@ -8014,7 +8062,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ - rn = "UserTraceData"; + register_name = "UserTraceData"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; @@ -8022,142 +8070,142 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "TraceBPC"; + register_name = "TraceBPC"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 24: + case CP0_REGISTER_24: switch (sel) { case 0: /* EJTAG support */ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC)); - rn = "DEPC"; + register_name = "DEPC"; break; default: goto cp0_unimplemented; } break; - case 25: + case CP0_REGISTER_25: switch (sel) { case 0: gen_helper_mtc0_performance0(cpu_env, arg); - rn = "Performance0"; + register_name = "Performance0"; break; case 1: // gen_helper_mtc0_performance1(arg); - rn = "Performance1"; + register_name = "Performance1"; goto cp0_unimplemented; case 2: // gen_helper_mtc0_performance2(arg); - rn = "Performance2"; + register_name = "Performance2"; goto cp0_unimplemented; case 3: // gen_helper_mtc0_performance3(arg); - rn = "Performance3"; + register_name = "Performance3"; goto cp0_unimplemented; case 4: // gen_helper_mtc0_performance4(arg); - rn = "Performance4"; + register_name = "Performance4"; goto cp0_unimplemented; case 5: // gen_helper_mtc0_performance5(arg); - rn = "Performance5"; + register_name = "Performance5"; goto cp0_unimplemented; case 6: // gen_helper_mtc0_performance6(arg); - rn = "Performance6"; + register_name = "Performance6"; goto cp0_unimplemented; case 7: // gen_helper_mtc0_performance7(arg); - rn = "Performance7"; + register_name = "Performance7"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 26: + case CP0_REGISTER_26: switch (sel) { case 0: gen_helper_mtc0_errctl(cpu_env, arg); ctx->base.is_jmp = DISAS_STOP; - rn = "ErrCtl"; + register_name = "ErrCtl"; break; default: goto cp0_unimplemented; } break; - case 27: + case CP0_REGISTER_27: switch (sel) { case 0: case 1: case 2: case 3: /* ignored */ - rn = "CacheErr"; + register_name = "CacheErr"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: case 4: case 6: gen_helper_mtc0_taglo(cpu_env, arg); - rn = "TagLo"; + register_name = "TagLo"; break; case 1: case 3: case 5: case 7: gen_helper_mtc0_datalo(cpu_env, arg); - rn = "DataLo"; + register_name = "DataLo"; break; default: goto cp0_unimplemented; } break; - case 29: + case CP0_REGISTER_29: switch (sel) { case 0: case 2: case 4: case 6: gen_helper_mtc0_taghi(cpu_env, arg); - rn = "TagHi"; + register_name = "TagHi"; break; case 1: case 3: case 5: case 7: gen_helper_mtc0_datahi(cpu_env, arg); - rn = "DataHi"; + register_name = "DataHi"; break; default: - rn = "invalid sel"; + register_name = "invalid sel"; goto cp0_unimplemented; } break; - case 30: + case CP0_REGISTER_30: switch (sel) { case 0: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC)); - rn = "ErrorEPC"; + register_name = "ErrorEPC"; break; default: goto cp0_unimplemented; } break; - case 31: + case CP0_REGISTER_31: switch (sel) { case 0: /* EJTAG support */ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); - rn = "DESAVE"; + register_name = "DESAVE"; break; case 2: case 3: @@ -8168,7 +8216,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_KScratch[sel-2])); - rn = "KScratch"; + register_name = "KScratch"; break; default: goto cp0_unimplemented; @@ -8177,7 +8225,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("mtc0", rn, reg, sel); + trace_mips_translate_c0("mtc0", register_name, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { @@ -8190,297 +8238,298 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) return; cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", + register_name, reg, sel); } #if defined(TARGET_MIPS64) static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; if (sel != 0) check_insn(ctx, ISA_MIPS64); switch (reg) { - case 0: + case CP0_REGISTER_00: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index)); - rn = "Index"; + register_name = "Index"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpcontrol(arg, cpu_env); - rn = "MVPControl"; + register_name = "MVPControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf0(arg, cpu_env); - rn = "MVPConf0"; + register_name = "MVPConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf1(arg, cpu_env); - rn = "MVPConf1"; + register_name = "MVPConf1"; break; case 4: CP0_CHECK(ctx->vp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl)); - rn = "VPControl"; + register_name = "VPControl"; break; default: goto cp0_unimplemented; } break; - case 1: + case CP0_REGISTER_01: switch (sel) { case 0: CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); gen_helper_mfc0_random(arg, cpu_env); - rn = "Random"; + register_name = "Random"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl)); - rn = "VPEControl"; + register_name = "VPEControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0)); - rn = "VPEConf0"; + register_name = "VPEConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1)); - rn = "VPEConf1"; + register_name = "VPEConf1"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask)); - rn = "YQMask"; + register_name = "YQMask"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule)); - rn = "VPESchedule"; + register_name = "VPESchedule"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack)); - rn = "VPEScheFBack"; + register_name = "VPEScheFBack"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt)); - rn = "VPEOpt"; + register_name = "VPEOpt"; break; default: goto cp0_unimplemented; } break; - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0)); - rn = "EntryLo0"; + register_name = "EntryLo0"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcstatus(arg, cpu_env); - rn = "TCStatus"; + register_name = "TCStatus"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcbind(arg, cpu_env); - rn = "TCBind"; + register_name = "TCBind"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_dmfc0_tcrestart(arg, cpu_env); - rn = "TCRestart"; + register_name = "TCRestart"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_dmfc0_tchalt(arg, cpu_env); - rn = "TCHalt"; + register_name = "TCHalt"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_dmfc0_tccontext(arg, cpu_env); - rn = "TCContext"; + register_name = "TCContext"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_dmfc0_tcschedule(arg, cpu_env); - rn = "TCSchedule"; + register_name = "TCSchedule"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_dmfc0_tcschefback(arg, cpu_env); - rn = "TCScheFBack"; + register_name = "TCScheFBack"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1)); - rn = "EntryLo1"; + register_name = "EntryLo1"; break; case 1: CP0_CHECK(ctx->vp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber)); - rn = "GlobalNumber"; + register_name = "GlobalNumber"; break; default: goto cp0_unimplemented; } break; - case 4: + case CP0_REGISTER_04: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context)); - rn = "Context"; + register_name = "Context"; break; case 1: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */ - rn = "ContextConfig"; + register_name = "ContextConfig"; goto cp0_unimplemented; case 2: CP0_CHECK(ctx->ulri); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); - rn = "UserLocal"; + register_name = "UserLocal"; break; default: goto cp0_unimplemented; } break; - case 5: + case CP0_REGISTER_05: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask)); - rn = "PageMask"; + register_name = "PageMask"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain)); - rn = "PageGrain"; + register_name = "PageGrain"; break; case 2: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0)); - rn = "SegCtl0"; + register_name = "SegCtl0"; break; case 3: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1)); - rn = "SegCtl1"; + register_name = "SegCtl1"; break; case 4: CP0_CHECK(ctx->sc); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2)); - rn = "SegCtl2"; + register_name = "SegCtl2"; break; case 5: check_pw(ctx); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase)); - rn = "PWBase"; + register_name = "PWBase"; break; case 6: check_pw(ctx); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField)); - rn = "PWField"; + register_name = "PWField"; break; case 7: check_pw(ctx); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize)); - rn = "PWSize"; + register_name = "PWSize"; break; default: goto cp0_unimplemented; } break; - case 6: + case CP0_REGISTER_06: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired)); - rn = "Wired"; + register_name = "Wired"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0)); - rn = "SRSConf0"; + register_name = "SRSConf0"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1)); - rn = "SRSConf1"; + register_name = "SRSConf1"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2)); - rn = "SRSConf2"; + register_name = "SRSConf2"; break; case 4: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3)); - rn = "SRSConf3"; + register_name = "SRSConf3"; break; case 5: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4)); - rn = "SRSConf4"; + register_name = "SRSConf4"; break; case 6: check_pw(ctx); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl)); - rn = "PWCtl"; + register_name = "PWCtl"; break; default: goto cp0_unimplemented; } break; - case 7: + case CP0_REGISTER_07: switch (sel) { case 0: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna)); - rn = "HWREna"; + register_name = "HWREna"; break; default: goto cp0_unimplemented; } break; - case 8: + case CP0_REGISTER_08: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); - rn = "BadVAddr"; + register_name = "BadVAddr"; break; case 1: CP0_CHECK(ctx->bi); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr)); - rn = "BadInstr"; + register_name = "BadInstr"; break; case 2: CP0_CHECK(ctx->bp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); - rn = "BadInstrP"; + register_name = "BadInstrP"; break; case 3: CP0_CHECK(ctx->bi); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX)); tcg_gen_andi_tl(arg, arg, ~0xffff); - rn = "BadInstrX"; + register_name = "BadInstrX"; break; default: goto cp0_unimplemented; } break; - case 9: + case CP0_REGISTER_09: switch (sel) { case 0: /* Mark as an IO operation because we read the time. */ @@ -8496,160 +8545,169 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) ensure we break completely out of translated code. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Count"; + register_name = "Count"; + break; + case 6: + CP0_CHECK(ctx->saar); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI)); + register_name = "SAARI"; + break; + case 7: + CP0_CHECK(ctx->saar); + gen_helper_dmfc0_saar(arg, cpu_env); + register_name = "SAAR"; break; - /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 10: + case CP0_REGISTER_10: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi)); - rn = "EntryHi"; + register_name = "EntryHi"; break; default: goto cp0_unimplemented; } break; - case 11: + case CP0_REGISTER_11: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare)); - rn = "Compare"; + register_name = "Compare"; break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } break; - case 12: + case CP0_REGISTER_12: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status)); - rn = "Status"; + register_name = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl)); - rn = "IntCtl"; + register_name = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl)); - rn = "SRSCtl"; + register_name = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); - rn = "SRSMap"; + register_name = "SRSMap"; break; default: goto cp0_unimplemented; } break; - case 13: + case CP0_REGISTER_13: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause)); - rn = "Cause"; + register_name = "Cause"; break; default: goto cp0_unimplemented; } break; - case 14: + case CP0_REGISTER_14: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC)); - rn = "EPC"; + register_name = "EPC"; break; default: goto cp0_unimplemented; } break; - case 15: + case CP0_REGISTER_15: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid)); - rn = "PRid"; + register_name = "PRid"; break; case 1: check_insn(ctx, ISA_MIPS32R2); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase)); - rn = "EBase"; + register_name = "EBase"; break; case 3: check_insn(ctx, ISA_MIPS32R2); CP0_CHECK(ctx->cmgcr); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase)); - rn = "CMGCRBase"; + register_name = "CMGCRBase"; break; default: goto cp0_unimplemented; } break; - case 16: + case CP0_REGISTER_16: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0)); - rn = "Config"; + register_name = "Config"; break; case 1: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1)); - rn = "Config1"; + register_name = "Config1"; break; case 2: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2)); - rn = "Config2"; + register_name = "Config2"; break; case 3: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3)); - rn = "Config3"; + register_name = "Config3"; break; case 4: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4)); - rn = "Config4"; + register_name = "Config4"; break; case 5: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); - rn = "Config5"; + register_name = "Config5"; break; /* 6,7 are implementation dependent */ case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); - rn = "Config6"; + register_name = "Config6"; break; case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7)); - rn = "Config7"; + register_name = "Config7"; break; default: goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_17: switch (sel) { case 0: gen_helper_dmfc0_lladdr(arg, cpu_env); - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_dmfc0_maar(arg, cpu_env); - rn = "MAAR"; + register_name = "MAAR"; break; case 2: CP0_CHECK(ctx->mrp); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI)); - rn = "MAARI"; + register_name = "MAARI"; break; default: goto cp0_unimplemented; } break; - case 18: + case CP0_REGISTER_18: switch (sel) { case 0: case 1: @@ -8661,13 +8719,13 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_1e0i(dmfc0_watchlo, arg, sel); - rn = "WatchLo"; + register_name = "WatchLo"; break; default: goto cp0_unimplemented; } break; - case 19: + case CP0_REGISTER_19: switch (sel) { case 0: case 1: @@ -8679,125 +8737,125 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_1e0i(mfc0_watchhi, arg, sel); - rn = "WatchHi"; + register_name = "WatchHi"; break; default: goto cp0_unimplemented; } break; - case 20: + case CP0_REGISTER_20: switch (sel) { case 0: check_insn(ctx, ISA_MIPS3); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext)); - rn = "XContext"; + register_name = "XContext"; break; default: goto cp0_unimplemented; } break; - case 21: + case CP0_REGISTER_21: /* Officially reserved, but sel 0 is used for R1x000 framemask */ CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask)); - rn = "Framemask"; + register_name = "Framemask"; break; default: goto cp0_unimplemented; } break; - case 22: + case CP0_REGISTER_22: tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "'Diagnostic"; /* implementation dependent */ + register_name = "'Diagnostic"; /* implementation dependent */ break; - case 23: + case CP0_REGISTER_23: switch (sel) { case 0: gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */ - rn = "Debug"; + register_name = "Debug"; break; case 1: // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */ - rn = "TraceControl"; + register_name = "TraceControl"; goto cp0_unimplemented; case 2: // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */ - rn = "TraceControl2"; + register_name = "TraceControl2"; goto cp0_unimplemented; case 3: // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */ - rn = "UserTraceData"; + register_name = "UserTraceData"; goto cp0_unimplemented; case 4: // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */ - rn = "TraceBPC"; + register_name = "TraceBPC"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 24: + case CP0_REGISTER_24: switch (sel) { case 0: /* EJTAG support */ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC)); - rn = "DEPC"; + register_name = "DEPC"; break; default: goto cp0_unimplemented; } break; - case 25: + case CP0_REGISTER_25: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0)); - rn = "Performance0"; + register_name = "Performance0"; break; case 1: // gen_helper_dmfc0_performance1(arg); - rn = "Performance1"; + register_name = "Performance1"; goto cp0_unimplemented; case 2: // gen_helper_dmfc0_performance2(arg); - rn = "Performance2"; + register_name = "Performance2"; goto cp0_unimplemented; case 3: // gen_helper_dmfc0_performance3(arg); - rn = "Performance3"; + register_name = "Performance3"; goto cp0_unimplemented; case 4: // gen_helper_dmfc0_performance4(arg); - rn = "Performance4"; + register_name = "Performance4"; goto cp0_unimplemented; case 5: // gen_helper_dmfc0_performance5(arg); - rn = "Performance5"; + register_name = "Performance5"; goto cp0_unimplemented; case 6: // gen_helper_dmfc0_performance6(arg); - rn = "Performance6"; + register_name = "Performance6"; goto cp0_unimplemented; case 7: // gen_helper_dmfc0_performance7(arg); - rn = "Performance7"; + register_name = "Performance7"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 26: + case CP0_REGISTER_26: switch (sel) { case 0: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl)); - rn = "ErrCtl"; + register_name = "ErrCtl"; break; default: goto cp0_unimplemented; } break; - case 27: + case CP0_REGISTER_27: switch (sel) { /* ignored */ case 0: @@ -8805,68 +8863,68 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 2: case 3: tcg_gen_movi_tl(arg, 0); /* unimplemented */ - rn = "CacheErr"; + register_name = "CacheErr"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: case 4: case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo)); - rn = "TagLo"; + register_name = "TagLo"; break; case 1: case 3: case 5: case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo)); - rn = "DataLo"; + register_name = "DataLo"; break; default: goto cp0_unimplemented; } break; - case 29: + case CP0_REGISTER_29: switch (sel) { case 0: case 2: case 4: case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi)); - rn = "TagHi"; + register_name = "TagHi"; break; case 1: case 3: case 5: case 7: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi)); - rn = "DataHi"; + register_name = "DataHi"; break; default: goto cp0_unimplemented; } break; - case 30: + case CP0_REGISTER_30: switch (sel) { case 0: tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC)); - rn = "ErrorEPC"; + register_name = "ErrorEPC"; break; default: goto cp0_unimplemented; } break; - case 31: + case CP0_REGISTER_31: switch (sel) { case 0: /* EJTAG support */ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); - rn = "DESAVE"; + register_name = "DESAVE"; break; case 2: case 3: @@ -8877,7 +8935,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_KScratch[sel-2])); - rn = "KScratch"; + register_name = "KScratch"; break; default: goto cp0_unimplemented; @@ -8886,17 +8944,18 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("dmfc0", rn, reg, sel); + trace_mips_translate_c0("dmfc0", register_name, reg, sel); return; cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", + register_name, reg, sel); gen_mfc0_unimplemented(ctx, arg); } static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) { - const char *rn = "invalid"; + const char *register_name = "invalid"; if (sel != 0) check_insn(ctx, ISA_MIPS64); @@ -8906,308 +8965,317 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) } switch (reg) { - case 0: + case CP0_REGISTER_00: switch (sel) { case 0: gen_helper_mtc0_index(cpu_env, arg); - rn = "Index"; + register_name = "Index"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_mvpcontrol(cpu_env, arg); - rn = "MVPControl"; + register_name = "MVPControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); /* ignored */ - rn = "MVPConf0"; + register_name = "MVPConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); /* ignored */ - rn = "MVPConf1"; + register_name = "MVPConf1"; break; case 4: CP0_CHECK(ctx->vp); /* ignored */ - rn = "VPControl"; + register_name = "VPControl"; break; default: goto cp0_unimplemented; } break; - case 1: + case CP0_REGISTER_01: switch (sel) { case 0: /* ignored */ - rn = "Random"; + register_name = "Random"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpecontrol(cpu_env, arg); - rn = "VPEControl"; + register_name = "VPEControl"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeconf0(cpu_env, arg); - rn = "VPEConf0"; + register_name = "VPEConf0"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeconf1(cpu_env, arg); - rn = "VPEConf1"; + register_name = "VPEConf1"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_yqmask(cpu_env, arg); - rn = "YQMask"; + register_name = "YQMask"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule)); - rn = "VPESchedule"; + register_name = "VPESchedule"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack)); - rn = "VPEScheFBack"; + register_name = "VPEScheFBack"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_vpeopt(cpu_env, arg); - rn = "VPEOpt"; + register_name = "VPEOpt"; break; default: goto cp0_unimplemented; } break; - case 2: + case CP0_REGISTER_02: switch (sel) { case 0: gen_helper_dmtc0_entrylo0(cpu_env, arg); - rn = "EntryLo0"; + register_name = "EntryLo0"; break; case 1: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcstatus(cpu_env, arg); - rn = "TCStatus"; + register_name = "TCStatus"; break; case 2: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcbind(cpu_env, arg); - rn = "TCBind"; + register_name = "TCBind"; break; case 3: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcrestart(cpu_env, arg); - rn = "TCRestart"; + register_name = "TCRestart"; break; case 4: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tchalt(cpu_env, arg); - rn = "TCHalt"; + register_name = "TCHalt"; break; case 5: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tccontext(cpu_env, arg); - rn = "TCContext"; + register_name = "TCContext"; break; case 6: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcschedule(cpu_env, arg); - rn = "TCSchedule"; + register_name = "TCSchedule"; break; case 7: CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mtc0_tcschefback(cpu_env, arg); - rn = "TCScheFBack"; + register_name = "TCScheFBack"; break; default: goto cp0_unimplemented; } break; - case 3: + case CP0_REGISTER_03: switch (sel) { case 0: gen_helper_dmtc0_entrylo1(cpu_env, arg); - rn = "EntryLo1"; + register_name = "EntryLo1"; break; case 1: CP0_CHECK(ctx->vp); /* ignored */ - rn = "GlobalNumber"; + register_name = "GlobalNumber"; break; default: goto cp0_unimplemented; } break; - case 4: + case CP0_REGISTER_04: switch (sel) { case 0: gen_helper_mtc0_context(cpu_env, arg); - rn = "Context"; + register_name = "Context"; break; case 1: // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ - rn = "ContextConfig"; + register_name = "ContextConfig"; goto cp0_unimplemented; case 2: CP0_CHECK(ctx->ulri); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); - rn = "UserLocal"; + register_name = "UserLocal"; break; default: goto cp0_unimplemented; } break; - case 5: + case CP0_REGISTER_05: switch (sel) { case 0: gen_helper_mtc0_pagemask(cpu_env, arg); - rn = "PageMask"; + register_name = "PageMask"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_pagegrain(cpu_env, arg); - rn = "PageGrain"; + register_name = "PageGrain"; break; case 2: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl0(cpu_env, arg); - rn = "SegCtl0"; + register_name = "SegCtl0"; break; case 3: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl1(cpu_env, arg); - rn = "SegCtl1"; + register_name = "SegCtl1"; break; case 4: CP0_CHECK(ctx->sc); gen_helper_mtc0_segctl2(cpu_env, arg); - rn = "SegCtl2"; + register_name = "SegCtl2"; break; case 5: check_pw(ctx); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase)); - rn = "PWBase"; + register_name = "PWBase"; break; case 6: check_pw(ctx); gen_helper_mtc0_pwfield(cpu_env, arg); - rn = "PWField"; + register_name = "PWField"; break; case 7: check_pw(ctx); gen_helper_mtc0_pwsize(cpu_env, arg); - rn = "PWSize"; + register_name = "PWSize"; break; default: goto cp0_unimplemented; } break; - case 6: + case CP0_REGISTER_06: switch (sel) { case 0: gen_helper_mtc0_wired(cpu_env, arg); - rn = "Wired"; + register_name = "Wired"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf0(cpu_env, arg); - rn = "SRSConf0"; + register_name = "SRSConf0"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf1(cpu_env, arg); - rn = "SRSConf1"; + register_name = "SRSConf1"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf2(cpu_env, arg); - rn = "SRSConf2"; + register_name = "SRSConf2"; break; case 4: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf3(cpu_env, arg); - rn = "SRSConf3"; + register_name = "SRSConf3"; break; case 5: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsconf4(cpu_env, arg); - rn = "SRSConf4"; + register_name = "SRSConf4"; break; case 6: check_pw(ctx); gen_helper_mtc0_pwctl(cpu_env, arg); - rn = "PWCtl"; + register_name = "PWCtl"; break; default: goto cp0_unimplemented; } break; - case 7: + case CP0_REGISTER_07: switch (sel) { case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); ctx->base.is_jmp = DISAS_STOP; - rn = "HWREna"; + register_name = "HWREna"; break; default: goto cp0_unimplemented; } break; - case 8: + case CP0_REGISTER_08: switch (sel) { case 0: /* ignored */ - rn = "BadVAddr"; + register_name = "BadVAddr"; break; case 1: /* ignored */ - rn = "BadInstr"; + register_name = "BadInstr"; break; case 2: /* ignored */ - rn = "BadInstrP"; + register_name = "BadInstrP"; break; case 3: /* ignored */ - rn = "BadInstrX"; + register_name = "BadInstrX"; break; default: goto cp0_unimplemented; } break; - case 9: + case CP0_REGISTER_09: switch (sel) { case 0: gen_helper_mtc0_count(cpu_env, arg); - rn = "Count"; + register_name = "Count"; + break; + case 6: + CP0_CHECK(ctx->saar); + gen_helper_mtc0_saari(cpu_env, arg); + register_name = "SAARI"; + break; + case 7: + CP0_CHECK(ctx->saar); + gen_helper_mtc0_saar(cpu_env, arg); + register_name = "SAAR"; break; - /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; } /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; - case 10: + case CP0_REGISTER_10: switch (sel) { case 0: gen_helper_mtc0_entryhi(cpu_env, arg); - rn = "EntryHi"; + register_name = "EntryHi"; break; default: goto cp0_unimplemented; } break; - case 11: + case CP0_REGISTER_11: switch (sel) { case 0: gen_helper_mtc0_compare(cpu_env, arg); - rn = "Compare"; + register_name = "Compare"; break; /* 6,7 are implementation dependent */ default: @@ -9216,7 +9284,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; - case 12: + case CP0_REGISTER_12: switch (sel) { case 0: save_cpu_state(ctx, 1); @@ -9224,34 +9292,34 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Status"; + register_name = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "IntCtl"; + register_name = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "SRSCtl"; + register_name = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "SRSMap"; + register_name = "SRSMap"; break; default: goto cp0_unimplemented; } break; - case 13: + case CP0_REGISTER_13: switch (sel) { case 0: save_cpu_state(ctx, 1); @@ -9261,98 +9329,98 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) * translated code to check for pending interrupts. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Cause"; + register_name = "Cause"; break; default: goto cp0_unimplemented; } break; - case 14: + case CP0_REGISTER_14: switch (sel) { case 0: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC)); - rn = "EPC"; + register_name = "EPC"; break; default: goto cp0_unimplemented; } break; - case 15: + case CP0_REGISTER_15: switch (sel) { case 0: /* ignored */ - rn = "PRid"; + register_name = "PRid"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_ebase(cpu_env, arg); - rn = "EBase"; + register_name = "EBase"; break; default: goto cp0_unimplemented; } break; - case 16: + case CP0_REGISTER_16: switch (sel) { case 0: gen_helper_mtc0_config0(cpu_env, arg); - rn = "Config"; + register_name = "Config"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 1: /* ignored, read only */ - rn = "Config1"; + register_name = "Config1"; break; case 2: gen_helper_mtc0_config2(cpu_env, arg); - rn = "Config2"; + register_name = "Config2"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 3: gen_helper_mtc0_config3(cpu_env, arg); - rn = "Config3"; + register_name = "Config3"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; case 4: /* currently ignored */ - rn = "Config4"; + register_name = "Config4"; break; case 5: gen_helper_mtc0_config5(cpu_env, arg); - rn = "Config5"; + register_name = "Config5"; /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; break; /* 6,7 are implementation dependent */ default: - rn = "Invalid config selector"; + register_name = "Invalid config selector"; goto cp0_unimplemented; } break; - case 17: + case CP0_REGISTER_17: switch (sel) { case 0: gen_helper_mtc0_lladdr(cpu_env, arg); - rn = "LLAddr"; + register_name = "LLAddr"; break; case 1: CP0_CHECK(ctx->mrp); gen_helper_mtc0_maar(cpu_env, arg); - rn = "MAAR"; + register_name = "MAAR"; break; case 2: CP0_CHECK(ctx->mrp); gen_helper_mtc0_maari(cpu_env, arg); - rn = "MAARI"; + register_name = "MAARI"; break; default: goto cp0_unimplemented; } break; - case 18: + case CP0_REGISTER_18: switch (sel) { case 0: case 1: @@ -9364,13 +9432,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_0e1i(mtc0_watchlo, arg, sel); - rn = "WatchLo"; + register_name = "WatchLo"; break; default: goto cp0_unimplemented; } break; - case 19: + case CP0_REGISTER_19: switch (sel) { case 0: case 1: @@ -9382,206 +9450,206 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); gen_helper_0e1i(mtc0_watchhi, arg, sel); - rn = "WatchHi"; + register_name = "WatchHi"; break; default: goto cp0_unimplemented; } break; - case 20: + case CP0_REGISTER_20: switch (sel) { case 0: check_insn(ctx, ISA_MIPS3); gen_helper_mtc0_xcontext(cpu_env, arg); - rn = "XContext"; + register_name = "XContext"; break; default: goto cp0_unimplemented; } break; - case 21: + case CP0_REGISTER_21: /* Officially reserved, but sel 0 is used for R1x000 framemask */ CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); switch (sel) { case 0: gen_helper_mtc0_framemask(cpu_env, arg); - rn = "Framemask"; + register_name = "Framemask"; break; default: goto cp0_unimplemented; } break; - case 22: + case CP0_REGISTER_22: /* ignored */ - rn = "Diagnostic"; /* implementation dependent */ + register_name = "Diagnostic"; /* implementation dependent */ break; - case 23: + case CP0_REGISTER_23: switch (sel) { case 0: gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ /* DISAS_STOP isn't good enough here, hflags may have changed. */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; - rn = "Debug"; + register_name = "Debug"; break; case 1: // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "TraceControl"; + register_name = "TraceControl"; goto cp0_unimplemented; case 2: // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "TraceControl2"; + register_name = "TraceControl2"; goto cp0_unimplemented; case 3: // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "UserTraceData"; + register_name = "UserTraceData"; goto cp0_unimplemented; case 4: // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ ctx->base.is_jmp = DISAS_STOP; - rn = "TraceBPC"; + register_name = "TraceBPC"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 24: + case CP0_REGISTER_24: switch (sel) { case 0: /* EJTAG support */ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC)); - rn = "DEPC"; + register_name = "DEPC"; break; default: goto cp0_unimplemented; } break; - case 25: + case CP0_REGISTER_25: switch (sel) { case 0: gen_helper_mtc0_performance0(cpu_env, arg); - rn = "Performance0"; + register_name = "Performance0"; break; case 1: // gen_helper_mtc0_performance1(cpu_env, arg); - rn = "Performance1"; + register_name = "Performance1"; goto cp0_unimplemented; case 2: // gen_helper_mtc0_performance2(cpu_env, arg); - rn = "Performance2"; + register_name = "Performance2"; goto cp0_unimplemented; case 3: // gen_helper_mtc0_performance3(cpu_env, arg); - rn = "Performance3"; + register_name = "Performance3"; goto cp0_unimplemented; case 4: // gen_helper_mtc0_performance4(cpu_env, arg); - rn = "Performance4"; + register_name = "Performance4"; goto cp0_unimplemented; case 5: // gen_helper_mtc0_performance5(cpu_env, arg); - rn = "Performance5"; + register_name = "Performance5"; goto cp0_unimplemented; case 6: // gen_helper_mtc0_performance6(cpu_env, arg); - rn = "Performance6"; + register_name = "Performance6"; goto cp0_unimplemented; case 7: // gen_helper_mtc0_performance7(cpu_env, arg); - rn = "Performance7"; + register_name = "Performance7"; goto cp0_unimplemented; default: goto cp0_unimplemented; } break; - case 26: + case CP0_REGISTER_26: switch (sel) { case 0: gen_helper_mtc0_errctl(cpu_env, arg); ctx->base.is_jmp = DISAS_STOP; - rn = "ErrCtl"; + register_name = "ErrCtl"; break; default: goto cp0_unimplemented; } break; - case 27: + case CP0_REGISTER_27: switch (sel) { case 0: case 1: case 2: case 3: /* ignored */ - rn = "CacheErr"; + register_name = "CacheErr"; break; default: goto cp0_unimplemented; } break; - case 28: + case CP0_REGISTER_28: switch (sel) { case 0: case 2: case 4: case 6: gen_helper_mtc0_taglo(cpu_env, arg); - rn = "TagLo"; + register_name = "TagLo"; break; case 1: case 3: case 5: case 7: gen_helper_mtc0_datalo(cpu_env, arg); - rn = "DataLo"; + register_name = "DataLo"; break; default: goto cp0_unimplemented; } break; - case 29: + case CP0_REGISTER_29: switch (sel) { case 0: case 2: case 4: case 6: gen_helper_mtc0_taghi(cpu_env, arg); - rn = "TagHi"; + register_name = "TagHi"; break; case 1: case 3: case 5: case 7: gen_helper_mtc0_datahi(cpu_env, arg); - rn = "DataHi"; + register_name = "DataHi"; break; default: - rn = "invalid sel"; + register_name = "invalid sel"; goto cp0_unimplemented; } break; - case 30: + case CP0_REGISTER_30: switch (sel) { case 0: tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC)); - rn = "ErrorEPC"; + register_name = "ErrorEPC"; break; default: goto cp0_unimplemented; } break; - case 31: + case CP0_REGISTER_31: switch (sel) { case 0: /* EJTAG support */ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); - rn = "DESAVE"; + register_name = "DESAVE"; break; case 2: case 3: @@ -9592,7 +9660,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) CP0_CHECK(ctx->kscrexist & (1 << sel)); tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_KScratch[sel-2])); - rn = "KScratch"; + register_name = "KScratch"; break; default: goto cp0_unimplemented; @@ -9601,7 +9669,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) default: goto cp0_unimplemented; } - trace_mips_translate_c0("dmtc0", rn, reg, sel); + trace_mips_translate_c0("dmtc0", register_name, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { @@ -9614,7 +9682,8 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) return; cp0_unimplemented: - qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel); + qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", + register_name, reg, sel); } #endif /* TARGET_MIPS64 */ @@ -29781,6 +29850,17 @@ void mips_tcg_init(void) fpu_fcr31 = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMIPSState, active_fpu.fcr31), "fcr31"); + +#if defined(TARGET_MIPS64) + cpu_mmr[0] = NULL; + for (i = 1; i < 32; i++) { + cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUMIPSState, + active_tc.mmr[i]), + regnames[i]); + } +#endif + #if !defined(TARGET_MIPS64) for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) { mxu_gpr[i] = tcg_global_mem_new(cpu_env,