Dynamically translate MIPS mfc0 instructions.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2222 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2006-12-06 17:59:07 +00:00
parent 6ae817752b
commit 873eb01234
4 changed files with 327 additions and 147 deletions

View File

@ -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);

View File

@ -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();
}

View File

@ -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)

View File

@ -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;