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