qemu/target/sh4/helper.c
<<
>>
Prefs
   1/*
   2 *  SH4 emulation
   3 *
   4 *  Copyright (c) 2005 Samuel Tardieu
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2.1 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21
  22#include "cpu.h"
  23#include "exec/exec-all.h"
  24#include "exec/log.h"
  25
  26#if !defined(CONFIG_USER_ONLY)
  27#include "hw/sh4/sh_intc.h"
  28#include "sysemu/runstate.h"
  29#endif
  30
  31#define MMU_OK                   0
  32#define MMU_ITLB_MISS            (-1)
  33#define MMU_ITLB_MULTIPLE        (-2)
  34#define MMU_ITLB_VIOLATION       (-3)
  35#define MMU_DTLB_MISS_READ       (-4)
  36#define MMU_DTLB_MISS_WRITE      (-5)
  37#define MMU_DTLB_INITIAL_WRITE   (-6)
  38#define MMU_DTLB_VIOLATION_READ  (-7)
  39#define MMU_DTLB_VIOLATION_WRITE (-8)
  40#define MMU_DTLB_MULTIPLE        (-9)
  41#define MMU_DTLB_MISS            (-10)
  42#define MMU_IADDR_ERROR          (-11)
  43#define MMU_DADDR_ERROR_READ     (-12)
  44#define MMU_DADDR_ERROR_WRITE    (-13)
  45
  46#if defined(CONFIG_USER_ONLY)
  47
  48void superh_cpu_do_interrupt(CPUState *cs)
  49{
  50    cs->exception_index = -1;
  51}
  52
  53int cpu_sh4_is_cached(CPUSH4State *env, target_ulong addr)
  54{
  55    /* For user mode, only U0 area is cacheable. */
  56    return !(addr & 0x80000000);
  57}
  58
  59#else /* !CONFIG_USER_ONLY */
  60
  61void superh_cpu_do_interrupt(CPUState *cs)
  62{
  63    SuperHCPU *cpu = SUPERH_CPU(cs);
  64    CPUSH4State *env = &cpu->env;
  65    int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
  66    int do_exp, irq_vector = cs->exception_index;
  67
  68    /* prioritize exceptions over interrupts */
  69
  70    do_exp = cs->exception_index != -1;
  71    do_irq = do_irq && (cs->exception_index == -1);
  72
  73    if (env->sr & (1u << SR_BL)) {
  74        if (do_exp && cs->exception_index != 0x1e0) {
  75            /* In theory a masked exception generates a reset exception,
  76               which in turn jumps to the reset vector. However this only
  77               works when using a bootloader. When using a kernel and an
  78               initrd, they need to be reloaded and the program counter
  79               should be loaded with the kernel entry point.
  80               qemu_system_reset_request takes care of that.  */
  81            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  82            return;
  83        }
  84        if (do_irq && !env->in_sleep) {
  85            return; /* masked */
  86        }
  87    }
  88    env->in_sleep = 0;
  89
  90    if (do_irq) {
  91        irq_vector = sh_intc_get_pending_vector(env->intc_handle,
  92                                                (env->sr >> 4) & 0xf);
  93        if (irq_vector == -1) {
  94            return; /* masked */
  95        }
  96    }
  97
  98    if (qemu_loglevel_mask(CPU_LOG_INT)) {
  99        const char *expname;
 100        switch (cs->exception_index) {
 101        case 0x0e0:
 102            expname = "addr_error";
 103            break;
 104        case 0x040:
 105            expname = "tlb_miss";
 106            break;
 107        case 0x0a0:
 108            expname = "tlb_violation";
 109            break;
 110        case 0x180:
 111            expname = "illegal_instruction";
 112            break;
 113        case 0x1a0:
 114            expname = "slot_illegal_instruction";
 115            break;
 116        case 0x800:
 117            expname = "fpu_disable";
 118            break;
 119        case 0x820:
 120            expname = "slot_fpu";
 121            break;
 122        case 0x100:
 123            expname = "data_write";
 124            break;
 125        case 0x060:
 126            expname = "dtlb_miss_write";
 127            break;
 128        case 0x0c0:
 129            expname = "dtlb_violation_write";
 130            break;
 131        case 0x120:
 132            expname = "fpu_exception";
 133            break;
 134        case 0x080:
 135            expname = "initial_page_write";
 136            break;
 137        case 0x160:
 138            expname = "trapa";
 139            break;
 140        default:
 141            expname = do_irq ? "interrupt" : "???";
 142            break;
 143        }
 144        qemu_log("exception 0x%03x [%s] raised\n",
 145                  irq_vector, expname);
 146        log_cpu_state(cs, 0);
 147    }
 148
 149    env->ssr = cpu_read_sr(env);
 150    env->spc = env->pc;
 151    env->sgr = env->gregs[15];
 152    env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
 153    env->lock_addr = -1;
 154
 155    if (env->flags & DELAY_SLOT_MASK) {
 156        /* Branch instruction should be executed again before delay slot. */
 157        env->spc -= 2;
 158        /* Clear flags for exception/interrupt routine. */
 159        env->flags &= ~DELAY_SLOT_MASK;
 160    }
 161
 162    if (do_exp) {
 163        env->expevt = cs->exception_index;
 164        switch (cs->exception_index) {
 165        case 0x000:
 166        case 0x020:
 167        case 0x140:
 168            env->sr &= ~(1u << SR_FD);
 169            env->sr |= 0xf << 4; /* IMASK */
 170            env->pc = 0xa0000000;
 171            break;
 172        case 0x040:
 173        case 0x060:
 174            env->pc = env->vbr + 0x400;
 175            break;
 176        case 0x160:
 177            env->spc += 2; /* special case for TRAPA */
 178            /* fall through */
 179        default:
 180            env->pc = env->vbr + 0x100;
 181            break;
 182        }
 183        return;
 184    }
 185
 186    if (do_irq) {
 187        env->intevt = irq_vector;
 188        env->pc = env->vbr + 0x600;
 189        return;
 190    }
 191}
 192
 193static void update_itlb_use(CPUSH4State * env, int itlbnb)
 194{
 195    uint8_t or_mask = 0, and_mask = (uint8_t) - 1;
 196
 197    switch (itlbnb) {
 198    case 0:
 199        and_mask = 0x1f;
 200        break;
 201    case 1:
 202        and_mask = 0xe7;
 203        or_mask = 0x80;
 204        break;
 205    case 2:
 206        and_mask = 0xfb;
 207        or_mask = 0x50;
 208        break;
 209    case 3:
 210        or_mask = 0x2c;
 211        break;
 212    }
 213
 214    env->mmucr &= (and_mask << 24) | 0x00ffffff;
 215    env->mmucr |= (or_mask << 24);
 216}
 217
 218static int itlb_replacement(CPUSH4State * env)
 219{
 220    if ((env->mmucr & 0xe0000000) == 0xe0000000) {
 221        return 0;
 222    }
 223    if ((env->mmucr & 0x98000000) == 0x18000000) {
 224        return 1;
 225    }
 226    if ((env->mmucr & 0x54000000) == 0x04000000) {
 227        return 2;
 228    }
 229    if ((env->mmucr & 0x2c000000) == 0x00000000) {
 230        return 3;
 231    }
 232    cpu_abort(env_cpu(env), "Unhandled itlb_replacement");
 233}
 234
 235/* Find the corresponding entry in the right TLB
 236   Return entry, MMU_DTLB_MISS or MMU_DTLB_MULTIPLE
 237*/
 238static int find_tlb_entry(CPUSH4State * env, target_ulong address,
 239                          tlb_t * entries, uint8_t nbtlb, int use_asid)
 240{
 241    int match = MMU_DTLB_MISS;
 242    uint32_t start, end;
 243    uint8_t asid;
 244    int i;
 245
 246    asid = env->pteh & 0xff;
 247
 248    for (i = 0; i < nbtlb; i++) {
 249        if (!entries[i].v)
 250            continue;           /* Invalid entry */
 251        if (!entries[i].sh && use_asid && entries[i].asid != asid)
 252            continue;           /* Bad ASID */
 253        start = (entries[i].vpn << 10) & ~(entries[i].size - 1);
 254        end = start + entries[i].size - 1;
 255        if (address >= start && address <= end) {       /* Match */
 256            if (match != MMU_DTLB_MISS)
 257                return MMU_DTLB_MULTIPLE;       /* Multiple match */
 258            match = i;
 259        }
 260    }
 261    return match;
 262}
 263
 264static void increment_urc(CPUSH4State * env)
 265{
 266    uint8_t urb, urc;
 267
 268    /* Increment URC */
 269    urb = ((env->mmucr) >> 18) & 0x3f;
 270    urc = ((env->mmucr) >> 10) & 0x3f;
 271    urc++;
 272    if ((urb > 0 && urc > urb) || urc > (UTLB_SIZE - 1))
 273        urc = 0;
 274    env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10);
 275}
 276
 277/* Copy and utlb entry into itlb
 278   Return entry
 279*/
 280static int copy_utlb_entry_itlb(CPUSH4State *env, int utlb)
 281{
 282    int itlb;
 283
 284    tlb_t * ientry;
 285    itlb = itlb_replacement(env);
 286    ientry = &env->itlb[itlb];
 287    if (ientry->v) {
 288        tlb_flush_page(env_cpu(env), ientry->vpn << 10);
 289    }
 290    *ientry = env->utlb[utlb];
 291    update_itlb_use(env, itlb);
 292    return itlb;
 293}
 294
 295/* Find itlb entry
 296   Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE
 297*/
 298static int find_itlb_entry(CPUSH4State * env, target_ulong address,
 299                           int use_asid)
 300{
 301    int e;
 302
 303    e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid);
 304    if (e == MMU_DTLB_MULTIPLE) {
 305        e = MMU_ITLB_MULTIPLE;
 306    } else if (e == MMU_DTLB_MISS) {
 307        e = MMU_ITLB_MISS;
 308    } else if (e >= 0) {
 309        update_itlb_use(env, e);
 310    }
 311    return e;
 312}
 313
 314/* Find utlb entry
 315   Return entry, MMU_DTLB_MISS, MMU_DTLB_MULTIPLE */
 316static int find_utlb_entry(CPUSH4State * env, target_ulong address, int use_asid)
 317{
 318    /* per utlb access */
 319    increment_urc(env);
 320
 321    /* Return entry */
 322    return find_tlb_entry(env, address, env->utlb, UTLB_SIZE, use_asid);
 323}
 324
 325/* Match address against MMU
 326   Return MMU_OK, MMU_DTLB_MISS_READ, MMU_DTLB_MISS_WRITE,
 327   MMU_DTLB_INITIAL_WRITE, MMU_DTLB_VIOLATION_READ,
 328   MMU_DTLB_VIOLATION_WRITE, MMU_ITLB_MISS,
 329   MMU_ITLB_MULTIPLE, MMU_ITLB_VIOLATION,
 330   MMU_IADDR_ERROR, MMU_DADDR_ERROR_READ, MMU_DADDR_ERROR_WRITE.
 331*/
 332static int get_mmu_address(CPUSH4State * env, target_ulong * physical,
 333                           int *prot, target_ulong address,
 334                           MMUAccessType access_type)
 335{
 336    int use_asid, n;
 337    tlb_t *matching = NULL;
 338
 339    use_asid = !(env->mmucr & MMUCR_SV) || !(env->sr & (1u << SR_MD));
 340
 341    if (access_type == MMU_INST_FETCH) {
 342        n = find_itlb_entry(env, address, use_asid);
 343        if (n >= 0) {
 344            matching = &env->itlb[n];
 345            if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
 346                n = MMU_ITLB_VIOLATION;
 347            } else {
 348                *prot = PAGE_EXEC;
 349            }
 350        } else {
 351            n = find_utlb_entry(env, address, use_asid);
 352            if (n >= 0) {
 353                n = copy_utlb_entry_itlb(env, n);
 354                matching = &env->itlb[n];
 355                if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
 356                    n = MMU_ITLB_VIOLATION;
 357                } else {
 358                    *prot = PAGE_READ | PAGE_EXEC;
 359                    if ((matching->pr & 1) && matching->d) {
 360                        *prot |= PAGE_WRITE;
 361                    }
 362                }
 363            } else if (n == MMU_DTLB_MULTIPLE) {
 364                n = MMU_ITLB_MULTIPLE;
 365            } else if (n == MMU_DTLB_MISS) {
 366                n = MMU_ITLB_MISS;
 367            }
 368        }
 369    } else {
 370        n = find_utlb_entry(env, address, use_asid);
 371        if (n >= 0) {
 372            matching = &env->utlb[n];
 373            if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
 374                n = (access_type == MMU_DATA_STORE)
 375                    ? MMU_DTLB_VIOLATION_WRITE : MMU_DTLB_VIOLATION_READ;
 376            } else if ((access_type == MMU_DATA_STORE) && !(matching->pr & 1)) {
 377                n = MMU_DTLB_VIOLATION_WRITE;
 378            } else if ((access_type == MMU_DATA_STORE) && !matching->d) {
 379                n = MMU_DTLB_INITIAL_WRITE;
 380            } else {
 381                *prot = PAGE_READ;
 382                if ((matching->pr & 1) && matching->d) {
 383                    *prot |= PAGE_WRITE;
 384                }
 385            }
 386        } else if (n == MMU_DTLB_MISS) {
 387            n = (access_type == MMU_DATA_STORE)
 388                ? MMU_DTLB_MISS_WRITE : MMU_DTLB_MISS_READ;
 389        }
 390    }
 391    if (n >= 0) {
 392        n = MMU_OK;
 393        *physical = ((matching->ppn << 10) & ~(matching->size - 1))
 394                    | (address & (matching->size - 1));
 395    }
 396    return n;
 397}
 398
 399static int get_physical_address(CPUSH4State * env, target_ulong * physical,
 400                                int *prot, target_ulong address,
 401                                MMUAccessType access_type)
 402{
 403    /* P1, P2 and P4 areas do not use translation */
 404    if ((address >= 0x80000000 && address < 0xc0000000) || address >= 0xe0000000) {
 405        if (!(env->sr & (1u << SR_MD))
 406                && (address < 0xe0000000 || address >= 0xe4000000)) {
 407            /* Unauthorized access in user mode (only store queues are available) */
 408            qemu_log_mask(LOG_GUEST_ERROR, "Unauthorized access\n");
 409            if (access_type == MMU_DATA_LOAD) {
 410                return MMU_DADDR_ERROR_READ;
 411            } else if (access_type == MMU_DATA_STORE) {
 412                return MMU_DADDR_ERROR_WRITE;
 413            } else {
 414                return MMU_IADDR_ERROR;
 415            }
 416        }
 417        if (address >= 0x80000000 && address < 0xc0000000) {
 418            /* Mask upper 3 bits for P1 and P2 areas */
 419            *physical = address & 0x1fffffff;
 420        } else {
 421            *physical = address;
 422        }
 423        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 424        return MMU_OK;
 425    }
 426
 427    /* If MMU is disabled, return the corresponding physical page */
 428    if (!(env->mmucr & MMUCR_AT)) {
 429        *physical = address & 0x1FFFFFFF;
 430        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 431        return MMU_OK;
 432    }
 433
 434    /* We need to resort to the MMU */
 435    return get_mmu_address(env, physical, prot, address, access_type);
 436}
 437
 438hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 439{
 440    SuperHCPU *cpu = SUPERH_CPU(cs);
 441    target_ulong physical;
 442    int prot;
 443
 444    if (get_physical_address(&cpu->env, &physical, &prot, addr, MMU_DATA_LOAD)
 445            == MMU_OK) {
 446        return physical;
 447    }
 448
 449    return -1;
 450}
 451
 452void cpu_load_tlb(CPUSH4State * env)
 453{
 454    CPUState *cs = env_cpu(env);
 455    int n = cpu_mmucr_urc(env->mmucr);
 456    tlb_t * entry = &env->utlb[n];
 457
 458    if (entry->v) {
 459        /* Overwriting valid entry in utlb. */
 460        target_ulong address = entry->vpn << 10;
 461        tlb_flush_page(cs, address);
 462    }
 463
 464    /* Take values into cpu status from registers. */
 465    entry->asid = (uint8_t)cpu_pteh_asid(env->pteh);
 466    entry->vpn  = cpu_pteh_vpn(env->pteh);
 467    entry->v    = (uint8_t)cpu_ptel_v(env->ptel);
 468    entry->ppn  = cpu_ptel_ppn(env->ptel);
 469    entry->sz   = (uint8_t)cpu_ptel_sz(env->ptel);
 470    switch (entry->sz) {
 471    case 0: /* 00 */
 472        entry->size = 1024; /* 1K */
 473        break;
 474    case 1: /* 01 */
 475        entry->size = 1024 * 4; /* 4K */
 476        break;
 477    case 2: /* 10 */
 478        entry->size = 1024 * 64; /* 64K */
 479        break;
 480    case 3: /* 11 */
 481        entry->size = 1024 * 1024; /* 1M */
 482        break;
 483    default:
 484        cpu_abort(cs, "Unhandled load_tlb");
 485        break;
 486    }
 487    entry->sh   = (uint8_t)cpu_ptel_sh(env->ptel);
 488    entry->c    = (uint8_t)cpu_ptel_c(env->ptel);
 489    entry->pr   = (uint8_t)cpu_ptel_pr(env->ptel);
 490    entry->d    = (uint8_t)cpu_ptel_d(env->ptel);
 491    entry->wt   = (uint8_t)cpu_ptel_wt(env->ptel);
 492    entry->sa   = (uint8_t)cpu_ptea_sa(env->ptea);
 493    entry->tc   = (uint8_t)cpu_ptea_tc(env->ptea);
 494}
 495
 496 void cpu_sh4_invalidate_tlb(CPUSH4State *s)
 497{
 498    int i;
 499
 500    /* UTLB */
 501    for (i = 0; i < UTLB_SIZE; i++) {
 502        tlb_t * entry = &s->utlb[i];
 503        entry->v = 0;
 504    }
 505    /* ITLB */
 506    for (i = 0; i < ITLB_SIZE; i++) {
 507        tlb_t * entry = &s->itlb[i];
 508        entry->v = 0;
 509    }
 510
 511    tlb_flush(env_cpu(s));
 512}
 513
 514uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s,
 515                                       hwaddr addr)
 516{
 517    int index = (addr & 0x00000300) >> 8;
 518    tlb_t * entry = &s->itlb[index];
 519
 520    return (entry->vpn  << 10) |
 521           (entry->v    <<  8) |
 522           (entry->asid);
 523}
 524
 525void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, hwaddr addr,
 526                                    uint32_t mem_value)
 527{
 528    uint32_t vpn = (mem_value & 0xfffffc00) >> 10;
 529    uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
 530    uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
 531
 532    int index = (addr & 0x00000300) >> 8;
 533    tlb_t * entry = &s->itlb[index];
 534    if (entry->v) {
 535        /* Overwriting valid entry in itlb. */
 536        target_ulong address = entry->vpn << 10;
 537        tlb_flush_page(env_cpu(s), address);
 538    }
 539    entry->asid = asid;
 540    entry->vpn = vpn;
 541    entry->v = v;
 542}
 543
 544uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s,
 545                                       hwaddr addr)
 546{
 547    int array = (addr & 0x00800000) >> 23;
 548    int index = (addr & 0x00000300) >> 8;
 549    tlb_t * entry = &s->itlb[index];
 550
 551    if (array == 0) {
 552        /* ITLB Data Array 1 */
 553        return (entry->ppn << 10) |
 554               (entry->v   <<  8) |
 555               (entry->pr  <<  5) |
 556               ((entry->sz & 1) <<  6) |
 557               ((entry->sz & 2) <<  4) |
 558               (entry->c   <<  3) |
 559               (entry->sh  <<  1);
 560    } else {
 561        /* ITLB Data Array 2 */
 562        return (entry->tc << 1) |
 563               (entry->sa);
 564    }
 565}
 566
 567void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, hwaddr addr,
 568                                    uint32_t mem_value)
 569{
 570    int array = (addr & 0x00800000) >> 23;
 571    int index = (addr & 0x00000300) >> 8;
 572    tlb_t * entry = &s->itlb[index];
 573
 574    if (array == 0) {
 575        /* ITLB Data Array 1 */
 576        if (entry->v) {
 577            /* Overwriting valid entry in utlb. */
 578            target_ulong address = entry->vpn << 10;
 579            tlb_flush_page(env_cpu(s), address);
 580        }
 581        entry->ppn = (mem_value & 0x1ffffc00) >> 10;
 582        entry->v   = (mem_value & 0x00000100) >> 8;
 583        entry->sz  = (mem_value & 0x00000080) >> 6 |
 584                     (mem_value & 0x00000010) >> 4;
 585        entry->pr  = (mem_value & 0x00000040) >> 5;
 586        entry->c   = (mem_value & 0x00000008) >> 3;
 587        entry->sh  = (mem_value & 0x00000002) >> 1;
 588    } else {
 589        /* ITLB Data Array 2 */
 590        entry->tc  = (mem_value & 0x00000008) >> 3;
 591        entry->sa  = (mem_value & 0x00000007);
 592    }
 593}
 594
 595uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s,
 596                                       hwaddr addr)
 597{
 598    int index = (addr & 0x00003f00) >> 8;
 599    tlb_t * entry = &s->utlb[index];
 600
 601    increment_urc(s); /* per utlb access */
 602
 603    return (entry->vpn  << 10) |
 604           (entry->v    <<  8) |
 605           (entry->asid);
 606}
 607
 608void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr,
 609                                    uint32_t mem_value)
 610{
 611    int associate = addr & 0x0000080;
 612    uint32_t vpn = (mem_value & 0xfffffc00) >> 10;
 613    uint8_t d = (uint8_t)((mem_value & 0x00000200) >> 9);
 614    uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
 615    uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
 616    int use_asid = !(s->mmucr & MMUCR_SV) || !(s->sr & (1u << SR_MD));
 617
 618    if (associate) {
 619        int i;
 620        tlb_t * utlb_match_entry = NULL;
 621        int needs_tlb_flush = 0;
 622
 623        /* search UTLB */
 624        for (i = 0; i < UTLB_SIZE; i++) {
 625            tlb_t * entry = &s->utlb[i];
 626            if (!entry->v)
 627                continue;
 628
 629            if (entry->vpn == vpn
 630                && (!use_asid || entry->asid == asid || entry->sh)) {
 631                if (utlb_match_entry) {
 632                    CPUState *cs = env_cpu(s);
 633
 634                    /* Multiple TLB Exception */
 635                    cs->exception_index = 0x140;
 636                    s->tea = addr;
 637                    break;
 638                }
 639                if (entry->v && !v)
 640                    needs_tlb_flush = 1;
 641                entry->v = v;
 642                entry->d = d;
 643                utlb_match_entry = entry;
 644            }
 645            increment_urc(s); /* per utlb access */
 646        }
 647
 648        /* search ITLB */
 649        for (i = 0; i < ITLB_SIZE; i++) {
 650            tlb_t * entry = &s->itlb[i];
 651            if (entry->vpn == vpn
 652                && (!use_asid || entry->asid == asid || entry->sh)) {
 653                if (entry->v && !v)
 654                    needs_tlb_flush = 1;
 655                if (utlb_match_entry)
 656                    *entry = *utlb_match_entry;
 657                else
 658                    entry->v = v;
 659                break;
 660            }
 661        }
 662
 663        if (needs_tlb_flush) {
 664            tlb_flush_page(env_cpu(s), vpn << 10);
 665        }
 666    } else {
 667        int index = (addr & 0x00003f00) >> 8;
 668        tlb_t * entry = &s->utlb[index];
 669        if (entry->v) {
 670            CPUState *cs = env_cpu(s);
 671
 672            /* Overwriting valid entry in utlb. */
 673            target_ulong address = entry->vpn << 10;
 674            tlb_flush_page(cs, address);
 675        }
 676        entry->asid = asid;
 677        entry->vpn = vpn;
 678        entry->d = d;
 679        entry->v = v;
 680        increment_urc(s);
 681    }
 682}
 683
 684uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s,
 685                                       hwaddr addr)
 686{
 687    int array = (addr & 0x00800000) >> 23;
 688    int index = (addr & 0x00003f00) >> 8;
 689    tlb_t * entry = &s->utlb[index];
 690
 691    increment_urc(s); /* per utlb access */
 692
 693    if (array == 0) {
 694        /* ITLB Data Array 1 */
 695        return (entry->ppn << 10) |
 696               (entry->v   <<  8) |
 697               (entry->pr  <<  5) |
 698               ((entry->sz & 1) <<  6) |
 699               ((entry->sz & 2) <<  4) |
 700               (entry->c   <<  3) |
 701               (entry->d   <<  2) |
 702               (entry->sh  <<  1) |
 703               (entry->wt);
 704    } else {
 705        /* ITLB Data Array 2 */
 706        return (entry->tc << 1) |
 707               (entry->sa);
 708    }
 709}
 710
 711void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, hwaddr addr,
 712                                    uint32_t mem_value)
 713{
 714    int array = (addr & 0x00800000) >> 23;
 715    int index = (addr & 0x00003f00) >> 8;
 716    tlb_t * entry = &s->utlb[index];
 717
 718    increment_urc(s); /* per utlb access */
 719
 720    if (array == 0) {
 721        /* UTLB Data Array 1 */
 722        if (entry->v) {
 723            /* Overwriting valid entry in utlb. */
 724            target_ulong address = entry->vpn << 10;
 725            tlb_flush_page(env_cpu(s), address);
 726        }
 727        entry->ppn = (mem_value & 0x1ffffc00) >> 10;
 728        entry->v   = (mem_value & 0x00000100) >> 8;
 729        entry->sz  = (mem_value & 0x00000080) >> 6 |
 730                     (mem_value & 0x00000010) >> 4;
 731        entry->pr  = (mem_value & 0x00000060) >> 5;
 732        entry->c   = (mem_value & 0x00000008) >> 3;
 733        entry->d   = (mem_value & 0x00000004) >> 2;
 734        entry->sh  = (mem_value & 0x00000002) >> 1;
 735        entry->wt  = (mem_value & 0x00000001);
 736    } else {
 737        /* UTLB Data Array 2 */
 738        entry->tc = (mem_value & 0x00000008) >> 3;
 739        entry->sa = (mem_value & 0x00000007);
 740    }
 741}
 742
 743int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 744{
 745    int n;
 746    int use_asid = !(env->mmucr & MMUCR_SV) || !(env->sr & (1u << SR_MD));
 747
 748    /* check area */
 749    if (env->sr & (1u << SR_MD)) {
 750        /* For privileged mode, P2 and P4 area is not cacheable. */
 751        if ((0xA0000000 <= addr && addr < 0xC0000000) || 0xE0000000 <= addr)
 752            return 0;
 753    } else {
 754        /* For user mode, only U0 area is cacheable. */
 755        if (0x80000000 <= addr)
 756            return 0;
 757    }
 758
 759    /*
 760     * TODO : Evaluate CCR and check if the cache is on or off.
 761     *        Now CCR is not in CPUSH4State, but in SH7750State.
 762     *        When you move the ccr into CPUSH4State, the code will be
 763     *        as follows.
 764     */
 765#if 0
 766    /* check if operand cache is enabled or not. */
 767    if (!(env->ccr & 1))
 768        return 0;
 769#endif
 770
 771    /* if MMU is off, no check for TLB. */
 772    if (env->mmucr & MMUCR_AT)
 773        return 1;
 774
 775    /* check TLB */
 776    n = find_tlb_entry(env, addr, env->itlb, ITLB_SIZE, use_asid);
 777    if (n >= 0)
 778        return env->itlb[n].c;
 779
 780    n = find_tlb_entry(env, addr, env->utlb, UTLB_SIZE, use_asid);
 781    if (n >= 0)
 782        return env->utlb[n].c;
 783
 784    return 0;
 785}
 786
 787#endif
 788
 789bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 790{
 791    if (interrupt_request & CPU_INTERRUPT_HARD) {
 792        SuperHCPU *cpu = SUPERH_CPU(cs);
 793        CPUSH4State *env = &cpu->env;
 794
 795        /* Delay slots are indivisible, ignore interrupts */
 796        if (env->flags & DELAY_SLOT_MASK) {
 797            return false;
 798        } else {
 799            superh_cpu_do_interrupt(cs);
 800            return true;
 801        }
 802    }
 803    return false;
 804}
 805
 806bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 807                         MMUAccessType access_type, int mmu_idx,
 808                         bool probe, uintptr_t retaddr)
 809{
 810    SuperHCPU *cpu = SUPERH_CPU(cs);
 811    CPUSH4State *env = &cpu->env;
 812    int ret;
 813
 814#ifdef CONFIG_USER_ONLY
 815    ret = (access_type == MMU_DATA_STORE ? MMU_DTLB_VIOLATION_WRITE :
 816           access_type == MMU_INST_FETCH ? MMU_ITLB_VIOLATION :
 817           MMU_DTLB_VIOLATION_READ);
 818#else
 819    target_ulong physical;
 820    int prot;
 821
 822    ret = get_physical_address(env, &physical, &prot, address, access_type);
 823
 824    if (ret == MMU_OK) {
 825        address &= TARGET_PAGE_MASK;
 826        physical &= TARGET_PAGE_MASK;
 827        tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
 828        return true;
 829    }
 830    if (probe) {
 831        return false;
 832    }
 833
 834    if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) {
 835        env->pteh = (env->pteh & PTEH_ASID_MASK) | (address & PTEH_VPN_MASK);
 836    }
 837#endif
 838
 839    env->tea = address;
 840    switch (ret) {
 841    case MMU_ITLB_MISS:
 842    case MMU_DTLB_MISS_READ:
 843        cs->exception_index = 0x040;
 844        break;
 845    case MMU_DTLB_MULTIPLE:
 846    case MMU_ITLB_MULTIPLE:
 847        cs->exception_index = 0x140;
 848        break;
 849    case MMU_ITLB_VIOLATION:
 850        cs->exception_index = 0x0a0;
 851        break;
 852    case MMU_DTLB_MISS_WRITE:
 853        cs->exception_index = 0x060;
 854        break;
 855    case MMU_DTLB_INITIAL_WRITE:
 856        cs->exception_index = 0x080;
 857        break;
 858    case MMU_DTLB_VIOLATION_READ:
 859        cs->exception_index = 0x0a0;
 860        break;
 861    case MMU_DTLB_VIOLATION_WRITE:
 862        cs->exception_index = 0x0c0;
 863        break;
 864    case MMU_IADDR_ERROR:
 865    case MMU_DADDR_ERROR_READ:
 866        cs->exception_index = 0x0e0;
 867        break;
 868    case MMU_DADDR_ERROR_WRITE:
 869        cs->exception_index = 0x100;
 870        break;
 871    default:
 872        cpu_abort(cs, "Unhandled MMU fault");
 873    }
 874    cpu_loop_exit_restore(cs, retaddr);
 875}
 876