Handle MIPS64 SEGBITS value correctly.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3011 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-06-23 18:04:12 +00:00
parent 5c40d2bd48
commit e034e2c39a
5 changed files with 32 additions and 16 deletions

View File

@ -102,6 +102,8 @@ struct CPUMIPSState {
uint32_t nb_tlb; uint32_t nb_tlb;
uint32_t tlb_in_use; uint32_t tlb_in_use;
uint32_t SEGBITS;
target_ulong SEGMask;
int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type); int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
void (*do_tlbwi) (void); void (*do_tlbwi) (void);
void (*do_tlbwr) (void); void (*do_tlbwr) (void);

View File

@ -77,7 +77,7 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
target_ulong tag = address & ~mask; target_ulong tag = address & ~mask;
target_ulong VPN = tlb->VPN & ~mask; target_ulong VPN = tlb->VPN & ~mask;
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
tag &= 0xC00000FFFFFFFFFFULL; tag &= env->SEGMask;
#endif #endif
/* Check ASID, virtual page number & size */ /* Check ASID, virtual page number & size */
@ -140,18 +140,17 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
/* /*
XXX: Assuming : XXX: Assuming :
- PABITS = 36 (correct for MIPS64R1) - PABITS = 36 (correct for MIPS64R1)
- SEGBITS = 40
*/ */
} else if (address < 0x3FFFFFFFFFFFFFFFULL) { } else if (address < 0x3FFFFFFFFFFFFFFFULL) {
/* xuseg */ /* xuseg */
if (UX && address < 0x000000FFFFFFFFFFULL) { if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
ret = env->map_address(env, physical, prot, address, rw, access_type); ret = env->map_address(env, physical, prot, address, rw, access_type);
} else { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
} }
} else if (address < 0x7FFFFFFFFFFFFFFFULL) { } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
/* xsseg */ /* xsseg */
if (SX && address < 0x400000FFFFFFFFFFULL) { if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
ret = env->map_address(env, physical, prot, address, rw, access_type); ret = env->map_address(env, physical, prot, address, rw, access_type);
} else { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
@ -159,9 +158,9 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
} else if (address < 0xBFFFFFFFFFFFFFFFULL) { } else if (address < 0xBFFFFFFFFFFFFFFFULL) {
/* xkphys */ /* xkphys */
/* XXX: check supervisor mode */ /* XXX: check supervisor mode */
if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
{ {
*physical = address & 0X000000FFFFFFFFFFULL; *physical = address & 0X0000000FFFFFFFFFULL;
*prot = PAGE_READ | PAGE_WRITE; *prot = PAGE_READ | PAGE_WRITE;
} else { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
@ -169,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
} else if (address < 0xFFFFFFFF7FFFFFFFULL) { } else if (address < 0xFFFFFFFF7FFFFFFFULL) {
/* xkseg */ /* xkseg */
/* XXX: check supervisor mode */ /* XXX: check supervisor mode */
if (KX && address < 0xC00000FF7FFFFFFFULL) { if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
ret = env->map_address(env, physical, prot, address, rw, access_type); ret = env->map_address(env, physical, prot, address, rw, access_type);
} else { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
@ -303,10 +302,10 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->CP0_EntryHi = env->CP0_EntryHi =
(env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
env->CP0_EntryHi &= 0xc00000ffffffffffULL; env->CP0_EntryHi &= env->SEGMask;
env->CP0_XContext = (env->CP0_XContext & 0xfffffffe00000000ULL) | env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
((address >> 31) & 0x0000000180000000ULL) | ((address & 0xC00000000000ULL) >> (env->SEGBITS - 9)) |
((address >> 9) & 0x000000007ffffff0ULL); ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);
#endif #endif
env->exception_index = exception; env->exception_index = exception;
env->error_code = error_code; env->error_code = error_code;
@ -555,7 +554,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
if (tlb->V0) { if (tlb->V0) {
addr = tlb->VPN & ~mask; addr = tlb->VPN & ~mask;
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
if (addr >= 0xC00000FF80000000ULL) { if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
addr |= 0x3FFFFF0000000000ULL; addr |= 0x3FFFFF0000000000ULL;
} }
#endif #endif
@ -568,7 +567,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
if (tlb->V1) { if (tlb->V1) {
addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
if (addr >= 0xC00000FF80000000ULL) { if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
addr |= 0x3FFFFF0000000000ULL; addr |= 0x3FFFFF0000000000ULL;
} }
#endif #endif

View File

@ -1328,7 +1328,7 @@ void op_mtc0_entryhi (void)
/* 1k pages not implemented */ /* 1k pages not implemented */
val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF); val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
val = T0 & 0xC00000FFFFFFFFFFULL; val &= env->SEGMask;
#endif #endif
old = env->CP0_EntryHi; old = env->CP0_EntryHi;
env->CP0_EntryHi = val; env->CP0_EntryHi = val;
@ -1526,7 +1526,8 @@ void op_mtc0_desave (void)
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
void op_mtc0_xcontext (void) void op_mtc0_xcontext (void)
{ {
env->CP0_XContext = (env->CP0_XContext & 0x1ffffffffULL) | (T0 & ~0x1ffffffffULL); target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
RETURN(); RETURN();
} }

View File

@ -374,7 +374,7 @@ static void r4k_fill_tlb (int idx)
tlb = &env->mmu.r4k.tlb[idx]; tlb = &env->mmu.r4k.tlb[idx];
tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
tlb->VPN &= 0xC00000FFFFFFFFFFULL; tlb->VPN &= env->SEGMask;
#endif #endif
tlb->ASID = env->CP0_EntryHi & 0xFF; tlb->ASID = env->CP0_EntryHi & 0xFF;
tlb->PageMask = env->CP0_PageMask; tlb->PageMask = env->CP0_PageMask;

View File

@ -71,6 +71,7 @@ struct mips_def_t {
int32_t CCRes; int32_t CCRes;
int32_t Status_rw_bitmask; int32_t Status_rw_bitmask;
int32_t CP1_fcr0; int32_t CP1_fcr0;
int32_t SEGBITS;
}; };
/*****************************************************************************/ /*****************************************************************************/
@ -87,6 +88,7 @@ static mips_def_t mips_defs[] =
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .Status_rw_bitmask = 0x3278FF17,
.SEGBITS = 32,
}, },
{ {
.name = "4KEcR1", .name = "4KEcR1",
@ -98,6 +100,7 @@ static mips_def_t mips_defs[] =
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .Status_rw_bitmask = 0x3278FF17,
.SEGBITS = 32,
}, },
{ {
.name = "4KEc", .name = "4KEc",
@ -109,6 +112,7 @@ static mips_def_t mips_defs[] =
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .Status_rw_bitmask = 0x3278FF17,
.SEGBITS = 32,
}, },
{ {
.name = "24Kc", .name = "24Kc",
@ -120,6 +124,7 @@ static mips_def_t mips_defs[] =
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .Status_rw_bitmask = 0x3278FF17,
.SEGBITS = 32,
}, },
{ {
.name = "24Kf", .name = "24Kf",
@ -133,6 +138,7 @@ static mips_def_t mips_defs[] =
.Status_rw_bitmask = 0x3678FF17, .Status_rw_bitmask = 0x3678FF17,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
.SEGBITS = 32,
}, },
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
{ {
@ -147,6 +153,7 @@ static mips_def_t mips_defs[] =
.Status_rw_bitmask = 0x3678FFFF, .Status_rw_bitmask = 0x3678FFFF,
/* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40,
}, },
{ {
.name = "5Kc", .name = "5Kc",
@ -161,6 +168,7 @@ static mips_def_t mips_defs[] =
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x32F8FFFF, .Status_rw_bitmask = 0x32F8FFFF,
.SEGBITS = 42,
}, },
{ {
.name = "5Kf", .name = "5Kf",
@ -178,6 +186,7 @@ static mips_def_t mips_defs[] =
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV), (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 42,
}, },
{ {
.name = "20Kc", .name = "20Kc",
@ -198,6 +207,7 @@ static mips_def_t mips_defs[] =
.CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_D) | (1 << FCR0_S) | (1 << FCR0_D) | (1 << FCR0_S) |
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV), (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40,
}, },
#endif #endif
}; };
@ -274,6 +284,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->CCRes = def->CCRes; env->CCRes = def->CCRes;
env->Status_rw_bitmask = def->Status_rw_bitmask; env->Status_rw_bitmask = def->Status_rw_bitmask;
env->fcr0 = def->CP1_fcr0; env->fcr0 = def->CP1_fcr0;
#ifdef TARGET_MIPS64
env->SEGBITS = def->SEGBITS;
env->SEGMask = (3ULL << 62) | ((1ULL << def->SEGBITS) - 1);
#endif
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
if (env->CP0_Config1 & (1 << CP0C1_FP)) if (env->CP0_Config1 & (1 << CP0C1_FP))
env->hflags |= MIPS_HFLAG_FPU; env->hflags |= MIPS_HFLAG_FPU;