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 "helper.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
 114    register_m68k_insns(env);
 115
 116    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 117
 118    return cpu;
 119}
 120
 121void m68k_cpu_init_gdb(M68kCPU *cpu)
 122{
 123    CPUState *cs = CPU(cpu);
 124    CPUM68KState *env = &cpu->env;
 125
 126    if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
 127        gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
 128                                 11, "cf-fp.xml", 18);
 129    }
 130    /* TODO: Add [E]MAC registers.  */
 131}
 132
 133void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
 134{
 135    int flags;
 136    uint32_t src;
 137    uint32_t dest;
 138    uint32_t tmp;
 139
 140#define HIGHBIT 0x80000000u
 141
 142#define SET_NZ(x) do { \
 143    if ((x) == 0) \
 144        flags |= CCF_Z; \
 145    else if ((int32_t)(x) < 0) \
 146        flags |= CCF_N; \
 147    } while (0)
 148
 149#define SET_FLAGS_SUB(type, utype) do { \
 150    SET_NZ((type)dest); \
 151    tmp = dest + src; \
 152    if ((utype) tmp < (utype) src) \
 153        flags |= CCF_C; \
 154    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
 155        flags |= CCF_V; \
 156    } while (0)
 157
 158    flags = 0;
 159    src = env->cc_src;
 160    dest = env->cc_dest;
 161    switch (cc_op) {
 162    case CC_OP_FLAGS:
 163        flags = dest;
 164        break;
 165    case CC_OP_LOGIC:
 166        SET_NZ(dest);
 167        break;
 168    case CC_OP_ADD:
 169        SET_NZ(dest);
 170        if (dest < src)
 171            flags |= CCF_C;
 172        tmp = dest - src;
 173        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
 174            flags |= CCF_V;
 175        break;
 176    case CC_OP_SUB:
 177        SET_FLAGS_SUB(int32_t, uint32_t);
 178        break;
 179    case CC_OP_CMPB:
 180        SET_FLAGS_SUB(int8_t, uint8_t);
 181        break;
 182    case CC_OP_CMPW:
 183        SET_FLAGS_SUB(int16_t, uint16_t);
 184        break;
 185    case CC_OP_ADDX:
 186        SET_NZ(dest);
 187        if (dest <= src)
 188            flags |= CCF_C;
 189        tmp = dest - src - 1;
 190        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
 191            flags |= CCF_V;
 192        break;
 193    case CC_OP_SUBX:
 194        SET_NZ(dest);
 195        tmp = dest + src + 1;
 196        if (tmp <= src)
 197            flags |= CCF_C;
 198        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
 199            flags |= CCF_V;
 200        break;
 201    case CC_OP_SHIFT:
 202        SET_NZ(dest);
 203        if (src)
 204            flags |= CCF_C;
 205        break;
 206    default:
 207        cpu_abort(env, "Bad CC_OP %d", cc_op);
 208    }
 209    env->cc_op = CC_OP_FLAGS;
 210    env->cc_dest = flags;
 211}
 212
 213void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
 214{
 215    switch (reg) {
 216    case 0x02: /* CACR */
 217        env->cacr = val;
 218        m68k_switch_sp(env);
 219        break;
 220    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
 221        /* TODO: Implement Access Control Registers.  */
 222        break;
 223    case 0x801: /* VBR */
 224        env->vbr = val;
 225        break;
 226    /* TODO: Implement control registers.  */
 227    default:
 228        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
 229                  reg, val);
 230    }
 231}
 232
 233void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 234{
 235    uint32_t acc;
 236    int8_t exthigh;
 237    uint8_t extlow;
 238    uint64_t regval;
 239    int i;
 240    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
 241        for (i = 0; i < 4; i++) {
 242            regval = env->macc[i];
 243            exthigh = regval >> 40;
 244            if (env->macsr & MACSR_FI) {
 245                acc = regval >> 8;
 246                extlow = regval;
 247            } else {
 248                acc = regval;
 249                extlow = regval >> 32;
 250            }
 251            if (env->macsr & MACSR_FI) {
 252                regval = (((uint64_t)acc) << 8) | extlow;
 253                regval |= ((int64_t)exthigh) << 40;
 254            } else if (env->macsr & MACSR_SU) {
 255                regval = acc | (((int64_t)extlow) << 32);
 256                regval |= ((int64_t)exthigh) << 40;
 257            } else {
 258                regval = acc | (((uint64_t)extlow) << 32);
 259                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
 260            }
 261            env->macc[i] = regval;
 262        }
 263    }
 264    env->macsr = val;
 265}
 266
 267void m68k_switch_sp(CPUM68KState *env)
 268{
 269    int new_sp;
 270
 271    env->sp[env->current_sp] = env->aregs[7];
 272    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
 273             ? M68K_SSP : M68K_USP;
 274    env->aregs[7] = env->sp[new_sp];
 275    env->current_sp = new_sp;
 276}
 277
 278#if defined(CONFIG_USER_ONLY)
 279
 280int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
 281                               int mmu_idx)
 282{
 283    env->exception_index = EXCP_ACCESS;
 284    env->mmu.ar = address;
 285    return 1;
 286}
 287
 288#else
 289
 290/* MMU */
 291
 292/* TODO: This will need fixing once the MMU is implemented.  */
 293hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 294{
 295    return addr;
 296}
 297
 298int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
 299                               int mmu_idx)
 300{
 301    int prot;
 302
 303    address &= TARGET_PAGE_MASK;
 304    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 305    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
 306    return 0;
 307}
 308
 309/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
 310   be handled by the interrupt controller.  Real hardware only requests
 311   the vector when the interrupt is acknowledged by the CPU.  For
 312   simplicitly we calculate it when the interrupt is signalled.  */
 313void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 314{
 315    CPUState *cs = CPU(cpu);
 316    CPUM68KState *env = &cpu->env;
 317
 318    env->pending_level = level;
 319    env->pending_vector = vector;
 320    if (level) {
 321        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 322    } else {
 323        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 324    }
 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