Loading target-mips/helper.h +10 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ DEF_HELPER_2(msachiu, tl, tl, tl) DEF_HELPER_0(mfc0_mvpcontrol, tl) DEF_HELPER_0(mfc0_mvpconf0, tl) DEF_HELPER_0(mfc0_mvpconf1, tl) DEF_HELPER_0(mftc0_vpecontrol, tl) DEF_HELPER_0(mftc0_vpeconf0, tl) DEF_HELPER_0(mfc0_random, tl) DEF_HELPER_0(mfc0_tcstatus, tl) DEF_HELPER_0(mftc0_tcstatus, tl) Loading @@ -70,6 +72,10 @@ DEF_HELPER_0(mftc0_tcschefback, tl) DEF_HELPER_0(mfc0_count, tl) DEF_HELPER_0(mftc0_entryhi, tl) DEF_HELPER_0(mftc0_status, tl) DEF_HELPER_0(mftc0_cause, tl) DEF_HELPER_0(mftc0_epc, tl) DEF_HELPER_0(mftc0_ebase, tl) DEF_HELPER_1(mftc0_configx, tl, tl) DEF_HELPER_0(mfc0_lladdr, tl) DEF_HELPER_1(mfc0_watchlo, tl, i32) DEF_HELPER_1(mfc0_watchhi, tl, i32) Loading @@ -88,7 +94,9 @@ DEF_HELPER_1(dmfc0_watchlo, tl, i32) DEF_HELPER_1(mtc0_index, void, tl) DEF_HELPER_1(mtc0_mvpcontrol, void, tl) DEF_HELPER_1(mtc0_vpecontrol, void, tl) DEF_HELPER_1(mttc0_vpecontrol, void, tl) DEF_HELPER_1(mtc0_vpeconf0, void, tl) DEF_HELPER_1(mttc0_vpeconf0, void, tl) DEF_HELPER_1(mtc0_vpeconf1, void, tl) DEF_HELPER_1(mtc0_yqmask, void, tl) DEF_HELPER_1(mtc0_vpeopt, void, tl) Loading Loading @@ -127,7 +135,9 @@ DEF_HELPER_1(mttc0_status, void, tl) DEF_HELPER_1(mtc0_intctl, void, tl) DEF_HELPER_1(mtc0_srsctl, void, tl) DEF_HELPER_1(mtc0_cause, void, tl) DEF_HELPER_1(mttc0_cause, void, tl) DEF_HELPER_1(mtc0_ebase, void, tl) DEF_HELPER_1(mttc0_ebase, void, tl) DEF_HELPER_1(mtc0_config0, void, tl) DEF_HELPER_1(mtc0_config2, void, tl) DEF_HELPER_1(mtc0_lladdr, void, tl) Loading target-mips/op_helper.c +129 −11 Original line number Diff line number Diff line Loading @@ -1012,6 +1012,21 @@ target_ulong helper_mftc0_entryhi(void) return other->CP0_EntryHi; } target_ulong helper_mftc0_cause(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tccause; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == other->current_tc) { tccause = other->CP0_Cause; } else { tccause = other->CP0_Cause; } return tccause; } target_ulong helper_mftc0_status(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); Loading Loading @@ -1143,6 +1158,38 @@ void helper_mtc0_vpecontrol (target_ulong arg1) env->CP0_VPEControl = newval; } void helper_mttc0_vpecontrol(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); uint32_t mask; uint32_t newval; mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) | (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC); newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask); /* TODO: Enable/disable TCs. */ other->CP0_VPEControl = newval; } target_ulong helper_mftc0_vpecontrol(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); /* FIXME: Mask away return zero on read bits. */ return other->CP0_VPEControl; } target_ulong helper_mftc0_vpeconf0(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_VPEConf0; } void helper_mtc0_vpeconf0 (target_ulong arg1) { uint32_t mask = 0; Loading @@ -1160,6 +1207,20 @@ void helper_mtc0_vpeconf0 (target_ulong arg1) env->CP0_VPEConf0 = newval; } void helper_mttc0_vpeconf0(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); uint32_t mask = 0; uint32_t newval; mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask); /* TODO: TC exclusive handling due to ERL/EXL. */ other->CP0_VPEConf0 = newval; } void helper_mtc0_vpeconf1 (target_ulong arg1) { uint32_t mask = 0; Loading Loading @@ -1490,30 +1551,61 @@ void helper_mtc0_srsctl (target_ulong arg1) env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask); } void helper_mtc0_cause (target_ulong arg1) static void mtc0_cause(CPUState *cpu, target_ulong arg1) { uint32_t mask = 0x00C00300; uint32_t old = env->CP0_Cause; uint32_t old = cpu->CP0_Cause; int i; if (env->insn_flags & ISA_MIPS32R2) if (cpu->insn_flags & ISA_MIPS32R2) { mask |= 1 << CP0Ca_DC; } env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask); cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask); if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { if (env->CP0_Cause & (1 << CP0Ca_DC)) cpu_mips_stop_count(env); else cpu_mips_start_count(env); if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) { if (cpu->CP0_Cause & (1 << CP0Ca_DC)) { cpu_mips_stop_count(cpu); } else { cpu_mips_start_count(cpu); } } /* Set/reset software interrupts */ for (i = 0 ; i < 2 ; i++) { if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) { cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i))); } } } void helper_mtc0_cause(target_ulong arg1) { mtc0_cause(env, arg1); } void helper_mttc0_cause(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); mtc0_cause(other, arg1); } target_ulong helper_mftc0_epc(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_EPC; } target_ulong helper_mftc0_ebase(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_EBase; } void helper_mtc0_ebase (target_ulong arg1) Loading @@ -1522,6 +1614,32 @@ void helper_mtc0_ebase (target_ulong arg1) env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } void helper_mttc0_ebase(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } target_ulong helper_mftc0_configx(target_ulong idx) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); switch (idx) { case 0: return other->CP0_Config0; case 1: return other->CP0_Config1; case 2: return other->CP0_Config2; case 3: return other->CP0_Config3; /* 4 and 5 are reserved. */ case 6: return other->CP0_Config6; case 7: return other->CP0_Config7; default: break; } return 0; } void helper_mtc0_config0 (target_ulong arg1) { env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007); Loading target-mips/translate.c +86 −0 Original line number Diff line number Diff line Loading @@ -5537,6 +5537,19 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, tcg_gen_movi_tl(t0, -1); else if (u == 0) { switch (rt) { case 1: switch (sel) { case 1: gen_helper_mftc0_vpecontrol(t0); break; case 2: gen_helper_mftc0_vpeconf0(t0); break; default: goto die; break; } break; case 2: switch (sel) { case 1: Loading Loading @@ -5583,6 +5596,46 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, gen_mfc0(env, ctx, t0, rt, sel); break; } case 13: switch (sel) { case 0: gen_helper_mftc0_cause(t0); break; default: goto die; break; } break; case 14: switch (sel) { case 0: gen_helper_mftc0_epc(t0); break; default: goto die; break; } break; case 15: switch (sel) { case 1: gen_helper_mftc0_ebase(t0); break; default: goto die; break; } break; case 16: switch (sel) { case 0 ... 7: gen_helper_mftc0_configx(t0, tcg_const_tl(sel)); break; default: goto die; break; } break; case 23: switch (sel) { case 0: Loading Loading @@ -5702,6 +5755,19 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, /* NOP */ ; else if (u == 0) { switch (rd) { case 1: switch (sel) { case 1: gen_helper_mttc0_vpecontrol(t0); break; case 2: gen_helper_mttc0_vpeconf0(t0); break; default: goto die; break; } break; case 2: switch (sel) { case 1: Loading Loading @@ -5748,6 +5814,26 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, gen_mtc0(env, ctx, t0, rd, sel); break; } case 13: switch (sel) { case 0: gen_helper_mttc0_cause(t0); break; default: goto die; break; } break; case 15: switch (sel) { case 1: gen_helper_mttc0_ebase(t0); break; default: goto die; break; } break; case 23: switch (sel) { case 0: Loading Loading
target-mips/helper.h +10 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ DEF_HELPER_2(msachiu, tl, tl, tl) DEF_HELPER_0(mfc0_mvpcontrol, tl) DEF_HELPER_0(mfc0_mvpconf0, tl) DEF_HELPER_0(mfc0_mvpconf1, tl) DEF_HELPER_0(mftc0_vpecontrol, tl) DEF_HELPER_0(mftc0_vpeconf0, tl) DEF_HELPER_0(mfc0_random, tl) DEF_HELPER_0(mfc0_tcstatus, tl) DEF_HELPER_0(mftc0_tcstatus, tl) Loading @@ -70,6 +72,10 @@ DEF_HELPER_0(mftc0_tcschefback, tl) DEF_HELPER_0(mfc0_count, tl) DEF_HELPER_0(mftc0_entryhi, tl) DEF_HELPER_0(mftc0_status, tl) DEF_HELPER_0(mftc0_cause, tl) DEF_HELPER_0(mftc0_epc, tl) DEF_HELPER_0(mftc0_ebase, tl) DEF_HELPER_1(mftc0_configx, tl, tl) DEF_HELPER_0(mfc0_lladdr, tl) DEF_HELPER_1(mfc0_watchlo, tl, i32) DEF_HELPER_1(mfc0_watchhi, tl, i32) Loading @@ -88,7 +94,9 @@ DEF_HELPER_1(dmfc0_watchlo, tl, i32) DEF_HELPER_1(mtc0_index, void, tl) DEF_HELPER_1(mtc0_mvpcontrol, void, tl) DEF_HELPER_1(mtc0_vpecontrol, void, tl) DEF_HELPER_1(mttc0_vpecontrol, void, tl) DEF_HELPER_1(mtc0_vpeconf0, void, tl) DEF_HELPER_1(mttc0_vpeconf0, void, tl) DEF_HELPER_1(mtc0_vpeconf1, void, tl) DEF_HELPER_1(mtc0_yqmask, void, tl) DEF_HELPER_1(mtc0_vpeopt, void, tl) Loading Loading @@ -127,7 +135,9 @@ DEF_HELPER_1(mttc0_status, void, tl) DEF_HELPER_1(mtc0_intctl, void, tl) DEF_HELPER_1(mtc0_srsctl, void, tl) DEF_HELPER_1(mtc0_cause, void, tl) DEF_HELPER_1(mttc0_cause, void, tl) DEF_HELPER_1(mtc0_ebase, void, tl) DEF_HELPER_1(mttc0_ebase, void, tl) DEF_HELPER_1(mtc0_config0, void, tl) DEF_HELPER_1(mtc0_config2, void, tl) DEF_HELPER_1(mtc0_lladdr, void, tl) Loading
target-mips/op_helper.c +129 −11 Original line number Diff line number Diff line Loading @@ -1012,6 +1012,21 @@ target_ulong helper_mftc0_entryhi(void) return other->CP0_EntryHi; } target_ulong helper_mftc0_cause(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); int32_t tccause; CPUState *other = mips_cpu_map_tc(&other_tc); if (other_tc == other->current_tc) { tccause = other->CP0_Cause; } else { tccause = other->CP0_Cause; } return tccause; } target_ulong helper_mftc0_status(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); Loading Loading @@ -1143,6 +1158,38 @@ void helper_mtc0_vpecontrol (target_ulong arg1) env->CP0_VPEControl = newval; } void helper_mttc0_vpecontrol(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); uint32_t mask; uint32_t newval; mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) | (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC); newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask); /* TODO: Enable/disable TCs. */ other->CP0_VPEControl = newval; } target_ulong helper_mftc0_vpecontrol(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); /* FIXME: Mask away return zero on read bits. */ return other->CP0_VPEControl; } target_ulong helper_mftc0_vpeconf0(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_VPEConf0; } void helper_mtc0_vpeconf0 (target_ulong arg1) { uint32_t mask = 0; Loading @@ -1160,6 +1207,20 @@ void helper_mtc0_vpeconf0 (target_ulong arg1) env->CP0_VPEConf0 = newval; } void helper_mttc0_vpeconf0(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); uint32_t mask = 0; uint32_t newval; mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask); /* TODO: TC exclusive handling due to ERL/EXL. */ other->CP0_VPEConf0 = newval; } void helper_mtc0_vpeconf1 (target_ulong arg1) { uint32_t mask = 0; Loading Loading @@ -1490,30 +1551,61 @@ void helper_mtc0_srsctl (target_ulong arg1) env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask); } void helper_mtc0_cause (target_ulong arg1) static void mtc0_cause(CPUState *cpu, target_ulong arg1) { uint32_t mask = 0x00C00300; uint32_t old = env->CP0_Cause; uint32_t old = cpu->CP0_Cause; int i; if (env->insn_flags & ISA_MIPS32R2) if (cpu->insn_flags & ISA_MIPS32R2) { mask |= 1 << CP0Ca_DC; } env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask); cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask); if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { if (env->CP0_Cause & (1 << CP0Ca_DC)) cpu_mips_stop_count(env); else cpu_mips_start_count(env); if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) { if (cpu->CP0_Cause & (1 << CP0Ca_DC)) { cpu_mips_stop_count(cpu); } else { cpu_mips_start_count(cpu); } } /* Set/reset software interrupts */ for (i = 0 ; i < 2 ; i++) { if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) { cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i))); } } } void helper_mtc0_cause(target_ulong arg1) { mtc0_cause(env, arg1); } void helper_mttc0_cause(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); mtc0_cause(other, arg1); } target_ulong helper_mftc0_epc(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_EPC; } target_ulong helper_mftc0_ebase(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); return other->CP0_EBase; } void helper_mtc0_ebase (target_ulong arg1) Loading @@ -1522,6 +1614,32 @@ void helper_mtc0_ebase (target_ulong arg1) env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } void helper_mttc0_ebase(target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); } target_ulong helper_mftc0_configx(target_ulong idx) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUState *other = mips_cpu_map_tc(&other_tc); switch (idx) { case 0: return other->CP0_Config0; case 1: return other->CP0_Config1; case 2: return other->CP0_Config2; case 3: return other->CP0_Config3; /* 4 and 5 are reserved. */ case 6: return other->CP0_Config6; case 7: return other->CP0_Config7; default: break; } return 0; } void helper_mtc0_config0 (target_ulong arg1) { env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007); Loading
target-mips/translate.c +86 −0 Original line number Diff line number Diff line Loading @@ -5537,6 +5537,19 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, tcg_gen_movi_tl(t0, -1); else if (u == 0) { switch (rt) { case 1: switch (sel) { case 1: gen_helper_mftc0_vpecontrol(t0); break; case 2: gen_helper_mftc0_vpeconf0(t0); break; default: goto die; break; } break; case 2: switch (sel) { case 1: Loading Loading @@ -5583,6 +5596,46 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, gen_mfc0(env, ctx, t0, rt, sel); break; } case 13: switch (sel) { case 0: gen_helper_mftc0_cause(t0); break; default: goto die; break; } break; case 14: switch (sel) { case 0: gen_helper_mftc0_epc(t0); break; default: goto die; break; } break; case 15: switch (sel) { case 1: gen_helper_mftc0_ebase(t0); break; default: goto die; break; } break; case 16: switch (sel) { case 0 ... 7: gen_helper_mftc0_configx(t0, tcg_const_tl(sel)); break; default: goto die; break; } break; case 23: switch (sel) { case 0: Loading Loading @@ -5702,6 +5755,19 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, /* NOP */ ; else if (u == 0) { switch (rd) { case 1: switch (sel) { case 1: gen_helper_mttc0_vpecontrol(t0); break; case 2: gen_helper_mttc0_vpeconf0(t0); break; default: goto die; break; } break; case 2: switch (sel) { case 1: Loading Loading @@ -5748,6 +5814,26 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, gen_mtc0(env, ctx, t0, rd, sel); break; } case 13: switch (sel) { case 0: gen_helper_mttc0_cause(t0); break; default: goto die; break; } break; case 15: switch (sel) { case 1: gen_helper_mttc0_ebase(t0); break; default: goto die; break; } break; case 23: switch (sel) { case 0: Loading