diff --git a/target-mips/exec.h b/target-mips/exec.h index a1cf685a16..bc330c0295 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -66,7 +66,8 @@ void do_maddu (void); void do_msub (void); void do_msubu (void); #endif -void do_mfc0(int reg, int sel); +void do_mfc0_random(void); +void do_mfc0_count(void); void do_mtc0(int reg, int sel); void do_tlbwi (void); void do_tlbwr (void); diff --git a/target-mips/op.c b/target-mips/op.c index 534c90e51f..2597e2e3d3 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -688,9 +688,167 @@ void op_jnz_T2 (void) } /* CP0 functions */ -void op_mfc0 (void) +void op_mfc0_index (void) { - CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2); + T0 = env->CP0_index; + RETURN(); +} + +void op_mfc0_random (void) +{ + CALL_FROM_TB0(do_mfc0_random); + RETURN(); +} + +void op_mfc0_entrylo0 (void) +{ + T0 = env->CP0_EntryLo0; + RETURN(); +} + +void op_mfc0_entrylo1 (void) +{ + T0 = env->CP0_EntryLo1; + RETURN(); +} + +void op_mfc0_context (void) +{ + T0 = env->CP0_Context; + RETURN(); +} + +void op_mfc0_pagemask (void) +{ + T0 = env->CP0_PageMask; + RETURN(); +} + +void op_mfc0_wired (void) +{ + T0 = env->CP0_Wired; + RETURN(); +} + +void op_mfc0_badvaddr (void) +{ + T0 = env->CP0_BadVAddr; + RETURN(); +} + +void op_mfc0_count (void) +{ + CALL_FROM_TB0(do_mfc0_count); + RETURN(); +} + +void op_mfc0_entryhi (void) +{ + T0 = env->CP0_EntryHi; + RETURN(); +} + +void op_mfc0_compare (void) +{ + T0 = env->CP0_Compare; + RETURN(); +} + +void op_mfc0_status (void) +{ + T0 = env->CP0_Status; + if (env->hflags & MIPS_HFLAG_UM) + T0 |= (1 << CP0St_UM); + if (env->hflags & MIPS_HFLAG_ERL) + T0 |= (1 << CP0St_ERL); + if (env->hflags & MIPS_HFLAG_EXL) + T0 |= (1 << CP0St_EXL); + RETURN(); +} + +void op_mfc0_cause (void) +{ + T0 = env->CP0_Cause; + RETURN(); +} + +void op_mfc0_epc (void) +{ + T0 = env->CP0_EPC; + RETURN(); +} + +void op_mfc0_prid (void) +{ + T0 = env->CP0_PRid; + RETURN(); +} + +void op_mfc0_config0 (void) +{ + T0 = env->CP0_Config0; + RETURN(); +} + +void op_mfc0_config1 (void) +{ + T0 = env->CP0_Config1; + RETURN(); +} + +void op_mfc0_lladdr (void) +{ + T0 = env->CP0_LLAddr >> 4; + RETURN(); +} + +void op_mfc0_watchlo (void) +{ + T0 = env->CP0_WatchLo; + RETURN(); +} + +void op_mfc0_watchhi (void) +{ + T0 = env->CP0_WatchHi; + RETURN(); +} + +void op_mfc0_debug (void) +{ + T0 = env->CP0_Debug; + if (env->hflags & MIPS_HFLAG_DM) + T0 |= 1 << CP0DB_DM; + RETURN(); +} + +void op_mfc0_depc (void) +{ + T0 = env->CP0_DEPC; + RETURN(); +} + +void op_mfc0_taglo (void) +{ + T0 = env->CP0_TagLo; + RETURN(); +} + +void op_mfc0_datalo (void) +{ + T0 = env->CP0_DataLo; + RETURN(); +} + +void op_mfc0_errorepc (void) +{ + T0 = env->CP0_ErrorEPC; + RETURN(); +} + +void op_mfc0_desave (void) +{ + T0 = env->CP0_DESAVE; RETURN(); } diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index c7d86d0167..d3959f3801 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -131,10 +131,16 @@ void do_msubu (void) #endif #if defined(CONFIG_USER_ONLY) -void do_mfc0 (int reg, int sel) +void do_mfc0_random (void) { - cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel); + cpu_abort(env, "mfc0 random\n"); } + +void do_mfc0_count (void) +{ + cpu_abort(env, "mfc0 count\n"); +} + void do_mtc0 (int reg, int sel) { cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel); @@ -159,152 +165,18 @@ void do_tlbr (void) { cpu_abort(env, "tlbr\n"); } + #else /* CP0 helpers */ -void do_mfc0 (int reg, int sel) +void do_mfc0_random (void) { - const unsigned char *rn; + T0 = cpu_mips_get_random(env); +} - if (sel != 0 && reg != 16 && reg != 28) { - rn = "invalid"; - goto print; - } - switch (reg) { - case 0: - T0 = env->CP0_index; - rn = "Index"; - break; - case 1: - T0 = cpu_mips_get_random(env); - rn = "Random"; - break; - case 2: - T0 = env->CP0_EntryLo0; - rn = "EntryLo0"; - break; - case 3: - T0 = env->CP0_EntryLo1; - rn = "EntryLo1"; - break; - case 4: - T0 = env->CP0_Context; - rn = "Context"; - break; - case 5: - T0 = env->CP0_PageMask; - rn = "PageMask"; - break; - case 6: - T0 = env->CP0_Wired; - rn = "Wired"; - break; - case 8: - T0 = env->CP0_BadVAddr; - rn = "BadVaddr"; - break; - case 9: - T0 = cpu_mips_get_count(env); - rn = "Count"; - break; - case 10: - T0 = env->CP0_EntryHi; - rn = "EntryHi"; - break; - case 11: - T0 = env->CP0_Compare; - rn = "Compare"; - break; - case 12: - T0 = env->CP0_Status; - if (env->hflags & MIPS_HFLAG_UM) - T0 |= (1 << CP0St_UM); - rn = "Status"; - break; - case 13: - T0 = env->CP0_Cause; - rn = "Cause"; - break; - case 14: - T0 = env->CP0_EPC; - rn = "EPC"; - break; - case 15: - T0 = env->CP0_PRid; - rn = "PRid"; - break; - case 16: - switch (sel) { - case 0: - T0 = env->CP0_Config0; - rn = "Config"; - break; - case 1: - T0 = env->CP0_Config1; - rn = "Config1"; - break; - default: - rn = "Unknown config register"; - break; - } - break; - case 17: - T0 = env->CP0_LLAddr >> 4; - rn = "LLAddr"; - break; - case 18: - T0 = env->CP0_WatchLo; - rn = "WatchLo"; - break; - case 19: - T0 = env->CP0_WatchHi; - rn = "WatchHi"; - break; - case 23: - T0 = env->CP0_Debug; - if (env->hflags & MIPS_HFLAG_DM) - T0 |= 1 << CP0DB_DM; - rn = "Debug"; - break; - case 24: - T0 = env->CP0_DEPC; - rn = "DEPC"; - break; - case 28: - switch (sel) { - case 0: - T0 = env->CP0_TagLo; - rn = "TagLo"; - break; - case 1: - T0 = env->CP0_DataLo; - rn = "DataLo"; - break; - default: - rn = "unknown sel"; - break; - } - break; - case 30: - T0 = env->CP0_ErrorEPC; - rn = "ErrorEPC"; - break; - case 31: - T0 = env->CP0_DESAVE; - rn = "DESAVE"; - break; - default: - rn = "unknown"; - break; - } - print: -#if defined MIPS_DEBUG_DISAS - if (loglevel & CPU_LOG_TB_IN_ASM) { - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", - env->PC, rn, T0, reg, sel); - } -#endif - return; +void do_mfc0_count (void) +{ + T0 = cpu_mips_get_count(env); } void do_mtc0 (int reg, int sel) diff --git a/target-mips/translate.c b/target-mips/translate.c index 07725b3445..e1c8bd4c70 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1349,6 +1349,155 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, } /* CP0 (MMU and control) */ +static void gen_mfc0 (DisasContext *ctx, int reg, int sel) +{ + const unsigned char *rn; + + if (sel != 0 && reg != 16 && reg != 28) { + rn = "invalid"; + goto die; + } + switch (reg) { + case 0: + gen_op_mfc0_index(); + rn = "Index"; + break; + case 1: + gen_op_mfc0_random(); + rn = "Random"; + break; + case 2: + gen_op_mfc0_entrylo0(); + rn = "EntryLo0"; + break; + case 3: + gen_op_mfc0_entrylo1(); + rn = "EntryLo1"; + break; + case 4: + gen_op_mfc0_context(); + rn = "Context"; + break; + case 5: + gen_op_mfc0_pagemask(); + rn = "PageMask"; + break; + case 6: + gen_op_mfc0_wired(); + rn = "Wired"; + break; + case 8: + gen_op_mfc0_badvaddr(); + rn = "BadVaddr"; + break; + case 9: + gen_op_mfc0_count(); + rn = "Count"; + break; + case 10: + gen_op_mfc0_entryhi(); + rn = "EntryHi"; + break; + case 11: + gen_op_mfc0_compare(); + rn = "Compare"; + break; + case 12: + gen_op_mfc0_status(); + rn = "Status"; + break; + case 13: + gen_op_mfc0_cause(); + rn = "Cause"; + break; + case 14: + gen_op_mfc0_epc(); + rn = "EPC"; + break; + case 15: + gen_op_mfc0_prid(); + rn = "PRid"; + break; + case 16: + switch (sel) { + case 0: + gen_op_mfc0_config0(); + rn = "Config"; + break; + case 1: + gen_op_mfc0_config1(); + rn = "Config1"; + break; + default: + rn = "Unknown config register"; + goto die; + } + break; + case 17: + gen_op_mfc0_lladdr(); + rn = "LLAddr"; + break; + case 18: + gen_op_mfc0_watchlo(); + rn = "WatchLo"; + break; + case 19: + gen_op_mfc0_watchhi(); + rn = "WatchHi"; + break; + case 23: + gen_op_mfc0_debug(); + rn = "Debug"; + break; + case 24: + gen_op_mfc0_depc(); + rn = "DEPC"; + break; + case 28: + switch (sel) { + case 0: + gen_op_mfc0_taglo(); + rn = "TagLo"; + break; + case 1: + gen_op_mfc0_datalo(); + rn = "DataLo"; + break; + default: + rn = "unknown sel"; + goto die; + } + break; + case 30: + gen_op_mfc0_errorepc(); + rn = "ErrorEPC"; + break; + case 31: + gen_op_mfc0_desave(); + rn = "DESAVE"; + break; + default: + rn = "unknown"; + goto die; + } +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", + env->PC, rn, T0, reg, sel); + } +#endif + return; + +die: +#if defined MIPS_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { + fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", + env->PC, rn, T0, reg, sel); + } +#endif + generate_exception(ctx, EXCP_RI); +} + static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) { const unsigned char *opn = "unk"; @@ -1370,7 +1519,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) /* Treat as NOP */ return; } - gen_op_mfc0(rd, ctx->opcode & 0x7); + gen_mfc0(ctx, rd, ctx->opcode & 0x7); gen_op_store_T0_gpr(rt); opn = "mfc0"; break;