Commit 6e8e7d4c092951f417297120e3d3cc28840a045b

Authored by Igor Kovalenko
Committed by Blue Swirl
1 parent 33b544ba

sparc64 name mmu registers and general cleanup

- add names to mmu registers, this helps understanding the code which
uses/modifies them.
- fold i/d mmu tlb entries tag and tte arrays into arrays of tlb entries
- extract demap_tlb routine (code duplication)
- extract replace_tlb routine (code duplication)

- flush qemu tlb translations when replacing sparc64 mmu tlb entries

I have no test case which demands flushing qemu translations,
and this patch should have no other visible changes to runtime.

Signed-off-by: igor.v.kovalenko@gmail.com

--
Kind regards,
Igor V. Kovalenko
target-sparc/cpu.h
... ... @@ -273,6 +273,11 @@ enum {
273 273 };
274 274 #endif
275 275  
  276 +typedef struct SparcTLBEntry {
  277 + uint64_t tag;
  278 + uint64_t tte;
  279 +} SparcTLBEntry;
  280 +
276 281 typedef struct CPUSPARCState {
277 282 target_ulong gregs[8]; /* general registers */
278 283 target_ulong *regwptr; /* pointer to current register window */
... ... @@ -319,12 +324,33 @@ typedef struct CPUSPARCState {
319 324 uint64_t lsu;
320 325 #define DMMU_E 0x8
321 326 #define IMMU_E 0x4
322   - uint64_t immuregs[16];
323   - uint64_t dmmuregs[16];
324   - uint64_t itlb_tag[64];
325   - uint64_t itlb_tte[64];
326   - uint64_t dtlb_tag[64];
327   - uint64_t dtlb_tte[64];
  327 + //typedef struct SparcMMU
  328 + union {
  329 + uint64_t immuregs[16];
  330 + struct {
  331 + uint64_t tsb_tag_target;
  332 + uint64_t unused_mmu_primary_context; // use DMMU
  333 + uint64_t unused_mmu_secondary_context; // use DMMU
  334 + uint64_t sfsr;
  335 + uint64_t sfar;
  336 + uint64_t tsb;
  337 + uint64_t tag_access;
  338 + } immu;
  339 + };
  340 + union {
  341 + uint64_t dmmuregs[16];
  342 + struct {
  343 + uint64_t tsb_tag_target;
  344 + uint64_t mmu_primary_context;
  345 + uint64_t mmu_secondary_context;
  346 + uint64_t sfsr;
  347 + uint64_t sfar;
  348 + uint64_t tsb;
  349 + uint64_t tag_access;
  350 + } dmmu;
  351 + };
  352 + SparcTLBEntry itlb[64];
  353 + SparcTLBEntry dtlb[64];
328 354 uint32_t mmu_version;
329 355 #else
330 356 uint32_t mmuregs[32];
... ...
target-sparc/helper.c
... ... @@ -386,13 +386,13 @@ static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
386 386  
387 387 // Returns true if TTE tag is valid and matches virtual address value in context
388 388 // requires virtual address mask value calculated from TTE entry size
389   -static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
  389 +static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
390 390 uint64_t address, uint64_t context,
391 391 target_phys_addr_t *physical)
392 392 {
393 393 uint64_t mask;
394 394  
395   - switch ((tlb_tte >> 61) & 3) {
  395 + switch ((tlb->tte >> 61) & 3) {
396 396 default:
397 397 case 0x0: // 8k
398 398 mask = 0xffffffffffffe000ULL;
... ... @@ -409,12 +409,12 @@ static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
409 409 }
410 410  
411 411 // valid, context match, virtual address match?
412   - if ((tlb_tte & 0x8000000000000000ULL) &&
413   - compare_masked(context, tlb_tag, 0x1fff) &&
414   - compare_masked(address, tlb_tag, mask))
  412 + if ((tlb->tte & 0x8000000000000000ULL) &&
  413 + compare_masked(context, tlb->tag, 0x1fff) &&
  414 + compare_masked(address, tlb->tag, mask))
415 415 {
416 416 // decode physical address
417   - *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
  417 + *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
418 418 return 1;
419 419 }
420 420  
... ... @@ -434,21 +434,31 @@ static int get_physical_address_data(CPUState *env,
434 434 return 0;
435 435 }
436 436  
437   - context = env->dmmuregs[1] & 0x1fff;
  437 + context = env->dmmu.mmu_primary_context & 0x1fff;
438 438  
439 439 for (i = 0; i < 64; i++) {
440 440 // ctx match, vaddr match, valid?
441   - if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i],
  441 + if (ultrasparc_tag_match(&env->dtlb[i],
442 442 address, context, physical)
443 443 ) {
444 444 // access ok?
445   - if (((env->dtlb_tte[i] & 0x4) && is_user) ||
446   - (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
447   - if (env->dmmuregs[3]) /* Fault status register */
448   - env->dmmuregs[3] = 2; /* overflow (not read before
  445 + if (((env->dtlb[i].tte & 0x4) && is_user) ||
  446 + (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
  447 + uint8_t fault_type = 0;
  448 +
  449 + if ((env->dtlb[i].tte & 0x4) && is_user) {
  450 + fault_type |= 1; /* privilege violation */
  451 + }
  452 +
  453 + if (env->dmmu.sfsr & 1) /* Fault status register */
  454 + env->dmmu.sfsr = 2; /* overflow (not read before
449 455 another fault) */
450   - env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
451   - env->dmmuregs[4] = address; /* Fault address register */
  456 +
  457 + env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
  458 +
  459 + env->dmmu.sfsr |= (fault_type << 7);
  460 +
  461 + env->dmmu.sfar = address; /* Fault address register */
452 462 env->exception_index = TT_DFAULT;
453 463 #ifdef DEBUG_MMU
454 464 printf("DFAULT at 0x%" PRIx64 "\n", address);
... ... @@ -456,7 +466,7 @@ static int get_physical_address_data(CPUState *env,
456 466 return 1;
457 467 }
458 468 *prot = PAGE_READ;
459   - if (env->dtlb_tte[i] & 0x2)
  469 + if (env->dtlb[i].tte & 0x2)
460 470 *prot |= PAGE_WRITE;
461 471 return 0;
462 472 }
... ... @@ -464,7 +474,7 @@ static int get_physical_address_data(CPUState *env,
464 474 #ifdef DEBUG_MMU
465 475 printf("DMISS at 0x%" PRIx64 "\n", address);
466 476 #endif
467   - env->dmmuregs[6] = (address & ~0x1fffULL) | context;
  477 + env->dmmu.tag_access = (address & ~0x1fffULL) | context;
468 478 env->exception_index = TT_DMISS;
469 479 return 1;
470 480 }
... ... @@ -483,19 +493,19 @@ static int get_physical_address_code(CPUState *env,
483 493 return 0;
484 494 }
485 495  
486   - context = env->dmmuregs[1] & 0x1fff;
  496 + context = env->dmmu.mmu_primary_context & 0x1fff;
487 497  
488 498 for (i = 0; i < 64; i++) {
489 499 // ctx match, vaddr match, valid?
490   - if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i],
  500 + if (ultrasparc_tag_match(&env->itlb[i],
491 501 address, context, physical)
492 502 ) {
493 503 // access ok?
494   - if ((env->itlb_tte[i] & 0x4) && is_user) {
495   - if (env->immuregs[3]) /* Fault status register */
496   - env->immuregs[3] = 2; /* overflow (not read before
  504 + if ((env->itlb[i].tte & 0x4) && is_user) {
  505 + if (env->immu.sfsr) /* Fault status register */
  506 + env->immu.sfsr = 2; /* overflow (not read before
497 507 another fault) */
498   - env->immuregs[3] |= (is_user << 3) | 1;
  508 + env->immu.sfsr |= (is_user << 3) | 1;
499 509 env->exception_index = TT_TFAULT;
500 510 #ifdef DEBUG_MMU
501 511 printf("TFAULT at 0x%" PRIx64 "\n", address);
... ... @@ -510,7 +520,7 @@ static int get_physical_address_code(CPUState *env,
510 520 printf("TMISS at 0x%" PRIx64 "\n", address);
511 521 #endif
512 522 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
513   - env->immuregs[6] = (address & ~0x1fffULL) | context;
  523 + env->immu.tag_access = (address & ~0x1fffULL) | context;
514 524 env->exception_index = TT_TMISS;
515 525 return 1;
516 526 }
... ... @@ -561,7 +571,7 @@ void dump_mmu(CPUState *env)
561 571 const char *mask;
562 572  
563 573 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
564   - env->dmmuregs[1], env->dmmuregs[2]);
  574 + env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
565 575 if ((env->lsu & DMMU_E) == 0) {
566 576 printf("DMMU disabled\n");
567 577 } else {
... ... @@ -583,8 +593,9 @@ void dump_mmu(CPUState *env)
583 593 break;
584 594 }
585 595 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
586   - printf("VA: %" PRIx64 ", PA: %" PRIx64
  596 + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
587 597 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
  598 + i,
588 599 env->dtlb_tag[i] & (uint64_t)~0x1fffULL,
589 600 env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
590 601 mask,
... ... @@ -616,14 +627,15 @@ void dump_mmu(CPUState *env)
616 627 break;
617 628 }
618 629 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
619   - printf("VA: %" PRIx64 ", PA: %" PRIx64
  630 + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
620 631 ", %s, %s, %s, ctx %" PRId64 "\n",
621   - env->itlb_tag[i] & (uint64_t)~0x1fffULL,
  632 + i,
  633 + env->itlb[i].tag & (uint64_t)~0x1fffULL,
622 634 env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
623 635 mask,
624 636 env->itlb_tte[i] & 0x4? "priv": "user",
625 637 env->itlb_tte[i] & 0x40? "locked": "unlocked",
626   - env->itlb_tag[i] & (uint64_t)0x1fffULL);
  638 + env->itlb[i].tag & (uint64_t)0x1fffULL);
627 639 }
628 640 }
629 641 }
... ...
target-sparc/machine.c
... ... @@ -52,10 +52,10 @@ void cpu_save(QEMUFile *f, void *opaque)
52 52 qemu_put_be64s(f, &env->dmmuregs[i]);
53 53 }
54 54 for (i = 0; i < 64; i++) {
55   - qemu_put_be64s(f, &env->itlb_tag[i]);
56   - qemu_put_be64s(f, &env->itlb_tte[i]);
57   - qemu_put_be64s(f, &env->dtlb_tag[i]);
58   - qemu_put_be64s(f, &env->dtlb_tte[i]);
  55 + qemu_put_be64s(f, &env->itlb[i].tag);
  56 + qemu_put_be64s(f, &env->itlb[i].tte);
  57 + qemu_put_be64s(f, &env->dtlb[i].tag);
  58 + qemu_put_be64s(f, &env->dtlb[i].tte);
59 59 }
60 60 qemu_put_be32s(f, &env->mmu_version);
61 61 for (i = 0; i < MAXTL_MAX; i++) {
... ... @@ -148,10 +148,10 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
148 148 qemu_get_be64s(f, &env->dmmuregs[i]);
149 149 }
150 150 for (i = 0; i < 64; i++) {
151   - qemu_get_be64s(f, &env->itlb_tag[i]);
152   - qemu_get_be64s(f, &env->itlb_tte[i]);
153   - qemu_get_be64s(f, &env->dtlb_tag[i]);
154   - qemu_get_be64s(f, &env->dtlb_tte[i]);
  151 + qemu_get_be64s(f, &env->itlb[i].tag);
  152 + qemu_get_be64s(f, &env->itlb[i].tte);
  153 + qemu_get_be64s(f, &env->dtlb[i].tag);
  154 + qemu_get_be64s(f, &env->dtlb[i].tte);
155 155 }
156 156 qemu_get_be32s(f, &env->mmu_version);
157 157 for (i = 0; i < MAXTL_MAX; i++) {
... ...
target-sparc/op_helper.c
... ... @@ -46,8 +46,8 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
46 46 int page_size)
47 47 {
48 48 uint64_t tsb_base = tsb_register & ~0x1fffULL;
49   - int tsb_split = (env->dmmuregs[5] & 0x1000ULL) ? 1 : 0;
50   - int tsb_size = env->dmmuregs[5] & 0xf;
  49 + int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
  50 + int tsb_size = tsb_register & 0xf;
51 51  
52 52 // discard lower 13 bits which hold tag access context
53 53 uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
... ... @@ -87,6 +87,55 @@ static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
87 87 return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
88 88 }
89 89  
  90 +static void replace_tlb_entry(SparcTLBEntry *tlb, CPUState *env1,
  91 + uint64_t tlb_tag, uint64_t tlb_tte)
  92 +{
  93 + target_ulong mask, size, va, offset;
  94 +
  95 + // flush page range if translation is valid
  96 + if (tlb->tte & 0x8000000000000000ULL) {
  97 +
  98 + mask = 0xffffffffffffe000ULL;
  99 + mask <<= 3 * ((tlb->tte >> 61) & 3);
  100 + size = ~mask + 1;
  101 +
  102 + va = tlb->tag & mask;
  103 +
  104 + for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
  105 + tlb_flush_page(env1, va + offset);
  106 + }
  107 + }
  108 +
  109 + tlb->tag = tlb_tag;
  110 + tlb->tte = tlb_tte;
  111 +}
  112 +
  113 +static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
  114 + CPUState *env1)
  115 +{
  116 + unsigned int i;
  117 + target_ulong mask;
  118 +
  119 + for (i = 0; i < 64; i++) {
  120 + if (tlb[i].tte & 0x8000000000000000ULL) {
  121 +
  122 + mask = 0xffffffffffffe000ULL;
  123 + mask <<= 3 * ((tlb[i].tte >> 61) & 3);
  124 +
  125 + if ((demap_addr & mask) == (tlb[i].tag & mask)) {
  126 + replace_tlb_entry(&tlb[i], env1, 0, 0);
  127 +#ifdef DEBUG_MMU
  128 + DPRINTF_MMU("mmu demap invalidated entry [%02u]\n",
  129 + i);
  130 + dump_mmu(env);
  131 +#endif
  132 + }
  133 + //return;
  134 + }
  135 + }
  136 +
  137 +}
  138 +
