cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

helper.c (45097B)


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