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/* MMU */
 346
 347/* TODO: This will need fixing once the MMU is implemented.  */
 348target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 349{
 350    return addr;
 351}
 352
 353#if defined(CONFIG_USER_ONLY)
 354
 355int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 356                               int mmu_idx, int is_softmmu)
 357{
 358    env->exception_index = EXCP_ACCESS;
 359    env->mmu.ar = address;
 360    return 1;
 361}
 362
 363#else
 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;
 372    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
 373}
 374
 375/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
 376   be handled by the interrupt controller.  Real hardware only requests
 377   the vector when the interrupt is acknowledged by the CPU.  For
 378   simplicitly we calculate it when the interrupt is signalled.  */
 379void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
 380{
 381    env->pending_level = level;
 382    env->pending_vector = vector;
 383    if (level)
 384        cpu_interrupt(env, CPU_INTERRUPT_HARD);
 385    else
 386        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 387}
 388
 389#endif
 390
 391uint32_t HELPER(bitrev)(uint32_t x)
 392{
 393    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
 394    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
 395    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
 396    return bswap32(x);
 397}
 398
 399uint32_t HELPER(ff1)(uint32_t x)
 400{
 401    int n;
 402    for (n = 32; x; n--)
 403        x >>= 1;
 404    return n;
 405}
 406
 407uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 408{
 409    /* The result has the opposite sign to the original value.  */
 410    if (ccr & CCF_V)
 411        val = (((int32_t)val) >> 31) ^ SIGNBIT;
 412    return val;
 413}
 414
 415uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 416{
 417    uint32_t res;
 418    uint32_t old_flags;
 419
 420    old_flags = env->cc_dest;
 421    if (env->cc_x) {
 422        env->cc_x = (op1 <= op2);
 423        env->cc_op = CC_OP_SUBX;
 424        res = op1 - (op2 + 1);
 425    } else {
 426        env->cc_x = (op1 < op2);
 427        env->cc_op = CC_OP_SUB;
 428        res = op1 - op2;
 429    }
 430    env->cc_dest = res;
 431    env->cc_src = op2;
 432    cpu_m68k_flush_flags(env, env->cc_op);
 433    /* !Z is sticky.  */
 434    env->cc_dest &= (old_flags | ~CCF_Z);
 435    return res;
 436}
 437
 438uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 439{
 440    uint32_t res;
 441    uint32_t old_flags;
 442
 443    old_flags = env->cc_dest;
 444    if (env->cc_x) {
 445        res = op1 + op2 + 1;
 446        env->cc_x = (res <= op2);
 447        env->cc_op = CC_OP_ADDX;
 448    } else {
 449        res = op1 + op2;
 450        env->cc_x = (res < op2);
 451        env->cc_op = CC_OP_ADD;
 452    }
 453    env->cc_dest = res;
 454    env->cc_src = op2;
 455    cpu_m68k_flush_flags(env, env->cc_op);
 456    /* !Z is sticky.  */
 457    env->cc_dest &= (old_flags | ~CCF_Z);
 458    return res;
 459}
 460
 461uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
 462{
 463    return a < b;
 464}
 465
 466void HELPER(set_sr)(CPUState *env, uint32_t val)
 467{
 468    env->sr = val & 0xffff;
 469    m68k_switch_sp(env);
 470}
 471
 472uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
 473{
 474    uint32_t result;
 475    uint32_t cf;
 476
 477    shift &= 63;
 478    if (shift == 0) {
 479        result = val;
 480        cf = env->cc_src & CCF_C;
 481    } else if (shift < 32) {
 482        result = val << shift;
 483        cf = (val >> (32 - shift)) & 1;
 484    } else if (shift == 32) {
 485        result = 0;
 486        cf = val & 1;
 487    } else /* shift > 32 */ {
 488        result = 0;
 489        cf = 0;
 490    }
 491    env->cc_src = cf;
 492    env->cc_x = (cf != 0);
 493    env->cc_dest = result;
 494    return result;
 495}
 496
 497uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
 498{
 499    uint32_t result;
 500    uint32_t cf;
 501
 502    shift &= 63;
 503    if (shift == 0) {
 504        result = val;
 505        cf = env->cc_src & CCF_C;
 506    } else if (shift < 32) {
 507        result = val >> shift;
 508        cf = (val >> (shift - 1)) & 1;
 509    } else if (shift == 32) {
 510        result = 0;
 511        cf = val >> 31;
 512    } else /* shift > 32 */ {
 513        result = 0;
 514        cf = 0;
 515    }
 516    env->cc_src = cf;
 517    env->cc_x = (cf != 0);
 518    env->cc_dest = result;
 519    return result;
 520}
 521
 522uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
 523{
 524    uint32_t result;
 525    uint32_t cf;
 526
 527    shift &= 63;
 528    if (shift == 0) {
 529        result = val;
 530        cf = (env->cc_src & CCF_C) != 0;
 531    } else if (shift < 32) {
 532        result = (int32_t)val >> shift;
 533        cf = (val >> (shift - 1)) & 1;
 534    } else /* shift >= 32 */ {
 535        result = (int32_t)val >> 31;
 536        cf = val >> 31;
 537    }
 538    env->cc_src = cf;
 539    env->cc_x = cf;
 540    env->cc_dest = result;
 541    return result;
 542}
 543
 544/* FPU helpers.  */
 545uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
 546{
 547    return float64_to_int32(val, &env->fp_status);
 548}
 549
 550float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
 551{
 552    return float64_to_float32(val, &env->fp_status);
 553}
 554
 555float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
 556{
 557    return int32_to_float64(val, &env->fp_status);
 558}
 559
 560float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
 561{
 562    return float32_to_float64(val, &env->fp_status);
 563}
 564
 565float64 HELPER(iround_f64)(CPUState *env, float64 val)
 566{
 567    return float64_round_to_int(val, &env->fp_status);
 568}
 569
 570float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
 571{
 572    return float64_trunc_to_int(val, &env->fp_status);
 573}
 574
 575float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
 576{
 577    return float64_sqrt(val, &env->fp_status);
 578}
 579
 580float64 HELPER(abs_f64)(float64 val)
 581{
 582    return float64_abs(val);
 583}
 584
 585float64 HELPER(chs_f64)(float64 val)
 586{
 587    return float64_chs(val);
 588}
 589
 590float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
 591{
 592    return float64_add(a, b, &env->fp_status);
 593}
 594
 595float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
 596{
 597    return float64_sub(a, b, &env->fp_status);
 598}
 599
 600float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
 601{
 602    return float64_mul(a, b, &env->fp_status);
 603}
 604
 605float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
 606{
 607    return float64_div(a, b, &env->fp_status);
 608}
 609
 610float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
 611{
 612    /* ??? This may incorrectly raise exceptions.  */
 613    /* ??? Should flush denormals to zero.  */
 614    float64 res;
 615    res = float64_sub(a, b, &env->fp_status);
 616    if (float64_is_nan(res)) {
 617        /* +/-inf compares equal against itself, but sub returns nan.  */
 618        if (!float64_is_nan(a)
 619            && !float64_is_nan(b)) {
 620            res = float64_zero;
 621            if (float64_lt_quiet(a, res, &env->fp_status))
 622                res = float64_chs(res);
 623        }
 624    }
 625    return res;
 626}
 627
 628uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
 629{
 630    return float64_compare_quiet(val, float64_zero, &env->fp_status);
 631}
 632
 633/* MAC unit.  */
 634/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
 635   take values,  others take register numbers and manipulate the contents
 636   in-place.  */
 637void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
 638{
 639    uint32_t mask;
 640    env->macc[dest] = env->macc[src];
 641    mask = MACSR_PAV0 << dest;
 642    if (env->macsr & (MACSR_PAV0 << src))
 643        env->macsr |= mask;
 644    else
 645        env->macsr &= ~mask;
 646}
 647
 648uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
 649{
 650    int64_t product;
 651    int64_t res;
 652
 653    product = (uint64_t)op1 * op2;
 654    res = (product << 24) >> 24;
 655    if (res != product) {
 656        env->macsr |= MACSR_V;
 657        if (env->macsr & MACSR_OMC) {
 658            /* Make sure the accumulate operation overflows.  */
 659            if (product < 0)
 660                res = ~(1ll << 50);
 661            else
 662                res = 1ll << 50;
 663        }
 664    }
 665    return res;
 666}
 667
 668uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
 669{
 670    uint64_t product;
 671
 672    product = (uint64_t)op1 * op2;
 673    if (product & (0xffffffull << 40)) {
 674        env->macsr |= MACSR_V;
 675        if (env->macsr & MACSR_OMC) {
 676            /* Make sure the accumulate operation overflows.  */
 677            product = 1ll << 50;
 678        } else {
 679            product &= ((1ull << 40) - 1);
 680        }
 681    }
 682    return product;
 683}
 684
 685uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
 686{
 687    uint64_t product;
 688    uint32_t remainder;
 689
 690    product = (uint64_t)op1 * op2;
 691    if (env->macsr & MACSR_RT) {
 692        remainder = product & 0xffffff;
 693        product >>= 24;
 694        if (remainder > 0x800000)
 695            product++;
 696        else if (remainder == 0x800000)
 697            product += (product & 1);
 698    } else {
 699        product >>= 24;
 700    }
 701    return product;
 702}
 703
 704void HELPER(macsats)(CPUState *env, uint32_t acc)
 705{
 706    int64_t tmp;
 707    int64_t result;
 708    tmp = env->macc[acc];
 709    result = ((tmp << 16) >> 16);
 710    if (result != tmp) {
 711        env->macsr |= MACSR_V;
 712    }
 713    if (env->macsr & MACSR_V) {
 714        env->macsr |= MACSR_PAV0 << acc;
 715        if (env->macsr & MACSR_OMC) {
 716            /* The result is saturated to 32 bits, despite overflow occuring
 717               at 48 bits.  Seems weird, but that's what the hardware docs
 718               say.  */
 719            result = (result >> 63) ^ 0x7fffffff;
 720        }
 721    }
 722    env->macc[acc] = result;
 723}
 724
 725void HELPER(macsatu)(CPUState *env, uint32_t acc)
 726{
 727    uint64_t val;
 728
 729    val = env->macc[acc];
 730    if (val & (0xffffull << 48)) {
 731        env->macsr |= MACSR_V;
 732    }
 733    if (env->macsr & MACSR_V) {
 734        env->macsr |= MACSR_PAV0 << acc;
 735        if (env->macsr & MACSR_OMC) {
 736            if (val > (1ull << 53))
 737                val = 0;
 738            else
 739                val = (1ull << 48) - 1;
 740        } else {
 741            val &= ((1ull << 48) - 1);
 742        }
 743    }
 744    env->macc[acc] = val;
 745}
 746
 747void HELPER(macsatf)(CPUState *env, uint32_t acc)
 748{
 749    int64_t sum;
 750    int64_t result;
 751
 752    sum = env->macc[acc];
 753    result = (sum << 16) >> 16;
 754    if (result != sum) {
 755        env->macsr |= MACSR_V;
 756    }
 757    if (env->macsr & MACSR_V) {
 758        env->macsr |= MACSR_PAV0 << acc;
 759        if (env->macsr & MACSR_OMC) {
 760            result = (result >> 63) ^ 0x7fffffffffffll;
 761        }
 762    }
 763    env->macc[acc] = result;
 764}
 765
 766void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
 767{
 768    uint64_t val;
 769    val = env->macc[acc];
 770    if (val == 0)
 771        env->macsr |= MACSR_Z;
 772    else if (val & (1ull << 47));
 773        env->macsr |= MACSR_N;
 774    if (env->macsr & (MACSR_PAV0 << acc)) {
 775        env->macsr |= MACSR_V;
 776    }
 777    if (env->macsr & MACSR_FI) {
 778        val = ((int64_t)val) >> 40;
 779        if (val != 0 && val != -1)
 780            env->macsr |= MACSR_EV;
 781    } else if (env->macsr & MACSR_SU) {
 782        val = ((int64_t)val) >> 32;
 783        if (val != 0 && val != -1)
 784            env->macsr |= MACSR_EV;
 785    } else {
 786        if ((val >> 32) != 0)
 787            env->macsr |= MACSR_EV;
 788    }
 789}
 790
 791void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
 792{
 793    cpu_m68k_flush_flags(env, cc_op);
 794}
 795
 796uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
 797{
 798    int rem;
 799    uint32_t result;
 800
 801    if (env->macsr & MACSR_SU) {
 802        /* 16-bit rounding.  */
 803        rem = val & 0xffffff;
 804        val = (val >> 24) & 0xffffu;
 805        if (rem > 0x800000)
 806            val++;
 807        else if (rem == 0x800000)
 808            val += (val & 1);
 809    } else if (env->macsr & MACSR_RT) {
 810        /* 32-bit rounding.  */
 811        rem = val & 0xff;
 812        val >>= 8;
 813        if (rem > 0x80)
 814            val++;
 815        else if (rem == 0x80)
 816            val += (val & 1);
 817    } else {
 818        /* No rounding.  */
 819        val >>= 8;
 820    }
 821    if (env->macsr & MACSR_OMC) {
 822        /* Saturate.  */
 823        if (env->macsr & MACSR_SU) {
 824            if (val != (uint16_t) val) {
 825                result = ((val >> 63) ^ 0x7fff) & 0xffff;
 826            } else {
 827                result = val & 0xffff;
 828            }
 829        } else {
 830            if (val != (uint32_t)val) {
 831                result = ((uint32_t)(val >> 63) & 0x7fffffff);
 832            } else {
 833                result = (uint32_t)val;
 834            }
 835        }
 836    } else {
 837        /* No saturation.  */
 838        if (env->macsr & MACSR_SU) {
 839            result = val & 0xffff;
 840        } else {
 841            result = (uint32_t)val;
 842        }
 843    }
 844    return result;
 845}
 846
 847uint32_t HELPER(get_macs)(uint64_t val)
 848{
 849    if (val == (int32_t)val) {
 850        return (int32_t)val;
 851    } else {
 852        return (val >> 61) ^ ~SIGNBIT;
 853    }
 854}
 855
 856uint32_t HELPER(get_macu)(uint64_t val)
 857{
 858    if ((val >> 32) == 0) {
 859        return (uint32_t)val;
 860    } else {
 861        return 0xffffffffu;
 862    }
 863}
 864
 865uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
 866{
 867    uint32_t val;
 868    val = env->macc[acc] & 0x00ff;
 869    val = (env->macc[acc] >> 32) & 0xff00;
 870    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
 871    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
 872    return val;
 873}
 874
 875uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
 876{
 877    uint32_t val;
 878    val = (env->macc[acc] >> 32) & 0xffff;
 879    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
 880    return val;
 881}
 882
 883void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
 884{
 885    int64_t res;
 886    int32_t tmp;
 887    res = env->macc[acc] & 0xffffffff00ull;
 888    tmp = (int16_t)(val & 0xff00);
 889    res |= ((int64_t)tmp) << 32;
 890    res |= val & 0xff;
 891    env->macc[acc] = res;
 892    res = env->macc[acc + 1] & 0xffffffff00ull;
 893    tmp = (val & 0xff000000);
 894    res |= ((int64_t)tmp) << 16;
 895    res |= (val >> 16) & 0xff;
 896    env->macc[acc + 1] = res;
 897}
 898
 899void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
 900{
 901    int64_t res;
 902    int32_t tmp;
 903    res = (uint32_t)env->macc[acc];
 904    tmp = (int16_t)val;
 905    res |= ((int64_t)tmp) << 32;
 906    env->macc[acc] = res;
 907    res = (uint32_t)env->macc[acc + 1];
 908    tmp = val & 0xffff0000;
 909    res |= (int64_t)tmp << 16;
 910    env->macc[acc + 1] = res;
 911}
 912
 913void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
 914{
 915    uint64_t res;
 916    res = (uint32_t)env->macc[acc];
 917    res |= ((uint64_t)(val & 0xffff)) << 32;
 918    env->macc[acc] = res;
 919    res = (uint32_t)env->macc[acc + 1];
 920    res |= (uint64_t)(val & 0xffff0000) << 16;
 921    env->macc[acc + 1] = res;
 922}
 923