90 139 #endif
91 140  
92 141 static inline void address_mask(CPUState *env1, target_ulong *addr)
... ... @@ -2143,7 +2192,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2143 2192  
2144 2193 if (reg == 0) {
2145 2194 // I-TSB Tag Target register
2146   - ret = ultrasparc_tag_target(env->immuregs[6]);
  2195 + ret = ultrasparc_tag_target(env->immu.tag_access);
2147 2196 } else {
2148 2197 ret = env->immuregs[reg];
2149 2198 }
... ... @@ -2154,7 +2203,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2154 2203 {
2155 2204 // env->immuregs[5] holds I-MMU TSB register value
2156 2205 // env->immuregs[6] holds I-MMU Tag Access register value
2157   - ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
  2206 + ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2158 2207 8*1024);
2159 2208 break;
2160 2209 }
... ... @@ -2162,7 +2211,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2162 2211 {
2163 2212 // env->immuregs[5] holds I-MMU TSB register value
2164 2213 // env->immuregs[6] holds I-MMU Tag Access register value
2165   - ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
  2214 + ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2166 2215 64*1024);
2167 2216 break;
2168 2217 }
... ... @@ -2170,14 +2219,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2170 2219 {
2171 2220 int reg = (addr >> 3) & 0x3f;
2172 2221  
2173   - ret = env->itlb_tte[reg];
  2222 + ret = env->itlb[reg].tte;
2174 2223 break;
2175 2224 }
2176 2225 case 0x56: // I-MMU tag read
2177 2226 {
2178 2227 int reg = (addr >> 3) & 0x3f;
2179 2228  
2180   - ret = env->itlb_tag[reg];
  2229 + ret = env->itlb[reg].tag;
2181 2230 break;
2182 2231 }
2183 2232 case 0x58: // D-MMU regs
... ... @@ -2186,7 +2235,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2186 2235  
2187 2236 if (reg == 0) {
2188 2237 // D-TSB Tag Target register
2189   - ret = ultrasparc_tag_target(env->dmmuregs[6]);
  2238 + ret = ultrasparc_tag_target(env->dmmu.tag_access);
2190 2239 } else {
2191 2240 ret = env->dmmuregs[reg];
2192 2241 }
... ... @@ -2196,7 +2245,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2196 2245 {
2197 2246 // env->dmmuregs[5] holds D-MMU TSB register value
2198 2247 // env->dmmuregs[6] holds D-MMU Tag Access register value
2199   - ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
  2248 + ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2200 2249 8*1024);
