提交 9c2149c8 编写于 作者: T ths

Implementing dmfc/dmtc.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2348 c046a42c-6fe2-441c-8c8c-71466251a162
上级 17c275d9
......@@ -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;
......
......@@ -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
......
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册