Hi all, The patch below fixes the mfc0 and dmtc0 instructions for the MIPS64 target:
- The mfc0 instruction should return the 32 lowest bits of the coprocessor 0 register sign extended to 64-bit. - The mtc0 instruction should do the same as the dmtc0 instruction for 64-bit coprocessor registers instead of copying only the low 32 bits. - The XContest register does not exists on MIPS32 CPU. Note that this patch does not fix the mfc0 and dmtc0 instructions for the EntryHi coprocessor 0 register, as it would break the MIPS64 target. I will send the fix in a later patch. Bye, Aurelien --- target-mips/cpu.h 7 May 2007 13:55:33 -0000 1.31 +++ target-mips/cpu.h 12 May 2007 00:40:00 -0000 @@ -212,7 +212,9 @@ struct CPUMIPSState { target_ulong CP0_LLAddr; target_ulong CP0_WatchLo; int32_t CP0_WatchHi; +#ifdef TARGET_MIPS64 target_ulong CP0_XContext; +#endif int32_t CP0_Framemask; int32_t CP0_Debug; #define CPDB_DBD 31 --- target-mips/op.c 11 May 2007 17:08:26 -0000 1.49 +++ target-mips/op.c 12 May 2007 00:40:01 -0000 @@ -1006,7 +1006,7 @@ void op_jnz_T2 (void) /* CP0 functions */ void op_mfc0_index (void) { - T0 = env->CP0_Index; + T0 = (int32_t)env->CP0_Index; RETURN(); } @@ -1036,25 +1036,25 @@ void op_mfc0_context (void) void op_mfc0_pagemask (void) { - T0 = env->CP0_PageMask; + T0 = (int32_t)env->CP0_PageMask; RETURN(); } void op_mfc0_pagegrain (void) { - T0 = env->CP0_PageGrain; + T0 = (int32_t)env->CP0_PageGrain; RETURN(); } void op_mfc0_wired (void) { - T0 = env->CP0_Wired; + T0 = (int32_t)env->CP0_Wired; RETURN(); } void op_mfc0_hwrena (void) { - T0 = env->CP0_HWREna; + T0 = (int32_t)env->CP0_HWREna; RETURN(); } @@ -1078,37 +1078,37 @@ void op_mfc0_entryhi (void) void op_mfc0_compare (void) { - T0 = env->CP0_Compare; + T0 = (int32_t)env->CP0_Compare; RETURN(); } void op_mfc0_status (void) { - T0 = env->CP0_Status; + T0 = (int32_t)env->CP0_Status; RETURN(); } void op_mfc0_intctl (void) { - T0 = env->CP0_IntCtl; + T0 = (int32_t)env->CP0_IntCtl; RETURN(); } void op_mfc0_srsctl (void) { - T0 = env->CP0_SRSCtl; + T0 = (int32_t)env->CP0_SRSCtl; RETURN(); } void op_mfc0_srsmap (void) { - T0 = env->CP0_SRSMap; + T0 = (int32_t)env->CP0_SRSMap; RETURN(); } void op_mfc0_cause (void) { - T0 = env->CP0_Cause; + T0 = (int32_t)env->CP0_Cause; RETURN(); } @@ -1120,55 +1120,55 @@ void op_mfc0_epc (void) void op_mfc0_prid (void) { - T0 = env->CP0_PRid; + T0 = (int32_t)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 = env->CP0_Config0; + T0 = (int32_t)env->CP0_Config0; RETURN(); } void op_mfc0_config1 (void) { - T0 = env->CP0_Config1; + T0 = (int32_t)env->CP0_Config1; RETURN(); } void op_mfc0_config2 (void) { - T0 = env->CP0_Config2; + T0 = (int32_t)env->CP0_Config2; RETURN(); } void op_mfc0_config3 (void) { - T0 = env->CP0_Config3; + T0 = (int32_t)env->CP0_Config3; RETURN(); } void op_mfc0_config6 (void) { - T0 = env->CP0_Config6; + T0 = (int32_t)env->CP0_Config6; RETURN(); } void op_mfc0_config7 (void) { - T0 = env->CP0_Config7; + T0 = (int32_t)env->CP0_Config7; RETURN(); } void op_mfc0_lladdr (void) { - T0 = (int32_t)env->CP0_LLAddr >> 4; + T0 = (int32_t)(env->CP0_LLAddr >> 4); RETURN(); } @@ -1180,25 +1180,19 @@ void op_mfc0_watchlo0 (void) void op_mfc0_watchhi0 (void) { - T0 = env->CP0_WatchHi; - RETURN(); -} - -void op_mfc0_xcontext (void) -{ - T0 = (int32_t)env->CP0_XContext; + T0 = (int32_t)env->CP0_WatchHi; RETURN(); } void op_mfc0_framemask (void) { - T0 = env->CP0_Framemask; + T0 = (int32_t)env->CP0_Framemask; RETURN(); } void op_mfc0_debug (void) { - T0 = env->CP0_Debug; + T0 = (int32_t)env->CP0_Debug; if (env->hflags & MIPS_HFLAG_DM) T0 |= 1 << CP0DB_DM; RETURN(); @@ -1212,31 +1206,31 @@ void op_mfc0_depc (void) void op_mfc0_performance0 (void) { - T0 = env->CP0_Performance0; + T0 = (int32_t)env->CP0_Performance0; RETURN(); } void op_mfc0_taglo (void) { - T0 = env->CP0_TagLo; + T0 = (int32_t)env->CP0_TagLo; RETURN(); } void op_mfc0_datalo (void) { - T0 = env->CP0_DataLo; + T0 = (int32_t)env->CP0_DataLo; RETURN(); } void op_mfc0_taghi (void) { - T0 = env->CP0_TagHi; + T0 = (int32_t)env->CP0_TagHi; RETURN(); } void op_mfc0_datahi (void) { - T0 = env->CP0_DataHi; + T0 = (int32_t)env->CP0_DataHi; RETURN(); } @@ -1248,7 +1242,7 @@ void op_mfc0_errorepc (void) void op_mfc0_desave (void) { - T0 = env->CP0_DESAVE; + T0 = (int32_t)env->CP0_DESAVE; RETURN(); } @@ -1262,7 +1256,7 @@ void op_mtc0_entrylo0 (void) { /* Large physaddr not implemented */ /* 1k pages not implemented */ - env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF; + env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; RETURN(); } @@ -1270,7 +1264,7 @@ void op_mtc0_entrylo1 (void) { /* Large physaddr not implemented */ /* 1k pages not implemented */ - env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF; + env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; RETURN(); } @@ -1340,9 +1334,9 @@ void op_mtc0_status (void) uint32_t val, old; uint32_t mask = env->Status_rw_bitmask; - /* No reverse endianness, no MDMX/DSP, no 64bit ops, - no 64bit addressing implemented. */ - val = (int32_t)T0 & mask; + /* No reverse endianness, no MDMX/DSP, no 64bit ops + implemented. */ + val = T0 & mask; old = env->CP0_Status; if (!(val & (1 << CP0St_EXL)) && !(val & (1 << CP0St_ERL)) && @@ -1397,7 +1391,7 @@ void op_mtc0_cause (void) void op_mtc0_epc (void) { - env->CP0_EPC = (int32_t)T0; + env->CP0_EPC = T0; RETURN(); } @@ -1431,7 +1425,7 @@ void op_mtc0_watchlo0 (void) { /* Watch exceptions for instructions, data loads, data stores not implemented. */ - env->CP0_WatchLo = (int32_t)(T0 & ~0x7); + env->CP0_WatchLo = (T0 & ~0x7); RETURN(); } @@ -1460,7 +1454,7 @@ void op_mtc0_debug (void) void op_mtc0_depc (void) { - env->CP0_DEPC = (int32_t)T0; + env->CP0_DEPC = T0; RETURN(); } @@ -1496,7 +1490,7 @@ void op_mtc0_datahi (void) void op_mtc0_errorepc (void) { - env->CP0_ErrorEPC = (int32_t)T0; + env->CP0_ErrorEPC = T0; RETURN(); } @@ -1507,6 +1501,18 @@ void op_mtc0_desave (void) } #ifdef TARGET_MIPS64 +void op_mfc0_xcontext (void) +{ + T0 = (int32_t)env->CP0_XContext; + RETURN(); +} + +void op_mtc0_xcontext (void) +{ + env->CP0_XContext = (env->CP0_XContext & 0x1ffffffff) | (T0 & ~0x1ffffffff); + RETURN(); +} + void op_dmfc0_entrylo0 (void) { T0 = env->CP0_EntryLo0; @@ -1572,60 +1578,6 @@ 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 & ~0x007FFFFF); - RETURN(); -} - -void op_dmtc0_epc (void) -{ - env->CP0_EPC = T0; - RETURN(); -} - -void op_dmtc0_watchlo0 (void) -{ - /* Watch exceptions for instructions, data loads, data stores - not implemented. */ - env->CP0_WatchLo = T0 & ~0x7; - RETURN(); -} - -void op_dmtc0_xcontext (void) -{ - env->CP0_XContext = (env->CP0_XContext & 0xffffffff) | (T0 & ~0xffffffff); - RETURN(); -} - -void op_dmtc0_depc (void) -{ - env->CP0_DEPC = T0; - RETURN(); -} - -void op_dmtc0_errorepc (void) -{ - env->CP0_ErrorEPC = T0; - RETURN(); -} #endif /* TARGET_MIPS64 */ /* CP1 functions */ --- target-mips/translate.c 11 May 2007 17:08:26 -0000 1.75 +++ target-mips/translate.c 12 May 2007 00:40:01 -0000 @@ -2189,11 +2189,13 @@ static void gen_mfc0 (DisasContext *ctx, break; case 20: switch (sel) { +#ifdef TARGET_MIPS64 case 0: /* 64 bit MMU only */ gen_op_mfc0_xcontext(); rn = "XContext"; break; +#endif default: goto die; } @@ -2787,11 +2789,13 @@ static void gen_mtc0 (DisasContext *ctx, break; case 20: switch (sel) { +#ifdef TARGET_MIPS64 case 0: /* 64 bit MMU only */ - /* Nothing writable in lower 32 bits */ + gen_op_mtc0_xcontext(); rn = "XContext"; break; +#endif default: goto die; } @@ -3376,11 +3380,13 @@ static void gen_dmfc0 (DisasContext *ctx break; case 20: switch (sel) { +#ifdef TARGET_MIPS64 case 0: /* 64 bit MMU only */ gen_op_dmfc0_xcontext(); rn = "XContext"; break; +#endif default: goto die; } @@ -3580,15 +3586,15 @@ static void gen_dmtc0 (DisasContext *ctx rn = "Index"; break; case 1: -// gen_op_dmtc0_mvpcontrol(); /* MT ASE */ +// gen_op_mtc0_mvpcontrol(); /* MT ASE */ rn = "MVPControl"; // break; case 2: -// gen_op_dmtc0_mvpconf0(); /* MT ASE */ +// gen_op_mtc0_mvpconf0(); /* MT ASE */ rn = "MVPConf0"; // break; case 3: -// gen_op_dmtc0_mvpconf1(); /* MT ASE */ +// gen_op_mtc0_mvpconf1(); /* MT ASE */ rn = "MVPConf1"; // break; default: @@ -3602,31 +3608,31 @@ static void gen_dmtc0 (DisasContext *ctx rn = "Random"; break; case 1: -// gen_op_dmtc0_vpecontrol(); /* MT ASE */ +// gen_op_mtc0_vpecontrol(); /* MT ASE */ rn = "VPEControl"; // break; case 2: -// gen_op_dmtc0_vpeconf0(); /* MT ASE */ +// gen_op_mtc0_vpeconf0(); /* MT ASE */ rn = "VPEConf0"; // break; case 3: -// gen_op_dmtc0_vpeconf1(); /* MT ASE */ +// gen_op_mtc0_vpeconf1(); /* MT ASE */ rn = "VPEConf1"; // break; case 4: -// gen_op_dmtc0_YQMask(); /* MT ASE */ +// gen_op_mtc0_YQMask(); /* MT ASE */ rn = "YQMask"; // break; case 5: -// gen_op_dmtc0_vpeschedule(); /* MT ASE */ +// gen_op_mtc0_vpeschedule(); /* MT ASE */ rn = "VPESchedule"; // break; case 6: -// gen_op_dmtc0_vpeschefback(); /* MT ASE */ +// gen_op_mtc0_vpeschefback(); /* MT ASE */ rn = "VPEScheFBack"; // break; case 7: -// gen_op_dmtc0_vpeopt(); /* MT ASE */ +// gen_op_mtc0_vpeopt(); /* MT ASE */ rn = "VPEOpt"; // break; default: @@ -3636,35 +3642,35 @@ static void gen_dmtc0 (DisasContext *ctx case 2: switch (sel) { case 0: - gen_op_dmtc0_entrylo0(); + gen_op_mtc0_entrylo0(); rn = "EntryLo0"; break; case 1: -// gen_op_dmtc0_tcstatus(); /* MT ASE */ +// gen_op_mtc0_tcstatus(); /* MT ASE */ rn = "TCStatus"; // break; case 2: -// gen_op_dmtc0_tcbind(); /* MT ASE */ +// gen_op_mtc0_tcbind(); /* MT ASE */ rn = "TCBind"; // break; case 3: -// gen_op_dmtc0_tcrestart(); /* MT ASE */ +// gen_op_mtc0_tcrestart(); /* MT ASE */ rn = "TCRestart"; // break; case 4: -// gen_op_dmtc0_tchalt(); /* MT ASE */ +// gen_op_mtc0_tchalt(); /* MT ASE */ rn = "TCHalt"; // break; case 5: -// gen_op_dmtc0_tccontext(); /* MT ASE */ +// gen_op_mtc0_tccontext(); /* MT ASE */ rn = "TCContext"; // break; case 6: -// gen_op_dmtc0_tcschedule(); /* MT ASE */ +// gen_op_mtc0_tcschedule(); /* MT ASE */ rn = "TCSchedule"; // break; case 7: -// gen_op_dmtc0_tcschefback(); /* MT ASE */ +// gen_op_mtc0_tcschefback(); /* MT ASE */ rn = "TCScheFBack"; // break; default: @@ -3674,7 +3680,7 @@ static void gen_dmtc0 (DisasContext *ctx case 3: switch (sel) { case 0: - gen_op_dmtc0_entrylo1(); + gen_op_mtc0_entrylo1(); rn = "EntryLo1"; break; default: @@ -3684,11 +3690,11 @@ static void gen_dmtc0 (DisasContext *ctx case 4: switch (sel) { case 0: - gen_op_dmtc0_context(); + gen_op_mtc0_context(); rn = "Context"; break; case 1: -// gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */ +// gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */ rn = "ContextConfig"; // break; default: @@ -3716,23 +3722,23 @@ static void gen_dmtc0 (DisasContext *ctx rn = "Wired"; break; case 1: -// gen_op_dmtc0_srsconf0(); /* shadow registers */ +// gen_op_mtc0_srsconf0(); /* shadow registers */ rn = "SRSConf0"; // break; case 2: -// gen_op_dmtc0_srsconf1(); /* shadow registers */ +// gen_op_mtc0_srsconf1(); /* shadow registers */ rn = "SRSConf1"; // break; case 3: -// gen_op_dmtc0_srsconf2(); /* shadow registers */ +// gen_op_mtc0_srsconf2(); /* shadow registers */ rn = "SRSConf2"; // break; case 4: -// gen_op_dmtc0_srsconf3(); /* shadow registers */ +// gen_op_mtc0_srsconf3(); /* shadow registers */ rn = "SRSConf3"; // break; case 5: -// gen_op_dmtc0_srsconf4(); /* shadow registers */ +// gen_op_mtc0_srsconf4(); /* shadow registers */ rn = "SRSConf4"; // break; default: @@ -3828,7 +3834,7 @@ static void gen_dmtc0 (DisasContext *ctx case 14: switch (sel) { case 0: - gen_op_dmtc0_epc(); + gen_op_mtc0_epc(); rn = "EPC"; break; default: @@ -3890,35 +3896,35 @@ static void gen_dmtc0 (DisasContext *ctx case 18: switch (sel) { case 0: - gen_op_dmtc0_watchlo0(); + gen_op_mtc0_watchlo0(); rn = "WatchLo"; break; case 1: -// gen_op_dmtc0_watchlo1(); +// gen_op_mtc0_watchlo1(); rn = "WatchLo1"; // break; case 2: -// gen_op_dmtc0_watchlo2(); +// gen_op_mtc0_watchlo2(); rn = "WatchLo2"; // break; case 3: -// gen_op_dmtc0_watchlo3(); +// gen_op_mtc0_watchlo3(); rn = "WatchLo3"; // break; case 4: -// gen_op_dmtc0_watchlo4(); +// gen_op_mtc0_watchlo4(); rn = "WatchLo4"; // break; case 5: -// gen_op_dmtc0_watchlo5(); +// gen_op_mtc0_watchlo5(); rn = "WatchLo5"; // break; case 6: -// gen_op_dmtc0_watchlo6(); +// gen_op_mtc0_watchlo6(); rn = "WatchLo6"; // break; case 7: -// gen_op_dmtc0_watchlo7(); +// gen_op_mtc0_watchlo7(); rn = "WatchLo7"; // break; default: @@ -3932,31 +3938,31 @@ static void gen_dmtc0 (DisasContext *ctx rn = "WatchHi"; break; case 1: -// gen_op_dmtc0_watchhi1(); +// gen_op_mtc0_watchhi1(); rn = "WatchHi1"; // break; case 2: -// gen_op_dmtc0_watchhi2(); +// gen_op_mtc0_watchhi2(); rn = "WatchHi2"; // break; case 3: -// gen_op_dmtc0_watchhi3(); +// gen_op_mtc0_watchhi3(); rn = "WatchHi3"; // break; case 4: -// gen_op_dmtc0_watchhi4(); +// gen_op_mtc0_watchhi4(); rn = "WatchHi4"; // break; case 5: -// gen_op_dmtc0_watchhi5(); +// gen_op_mtc0_watchhi5(); rn = "WatchHi5"; // break; case 6: -// gen_op_dmtc0_watchhi6(); +// gen_op_mtc0_watchhi6(); rn = "WatchHi6"; // break; case 7: -// gen_op_dmtc0_watchhi7(); +// gen_op_mtc0_watchhi7(); rn = "WatchHi7"; // break; default: @@ -3967,7 +3973,7 @@ static void gen_dmtc0 (DisasContext *ctx switch (sel) { case 0: /* 64 bit MMU only */ - gen_op_dmtc0_xcontext(); + gen_op_mtc0_xcontext(); rn = "XContext"; break; default: @@ -3996,19 +4002,19 @@ static void gen_dmtc0 (DisasContext *ctx rn = "Debug"; break; case 1: -// gen_op_dmtc0_tracecontrol(); /* PDtrace support */ +// gen_op_mtc0_tracecontrol(); /* PDtrace support */ rn = "TraceControl"; // break; case 2: -// gen_op_dmtc0_tracecontrol2(); /* PDtrace support */ +// gen_op_mtc0_tracecontrol2(); /* PDtrace support */ rn = "TraceControl2"; // break; case 3: -// gen_op_dmtc0_usertracedata(); /* PDtrace support */ +// gen_op_mtc0_usertracedata(); /* PDtrace support */ rn = "UserTraceData"; // break; case 4: -// gen_op_dmtc0_debug(); /* PDtrace support */ +// gen_op_mtc0_debug(); /* PDtrace support */ rn = "TraceBPC"; // break; default: @@ -4020,7 +4026,7 @@ static void gen_dmtc0 (DisasContext *ctx case 24: switch (sel) { case 0: - gen_op_dmtc0_depc(); /* EJTAG support */ + gen_op_mtc0_depc(); /* EJTAG support */ rn = "DEPC"; break; default: @@ -4034,31 +4040,31 @@ static void gen_dmtc0 (DisasContext *ctx rn = "Performance0"; break; case 1: -// gen_op_dmtc0_performance1(); +// gen_op_mtc0_performance1(); rn = "Performance1"; // break; case 2: -// gen_op_dmtc0_performance2(); +// gen_op_mtc0_performance2(); rn = "Performance2"; // break; case 3: -// gen_op_dmtc0_performance3(); +// gen_op_mtc0_performance3(); rn = "Performance3"; // break; case 4: -// gen_op_dmtc0_performance4(); +// gen_op_mtc0_performance4(); rn = "Performance4"; // break; case 5: -// gen_op_dmtc0_performance5(); +// gen_op_mtc0_performance5(); rn = "Performance5"; // break; case 6: -// gen_op_dmtc0_performance6(); +// gen_op_mtc0_performance6(); rn = "Performance6"; // break; case 7: -// gen_op_dmtc0_performance7(); +// gen_op_mtc0_performance7(); rn = "Performance7"; // break; default: @@ -4123,7 +4129,7 @@ static void gen_dmtc0 (DisasContext *ctx case 30: switch (sel) { case 0: - gen_op_dmtc0_errorepc(); + gen_op_mtc0_errorepc(); rn = "ErrorEPC"; break; default: -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [EMAIL PROTECTED] | [EMAIL PROTECTED] `- people.debian.org/~aurel32 | www.aurel32.net