2201 2250 break;
2202 2251 }
... ... @@ -2204,7 +2253,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2204 2253 {
2205 2254 // env->dmmuregs[5] holds D-MMU TSB register value
2206 2255 // env->dmmuregs[6] holds D-MMU Tag Access register value
2207   - ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
  2256 + ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2208 2257 64*1024);
2209 2258 break;
2210 2259 }
... ... @@ -2212,14 +2261,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2212 2261 {
2213 2262 int reg = (addr >> 3) & 0x3f;
2214 2263  
2215   - ret = env->dtlb_tte[reg];
  2264 + ret = env->dtlb[reg].tte;
2216 2265 break;
2217 2266 }
2218 2267 case 0x5e: // D-MMU tag read
2219 2268 {
2220 2269 int reg = (addr >> 3) & 0x3f;
2221 2270  
2222   - ret = env->dtlb_tag[reg];
  2271 + ret = env->dtlb[reg].tag;
2223 2272 break;
2224 2273 }
2225 2274 case 0x46: // D-cache data
... ... @@ -2462,25 +2511,34 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2462 2511 oldreg = env->immuregs[reg];
2463 2512 switch(reg) {
2464 2513 case 0: // RO
2465   - case 4:
2466 2514 return;
2467 2515 case 1: // Not in I-MMU
2468 2516 case 2:
2469   - case 7:
2470   - case 8:
2471 2517 return;
2472 2518 case 3: // SFSR
2473 2519 if ((val & 1) == 0)
2474 2520 val = 0; // Clear SFSR
  2521 + env->immu.sfsr = val;
2475 2522 break;
  2523 + case 4: // RO
  2524 + return;
2476 2525 case 5: // TSB access
  2526 + DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
  2527 + PRIx64 "\n", env->immu.tsb, val);
  2528 + env->immu.tsb = val;
  2529 + break;
