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 cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
  77{
  78    if (n < 8) {
  79        float_status s;
  80        stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
  81        return 8;
  82    }
  83    switch (n) {
  84    case 8: /* fpcontrol */
  85        stl_be_p(mem_buf, env->fpcr);
  86        return 4;
  87    case 9: /* fpstatus */
  88        stl_be_p(mem_buf, env->fpsr);
  89        return 4;
  90    case 10: /* fpiar, not implemented */
  91        memset(mem_buf, 0, 4);
  92        return 4;
  93    }
  94    return 0;
  95}
  96
  97static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
  98{
  99    if (n < 8) {
 100        float_status s;
 101        env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
 102        return 8;
 103    }
 104    switch (n) {
 105    case 8: /* fpcontrol */
 106        cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
 107        return 4;
 108    case 9: /* fpstatus */
 109        env->fpsr = ldl_p(mem_buf);
 110        return 4;
 111    case 10: /* fpiar, not implemented */
 112        return 4;
 113    }
 114    return 0;
 115}
 116
 117static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
 118{
 119    if (n < 8) {
 120        stw_be_p(mem_buf, env->fregs[n].l.upper);
 121        memset(mem_buf + 2, 0, 2);
 122        stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
 123        return 12;
 124    }
 125    switch (n) {
 126    case 8: /* fpcontrol */
 127        stl_be_p(mem_buf, env->fpcr);
 128        return 4;
 129    case 9: /* fpstatus */
 130        stl_be_p(mem_buf, env->fpsr);
 131        return 4;
 132    case 10: /* fpiar, not implemented */
 133        memset(mem_buf, 0, 4);
 134        return 4;
 135    }
 136    return 0;
 137}
 138
 139static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
 140{
 141    if (n < 8) {
 142        env->fregs[n].l.upper = lduw_be_p(mem_buf);
 143        env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
 144        return 12;
 145    }
 146    switch (n) {
 147    case 8: /* fpcontrol */
 148        cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
 149        return 4;
 150    case 9: /* fpstatus */
 151        env->fpsr = ldl_p(mem_buf);
 152        return 4;
 153    case 10: /* fpiar, not implemented */
 154        return 4;
 155    }
 156    return 0;
 157}
 158
 159M68kCPU *cpu_m68k_init(const char *cpu_model)
 160{
 161    M68kCPU *cpu;
 162    CPUM68KState *env;
 163    ObjectClass *oc;
 164
 165    oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
 166    if (oc == NULL) {
 167        return NULL;
 168    }
 169    cpu = M68K_CPU(object_new(object_class_get_name(oc)));
 170    env = &cpu->env;
 171
 172    register_m68k_insns(env);
 173
 174    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 175
 176    return cpu;
 177}
 178
 179void m68k_cpu_init_gdb(M68kCPU *cpu)
 180{
 181    CPUState *cs = CPU(cpu);
 182    CPUM68KState *env = &cpu->env;
 183
 184    if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
 185        gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
 186                                 11, "cf-fp.xml", 18);
 187    } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
 188        gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
 189                                 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
 190    }
 191    /* TODO: Add [E]MAC registers.  */
 192}
 193
 194void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
 195{
 196    M68kCPU *cpu = m68k_env_get_cpu(env);
 197
 198    switch (reg) {
 199    case 0x02: /* CACR */
 200        env->cacr = val;
 201        m68k_switch_sp(env);
 202        break;
 203    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
 204        /* TODO: Implement Access Control Registers.  */
 205        break;
 206    case 0x801: /* VBR */
 207        env->vbr = val;
 208        break;
 209    /* TODO: Implement control registers.  */
 210    default:
 211        cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
 212                  reg, val);
 213    }
 214}
 215
 216void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 217{
 218    uint32_t acc;
 219    int8_t exthigh;
 220    uint8_t extlow;
 221    uint64_t regval;
 222    int i;
 223    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
 224        for (i = 0; i < 4; i++) {
 225            regval = env->macc[i];
 226            exthigh = regval >> 40;
 227            if (env->macsr & MACSR_FI) {
 228                acc = regval >> 8;
 229                extlow = regval;
 230            } else {
 231                acc = regval;
 232                extlow = regval >> 32;
 233            }
 234            if (env->macsr & MACSR_FI) {
 235                regval = (((uint64_t)acc) << 8) | extlow;
 236                regval |= ((int64_t)exthigh) << 40;
 237            } else if (env->macsr & MACSR_SU) {
 238                regval = acc | (((int64_t)extlow) << 32);
 239                regval |= ((int64_t)exthigh) << 40;
 240            } else {
 241                regval = acc | (((uint64_t)extlow) << 32);
 242                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
 243            }
 244            env->macc[i] = regval;
 245        }
 246    }
 247    env->macsr = val;
 248}
 249
 250void m68k_switch_sp(CPUM68KState *env)
 251{
 252    int new_sp;
 253
 254    env->sp[env->current_sp] = env->aregs[7];
 255    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
 256             ? M68K_SSP : M68K_USP;
 257    env->aregs[7] = env->sp[new_sp];
 258    env->current_sp = new_sp;
 259}
 260
 261#if defined(CONFIG_USER_ONLY)
 262
 263int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 264                              int mmu_idx)
 265{
 266    M68kCPU *cpu = M68K_CPU(cs);
 267
 268    cs->exception_index = EXCP_ACCESS;
 269    cpu->env.mmu.ar = address;
 270    return 1;
 271}
 272
 273#else
 274
 275/* MMU */
 276
 277/* TODO: This will need fixing once the MMU is implemented.  */
 278hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 279{
 280    return addr;
 281}
 282
 283int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 284                              int mmu_idx)
 285{
 286    int prot;
 287
 288    address &= TARGET_PAGE_MASK;
 289    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 290    tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
 291    return 0;
 292}
 293
 294/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
 295   be handled by the interrupt controller.  Real hardware only requests
 296   the vector when the interrupt is acknowledged by the CPU.  For
 297   simplicitly we calculate it when the interrupt is signalled.  */
 298void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 299{
 300    CPUState *cs = CPU(cpu);
 301    CPUM68KState *env = &cpu->env;
 302
 303    env->pending_level = level;
 304    env->pending_vector = vector;
 305    if (level) {
 306        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
 307    } else {
 308        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 309    }
 310}
 311
 312#endif
 313
 314uint32_t HELPER(bitrev)(uint32_t x)
 315{
 316    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
 317    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
 318    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
 319    return bswap32(x);
 320}
 321
 322uint32_t HELPER(ff1)(uint32_t x)
 323{
 324    int n;
 325    for (n = 32; x; n--)
 326        x >>= 1;
 327    return n;
 328}
 329
 330uint32_t HELPER(sats)(uint32_t val, uint32_t v)
 331{
 332    /* The result has the opposite sign to the original value.  */
 333    if ((int32_t)v < 0) {
 334        val = (((int32_t)val) >> 31) ^ SIGNBIT;
 335    }
 336    return val;
 337}
 338
 339void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
 340{
 341    env->sr = val & 0xffe0;
 342    cpu_m68k_set_ccr(env, val);
 343    m68k_switch_sp(env);
 344}
 345
 346
 347/* MAC unit.  */
 348/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
 349   take values,  others take register numbers and manipulate the contents
 350   in-place.  */
 351void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
 352{
 353    uint32_t mask;
 354    env->macc[dest] = env->macc[src];
 355    mask = MACSR_PAV0 << dest;
 356    if (env->macsr & (MACSR_PAV0 << src))
 357        env->macsr |= mask;
 358    else
 359        env->macsr &= ~mask;
 360}
 361
 362uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 363{
 364    int64_t product;
 365    int64_t res;
 366
 367    product = (uint64_t)op1 * op2;
 368    res = (product << 24) >> 24;
 369    if (res != product) {
 370        env->macsr |= MACSR_V;
 371        if (env->macsr & MACSR_OMC) {
 372            /* Make sure the accumulate operation overflows.  */
 373            if (product < 0)
 374                res = ~(1ll << 50);
 375            else
 376                res = 1ll << 50;
 377        }
 378    }
 379    return res;
 380}
 381
 382uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 383{
 384    uint64_t product;
 385
 386    product = (uint64_t)op1 * op2;
 387    if (product & (0xffffffull << 40)) {
 388        env->macsr |= MACSR_V;
 389        if (env->macsr & MACSR_OMC) {
 390            /* Make sure the accumulate operation overflows.  */
 391            product = 1ll << 50;
 392        } else {
 393            product &= ((1ull << 40) - 1);
 394        }
 395    }
 396    return product;
 397}
 398
 399uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
 400{
 401    uint64_t product;
 402    uint32_t remainder;
 403
 404    product = (uint64_t)op1 * op2;
 405    if (env->macsr & MACSR_RT) {
 406        remainder = product & 0xffffff;
 407        product >>= 24;
 408        if (remainder > 0x800000)
 409            product++;
 410        else if (remainder == 0x800000)
 411            product += (product & 1);
 412    } else {
 413        product >>= 24;
 414    }
 415    return product;
 416}
 417
 418void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
 419{
 420    int64_t tmp;
 421    int64_t result;
 422    tmp = env->macc[acc];
 423    result = ((tmp << 16) >> 16);
 424    if (result != tmp) {
 425        env->macsr |= MACSR_V;
 426    }
 427    if (env->macsr & MACSR_V) {
 428        env->macsr |= MACSR_PAV0 << acc;
 429        if (env->macsr & MACSR_OMC) {
 430            /* The result is saturated to 32 bits, despite overflow occurring
 431               at 48 bits.  Seems weird, but that's what the hardware docs
 432               say.  */
 433            result = (result >> 63) ^ 0x7fffffff;
 434        }
 435    }
 436    env->macc[acc] = result;
 437}
 438
 439void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
 440{
 441    uint64_t val;
 442
 443    val = env->macc[acc];
 444    if (val & (0xffffull << 48)) {
 445        env->macsr |= MACSR_V;
 446    }
 447    if (env->macsr & MACSR_V) {
 448        env->macsr |= MACSR_PAV0 << acc;
 449        if (env->macsr & MACSR_OMC) {
 450            if (val > (1ull << 53))
 451                val = 0;
 452            else
 453                val = (1ull << 48) - 1;
 454        } else {
 455            val &= ((1ull << 48) - 1);
 456        }
 457    }
 458    env->macc[acc] = val;
 459}
 460
 461void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
 462{
 463    int64_t sum;
 464    int64_t result;
 465
 466    sum = env->macc[acc];
 467    result = (sum << 16) >> 16;
 468    if (result != sum) {
 469        env->macsr |= MACSR_V;
 470    }
 471    if (env->macsr & MACSR_V) {
 472        env->macsr |= MACSR_PAV0 << acc;
 473        if (env->macsr & MACSR_OMC) {
 474            result = (result >> 63) ^ 0x7fffffffffffll;
 475        }
 476    }
 477    env->macc[acc] = result;
 478}
 479
 480void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
 481{
 482    uint64_t val;
 483    val = env->macc[acc];
 484    if (val == 0) {
 485        env->macsr |= MACSR_Z;
 486    } else if (val & (1ull << 47)) {
 487        env->macsr |= MACSR_N;
 488    }
 489    if (env->macsr & (MACSR_PAV0 << acc)) {
 490        env->macsr |= MACSR_V;
 491    }
 492    if (env->macsr & MACSR_FI) {
 493        val = ((int64_t)val) >> 40;
 494        if (val != 0 && val != -1)
 495            env->macsr |= MACSR_EV;
 496    } else if (env->macsr & MACSR_SU) {
 497        val = ((int64_t)val) >> 32;
 498        if (val != 0 && val != -1)
 499            env->macsr |= MACSR_EV;
 500    } else {
 501        if ((val >> 32) != 0)
 502            env->macsr |= MACSR_EV;
 503    }
 504}
 505
 506#define EXTSIGN(val, index) (     \
 507    (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
 508)
 509
 510#define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
 511    switch (op) {                                                          \
 512    case CC_OP_FLAGS:                                                      \
 513        /* Everything in place.  */                                        \
 514        break;                                                             \
 515    case CC_OP_ADDB:                                                       \
 516    case CC_OP_ADDW:                                                       \
 517    case CC_OP_ADDL:                                                       \
 518        res = n;                                                           \
 519        src2 = v;                                                          \
 520        src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
 521        c = x;                                                             \
 522        z = n;                                                             \
 523        v = (res ^ src1) & ~(src1 ^ src2);                                 \
 524        break;                                                             \
 525    case CC_OP_SUBB:                                                       \
 526    case CC_OP_SUBW:                                                       \
 527    case CC_OP_SUBL:                                                       \
 528        res = n;                                                           \
 529        src2 = v;                                                          \
 530        src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
 531        c = x;                                                             \
 532        z = n;                                                             \
 533        v = (res ^ src1) & (src1 ^ src2);                                  \
 534        break;                                                             \
 535    case CC_OP_CMPB:                                                       \
 536    case CC_OP_CMPW:                                                       \
 537    case CC_OP_CMPL:                                                       \
 538        src1 = n;                                                          \
 539        src2 = v;                                                          \
 540        res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
 541        n = res;                                                           \
 542        z = res;                                                           \
 543        c = src1 < src2;                                                   \
 544        v = (res ^ src1) & (src1 ^ src2);                                  \
 545        break;                                                             \
 546    case CC_OP_LOGIC:                                                      \
 547        c = v = 0;                                                         \
 548        z = n;                                                             \
 549        break;                                                             \
 550    default:                                                               \
 551        cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op);         \
 552    }                                                                      \
 553} while (0)
 554
 555uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
 556{
 557    uint32_t x, c, n, z, v;
 558    uint32_t res, src1, src2;
 559
 560    x = env->cc_x;
 561    n = env->cc_n;
 562    z = env->cc_z;
 563    v = env->cc_v;
 564    c = env->cc_c;
 565
 566    COMPUTE_CCR(env->cc_op, x, n, z, v, c);
 567
 568    n = n >> 31;
 569    z = (z == 0);
 570    v = v >> 31;
 571
 572    return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
 573}
 574
 575uint32_t HELPER(get_ccr)(CPUM68KState *env)
 576{
 577    return cpu_m68k_get_ccr(env);
 578}
 579
 580void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
 581{
 582    env->cc_x = (ccr & CCF_X ? 1 : 0);
 583    env->cc_n = (ccr & CCF_N ? -1 : 0);
 584    env->cc_z = (ccr & CCF_Z ? 0 : 1);
 585    env->cc_v = (ccr & CCF_V ? -1 : 0);
 586    env->cc_c = (ccr & CCF_C ? 1 : 0);
 587    env->cc_op = CC_OP_FLAGS;
 588}
 589
 590void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
 591{
 592    cpu_m68k_set_ccr(env, ccr);
 593}
 594
 595void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
 596{
 597    uint32_t res, src1, src2;
 598
 599    COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
 600    env->cc_op = CC_OP_FLAGS;
 601}
 602
 603uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
 604{
 605    int rem;
 606    uint32_t result;
 607
 608    if (env->macsr & MACSR_SU) {
 609        /* 16-bit rounding.  */
 610        rem = val & 0xffffff;
 611        val = (val >> 24) & 0xffffu;
 612        if (rem > 0x800000)
 613            val++;
 614        else if (rem == 0x800000)
 615            val += (val & 1);
 616    } else if (env->macsr & MACSR_RT) {
 617        /* 32-bit rounding.  */
 618        rem = val & 0xff;
 619        val >>= 8;
 620        if (rem > 0x80)
 621            val++;
 622        else if (rem == 0x80)
 623            val += (val & 1);
 624    } else {
 625        /* No rounding.  */
 626        val >>= 8;
 627    }
 628    if (env->macsr & MACSR_OMC) {
 629        /* Saturate.  */
 630        if (env->macsr & MACSR_SU) {
 631            if (val != (uint16_t) val) {
 632                result = ((val >> 63) ^ 0x7fff) & 0xffff;
 633            } else {
 634                result = val & 0xffff;
 635            }
 636        } else {
 637            if (val != (uint32_t)val) {
 638                result = ((uint32_t)(val >> 63) & 0x7fffffff);
 639            } else {
 640                result = (uint32_t)val;
 641            }
 642        }
 643    } else {
 644        /* No saturation.  */
 645        if (env->macsr & MACSR_SU) {
 646            result = val & 0xffff;
 647        } else {
 648            result = (uint32_t)val;
 649        }
 650    }
 651    return result;
 652}
 653
 654uint32_t HELPER(get_macs)(uint64_t val)
 655{
 656    if (val == (int32_t)val) {
 657        return (int32_t)val;
 658    } else {
 659        return (val >> 61) ^ ~SIGNBIT;
 660    }
 661}
 662
 663uint32_t HELPER(get_macu)(uint64_t val)
 664{
 665    if ((val >> 32) == 0) {
 666        return (uint32_t)val;
 667    } else {
 668        return 0xffffffffu;
 669    }
 670}
 671
 672uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
 673{
 674    uint32_t val;
 675    val = env->macc[acc] & 0x00ff;
 676    val |= (env->macc[acc] >> 32) & 0xff00;
 677    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
 678    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
 679    return val;
 680}
 681
 682uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
 683{
 684    uint32_t val;
 685    val = (env->macc[acc] >> 32) & 0xffff;
 686    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
 687    return val;
 688}
 689
 690void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
 691{
 692    int64_t res;
 693    int32_t tmp;
 694    res = env->macc[acc] & 0xffffffff00ull;
 695    tmp = (int16_t)(val & 0xff00);
 696    res |= ((int64_t)tmp) << 32;
 697    res |= val & 0xff;
 698    env->macc[acc] = res;
 699    res = env->macc[acc + 1] & 0xffffffff00ull;
 700    tmp = (val & 0xff000000);
 701    res |= ((int64_t)tmp) << 16;
 702    res |= (val >> 16) & 0xff;
 703    env->macc[acc + 1] = res;
 704}
 705
 706void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
 707{
 708    int64_t res;
 709    int32_t tmp;
 710    res = (uint32_t)env->macc[acc];
 711    tmp = (int16_t)val;
 712    res |= ((int64_t)tmp) << 32;
 713    env->macc[acc] = res;
 714    res = (uint32_t)env->macc[acc + 1];
 715    tmp = val & 0xffff0000;
 716    res |= (int64_t)tmp << 16;
 717    env->macc[acc + 1] = res;
 718}
 719
 720void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
 721{
 722    uint64_t res;
 723    res = (uint32_t)env->macc[acc];
 724    res |= ((uint64_t)(val & 0xffff)) << 32;
 725    env->macc[acc] = res;
 726    res = (uint32_t)env->macc[acc + 1];
 727    res |= (uint64_t)(val & 0xffff0000) << 16;
 728    env->macc[acc + 1] = res;
 729}
 730