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 "exec/helper-proto.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    M68kCPU *cpu = m68k_env_get_cpu(env);
 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(CPU(cpu), "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    M68kCPU *cpu = m68k_env_get_cpu(env);
 217
 218    switch (reg) {
 219    case 0x02: /* CACR */
 220        env->cacr = val;
 221        m68k_switch_sp(env);
 222        break;
 223    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
 224        /* TODO: Implement Access Control Registers.  */
 225        break;
 226    case 0x801: /* VBR */
 227        env->vbr = val;
 228        break;
 229    /* TODO: Implement control registers.  */
 230    default:
 231        cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
 232                  reg, val);
 233    }
 234}
 235
 236void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 237{
 238    uint32_t acc;
 239    int8_t exthigh;
 240    uint8_t extlow;
 241    uint64_t regval;
 242    int i;
 243    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
 244        for (i = 0; i < 4; i++) {
 245            regval = env->macc[i];
 246            exthigh = regval >> 40;
 247            if (env->macsr & MACSR_FI) {
 248                acc = regval >> 8;
 249                extlow = regval;
 250            } else {
 251                acc = regval;
 252                extlow = regval >> 32;
 253            }
 254            if (env->macsr & MACSR_FI) {
 255                regval = (((uint64_t)acc) << 8) | extlow;
 256                regval |= ((int64_t)exthigh) << 40;
 257            } else if (env->macsr & MACSR_SU) {
 258                regval = acc | (((int64_t)extlow) << 32);
 259                regval |= ((int64_t)exthigh) << 40;
 260            } else {
 261                regval = acc | (((uint64_t)extlow) << 32);
 262                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
 263            }
 264            env->macc[i] = regval;
 265        }
 266    }
 267    env->macsr = val;
 268}
 269
 270void m68k_switch_sp(CPUM68KState *env)
 271{
 272    int new_sp;
 273
 274    env->sp[env->current_sp] = env->aregs[7];
 275    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
 276             ? M68K_SSP : M68K_USP;
 277    env->aregs[7] = env->sp[new_sp];
 278    env->current_sp = new_sp;
 279}
 280
 281#if defined(CONFIG_USER_ONLY)
 282
 283int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 284                              int mmu_idx)
 285{
 286    M68kCPU *cpu = M68K_CPU(cs);
 287
 288    cs->exception_index = EXCP_ACCESS;
 289    cpu->env.mmu.ar = address;
 290    return 1;
 291}
 292
 293#else
 294
 295/* MMU */
 296
 297/* TODO: This will need fixing once the MMU is implemented.  */
 298hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 299{
 300    return addr;
 301}
 302
 303int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 304                              int mmu_idx)
 305{
 306    int prot;
 307
 308    address &= TARGET_PAGE_MASK;
 309    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 310    tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
 311    return 0;
 312}
 313
 314/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
 315   be handled by the interrupt controller.  Real hardware only requests
 316   the vector when the interrupt is acknowledged by the CPU.  For
 317   simplicitly we calculate it when the interrupt is signalled.  */
 318void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 319{
 320    CPUState *cs = CPU(cpu);
 321    CPUM68KState *env = &cpu->env;
 322
 323    env->pending_level = level;
 324    env->pending_vector = vector;
 325    if (level) {
 326        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 327    } else {
 328        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 329    }
 330}
 331
 332#endif
 333
 334uint32_t HELPER(bitrev)(uint32_t x)
 335{
 336    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
 337    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
 338    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
 339    return bswap32(x);
 340}
 341
 342uint32_t HELPER(ff1)(uint32_t x)
 343{
 344    int n;
 345    for (n = 32; x; n--)
 346        x >>= 1;
 347    return n;
 348}
 349
 350uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 351{
 352    /* The result has the opposite sign to the original value.  */
 353    if (ccr & CCF_V)
 354        val = (((int32_t)val) >> 31) ^ SIGNBIT;
 355    return val;
 356}
 357
 358uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 359{
 360    uint32_t res;
 361    uint32_t old_flags;
 362
 363    old_flags = env->cc_dest;
 364    if (env->cc_x) {
 365        env->cc_x = (op1 <= op2);
 366        env->cc_op = CC_OP_SUBX;
 367        res = op1 - (op2 + 1);
 368    } else {
 369        env->cc_x = (op1 < op2);
 370        env->cc_op = CC_OP_SUB;
 371        res = op1 - op2;
 372    }
 373    env->cc_dest = res;
 374    env->cc_src = op2;
 375    cpu_m68k_flush_flags(env, env->cc_op);
 376    /* !Z is sticky.  */
 377    env->cc_dest &= (old_flags | ~CCF_Z);
 378    return res;
 379}
 380
 381uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 382{
 383    uint32_t res;
 384    uint32_t old_flags;
 385
 386    old_flags = env->cc_dest;
 387    if (env->cc_x) {
 388        res = op1 + op2 + 1;
 389        env->cc_x = (res <= op2);
 390        env->cc_op = CC_OP_ADDX;
 391    } else {
 392        res = op1 + op2;
 393        env->cc_x = (res < op2);
 394        env->cc_op = CC_OP_ADD;
 395    }
 396    env->cc_dest = res;
 397    env->cc_src = op2;
 398    cpu_m68k_flush_flags(env, env->cc_op);
 399    /* !Z is sticky.  */
 400    env->cc_dest &= (old_flags | ~CCF_Z);
 401    return res;
 402}
 403
 404uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
 405{
 406    return a < b;
 407}
 408
 409void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 410{
 411    env->sr = val & 0xffff;
 412    m68k_switch_sp(env);
 413}
 414
 415uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 416{
 417    uint32_t result;
 418    uint32_t cf;
 419
 420    shift &= 63;
 421    if (shift == 0) {
 422        result = val;
 423        cf = env->cc_src & CCF_C;
 424    } else if (shift < 32) {
 425        result = val << shift;
 426        cf = (val >> (32 - shift)) & 1;
 427    } else if (shift == 32) {
 428        result = 0;
 429        cf = val & 1;
 430    } else /* shift > 32 */ {
 431        result = 0;
 432        cf = 0;
 433    }
 434    env->cc_src = cf;
 435    env->cc_x = (cf != 0);
 436    env->cc_dest = result;
 437    return result;
 438}
 439
 440uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 441{
 442    uint32_t result;
 443    uint32_t cf;
 444
 445    shift &= 63;
 446    if (shift == 0) {
 447        result = val;
 448        cf = env->cc_src & CCF_C;
 449    } else if (shift < 32) {
 450        result = val >> shift;
 451        cf = (val >> (shift - 1)) & 1;
 452    } else if (shift == 32) {
 453        result = 0;
 454        cf = val >> 31;
 455    } else /* shift > 32 */ {
 456        result = 0;
 457        cf = 0;
 458    }
 459    env->cc_src = cf;
 460    env->cc_x = (cf != 0);
 461    env->cc_dest = result;
 462    return result;
 463}
 464
 465uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
 466{
 467    uint32_t result;
 468    uint32_t cf;
 469
 470    shift &= 63;
 471    if (shift == 0) {
 472        result = val;
 473        cf = (env->cc_src & CCF_C) != 0;
 474    } else if (shift < 32) {
 475        result = (int32_t)val >> shift;
 476        cf = (val >> (shift - 1)) & 1;
 477    } else /* shift >= 32 */ {
 478        result = (int32_t)val >> 31;
 479        cf = val >> 31;
 480    }
 481    env->cc_src = cf;
 482    env->cc_x = cf;
 483    env->cc_dest = result;
 484    return result;
 485}
 486
 487/* FPU helpers.  */
 488uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
 489{
 490    return float64_to_int32(val, &env->fp_status);
 491}
 492
 493float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
 494{
 495    return float64_to_float32(val, &env->fp_status);
 496}
 497
 498float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
 499{
 500    return int32_to_float64(val, &env->fp_status);
 501}
 502
 503float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
 504{
 505    return float32_to_float64(val, &env->fp_status);
 506}
 507
 508float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
 509{
 510    return float64_round_to_int(val, &env->fp_status);
 511}
 512
 513float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
 514{
 515    return float64_trunc_to_int(val, &env->fp_status);
 516}
 517
 518float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
 519{
 520    return float64_sqrt(val, &env->fp_status);
 521}
 522
 523float64 HELPER(abs_f64)(float64 val)
 524{
 525    return float64_abs(val);
 526}
 527
 528float64 HELPER(chs_f64)(float64 val)
 529{
 530    return float64_chs(val);
 531}
 532
 533float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
 534{
 535    return float64_add(a, b, &env->fp_status);
 536}
 537
 538float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
 539{
 540    return float64_sub(a, b, &env->fp_status);
 541}
 542
 543float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
 544{
 545    return float64_mul(a, b, &env->fp_status);
 546}
 547
 548float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
 549{
 550    return float64_div(a, b, &env->fp_status);
 551}
 552
 553float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
 554{
 555    /* ??? This may incorrectly raise exceptions.  */
 556    /* ??? Should flush denormals to zero.  */
 557    float64 res;
 558    res = float64_sub(a, b, &env->fp_status);
 559    if (float64_is_quiet_nan(res)) {
 560        /* +/-inf compares equal against itself, but sub returns nan.  */
 561        if (!float64_is_quiet_nan(a)
 562            && !float64_is_quiet_nan(b)) {
 563            res = float64_zero;
 564            if (float64_lt_quiet(a, res, &env->fp_status))
 565                res = float64_chs(res);
 566        }
 567    }
 568    return res;
 569}
 570
 571uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
 572{
 573    return float64_compare_quiet(val, float64_zero, &env->fp_status);
 574}
 575
 576/* MAC unit.  */
 577/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
 578   take values,  others take register numbers and manipulate the contents
 579   in-place.  */
 580void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
 581{
 582    uint32_t mask;
 583    env->macc[dest] = env->macc[src];
 584    mask = MACSR_PAV0 << dest;
 585    if (env->macsr & (MACSR_PAV0 << src))
 586        env->macsr |= mask;
 587    else
 588        env->macsr &= ~mask;
 589}
 590
 591uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 592{
 593    int64_t product;
 594    int64_t res;
 595
 596    product = (uint64_t)op1 * op2;
 597    res = (product << 24) >> 24;
 598    if (res != product) {
 599        env->macsr |= MACSR_V;
 600        if (env->macsr & MACSR_OMC) {
 601            /* Make sure the accumulate operation overflows.  */
 602            if (product < 0)
 603                res = ~(1ll << 50);
 604            else
 605                res = 1ll << 50;
 606        }
 607    }
 608    return res;
 609}
 610
 611uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 612{
 613    uint64_t product;
 614
 615    product = (uint64_t)op1 * op2;
 616    if (product & (0xffffffull << 40)) {
 617        env->macsr |= MACSR_V;
 618        if (env->macsr & MACSR_OMC) {
 619            /* Make sure the accumulate operation overflows.  */
 620            product = 1ll << 50;
 621        } else {
 622            product &= ((1ull << 40) - 1);
 623        }
 624    }
 625    return product;
 626}
 627
 628uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 629{
 630    uint64_t product;
 631    uint32_t remainder;
 632
 633    product = (uint64_t)op1 * op2;
 634    if (env->macsr & MACSR_RT) {
 635        remainder = product & 0xffffff;
 636        product >>= 24;
 637        if (remainder > 0x800000)
 638            product++;
 639        else if (remainder == 0x800000)
 640            product += (product & 1);
 641    } else {
 642        product >>= 24;
 643    }
 644    return product;
 645}
 646
 647void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
 648{
 649    int64_t tmp;
 650    int64_t result;
 651    tmp = env->macc[acc];
 652    result = ((tmp << 16) >> 16);
 653    if (result != tmp) {
 654        env->macsr |= MACSR_V;
 655    }
 656    if (env->macsr & MACSR_V) {
 657        env->macsr |= MACSR_PAV0 << acc;
 658        if (env->macsr & MACSR_OMC) {
 659            /* The result is saturated to 32 bits, despite overflow occurring
 660               at 48 bits.  Seems weird, but that's what the hardware docs
 661               say.  */
 662            result = (result >> 63) ^ 0x7fffffff;
 663        }
 664    }
 665    env->macc[acc] = result;
 666}
 667
 668void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
 669{
 670    uint64_t val;
 671
 672    val = env->macc[acc];
 673    if (val & (0xffffull << 48)) {
 674        env->macsr |= MACSR_V;
 675    }
 676    if (env->macsr & MACSR_V) {
 677        env->macsr |= MACSR_PAV0 << acc;
 678        if (env->macsr & MACSR_OMC) {
 679            if (val > (1ull << 53))
 680                val = 0;
 681            else
 682                val = (1ull << 48) - 1;
 683        } else {
 684            val &= ((1ull << 48) - 1);
 685        }
 686    }
 687    env->macc[acc] = val;
 688}
 689
 690void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
 691{
 692    int64_t sum;
 693    int64_t result;
 694
 695    sum = env->macc[acc];
 696    result = (sum << 16) >> 16;
 697    if (result != sum) {
 698        env->macsr |= MACSR_V;
 699    }
 700    if (env->macsr & MACSR_V) {
 701        env->macsr |= MACSR_PAV0 << acc;
 702        if (env->macsr & MACSR_OMC) {
 703            result = (result >> 63) ^ 0x7fffffffffffll;
 704        }
 705    }
 706    env->macc[acc] = result;
 707}
 708
 709void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
 710{
 711    uint64_t val;
 712    val = env->macc[acc];
 713    if (val == 0) {
 714        env->macsr |= MACSR_Z;
 715    } else if (val & (1ull << 47)) {
 716        env->macsr |= MACSR_N;
 717    }
 718    if (env->macsr & (MACSR_PAV0 << acc)) {
 719        env->macsr |= MACSR_V;
 720    }
 721    if (env->macsr & MACSR_FI) {
 722        val = ((int64_t)val) >> 40;
 723        if (val != 0 && val != -1)
 724            env->macsr |= MACSR_EV;
 725    } else if (env->macsr & MACSR_SU) {
 726        val = ((int64_t)val) >> 32;
 727        if (val != 0 && val != -1)
 728            env->macsr |= MACSR_EV;
 729    } else {
 730        if ((val >> 32) != 0)
 731            env->macsr |= MACSR_EV;
 732    }
 733}
 734
 735void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
 736{
 737    cpu_m68k_flush_flags(env, cc_op);
 738}
 739
 740uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
 741{
 742    int rem;
 743    uint32_t result;
 744
 745    if (env->macsr & MACSR_SU) {
 746        /* 16-bit rounding.  */
 747        rem = val & 0xffffff;
 748        val = (val >> 24) & 0xffffu;
 749        if (rem > 0x800000)
 750            val++;
 751        else if (rem == 0x800000)
 752            val += (val & 1);
 753    } else if (env->macsr & MACSR_RT) {
 754        /* 32-bit rounding.  */
 755        rem = val & 0xff;
 756        val >>= 8;
 757        if (rem > 0x80)
 758            val++;
 759        else if (rem == 0x80)
 760            val += (val & 1);
 761    } else {
 762        /* No rounding.  */
 763        val >>= 8;
 764    }
 765    if (env->macsr & MACSR_OMC) {
 766        /* Saturate.  */
 767        if (env->macsr & MACSR_SU) {
 768            if (val != (uint16_t) val) {
 769                result = ((val >> 63) ^ 0x7fff) & 0xffff;
 770            } else {
 771                result = val & 0xffff;
 772            }
 773        } else {
 774            if (val != (uint32_t)val) {
 775                result = ((uint32_t)(val >> 63) & 0x7fffffff);
 776            } else {
 777                result = (uint32_t)val;
 778            }
 779        }
 780    } else {
 781        /* No saturation.  */
 782        if (env->macsr & MACSR_SU) {
 783            result = val & 0xffff;
 784        } else {
 785            result = (uint32_t)val;
 786        }
 787    }
 788    return result;
 789}
 790
 791uint32_t HELPER(get_macs)(uint64_t val)
 792{
 793    if (val == (int32_t)val) {
 794        return (int32_t)val;
 795    } else {
 796        return (val >> 61) ^ ~SIGNBIT;
 797    }
 798}
 799
 800uint32_t HELPER(get_macu)(uint64_t val)
 801{
 802    if ((val >> 32) == 0) {
 803        return (uint32_t)val;
 804    } else {
 805        return 0xffffffffu;
 806    }
 807}
 808
 809uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
 810{
 811    uint32_t val;
 812    val = env->macc[acc] & 0x00ff;
 813    val = (env->macc[acc] >> 32) & 0xff00;
 814    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
 815    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
 816    return val;
 817}
 818
 819uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
 820{
 821    uint32_t val;
 822    val = (env->macc[acc] >> 32) & 0xffff;
 823    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
 824    return val;
 825}
 826
 827void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
 828{
 829    int64_t res;
 830    int32_t tmp;
 831    res = env->macc[acc] & 0xffffffff00ull;
 832    tmp = (int16_t)(val & 0xff00);
 833    res |= ((int64_t)tmp) << 32;
 834    res |= val & 0xff;
 835    env->macc[acc] = res;
 836    res = env->macc[acc + 1] & 0xffffffff00ull;
 837    tmp = (val & 0xff000000);
 838    res |= ((int64_t)tmp) << 16;
 839    res |= (val >> 16) & 0xff;
 840    env->macc[acc + 1] = res;
 841}
 842
 843void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
 844{
 845    int64_t res;
 846    int32_t tmp;
 847    res = (uint32_t)env->macc[acc];
 848    tmp = (int16_t)val;
 849    res |= ((int64_t)tmp) << 32;
 850    env->macc[acc] = res;
 851    res = (uint32_t)env->macc[acc + 1];
 852    tmp = val & 0xffff0000;
 853    res |= (int64_t)tmp << 16;
 854    env->macc[acc + 1] = res;
 855}
 856
 857void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
 858{
 859    uint64_t res;
 860    res = (uint32_t)env->macc[acc];
 861    res |= ((uint64_t)(val & 0xffff)) << 32;
 862    env->macc[acc] = res;
 863    res = (uint32_t)env->macc[acc + 1];
 864    res |= (uint64_t)(val & 0xffff0000) << 16;
 865    env->macc[acc + 1] = res;
 866}
 867
 868void m68k_cpu_exec_enter(CPUState *cs)
 869{
 870    M68kCPU *cpu = M68K_CPU(cs);
 871    CPUM68KState *env = &cpu->env;
 872
 873    env->cc_op = CC_OP_FLAGS;
 874    env->cc_dest = env->sr & 0xf;
 875    env->cc_x = (env->sr >> 4) & 1;
 876}
 877
 878void m68k_cpu_exec_exit(CPUState *cs)
 879{
 880    M68kCPU *cpu = M68K_CPU(cs);
 881    CPUM68KState *env = &cpu->env;
 882
 883    cpu_m68k_flush_flags(env, env->cc_op);
 884    env->cc_op = CC_OP_FLAGS;
 885    env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
 886}
 887