On Sun, May 13, 2007 at 04:57:42PM +0200, Aurelien Jarno wrote: > Thiemo Seufer a écrit : > > Aurelien Jarno wrote: > >> 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. > > > > Agreed, and I think it doess already. (The places where you added > > casts read fron 32bit wide registers anyway.) > > Oops, I haven't seen before that those registers were declared as > int32_t, so that the sign extension is already done. > > Forget that part. > > >> - The mtc0 instruction should do the same as the dmtc0 instruction for > >> 64-bit coprocessor registers instead of copying only the low 32 bits. > > > > I'm not entirely sure about this, but it feels wrong, as mtc0 should > > have the same behaviour as on 32bit CPUs. What prompted the change here? > > The MIPS64 ISA manual: > > Operation: > data GPR[rt] > if (Width(CPR[0,rd,sel]) = 64) then > CPR[0,rd,sel] data > else > CPR[0,rd,sel] data31..0 > endif > > But it is also need if you need to run a 32-bit kernel on MIPS64. For > example the EntryHi register is a 64-bit register, and the higher 32 > bits (and most notably the R part of this register) has to be filled. > This part is initialised when an exception occurs, so even if a 32-bit > kernel don't know about it, it already holds the correct values. > > >> - The XContest register does not exists on MIPS32 CPU. > > > > Indeed, but simply not wiring up the instruction decoding for 32bit > > should be good enough, no need to #ifdef everything. > > >
Please find below an updated patch against the current CVS that take into account the remarks you made. Bye, Aurelien Index: op.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op.c,v retrieving revision 1.51 diff -u -d -p -r1.51 op.c --- op.c 13 May 2007 14:07:26 -0000 1.51 +++ op.c 13 May 2007 16:44:43 -0000 @@ -1262,7 +1262,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 +1270,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 +1340,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 +1397,7 @@ void op_mtc0_cause (void) void op_mtc0_epc (void) { - env->CP0_EPC = (int32_t)T0; + env->CP0_EPC = T0; RETURN(); } @@ -1426,7 +1426,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(); } @@ -1455,7 +1455,7 @@ void op_mtc0_debug (void) void op_mtc0_depc (void) { - env->CP0_DEPC = (int32_t)T0; + env->CP0_DEPC = T0; RETURN(); } @@ -1491,7 +1491,7 @@ void op_mtc0_datahi (void) void op_mtc0_errorepc (void) { - env->CP0_ErrorEPC = (int32_t)T0; + env->CP0_ErrorEPC = T0; RETURN(); } @@ -1502,6 +1502,12 @@ void op_mtc0_desave (void) } #ifdef TARGET_MIPS64 +void op_mtc0_xcontext (void) +{ + env->CP0_XContext = (env->CP0_XContext & 0x1ffffffff) | (T0 & ~0x1ffffffff); + RETURN(); +} + void op_dmfc0_entrylo0 (void) { T0 = env->CP0_EntryLo0; @@ -1567,60 +1573,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 */ Index: translate.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/translate.c,v retrieving revision 1.77 diff -u -d -p -r1.77 translate.c --- translate.c 13 May 2007 14:42:18 -0000 1.77 +++ translate.c 13 May 2007 16:44:44 -0000 @@ -2790,7 +2790,7 @@ static void gen_mtc0 (DisasContext *ctx, switch (sel) { case 0: #ifdef TARGET_MIPS64 - /* Nothing writable in lower 32 bits */ + gen_op_mtc0_xcontext(); rn = "XContext"; break; #endif @@ -3583,15 +3583,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: @@ -3605,31 +3605,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: @@ -3639,35 +3639,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: @@ -3677,7 +3677,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: @@ -3687,11 +3687,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: @@ -3719,23 +3719,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: @@ -3831,7 +3831,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: @@ -3893,35 +3893,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: @@ -3935,31 +3935,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: @@ -3970,7 +3970,7 @@ static void gen_dmtc0 (DisasContext *ctx switch (sel) { case 0: #ifdef TARGET_MIPS64 - gen_op_dmtc0_xcontext(); + gen_op_mtc0_xcontext(); rn = "XContext"; break; #endif @@ -4000,19 +4000,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: @@ -4024,7 +4024,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: @@ -4038,31 +4038,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: @@ -4127,7 +4127,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