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