2477 2530 case 6: // Tag access
  2531 + env->immu.tag_access = val;
  2532 + break;
  2533 + case 7:
  2534 + case 8:
  2535 + return;
2478 2536 default:
2479 2537 break;
2480 2538 }
2481   - env->immuregs[reg] = val;
  2539 +
2482 2540 if (oldreg != env->immuregs[reg]) {
2483   - DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
  2541 + DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2484 2542 PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2485 2543 }
2486 2544 #ifdef DEBUG_MMU
... ... @@ -2494,20 +2552,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2494 2552  
2495 2553 // Try finding an invalid entry
2496 2554 for (i = 0; i < 64; i++) {
2497   - if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2498   - env->itlb_tag[i] = env->immuregs[6];
2499   - env->itlb_tte[i] = val;
  2555 + if ((env->itlb[i].tte & 0x8000000000000000ULL) == 0) {
  2556 + replace_tlb_entry(&env->itlb[i], env,
  2557 + env->immu.tag_access, val);
  2558 +#ifdef DEBUG_MMU
  2559 + DPRINTF_MMU("immu data map replaced invalid entry [%i]\n",
  2560 + i);
  2561 + dump_mmu(env);
  2562 +#endif
2500 2563 return;
2501 2564 }
2502 2565 }
2503 2566 // Try finding an unlocked entry
2504 2567 for (i = 0; i < 64; i++) {
2505   - if ((env->itlb_tte[i] & 0x40) == 0) {
2506   - env->itlb_tag[i] = env->immuregs[6];
2507   - env->itlb_tte[i] = val;
  2568 + if ((env->itlb[i].tte & 0x40) == 0) {
  2569 + replace_tlb_entry(&env->itlb[i], env,
  2570 + env->immu.tag_access, val);
  2571 +#ifdef DEBUG_MMU
  2572 + DPRINTF_MMU("immu data map replaced unlocked entry [%i]\n",
  2573 + i);
  2574 + dump_mmu(env);
  2575 +#endif
2508 2576 return;
2509 2577 }
2510 2578 }
  2579 +#ifdef DEBUG_MMU
  2580 + DPRINTF_MMU("immu data map failed: no entries available\n");
  2581 +#endif
2511 2582 // error state?
2512 2583 return;
2513 2584 }
... ... @@ -2517,27 +2588,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2517 2588  
2518 2589 unsigned int i = (addr >> 3) & 0x3f;
2519 2590  
2520   - env->itlb_tag[i] = env->immuregs[6];
2521   - env->itlb_tte[i] = val;
  2591 + replace_tlb_entry(&env->itlb[i], env,
  2592 + env->immu.tag_access, val);
  2593 +
  2594 +#ifdef DEBUG_MMU
  2595 + DPRINTF_MMU("immu data access replaced entry [%i]\n",
  2596 + i);
  2597 + dump_mmu(env);
  2598 +#endif
