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