Commit e034e2c39aee1800101812045690e0575abb428b
1 parent
5c40d2bd
Handle MIPS64 SEGBITS value correctly.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3011 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
32 additions
and
16 deletions
target-mips/cpu.h
| @@ -102,6 +102,8 @@ struct CPUMIPSState { | @@ -102,6 +102,8 @@ struct CPUMIPSState { | ||
| 102 | 102 | ||
| 103 | uint32_t nb_tlb; | 103 | uint32_t nb_tlb; |
| 104 | uint32_t tlb_in_use; | 104 | uint32_t tlb_in_use; |
| 105 | + uint32_t SEGBITS; | ||
| 106 | + target_ulong SEGMask; | ||
| 105 | int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type); | 107 | int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type); |
| 106 | void (*do_tlbwi) (void); | 108 | void (*do_tlbwi) (void); |
| 107 | void (*do_tlbwr) (void); | 109 | void (*do_tlbwr) (void); |
target-mips/helper.c
| @@ -77,7 +77,7 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, | @@ -77,7 +77,7 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, | ||
| 77 | target_ulong tag = address & ~mask; | 77 | target_ulong tag = address & ~mask; |
| 78 | target_ulong VPN = tlb->VPN & ~mask; | 78 | target_ulong VPN = tlb->VPN & ~mask; |
| 79 | #ifdef TARGET_MIPS64 | 79 | #ifdef TARGET_MIPS64 |
| 80 | - tag &= 0xC00000FFFFFFFFFFULL; | 80 | + tag &= env->SEGMask; |
| 81 | #endif | 81 | #endif |
| 82 | 82 | ||
| 83 | /* Check ASID, virtual page number & size */ | 83 | /* Check ASID, virtual page number & size */ |
| @@ -140,18 +140,17 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -140,18 +140,17 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 140 | /* | 140 | /* |
| 141 | XXX: Assuming : | 141 | XXX: Assuming : |
| 142 | - PABITS = 36 (correct for MIPS64R1) | 142 | - PABITS = 36 (correct for MIPS64R1) |
| 143 | - - SEGBITS = 40 | ||
| 144 | */ | 143 | */ |
| 145 | } else if (address < 0x3FFFFFFFFFFFFFFFULL) { | 144 | } else if (address < 0x3FFFFFFFFFFFFFFFULL) { |
| 146 | /* xuseg */ | 145 | /* xuseg */ |
| 147 | - if (UX && address < 0x000000FFFFFFFFFFULL) { | 146 | + if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { |
| 148 | ret = env->map_address(env, physical, prot, address, rw, access_type); | 147 | ret = env->map_address(env, physical, prot, address, rw, access_type); |
| 149 | } else { | 148 | } else { |
| 150 | ret = TLBRET_BADADDR; | 149 | ret = TLBRET_BADADDR; |
| 151 | } | 150 | } |
| 152 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { | 151 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { |
| 153 | /* xsseg */ | 152 | /* xsseg */ |
| 154 | - if (SX && address < 0x400000FFFFFFFFFFULL) { | 153 | + if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { |
| 155 | ret = env->map_address(env, physical, prot, address, rw, access_type); | 154 | ret = env->map_address(env, physical, prot, address, rw, access_type); |
| 156 | } else { | 155 | } else { |
| 157 | ret = TLBRET_BADADDR; | 156 | ret = TLBRET_BADADDR; |
| @@ -159,9 +158,9 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -159,9 +158,9 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 159 | } else if (address < 0xBFFFFFFFFFFFFFFFULL) { | 158 | } else if (address < 0xBFFFFFFFFFFFFFFFULL) { |
| 160 | /* xkphys */ | 159 | /* xkphys */ |
| 161 | /* XXX: check supervisor mode */ | 160 | /* XXX: check supervisor mode */ |
| 162 | - if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) | 161 | + if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) |
| 163 | { | 162 | { |
| 164 | - *physical = address & 0X000000FFFFFFFFFFULL; | 163 | + *physical = address & 0X0000000FFFFFFFFFULL; |
| 165 | *prot = PAGE_READ | PAGE_WRITE; | 164 | *prot = PAGE_READ | PAGE_WRITE; |
| 166 | } else { | 165 | } else { |
| 167 | ret = TLBRET_BADADDR; | 166 | ret = TLBRET_BADADDR; |
| @@ -169,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -169,7 +168,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 169 | } else if (address < 0xFFFFFFFF7FFFFFFFULL) { | 168 | } else if (address < 0xFFFFFFFF7FFFFFFFULL) { |
| 170 | /* xkseg */ | 169 | /* xkseg */ |
| 171 | /* XXX: check supervisor mode */ | 170 | /* XXX: check supervisor mode */ |
| 172 | - if (KX && address < 0xC00000FF7FFFFFFFULL) { | 171 | + if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { |
| 173 | ret = env->map_address(env, physical, prot, address, rw, access_type); | 172 | ret = env->map_address(env, physical, prot, address, rw, access_type); |
| 174 | } else { | 173 | } else { |
| 175 | ret = TLBRET_BADADDR; | 174 | ret = TLBRET_BADADDR; |
| @@ -303,10 +302,10 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -303,10 +302,10 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 303 | env->CP0_EntryHi = | 302 | env->CP0_EntryHi = |
| 304 | (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); | 303 | (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); |
| 305 | #ifdef TARGET_MIPS64 | 304 | #ifdef TARGET_MIPS64 |
| 306 | - env->CP0_EntryHi &= 0xc00000ffffffffffULL; | ||
| 307 | - env->CP0_XContext = (env->CP0_XContext & 0xfffffffe00000000ULL) | | ||
| 308 | - ((address >> 31) & 0x0000000180000000ULL) | | ||
| 309 | - ((address >> 9) & 0x000000007ffffff0ULL); | 305 | + env->CP0_EntryHi &= env->SEGMask; |
| 306 | + env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | | ||
| 307 | + ((address & 0xC00000000000ULL) >> (env->SEGBITS - 9)) | | ||
| 308 | + ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9); | ||
| 310 | #endif | 309 | #endif |
| 311 | env->exception_index = exception; | 310 | env->exception_index = exception; |
| 312 | env->error_code = error_code; | 311 | env->error_code = error_code; |
| @@ -555,7 +554,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -555,7 +554,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
| 555 | if (tlb->V0) { | 554 | if (tlb->V0) { |
| 556 | addr = tlb->VPN & ~mask; | 555 | addr = tlb->VPN & ~mask; |
| 557 | #ifdef TARGET_MIPS64 | 556 | #ifdef TARGET_MIPS64 |
| 558 | - if (addr >= 0xC00000FF80000000ULL) { | 557 | + if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { |
| 559 | addr |= 0x3FFFFF0000000000ULL; | 558 | addr |= 0x3FFFFF0000000000ULL; |
| 560 | } | 559 | } |
| 561 | #endif | 560 | #endif |
| @@ -568,7 +567,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | @@ -568,7 +567,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) | ||
| 568 | if (tlb->V1) { | 567 | if (tlb->V1) { |
| 569 | addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); | 568 | addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); |
| 570 | #ifdef TARGET_MIPS64 | 569 | #ifdef TARGET_MIPS64 |
| 571 | - if (addr >= 0xC00000FF80000000ULL) { | 570 | + if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { |
| 572 | addr |= 0x3FFFFF0000000000ULL; | 571 | addr |= 0x3FFFFF0000000000ULL; |
| 573 | } | 572 | } |
| 574 | #endif | 573 | #endif |
target-mips/op.c
| @@ -1328,7 +1328,7 @@ void op_mtc0_entryhi (void) | @@ -1328,7 +1328,7 @@ void op_mtc0_entryhi (void) | ||
| 1328 | /* 1k pages not implemented */ | 1328 | /* 1k pages not implemented */ |
| 1329 | val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF); | 1329 | val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF); |
| 1330 | #ifdef TARGET_MIPS64 | 1330 | #ifdef TARGET_MIPS64 |
| 1331 | - val = T0 & 0xC00000FFFFFFFFFFULL; | 1331 | + val &= env->SEGMask; |
| 1332 | #endif | 1332 | #endif |
| 1333 | old = env->CP0_EntryHi; | 1333 | old = env->CP0_EntryHi; |
| 1334 | env->CP0_EntryHi = val; | 1334 | env->CP0_EntryHi = val; |
| @@ -1526,7 +1526,8 @@ void op_mtc0_desave (void) | @@ -1526,7 +1526,8 @@ void op_mtc0_desave (void) | ||
| 1526 | #ifdef TARGET_MIPS64 | 1526 | #ifdef TARGET_MIPS64 |
| 1527 | void op_mtc0_xcontext (void) | 1527 | void op_mtc0_xcontext (void) |
| 1528 | { | 1528 | { |
| 1529 | - env->CP0_XContext = (env->CP0_XContext & 0x1ffffffffULL) | (T0 & ~0x1ffffffffULL); | 1529 | + target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1; |
| 1530 | + env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask); | ||
| 1530 | RETURN(); | 1531 | RETURN(); |
| 1531 | } | 1532 | } |
| 1532 | 1533 |
target-mips/op_helper.c
| @@ -374,7 +374,7 @@ static void r4k_fill_tlb (int idx) | @@ -374,7 +374,7 @@ static void r4k_fill_tlb (int idx) | ||
| 374 | tlb = &env->mmu.r4k.tlb[idx]; | 374 | tlb = &env->mmu.r4k.tlb[idx]; |
| 375 | tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); | 375 | tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); |
| 376 | #ifdef TARGET_MIPS64 | 376 | #ifdef TARGET_MIPS64 |
| 377 | - tlb->VPN &= 0xC00000FFFFFFFFFFULL; | 377 | + tlb->VPN &= env->SEGMask; |
| 378 | #endif | 378 | #endif |
| 379 | tlb->ASID = env->CP0_EntryHi & 0xFF; | 379 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
| 380 | tlb->PageMask = env->CP0_PageMask; | 380 | tlb->PageMask = env->CP0_PageMask; |
target-mips/translate_init.c
| @@ -71,6 +71,7 @@ struct mips_def_t { | @@ -71,6 +71,7 @@ struct mips_def_t { | ||
| 71 | int32_t CCRes; | 71 | int32_t CCRes; |
| 72 | int32_t Status_rw_bitmask; | 72 | int32_t Status_rw_bitmask; |
| 73 | int32_t CP1_fcr0; | 73 | int32_t CP1_fcr0; |
| 74 | + int32_t SEGBITS; | ||
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | /*****************************************************************************/ | 77 | /*****************************************************************************/ |
| @@ -87,6 +88,7 @@ static mips_def_t mips_defs[] = | @@ -87,6 +88,7 @@ static mips_def_t mips_defs[] = | ||
| 87 | .SYNCI_Step = 32, | 88 | .SYNCI_Step = 32, |
| 88 | .CCRes = 2, | 89 | .CCRes = 2, |
| 89 | .Status_rw_bitmask = 0x3278FF17, | 90 | .Status_rw_bitmask = 0x3278FF17, |
| 91 | + .SEGBITS = 32, | ||
| 90 | }, | 92 | }, |
| 91 | { | 93 | { |
| 92 | .name = "4KEcR1", | 94 | .name = "4KEcR1", |
| @@ -98,6 +100,7 @@ static mips_def_t mips_defs[] = | @@ -98,6 +100,7 @@ static mips_def_t mips_defs[] = | ||
| 98 | .SYNCI_Step = 32, | 100 | .SYNCI_Step = 32, |
| 99 | .CCRes = 2, | 101 | .CCRes = 2, |
| 100 | .Status_rw_bitmask = 0x3278FF17, | 102 | .Status_rw_bitmask = 0x3278FF17, |
| 103 | + .SEGBITS = 32, | ||
| 101 | }, | 104 | }, |
| 102 | { | 105 | { |
| 103 | .name = "4KEc", | 106 | .name = "4KEc", |
| @@ -109,6 +112,7 @@ static mips_def_t mips_defs[] = | @@ -109,6 +112,7 @@ static mips_def_t mips_defs[] = | ||
| 109 | .SYNCI_Step = 32, | 112 | .SYNCI_Step = 32, |
| 110 | .CCRes = 2, | 113 | .CCRes = 2, |
| 111 | .Status_rw_bitmask = 0x3278FF17, | 114 | .Status_rw_bitmask = 0x3278FF17, |
| 115 | + .SEGBITS = 32, | ||
| 112 | }, | 116 | }, |
| 113 | { | 117 | { |
| 114 | .name = "24Kc", | 118 | .name = "24Kc", |
| @@ -120,6 +124,7 @@ static mips_def_t mips_defs[] = | @@ -120,6 +124,7 @@ static mips_def_t mips_defs[] = | ||
| 120 | .SYNCI_Step = 32, | 124 | .SYNCI_Step = 32, |
| 121 | .CCRes = 2, | 125 | .CCRes = 2, |
| 122 | .Status_rw_bitmask = 0x3278FF17, | 126 | .Status_rw_bitmask = 0x3278FF17, |
| 127 | + .SEGBITS = 32, | ||
| 123 | }, | 128 | }, |
| 124 | { | 129 | { |
| 125 | .name = "24Kf", | 130 | .name = "24Kf", |
| @@ -133,6 +138,7 @@ static mips_def_t mips_defs[] = | @@ -133,6 +138,7 @@ static mips_def_t mips_defs[] = | ||
| 133 | .Status_rw_bitmask = 0x3678FF17, | 138 | .Status_rw_bitmask = 0x3678FF17, |
| 134 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | | 139 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | |
| 135 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), | 140 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), |
| 141 | + .SEGBITS = 32, | ||
| 136 | }, | 142 | }, |
| 137 | #ifdef TARGET_MIPS64 | 143 | #ifdef TARGET_MIPS64 |
| 138 | { | 144 | { |
| @@ -147,6 +153,7 @@ static mips_def_t mips_defs[] = | @@ -147,6 +153,7 @@ static mips_def_t mips_defs[] = | ||
| 147 | .Status_rw_bitmask = 0x3678FFFF, | 153 | .Status_rw_bitmask = 0x3678FFFF, |
| 148 | /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ | 154 | /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ |
| 149 | .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), | 155 | .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), |
| 156 | + .SEGBITS = 40, | ||
| 150 | }, | 157 | }, |
| 151 | { | 158 | { |
| 152 | .name = "5Kc", | 159 | .name = "5Kc", |
| @@ -161,6 +168,7 @@ static mips_def_t mips_defs[] = | @@ -161,6 +168,7 @@ static mips_def_t mips_defs[] = | ||
| 161 | .SYNCI_Step = 32, | 168 | .SYNCI_Step = 32, |
| 162 | .CCRes = 2, | 169 | .CCRes = 2, |
| 163 | .Status_rw_bitmask = 0x32F8FFFF, | 170 | .Status_rw_bitmask = 0x32F8FFFF, |
| 171 | + .SEGBITS = 42, | ||
| 164 | }, | 172 | }, |
| 165 | { | 173 | { |
| 166 | .name = "5Kf", | 174 | .name = "5Kf", |
| @@ -178,6 +186,7 @@ static mips_def_t mips_defs[] = | @@ -178,6 +186,7 @@ static mips_def_t mips_defs[] = | ||
| 178 | /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ | 186 | /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ |
| 179 | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | | 187 | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | |
| 180 | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), | 188 | (0x81 << FCR0_PRID) | (0x0 << FCR0_REV), |
| 189 | + .SEGBITS = 42, | ||
| 181 | }, | 190 | }, |
| 182 | { | 191 | { |
| 183 | .name = "20Kc", | 192 | .name = "20Kc", |
| @@ -198,6 +207,7 @@ static mips_def_t mips_defs[] = | @@ -198,6 +207,7 @@ static mips_def_t mips_defs[] = | ||
| 198 | .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | | 207 | .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | |
| 199 | (1 << FCR0_D) | (1 << FCR0_S) | | 208 | (1 << FCR0_D) | (1 << FCR0_S) | |
| 200 | (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), | 209 | (0x82 << FCR0_PRID) | (0x0 << FCR0_REV), |
| 210 | + .SEGBITS = 40, | ||
| 201 | }, | 211 | }, |
| 202 | #endif | 212 | #endif |
| 203 | }; | 213 | }; |
| @@ -274,6 +284,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) | @@ -274,6 +284,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) | ||
| 274 | env->CCRes = def->CCRes; | 284 | env->CCRes = def->CCRes; |
| 275 | env->Status_rw_bitmask = def->Status_rw_bitmask; | 285 | env->Status_rw_bitmask = def->Status_rw_bitmask; |
| 276 | env->fcr0 = def->CP1_fcr0; | 286 | env->fcr0 = def->CP1_fcr0; |
| 287 | +#ifdef TARGET_MIPS64 | ||
| 288 | + env->SEGBITS = def->SEGBITS; | ||
| 289 | + env->SEGMask = (3ULL << 62) | ((1ULL << def->SEGBITS) - 1); | ||
| 290 | +#endif | ||
| 277 | #ifdef CONFIG_USER_ONLY | 291 | #ifdef CONFIG_USER_ONLY |
| 278 | if (env->CP0_Config1 & (1 << CP0C1_FP)) | 292 | if (env->CP0_Config1 & (1 << CP0C1_FP)) |
| 279 | env->hflags |= MIPS_HFLAG_FPU; | 293 | env->hflags |= MIPS_HFLAG_FPU; |