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