2522 2599 return;
2523 2600 }
2524 2601 case 0x57: // I-MMU demap
2525   - {
2526   - unsigned int i;
2527   -
2528   - for (i = 0; i < 64; i++) {
2529   - if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2530   - target_ulong mask = 0xffffffffffffe000ULL;
2531   -
2532   - mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2533   - if ((val & mask) == (env->itlb_tag[i] & mask)) {
2534   - env->itlb_tag[i] = 0;
2535   - env->itlb_tte[i] = 0;
2536   - }
2537   - return;
2538   - }
2539   - }
2540   - }
  2602 + demap_tlb(env->itlb, val, env);
2541 2603 return;
2542 2604 case 0x58: // D-MMU regs
2543 2605 {
... ... @@ -2552,22 +2614,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2552 2614 case 3: // SFSR
2553 2615 if ((val & 1) == 0) {
2554 2616 val = 0; // Clear SFSR, Fault address
2555   - env->dmmuregs[4] = 0;
  2617 + env->dmmu.sfar = 0;
2556 2618 }
2557   - env->dmmuregs[reg] = val;
  2619 + env->dmmu.sfsr = val;
2558 2620 break;
2559 2621 case 1: // Primary context
  2622 + env->dmmu.mmu_primary_context = val;
  2623 + break;
2560 2624 case 2: // Secondary context
  2625 + env->dmmu.mmu_secondary_context = val;
  2626 + break;
2561 2627 case 5: // TSB access
  2628 + DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
  2629 + PRIx64 "\n", env->dmmu.tsb, val);
  2630 + env->dmmu.tsb = val;
  2631 + break;
