From 9c2149c8e06cf6fbf1bd5096a50486abc3b71f17 Mon Sep 17 00:00:00 2001 From: ths Date: Tue, 23 Jan 2007 22:45:22 +0000 Subject: [PATCH] Implementing dmfc/dmtc. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2348 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/cpu.h | 67 +-- target-mips/op.c | 236 ++++++++-- target-mips/op_helper.c | 12 +- target-mips/translate.c | 1205 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 1434 insertions(+), 86 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c1001c7fce..8781e3098d 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -44,7 +44,7 @@ union fpr_t { typedef struct tlb_t tlb_t; struct tlb_t { target_ulong VPN; - uint_fast32_t PageMask; + uint32_t PageMask; uint_fast8_t ASID; uint_fast16_t G:1; uint_fast16_t C0:3; @@ -110,20 +110,20 @@ struct CPUMIPSState { tlb_t tlb[MIPS_TLB_MAX]; uint32_t tlb_in_use; #endif - uint32_t CP0_index; - uint32_t CP0_random; - uint64_t CP0_EntryLo0; - uint64_t CP0_EntryLo1; - uint64_t CP0_Context; - uint32_t CP0_PageMask; - uint32_t CP0_PageGrain; - uint32_t CP0_Wired; - uint32_t CP0_HWREna; + int32_t CP0_Index; + int32_t CP0_Random; + target_ulong CP0_EntryLo0; + target_ulong CP0_EntryLo1; + target_ulong CP0_Context; + int32_t CP0_PageMask; + int32_t CP0_PageGrain; + int32_t CP0_Wired; + int32_t CP0_HWREna; target_ulong CP0_BadVAddr; - uint32_t CP0_Count; - uint64_t CP0_EntryHi; - uint32_t CP0_Compare; - uint32_t CP0_Status; + int32_t CP0_Count; + target_ulong CP0_EntryHi; + int32_t CP0_Compare; + int32_t CP0_Status; #define CP0St_CU3 31 #define CP0St_CU2 30 #define CP0St_CU1 29 @@ -146,9 +146,10 @@ struct CPUMIPSState { #define CP0St_ERL 2 #define CP0St_EXL 1 #define CP0St_IE 0 - uint32_t CP0_IntCtl; - uint32_t CP0_SRSCtl; - uint32_t CP0_Cause; + int32_t CP0_IntCtl; + int32_t CP0_SRSCtl; + int32_t CP0_SRSMap; + int32_t CP0_Cause; #define CP0Ca_BD 31 #define CP0Ca_TI 30 #define CP0Ca_CE 28 @@ -159,9 +160,9 @@ struct CPUMIPSState { #define CP0Ca_IP 8 #define CP0Ca_EC 2 target_ulong CP0_EPC; - uint32_t CP0_PRid; + int32_t CP0_PRid; target_ulong CP0_EBase; - uint32_t CP0_Config0; + int32_t CP0_Config0; #define CP0C0_M 31 #define CP0C0_K23 28 #define CP0C0_KU 25 @@ -174,7 +175,7 @@ struct CPUMIPSState { #define CP0C0_MT 7 #define CP0C0_VI 3 #define CP0C0_K0 0 - uint32_t CP0_Config1; + int32_t CP0_Config1; #define CP0C1_M 31 #define CP0C1_MMU 25 #define CP0C1_IS 22 @@ -190,7 +191,7 @@ struct CPUMIPSState { #define CP0C1_CA 2 #define CP0C1_EP 1 #define CP0C1_FP 0 - uint32_t CP0_Config2; + int32_t CP0_Config2; #define CP0C2_M 31 #define CP0C2_TU 28 #define CP0C2_TS 24 @@ -200,7 +201,7 @@ struct CPUMIPSState { #define CP0C2_SS 8 #define CP0C2_SL 4 #define CP0C2_SA 0 - uint32_t CP0_Config3; + int32_t CP0_Config3; #define CP0C3_M 31 #define CP0C3_DSPP 10 #define CP0C3_LPA 7 @@ -211,11 +212,11 @@ struct CPUMIPSState { #define CP0C3_SM 1 #define CP0C3_TL 0 target_ulong CP0_LLAddr; - uint32_t CP0_WatchLo; - uint32_t CP0_WatchHi; - uint32_t CP0_XContext; - uint32_t CP0_Framemask; - uint32_t CP0_Debug; + target_ulong CP0_WatchLo; + int32_t CP0_WatchHi; + target_ulong CP0_XContext; + int32_t CP0_Framemask; + int32_t CP0_Debug; #define CPDB_DBD 31 #define CP0DB_DM 30 #define CP0DB_LSNM 28 @@ -235,13 +236,13 @@ struct CPUMIPSState { #define CP0DB_DBp 1 #define CP0DB_DSS 0 target_ulong CP0_DEPC; - uint32_t CP0_Performance0; - uint32_t CP0_TagLo; - uint32_t CP0_DataLo; - uint32_t CP0_TagHi; - uint32_t CP0_DataHi; + int32_t CP0_Performance0; + int32_t CP0_TagLo; + int32_t CP0_DataLo; + int32_t CP0_TagHi; + int32_t CP0_DataHi; target_ulong CP0_ErrorEPC; - uint32_t CP0_DESAVE; + int32_t CP0_DESAVE; /* Qemu */ int interrupt_request; jmp_buf jmp_env; diff --git a/target-mips/op.c b/target-mips/op.c index 0550d27869..dec9f31ade 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -1032,7 +1032,7 @@ void op_jnz_T2 (void) /* CP0 functions */ void op_mfc0_index (void) { - T0 = (int32_t)(env->CP0_index); + T0 = env->CP0_Index; RETURN(); } @@ -1044,49 +1044,49 @@ void op_mfc0_random (void) void op_mfc0_entrylo0 (void) { - T0 = env->CP0_EntryLo0; + T0 = (int32_t)env->CP0_EntryLo0; RETURN(); } void op_mfc0_entrylo1 (void) { - T0 = env->CP0_EntryLo1; + T0 = (int32_t)env->CP0_EntryLo1; RETURN(); } void op_mfc0_context (void) { - T0 = env->CP0_Context; + T0 = (int32_t)env->CP0_Context; RETURN(); } void op_mfc0_pagemask (void) { - T0 = (int32_t)env->CP0_PageMask; + T0 = env->CP0_PageMask; RETURN(); } void op_mfc0_pagegrain (void) { - T0 = (int32_t)env->CP0_PageGrain; + T0 = env->CP0_PageGrain; RETURN(); } void op_mfc0_wired (void) { - T0 = (int32_t)env->CP0_Wired; + T0 = env->CP0_Wired; RETURN(); } void op_mfc0_hwrena (void) { - T0 = (int32_t)env->CP0_HWREna; + T0 = env->CP0_HWREna; RETURN(); } void op_mfc0_badvaddr (void) { - T0 = env->CP0_BadVAddr; + T0 = (int32_t)env->CP0_BadVAddr; RETURN(); } @@ -1098,19 +1098,19 @@ void op_mfc0_count (void) void op_mfc0_entryhi (void) { - T0 = env->CP0_EntryHi; + T0 = (int32_t)env->CP0_EntryHi; RETURN(); } void op_mfc0_compare (void) { - T0 = (int32_t)env->CP0_Compare; + T0 = env->CP0_Compare; RETURN(); } void op_mfc0_status (void) { - T0 = (int32_t)env->CP0_Status; + T0 = env->CP0_Status; if (env->hflags & MIPS_HFLAG_UM) T0 |= (1 << CP0St_UM); if (env->hflags & MIPS_HFLAG_ERL) @@ -1122,67 +1122,73 @@ void op_mfc0_status (void) void op_mfc0_intctl (void) { - T0 = (int32_t)env->CP0_IntCtl; + T0 = env->CP0_IntCtl; RETURN(); } void op_mfc0_srsctl (void) { - T0 = (int32_t)env->CP0_SRSCtl; + T0 = env->CP0_SRSCtl; + RETURN(); +} + +void op_mfc0_srsmap (void) +{ + T0 = env->CP0_SRSMap; RETURN(); } void op_mfc0_cause (void) { - T0 = (int32_t)env->CP0_Cause; + T0 = env->CP0_Cause; RETURN(); } void op_mfc0_epc (void) { - T0 = env->CP0_EPC; + T0 = (int32_t)env->CP0_EPC; RETURN(); } void op_mfc0_prid (void) { - T0 = (int32_t)env->CP0_PRid; + T0 = env->CP0_PRid; RETURN(); } void op_mfc0_ebase (void) { - T0 = env->CP0_EBase; + T0 = (int32_t)env->CP0_EBase; RETURN(); } void op_mfc0_config0 (void) { - T0 = (int32_t)env->CP0_Config0; + T0 = env->CP0_Config0; RETURN(); } void op_mfc0_config1 (void) { - T0 = (int32_t)env->CP0_Config1; + T0 = env->CP0_Config1; RETURN(); } void op_mfc0_config2 (void) { - T0 = (int32_t)env->CP0_Config2; + T0 = env->CP0_Config2; RETURN(); } void op_mfc0_config3 (void) { - T0 = (int32_t)env->CP0_Config3; + T0 = env->CP0_Config3; RETURN(); } void op_mfc0_lladdr (void) { - T0 = env->CP0_LLAddr >> 4; + T0 = (int32_t)env->CP0_LLAddr >> 4; RETURN(); } @@ -1194,13 +1200,13 @@ void op_mfc0_watchlo0 (void) void op_mfc0_watchhi0 (void) { - T0 = (int32_t)env->CP0_WatchHi; + T0 = env->CP0_WatchHi; RETURN(); } void op_mfc0_xcontext (void) { - T0 = env->CP0_XContext; + T0 = (int32_t)env->CP0_XContext; RETURN(); } @@ -1212,7 +1218,7 @@ void op_mfc0_framemask (void) void op_mfc0_debug (void) { - T0 = (int32_t)env->CP0_Debug; + T0 = env->CP0_Debug; if (env->hflags & MIPS_HFLAG_DM) T0 |= 1 << CP0DB_DM; RETURN(); @@ -1220,55 +1226,55 @@ void op_mfc0_debug (void) void op_mfc0_depc (void) { - T0 = env->CP0_DEPC; + T0 = (int32_t)env->CP0_DEPC; RETURN(); } void op_mfc0_performance0 (void) { - T0 = (int32_t)env->CP0_Performance0; + T0 = env->CP0_Performance0; RETURN(); } void op_mfc0_taglo (void) { - T0 = (int32_t)env->CP0_TagLo; + T0 = env->CP0_TagLo; RETURN(); } void op_mfc0_datalo (void) { - T0 = (int32_t)env->CP0_DataLo; + T0 = env->CP0_DataLo; RETURN(); } void op_mfc0_taghi (void) { - T0 = (int32_t)env->CP0_TagHi; + T0 = env->CP0_TagHi; RETURN(); } void op_mfc0_datahi (void) { - T0 = (int32_t)env->CP0_DataHi; + T0 = env->CP0_DataHi; RETURN(); } void op_mfc0_errorepc (void) { - T0 = env->CP0_ErrorEPC; + T0 = (int32_t)env->CP0_ErrorEPC; RETURN(); } void op_mfc0_desave (void) { - T0 = (int32_t)env->CP0_DESAVE; + T0 = env->CP0_DESAVE; RETURN(); } void op_mtc0_index (void) { - env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); + env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); RETURN(); } @@ -1276,7 +1282,7 @@ void op_mtc0_entrylo0 (void) { /* Large physaddr not implemented */ /* 1k pages not implemented */ - env->CP0_EntryLo0 = T0 & (int32_t)0x3FFFFFFF; + env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF; RETURN(); } @@ -1284,7 +1290,7 @@ void op_mtc0_entrylo1 (void) { /* Large physaddr not implemented */ /* 1k pages not implemented */ - env->CP0_EntryLo1 = T0 & (int32_t)0x3FFFFFFF; + env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF; RETURN(); } @@ -1334,7 +1340,7 @@ void op_mtc0_entryhi (void) /* 1k pages not implemented */ /* Ignore MIPS64 TLB for now */ - val = T0 & (int32_t)0xFFFFE0FF; + val = (int32_t)T0 & 0xFFFFE0FF; old = env->CP0_EntryHi; env->CP0_EntryHi = val; /* If the ASID changes, flush qemu's TLB. */ @@ -1353,7 +1359,7 @@ void op_mtc0_status (void) { uint32_t val, old, mask; - val = T0 & (int32_t)0xFA78FF01; + val = (int32_t)T0 & 0xFA78FF01; old = env->CP0_Status; if (T0 & (1 << CP0St_UM)) env->hflags |= MIPS_HFLAG_UM; @@ -1400,6 +1406,13 @@ void op_mtc0_srsctl (void) RETURN(); } +void op_mtc0_srsmap (void) +{ + /* shadow registers not implemented */ + env->CP0_SRSMap = 0; + RETURN(); +} + void op_mtc0_cause (void) { uint32_t val, old; @@ -1423,7 +1436,7 @@ void op_mtc0_cause (void) void op_mtc0_epc (void) { - env->CP0_EPC = T0; + env->CP0_EPC = (int32_t)T0; RETURN(); } @@ -1455,7 +1468,7 @@ void op_mtc0_config2 (void) void op_mtc0_watchlo0 (void) { - env->CP0_WatchLo = T0; + env->CP0_WatchLo = (int32_t)T0; RETURN(); } @@ -1467,7 +1480,7 @@ void op_mtc0_watchhi0 (void) void op_mtc0_xcontext (void) { - env->CP0_XContext = T0; /* XXX */ + env->CP0_XContext = (int32_t)T0; /* XXX */ RETURN(); } @@ -1489,7 +1502,7 @@ void op_mtc0_debug (void) void op_mtc0_depc (void) { - env->CP0_DEPC = T0; + env->CP0_DEPC = (int32_t)T0; RETURN(); } @@ -1501,7 +1514,7 @@ void op_mtc0_performance0 (void) void op_mtc0_taglo (void) { - env->CP0_TagLo = T0 & (int32_t)0xFFFFFCF6; + env->CP0_TagLo = T0 & 0xFFFFFCF6; RETURN(); } @@ -1525,7 +1538,7 @@ void op_mtc0_datahi (void) void op_mtc0_errorepc (void) { - env->CP0_ErrorEPC = T0; + env->CP0_ErrorEPC = (int32_t)T0; RETURN(); } @@ -1535,6 +1548,139 @@ void op_mtc0_desave (void) RETURN(); } +void op_dmfc0_entrylo0 (void) +{ + T0 = env->CP0_EntryLo0; + RETURN(); +} + +void op_dmfc0_entrylo1 (void) +{ + T0 = env->CP0_EntryLo1; + RETURN(); +} + +void op_dmfc0_context (void) +{ + T0 = env->CP0_Context; + RETURN(); +} + +void op_dmfc0_badvaddr (void) +{ + T0 = env->CP0_BadVAddr; + RETURN(); +} + +void op_dmfc0_entryhi (void) +{ + T0 = env->CP0_EntryHi; + RETURN(); +} + +void op_dmfc0_epc (void) +{ + T0 = env->CP0_EPC; + RETURN(); +} + +void op_dmfc0_ebase (void) +{ + T0 = env->CP0_EBase; + RETURN(); +} + +void op_dmfc0_lladdr (void) +{ + T0 = env->CP0_LLAddr >> 4; + RETURN(); +} + +void op_dmfc0_watchlo0 (void) +{ + T0 = env->CP0_WatchLo; + RETURN(); +} + +void op_dmfc0_xcontext (void) +{ + T0 = env->CP0_XContext; + RETURN(); +} + +void op_dmfc0_depc (void) +{ + T0 = env->CP0_DEPC; + RETURN(); +} + +void op_dmfc0_errorepc (void) +{ + T0 = env->CP0_ErrorEPC; + RETURN(); +} + +void op_dmtc0_entrylo0 (void) +{ + /* Large physaddr not implemented */ + /* 1k pages not implemented */ + env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; + RETURN(); +} + +void op_dmtc0_entrylo1 (void) +{ + /* Large physaddr not implemented */ + /* 1k pages not implemented */ + env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; + RETURN(); +} + +void op_dmtc0_context (void) +{ + env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0); + RETURN(); +} + +void op_dmtc0_epc (void) +{ + env->CP0_EPC = T0; + RETURN(); +} + +void op_dmtc0_ebase (void) +{ + /* vectored interrupts not implemented */ + /* Multi-CPU not implemented */ + /* XXX: 64bit addressing broken */ + env->CP0_EBase = (int32_t)0x80000000 | (T0 & 0x3FFFF000); + RETURN(); +} + +void op_dmtc0_watchlo0 (void) +{ + env->CP0_WatchLo = T0; + RETURN(); +} + +void op_dmtc0_xcontext (void) +{ + env->CP0_XContext = T0; /* XXX */ + RETURN(); +} + +void op_dmtc0_depc (void) +{ + env->CP0_DEPC = T0; + RETURN(); +} + +void op_dmtc0_errorepc (void) +{ + env->CP0_ErrorEPC = T0; + RETURN(); +} + #ifdef MIPS_USES_FPU #if 0 diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 4326b6621d..bea5a905e1 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -411,10 +411,10 @@ void do_tlbwi (void) that might be a further win. */ mips_tlb_flush_extra (env, MIPS_TLB_NB); - /* Wildly undefined effects for CP0_index containing a too high value and + /* Wildly undefined effects for CP0_Index containing a too high value and MIPS_TLB_NB not being a power of two. But so does real silicon. */ - invalidate_tlb(env, env->CP0_index & (MIPS_TLB_NB - 1), 0); - fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1)); + invalidate_tlb(env, env->CP0_Index & (MIPS_TLB_NB - 1), 0); + fill_tlb(env->CP0_Index & (MIPS_TLB_NB - 1)); } void do_tlbwr (void) @@ -439,7 +439,7 @@ void do_tlbp (void) /* Check ASID, virtual page number & size */ if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { /* TLB match */ - env->CP0_index = i; + env->CP0_Index = i; break; } } @@ -455,7 +455,7 @@ void do_tlbp (void) } } - env->CP0_index |= 0x80000000; + env->CP0_Index |= 0x80000000; } } @@ -465,7 +465,7 @@ void do_tlbr (void) uint8_t ASID; ASID = env->CP0_EntryHi & 0xFF; - tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; + tlb = &env->tlb[env->CP0_Index & (MIPS_TLB_NB - 1)]; /* If this will change the current ASID, flush qemu's TLB. */ if (ASID != tlb->ASID) diff --git a/target-mips/translate.c b/target-mips/translate.c index a501a178f5..3cc8a55d4e 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2827,6 +2827,1181 @@ die: generate_exception(ctx, EXCP_RI); } +static void gen_dmfc0 (DisasContext *ctx, int reg, int sel) +{ + const char *rn = "invalid"; + + switch (reg) { + case 0: + switch (sel) { + case 0: + gen_op_mfc0_index(); + rn = "Index"; + break; + case 1: +// gen_op_dmfc0_mvpcontrol(); /* MT ASE */ + rn = "MVPControl"; +// break; + case 2: +// gen_op_dmfc0_mvpconf0(); /* MT ASE */ + rn = "MVPConf0"; +// break; + case 3: +// gen_op_dmfc0_mvpconf1(); /* MT ASE */ + rn = "MVPConf1"; +// break; + default: + goto die; + } + break; + case 1: + switch (sel) { + case 0: + gen_op_mfc0_random(); + rn = "Random"; + break; + case 1: +// gen_op_dmfc0_vpecontrol(); /* MT ASE */ + rn = "VPEControl"; +// break; + case 2: +// gen_op_dmfc0_vpeconf0(); /* MT ASE */ + rn = "VPEConf0"; +// break; + case 3: +// gen_op_dmfc0_vpeconf1(); /* MT ASE */ + rn = "VPEConf1"; +// break; + case 4: +// gen_op_dmfc0_YQMask(); /* MT ASE */ + rn = "YQMask"; +// break; + case 5: +// gen_op_dmfc0_vpeschedule(); /* MT ASE */ + rn = "VPESchedule"; +// break; + case 6: +// gen_op_dmfc0_vpeschefback(); /* MT ASE */ + rn = "VPEScheFBack"; +// break; + case 7: +// gen_op_dmfc0_vpeopt(); /* MT ASE */ + rn = "VPEOpt"; +// break; + default: + goto die; + } + break; + case 2: + switch (sel) { + case 0: + gen_op_dmfc0_entrylo0(); + rn = "EntryLo0"; + break; + case 1: +// gen_op_dmfc0_tcstatus(); /* MT ASE */ + rn = "TCStatus"; +// break; + case 2: +// gen_op_dmfc0_tcbind(); /* MT ASE */ + rn = "TCBind"; +// break; + case 3: +// gen_op_dmfc0_tcrestart(); /* MT ASE */ + rn = "TCRestart"; +// break; + case 4: +// gen_op_dmfc0_tchalt(); /* MT ASE */ + rn = "TCHalt"; +// break; + case 5: +// gen_op_dmfc0_tccontext(); /* MT ASE */ + rn = "TCContext"; +// break; + case 6: +// gen_op_dmfc0_tcschedule(); /* MT ASE */ + rn = "TCSchedule"; +// break; + case 7: +// gen_op_dmfc0_tcschefback(); /* MT ASE */ + rn = "TCScheFBack"; +// break; + default: + goto die; + } + break; + case 3: + switch (sel) { + case 0: + gen_op_dmfc0_entrylo1(); + rn = "EntryLo1"; + break; + default: + goto die; + } + break; + case 4: + switch (sel) { + case 0: + gen_op_dmfc0_context(); + rn = "Context"; + break; + case 1: +// gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */ + rn = "ContextConfig"; +// break; + default: + goto die; + } + break; + case 5: + switch (sel) { + case 0: + gen_op_mfc0_pagemask(); + rn = "PageMask"; + break; + case 1: + gen_op_mfc0_pagegrain(); + rn = "PageGrain"; + break; + default: + goto die; + } + break; + case 6: + switch (sel) { + case 0: + gen_op_mfc0_wired(); + rn = "Wired"; + break; + case 1: +// gen_op_dmfc0_srsconf0(); /* shadow registers */ + rn = "SRSConf0"; +// break; + case 2: +// gen_op_dmfc0_srsconf1(); /* shadow registers */ + rn = "SRSConf1"; +// break; + case 3: +// gen_op_dmfc0_srsconf2(); /* shadow registers */ + rn = "SRSConf2"; +// break; + case 4: +// gen_op_dmfc0_srsconf3(); /* shadow registers */ + rn = "SRSConf3"; +// break; + case 5: +// gen_op_dmfc0_srsconf4(); /* shadow registers */ + rn = "SRSConf4"; +// break; + default: + goto die; + } + break; + case 7: + switch (sel) { + case 0: + gen_op_mfc0_hwrena(); + rn = "HWREna"; + break; + default: + goto die; + } + break; + case 8: + switch (sel) { + case 0: + gen_op_dmfc0_badvaddr(); + rn = "BadVaddr"; + break; + default: + goto die; + } + break; + case 9: + switch (sel) { + case 0: + gen_op_mfc0_count(); + rn = "Count"; + break; + /* 6,7 are implementation dependent */ + default: + goto die; + } + break; + case 10: + switch (sel) { + case 0: + gen_op_dmfc0_entryhi(); + rn = "EntryHi"; + break; + default: + goto die; + } + break; + case 11: + switch (sel) { + case 0: + gen_op_mfc0_compare(); + rn = "Compare"; + break; + /* 6,7 are implementation dependent */ + default: + goto die; + } + break; + case 12: + switch (sel) { + case 0: + gen_op_mfc0_status(); + rn = "Status"; + break; + case 1: + gen_op_mfc0_intctl(); + rn = "IntCtl"; + break; + case 2: + gen_op_mfc0_srsctl(); + rn = "SRSCtl"; + break; + case 3: + gen_op_mfc0_srsmap(); /* shadow registers */ + rn = "SRSMap"; + break; + default: + goto die; + } + break; + case 13: + switch (sel) { + case 0: + gen_op_mfc0_cause(); + rn = "Cause"; + break; + default: + goto die; + } + break; + case 14: + switch (sel) { + case 0: + gen_op_dmfc0_epc(); + rn = "EPC"; + break; + default: + goto die; + } + break; + case 15: + switch (sel) { + case 0: + gen_op_mfc0_prid(); + rn = "PRid"; + break; + case 1: + gen_op_dmfc0_ebase(); + rn = "EBase"; + break; + default: + goto die; + } + break; + case 16: + switch (sel) { + case 0: + gen_op_mfc0_config0(); + rn = "Config"; + break; + case 1: + gen_op_mfc0_config1(); + rn = "Config1"; + break; + case 2: + gen_op_mfc0_config2(); + rn = "Config2"; + break; + case 3: + gen_op_mfc0_config3(); + rn = "Config3"; + break; + /* 6,7 are implementation dependent */ + default: + goto die; + } + break; + case 17: + switch (sel) { + case 0: + gen_op_dmfc0_lladdr(); + rn = "LLAddr"; + break; + default: + goto die; + } + break; + case 18: + switch (sel) { + case 0: + gen_op_dmfc0_watchlo0(); + rn = "WatchLo"; + break; + case 1: +// gen_op_dmfc0_watchlo1(); + rn = "WatchLo1"; +// break; + case 2: +// gen_op_dmfc0_watchlo2(); + rn = "WatchLo2"; +// break; + case 3: +// gen_op_dmfc0_watchlo3(); + rn = "WatchLo3"; +// break; + case 4: +// gen_op_dmfc0_watchlo4(); + rn = "WatchLo4"; +// break; + case 5: +// gen_op_dmfc0_watchlo5(); + rn = "WatchLo5"; +// break; + case 6: +// gen_op_dmfc0_watchlo6(); + rn = "WatchLo6"; +// break; + case 7: +// gen_op_dmfc0_watchlo7(); + rn = "WatchLo7"; +// break; + default: + goto die; + } + break; + case 19: + switch (sel) { + case 0: + gen_op_mfc0_watchhi0(); + rn = "WatchHi"; + break; + case 1: +// gen_op_mfc0_watchhi1(); + rn = "WatchHi1"; +// break; + case 2: +// gen_op_mfc0_watchhi2(); + rn = "WatchHi2"; +// break; + case 3: +// gen_op_mfc0_watchhi3(); + rn = "WatchHi3"; +// break; + case 4: +// gen_op_mfc0_watchhi4(); + rn = "WatchHi4"; +// break; + case 5: +// gen_op_mfc0_watchhi5(); + rn = "WatchHi5"; +// break; + case 6: +// gen_op_mfc0_watchhi6(); + rn = "WatchHi6"; +// break; + case 7: +// gen_op_mfc0_watchhi7(); + rn = "WatchHi7"; +// break; + default: + goto die; + } + break; + case 20: + switch (sel) { + case 0: + /* 64 bit MMU only */ + gen_op_dmfc0_xcontext(); + rn = "XContext"; + break; + default: + goto die; + } + break; + case 21: + /* Officially reserved, but sel 0 is used for R1x000 framemask */ + switch (sel) { + case 0: + gen_op_mfc0_framemask(); + rn = "Framemask"; + break; + default: + goto die; + } + break; + case 22: + /* ignored */ + rn = "'Diagnostic"; /* implementation dependent */ + break; + case 23: + switch (sel) { + case 0: + gen_op_mfc0_debug(); /* EJTAG support */ + rn = "Debug"; + break; + case 1: +// gen_op_dmfc0_tracecontrol(); /* PDtrace support */ + rn = "TraceControl"; +// break; + case 2: +// gen_op_dmfc0_tracecontrol2(); /* PDtrace support */ + rn = "TraceControl2"; +// break; + case 3: +// gen_op_dmfc0_usertracedata(); /* PDtrace support */ + rn = "UserTraceData"; +// break; + case 4: +// gen_op_dmfc0_debug(); /* PDtrace support */ + rn = "TraceBPC"; +// break; + default: + goto die; + } + break; + case 24: + switch (sel) { + case 0: + gen_op_dmfc0_depc(); /* EJTAG support */ + rn = "DEPC"; + break; + default: + goto die; + } + break; + case 25: + switch (sel) { + case 0: + gen_op_mfc0_performance0(); + rn = "Performance0"; + break; + case 1: +// gen_op_dmfc0_performance1(); + rn = "Performance1"; +// break; + case 2: +// gen_op_dmfc0_performance2(); + rn = "Performance2"; +// break; + case 3: +// gen_op_dmfc0_performance3(); + rn = "Performance3"; +// break; + case 4: +// gen_op_dmfc0_performance4(); + rn = "Performance4"; +// break; + case 5: +// gen_op_dmfc0_performance5(); + rn = "Performance5"; +// break; + case 6: +// gen_op_dmfc0_performance6(); + rn = "Performance6"; +// break; + case 7: +// gen_op_dmfc0_performance7(); + rn = "Performance7"; +// break; + default: + goto die; + } + break; + case 26: + rn = "ECC"; + break; + case 27: + switch (sel) { + /* ignored */ + case 0 ... 3: + rn = "CacheErr"; + break; + default: + goto die; + } + break; + case 28: + switch (sel) { + case 0: + case 2: + case 4: + case 6: + gen_op_mfc0_taglo(); + rn = "TagLo"; + break; + case 1: + case 3: + case 5: + case 7: + gen_op_mfc0_datalo(); + rn = "DataLo"; + break; + default: + goto die; + } + break; + case 29: + switch (sel) { + case 0: + case 2: + case 4: + case 6: + gen_op_mfc0_taghi(); + rn = "TagHi"; + break; + case 1: + case 3: + case 5: + case 7: + gen_op_mfc0_datahi(); + rn = "DataHi"; + break; + default: + goto die; + } + break; + case 30: + switch (sel) { + case 0: + gen_op_dmfc0_errorepc(); + rn = "ErrorEPC"; + break; + default: + goto die; + } + break; + case 31: + switch (sel) { + case 0: + gen_op_mfc0_desave(); /* EJTAG support */ + rn = "DESAVE"; + break; + default: + goto die; + } + break; + default: + goto die; + } +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n", + rn, reg, sel); + } +#endif + return; + +die: +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n", + rn, reg, sel); + } +#endif + generate_exception(ctx, EXCP_RI); +} + +static void gen_dmtc0 (DisasContext *ctx, int reg, int sel) +{ + const char *rn = "invalid"; + + switch (reg) { + case 0: + switch (sel) { + case 0: + gen_op_mtc0_index(); + rn = "Index"; + break; + case 1: +// gen_op_dmtc0_mvpcontrol(); /* MT ASE */ + rn = "MVPControl"; +// break; + case 2: +// gen_op_dmtc0_mvpconf0(); /* MT ASE */ + rn = "MVPConf0"; +// break; + case 3: +// gen_op_dmtc0_mvpconf1(); /* MT ASE */ + rn = "MVPConf1"; +// break; + default: + goto die; + } + break; + case 1: + switch (sel) { + case 0: + /* ignored */ + rn = "Random"; + break; + case 1: +// gen_op_dmtc0_vpecontrol(); /* MT ASE */ + rn = "VPEControl"; +// break; + case 2: +// gen_op_dmtc0_vpeconf0(); /* MT ASE */ + rn = "VPEConf0"; +// break; + case 3: +// gen_op_dmtc0_vpeconf1(); /* MT ASE */ + rn = "VPEConf1"; +// break; + case 4: +// gen_op_dmtc0_YQMask(); /* MT ASE */ + rn = "YQMask"; +// break; + case 5: +// gen_op_dmtc0_vpeschedule(); /* MT ASE */ + rn = "VPESchedule"; +// break; + case 6: +// gen_op_dmtc0_vpeschefback(); /* MT ASE */ + rn = "VPEScheFBack"; +// break; + case 7: +// gen_op_dmtc0_vpeopt(); /* MT ASE */ + rn = "VPEOpt"; +// break; + default: + goto die; + } + break; + case 2: + switch (sel) { + case 0: + gen_op_dmtc0_entrylo0(); + rn = "EntryLo0"; + break; + case 1: +// gen_op_dmtc0_tcstatus(); /* MT ASE */ + rn = "TCStatus"; +// break; + case 2: +// gen_op_dmtc0_tcbind(); /* MT ASE */ + rn = "TCBind"; +// break; + case 3: +// gen_op_dmtc0_tcrestart(); /* MT ASE */ + rn = "TCRestart"; +// break; + case 4: +// gen_op_dmtc0_tchalt(); /* MT ASE */ + rn = "TCHalt"; +// break; + case 5: +// gen_op_dmtc0_tccontext(); /* MT ASE */ + rn = "TCContext"; +// break; + case 6: +// gen_op_dmtc0_tcschedule(); /* MT ASE */ + rn = "TCSchedule"; +// break; + case 7: +// gen_op_dmtc0_tcschefback(); /* MT ASE */ + rn = "TCScheFBack"; +// break; + default: + goto die; + } + break; + case 3: + switch (sel) { + case 0: + gen_op_dmtc0_entrylo1(); + rn = "EntryLo1"; + break; + default: + goto die; + } + break; + case 4: + switch (sel) { + case 0: + gen_op_dmtc0_context(); + rn = "Context"; + break; + case 1: +// gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */ + rn = "ContextConfig"; +// break; + default: + goto die; + } + break; + case 5: + switch (sel) { + case 0: + gen_op_mtc0_pagemask(); + rn = "PageMask"; + break; + case 1: + gen_op_mtc0_pagegrain(); + rn = "PageGrain"; + break; + default: + goto die; + } + break; + case 6: + switch (sel) { + case 0: + gen_op_mtc0_wired(); + rn = "Wired"; + break; + case 1: +// gen_op_dmtc0_srsconf0(); /* shadow registers */ + rn = "SRSConf0"; +// break; + case 2: +// gen_op_dmtc0_srsconf1(); /* shadow registers */ + rn = "SRSConf1"; +// break; + case 3: +// gen_op_dmtc0_srsconf2(); /* shadow registers */ + rn = "SRSConf2"; +// break; + case 4: +// gen_op_dmtc0_srsconf3(); /* shadow registers */ + rn = "SRSConf3"; +// break; + case 5: +// gen_op_dmtc0_srsconf4(); /* shadow registers */ + rn = "SRSConf4"; +// break; + default: + goto die; + } + break; + case 7: + switch (sel) { + case 0: + gen_op_mtc0_hwrena(); + rn = "HWREna"; + break; + default: + goto die; + } + break; + case 8: + /* ignored */ + rn = "BadVaddr"; + break; + case 9: + switch (sel) { + case 0: + gen_op_mtc0_count(); + rn = "Count"; + break; + /* 6,7 are implementation dependent */ + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 10: + switch (sel) { + case 0: + gen_op_mtc0_entryhi(); + rn = "EntryHi"; + break; + default: + goto die; + } + break; + case 11: + switch (sel) { + case 0: + gen_op_mtc0_compare(); + rn = "Compare"; + break; + /* 6,7 are implementation dependent */ + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 12: + switch (sel) { + case 0: + gen_op_mtc0_status(); + rn = "Status"; + break; + case 1: + gen_op_mtc0_intctl(); + rn = "IntCtl"; + break; + case 2: + gen_op_mtc0_srsctl(); + rn = "SRSCtl"; + break; + case 3: + gen_op_mtc0_srsmap(); /* shadow registers */ + rn = "SRSMap"; + break; + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 13: + switch (sel) { + case 0: + gen_op_mtc0_cause(); + rn = "Cause"; + break; + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 14: + switch (sel) { + case 0: + gen_op_dmtc0_epc(); + rn = "EPC"; + break; + default: + goto die; + } + break; + case 15: + switch (sel) { + case 0: + /* ignored */ + rn = "PRid"; + break; + case 1: + gen_op_dmtc0_ebase(); + rn = "EBase"; + break; + default: + goto die; + } + break; + case 16: + switch (sel) { + case 0: + gen_op_mtc0_config0(); + rn = "Config"; + break; + case 1: + /* ignored */ + rn = "Config1"; + break; + case 2: + gen_op_mtc0_config2(); + rn = "Config2"; + break; + case 3: + /* ignored */ + rn = "Config3"; + break; + /* 6,7 are implementation dependent */ + default: + rn = "Invalid config selector"; + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 17: + switch (sel) { + case 0: + /* ignored */ + rn = "LLAddr"; + break; + default: + goto die; + } + break; + case 18: + switch (sel) { + case 0: + gen_op_dmtc0_watchlo0(); + rn = "WatchLo"; + break; + case 1: +// gen_op_dmtc0_watchlo1(); + rn = "WatchLo1"; +// break; + case 2: +// gen_op_dmtc0_watchlo2(); + rn = "WatchLo2"; +// break; + case 3: +// gen_op_dmtc0_watchlo3(); + rn = "WatchLo3"; +// break; + case 4: +// gen_op_dmtc0_watchlo4(); + rn = "WatchLo4"; +// break; + case 5: +// gen_op_dmtc0_watchlo5(); + rn = "WatchLo5"; +// break; + case 6: +// gen_op_dmtc0_watchlo6(); + rn = "WatchLo6"; +// break; + case 7: +// gen_op_dmtc0_watchlo7(); + rn = "WatchLo7"; +// break; + default: + goto die; + } + break; + case 19: + switch (sel) { + case 0: + gen_op_mtc0_watchhi0(); + rn = "WatchHi"; + break; + case 1: +// gen_op_dmtc0_watchhi1(); + rn = "WatchHi1"; +// break; + case 2: +// gen_op_dmtc0_watchhi2(); + rn = "WatchHi2"; +// break; + case 3: +// gen_op_dmtc0_watchhi3(); + rn = "WatchHi3"; +// break; + case 4: +// gen_op_dmtc0_watchhi4(); + rn = "WatchHi4"; +// break; + case 5: +// gen_op_dmtc0_watchhi5(); + rn = "WatchHi5"; +// break; + case 6: +// gen_op_dmtc0_watchhi6(); + rn = "WatchHi6"; +// break; + case 7: +// gen_op_dmtc0_watchhi7(); + rn = "WatchHi7"; +// break; + default: + goto die; + } + break; + case 20: + switch (sel) { + case 0: + /* 64 bit MMU only */ + gen_op_dmtc0_xcontext(); + rn = "XContext"; + break; + default: + goto die; + } + break; + case 21: + /* Officially reserved, but sel 0 is used for R1x000 framemask */ + switch (sel) { + case 0: + gen_op_mtc0_framemask(); + rn = "Framemask"; + break; + default: + goto die; + } + break; + case 22: + /* ignored */ + rn = "Diagnostic"; /* implementation dependent */ + break; + case 23: + switch (sel) { + case 0: + gen_op_mtc0_debug(); /* EJTAG support */ + rn = "Debug"; + break; + case 1: +// gen_op_dmtc0_tracecontrol(); /* PDtrace support */ + rn = "TraceControl"; +// break; + case 2: +// gen_op_dmtc0_tracecontrol2(); /* PDtrace support */ + rn = "TraceControl2"; +// break; + case 3: +// gen_op_dmtc0_usertracedata(); /* PDtrace support */ + rn = "UserTraceData"; +// break; + case 4: +// gen_op_dmtc0_debug(); /* PDtrace support */ + rn = "TraceBPC"; +// break; + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + case 24: + switch (sel) { + case 0: + gen_op_dmtc0_depc(); /* EJTAG support */ + rn = "DEPC"; + break; + default: + goto die; + } + break; + case 25: + switch (sel) { + case 0: + gen_op_mtc0_performance0(); + rn = "Performance0"; + break; + case 1: +// gen_op_dmtc0_performance1(); + rn = "Performance1"; +// break; + case 2: +// gen_op_dmtc0_performance2(); + rn = "Performance2"; +// break; + case 3: +// gen_op_dmtc0_performance3(); + rn = "Performance3"; +// break; + case 4: +// gen_op_dmtc0_performance4(); + rn = "Performance4"; +// break; + case 5: +// gen_op_dmtc0_performance5(); + rn = "Performance5"; +// break; + case 6: +// gen_op_dmtc0_performance6(); + rn = "Performance6"; +// break; + case 7: +// gen_op_dmtc0_performance7(); + rn = "Performance7"; +// break; + default: + goto die; + } + break; + case 26: + /* ignored */ + rn = "ECC"; + break; + case 27: + switch (sel) { + case 0 ... 3: + /* ignored */ + rn = "CacheErr"; + break; + default: + goto die; + } + break; + case 28: + switch (sel) { + case 0: + case 2: + case 4: + case 6: + gen_op_mtc0_taglo(); + rn = "TagLo"; + break; + case 1: + case 3: + case 5: + case 7: + gen_op_mtc0_datalo(); + rn = "DataLo"; + break; + default: + goto die; + } + break; + case 29: + switch (sel) { + case 0: + case 2: + case 4: + case 6: + gen_op_mtc0_taghi(); + rn = "TagHi"; + break; + case 1: + case 3: + case 5: + case 7: + gen_op_mtc0_datahi(); + rn = "DataHi"; + break; + default: + rn = "invalid sel"; + goto die; + } + break; + case 30: + switch (sel) { + case 0: + gen_op_dmtc0_errorepc(); + rn = "ErrorEPC"; + break; + default: + goto die; + } + break; + case 31: + switch (sel) { + case 0: + gen_op_mtc0_desave(); /* EJTAG support */ + rn = "DESAVE"; + break; + default: + goto die; + } + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; + default: + goto die; + } +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n", + rn, reg, sel); + } +#endif + return; + +die: +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n", + rn, reg, sel); + } +#endif + generate_exception(ctx, EXCP_RI); +} + static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) { const char *opn = "unk"; @@ -2854,7 +4029,7 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) break; case OPC_MTC0: /* If we get an exception, we want to restart at next instruction */ - /* XXX: breaks for mtc in delay slot */ + /* XXX: breaks for mtc in delay slot */ ctx->pc += 4; save_cpu_state(ctx, 1); ctx->pc -= 4; @@ -2862,6 +4037,25 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) gen_mtc0(ctx, rd, ctx->opcode & 0x7); opn = "mtc0"; break; + case OPC_DMFC0: + if (rt == 0) { + /* Treat as NOP */ + return; + } + gen_dmfc0(ctx, rd, ctx->opcode & 0x7); + gen_op_store_T0_gpr(rt); + opn = "dmfc0"; + break; + case OPC_DMTC0: + /* If we get an exception, we want to restart at next instruction */ + /* XXX: breaks for dmtc in delay slot */ + ctx->pc += 4; + save_cpu_state(ctx, 1); + ctx->pc -= 4; + GEN_LOAD_REG_TN(T0, rt); + gen_dmtc0(ctx, rd, ctx->opcode & 0x7); + opn = "dmtc0"; + break; #if defined(MIPS_USES_R4K_TLB) case OPC_TLBWI: gen_op_tlbwi(); @@ -3002,6 +4196,9 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) gen_op_ctc1(); opn = "ctc1"; break; + case OPC_DMFC1: + case OPC_DMTC1: + /* Not implemented, fallthrough. */ default: if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n", @@ -3703,6 +4900,10 @@ static void decode_opc (DisasContext *ctx) case OPC_CFC1: case OPC_MTC1: case OPC_CTC1: +#ifdef MIPS_HAS_MIPS64 + case OPC_DMFC1: + case OPC_DMTC1: +#endif gen_cp1(ctx, op1, rt, rd); break; case OPC_BC1: @@ -4099,7 +5300,7 @@ void cpu_reset (CPUMIPSState *env) } env->PC = (int32_t)0xBFC00000; #if defined (MIPS_USES_R4K_TLB) - env->CP0_random = MIPS_TLB_NB - 1; + env->CP0_Random = MIPS_TLB_NB - 1; env->tlb_in_use = MIPS_TLB_NB; #endif env->CP0_Wired = 0; -- 2.11.0