+static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
+ int u, int sel, int h)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
+ ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
+ (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
+ gen_op_set_T0(-1);
+ else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
+ (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
+ gen_op_set_T0(-1);
+ else if (u == 0) {
+ switch (rt) {
+ case 2:
+ switch (sel) {
+ case 1:
+ gen_op_mftc0_tcstatus();
+ break;
+ case 2:
+ gen_op_mftc0_tcbind();
+ break;
+ case 3:
+ gen_op_mftc0_tcrestart();
+ break;
+ case 4:
+ gen_op_mftc0_tchalt();
+ break;
+ case 5:
+ gen_op_mftc0_tccontext();
+ break;
+ case 6:
+ gen_op_mftc0_tcschedule();
+ break;
+ case 7:
+ gen_op_mftc0_tcschefback();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ break;
+ case 10:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_entryhi();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ case 12:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_status();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ case 23:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_debug();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ }
+ } else switch (sel) {
+ /* GPR registers. */
+ case 0:
+ gen_op_mftgpr(rt);
+ break;
+ /* Auxiliary CPU registers */
+ case 1:
+ switch (rt) {
+ case 0:
+ gen_op_mftlo(0);
+ break;
+ case 1:
+ gen_op_mfthi(0);
+ break;
+ case 2:
+ gen_op_mftacx(0);
+ break;
+ case 4:
+ gen_op_mftlo(1);
+ break;
+ case 5:
+ gen_op_mfthi(1);
+ break;
+ case 6:
+ gen_op_mftacx(1);
+ break;
+ case 8:
+ gen_op_mftlo(2);
+ break;
+ case 9:
+ gen_op_mfthi(2);
+ break;
+ case 10:
+ gen_op_mftacx(2);
+ break;
+ case 12:
+ gen_op_mftlo(3);
+ break;
+ case 13:
+ gen_op_mfthi(3);
+ break;
+ case 14:
+ gen_op_mftacx(3);
+ break;
+ case 16:
+ gen_op_mftdsp();
+ break;
+ default:
+ goto die;
+ }
+ break;
+ /* Floating point (COP1). */
+ case 2:
+ /* XXX: For now we support only a single FPU context. */
+ if (h == 0) {
+ GEN_LOAD_FREG_FTN(WT0, rt);
+ gen_op_mfc1();
+ } else {
+ GEN_LOAD_FREG_FTN(WTH0, rt);
+ gen_op_mfhc1();
+ }
+ break;
+ case 3:
+ /* XXX: For now we support only a single FPU context. */
+ gen_op_cfc1(rt);
+ break;
+ /* COP2: Not implemented. */
+ case 4:
+ case 5:
+ /* fall through */
+ default:
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
+ rt, u, sel, h);
+ }
+#endif
+ return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
+ rt, u, sel, h);
+ }
+#endif
+ generate_exception(ctx, EXCP_RI);
+}
+
+static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
+ int u, int sel, int h)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
+ ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
+ (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
+ /* NOP */ ;
+ else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
+ (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
+ /* NOP */ ;
+ else if (u == 0) {
+ switch (rd) {
+ case 2:
+ switch (sel) {
+ case 1:
+ gen_op_mttc0_tcstatus();
+ break;
+ case 2:
+ gen_op_mttc0_tcbind();
+ break;
+ case 3:
+ gen_op_mttc0_tcrestart();
+ break;
+ case 4:
+ gen_op_mttc0_tchalt();
+ break;
+ case 5:
+ gen_op_mttc0_tccontext();
+ break;
+ case 6:
+ gen_op_mttc0_tcschedule();
+ break;
+ case 7:
+ gen_op_mttc0_tcschefback();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ break;
+ case 10:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_entryhi();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ case 12:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_status();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ case 23:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_debug();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ }
+ } else switch (sel) {
+ /* GPR registers. */
+ case 0:
+ gen_op_mttgpr(rd);
+ break;
+ /* Auxiliary CPU registers */
+ case 1:
+ switch (rd) {
+ case 0:
+ gen_op_mttlo(0);
+ break;
+ case 1:
+ gen_op_mtthi(0);
+ break;
+ case 2:
+ gen_op_mttacx(0);
+ break;
+ case 4:
+ gen_op_mttlo(1);
+ break;
+ case 5:
+ gen_op_mtthi(1);
+ break;
+ case 6:
+ gen_op_mttacx(1);
+ break;
+ case 8:
+ gen_op_mttlo(2);
+ break;
+ case 9:
+ gen_op_mtthi(2);
+ break;
+ case 10:
+ gen_op_mttacx(2);
+ break;
+ case 12:
+ gen_op_mttlo(3);
+ break;
+ case 13:
+ gen_op_mtthi(3);
+ break;
+ case 14:
+ gen_op_mttacx(3);
+ break;
+ case 16:
+ gen_op_mttdsp();
+ break;
+ default:
+ goto die;
+ }
+ break;
+ /* Floating point (COP1). */
+ case 2:
+ /* XXX: For now we support only a single FPU context. */
+ if (h == 0) {
+ gen_op_mtc1();
+ GEN_STORE_FTN_FREG(rd, WT0);
+ } else {
+ gen_op_mthc1();
+ GEN_STORE_FTN_FREG(rd, WTH0);
+ }
+ break;
+ case 3:
+ /* XXX: For now we support only a single FPU context. */
+ gen_op_ctc1(rd);
+ break;
+ /* COP2: Not implemented. */
+ case 4:
+ case 5:
+ /* fall through */
+ default:
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
+ rd, u, sel, h);
+ }
+#endif
+ return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
+ rd, u, sel, h);
+ }
+#endif
+ generate_exception(ctx, EXCP_RI);
+}
+