提交 7a387fff 编写于 作者: T ths

Add MIPS32R2 instructions, and generally straighten out the instruction

decoding. This is also the first percent towards MIPS64 support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2224 c046a42c-6fe2-441c-8c8c-71466251a162
上级 8c0fdd85
...@@ -99,14 +99,16 @@ struct CPUMIPSState { ...@@ -99,14 +99,16 @@ struct CPUMIPSState {
#endif #endif
uint32_t CP0_index; uint32_t CP0_index;
uint32_t CP0_random; uint32_t CP0_random;
uint32_t CP0_EntryLo0; uint64_t CP0_EntryLo0;
uint32_t CP0_EntryLo1; uint64_t CP0_EntryLo1;
uint32_t CP0_Context; uint64_t CP0_Context;
uint32_t CP0_PageMask; uint32_t CP0_PageMask;
uint32_t CP0_PageGrain;
uint32_t CP0_Wired; uint32_t CP0_Wired;
uint32_t CP0_HWREna;
uint32_t CP0_BadVAddr; uint32_t CP0_BadVAddr;
uint32_t CP0_Count; uint32_t CP0_Count;
uint32_t CP0_EntryHi; uint64_t CP0_EntryHi;
uint32_t CP0_Compare; uint32_t CP0_Compare;
uint32_t CP0_Status; uint32_t CP0_Status;
#define CP0St_CU3 31 #define CP0St_CU3 31
...@@ -116,19 +118,36 @@ struct CPUMIPSState { ...@@ -116,19 +118,36 @@ struct CPUMIPSState {
#define CP0St_RP 27 #define CP0St_RP 27
#define CP0St_FR 26 #define CP0St_FR 26
#define CP0St_RE 25 #define CP0St_RE 25
#define CP0St_MX 24
#define CP0St_PX 23
#define CP0St_BEV 22 #define CP0St_BEV 22
#define CP0St_TS 21 #define CP0St_TS 21
#define CP0St_SR 20 #define CP0St_SR 20
#define CP0St_NMI 19 #define CP0St_NMI 19
#define CP0St_IM 8 #define CP0St_IM 8
#define CP0St_KX 7
#define CP0St_SX 6
#define CP0St_UX 5
#define CP0St_UM 4 #define CP0St_UM 4
#define CP0St_R0 3
#define CP0St_ERL 2 #define CP0St_ERL 2
#define CP0St_EXL 1 #define CP0St_EXL 1
#define CP0St_IE 0 #define CP0St_IE 0
uint32_t CP0_IntCtl;
uint32_t CP0_SRSCtl;
uint32_t CP0_Cause; uint32_t CP0_Cause;
#define CP0Ca_BD 31
#define CP0Ca_TI 30
#define CP0Ca_CE 28
#define CP0Ca_DC 27
#define CP0Ca_PCI 26
#define CP0Ca_IV 23 #define CP0Ca_IV 23
#define CP0Ca_WP 22
#define CP0Ca_IP 8
#define CP0Ca_EC 2
uint32_t CP0_EPC; uint32_t CP0_EPC;
uint32_t CP0_PRid; uint32_t CP0_PRid;
uint32_t CP0_EBase;
uint32_t CP0_Config0; uint32_t CP0_Config0;
#define CP0C0_M 31 #define CP0C0_M 31
#define CP0C0_K23 28 #define CP0C0_K23 28
...@@ -140,8 +159,10 @@ struct CPUMIPSState { ...@@ -140,8 +159,10 @@ struct CPUMIPSState {
#define CP0C0_AT 13 #define CP0C0_AT 13
#define CP0C0_AR 10 #define CP0C0_AR 10
#define CP0C0_MT 7 #define CP0C0_MT 7
#define CP0C0_VI 3
#define CP0C0_K0 0 #define CP0C0_K0 0
uint32_t CP0_Config1; uint32_t CP0_Config1;
#define CP0C1_M 31
#define CP0C1_MMU 25 #define CP0C1_MMU 25
#define CP0C1_IS 22 #define CP0C1_IS 22
#define CP0C1_IL 19 #define CP0C1_IL 19
...@@ -149,14 +170,38 @@ struct CPUMIPSState { ...@@ -149,14 +170,38 @@ struct CPUMIPSState {
#define CP0C1_DS 13 #define CP0C1_DS 13
#define CP0C1_DL 10 #define CP0C1_DL 10
#define CP0C1_DA 7 #define CP0C1_DA 7
#define CP0C1_C2 6
#define CP0C1_MD 5
#define CP0C1_PC 4 #define CP0C1_PC 4
#define CP0C1_WR 3 #define CP0C1_WR 3
#define CP0C1_CA 2 #define CP0C1_CA 2
#define CP0C1_EP 1 #define CP0C1_EP 1
#define CP0C1_FP 0 #define CP0C1_FP 0
uint32_t CP0_Config2;
#define CP0C2_M 31
#define CP0C2_TU 28
#define CP0C2_TS 24
#define CP0C2_TL 20
#define CP0C2_TA 16
#define CP0C2_SU 12
#define CP0C2_SS 8
#define CP0C2_SL 4
#define CP0C2_SA 0
uint32_t CP0_Config3;
#define CP0C3_M 31
#define CP0C3_DSPP 10
#define CP0C3_LPA 7
#define CP0C3_VEIC 6
#define CP0C3_VInt 5
#define CP0C3_SP 4
#define CP0C3_MT 2
#define CP0C3_SM 1
#define CP0C3_TL 0
uint32_t CP0_LLAddr; uint32_t CP0_LLAddr;
uint32_t CP0_WatchLo; uint32_t CP0_WatchLo;
uint32_t CP0_WatchHi; uint32_t CP0_WatchHi;
uint32_t CP0_XContext;
uint32_t CP0_Framemask;
uint32_t CP0_Debug; uint32_t CP0_Debug;
#define CPDB_DBD 31 #define CPDB_DBD 31
#define CP0DB_DM 30 #define CP0DB_DM 30
...@@ -177,8 +222,11 @@ struct CPUMIPSState { ...@@ -177,8 +222,11 @@ struct CPUMIPSState {
#define CP0DB_DBp 1 #define CP0DB_DBp 1
#define CP0DB_DSS 0 #define CP0DB_DSS 0
uint32_t CP0_DEPC; uint32_t CP0_DEPC;
uint32_t CP0_Performance0;
uint32_t CP0_TagLo; uint32_t CP0_TagLo;
uint32_t CP0_DataLo; uint32_t CP0_DataLo;
uint32_t CP0_TagHi;
uint32_t CP0_DataHi;
uint32_t CP0_ErrorEPC; uint32_t CP0_ErrorEPC;
uint32_t CP0_DESAVE; uint32_t CP0_DESAVE;
/* Qemu */ /* Qemu */
...@@ -211,6 +259,9 @@ struct CPUMIPSState { ...@@ -211,6 +259,9 @@ struct CPUMIPSState {
int halted; /* TRUE if the CPU is in suspend state */ int halted; /* TRUE if the CPU is in suspend state */
int SYNCI_Step; /* Address step size for SYNCI */
int CCRes; /* Cycle count resolution/divisor */
CPU_COMMON CPU_COMMON
int ram_size; int ram_size;
......
...@@ -68,6 +68,7 @@ void do_msubu (void); ...@@ -68,6 +68,7 @@ void do_msubu (void);
#endif #endif
void do_mfc0_random(void); void do_mfc0_random(void);
void do_mfc0_count(void); void do_mfc0_count(void);
void do_mtc0_entryhi(uint32_t in);
void do_mtc0_status_debug(uint32_t old, uint32_t val); void do_mtc0_status_debug(uint32_t old, uint32_t val);
void do_mtc0_status_irqraise_debug(void); void do_mtc0_status_irqraise_debug(void);
void do_tlbwi (void); void do_tlbwi (void);
......
...@@ -302,15 +302,9 @@ void do_interrupt (CPUState *env) ...@@ -302,15 +302,9 @@ void do_interrupt (CPUState *env)
#endif #endif
env->CP0_Wired = 0; env->CP0_Wired = 0;
env->CP0_Config0 = MIPS_CONFIG0; env->CP0_Config0 = MIPS_CONFIG0;
#if defined (MIPS_CONFIG1)
env->CP0_Config1 = MIPS_CONFIG1; env->CP0_Config1 = MIPS_CONFIG1;
#endif
#if defined (MIPS_CONFIG2)
env->CP0_Config2 = MIPS_CONFIG2; env->CP0_Config2 = MIPS_CONFIG2;
#endif
#if defined (MIPS_CONFIG3)
env->CP0_Config3 = MIPS_CONFIG3; env->CP0_Config3 = MIPS_CONFIG3;
#endif
env->CP0_WatchLo = 0; env->CP0_WatchLo = 0;
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
goto set_error_EPC; goto set_error_EPC;
......
...@@ -29,26 +29,44 @@ ...@@ -29,26 +29,44 @@
* Define a major version 1, minor version 0. * Define a major version 1, minor version 0.
*/ */
#define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0) #define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0)
/* Have config1, uses TLB */ /* Have config1, is MIPS32R1, uses TLB, no virtual icache,
#define MIPS_CONFIG0_1 \ uncached coherency */
((1 << CP0C0_M) | (0 << CP0C0_K23) | (0 << CP0C0_KU) | \ #define MIPS_CONFIG0_1 \
(1 << CP0C0_MT) | (2 << CP0C0_K0)) ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) | \
(0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \
(0x2 << CP0C0_K0))
#ifdef TARGET_WORDS_BIGENDIAN #ifdef TARGET_WORDS_BIGENDIAN
#define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE)) #define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE))
#else #else
#define MIPS_CONFIG0 MIPS_CONFIG0_1 #define MIPS_CONFIG0 MIPS_CONFIG0_1
#endif #endif
/* 16 TLBs, 64 sets Icache, 16 bytes Icache line, 2-way Icache, /* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line,
* 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache,
* no performance counters, watch registers present, no code compression, no coprocessor2 attached, no MDMX support attached,
* EJTAG present, FPU enable bit depending on MIPS_USES_FPU no performance counters, watch registers present,
*/ no code compression, EJTAG present, FPU enable bit depending on
#define MIPS_CONFIG1 \ MIPS_USES_FPU */
((15 << CP0C1_MMU) | \ #define MIPS_CONFIG1_1 \
(0x000 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x01 << CP0C1_IA) | \ ((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \
(0x000 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x01 << CP0C1_DA) | \ (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (0 << CP0C1_CA) | \ (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \
(1 << CP0C1_EP) | (MIPS_USES_FPU << CP0C1_FP)) (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
(1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP))
#ifdef MIPS_USES_FPU
#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (1 << CP0C1_FP))
#else
#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (0 << CP0C1_FP))
#endif
/* Have config3, no tertiary/secondary caches implemented */
#define MIPS_CONFIG2 \
((1 << CP0C2_M))
/* No config4, no DSP ASE, no large physaddr,
no external interrupt controller, no vectored interupts,
no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */
#define MIPS_CONFIG3 \
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
(0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL))
#elif (MIPS_CPU == MIPS_R4Kp) #elif (MIPS_CPU == MIPS_R4Kp)
/* 32 bits target */ /* 32 bits target */
#define TARGET_LONG_BITS 32 #define TARGET_LONG_BITS 32
...@@ -60,7 +78,7 @@ ...@@ -60,7 +78,7 @@
#define MIPS_USES_R4K_FPM #define MIPS_USES_R4K_FPM
#else #else
#error "MIPS CPU not defined" #error "MIPS CPU not defined"
/* Remainder for other flags */ /* Reminder for other flags */
//#define TARGET_MIPS64 //#define TARGET_MIPS64
//#define MIPS_USES_FPU //#define MIPS_USES_FPU
#endif #endif
......
...@@ -437,6 +437,18 @@ void op_srl (void) ...@@ -437,6 +437,18 @@ void op_srl (void)
RETURN(); RETURN();
} }
void op_rotr (void)
{
target_ulong tmp;
if (T1) {
tmp = T0 << (0x20 - T1);
T0 = (T0 >> T1) | tmp;
} else
T0 = T1;
RETURN();
}
void op_sllv (void) void op_sllv (void)
{ {
T0 = T1 << (T0 & 0x1F); T0 = T1 << (T0 & 0x1F);
...@@ -455,6 +467,19 @@ void op_srlv (void) ...@@ -455,6 +467,19 @@ void op_srlv (void)
RETURN(); RETURN();
} }
void op_rotrv (void)
{
target_ulong tmp;
T0 &= 0x1F;
if (T0) {
tmp = T1 << (0x20 - T0);
T0 = (T1 >> T0) | tmp;
} else
T0 = T1;
RETURN();
}
void op_clo (void) void op_clo (void)
{ {
int n; int n;
...@@ -602,6 +627,20 @@ void op_movz (void) ...@@ -602,6 +627,20 @@ void op_movz (void)
RETURN(); RETURN();
} }
void op_movf (void)
{
if (!(env->fcr31 & PARAM1))
env->gpr[PARAM2] = env->gpr[PARAM3];
RETURN();
}
void op_movt (void)
{
if (env->fcr31 & PARAM1)
env->gpr[PARAM2] = env->gpr[PARAM3];
RETURN();
}
/* Tests */ /* Tests */
#define OP_COND(name, cond) \ #define OP_COND(name, cond) \
void glue(op_, name) (void) \ void glue(op_, name) (void) \
...@@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0); ...@@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0);
OP_COND(lez, (int32_t)T0 <= 0); OP_COND(lez, (int32_t)T0 <= 0);
OP_COND(ltz, (int32_t)T0 < 0); OP_COND(ltz, (int32_t)T0 < 0);
/* Branchs */ /* Branches */
//#undef USE_DIRECT_JUMP //#undef USE_DIRECT_JUMP
void OPPROTO op_goto_tb0(void) void OPPROTO op_goto_tb0(void)
{ {
GOTO_TB(op_goto_tb0, PARAM1, 0); GOTO_TB(op_goto_tb0, PARAM1, 0);
RETURN();
} }
void OPPROTO op_goto_tb1(void) void OPPROTO op_goto_tb1(void)
{ {
GOTO_TB(op_goto_tb1, PARAM1, 1); GOTO_TB(op_goto_tb1, PARAM1, 1);
RETURN();
} }
/* Branch to register */ /* Branch to register */
void op_save_breg_target (void) void op_save_breg_target (void)
{ {
env->btarget = T2; env->btarget = T2;
RETURN();
} }
void op_restore_breg_target (void) void op_restore_breg_target (void)
{ {
T2 = env->btarget; T2 = env->btarget;
RETURN();
} }
void op_breg (void) void op_breg (void)
...@@ -724,12 +767,24 @@ void op_mfc0_pagemask (void) ...@@ -724,12 +767,24 @@ void op_mfc0_pagemask (void)
RETURN(); RETURN();
} }
void op_mfc0_pagegrain (void)
{
T0 = env->CP0_PageGrain;
RETURN();
}
void op_mfc0_wired (void) void op_mfc0_wired (void)
{ {
T0 = env->CP0_Wired; T0 = env->CP0_Wired;
RETURN(); RETURN();
} }
void op_mfc0_hwrena (void)
{
T0 = env->CP0_HWREna;
RETURN();
}
void op_mfc0_badvaddr (void) void op_mfc0_badvaddr (void)
{ {
T0 = env->CP0_BadVAddr; T0 = env->CP0_BadVAddr;
...@@ -766,6 +821,18 @@ void op_mfc0_status (void) ...@@ -766,6 +821,18 @@ void op_mfc0_status (void)
RETURN(); RETURN();
} }
void op_mfc0_intctl (void)
{
T0 = env->CP0_IntCtl;
RETURN();
}
void op_mfc0_srsctl (void)
{
T0 = env->CP0_SRSCtl;
RETURN();
}
void op_mfc0_cause (void) void op_mfc0_cause (void)
{ {
T0 = env->CP0_Cause; T0 = env->CP0_Cause;
...@@ -784,6 +851,12 @@ void op_mfc0_prid (void) ...@@ -784,6 +851,12 @@ void op_mfc0_prid (void)
RETURN(); RETURN();
} }
void op_mfc0_ebase (void)
{
T0 = env->CP0_EBase;
RETURN();
}
void op_mfc0_config0 (void) void op_mfc0_config0 (void)
{ {
T0 = env->CP0_Config0; T0 = env->CP0_Config0;
...@@ -796,24 +869,48 @@ void op_mfc0_config1 (void) ...@@ -796,24 +869,48 @@ void op_mfc0_config1 (void)
RETURN(); RETURN();
} }
void op_mfc0_config2 (void)
{
T0 = env->CP0_Config2;
RETURN();
}
void op_mfc0_config3 (void)
{
T0 = env->CP0_Config3;
RETURN();
}
void op_mfc0_lladdr (void) void op_mfc0_lladdr (void)
{ {
T0 = env->CP0_LLAddr >> 4; T0 = env->CP0_LLAddr >> 4;
RETURN(); RETURN();
} }
void op_mfc0_watchlo (void) void op_mfc0_watchlo0 (void)
{ {
T0 = env->CP0_WatchLo; T0 = env->CP0_WatchLo;
RETURN(); RETURN();
} }
void op_mfc0_watchhi (void) void op_mfc0_watchhi0 (void)
{ {
T0 = env->CP0_WatchHi; T0 = env->CP0_WatchHi;
RETURN(); RETURN();
} }
void op_mfc0_xcontext (void)
{
T0 = env->CP0_XContext;
RETURN();
}
void op_mfc0_framemask (void)
{
T0 = env->CP0_Framemask;
RETURN();
}
void op_mfc0_debug (void) void op_mfc0_debug (void)
{ {
T0 = env->CP0_Debug; T0 = env->CP0_Debug;
...@@ -828,6 +925,12 @@ void op_mfc0_depc (void) ...@@ -828,6 +925,12 @@ void op_mfc0_depc (void)
RETURN(); RETURN();
} }
void op_mfc0_performance0 (void)
{
T0 = env->CP0_Performance0;
RETURN();
}
void op_mfc0_taglo (void) void op_mfc0_taglo (void)
{ {
T0 = env->CP0_TagLo; T0 = env->CP0_TagLo;
...@@ -840,6 +943,18 @@ void op_mfc0_datalo (void) ...@@ -840,6 +943,18 @@ void op_mfc0_datalo (void)
RETURN(); RETURN();
} }
void op_mfc0_taghi (void)
{
T0 = env->CP0_TagHi;
RETURN();
}
void op_mfc0_datahi (void)
{
T0 = env->CP0_DataHi;
RETURN();
}
void op_mfc0_errorepc (void) void op_mfc0_errorepc (void)
{ {
T0 = env->CP0_ErrorEPC; T0 = env->CP0_ErrorEPC;
...@@ -854,37 +969,57 @@ void op_mfc0_desave (void) ...@@ -854,37 +969,57 @@ void op_mfc0_desave (void)
void op_mtc0_index (void) void op_mtc0_index (void)
{ {
env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
RETURN(); RETURN();
} }
void op_mtc0_entrylo0 (void) void op_mtc0_entrylo0 (void)
{ {
env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; /* Large physaddr not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL;
RETURN(); RETURN();
} }
void op_mtc0_entrylo1 (void) void op_mtc0_entrylo1 (void)
{ {
env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; /* Large physaddr not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL;
RETURN(); RETURN();
} }
void op_mtc0_context (void) void op_mtc0_context (void)
{ {
env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
RETURN(); RETURN();
} }
void op_mtc0_pagemask (void) void op_mtc0_pagemask (void)
{ {
env->CP0_PageMask = T0 & 0x01FFE000; /* 1k pages not implemented */
env->CP0_PageMask = T0 & 0x1FFFE000;
RETURN();
}
void op_mtc0_pagegrain (void)
{
/* SmartMIPS not implemented */
/* Large physaddr not implemented */
/* 1k pages not implemented */
env->CP0_PageGrain = 0;
RETURN(); RETURN();
} }
void op_mtc0_wired (void) void op_mtc0_wired (void)
{ {
env->CP0_Wired = T0 & 0x0000000F; env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
RETURN();
}
void op_mtc0_hwrena (void)
{
env->CP0_HWREna = T0 & 0x0000000F;
RETURN(); RETURN();
} }
...@@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void) ...@@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void)
{ {
uint32_t old, val; uint32_t old, val;
/* 1k pages not implemented */
/* Ignore MIPS64 TLB for now */
val = T0 & 0xFFFFE0FF; val = T0 & 0xFFFFE0FF;
old = env->CP0_EntryHi; old = env->CP0_EntryHi;
env->CP0_EntryHi = val; env->CP0_EntryHi = val;
...@@ -950,6 +1087,20 @@ void op_mtc0_status (void) ...@@ -950,6 +1087,20 @@ void op_mtc0_status (void)
RETURN(); RETURN();
} }
void op_mtc0_intctl (void)
{
/* vectored interrupts not implemented */
env->CP0_IntCtl = 0;
RETURN();
}
void op_mtc0_srsctl (void)
{
/* shadow registers not implemented */
env->CP0_SRSCtl = 0;
RETURN();
}
void op_mtc0_cause (void) void op_mtc0_cause (void)
{ {
uint32_t val, old; uint32_t val, old;
...@@ -960,7 +1111,6 @@ void op_mtc0_cause (void) ...@@ -960,7 +1111,6 @@ void op_mtc0_cause (void)
#if 0 #if 0
{ {
int i, mask; int i, mask;
/* Check if we ever asserted a software IRQ */ /* Check if we ever asserted a software IRQ */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
mask = 0x100 << i; mask = 0x100 << i;
...@@ -978,28 +1128,56 @@ void op_mtc0_epc (void) ...@@ -978,28 +1128,56 @@ void op_mtc0_epc (void)
RETURN(); RETURN();
} }
void op_mtc0_ebase (void)
{
/* vectored interrupts not implemented */
/* Multi-CPU not implemented */
env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
RETURN();
}
void op_mtc0_config0 (void) void op_mtc0_config0 (void)
{ {
#if defined(MIPS_USES_R4K_TLB) #if defined(MIPS_USES_R4K_TLB)
env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); /* Fixed mapping MMU not implemented */
env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
#else #else
env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
#endif #endif
RETURN(); RETURN();
} }
void op_mtc0_watchlo (void) void op_mtc0_config2 (void)
{
/* tertiary/secondary caches not implemented */
env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
RETURN();
}
void op_mtc0_watchlo0 (void)
{ {
env->CP0_WatchLo = T0; env->CP0_WatchLo = T0;
RETURN(); RETURN();
} }
void op_mtc0_watchhi (void) void op_mtc0_watchhi0 (void)
{ {
env->CP0_WatchHi = T0 & 0x40FF0FF8; env->CP0_WatchHi = T0 & 0x40FF0FF8;
RETURN(); RETURN();
} }
void op_mtc0_xcontext (void)
{
env->CP0_XContext = T0; /* XXX */
RETURN();
}
void op_mtc0_framemask (void)
{
env->CP0_Framemask = T0; /* XXX */
RETURN();
}
void op_mtc0_debug (void) void op_mtc0_debug (void)
{ {
env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
...@@ -1016,12 +1194,36 @@ void op_mtc0_depc (void) ...@@ -1016,12 +1194,36 @@ void op_mtc0_depc (void)
RETURN(); RETURN();
} }
void op_mtc0_performance0 (void)
{
env->CP0_Performance0 = T0; /* XXX */
RETURN();
}
void op_mtc0_taglo (void) void op_mtc0_taglo (void)
{ {
env->CP0_TagLo = T0 & 0xFFFFFCF6; env->CP0_TagLo = T0 & 0xFFFFFCF6;
RETURN(); RETURN();
} }
void op_mtc0_datalo (void)
{
env->CP0_DataLo = T0; /* XXX */
RETURN();
}
void op_mtc0_taghi (void)
{
env->CP0_TagHi = T0; /* XXX */
RETURN();
}
void op_mtc0_datahi (void)
{
env->CP0_DataHi = T0; /* XXX */
RETURN();
}
void op_mtc0_errorepc (void) void op_mtc0_errorepc (void)
{ {
env->CP0_ErrorEPC = T0; env->CP0_ErrorEPC = T0;
...@@ -1422,6 +1624,42 @@ void op_tlbr (void) ...@@ -1422,6 +1624,42 @@ void op_tlbr (void)
void op_pmon (void) void op_pmon (void)
{ {
CALL_FROM_TB1(do_pmon, PARAM1); CALL_FROM_TB1(do_pmon, PARAM1);
RETURN();
}
void op_di (void)
{
uint32_t val;
T0 = env->CP0_Status;
val = T0 & ~(1 << CP0St_IE);
if (val != T0) {
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
env->CP0_Status = val;
}
RETURN();
}
void op_ei (void)
{
uint32_t val;
T0 = env->CP0_Status;
val = T0 | (1 << CP0St_IE);
if (val != T0) {
const uint32_t mask = 0x0000FF00;
env->CP0_Status = val;
if (!(env->hflags & MIPS_HFLAG_EXL) &&
!(env->hflags & MIPS_HFLAG_ERL) &&
!(env->hflags & MIPS_HFLAG_DM) &&
(env->CP0_Status & env->CP0_Cause & mask)) {
env->interrupt_request |= CPU_INTERRUPT_HARD;
if (logfile)
CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
}
}
RETURN();
} }
void op_trap (void) void op_trap (void)
...@@ -1434,12 +1672,14 @@ void op_trap (void) ...@@ -1434,12 +1672,14 @@ void op_trap (void)
void op_debug (void) void op_debug (void)
{ {
CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
RETURN();
} }
void op_set_lladdr (void) void op_set_lladdr (void)
{ {
env->CP0_LLAddr = T2; env->CP0_LLAddr = T2;
RETURN();
} }
void debug_eret (void); void debug_eret (void);
...@@ -1456,12 +1696,50 @@ void op_eret (void) ...@@ -1456,12 +1696,50 @@ void op_eret (void)
env->CP0_Status &= ~(1 << CP0St_EXL); env->CP0_Status &= ~(1 << CP0St_EXL);
} }
env->CP0_LLAddr = 1; env->CP0_LLAddr = 1;
RETURN();
} }
void op_deret (void) void op_deret (void)
{ {
CALL_FROM_TB0(debug_eret); CALL_FROM_TB0(debug_eret);
env->PC = env->CP0_DEPC; env->PC = env->CP0_DEPC;
RETURN();
}
void op_rdhwr_cpunum(void)
{
if (env->CP0_HWREna & (1 << 0))
T0 = env->CP0_EBase & 0x2ff;
else
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
RETURN();
}
void op_rdhwr_synci_step(void)
{
if (env->CP0_HWREna & (1 << 1))
T0 = env->SYNCI_Step;
else
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
RETURN();
}
void op_rdhwr_cc(void)
{
if (env->CP0_HWREna & (1 << 2))
T0 = env->CP0_Count;
else
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
RETURN();
}
void op_rdhwr_ccres(void)
{
if (env->CP0_HWREna & (1 << 3))
T0 = env->CCRes;
else
CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
RETURN();
} }
void op_save_state (void) void op_save_state (void)
...@@ -1491,10 +1769,62 @@ void op_raise_exception_err (void) ...@@ -1491,10 +1769,62 @@ void op_raise_exception_err (void)
void op_exit_tb (void) void op_exit_tb (void)
{ {
EXIT_TB(); EXIT_TB();
RETURN();
} }
void op_wait (void) void op_wait (void)
{ {
env->halted = 1; env->halted = 1;
CALL_FROM_TB1(do_raise_exception, EXCP_HLT); CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
RETURN();
}
/* Bitfield operations. */
void op_ext(void)
{
unsigned int pos = PARAM1;
unsigned int size = PARAM2;
T0 = (T1 >> pos) & ((1 << size) - 1);
RETURN();
}
void op_ins(void)
{
unsigned int pos = PARAM1;
unsigned int size = PARAM2;
target_ulong mask = ((1 << size) - 1) << pos;
T0 = (T2 & ~mask) | ((T1 << pos) & mask);
RETURN();
}
void op_wsbh(void)
{
T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
RETURN();
}
void op_dsbh(void)
{
T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
RETURN();
}
void op_dshd(void)
{
T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
RETURN();
}
void op_seb(void)
{
T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
RETURN();
}
void op_seh(void)
{
T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
RETURN();
} }
...@@ -153,12 +153,12 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value) ...@@ -153,12 +153,12 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value)
void do_mtc0_status_debug(uint32_t old, uint32_t val) void do_mtc0_status_debug(uint32_t old, uint32_t val)
{ {
cpu_abort(env, "mtc0 status\n"); cpu_abort(env, "mtc0 status debug\n");
} }
void do_mtc0_status_irqraise_debug(void) void do_mtc0_status_irqraise_debug (void)
{ {
cpu_abort(env, "mtc0 status\n"); cpu_abort(env, "mtc0 status irqraise debug\n");
} }
void do_tlbwi (void) void do_tlbwi (void)
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册