Loading target-mips/op_helper.c +161 −105 Original line number Diff line number Diff line Loading @@ -749,6 +749,31 @@ void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) #endif #ifndef CONFIG_USER_ONLY /* tc should point to an int with the value of the global TC index. This function will transform it into a local index within the returned CPUState. FIXME: This code assumes that all VPEs have the same number of TCs, which depends on runtime setup. Can probably be fixed by walking the list of CPUStates. */ static CPUState *mips_cpu_map_tc(int *tc) { CPUState *other; int vpe_idx, nr_threads = env->nr_threads; int tc_idx = *tc; if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) { /* Not allowed to address other CPUs. */ *tc = env->current_tc; return env; } vpe_idx = tc_idx / nr_threads; *tc = tc_idx % nr_threads; other = qemu_get_cpu(vpe_idx); return other ? other : env; } /* CP0 helpers */ target_ulong helper_mfc0_mvpcontrol (void) { Loading Loading @@ -778,11 +803,12 @@ target_ulong helper_mfc0_tcstatus (void) target_ulong helper_mftc0_tcstatus(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) return other->active_tc.CP0_TCStatus; else return env->tcs[other_tc].CP0_TCStatus; return other->tcs[other_tc].CP0_TCStatus; } target_ulong helper_mfc0_tcbind (void) Loading @@ -793,11 +819,12 @@ target_ulong helper_mfc0_tcbind (void) target_ulong helper_mftc0_tcbind(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCBind; if (other_tc == other->current_tc) return other->active_tc.CP0_TCBind; else return env->tcs[other_tc].CP0_TCBind; return other->tcs[other_tc].CP0_TCBind; } target_ulong helper_mfc0_tcrestart (void) Loading @@ -808,11 +835,12 @@ target_ulong helper_mfc0_tcrestart (void) target_ulong helper_mftc0_tcrestart(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.PC; if (other_tc == other->current_tc) return other->active_tc.PC; else return env->tcs[other_tc].PC; return other->tcs[other_tc].PC; } target_ulong helper_mfc0_tchalt (void) Loading @@ -823,11 +851,12 @@ target_ulong helper_mfc0_tchalt (void) target_ulong helper_mftc0_tchalt(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCHalt; if (other_tc == other->current_tc) return other->active_tc.CP0_TCHalt; else return env->tcs[other_tc].CP0_TCHalt; return other->tcs[other_tc].CP0_TCHalt; } target_ulong helper_mfc0_tccontext (void) Loading @@ -838,11 +867,12 @@ target_ulong helper_mfc0_tccontext (void) target_ulong helper_mftc0_tccontext(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCContext; if (other_tc == other->current_tc) return other->active_tc.CP0_TCContext; else return env->tcs[other_tc].CP0_TCContext; return other->tcs[other_tc].CP0_TCContext; } target_ulong helper_mfc0_tcschedule (void) Loading @@ -853,11 +883,12 @@ target_ulong helper_mfc0_tcschedule (void) target_ulong helper_mftc0_tcschedule(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCSchedule; if (other_tc == other->current_tc) return other->active_tc.CP0_TCSchedule; else return env->tcs[other_tc].CP0_TCSchedule; return other->tcs[other_tc].CP0_TCSchedule; } target_ulong helper_mfc0_tcschefback (void) Loading @@ -868,11 +899,12 @@ target_ulong helper_mfc0_tcschefback (void) target_ulong helper_mftc0_tcschefback(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCScheFBack; if (other_tc == other->current_tc) return other->active_tc.CP0_TCScheFBack; else return env->tcs[other_tc].CP0_TCScheFBack; return other->tcs[other_tc].CP0_TCScheFBack; } target_ulong helper_mfc0_count (void) Loading @@ -883,14 +915,15 @@ target_ulong helper_mfc0_count (void) target_ulong helper_mftc0_entryhi(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); int32_t tcstatus; if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_TCStatus; else tcstatus = env->tcs[other_tc].CP0_TCStatus; tcstatus = other->tcs[other_tc].CP0_TCStatus; return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); return (other->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); } target_ulong helper_mftc0_status(void) Loading @@ -898,13 +931,14 @@ target_ulong helper_mftc0_status(void) int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); target_ulong t0; int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_TCStatus; else tcstatus = env->tcs[other_tc].CP0_TCStatus; tcstatus = other->tcs[other_tc].CP0_TCStatus; t0 = env->CP0_Status & ~0xf1000018; t0 = other->CP0_Status & ~0xf1000018; t0 |= tcstatus & (0xf << CP0TCSt_TCU0); t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX); t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU); Loading Loading @@ -940,14 +974,15 @@ target_ulong helper_mftc0_debug(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_Debug_tcstatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_Debug_tcstatus; else tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus; tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus; /* XXX: Might be wrong, check with EJTAG spec. */ return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } Loading Loading @@ -1102,13 +1137,14 @@ void helper_mtc0_tcstatus (target_ulong arg1) void helper_mttc0_tcstatus (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); // TODO: Sync with CP0_Status. if (other_tc == env->current_tc) env->active_tc.CP0_TCStatus = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCStatus = arg1; else env->tcs[other_tc].CP0_TCStatus = arg1; other->tcs[other_tc].CP0_TCStatus = arg1; } void helper_mtc0_tcbind (target_ulong arg1) Loading @@ -1127,15 +1163,16 @@ void helper_mttc0_tcbind (target_ulong arg1) int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t mask = (1 << CP0TCBd_TBE); uint32_t newval; CPUState *other = mips_cpu_map_tc(&other_tc); if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); if (other_tc == env->current_tc) { newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); env->active_tc.CP0_TCBind = newval; if (other_tc == other->current_tc) { newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); other->active_tc.CP0_TCBind = newval; } else { newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); env->tcs[other_tc].CP0_TCBind = newval; newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); other->tcs[other_tc].CP0_TCBind = newval; } } Loading @@ -1150,16 +1187,17 @@ void helper_mtc0_tcrestart (target_ulong arg1) void helper_mttc0_tcrestart (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) { env->active_tc.PC = arg1; env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->lladdr = 0ULL; if (other_tc == other->current_tc) { other->active_tc.PC = arg1; other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); other->lladdr = 0ULL; /* MIPS16 not implemented. */ } else { env->tcs[other_tc].PC = arg1; env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->lladdr = 0ULL; other->tcs[other_tc].PC = arg1; other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); other->lladdr = 0ULL; /* MIPS16 not implemented. */ } } Loading @@ -1174,13 +1212,14 @@ void helper_mtc0_tchalt (target_ulong arg1) void helper_mttc0_tchalt (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); // TODO: Halt TC / Restart (if allocated+active) TC. if (other_tc == env->current_tc) env->active_tc.CP0_TCHalt = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCHalt = arg1; else env->tcs[other_tc].CP0_TCHalt = arg1; other->tcs[other_tc].CP0_TCHalt = arg1; } void helper_mtc0_tccontext (target_ulong arg1) Loading @@ -1191,11 +1230,12 @@ void helper_mtc0_tccontext (target_ulong arg1) void helper_mttc0_tccontext (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCContext = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCContext = arg1; else env->tcs[other_tc].CP0_TCContext = arg1; other->tcs[other_tc].CP0_TCContext = arg1; } void helper_mtc0_tcschedule (target_ulong arg1) Loading @@ -1206,11 +1246,12 @@ void helper_mtc0_tcschedule (target_ulong arg1) void helper_mttc0_tcschedule (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCSchedule = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCSchedule = arg1; else env->tcs[other_tc].CP0_TCSchedule = arg1; other->tcs[other_tc].CP0_TCSchedule = arg1; } void helper_mtc0_tcschefback (target_ulong arg1) Loading @@ -1221,11 +1262,12 @@ void helper_mtc0_tcschefback (target_ulong arg1) void helper_mttc0_tcschefback (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCScheFBack = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCScheFBack = arg1; else env->tcs[other_tc].CP0_TCScheFBack = arg1; other->tcs[other_tc].CP0_TCScheFBack = arg1; } void helper_mtc0_entrylo1 (target_ulong arg1) Loading Loading @@ -1318,14 +1360,15 @@ void helper_mttc0_entryhi(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff); if (other_tc == env->current_tc) { tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff); env->active_tc.CP0_TCStatus = tcstatus; other->CP0_EntryHi = (other->CP0_EntryHi & 0xff) | (arg1 & ~0xff); if (other_tc == other->current_tc) { tcstatus = (other->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff); other->active_tc.CP0_TCStatus = tcstatus; } else { tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff); env->tcs[other_tc].CP0_TCStatus = tcstatus; tcstatus = (other->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff); other->tcs[other_tc].CP0_TCStatus = tcstatus; } } Loading Loading @@ -1361,15 +1404,16 @@ void helper_mttc0_status(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus; CPUState *other = mips_cpu_map_tc(&other_tc); env->CP0_Status = arg1 & ~0xf1000018; other->CP0_Status = arg1 & ~0xf1000018; tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0)); tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU)); if (other_tc == env->current_tc) env->active_tc.CP0_TCStatus = tcstatus; if (other_tc == other->current_tc) other->active_tc.CP0_TCStatus = tcstatus; else env->tcs[other_tc].CP0_TCStatus = tcstatus; other->tcs[other_tc].CP0_TCStatus = tcstatus; } void helper_mtc0_intctl (target_ulong arg1) Loading Loading @@ -1471,13 +1515,15 @@ void helper_mttc0_debug(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); CPUState *other = mips_cpu_map_tc(&other_tc); /* XXX: Might be wrong, check with EJTAG spec. */ if (other_tc == env->current_tc) env->active_tc.CP0_Debug_tcstatus = val; if (other_tc == other->current_tc) other->active_tc.CP0_Debug_tcstatus = val; else env->tcs[other_tc].CP0_Debug_tcstatus = val; env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | other->tcs[other_tc].CP0_Debug_tcstatus = val; other->CP0_Debug = (other->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } Loading Loading @@ -1510,101 +1556,111 @@ void helper_mtc0_datahi (target_ulong arg1) target_ulong helper_mftgpr(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.gpr[sel]; if (other_tc == other->current_tc) return other->active_tc.gpr[sel]; else return env->tcs[other_tc].gpr[sel]; return other->tcs[other_tc].gpr[sel]; } target_ulong helper_mftlo(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.LO[sel]; if (other_tc == other->current_tc) return other->active_tc.LO[sel]; else return env->tcs[other_tc].LO[sel]; return other->tcs[other_tc].LO[sel]; } target_ulong helper_mfthi(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.HI[sel]; if (other_tc == other->current_tc) return other->active_tc.HI[sel]; else return env->tcs[other_tc].HI[sel]; return other->tcs[other_tc].HI[sel]; } target_ulong helper_mftacx(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.ACX[sel]; if (other_tc == other->current_tc) return other->active_tc.ACX[sel]; else return env->tcs[other_tc].ACX[sel]; return other->tcs[other_tc].ACX[sel]; } target_ulong helper_mftdsp(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.DSPControl; if (other_tc == other->current_tc) return other->active_tc.DSPControl; else return env->tcs[other_tc].DSPControl; return other->tcs[other_tc].DSPControl; } void helper_mttgpr(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.gpr[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.gpr[sel] = arg1; else env->tcs[other_tc].gpr[sel] = arg1; other->tcs[other_tc].gpr[sel] = arg1; } void helper_mttlo(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.LO[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.LO[sel] = arg1; else env->tcs[other_tc].LO[sel] = arg1; other->tcs[other_tc].LO[sel] = arg1; } void helper_mtthi(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.HI[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.HI[sel] = arg1; else env->tcs[other_tc].HI[sel] = arg1; other->tcs[other_tc].HI[sel] = arg1; } void helper_mttacx(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.ACX[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.ACX[sel] = arg1; else env->tcs[other_tc].ACX[sel] = arg1; other->tcs[other_tc].ACX[sel] = arg1; } void helper_mttdsp(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.DSPControl = arg1; if (other_tc == other->current_tc) other->active_tc.DSPControl = arg1; else env->tcs[other_tc].DSPControl = arg1; other->tcs[other_tc].DSPControl = arg1; } /* MIPS MT functions */ Loading Loading
target-mips/op_helper.c +161 −105 Original line number Diff line number Diff line Loading @@ -749,6 +749,31 @@ void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx) #endif #ifndef CONFIG_USER_ONLY /* tc should point to an int with the value of the global TC index. This function will transform it into a local index within the returned CPUState. FIXME: This code assumes that all VPEs have the same number of TCs, which depends on runtime setup. Can probably be fixed by walking the list of CPUStates. */ static CPUState *mips_cpu_map_tc(int *tc) { CPUState *other; int vpe_idx, nr_threads = env->nr_threads; int tc_idx = *tc; if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) { /* Not allowed to address other CPUs. */ *tc = env->current_tc; return env; } vpe_idx = tc_idx / nr_threads; *tc = tc_idx % nr_threads; other = qemu_get_cpu(vpe_idx); return other ? other : env; } /* CP0 helpers */ target_ulong helper_mfc0_mvpcontrol (void) { Loading Loading @@ -778,11 +803,12 @@ target_ulong helper_mfc0_tcstatus (void) target_ulong helper_mftc0_tcstatus(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) return other->active_tc.CP0_TCStatus; else return env->tcs[other_tc].CP0_TCStatus; return other->tcs[other_tc].CP0_TCStatus; } target_ulong helper_mfc0_tcbind (void) Loading @@ -793,11 +819,12 @@ target_ulong helper_mfc0_tcbind (void) target_ulong helper_mftc0_tcbind(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCBind; if (other_tc == other->current_tc) return other->active_tc.CP0_TCBind; else return env->tcs[other_tc].CP0_TCBind; return other->tcs[other_tc].CP0_TCBind; } target_ulong helper_mfc0_tcrestart (void) Loading @@ -808,11 +835,12 @@ target_ulong helper_mfc0_tcrestart (void) target_ulong helper_mftc0_tcrestart(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.PC; if (other_tc == other->current_tc) return other->active_tc.PC; else return env->tcs[other_tc].PC; return other->tcs[other_tc].PC; } target_ulong helper_mfc0_tchalt (void) Loading @@ -823,11 +851,12 @@ target_ulong helper_mfc0_tchalt (void) target_ulong helper_mftc0_tchalt(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCHalt; if (other_tc == other->current_tc) return other->active_tc.CP0_TCHalt; else return env->tcs[other_tc].CP0_TCHalt; return other->tcs[other_tc].CP0_TCHalt; } target_ulong helper_mfc0_tccontext (void) Loading @@ -838,11 +867,12 @@ target_ulong helper_mfc0_tccontext (void) target_ulong helper_mftc0_tccontext(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCContext; if (other_tc == other->current_tc) return other->active_tc.CP0_TCContext; else return env->tcs[other_tc].CP0_TCContext; return other->tcs[other_tc].CP0_TCContext; } target_ulong helper_mfc0_tcschedule (void) Loading @@ -853,11 +883,12 @@ target_ulong helper_mfc0_tcschedule (void) target_ulong helper_mftc0_tcschedule(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCSchedule; if (other_tc == other->current_tc) return other->active_tc.CP0_TCSchedule; else return env->tcs[other_tc].CP0_TCSchedule; return other->tcs[other_tc].CP0_TCSchedule; } target_ulong helper_mfc0_tcschefback (void) Loading @@ -868,11 +899,12 @@ target_ulong helper_mfc0_tcschefback (void) target_ulong helper_mftc0_tcschefback(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.CP0_TCScheFBack; if (other_tc == other->current_tc) return other->active_tc.CP0_TCScheFBack; else return env->tcs[other_tc].CP0_TCScheFBack; return other->tcs[other_tc].CP0_TCScheFBack; } target_ulong helper_mfc0_count (void) Loading @@ -883,14 +915,15 @@ target_ulong helper_mfc0_count (void) target_ulong helper_mftc0_entryhi(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); int32_t tcstatus; if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_TCStatus; else tcstatus = env->tcs[other_tc].CP0_TCStatus; tcstatus = other->tcs[other_tc].CP0_TCStatus; return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); return (other->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); } target_ulong helper_mftc0_status(void) Loading @@ -898,13 +931,14 @@ target_ulong helper_mftc0_status(void) int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); target_ulong t0; int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_TCStatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_TCStatus; else tcstatus = env->tcs[other_tc].CP0_TCStatus; tcstatus = other->tcs[other_tc].CP0_TCStatus; t0 = env->CP0_Status & ~0xf1000018; t0 = other->CP0_Status & ~0xf1000018; t0 |= tcstatus & (0xf << CP0TCSt_TCU0); t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX); t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU); Loading Loading @@ -940,14 +974,15 @@ target_ulong helper_mftc0_debug(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) tcstatus = env->active_tc.CP0_Debug_tcstatus; if (other_tc == other->current_tc) tcstatus = other->active_tc.CP0_Debug_tcstatus; else tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus; tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus; /* XXX: Might be wrong, check with EJTAG spec. */ return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } Loading Loading @@ -1102,13 +1137,14 @@ void helper_mtc0_tcstatus (target_ulong arg1) void helper_mttc0_tcstatus (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); // TODO: Sync with CP0_Status. if (other_tc == env->current_tc) env->active_tc.CP0_TCStatus = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCStatus = arg1; else env->tcs[other_tc].CP0_TCStatus = arg1; other->tcs[other_tc].CP0_TCStatus = arg1; } void helper_mtc0_tcbind (target_ulong arg1) Loading @@ -1127,15 +1163,16 @@ void helper_mttc0_tcbind (target_ulong arg1) int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t mask = (1 << CP0TCBd_TBE); uint32_t newval; CPUState *other = mips_cpu_map_tc(&other_tc); if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); if (other_tc == env->current_tc) { newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); env->active_tc.CP0_TCBind = newval; if (other_tc == other->current_tc) { newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask); other->active_tc.CP0_TCBind = newval; } else { newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); env->tcs[other_tc].CP0_TCBind = newval; newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask); other->tcs[other_tc].CP0_TCBind = newval; } } Loading @@ -1150,16 +1187,17 @@ void helper_mtc0_tcrestart (target_ulong arg1) void helper_mttc0_tcrestart (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) { env->active_tc.PC = arg1; env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->lladdr = 0ULL; if (other_tc == other->current_tc) { other->active_tc.PC = arg1; other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); other->lladdr = 0ULL; /* MIPS16 not implemented. */ } else { env->tcs[other_tc].PC = arg1; env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->lladdr = 0ULL; other->tcs[other_tc].PC = arg1; other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); other->lladdr = 0ULL; /* MIPS16 not implemented. */ } } Loading @@ -1174,13 +1212,14 @@ void helper_mtc0_tchalt (target_ulong arg1) void helper_mttc0_tchalt (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); // TODO: Halt TC / Restart (if allocated+active) TC. if (other_tc == env->current_tc) env->active_tc.CP0_TCHalt = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCHalt = arg1; else env->tcs[other_tc].CP0_TCHalt = arg1; other->tcs[other_tc].CP0_TCHalt = arg1; } void helper_mtc0_tccontext (target_ulong arg1) Loading @@ -1191,11 +1230,12 @@ void helper_mtc0_tccontext (target_ulong arg1) void helper_mttc0_tccontext (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCContext = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCContext = arg1; else env->tcs[other_tc].CP0_TCContext = arg1; other->tcs[other_tc].CP0_TCContext = arg1; } void helper_mtc0_tcschedule (target_ulong arg1) Loading @@ -1206,11 +1246,12 @@ void helper_mtc0_tcschedule (target_ulong arg1) void helper_mttc0_tcschedule (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCSchedule = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCSchedule = arg1; else env->tcs[other_tc].CP0_TCSchedule = arg1; other->tcs[other_tc].CP0_TCSchedule = arg1; } void helper_mtc0_tcschefback (target_ulong arg1) Loading @@ -1221,11 +1262,12 @@ void helper_mtc0_tcschefback (target_ulong arg1) void helper_mttc0_tcschefback (target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.CP0_TCScheFBack = arg1; if (other_tc == other->current_tc) other->active_tc.CP0_TCScheFBack = arg1; else env->tcs[other_tc].CP0_TCScheFBack = arg1; other->tcs[other_tc].CP0_TCScheFBack = arg1; } void helper_mtc0_entrylo1 (target_ulong arg1) Loading Loading @@ -1318,14 +1360,15 @@ void helper_mttc0_entryhi(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus; CPUState *other = mips_cpu_map_tc(&other_tc); env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff); if (other_tc == env->current_tc) { tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff); env->active_tc.CP0_TCStatus = tcstatus; other->CP0_EntryHi = (other->CP0_EntryHi & 0xff) | (arg1 & ~0xff); if (other_tc == other->current_tc) { tcstatus = (other->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff); other->active_tc.CP0_TCStatus = tcstatus; } else { tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff); env->tcs[other_tc].CP0_TCStatus = tcstatus; tcstatus = (other->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff); other->tcs[other_tc].CP0_TCStatus = tcstatus; } } Loading Loading @@ -1361,15 +1404,16 @@ void helper_mttc0_status(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus; CPUState *other = mips_cpu_map_tc(&other_tc); env->CP0_Status = arg1 & ~0xf1000018; other->CP0_Status = arg1 & ~0xf1000018; tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0)); tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU)); if (other_tc == env->current_tc) env->active_tc.CP0_TCStatus = tcstatus; if (other_tc == other->current_tc) other->active_tc.CP0_TCStatus = tcstatus; else env->tcs[other_tc].CP0_TCStatus = tcstatus; other->tcs[other_tc].CP0_TCStatus = tcstatus; } void helper_mtc0_intctl (target_ulong arg1) Loading Loading @@ -1471,13 +1515,15 @@ void helper_mttc0_debug(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); CPUState *other = mips_cpu_map_tc(&other_tc); /* XXX: Might be wrong, check with EJTAG spec. */ if (other_tc == env->current_tc) env->active_tc.CP0_Debug_tcstatus = val; if (other_tc == other->current_tc) other->active_tc.CP0_Debug_tcstatus = val; else env->tcs[other_tc].CP0_Debug_tcstatus = val; env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | other->tcs[other_tc].CP0_Debug_tcstatus = val; other->CP0_Debug = (other->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } Loading Loading @@ -1510,101 +1556,111 @@ void helper_mtc0_datahi (target_ulong arg1) target_ulong helper_mftgpr(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.gpr[sel]; if (other_tc == other->current_tc) return other->active_tc.gpr[sel]; else return env->tcs[other_tc].gpr[sel]; return other->tcs[other_tc].gpr[sel]; } target_ulong helper_mftlo(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.LO[sel]; if (other_tc == other->current_tc) return other->active_tc.LO[sel]; else return env->tcs[other_tc].LO[sel]; return other->tcs[other_tc].LO[sel]; } target_ulong helper_mfthi(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.HI[sel]; if (other_tc == other->current_tc) return other->active_tc.HI[sel]; else return env->tcs[other_tc].HI[sel]; return other->tcs[other_tc].HI[sel]; } target_ulong helper_mftacx(uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.ACX[sel]; if (other_tc == other->current_tc) return other->active_tc.ACX[sel]; else return env->tcs[other_tc].ACX[sel]; return other->tcs[other_tc].ACX[sel]; } target_ulong helper_mftdsp(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) return env->active_tc.DSPControl; if (other_tc == other->current_tc) return other->active_tc.DSPControl; else return env->tcs[other_tc].DSPControl; return other->tcs[other_tc].DSPControl; } void helper_mttgpr(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.gpr[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.gpr[sel] = arg1; else env->tcs[other_tc].gpr[sel] = arg1; other->tcs[other_tc].gpr[sel] = arg1; } void helper_mttlo(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.LO[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.LO[sel] = arg1; else env->tcs[other_tc].LO[sel] = arg1; other->tcs[other_tc].LO[sel] = arg1; } void helper_mtthi(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.HI[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.HI[sel] = arg1; else env->tcs[other_tc].HI[sel] = arg1; other->tcs[other_tc].HI[sel] = arg1; } void helper_mttacx(target_ulong arg1, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.ACX[sel] = arg1; if (other_tc == other->current_tc) other->active_tc.ACX[sel] = arg1; else env->tcs[other_tc].ACX[sel] = arg1; other->tcs[other_tc].ACX[sel] = arg1; } void helper_mttdsp(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == env->current_tc) env->active_tc.DSPControl = arg1; if (other_tc == other->current_tc) other->active_tc.DSPControl = arg1; else env->tcs[other_tc].DSPControl = arg1; other->tcs[other_tc].DSPControl = arg1; } /* MIPS MT functions */ Loading