qemu/target/m68k/helper.c
<<
>>
Prefs
   1/*
   2 *  m68k op helpers
   3 *
   4 *  Copyright (c) 2006-2007 CodeSourcery
   5 *  Written by Paul Brook
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "cpu.h"
  23#include "exec/exec-all.h"
  24#include "exec/gdbstub.h"
  25#include "exec/helper-proto.h"
  26#include "fpu/softfloat.h"
  27#include "qemu/qemu-print.h"
  28
  29#define SIGNBIT (1u << 31)
  30
  31/* Sort alphabetically, except for "any". */
  32static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
  33{
  34    ObjectClass *class_a = (ObjectClass *)a;
  35    ObjectClass *class_b = (ObjectClass *)b;
  36    const char *name_a, *name_b;
  37
  38    name_a = object_class_get_name(class_a);
  39    name_b = object_class_get_name(class_b);
  40    if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
  41        return 1;
  42    } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
  43        return -1;
  44    } else {
  45        return strcasecmp(name_a, name_b);
  46    }
  47}
  48
  49static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
  50{
  51    ObjectClass *c = data;
  52    const char *typename;
  53    char *name;
  54
  55    typename = object_class_get_name(c);
  56    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
  57    qemu_printf("%s\n", name);
  58    g_free(name);
  59}
  60
  61void m68k_cpu_list(void)
  62{
  63    GSList *list;
  64
  65    list = object_class_get_list(TYPE_M68K_CPU, false);
  66    list = g_slist_sort(list, m68k_cpu_list_compare);
  67    g_slist_foreach(list, m68k_cpu_list_entry, NULL);
  68    g_slist_free(list);
  69}
  70
  71static int cf_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
  72{
  73    if (n < 8) {
  74        float_status s;
  75        return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
  76    }
  77    switch (n) {
  78    case 8: /* fpcontrol */
  79        return gdb_get_reg32(mem_buf, env->fpcr);
  80    case 9: /* fpstatus */
  81        return gdb_get_reg32(mem_buf, env->fpsr);
  82    case 10: /* fpiar, not implemented */
  83        return gdb_get_reg32(mem_buf, 0);
  84    }
  85    return 0;
  86}
  87
  88static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
  89{
  90    if (n < 8) {
  91        float_status s;
  92        env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
  93        return 8;
  94    }
  95    switch (n) {
  96    case 8: /* fpcontrol */
  97        cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
  98        return 4;
  99    case 9: /* fpstatus */
 100        env->fpsr = ldl_p(mem_buf);
 101        return 4;
 102    case 10: /* fpiar, not implemented */
 103        return 4;
 104    }
 105    return 0;
 106}
 107
 108static int m68k_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
 109{
 110    if (n < 8) {
 111        int len = gdb_get_reg16(mem_buf, env->fregs[n].l.upper);
 112        len += gdb_get_reg16(mem_buf, 0);
 113        len += gdb_get_reg64(mem_buf, env->fregs[n].l.lower);
 114        return len;
 115    }
 116    switch (n) {
 117    case 8: /* fpcontrol */
 118        return gdb_get_reg32(mem_buf, env->fpcr);
 119    case 9: /* fpstatus */
 120        return gdb_get_reg32(mem_buf, env->fpsr);
 121    case 10: /* fpiar, not implemented */
 122        return gdb_get_reg32(mem_buf, 0);
 123    }
 124    return 0;
 125}
 126
 127static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
 128{
 129    if (n < 8) {
 130        env->fregs[n].l.upper = lduw_be_p(mem_buf);
 131        env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
 132        return 12;
 133    }
 134    switch (n) {
 135    case 8: /* fpcontrol */
 136        cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
 137        return 4;
 138    case 9: /* fpstatus */
 139        env->fpsr = ldl_p(mem_buf);
 140        return 4;
 141    case 10: /* fpiar, not implemented */
 142        return 4;
 143    }
 144    return 0;
 145}
 146
 147void m68k_cpu_init_gdb(M68kCPU *cpu)
 148{
 149    CPUState *cs = CPU(cpu);
 150    CPUM68KState *env = &cpu->env;
 151
 152    if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
 153        gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
 154                                 11, "cf-fp.xml", 18);
 155    } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
 156        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
 157                                 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
 158    }
 159    /* TODO: Add [E]MAC registers.  */
 160}
 161
 162void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
 163{
 164    switch (reg) {
 165    case M68K_CR_CACR:
 166        env->cacr = val;
 167        m68k_switch_sp(env);
 168        break;
 169    case M68K_CR_ACR0:
 170    case M68K_CR_ACR1:
 171    case M68K_CR_ACR2:
 172    case M68K_CR_ACR3:
 173        /* TODO: Implement Access Control Registers.  */
 174        break;
 175    case M68K_CR_VBR:
 176        env->vbr = val;
 177        break;
 178    /* TODO: Implement control registers.  */
 179    default:
 180        cpu_abort(env_cpu(env),
 181                  "Unimplemented control register write 0x%x = 0x%x\n",
 182                  reg, val);
 183    }
 184}
 185
 186void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
 187{
 188    switch (reg) {
 189    /* MC680[1234]0 */
 190    case M68K_CR_SFC:
 191        env->sfc = val & 7;
 192        return;
 193    case M68K_CR_DFC:
 194        env->dfc = val & 7;
 195        return;
 196    case M68K_CR_VBR:
 197        env->vbr = val;
 198        return;
 199    /* MC680[2346]0 */
 200    case M68K_CR_CACR:
 201        if (m68k_feature(env, M68K_FEATURE_M68020)) {
 202            env->cacr = val & 0x0000000f;
 203        } else if (m68k_feature(env, M68K_FEATURE_M68030)) {
 204            env->cacr = val & 0x00003f1f;
 205        } else if (m68k_feature(env, M68K_FEATURE_M68040)) {
 206            env->cacr = val & 0x80008000;
 207        } else if (m68k_feature(env, M68K_FEATURE_M68060)) {
 208            env->cacr = val & 0xf8e0e000;
 209        }
 210        m68k_switch_sp(env);
 211        return;
 212    /* MC680[34]0 */
 213    case M68K_CR_TC:
 214        env->mmu.tcr = val;
 215        return;
 216    case M68K_CR_MMUSR:
 217        env->mmu.mmusr = val;
 218        return;
 219    case M68K_CR_SRP:
 220        env->mmu.srp = val;
 221        return;
 222    case M68K_CR_URP:
 223        env->mmu.urp = val;
 224        return;
 225    case M68K_CR_USP:
 226        env->sp[M68K_USP] = val;
 227        return;
 228    case M68K_CR_MSP:
 229        env->sp[M68K_SSP] = val;
 230        return;
 231    case M68K_CR_ISP:
 232        env->sp[M68K_ISP] = val;
 233        return;
 234    /* MC68040/MC68LC040 */
 235    case M68K_CR_ITT0:
 236        env->mmu.ttr[M68K_ITTR0] = val;
 237        return;
 238    case M68K_CR_ITT1:
 239         env->mmu.ttr[M68K_ITTR1] = val;
 240        return;
 241    case M68K_CR_DTT0:
 242        env->mmu.ttr[M68K_DTTR0] = val;
 243        return;
 244    case M68K_CR_DTT1:
 245        env->mmu.ttr[M68K_DTTR1] = val;
 246        return;
 247    }
 248    cpu_abort(env_cpu(env),
 249              "Unimplemented control register write 0x%x = 0x%x\n",
 250              reg, val);
 251}
 252
 253uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
 254{
 255    switch (reg) {
 256    /* MC680[1234]0 */
 257    case M68K_CR_SFC:
 258        return env->sfc;
 259    case M68K_CR_DFC:
 260        return env->dfc;
 261    case M68K_CR_VBR:
 262        return env->vbr;
 263    /* MC680[234]0 */
 264    case M68K_CR_CACR:
 265        return env->cacr;
 266    /* MC680[34]0 */
 267    case M68K_CR_TC:
 268        return env->mmu.tcr;
 269    case M68K_CR_MMUSR:
 270        return env->mmu.mmusr;
 271    case M68K_CR_SRP:
 272        return env->mmu.srp;
 273    case M68K_CR_USP:
 274        return env->sp[M68K_USP];
 275    case M68K_CR_MSP:
 276        return env->sp[M68K_SSP];
 277    case M68K_CR_ISP:
 278        return env->sp[M68K_ISP];
 279    /* MC68040/MC68LC040 */
 280    case M68K_CR_URP:
 281        return env->mmu.urp;
 282    case M68K_CR_ITT0:
 283        return env->mmu.ttr[M68K_ITTR0];
 284    case M68K_CR_ITT1:
 285        return env->mmu.ttr[M68K_ITTR1];
 286    case M68K_CR_DTT0:
 287        return env->mmu.ttr[M68K_DTTR0];
 288    case M68K_CR_DTT1:
 289        return env->mmu.ttr[M68K_DTTR1];
 290    }
 291    cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\n",
 292              reg);
 293}
 294
 295void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 296{
 297    uint32_t acc;
 298    int8_t exthigh;
 299    uint8_t extlow;
 300    uint64_t regval;
 301    int i;
 302    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
 303        for (i = 0; i < 4; i++) {
 304            regval = env->macc[i];
 305            exthigh = regval >> 40;
 306            if (env->macsr & MACSR_FI) {
 307                acc = regval >> 8;
 308                extlow = regval;
 309            } else {
 310                acc = regval;
 311                extlow = regval >> 32;
 312            }
 313            if (env->macsr & MACSR_FI) {
 314                regval = (((uint64_t)acc) << 8) | extlow;
 315                regval |= ((int64_t)exthigh) << 40;
 316            } else if (env->macsr & MACSR_SU) {
 317                regval = acc | (((int64_t)extlow) << 32);
 318                regval |= ((int64_t)exthigh) << 40;
 319            } else {
 320                regval = acc | (((uint64_t)extlow) << 32);
 321                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
 322            }
 323            env->macc[i] = regval;
 324        }
 325    }
 326    env->macsr = val;
 327}
 328
 329void m68k_switch_sp(CPUM68KState *env)
 330{
 331    int new_sp;
 332
 333    env->sp[env->current_sp] = env->aregs[7];
 334    if (m68k_feature(env, M68K_FEATURE_M68000)) {
 335        if (env->sr & SR_S) {
 336            if (env->sr & SR_M) {
 337                new_sp = M68K_SSP;
 338            } else {
 339                new_sp = M68K_ISP;
 340            }
 341        } else {
 342            new_sp = M68K_USP;
 343        }
 344    } else {
 345        new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
 346                 ? M68K_SSP : M68K_USP;
 347    }
 348    env->aregs[7] = env->sp[new_sp];
 349    env->current_sp = new_sp;
 350}
 351
 352#if !defined(CONFIG_USER_ONLY)
 353/* MMU: 68040 only */
 354
 355static void print_address_zone(uint32_t logical, uint32_t physical,
 356                               uint32_t size, int attr)
 357{
 358    qemu_printf("%08x - %08x -> %08x - %08x %c ",
 359                logical, logical + size - 1,
 360                physical, physical + size - 1,
 361                attr & 4 ? 'W' : '-');
 362    size >>= 10;
 363    if (size < 1024) {
 364        qemu_printf("(%d KiB)\n", size);
 365    } else {
 366        size >>= 10;
 367        if (size < 1024) {
 368            qemu_printf("(%d MiB)\n", size);
 369        } else {
 370            size >>= 10;
 371            qemu_printf("(%d GiB)\n", size);
 372        }
 373    }
 374}
 375
 376static void dump_address_map(CPUM68KState *env, uint32_t root_pointer)
 377{
 378    int i, j, k;
 379    int tic_size, tic_shift;
 380    uint32_t tib_mask;
 381    uint32_t tia, tib, tic;
 382    uint32_t logical = 0xffffffff, physical = 0xffffffff;
 383    uint32_t first_logical = 0xffffffff, first_physical = 0xffffffff;
 384    uint32_t last_logical, last_physical;
 385    int32_t size;
 386    int last_attr = -1, attr = -1;
 387    CPUState *cs = env_cpu(env);
 388    MemTxResult txres;
 389
 390    if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
 391        /* 8k page */
 392        tic_size = 32;
 393        tic_shift = 13;
 394        tib_mask = M68K_8K_PAGE_MASK;
 395    } else {
 396        /* 4k page */
 397        tic_size = 64;
 398        tic_shift = 12;
 399        tib_mask = M68K_4K_PAGE_MASK;
 400    }
 401    for (i = 0; i < M68K_ROOT_POINTER_ENTRIES; i++) {
 402        tia = address_space_ldl(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4,
 403                                MEMTXATTRS_UNSPECIFIED, &txres);
 404        if (txres != MEMTX_OK || !M68K_UDT_VALID(tia)) {
 405            continue;
 406        }
 407        for (j = 0; j < M68K_ROOT_POINTER_ENTRIES; j++) {
 408            tib = address_space_ldl(cs->as, M68K_POINTER_BASE(tia) + j * 4,
 409                                    MEMTXATTRS_UNSPECIFIED, &txres);
 410            if (txres != MEMTX_OK || !M68K_UDT_VALID(tib)) {
 411                continue;
 412            }
 413            for (k = 0; k < tic_size; k++) {
 414                tic = address_space_ldl(cs->as, (tib & tib_mask) + k * 4,
 415                                        MEMTXATTRS_UNSPECIFIED, &txres);
 416                if (txres != MEMTX_OK || !M68K_PDT_VALID(tic)) {
 417                    continue;
 418                }
 419                if (M68K_PDT_INDIRECT(tic)) {
 420                    tic = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(tic),
 421                                            MEMTXATTRS_UNSPECIFIED, &txres);
 422                    if (txres != MEMTX_OK) {
 423                        continue;
 424                    }
 425                }
 426
 427                last_logical = logical;
 428                logical = (i << M68K_TTS_ROOT_SHIFT) |
 429                          (j << M68K_TTS_POINTER_SHIFT) |
 430                          (k << tic_shift);
 431
 432                last_physical = physical;
 433                physical = tic & ~((1 << tic_shift) - 1);
 434
 435                last_attr = attr;
 436                attr = tic & ((1 << tic_shift) - 1);
 437
 438                if ((logical != (last_logical + (1 << tic_shift))) ||
 439                    (physical != (last_physical + (1 << tic_shift))) ||
 440                    (attr & 4) != (last_attr & 4)) {
 441
 442                    if (first_logical != 0xffffffff) {
 443                        size = last_logical + (1 << tic_shift) -
 444                               first_logical;
 445                        print_address_zone(first_logical,
 446                                           first_physical, size, last_attr);
 447                    }
 448                    first_logical = logical;
 449                    first_physical = physical;
 450                }
 451            }
 452        }
 453    }
 454    if (first_logical != logical || (attr & 4) != (last_attr & 4)) {
 455        size = logical + (1 << tic_shift) - first_logical;
 456        print_address_zone(first_logical, first_physical, size, last_attr);
 457    }
 458}
 459
 460#define DUMP_CACHEFLAGS(a) \
 461    switch (a & M68K_DESC_CACHEMODE) { \
 462    case M68K_DESC_CM_WRTHRU: /* cachable, write-through */ \
 463        qemu_printf("T"); \
 464        break; \
 465    case M68K_DESC_CM_COPYBK: /* cachable, copyback */ \
 466        qemu_printf("C"); \
 467        break; \
 468    case M68K_DESC_CM_SERIAL: /* noncachable, serialized */ \
 469        qemu_printf("S"); \
 470        break; \
 471    case M68K_DESC_CM_NCACHE: /* noncachable */ \
 472        qemu_printf("N"); \
 473        break; \
 474    }
 475
 476static void dump_ttr(uint32_t ttr)
 477{
 478    if ((ttr & M68K_TTR_ENABLED) == 0) {
 479        qemu_printf("disabled\n");
 480        return;
 481    }
 482    qemu_printf("Base: 0x%08x Mask: 0x%08x Control: ",
 483                ttr & M68K_TTR_ADDR_BASE,
 484                (ttr & M68K_TTR_ADDR_MASK) << M68K_TTR_ADDR_MASK_SHIFT);
 485    switch (ttr & M68K_TTR_SFIELD) {
 486    case M68K_TTR_SFIELD_USER:
 487        qemu_printf("U");
 488        break;
 489    case M68K_TTR_SFIELD_SUPER:
 490        qemu_printf("S");
 491        break;
 492    default:
 493        qemu_printf("*");
 494        break;
 495    }
 496    DUMP_CACHEFLAGS(ttr);
 497    if (ttr & M68K_DESC_WRITEPROT) {
 498        qemu_printf("R");
 499    } else {
 500        qemu_printf("W");
 501    }
 502    qemu_printf(" U: %d\n", (ttr & M68K_DESC_USERATTR) >>
 503                               M68K_DESC_USERATTR_SHIFT);
 504}
 505
 506void dump_mmu(CPUM68KState *env)
 507{
 508    if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
 509        qemu_printf("Translation disabled\n");
 510        return;
 511    }
 512    qemu_printf("Page Size: ");
 513    if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
 514        qemu_printf("8kB\n");
 515    } else {
 516        qemu_printf("4kB\n");
 517    }
 518
 519    qemu_printf("MMUSR: ");
 520    if (env->mmu.mmusr & M68K_MMU_B_040) {
 521        qemu_printf("BUS ERROR\n");
 522    } else {
 523        qemu_printf("Phy=%08x Flags: ", env->mmu.mmusr & 0xfffff000);
 524        /* flags found on the page descriptor */
 525        if (env->mmu.mmusr & M68K_MMU_G_040) {
 526            qemu_printf("G"); /* Global */
 527        } else {
 528            qemu_printf(".");
 529        }
 530        if (env->mmu.mmusr & M68K_MMU_S_040) {
 531            qemu_printf("S"); /* Supervisor */
 532        } else {
 533            qemu_printf(".");
 534        }
 535        if (env->mmu.mmusr & M68K_MMU_M_040) {
 536            qemu_printf("M"); /* Modified */
 537        } else {
 538            qemu_printf(".");
 539        }
 540        if (env->mmu.mmusr & M68K_MMU_WP_040) {
 541            qemu_printf("W"); /* Write protect */
 542        } else {
 543            qemu_printf(".");
 544        }
 545        if (env->mmu.mmusr & M68K_MMU_T_040) {
 546            qemu_printf("T"); /* Transparent */
 547        } else {
 548            qemu_printf(".");
 549        }
 550        if (env->mmu.mmusr & M68K_MMU_R_040) {
 551            qemu_printf("R"); /* Resident */
 552        } else {
 553            qemu_printf(".");
 554        }
 555        qemu_printf(" Cache: ");
 556        DUMP_CACHEFLAGS(env->mmu.mmusr);
 557        qemu_printf(" U: %d\n", (env->mmu.mmusr >> 8) & 3);
 558        qemu_printf("\n");
 559    }
 560
 561    qemu_printf("ITTR0: ");
 562    dump_ttr(env->mmu.ttr[M68K_ITTR0]);
 563    qemu_printf("ITTR1: ");
 564    dump_ttr(env->mmu.ttr[M68K_ITTR1]);
 565    qemu_printf("DTTR0: ");
 566    dump_ttr(env->mmu.ttr[M68K_DTTR0]);
 567    qemu_printf("DTTR1: ");
 568    dump_ttr(env->mmu.ttr[M68K_DTTR1]);
 569
 570    qemu_printf("SRP: 0x%08x\n", env->mmu.srp);
 571    dump_address_map(env, env->mmu.srp);
 572
 573    qemu_printf("URP: 0x%08x\n", env->mmu.urp);
 574    dump_address_map(env, env->mmu.urp);
 575}
 576
 577static int check_TTR(uint32_t ttr, int *prot, target_ulong addr,
 578                     int access_type)
 579{
 580    uint32_t base, mask;
 581
 582    /* check if transparent translation is enabled */
 583    if ((ttr & M68K_TTR_ENABLED) == 0) {
 584        return 0;
 585    }
 586
 587    /* check mode access */
 588    switch (ttr & M68K_TTR_SFIELD) {
 589    case M68K_TTR_SFIELD_USER:
 590        /* match only if user */
 591        if ((access_type & ACCESS_SUPER) != 0) {
 592            return 0;
 593        }
 594        break;
 595    case M68K_TTR_SFIELD_SUPER:
 596        /* match only if supervisor */
 597        if ((access_type & ACCESS_SUPER) == 0) {
 598            return 0;
 599        }
 600        break;
 601    default:
 602        /* all other values disable mode matching (FC2) */
 603        break;
 604    }
 605
 606    /* check address matching */
 607
 608    base = ttr & M68K_TTR_ADDR_BASE;
 609    mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK;
 610    mask <<= M68K_TTR_ADDR_MASK_SHIFT;
 611
 612    if ((addr & mask) != (base & mask)) {
 613        return 0;
 614    }
 615
 616    *prot = PAGE_READ | PAGE_EXEC;
 617    if ((ttr & M68K_DESC_WRITEPROT) == 0) {
 618        *prot |= PAGE_WRITE;
 619    }
 620
 621    return 1;
 622}
 623
 624static int get_physical_address(CPUM68KState *env, hwaddr *physical,
 625                                int *prot, target_ulong address,
 626                                int access_type, target_ulong *page_size)
 627{
 628    CPUState *cs = env_cpu(env);
 629    uint32_t entry;
 630    uint32_t next;
 631    target_ulong page_mask;
 632    bool debug = access_type & ACCESS_DEBUG;
 633    int page_bits;
 634    int i;
 635    MemTxResult txres;
 636
 637    /* Transparent Translation (physical = logical) */
 638    for (i = 0; i < M68K_MAX_TTR; i++) {
 639        if (check_TTR(env->mmu.TTR(access_type, i),
 640                      prot, address, access_type)) {
 641            if (access_type & ACCESS_PTEST) {
 642                /* Transparent Translation Register bit */
 643                env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040;
 644            }
 645            *physical = address & TARGET_PAGE_MASK;
 646            *page_size = TARGET_PAGE_SIZE;
 647            return 0;
 648        }
 649    }
 650
 651    /* Page Table Root Pointer */
 652    *prot = PAGE_READ | PAGE_WRITE;
 653    if (access_type & ACCESS_CODE) {
 654        *prot |= PAGE_EXEC;
 655    }
 656    if (access_type & ACCESS_SUPER) {
 657        next = env->mmu.srp;
 658    } else {
 659        next = env->mmu.urp;
 660    }
 661
 662    /* Root Index */
 663    entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);
 664
 665    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
 666    if (txres != MEMTX_OK) {
 667        goto txfail;
 668    }
 669    if (!M68K_UDT_VALID(next)) {
 670        return -1;
 671    }
 672    if (!(next & M68K_DESC_USED) && !debug) {
 673        address_space_stl(cs->as, entry, next | M68K_DESC_USED,
 674                          MEMTXATTRS_UNSPECIFIED, &txres);
 675        if (txres != MEMTX_OK) {
 676            goto txfail;
 677        }
 678    }
 679    if (next & M68K_DESC_WRITEPROT) {
 680        if (access_type & ACCESS_PTEST) {
 681            env->mmu.mmusr |= M68K_MMU_WP_040;
 682        }
 683        *prot &= ~PAGE_WRITE;
 684        if (access_type & ACCESS_STORE) {
 685            return -1;
 686        }
 687    }
 688
 689    /* Pointer Index */
 690    entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);
 691
 692    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
 693    if (txres != MEMTX_OK) {
 694        goto txfail;
 695    }
 696    if (!M68K_UDT_VALID(next)) {
 697        return -1;
 698    }
 699    if (!(next & M68K_DESC_USED) && !debug) {
 700        address_space_stl(cs->as, entry, next | M68K_DESC_USED,
 701                          MEMTXATTRS_UNSPECIFIED, &txres);
 702        if (txres != MEMTX_OK) {
 703            goto txfail;
 704        }
 705    }
 706    if (next & M68K_DESC_WRITEPROT) {
 707        if (access_type & ACCESS_PTEST) {
 708            env->mmu.mmusr |= M68K_MMU_WP_040;
 709        }
 710        *prot &= ~PAGE_WRITE;
 711        if (access_type & ACCESS_STORE) {
 712            return -1;
 713        }
 714    }
 715
 716    /* Page Index */
 717    if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
 718        entry = M68K_8K_PAGE_BASE(next) | M68K_8K_PAGE_INDEX(address);
 719    } else {
 720        entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
 721    }
 722
 723    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
 724    if (txres != MEMTX_OK) {
 725        goto txfail;
 726    }
 727
 728    if (!M68K_PDT_VALID(next)) {
 729        return -1;
 730    }
 731    if (M68K_PDT_INDIRECT(next)) {
 732        next = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(next),
 733                                 MEMTXATTRS_UNSPECIFIED, &txres);
 734        if (txres != MEMTX_OK) {
 735            goto txfail;
 736        }
 737    }
 738    if (access_type & ACCESS_STORE) {
 739        if (next & M68K_DESC_WRITEPROT) {
 740            if (!(next & M68K_DESC_USED) && !debug) {
 741                address_space_stl(cs->as, entry, next | M68K_DESC_USED,
 742                                  MEMTXATTRS_UNSPECIFIED, &txres);
 743                if (txres != MEMTX_OK) {
 744                    goto txfail;
 745                }
 746            }
 747        } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
 748                           (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
 749            address_space_stl(cs->as, entry,
 750                              next | (M68K_DESC_MODIFIED | M68K_DESC_USED),
 751                              MEMTXATTRS_UNSPECIFIED, &txres);
 752            if (txres != MEMTX_OK) {
 753                goto txfail;
 754            }
 755        }
 756    } else {
 757        if (!(next & M68K_DESC_USED) && !debug) {
 758            address_space_stl(cs->as, entry, next | M68K_DESC_USED,
 759                              MEMTXATTRS_UNSPECIFIED, &txres);
 760            if (txres != MEMTX_OK) {
 761                goto txfail;
 762            }
 763        }
 764    }
 765
 766    if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
 767        page_bits = 13;
 768    } else {
 769        page_bits = 12;
 770    }
 771    *page_size = 1 << page_bits;
 772    page_mask = ~(*page_size - 1);
 773    *physical = next & page_mask;
 774
 775    if (access_type & ACCESS_PTEST) {
 776        env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040;
 777        env->mmu.mmusr |= *physical & 0xfffff000;
 778        env->mmu.mmusr |= M68K_MMU_R_040;
 779    }
 780
 781    if (next & M68K_DESC_WRITEPROT) {
 782        *prot &= ~PAGE_WRITE;
 783        if (access_type & ACCESS_STORE) {
 784            return -1;
 785        }
 786    }
 787    if (next & M68K_DESC_SUPERONLY) {
 788        if ((access_type & ACCESS_SUPER) == 0) {
 789            return -1;
 790        }
 791    }
 792
 793    return 0;
 794
 795txfail:
 796    /*
 797     * A page table load/store failed. TODO: we should really raise a
 798     * suitable guest fault here if this is not a debug access.
 799     * For now just return that the translation failed.
 800     */
 801    return -1;
 802}
 803
 804hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 805{
 806    M68kCPU *cpu = M68K_CPU(cs);
 807    CPUM68KState *env = &cpu->env;
 808    hwaddr phys_addr;
 809    int prot;
 810    int access_type;
 811    target_ulong page_size;
 812
 813    if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
 814        /* MMU disabled */
 815        return addr;
 816    }
 817
 818    access_type = ACCESS_DATA | ACCESS_DEBUG;
 819    if (env->sr & SR_S) {
 820        access_type |= ACCESS_SUPER;
 821    }
 822    if (get_physical_address(env, &phys_addr, &prot,
 823                             addr, access_type, &page_size) != 0) {
 824        return -1;
 825    }
 826    return phys_addr;
 827}
 828
 829/*
 830 * Notify CPU of a pending interrupt.  Prioritization and vectoring should
 831 * be handled by the interrupt controller.  Real hardware only requests
 832 * the vector when the interrupt is acknowledged by the CPU.  For
 833 * simplicity we calculate it when the interrupt is signalled.
 834 */
 835void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 836{
 837    CPUState *cs = CPU(cpu);
 838    CPUM68KState *env = &cpu->env;
 839
 840    env->pending_level = level;
 841    env->pending_vector = vector;
 842    if (level) {
 843        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 844    } else {
 845        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 846    }
 847}
 848
 849#endif
 850
 851bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 852                       MMUAccessType qemu_access_type, int mmu_idx,
 853                       bool probe, uintptr_t retaddr)
 854{
 855    M68kCPU *cpu = M68K_CPU(cs);
 856    CPUM68KState *env = &cpu->env;
 857
 858#ifndef CONFIG_USER_ONLY
 859    hwaddr physical;
 860    int prot;
 861    int access_type;
 862    int ret;
 863    target_ulong page_size;
 864
 865    if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
 866        /* MMU disabled */
 867        tlb_set_page(cs, address & TARGET_PAGE_MASK,
 868                     address & TARGET_PAGE_MASK,
 869                     PAGE_READ | PAGE_WRITE | PAGE_EXEC,
 870                     mmu_idx, TARGET_PAGE_SIZE);
 871        return true;
 872    }
 873
 874    if (qemu_access_type == MMU_INST_FETCH) {
 875        access_type = ACCESS_CODE;
 876    } else {
 877        access_type = ACCESS_DATA;
 878        if (qemu_access_type == MMU_DATA_STORE) {
 879            access_type |= ACCESS_STORE;
 880        }
 881    }
 882    if (mmu_idx != MMU_USER_IDX) {
 883        access_type |= ACCESS_SUPER;
 884    }
 885
 886    ret = get_physical_address(&cpu->env, &physical, &prot,
 887                               address, access_type, &page_size);
 888    if (likely(ret == 0)) {
 889        address &= TARGET_PAGE_MASK;
 890        physical += address & (page_size - 1);
 891        tlb_set_page(cs, address, physical,
 892                     prot, mmu_idx, TARGET_PAGE_SIZE);
 893        return true;
 894    }
 895
 896    if (probe) {
 897        return false;
 898    }
 899
 900    /* page fault */
 901    env->mmu.ssw = M68K_ATC_040;
 902    switch (size) {
 903    case 1:
 904        env->mmu.ssw |= M68K_BA_SIZE_BYTE;
 905        break;
 906    case 2:
 907        env->mmu.ssw |= M68K_BA_SIZE_WORD;
 908        break;
 909    case 4:
 910        env->mmu.ssw |= M68K_BA_SIZE_LONG;
 911        break;
 912    }
 913    if (access_type & ACCESS_SUPER) {
 914        env->mmu.ssw |= M68K_TM_040_SUPER;
 915    }
 916    if (access_type & ACCESS_CODE) {
 917        env->mmu.ssw |= M68K_TM_040_CODE;
 918    } else {
 919        env->mmu.ssw |= M68K_TM_040_DATA;
 920    }
 921    if (!(access_type & ACCESS_STORE)) {
 922        env->mmu.ssw |= M68K_RW_040;
 923    }
 924#endif
 925
 926    cs->exception_index = EXCP_ACCESS;
 927    env->mmu.ar = address;
 928    cpu_loop_exit_restore(cs, retaddr);
 929}
 930
 931uint32_t HELPER(bitrev)(uint32_t x)
 932{
 933    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
 934    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
 935    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
 936    return bswap32(x);
 937}
 938
 939uint32_t HELPER(ff1)(uint32_t x)
 940{
 941    int n;
 942    for (n = 32; x; n--)
 943        x >>= 1;
 944    return n;
 945}
 946
 947uint32_t HELPER(sats)(uint32_t val, uint32_t v)
 948{
 949    /* The result has the opposite sign to the original value.  */
 950    if ((int32_t)v < 0) {
 951        val = (((int32_t)val) >> 31) ^ SIGNBIT;
 952    }
 953    return val;
 954}
 955
 956void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
 957{
 958    env->sr = sr & 0xffe0;
 959    cpu_m68k_set_ccr(env, sr);
 960    m68k_switch_sp(env);
 961}
 962
 963void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 964{
 965    cpu_m68k_set_sr(env, val);
 966}
 967
 968/* MAC unit.  */
 969/*
 970 * FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
 971 * take values,  others take register numbers and manipulate the contents
 972 * in-place.
 973 */
 974void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
 975{
 976    uint32_t mask;
 977    env->macc[dest] = env->macc[src];
 978    mask = MACSR_PAV0 << dest;
 979    if (env->macsr & (MACSR_PAV0 << src))
 980        env->macsr |= mask;
 981    else
 982        env->macsr &= ~mask;
 983}
 984
 985uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 986{
 987    int64_t product;
 988    int64_t res;
 989
 990    product = (uint64_t)op1 * op2;
 991    res = (product << 24) >> 24;
 992    if (res != product) {
 993        env->macsr |= MACSR_V;
 994        if (env->macsr & MACSR_OMC) {
 995            /* Make sure the accumulate operation overflows.  */
 996            if (product < 0)
 997                res = ~(1ll << 50);
 998            else
 999                res = 1ll << 50;
1000        }
1001    }
1002    return res;
1003}
1004
1005uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
1006{
1007    uint64_t product;
1008
1009    product = (uint64_t)op1 * op2;
1010    if (product & (0xffffffull << 40)) {
1011        env->macsr |= MACSR_V;
1012        if (env->macsr & MACSR_OMC) {
1013            /* Make sure the accumulate operation overflows.  */
1014            product = 1ll << 50;
1015        } else {
1016            product &= ((1ull << 40) - 1);
1017        }
1018    }
1019    return product;
1020}
1021
1022uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
1023{
1024    uint64_t product;
1025    uint32_t remainder;
1026
1027    product = (uint64_t)op1 * op2;
1028    if (env->macsr & MACSR_RT) {
1029        remainder = product & 0xffffff;
1030        product >>= 24;
1031        if (remainder > 0x800000)
1032            product++;
1033        else if (remainder == 0x800000)
1034            product += (product & 1);
1035    } else {
1036        product >>= 24;
1037    }
1038    return product;
1039}
1040
1041void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
1042{
1043    int64_t tmp;
1044    int64_t result;
1045    tmp = env->macc[acc];
1046    result = ((tmp << 16) >> 16);
1047    if (result != tmp) {
1048        env->macsr |= MACSR_V;
1049    }
1050    if (env->macsr & MACSR_V) {
1051        env->macsr |= MACSR_PAV0 << acc;
1052        if (env->macsr & MACSR_OMC) {
1053            /*
1054             * The result is saturated to 32 bits, despite overflow occurring
1055             * at 48 bits.  Seems weird, but that's what the hardware docs
1056             * say.
1057             */
1058            result = (result >> 63) ^ 0x7fffffff;
1059        }
1060    }
1061    env->macc[acc] = result;
1062}
1063
1064void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
1065{
1066    uint64_t val;
1067
1068    val = env->macc[acc];
1069    if (val & (0xffffull << 48)) {
1070        env->macsr |= MACSR_V;
1071    }
1072    if (env->macsr & MACSR_V) {
1073        env->macsr |= MACSR_PAV0 << acc;
1074        if (env->macsr & MACSR_OMC) {
1075            if (val > (1ull << 53))
1076                val = 0;
1077            else
1078                val = (1ull << 48) - 1;
1079        } else {
1080            val &= ((1ull << 48) - 1);
1081        }
1082    }
1083    env->macc[acc] = val;
1084}
1085
1086void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
1087{
1088    int64_t sum;
1089    int64_t result;
1090
1091    sum = env->macc[acc];
1092    result = (sum << 16) >> 16;
1093    if (result != sum) {
1094        env->macsr |= MACSR_V;
1095    }
1096    if (env->macsr & MACSR_V) {
1097        env->macsr |= MACSR_PAV0 << acc;
1098        if (env->macsr & MACSR_OMC) {
1099            result = (result >> 63) ^ 0x7fffffffffffll;
1100        }
1101    }
1102    env->macc[acc] = result;
1103}
1104
1105void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
1106{
1107    uint64_t val;
1108    val = env->macc[acc];
1109    if (val == 0) {
1110        env->macsr |= MACSR_Z;
1111    } else if (val & (1ull << 47)) {
1112        env->macsr |= MACSR_N;
1113    }
1114    if (env->macsr & (MACSR_PAV0 << acc)) {
1115        env->macsr |= MACSR_V;
1116    }
1117    if (env->macsr & MACSR_FI) {
1118        val = ((int64_t)val) >> 40;
1119        if (val != 0 && val != -1)
1120            env->macsr |= MACSR_EV;
1121    } else if (env->macsr & MACSR_SU) {
1122        val = ((int64_t)val) >> 32;
1123        if (val != 0 && val != -1)
1124            env->macsr |= MACSR_EV;
1125    } else {
1126        if ((val >> 32) != 0)
1127            env->macsr |= MACSR_EV;
1128    }
1129}
1130
1131#define EXTSIGN(val, index) (     \
1132    (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1133)
1134
1135#define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
1136    switch (op) {                                                          \
1137    case CC_OP_FLAGS:                                                      \
1138        /* Everything in place.  */                                        \
1139        break;                                                             \
1140    case CC_OP_ADDB:                                                       \
1141    case CC_OP_ADDW:                                                       \
1142    case CC_OP_ADDL:                                                       \
1143        res = n;                                                           \
1144        src2 = v;                                                          \
1145        src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
1146        c = x;                                                             \
1147        z = n;                                                             \
1148        v = (res ^ src1) & ~(src1 ^ src2);                                 \
1149        break;                                                             \
1150    case CC_OP_SUBB:                                                       \
1151    case CC_OP_SUBW:                                                       \
1152    case CC_OP_SUBL:                                                       \
1153        res = n;                                                           \
1154        src2 = v;                                                          \
1155        src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
1156        c = x;                                                             \
1157        z = n;                                                             \
1158        v = (res ^ src1) & (src1 ^ src2);                                  \
1159        break;                                                             \
1160    case CC_OP_CMPB:                                                       \
1161    case CC_OP_CMPW:                                                       \
1162    case CC_OP_CMPL:                                                       \
1163        src1 = n;                                                          \
1164        src2 = v;                                                          \
1165        res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
1166        n = res;                                                           \
1167        z = res;                                                           \
1168        c = src1 < src2;                                                   \
1169        v = (res ^ src1) & (src1 ^ src2);                                  \
1170        break;                                                             \
1171    case CC_OP_LOGIC:                                                      \
1172        c = v = 0;                                                         \
1173        z = n;                                                             \
1174        break;                                                             \
1175    default:                                                               \
1176        cpu_abort(env_cpu(env), "Bad CC_OP %d", op);                       \
1177    }                                                                      \
1178} while (0)
1179
1180uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
1181{
1182    uint32_t x, c, n, z, v;
1183    uint32_t res, src1, src2;
1184
1185    x = env->cc_x;
1186    n = env->cc_n;
1187    z = env->cc_z;
1188    v = env->cc_v;
1189    c = env->cc_c;
1190
1191    COMPUTE_CCR(env->cc_op, x, n, z, v, c);
1192
1193    n = n >> 31;
1194    z = (z == 0);
1195    v = v >> 31;
1196
1197    return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
1198}
1199
1200uint32_t HELPER(get_ccr)(CPUM68KState *env)
1201{
1202    return cpu_m68k_get_ccr(env);
1203}
1204
1205void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
1206{
1207    env->cc_x = (ccr & CCF_X ? 1 : 0);
1208    env->cc_n = (ccr & CCF_N ? -1 : 0);
1209    env->cc_z = (ccr & CCF_Z ? 0 : 1);
1210    env->cc_v = (ccr & CCF_V ? -1 : 0);
1211    env->cc_c = (ccr & CCF_C ? 1 : 0);
1212    env->cc_op = CC_OP_FLAGS;
1213}
1214
1215void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
1216{
1217    cpu_m68k_set_ccr(env, ccr);
1218}
1219
1220void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
1221{
1222    uint32_t res, src1, src2;
1223
1224    COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
1225    env->cc_op = CC_OP_FLAGS;
1226}
1227
1228uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
1229{
1230    int rem;
1231    uint32_t result;
1232
1233    if (env->macsr & MACSR_SU) {
1234        /* 16-bit rounding.  */
1235        rem = val & 0xffffff;
1236        val = (val >> 24) & 0xffffu;
1237        if (rem > 0x800000)
1238            val++;
1239        else if (rem == 0x800000)
1240            val += (val & 1);
1241    } else if (env->macsr & MACSR_RT) {
1242        /* 32-bit rounding.  */
1243        rem = val & 0xff;
1244        val >>= 8;
1245        if (rem > 0x80)
1246            val++;
1247        else if (rem == 0x80)
1248            val += (val & 1);
1249    } else {
1250        /* No rounding.  */
1251        val >>= 8;
1252    }
1253    if (env->macsr & MACSR_OMC) {
1254        /* Saturate.  */
1255        if (env->macsr & MACSR_SU) {
1256            if (val != (uint16_t) val) {
1257                result = ((val >> 63) ^ 0x7fff) & 0xffff;
1258            } else {
1259                result = val & 0xffff;
1260            }
1261        } else {
1262            if (val != (uint32_t)val) {
1263                result = ((uint32_t)(val >> 63) & 0x7fffffff);
1264            } else {
1265                result = (uint32_t)val;
1266            }
1267        }
1268    } else {
1269        /* No saturation.  */
1270        if (env->macsr & MACSR_SU) {
1271            result = val & 0xffff;
1272        } else {
1273            result = (uint32_t)val;
1274        }
1275    }
1276    return result;
1277}
1278
1279uint32_t HELPER(get_macs)(uint64_t val)
1280{
1281    if (val == (int32_t)val) {
1282        return (int32_t)val;
1283    } else {
1284        return (val >> 61) ^ ~SIGNBIT;
1285    }
1286}
1287
1288uint32_t HELPER(get_macu)(uint64_t val)
1289{
1290    if ((val >> 32) == 0) {
1291        return (uint32_t)val;
1292    } else {
1293        return 0xffffffffu;
1294    }
1295}
1296
1297uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
1298{
1299    uint32_t val;
1300    val = env->macc[acc] & 0x00ff;
1301    val |= (env->macc[acc] >> 32) & 0xff00;
1302    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
1303    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
1304    return val;
1305}
1306
1307uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
1308{
1309    uint32_t val;
1310    val = (env->macc[acc] >> 32) & 0xffff;
1311    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
1312    return val;
1313}
1314
1315void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
1316{
1317    int64_t res;
1318    int32_t tmp;
1319    res = env->macc[acc] & 0xffffffff00ull;
1320    tmp = (int16_t)(val & 0xff00);
1321    res |= ((int64_t)tmp) << 32;
1322    res |= val & 0xff;
1323    env->macc[acc] = res;
1324    res = env->macc[acc + 1] & 0xffffffff00ull;
1325    tmp = (val & 0xff000000);
1326    res |= ((int64_t)tmp) << 16;
1327    res |= (val >> 16) & 0xff;
1328    env->macc[acc + 1] = res;
1329}
1330
1331void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
1332{
1333    int64_t res;
1334    int32_t tmp;
1335    res = (uint32_t)env->macc[acc];
1336    tmp = (int16_t)val;
1337    res |= ((int64_t)tmp) << 32;
1338    env->macc[acc] = res;
1339    res = (uint32_t)env->macc[acc + 1];
1340    tmp = val & 0xffff0000;
1341    res |= (int64_t)tmp << 16;
1342    env->macc[acc + 1] = res;
1343}
1344
1345void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
1346{
1347    uint64_t res;
1348    res = (uint32_t)env->macc[acc];
1349    res |= ((uint64_t)(val & 0xffff)) << 32;
1350    env->macc[acc] = res;
1351    res = (uint32_t)env->macc[acc + 1];
1352    res |= (uint64_t)(val & 0xffff0000) << 16;
1353    env->macc[acc + 1] = res;
1354}
1355
1356#if defined(CONFIG_SOFTMMU)
1357void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read)
1358{
1359    hwaddr physical;
1360    int access_type;
1361    int prot;
1362    int ret;
1363    target_ulong page_size;
1364
1365    access_type = ACCESS_PTEST;
1366    if (env->dfc & 4) {
1367        access_type |= ACCESS_SUPER;
1368    }
1369    if ((env->dfc & 3) == 2) {
1370        access_type |= ACCESS_CODE;
1371    }
1372    if (!is_read) {
1373        access_type |= ACCESS_STORE;
1374    }
1375
1376    env->mmu.mmusr = 0;
1377    env->mmu.ssw = 0;
1378    ret = get_physical_address(env, &physical, &prot, addr,
1379                               access_type, &page_size);
1380    if (ret == 0) {
1381        addr &= TARGET_PAGE_MASK;
1382        physical += addr & (page_size - 1);
1383        tlb_set_page(env_cpu(env), addr, physical,
1384                     prot, access_type & ACCESS_SUPER ?
1385                     MMU_KERNEL_IDX : MMU_USER_IDX, page_size);
1386    }
1387}
1388
1389void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode)
1390{
1391    CPUState *cs = env_cpu(env);
1392
1393    switch (opmode) {
1394    case 0: /* Flush page entry if not global */
1395    case 1: /* Flush page entry */
1396        tlb_flush_page(cs, addr);
1397        break;
1398    case 2: /* Flush all except global entries */
1399        tlb_flush(cs);
1400        break;
1401    case 3: /* Flush all entries */
1402        tlb_flush(cs);
1403        break;
1404    }
1405}
1406
1407void HELPER(reset)(CPUM68KState *env)
1408{
1409    /* FIXME: reset all except CPU */
1410}
1411#endif
1412