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