2562 2632 case 6: // Tag access
  2633 + env->dmmu.tag_access = val;
  2634 + break;
2563 2635 case 7: // Virtual Watchpoint
2564 2636 case 8: // Physical Watchpoint
2565 2637 default:
  2638 + env->dmmuregs[reg] = val;
2566 2639 break;
2567 2640 }
2568   - env->dmmuregs[reg] = val;
  2641 +
2569 2642 if (oldreg != env->dmmuregs[reg]) {
2570   - DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
  2643 + DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2571 2644 PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2572 2645 }
2573 2646 #ifdef DEBUG_MMU
... ... @@ -2581,20 +2654,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2581 2654  
2582 2655 // Try finding an invalid entry
2583 2656 for (i = 0; i < 64; i++) {
2584   - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2585   - env->dtlb_tag[i] = env->dmmuregs[6];
2586   - env->dtlb_tte[i] = val;
  2657 + if ((env->dtlb[i].tte & 0x8000000000000000ULL) == 0) {
  2658 + replace_tlb_entry(&env->dtlb[i], env,
  2659 + env->dmmu.tag_access, val);
  2660 +#ifdef DEBUG_MMU
  2661 + DPRINTF_MMU("dmmu data map replaced invalid entry [%i]\n",
  2662 + i);
  2663 + dump_mmu(env);
  2664 +#endif
2587 2665 return;
2588 2666 }
2589 2667 }
2590 2668 // Try finding an unlocked entry
2591 2669 for (i = 0; i < 64; i++) {
2592   - if ((env->dtlb_tte[i] & 0x40) == 0) {
2593   - env->dtlb_tag[i] = env->dmmuregs[6];
2594   - env->dtlb_tte[i] = val;
  2670 + if ((env->dtlb[i].tte & 0x40) == 0) {
  2671 + replace_tlb_entry(&env->dtlb[i], env,
  2672 + env->dmmu.tag_access, val);
  2673 +#ifdef DEBUG_MMU
  2674 + DPRINTF_MMU("dmmu data map replaced unlocked entry [%i]\n",
  2675 + i);
  2676 + dump_mmu(env);
  2677 +#endif
2595 2678 return;
2596 2679 }
2597 2680 }
  2681 +#ifdef DEBUG_MMU
  2682 + DPRINTF_MMU("dmmu data map failed: no entries available\n");
  2683 +#endif
2598 2684 // error state?
2599 2685 return;
2600 2686 }
... ... @@ -2602,27 +2688,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2602 2688 {
2603 2689 unsigned int i = (addr >> 3) & 0x3f;
2604 2690  
2605   - env->dtlb_tag[i] = env->dmmuregs[6];
2606   - env->dtlb_tte[i] = val;
  2691 + replace_tlb_entry(&env->dtlb[i], env,
  2692 + env->dmmu.tag_access, val);
  2693 +#ifdef DEBUG_MMU
  2694 + DPRINTF_MMU("dmmu data access replaced entry [%i]\n",
  2695 + i);
  2696 + dump_mmu(env);
  2697 +#endif
2607 2698 return;
2608 2699 }
2609 2700 case 0x5f: // D-MMU demap
2610   - {
2611   - unsigned int i;
2612   -
2613   - for (i = 0; i < 64; i++) {
2614   - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2615   - target_ulong mask = 0xffffffffffffe000ULL;
2616   -
2617   - mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2618   - if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2619   - env->dtlb_tag[i] = 0;
2620   - env->dtlb_tte[i] = 0;
2621   - }
2622   - return;
2623   - }
2624   - }
2625   - }
  2701 + demap_tlb(env->dtlb, val, env);
2626 2702 return;
2627 2703 case 0x49: // Interrupt data receive
2628 2704 // XXX
... ...