qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

helper.c (45085B)


      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". */
     32 static 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 
     49 static 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 
     61 void 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 
     71 static 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 
     88 static 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 
    108 static 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 
    127 static 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 
    147 void 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 
    162 void 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 
    186 static 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 
    194 void 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 
    319 uint32_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 
    424 void 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 
    458 void 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_M68K)) {
    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 
    485 static 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 
    506 static 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 
    606 static 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 
    636 void 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 
    707 static 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 
    754 static 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 
    925 txfail:
    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 
    934 hwaddr 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  */
    967 void 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 bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
    982                        MMUAccessType qemu_access_type, int mmu_idx,
    983                        bool probe, uintptr_t retaddr)
    984 {
    985     M68kCPU *cpu = M68K_CPU(cs);
    986     CPUM68KState *env = &cpu->env;
    987     hwaddr physical;
    988     int prot;
    989     int access_type;
    990     int ret;
    991     target_ulong page_size;
    992 
    993     if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
    994         /* MMU disabled */
    995         tlb_set_page(cs, address & TARGET_PAGE_MASK,
    996                      address & TARGET_PAGE_MASK,
    997                      PAGE_READ | PAGE_WRITE | PAGE_EXEC,
    998                      mmu_idx, TARGET_PAGE_SIZE);
    999         return true;
   1000     }
   1001 
   1002     if (qemu_access_type == MMU_INST_FETCH) {
   1003         access_type = ACCESS_CODE;
   1004     } else {
   1005         access_type = ACCESS_DATA;
   1006         if (qemu_access_type == MMU_DATA_STORE) {
   1007             access_type |= ACCESS_STORE;
   1008         }
   1009     }
   1010     if (mmu_idx != MMU_USER_IDX) {
   1011         access_type |= ACCESS_SUPER;
   1012     }
   1013 
   1014     ret = get_physical_address(&cpu->env, &physical, &prot,
   1015                                address, access_type, &page_size);
   1016     if (likely(ret == 0)) {
   1017         tlb_set_page(cs, address & TARGET_PAGE_MASK,
   1018                      physical & TARGET_PAGE_MASK, prot, mmu_idx, page_size);
   1019         return true;
   1020     }
   1021 
   1022     if (probe) {
   1023         return false;
   1024     }
   1025 
   1026     /* page fault */
   1027     env->mmu.ssw = M68K_ATC_040;
   1028     switch (size) {
   1029     case 1:
   1030         env->mmu.ssw |= M68K_BA_SIZE_BYTE;
   1031         break;
   1032     case 2:
   1033         env->mmu.ssw |= M68K_BA_SIZE_WORD;
   1034         break;
   1035     case 4:
   1036         env->mmu.ssw |= M68K_BA_SIZE_LONG;
   1037         break;
   1038     }
   1039     if (access_type & ACCESS_SUPER) {
   1040         env->mmu.ssw |= M68K_TM_040_SUPER;
   1041     }
   1042     if (access_type & ACCESS_CODE) {
   1043         env->mmu.ssw |= M68K_TM_040_CODE;
   1044     } else {
   1045         env->mmu.ssw |= M68K_TM_040_DATA;
   1046     }
   1047     if (!(access_type & ACCESS_STORE)) {
   1048         env->mmu.ssw |= M68K_RW_040;
   1049     }
   1050 
   1051     cs->exception_index = EXCP_ACCESS;
   1052     env->mmu.ar = address;
   1053     cpu_loop_exit_restore(cs, retaddr);
   1054 }
   1055 #endif /* !CONFIG_USER_ONLY */
   1056 
   1057 uint32_t HELPER(bitrev)(uint32_t x)
   1058 {
   1059     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
   1060     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
   1061     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
   1062     return bswap32(x);
   1063 }
   1064 
   1065 uint32_t HELPER(ff1)(uint32_t x)
   1066 {
   1067     int n;
   1068     for (n = 32; x; n--)
   1069         x >>= 1;
   1070     return n;
   1071 }
   1072 
   1073 uint32_t HELPER(sats)(uint32_t val, uint32_t v)
   1074 {
   1075     /* The result has the opposite sign to the original value.  */
   1076     if ((int32_t)v < 0) {
   1077         val = (((int32_t)val) >> 31) ^ SIGNBIT;
   1078     }
   1079     return val;
   1080 }
   1081 
   1082 void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
   1083 {
   1084     env->sr = sr & 0xffe0;
   1085     cpu_m68k_set_ccr(env, sr);
   1086     m68k_switch_sp(env);
   1087 }
   1088 
   1089 void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
   1090 {
   1091     cpu_m68k_set_sr(env, val);
   1092 }
   1093 
   1094 /* MAC unit.  */
   1095 /*
   1096  * FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
   1097  * take values,  others take register numbers and manipulate the contents
   1098  * in-place.
   1099  */
   1100 void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
   1101 {
   1102     uint32_t mask;
   1103     env->macc[dest] = env->macc[src];
   1104     mask = MACSR_PAV0 << dest;
   1105     if (env->macsr & (MACSR_PAV0 << src))
   1106         env->macsr |= mask;
   1107     else
   1108         env->macsr &= ~mask;
   1109 }
   1110 
   1111 uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
   1112 {
   1113     int64_t product;
   1114     int64_t res;
   1115 
   1116     product = (uint64_t)op1 * op2;
   1117     res = (product << 24) >> 24;
   1118     if (res != product) {
   1119         env->macsr |= MACSR_V;
   1120         if (env->macsr & MACSR_OMC) {
   1121             /* Make sure the accumulate operation overflows.  */
   1122             if (product < 0)
   1123                 res = ~(1ll << 50);
   1124             else
   1125                 res = 1ll << 50;
   1126         }
   1127     }
   1128     return res;
   1129 }
   1130 
   1131 uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
   1132 {
   1133     uint64_t product;
   1134 
   1135     product = (uint64_t)op1 * op2;
   1136     if (product & (0xffffffull << 40)) {
   1137         env->macsr |= MACSR_V;
   1138         if (env->macsr & MACSR_OMC) {
   1139             /* Make sure the accumulate operation overflows.  */
   1140             product = 1ll << 50;
   1141         } else {
   1142             product &= ((1ull << 40) - 1);
   1143         }
   1144     }
   1145     return product;
   1146 }
   1147 
   1148 uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
   1149 {
   1150     uint64_t product;
   1151     uint32_t remainder;
   1152 
   1153     product = (uint64_t)op1 * op2;
   1154     if (env->macsr & MACSR_RT) {
   1155         remainder = product & 0xffffff;
   1156         product >>= 24;
   1157         if (remainder > 0x800000)
   1158             product++;
   1159         else if (remainder == 0x800000)
   1160             product += (product & 1);
   1161     } else {
   1162         product >>= 24;
   1163     }
   1164     return product;
   1165 }
   1166 
   1167 void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
   1168 {
   1169     int64_t tmp;
   1170     int64_t result;
   1171     tmp = env->macc[acc];
   1172     result = ((tmp << 16) >> 16);
   1173     if (result != tmp) {
   1174         env->macsr |= MACSR_V;
   1175     }
   1176     if (env->macsr & MACSR_V) {
   1177         env->macsr |= MACSR_PAV0 << acc;
   1178         if (env->macsr & MACSR_OMC) {
   1179             /*
   1180              * The result is saturated to 32 bits, despite overflow occurring
   1181              * at 48 bits.  Seems weird, but that's what the hardware docs
   1182              * say.
   1183              */
   1184             result = (result >> 63) ^ 0x7fffffff;
   1185         }
   1186     }
   1187     env->macc[acc] = result;
   1188 }
   1189 
   1190 void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
   1191 {
   1192     uint64_t val;
   1193 
   1194     val = env->macc[acc];
   1195     if (val & (0xffffull << 48)) {
   1196         env->macsr |= MACSR_V;
   1197     }
   1198     if (env->macsr & MACSR_V) {
   1199         env->macsr |= MACSR_PAV0 << acc;
   1200         if (env->macsr & MACSR_OMC) {
   1201             if (val > (1ull << 53))
   1202                 val = 0;
   1203             else
   1204                 val = (1ull << 48) - 1;
   1205         } else {
   1206             val &= ((1ull << 48) - 1);
   1207         }
   1208     }
   1209     env->macc[acc] = val;
   1210 }
   1211 
   1212 void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
   1213 {
   1214     int64_t sum;
   1215     int64_t result;
   1216 
   1217     sum = env->macc[acc];
   1218     result = (sum << 16) >> 16;
   1219     if (result != sum) {
   1220         env->macsr |= MACSR_V;
   1221     }
   1222     if (env->macsr & MACSR_V) {
   1223         env->macsr |= MACSR_PAV0 << acc;
   1224         if (env->macsr & MACSR_OMC) {
   1225             result = (result >> 63) ^ 0x7fffffffffffll;
   1226         }
   1227     }
   1228     env->macc[acc] = result;
   1229 }
   1230 
   1231 void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
   1232 {
   1233     uint64_t val;
   1234     val = env->macc[acc];
   1235     if (val == 0) {
   1236         env->macsr |= MACSR_Z;
   1237     } else if (val & (1ull << 47)) {
   1238         env->macsr |= MACSR_N;
   1239     }
   1240     if (env->macsr & (MACSR_PAV0 << acc)) {
   1241         env->macsr |= MACSR_V;
   1242     }
   1243     if (env->macsr & MACSR_FI) {
   1244         val = ((int64_t)val) >> 40;
   1245         if (val != 0 && val != -1)
   1246             env->macsr |= MACSR_EV;
   1247     } else if (env->macsr & MACSR_SU) {
   1248         val = ((int64_t)val) >> 32;
   1249         if (val != 0 && val != -1)
   1250             env->macsr |= MACSR_EV;
   1251     } else {
   1252         if ((val >> 32) != 0)
   1253             env->macsr |= MACSR_EV;
   1254     }
   1255 }
   1256 
   1257 #define EXTSIGN(val, index) (     \
   1258     (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
   1259 )
   1260 
   1261 #define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
   1262     switch (op) {                                                          \
   1263     case CC_OP_FLAGS:                                                      \
   1264         /* Everything in place.  */                                        \
   1265         break;                                                             \
   1266     case CC_OP_ADDB:                                                       \
   1267     case CC_OP_ADDW:                                                       \
   1268     case CC_OP_ADDL:                                                       \
   1269         res = n;                                                           \
   1270         src2 = v;                                                          \
   1271         src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
   1272         c = x;                                                             \
   1273         z = n;                                                             \
   1274         v = (res ^ src1) & ~(src1 ^ src2);                                 \
   1275         break;                                                             \
   1276     case CC_OP_SUBB:                                                       \
   1277     case CC_OP_SUBW:                                                       \
   1278     case CC_OP_SUBL:                                                       \
   1279         res = n;                                                           \
   1280         src2 = v;                                                          \
   1281         src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
   1282         c = x;                                                             \
   1283         z = n;                                                             \
   1284         v = (res ^ src1) & (src1 ^ src2);                                  \
   1285         break;                                                             \
   1286     case CC_OP_CMPB:                                                       \
   1287     case CC_OP_CMPW:                                                       \
   1288     case CC_OP_CMPL:                                                       \
   1289         src1 = n;                                                          \
   1290         src2 = v;                                                          \
   1291         res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
   1292         n = res;                                                           \
   1293         z = res;                                                           \
   1294         c = src1 < src2;                                                   \
   1295         v = (res ^ src1) & (src1 ^ src2);                                  \
   1296         break;                                                             \
   1297     case CC_OP_LOGIC:                                                      \
   1298         c = v = 0;                                                         \
   1299         z = n;                                                             \
   1300         break;                                                             \
   1301     default:                                                               \
   1302         cpu_abort(env_cpu(env), "Bad CC_OP %d", op);                       \
   1303     }                                                                      \
   1304 } while (0)
   1305 
   1306 uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
   1307 {
   1308     uint32_t x, c, n, z, v;
   1309     uint32_t res, src1, src2;
   1310 
   1311     x = env->cc_x;
   1312     n = env->cc_n;
   1313     z = env->cc_z;
   1314     v = env->cc_v;
   1315     c = env->cc_c;
   1316 
   1317     COMPUTE_CCR(env->cc_op, x, n, z, v, c);
   1318 
   1319     n = n >> 31;
   1320     z = (z == 0);
   1321     v = v >> 31;
   1322 
   1323     return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
   1324 }
   1325 
   1326 uint32_t HELPER(get_ccr)(CPUM68KState *env)
   1327 {
   1328     return cpu_m68k_get_ccr(env);
   1329 }
   1330 
   1331 void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
   1332 {
   1333     env->cc_x = (ccr & CCF_X ? 1 : 0);
   1334     env->cc_n = (ccr & CCF_N ? -1 : 0);
   1335     env->cc_z = (ccr & CCF_Z ? 0 : 1);
   1336     env->cc_v = (ccr & CCF_V ? -1 : 0);
   1337     env->cc_c = (ccr & CCF_C ? 1 : 0);
   1338     env->cc_op = CC_OP_FLAGS;
   1339 }
   1340 
   1341 void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
   1342 {
   1343     cpu_m68k_set_ccr(env, ccr);
   1344 }
   1345 
   1346 void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
   1347 {
   1348     uint32_t res, src1, src2;
   1349 
   1350     COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
   1351     env->cc_op = CC_OP_FLAGS;
   1352 }
   1353 
   1354 uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
   1355 {
   1356     int rem;
   1357     uint32_t result;
   1358 
   1359     if (env->macsr & MACSR_SU) {
   1360         /* 16-bit rounding.  */
   1361         rem = val & 0xffffff;
   1362         val = (val >> 24) & 0xffffu;
   1363         if (rem > 0x800000)
   1364             val++;
   1365         else if (rem == 0x800000)
   1366             val += (val & 1);
   1367     } else if (env->macsr & MACSR_RT) {
   1368         /* 32-bit rounding.  */
   1369         rem = val & 0xff;
   1370         val >>= 8;
   1371         if (rem > 0x80)
   1372             val++;
   1373         else if (rem == 0x80)
   1374             val += (val & 1);
   1375     } else {
   1376         /* No rounding.  */
   1377         val >>= 8;
   1378     }
   1379     if (env->macsr & MACSR_OMC) {
   1380         /* Saturate.  */
   1381         if (env->macsr & MACSR_SU) {
   1382             if (val != (uint16_t) val) {
   1383                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
   1384             } else {
   1385                 result = val & 0xffff;
   1386             }
   1387         } else {
   1388             if (val != (uint32_t)val) {
   1389                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
   1390             } else {
   1391                 result = (uint32_t)val;
   1392             }
   1393         }
   1394     } else {
   1395         /* No saturation.  */
   1396         if (env->macsr & MACSR_SU) {
   1397             result = val & 0xffff;
   1398         } else {
   1399             result = (uint32_t)val;
   1400         }
   1401     }
   1402     return result;
   1403 }
   1404 
   1405 uint32_t HELPER(get_macs)(uint64_t val)
   1406 {
   1407     if (val == (int32_t)val) {
   1408         return (int32_t)val;
   1409     } else {
   1410         return (val >> 61) ^ ~SIGNBIT;
   1411     }
   1412 }
   1413 
   1414 uint32_t HELPER(get_macu)(uint64_t val)
   1415 {
   1416     if ((val >> 32) == 0) {
   1417         return (uint32_t)val;
   1418     } else {
   1419         return 0xffffffffu;
   1420     }
   1421 }
   1422 
   1423 uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
   1424 {
   1425     uint32_t val;
   1426     val = env->macc[acc] & 0x00ff;
   1427     val |= (env->macc[acc] >> 32) & 0xff00;
   1428     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
   1429     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
   1430     return val;
   1431 }
   1432 
   1433 uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
   1434 {
   1435     uint32_t val;
   1436     val = (env->macc[acc] >> 32) & 0xffff;
   1437     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
   1438     return val;
   1439 }
   1440 
   1441 void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
   1442 {
   1443     int64_t res;
   1444     int32_t tmp;
   1445     res = env->macc[acc] & 0xffffffff00ull;
   1446     tmp = (int16_t)(val & 0xff00);
   1447     res |= ((int64_t)tmp) << 32;
   1448     res |= val & 0xff;
   1449     env->macc[acc] = res;
   1450     res = env->macc[acc + 1] & 0xffffffff00ull;
   1451     tmp = (val & 0xff000000);
   1452     res |= ((int64_t)tmp) << 16;
   1453     res |= (val >> 16) & 0xff;
   1454     env->macc[acc + 1] = res;
   1455 }
   1456 
   1457 void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
   1458 {
   1459     int64_t res;
   1460     int32_t tmp;
   1461     res = (uint32_t)env->macc[acc];
   1462     tmp = (int16_t)val;
   1463     res |= ((int64_t)tmp) << 32;
   1464     env->macc[acc] = res;
   1465     res = (uint32_t)env->macc[acc + 1];
   1466     tmp = val & 0xffff0000;
   1467     res |= (int64_t)tmp << 16;
   1468     env->macc[acc + 1] = res;
   1469 }
   1470 
   1471 void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
   1472 {
   1473     uint64_t res;
   1474     res = (uint32_t)env->macc[acc];
   1475     res |= ((uint64_t)(val & 0xffff)) << 32;
   1476     env->macc[acc] = res;
   1477     res = (uint32_t)env->macc[acc + 1];
   1478     res |= (uint64_t)(val & 0xffff0000) << 16;
   1479     env->macc[acc + 1] = res;
   1480 }
   1481 
   1482 #if defined(CONFIG_SOFTMMU)
   1483 void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read)
   1484 {
   1485     hwaddr physical;
   1486     int access_type;
   1487     int prot;
   1488     int ret;
   1489     target_ulong page_size;
   1490 
   1491     access_type = ACCESS_PTEST;
   1492     if (env->dfc & 4) {
   1493         access_type |= ACCESS_SUPER;
   1494     }
   1495     if ((env->dfc & 3) == 2) {
   1496         access_type |= ACCESS_CODE;
   1497     }
   1498     if (!is_read) {
   1499         access_type |= ACCESS_STORE;
   1500     }
   1501 
   1502     env->mmu.mmusr = 0;
   1503     env->mmu.ssw = 0;
   1504     ret = get_physical_address(env, &physical, &prot, addr,
   1505                                access_type, &page_size);
   1506     if (ret == 0) {
   1507         tlb_set_page(env_cpu(env), addr & TARGET_PAGE_MASK,
   1508                      physical & TARGET_PAGE_MASK,
   1509                      prot, access_type & ACCESS_SUPER ?
   1510                      MMU_KERNEL_IDX : MMU_USER_IDX, page_size);
   1511     }
   1512 }
   1513 
   1514 void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode)
   1515 {
   1516     CPUState *cs = env_cpu(env);
   1517 
   1518     switch (opmode) {
   1519     case 0: /* Flush page entry if not global */
   1520     case 1: /* Flush page entry */
   1521         tlb_flush_page(cs, addr);
   1522         break;
   1523     case 2: /* Flush all except global entries */
   1524         tlb_flush(cs);
   1525         break;
   1526     case 3: /* Flush all entries */
   1527         tlb_flush(cs);
   1528         break;
   1529     }
   1530 }
   1531 
   1532 void HELPER(reset)(CPUM68KState *env)
   1533 {
   1534     /* FIXME: reset all except CPU */
   1535 }
   1536 #endif