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