qemu/target-m68k/helper.c
<<
>>
Prefs
   1/*
   2 *  m68k op helpers
   3 *
   4 *  Copyright (c) 2006-2007 CodeSourcery
   5 *  Written by Paul Brook
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include <stdio.h>
  22#include <string.h>
  23
  24#include "config.h"
  25#include "cpu.h"
  26#include "exec-all.h"
  27#include "qemu-common.h"
  28#include "gdbstub.h"
  29
  30#include "helpers.h"
  31
  32#define SIGNBIT (1u << 31)
  33
  34enum m68k_cpuid {
  35    M68K_CPUID_M5206,
  36    M68K_CPUID_M5208,
  37    M68K_CPUID_CFV4E,
  38    M68K_CPUID_ANY,
  39};
  40
  41typedef struct m68k_def_t m68k_def_t;
  42
  43struct m68k_def_t {
  44    const char * name;
  45    enum m68k_cpuid id;
  46};
  47
  48static m68k_def_t m68k_cpu_defs[] = {
  49    {"m5206", M68K_CPUID_M5206},
  50    {"m5208", M68K_CPUID_M5208},
  51    {"cfv4e", M68K_CPUID_CFV4E},
  52    {"any", M68K_CPUID_ANY},
  53    {NULL, 0},
  54};
  55
  56void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
  57{
  58    unsigned int i;
  59
  60    for (i = 0; m68k_cpu_defs[i].name; i++) {
  61        (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
  62    }
  63}
  64
  65static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
  66{
  67    if (n < 8) {
  68        stfq_p(mem_buf, env->fregs[n]);
  69        return 8;
  70    }
  71    if (n < 11) {
  72        /* FP control registers (not implemented)  */
  73        memset(mem_buf, 0, 4);
  74        return 4;
  75    }
  76    return 0;
  77}
  78
  79static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
  80{
  81    if (n < 8) {
  82        env->fregs[n] = ldfq_p(mem_buf);
  83        return 8;
  84    }
  85    if (n < 11) {
  86        /* FP control registers (not implemented)  */
  87        return 4;
  88    }
  89    return 0;
  90}
  91
  92static void m68k_set_feature(CPUM68KState *env, int feature)
  93{
  94    env->features |= (1u << feature);
  95}
  96
  97static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
  98{
  99    m68k_def_t *def;
 100
 101    for (def = m68k_cpu_defs; def->name; def++) {
 102        if (strcmp(def->name, name) == 0)
 103            break;
 104    }
 105    if (!def->name)
 106        return -1;
 107
 108    switch (def->id) {
 109    case M68K_CPUID_M5206:
 110        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 111        break;
 112    case M68K_CPUID_M5208:
 113        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 114        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
 115        m68k_set_feature(env, M68K_FEATURE_BRAL);
 116        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
 117        m68k_set_feature(env, M68K_FEATURE_USP);
 118        break;
 119    case M68K_CPUID_CFV4E:
 120        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 121        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
 122        m68k_set_feature(env, M68K_FEATURE_BRAL);
 123        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
 124        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
 125        m68k_set_feature(env, M68K_FEATURE_USP);
 126        break;
 127    case M68K_CPUID_ANY:
 128        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
 129        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
 130        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
 131        m68k_set_feature(env, M68K_FEATURE_BRAL);
 132        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
 133        /* MAC and EMAC are mututally exclusive, so pick EMAC.
 134           It's mostly backwards compatible.  */
 135        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
 136        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
 137        m68k_set_feature(env, M68K_FEATURE_USP);
 138        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
 139        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
 140        break;
 141    }
 142
 143    register_m68k_insns(env);
 144    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
 145        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
 146                                 11, "cf-fp.xml", 18);
 147    }
 148    /* TODO: Add [E]MAC registers.  */
 149    return 0;
 150}
 151
 152void cpu_reset(CPUM68KState *env)
 153{
 154    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
 155        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
 156        log_cpu_state(env, 0);
 157    }
 158
 159    memset(env, 0, offsetof(CPUM68KState, breakpoints));
 160#if !defined (CONFIG_USER_ONLY)
 161    env->sr = 0x2700;
 162#endif
 163    m68k_switch_sp(env);
 164    /* ??? FP regs should be initialized to NaN.  */
 165    env->cc_op = CC_OP_FLAGS;
 166    /* TODO: We should set PC from the interrupt vector.  */
 167    env->pc = 0;
 168    tlb_flush(env, 1);
 169}
 170
 171CPUM68KState *cpu_m68k_init(const char *cpu_model)
 172{
 173    CPUM68KState *env;
 174    static int inited;
 175
 176    env = qemu_mallocz(sizeof(CPUM68KState));
 177    cpu_exec_init(env);
 178    if (!inited) {
 179        inited = 1;
 180        m68k_tcg_init();
 181    }
 182
 183    env->cpu_model_str = cpu_model;
 184
 185    if (cpu_m68k_set_model(env, cpu_model) < 0) {
 186        cpu_m68k_close(env);
 187        return NULL;
 188    }
 189
 190    cpu_reset(env);
 191    qemu_init_vcpu(env);
 192    return env;
 193}
 194
 195void cpu_m68k_close(CPUM68KState *env)
 196{
 197    qemu_free(env);
 198}
 199
 200void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
 201{
 202    int flags;
 203    uint32_t src;
 204    uint32_t dest;
 205    uint32_t tmp;
 206
 207#define HIGHBIT 0x80000000u
 208
 209#define SET_NZ(x) do { \
 210    if ((x) == 0) \
 211        flags |= CCF_Z; \
 212    else if ((int32_t)(x) < 0) \
 213        flags |= CCF_N; \
 214    } while (0)
 215
 216#define SET_FLAGS_SUB(type, utype) do { \
 217    SET_NZ((type)dest); \
 218    tmp = dest + src; \
 219    if ((utype) tmp < (utype) src) \
 220        flags |= CCF_C; \
 221    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
 222        flags |= CCF_V; \
 223    } while (0)
 224
 225    flags = 0;
 226    src = env->cc_src;
 227    dest = env->cc_dest;
 228    switch (cc_op) {
 229    case CC_OP_FLAGS:
 230        flags = dest;
 231        break;
 232    case CC_OP_LOGIC:
 233        SET_NZ(dest);
 234        break;
 235    case CC_OP_ADD:
 236        SET_NZ(dest);
 237        if (dest < src)
 238            flags |= CCF_C;
 239        tmp = dest - src;
 240        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
 241            flags |= CCF_V;
 242        break;
 243    case CC_OP_SUB:
 244        SET_FLAGS_SUB(int32_t, uint32_t);
 245        break;
 246    case CC_OP_CMPB:
 247        SET_FLAGS_SUB(int8_t, uint8_t);
 248        break;
 249    case CC_OP_CMPW:
 250        SET_FLAGS_SUB(int16_t, uint16_t);
 251        break;
 252    case CC_OP_ADDX:
 253        SET_NZ(dest);
 254        if (dest <= src)
 255            flags |= CCF_C;
 256        tmp = dest - src - 1;
 257        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
 258            flags |= CCF_V;
 259        break;
 260    case CC_OP_SUBX:
 261        SET_NZ(dest);
 262        tmp = dest + src + 1;
 263        if (tmp <= src)
 264            flags |= CCF_C;
 265        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
 266            flags |= CCF_V;
 267        break;
 268    case CC_OP_SHIFT:
 269        SET_NZ(dest);
 270        if (src)
 271            flags |= CCF_C;
 272        break;
 273    default:
 274        cpu_abort(env, "Bad CC_OP %d", cc_op);
 275    }
 276    env->cc_op = CC_OP_FLAGS;
 277    env->cc_dest = flags;
 278}
 279
 280void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
 281{
 282    switch (reg) {
 283    case 0x02: /* CACR */
 284        env->cacr = val;
 285        m68k_switch_sp(env);
 286        break;
 287    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
 288        /* TODO: Implement Access Control Registers.  */
 289        break;
 290    case 0x801: /* VBR */
 291        env->vbr = val;
 292        break;
 293    /* TODO: Implement control registers.  */
 294    default:
 295        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
 296                  reg, val);
 297    }
 298}
 299
 300void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 301{
 302    uint32_t acc;
 303    int8_t exthigh;
 304    uint8_t extlow;
 305    uint64_t regval;
 306    int i;
 307    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
 308        for (i = 0; i < 4; i++) {
 309            regval = env->macc[i];
 310            exthigh = regval >> 40;
 311            if (env->macsr & MACSR_FI) {
 312                acc = regval >> 8;
 313                extlow = regval;
 314            } else {
 315                acc = regval;
 316                extlow = regval >> 32;
 317            }
 318            if (env->macsr & MACSR_FI) {
 319                regval = (((uint64_t)acc) << 8) | extlow;
 320                regval |= ((int64_t)exthigh) << 40;
 321            } else if (env->macsr & MACSR_SU) {
 322                regval = acc | (((int64_t)extlow) << 32);
 323                regval |= ((int64_t)exthigh) << 40;
 324            } else {
 325                regval = acc | (((uint64_t)extlow) << 32);
 326                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
 327            }
 328            env->macc[i] = regval;
 329        }
 330    }
 331    env->macsr = val;
 332}
 333
 334void m68k_switch_sp(CPUM68KState *env)
 335{
 336    int new_sp;
 337
 338    env->sp[env->current_sp] = env->aregs[7];
 339    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
 340             ? M68K_SSP : M68K_USP;
 341    env->aregs[7] = env->sp[new_sp];
 342    env->current_sp = new_sp;
 343}
 344
 345#if defined(CONFIG_USER_ONLY)
 346
 347int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 348                               int mmu_idx, int is_softmmu)
 349{
 350    env->exception_index = EXCP_ACCESS;
 351    env->mmu.ar = address;
 352    return 1;
 353}
 354
 355#else
 356
 357/* MMU */
 358
 359/* TODO: This will need fixing once the MMU is implemented.  */
 360target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 361{
 362    return addr;
 363}
 364
 365int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 366                               int mmu_idx, int is_softmmu)
 367{
 368    int prot;
 369
 370    address &= TARGET_PAGE_MASK;
 371    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 372    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
 373    return 0;
 374}
 375
 376/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
 377   be handled by the interrupt controller.  Real hardware only requests
 378   the vector when the interrupt is acknowledged by the CPU.  For
 379   simplicitly we calculate it when the interrupt is signalled.  */
 380void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
 381{
 382    env->pending_level = level;
 383    env->pending_vector = vector;
 384    if (level)
 385        cpu_interrupt(env, CPU_INTERRUPT_HARD);
 386    else
 387        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 388}
 389
 390#endif
 391
 392uint32_t HELPER(bitrev)(uint32_t x)
 393{
 394    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
 395    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
 396    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
 397    return bswap32(x);
 398}
 399
 400uint32_t HELPER(ff1)(uint32_t x)
 401{
 402    int n;
 403    for (n = 32; x; n--)
 404        x >>= 1;
 405    return n;
 406}
 407
 408uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 409{
 410    /* The result has the opposite sign to the original value.  */
 411    if (ccr & CCF_V)
 412        val = (((int32_t)val) >> 31) ^ SIGNBIT;
 413    return val;
 414}
 415
 416uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 417{
 418    uint32_t res;
 419    uint32_t old_flags;
 420
 421    old_flags = env->cc_dest;
 422    if (env->cc_x) {
 423        env->cc_x = (op1 <= op2);
 424        env->cc_op = CC_OP_SUBX;
 425        res = op1 - (op2 + 1);
 426    } else {
 427        env->cc_x = (op1 < op2);
 428        env->cc_op = CC_OP_SUB;
 429        res = op1 - op2;
 430    }
 431    env->cc_dest = res;
 432    env->cc_src = op2;
 433    cpu_m68k_flush_flags(env, env->cc_op);
 434    /* !Z is sticky.  */
 435    env->cc_dest &= (old_flags | ~CCF_Z);
 436    return res;
 437}
 438
 439uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 440{
 441    uint32_t res;
 442    uint32_t old_flags;
 443
 444    old_flags = env->cc_dest;
 445    if (env->cc_x) {
 446        res = op1 + op2 + 1;
 447        env->cc_x = (res <= op2);
 448        env->cc_op = CC_OP_ADDX;
 449    } else {
 450        res = op1 + op2;
 451        env->cc_x = (res < op2);
 452        env->cc_op = CC_OP_ADD;
 453    }
 454    env->cc_dest = res;
 455    env->cc_src = op2;
 456    cpu_m68k_flush_flags(env, env->cc_op);
 457    /* !Z is sticky.  */
 458    env->cc_dest &= (old_flags | ~CCF_Z);
 459    return res;
 460}
 461
 462uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
 463{
 464    return a < b;
 465}
 466
 467void HELPER(set_sr)(CPUState *env, uint32_t val)
 468{
 469    env->sr = val & 0xffff;
 470    m68k_switch_sp(env);
 471}
 472
 473uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
 474{
 475    uint32_t result;
 476    uint32_t cf;
 477
 478    shift &= 63;
 479    if (shift == 0) {
 480        result = val;
 481        cf = env->cc_src & CCF_C;
 482    } else if (shift < 32) {
 483        result = val << shift;
 484        cf = (val >> (32 - shift)) & 1;
 485    } else if (shift == 32) {
 486        result = 0;
 487        cf = val & 1;
 488    } else /* shift > 32 */ {
 489        result = 0;
 490        cf = 0;
 491    }
 492    env->cc_src = cf;
 493    env->cc_x = (cf != 0);
 494    env->cc_dest = result;
 495    return result;
 496}
 497
 498uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
 499{
 500    uint32_t result;
 501    uint32_t cf;
 502
 503    shift &= 63;
 504    if (shift == 0) {
 505        result = val;
 506        cf = env->cc_src & CCF_C;
 507    } else if (shift < 32) {
 508        result = val >> shift;
 509        cf = (val >> (shift - 1)) & 1;
 510    } else if (shift == 32) {
 511        result = 0;
 512        cf = val >> 31;
 513    } else /* shift > 32 */ {
 514        result = 0;
 515        cf = 0;
 516    }
 517    env->cc_src = cf;
 518    env->cc_x = (cf != 0);
 519    env->cc_dest = result;
 520    return result;
 521}
 522
 523uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
 524{
 525    uint32_t result;
 526    uint32_t cf;
 527
 528    shift &= 63;
 529    if (shift == 0) {
 530        result = val;
 531        cf = (env->cc_src & CCF_C) != 0;
 532    } else if (shift < 32) {
 533        result = (int32_t)val >> shift;
 534        cf = (val >> (shift - 1)) & 1;
 535    } else /* shift >= 32 */ {
 536        result = (int32_t)val >> 31;
 537        cf = val >> 31;
 538    }
 539    env->cc_src = cf;
 540    env->cc_x = cf;
 541    env->cc_dest = result;
 542    return result;
 543}
 544
 545/* FPU helpers.  */
 546uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
 547{
 548    return float64_to_int32(val, &env->fp_status);
 549}
 550
 551float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
 552{
 553    return float64_to_float32(val, &env->fp_status);
 554}
 555
 556float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
 557{
 558    return int32_to_float64(val, &env->fp_status);
 559}
 560
 561float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
 562{
 563    return float32_to_float64(val, &env->fp_status);
 564}
 565
 566float64 HELPER(iround_f64)(CPUState *env, float64 val)
 567{
 568    return float64_round_to_int(val, &env->fp_status);
 569}
 570
 571float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
 572{
 573    return float64_trunc_to_int(val, &env->fp_status);
 574}
 575
 576float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
 577{
 578    return float64_sqrt(val, &env->fp_status);
 579}
 580
 581float64 HELPER(abs_f64)(float64 val)
 582{
 583    return float64_abs(val);
 584}
 585
 586float64 HELPER(chs_f64)(float64 val)
 587{
 588    return float64_chs(val);
 589}
 590
 591float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
 592{
 593    return float64_add(a, b, &env->fp_status);
 594}
 595
 596float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
 597{
 598    return float64_sub(a, b, &env->fp_status);
 599}
 600
 601float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
 602{
 603    return float64_mul(a, b, &env->fp_status);
 604}
 605
 606float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
 607{
 608    return float64_div(a, b, &env->fp_status);
 609}
 610
 611float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
 612{
 613    /* ??? This may incorrectly raise exceptions.  */
 614    /* ??? Should flush denormals to zero.  */
 615    float64 res;
 616    res = float64_sub(a, b, &env->fp_status);
 617    if (float64_is_nan(res)) {
 618        /* +/-inf compares equal against itself, but sub returns nan.  */
 619        if (!float64_is_nan(a)
 620            && !float64_is_nan(b)) {
 621            res = float64_zero;
 622            if (float64_lt_quiet(a, res, &env->fp_status))
 623                res = float64_chs(res);
 624        }
 625    }
 626    return res;
 627}
 628
 629uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
 630{
 631    return float64_compare_quiet(val, float64_zero, &env->fp_status);
 632}
 633
 634/* MAC unit.  */
 635/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
 636   take values,  others take register numbers and manipulate the contents
 637   in-place.  */
 638void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
 639{
 640    uint32_t mask;
 641    env->macc[dest] = env->macc[src];
 642    mask = MACSR_PAV0 << dest;
 643    if (env->macsr & (MACSR_PAV0 << src))
 644        env->macsr |= mask;
 645    else
 646        env->macsr &= ~mask;
 647}
 648
 649uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
 650{
 651    int64_t product;
 652    int64_t res;
 653
 654    product = (uint64_t)op1 * op2;
 655    res = (product << 24) >> 24;
 656    if (res != product) {
 657        env->macsr |= MACSR_V;
 658        if (env->macsr & MACSR_OMC) {
 659            /* Make sure the accumulate operation overflows.  */
 660            if (product < 0)
 661                res = ~(1ll << 50);
 662            else
 663                res = 1ll << 50;
 664        }
 665    }
 666    return res;
 667}
 668
 669uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
 670{
 671    uint64_t product;
 672
 673    product = (uint64_t)op1 * op2;
 674    if (product & (0xffffffull << 40)) {
 675        env->macsr |= MACSR_V;
 676        if (env->macsr & MACSR_OMC) {
 677            /* Make sure the accumulate operation overflows.  */
 678            product = 1ll << 50;
 679        } else {
 680            product &= ((1ull << 40) - 1);
 681        }
 682    }
 683    return product;
 684}
 685
 686uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
 687{
 688    uint64_t product;
 689    uint32_t remainder;
 690
 691    product = (uint64_t)op1 * op2;
 692    if (env->macsr & MACSR_RT) {
 693        remainder = product & 0xffffff;
 694        product >>= 24;
 695        if (remainder > 0x800000)
 696            product++;
 697        else if (remainder == 0x800000)
 698            product += (product & 1);
 699    } else {
 700        product >>= 24;
 701    }
 702    return product;
 703}
 704
 705void HELPER(macsats)(CPUState *env, uint32_t acc)
 706{
 707    int64_t tmp;
 708    int64_t result;
 709    tmp = env->macc[acc];
 710    result = ((tmp << 16) >> 16);
 711    if (result != tmp) {
 712        env->macsr |= MACSR_V;
 713    }
 714    if (env->macsr & MACSR_V) {
 715        env->macsr |= MACSR_PAV0 << acc;
 716        if (env->macsr & MACSR_OMC) {
 717            /* The result is saturated to 32 bits, despite overflow occuring
 718               at 48 bits.  Seems weird, but that's what the hardware docs
 719               say.  */
 720            result = (result >> 63) ^ 0x7fffffff;
 721        }
 722    }
 723    env->macc[acc] = result;
 724}
 725
 726void HELPER(macsatu)(CPUState *env, uint32_t acc)
 727{
 728    uint64_t val;
 729
 730    val = env->macc[acc];
 731    if (val & (0xffffull << 48)) {
 732        env->macsr |= MACSR_V;
 733    }
 734    if (env->macsr & MACSR_V) {
 735        env->macsr |= MACSR_PAV0 << acc;
 736        if (env->macsr & MACSR_OMC) {
 737            if (val > (1ull << 53))
 738                val = 0;
 739            else
 740                val = (1ull << 48) - 1;
 741        } else {
 742            val &= ((1ull << 48) - 1);
 743        }
 744    }
 745    env->macc[acc] = val;
 746}
 747
 748void HELPER(macsatf)(CPUState *env, uint32_t acc)
 749{
 750    int64_t sum;
 751    int64_t result;
 752
 753    sum = env->macc[acc];
 754    result = (sum << 16) >> 16;
 755    if (result != sum) {
 756        env->macsr |= MACSR_V;
 757    }
 758    if (env->macsr & MACSR_V) {
 759        env->macsr |= MACSR_PAV0 << acc;
 760        if (env->macsr & MACSR_OMC) {
 761            result = (result >> 63) ^ 0x7fffffffffffll;
 762        }
 763    }
 764    env->macc[acc] = result;
 765}
 766
 767void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
 768{
 769    uint64_t val;
 770    val = env->macc[acc];
 771    if (val == 0) {
 772        env->macsr |= MACSR_Z;
 773    } else if (val & (1ull << 47)) {
 774        env->macsr |= MACSR_N;
 775    }
 776    if (env->macsr & (MACSR_PAV0 << acc)) {
 777        env->macsr |= MACSR_V;
 778    }
 779    if (env->macsr & MACSR_FI) {
 780        val = ((int64_t)val) >> 40;
 781        if (val != 0 && val != -1)
 782            env->macsr |= MACSR_EV;
 783    } else if (env->macsr & MACSR_SU) {
 784        val = ((int64_t)val) >> 32;
 785        if (val != 0 && val != -1)
 786            env->macsr |= MACSR_EV;
 787    } else {
 788        if ((val >> 32) != 0)
 789            env->macsr |= MACSR_EV;
 790    }
 791}
 792
 793void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
 794{
 795    cpu_m68k_flush_flags(env, cc_op);
 796}
 797
 798uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
 799{
 800    int rem;
 801    uint32_t result;
 802
 803    if (env->macsr & MACSR_SU) {
 804        /* 16-bit rounding.  */
 805        rem = val & 0xffffff;
 806        val = (val >> 24) & 0xffffu;
 807        if (rem > 0x800000)
 808            val++;
 809        else if (rem == 0x800000)
 810            val += (val & 1);
 811    } else if (env->macsr & MACSR_RT) {
 812        /* 32-bit rounding.  */
 813        rem = val & 0xff;
 814        val >>= 8;
 815        if (rem > 0x80)
 816            val++;
 817        else if (rem == 0x80)
 818            val += (val & 1);
 819    } else {
 820        /* No rounding.  */
 821        val >>= 8;
 822    }
 823    if (env->macsr & MACSR_OMC) {
 824        /* Saturate.  */
 825        if (env->macsr & MACSR_SU) {
 826            if (val != (uint16_t) val) {
 827                result = ((val >> 63) ^ 0x7fff) & 0xffff;
 828            } else {
 829                result = val & 0xffff;
 830            }
 831        } else {
 832            if (val != (uint32_t)val) {
 833                result = ((uint32_t)(val >> 63) & 0x7fffffff);
 834            } else {
 835                result = (uint32_t)val;
 836            }
 837        }
 838    } else {
 839        /* No saturation.  */
 840        if (env->macsr & MACSR_SU) {
 841            result = val & 0xffff;
 842        } else {
 843            result = (uint32_t)val;
 844        }
 845    }
 846    return result;
 847}
 848
 849uint32_t HELPER(get_macs)(uint64_t val)
 850{
 851    if (val == (int32_t)val) {
 852        return (int32_t)val;
 853    } else {
 854        return (val >> 61) ^ ~SIGNBIT;
 855    }
 856}
 857
 858uint32_t HELPER(get_macu)(uint64_t val)
 859{
 860    if ((val >> 32) == 0) {
 861        return (uint32_t)val;
 862    } else {
 863        return 0xffffffffu;
 864    }
 865}
 866
 867uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
 868{
 869    uint32_t val;
 870    val = env->macc[acc] & 0x00ff;
 871    val = (env->macc[acc] >> 32) & 0xff00;
 872    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
 873    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
 874    return val;
 875}
 876
 877uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
 878{
 879    uint32_t val;
 880    val = (env->macc[acc] >> 32) & 0xffff;
 881    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
 882    return val;
 883}
 884
 885void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
 886{
 887    int64_t res;
 888    int32_t tmp;
 889    res = env->macc[acc] & 0xffffffff00ull;
 890    tmp = (int16_t)(val & 0xff00);
 891    res |= ((int64_t)tmp) << 32;
 892    res |= val & 0xff;
 893    env->macc[acc] = res;
 894    res = env->macc[acc + 1] & 0xffffffff00ull;
 895    tmp = (val & 0xff000000);
 896    res |= ((int64_t)tmp) << 16;
 897    res |= (val >> 16) & 0xff;
 898    env->macc[acc + 1] = res;
 899}
 900
 901void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
 902{
 903    int64_t res;
 904    int32_t tmp;
 905    res = (uint32_t)env->macc[acc];
 906    tmp = (int16_t)val;
 907    res |= ((int64_t)tmp) << 32;
 908    env->macc[acc] = res;
 909    res = (uint32_t)env->macc[acc + 1];
 910    tmp = val & 0xffff0000;
 911    res |= (int64_t)tmp << 16;
 912    env->macc[acc + 1] = res;
 913}
 914
 915void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
 916{
 917    uint64_t res;
 918    res = (uint32_t)env->macc[acc];
 919    res |= ((uint64_t)(val & 0xffff)) << 32;
 920    env->macc[acc] = res;
 921    res = (uint32_t)env->macc[acc + 1];
 922    res |= (uint64_t)(val & 0xffff0000) << 16;
 923    env->macc[acc + 1] = res;
 924}
 925