qemu/target/m68k/translate.c
<<
>>
Prefs
   1/*
   2 *  m68k translation
   3 *
   4 *  Copyright (c) 2005-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.1 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 * Lesser 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 "disas/disas.h"
  24#include "exec/exec-all.h"
  25#include "tcg/tcg-op.h"
  26#include "qemu/log.h"
  27#include "qemu/qemu-print.h"
  28#include "exec/cpu_ldst.h"
  29#include "exec/translator.h"
  30
  31#include "exec/helper-proto.h"
  32#include "exec/helper-gen.h"
  33
  34#include "exec/log.h"
  35#include "fpu/softfloat.h"
  36
  37
  38//#define DEBUG_DISPATCH 1
  39
  40#define DEFO32(name, offset) static TCGv QREG_##name;
  41#define DEFO64(name, offset) static TCGv_i64 QREG_##name;
  42#include "qregs.def"
  43#undef DEFO32
  44#undef DEFO64
  45
  46static TCGv_i32 cpu_halted;
  47static TCGv_i32 cpu_exception_index;
  48
  49static char cpu_reg_names[2 * 8 * 3 + 5 * 4];
  50static TCGv cpu_dregs[8];
  51static TCGv cpu_aregs[8];
  52static TCGv_i64 cpu_macc[4];
  53
  54#define REG(insn, pos)  (((insn) >> (pos)) & 7)
  55#define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
  56#define AREG(insn, pos) get_areg(s, REG(insn, pos))
  57#define MACREG(acc)     cpu_macc[acc]
  58#define QREG_SP         get_areg(s, 7)
  59
  60static TCGv NULL_QREG;
  61#define IS_NULL_QREG(t) (t == NULL_QREG)
  62/* Used to distinguish stores from bad addressing modes.  */
  63static TCGv store_dummy;
  64
  65#include "exec/gen-icount.h"
  66
  67void m68k_tcg_init(void)
  68{
  69    char *p;
  70    int i;
  71
  72#define DEFO32(name, offset) \
  73    QREG_##name = tcg_global_mem_new_i32(cpu_env, \
  74        offsetof(CPUM68KState, offset), #name);
  75#define DEFO64(name, offset) \
  76    QREG_##name = tcg_global_mem_new_i64(cpu_env, \
  77        offsetof(CPUM68KState, offset), #name);
  78#include "qregs.def"
  79#undef DEFO32
  80#undef DEFO64
  81
  82    cpu_halted = tcg_global_mem_new_i32(cpu_env,
  83                                        -offsetof(M68kCPU, env) +
  84                                        offsetof(CPUState, halted), "HALTED");
  85    cpu_exception_index = tcg_global_mem_new_i32(cpu_env,
  86                                                 -offsetof(M68kCPU, env) +
  87                                                 offsetof(CPUState, exception_index),
  88                                                 "EXCEPTION");
  89
  90    p = cpu_reg_names;
  91    for (i = 0; i < 8; i++) {
  92        sprintf(p, "D%d", i);
  93        cpu_dregs[i] = tcg_global_mem_new(cpu_env,
  94                                          offsetof(CPUM68KState, dregs[i]), p);
  95        p += 3;
  96        sprintf(p, "A%d", i);
  97        cpu_aregs[i] = tcg_global_mem_new(cpu_env,
  98                                          offsetof(CPUM68KState, aregs[i]), p);
  99        p += 3;
 100    }
 101    for (i = 0; i < 4; i++) {
 102        sprintf(p, "ACC%d", i);
 103        cpu_macc[i] = tcg_global_mem_new_i64(cpu_env,
 104                                         offsetof(CPUM68KState, macc[i]), p);
 105        p += 5;
 106    }
 107
 108    NULL_QREG = tcg_global_mem_new(cpu_env, -4, "NULL");
 109    store_dummy = tcg_global_mem_new(cpu_env, -8, "NULL");
 110}
 111
 112/* internal defines */
 113typedef struct DisasContext {
 114    DisasContextBase base;
 115    CPUM68KState *env;
 116    target_ulong pc;
 117    CCOp cc_op; /* Current CC operation */
 118    int cc_op_synced;
 119    TCGv_i64 mactmp;
 120    int done_mac;
 121    int writeback_mask;
 122    TCGv writeback[8];
 123#define MAX_TO_RELEASE 8
 124    int release_count;
 125    TCGv release[MAX_TO_RELEASE];
 126    bool ss_active;
 127} DisasContext;
 128
 129static void init_release_array(DisasContext *s)
 130{
 131#ifdef CONFIG_DEBUG_TCG
 132    memset(s->release, 0, sizeof(s->release));
 133#endif
 134    s->release_count = 0;
 135}
 136
 137static void do_release(DisasContext *s)
 138{
 139    int i;
 140    for (i = 0; i < s->release_count; i++) {
 141        tcg_temp_free(s->release[i]);
 142    }
 143    init_release_array(s);
 144}
 145
 146static TCGv mark_to_release(DisasContext *s, TCGv tmp)
 147{
 148    g_assert(s->release_count < MAX_TO_RELEASE);
 149    return s->release[s->release_count++] = tmp;
 150}
 151
 152static TCGv get_areg(DisasContext *s, unsigned regno)
 153{
 154    if (s->writeback_mask & (1 << regno)) {
 155        return s->writeback[regno];
 156    } else {
 157        return cpu_aregs[regno];
 158    }
 159}
 160
 161static void delay_set_areg(DisasContext *s, unsigned regno,
 162                           TCGv val, bool give_temp)
 163{
 164    if (s->writeback_mask & (1 << regno)) {
 165        if (give_temp) {
 166            tcg_temp_free(s->writeback[regno]);
 167            s->writeback[regno] = val;
 168        } else {
 169            tcg_gen_mov_i32(s->writeback[regno], val);
 170        }
 171    } else {
 172        s->writeback_mask |= 1 << regno;
 173        if (give_temp) {
 174            s->writeback[regno] = val;
 175        } else {
 176            TCGv tmp = tcg_temp_new();
 177            s->writeback[regno] = tmp;
 178            tcg_gen_mov_i32(tmp, val);
 179        }
 180    }
 181}
 182
 183static void do_writebacks(DisasContext *s)
 184{
 185    unsigned mask = s->writeback_mask;
 186    if (mask) {
 187        s->writeback_mask = 0;
 188        do {
 189            unsigned regno = ctz32(mask);
 190            tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]);
 191            tcg_temp_free(s->writeback[regno]);
 192            mask &= mask - 1;
 193        } while (mask);
 194    }
 195}
 196
 197/* is_jmp field values */
 198#define DISAS_JUMP      DISAS_TARGET_0 /* only pc was modified dynamically */
 199#define DISAS_EXIT      DISAS_TARGET_1 /* cpu state was modified dynamically */
 200
 201#if defined(CONFIG_USER_ONLY)
 202#define IS_USER(s) 1
 203#else
 204#define IS_USER(s)   (!(s->base.tb->flags & TB_FLAGS_MSR_S))
 205#define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \
 206                      MMU_KERNEL_IDX : MMU_USER_IDX)
 207#define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \
 208                      MMU_KERNEL_IDX : MMU_USER_IDX)
 209#endif
 210
 211typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
 212
 213#ifdef DEBUG_DISPATCH
 214#define DISAS_INSN(name)                                                \
 215    static void real_disas_##name(CPUM68KState *env, DisasContext *s,   \
 216                                  uint16_t insn);                       \
 217    static void disas_##name(CPUM68KState *env, DisasContext *s,        \
 218                             uint16_t insn)                             \
 219    {                                                                   \
 220        qemu_log("Dispatch " #name "\n");                               \
 221        real_disas_##name(env, s, insn);                                \
 222    }                                                                   \
 223    static void real_disas_##name(CPUM68KState *env, DisasContext *s,   \
 224                                  uint16_t insn)
 225#else
 226#define DISAS_INSN(name)                                                \
 227    static void disas_##name(CPUM68KState *env, DisasContext *s,        \
 228                             uint16_t insn)
 229#endif
 230
 231static const uint8_t cc_op_live[CC_OP_NB] = {
 232    [CC_OP_DYNAMIC] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
 233    [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
 234    [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V,
 235    [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V,
 236    [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V,
 237    [CC_OP_LOGIC] = CCF_X | CCF_N
 238};
 239
 240static void set_cc_op(DisasContext *s, CCOp op)
 241{
 242    CCOp old_op = s->cc_op;
 243    int dead;
 244
 245    if (old_op == op) {
 246        return;
 247    }
 248    s->cc_op = op;
 249    s->cc_op_synced = 0;
 250
 251    /*
 252     * Discard CC computation that will no longer be used.
 253     * Note that X and N are never dead.
 254     */
 255    dead = cc_op_live[old_op] & ~cc_op_live[op];
 256    if (dead & CCF_C) {
 257        tcg_gen_discard_i32(QREG_CC_C);
 258    }
 259    if (dead & CCF_Z) {
 260        tcg_gen_discard_i32(QREG_CC_Z);
 261    }
 262    if (dead & CCF_V) {
 263        tcg_gen_discard_i32(QREG_CC_V);
 264    }
 265}
 266
 267/* Update the CPU env CC_OP state.  */
 268static void update_cc_op(DisasContext *s)
 269{
 270    if (!s->cc_op_synced) {
 271        s->cc_op_synced = 1;
 272        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
 273    }
 274}
 275
 276/* Generate a jump to an immediate address.  */
 277static void gen_jmp_im(DisasContext *s, uint32_t dest)
 278{
 279    update_cc_op(s);
 280    tcg_gen_movi_i32(QREG_PC, dest);
 281    s->base.is_jmp = DISAS_JUMP;
 282}
 283
 284/* Generate a jump to the address in qreg DEST.  */
 285static void gen_jmp(DisasContext *s, TCGv dest)
 286{
 287    update_cc_op(s);
 288    tcg_gen_mov_i32(QREG_PC, dest);
 289    s->base.is_jmp = DISAS_JUMP;
 290}
 291
 292static void gen_raise_exception(int nr)
 293{
 294    TCGv_i32 tmp;
 295
 296    tmp = tcg_const_i32(nr);
 297    gen_helper_raise_exception(cpu_env, tmp);
 298    tcg_temp_free_i32(tmp);
 299}
 300
 301static void gen_exception(DisasContext *s, uint32_t dest, int nr)
 302{
 303    update_cc_op(s);
 304    tcg_gen_movi_i32(QREG_PC, dest);
 305
 306    gen_raise_exception(nr);
 307
 308    s->base.is_jmp = DISAS_NORETURN;
 309}
 310
 311static inline void gen_addr_fault(DisasContext *s)
 312{
 313    gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
 314}
 315
 316/*
 317 * Generate a load from the specified address.  Narrow values are
 318 *  sign extended to full register width.
 319 */
 320static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
 321                            int sign, int index)
 322{
 323    TCGv tmp;
 324    tmp = tcg_temp_new_i32();
 325    switch(opsize) {
 326    case OS_BYTE:
 327        if (sign)
 328            tcg_gen_qemu_ld8s(tmp, addr, index);
 329        else
 330            tcg_gen_qemu_ld8u(tmp, addr, index);
 331        break;
 332    case OS_WORD:
 333        if (sign)
 334            tcg_gen_qemu_ld16s(tmp, addr, index);
 335        else
 336            tcg_gen_qemu_ld16u(tmp, addr, index);
 337        break;
 338    case OS_LONG:
 339        tcg_gen_qemu_ld32u(tmp, addr, index);
 340        break;
 341    default:
 342        g_assert_not_reached();
 343    }
 344    return tmp;
 345}
 346
 347/* Generate a store.  */
 348static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val,
 349                             int index)
 350{
 351    switch(opsize) {
 352    case OS_BYTE:
 353        tcg_gen_qemu_st8(val, addr, index);
 354        break;
 355    case OS_WORD:
 356        tcg_gen_qemu_st16(val, addr, index);
 357        break;
 358    case OS_LONG:
 359        tcg_gen_qemu_st32(val, addr, index);
 360        break;
 361    default:
 362        g_assert_not_reached();
 363    }
 364}
 365
 366typedef enum {
 367    EA_STORE,
 368    EA_LOADU,
 369    EA_LOADS
 370} ea_what;
 371
 372/*
 373 * Generate an unsigned load if VAL is 0 a signed load if val is -1,
 374 * otherwise generate a store.
 375 */
 376static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
 377                     ea_what what, int index)
 378{
 379    if (what == EA_STORE) {
 380        gen_store(s, opsize, addr, val, index);
 381        return store_dummy;
 382    } else {
 383        return mark_to_release(s, gen_load(s, opsize, addr,
 384                                           what == EA_LOADS, index));
 385    }
 386}
 387
 388/* Read a 16-bit immediate constant */
 389static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
 390{
 391    uint16_t im;
 392    im = translator_lduw(env, &s->base, s->pc);
 393    s->pc += 2;
 394    return im;
 395}
 396
 397/* Read an 8-bit immediate constant */
 398static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
 399{
 400    return read_im16(env, s);
 401}
 402
 403/* Read a 32-bit immediate constant.  */
 404static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
 405{
 406    uint32_t im;
 407    im = read_im16(env, s) << 16;
 408    im |= 0xffff & read_im16(env, s);
 409    return im;
 410}
 411
 412/* Read a 64-bit immediate constant.  */
 413static inline uint64_t read_im64(CPUM68KState *env, DisasContext *s)
 414{
 415    uint64_t im;
 416    im = (uint64_t)read_im32(env, s) << 32;
 417    im |= (uint64_t)read_im32(env, s);
 418    return im;
 419}
 420
 421/* Calculate and address index.  */
 422static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp)
 423{
 424    TCGv add;
 425    int scale;
 426
 427    add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
 428    if ((ext & 0x800) == 0) {
 429        tcg_gen_ext16s_i32(tmp, add);
 430        add = tmp;
 431    }
 432    scale = (ext >> 9) & 3;
 433    if (scale != 0) {
 434        tcg_gen_shli_i32(tmp, add, scale);
 435        add = tmp;
 436    }
 437    return add;
 438}
 439
 440/*
 441 * Handle a base + index + displacement effective address.
 442 * A NULL_QREG base means pc-relative.
 443 */
 444static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
 445{
 446    uint32_t offset;
 447    uint16_t ext;
 448    TCGv add;
 449    TCGv tmp;
 450    uint32_t bd, od;
 451
 452    offset = s->pc;
 453    ext = read_im16(env, s);
 454
 455    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
 456        return NULL_QREG;
 457
 458    if (m68k_feature(s->env, M68K_FEATURE_M68000) &&
 459        !m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) {
 460        ext &= ~(3 << 9);
 461    }
 462
 463    if (ext & 0x100) {
 464        /* full extension word format */
 465        if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
 466            return NULL_QREG;
 467
 468        if ((ext & 0x30) > 0x10) {
 469            /* base displacement */
 470            if ((ext & 0x30) == 0x20) {
 471                bd = (int16_t)read_im16(env, s);
 472            } else {
 473                bd = read_im32(env, s);
 474            }
 475        } else {
 476            bd = 0;
 477        }
 478        tmp = mark_to_release(s, tcg_temp_new());
 479        if ((ext & 0x44) == 0) {
 480            /* pre-index */
 481            add = gen_addr_index(s, ext, tmp);
 482        } else {
 483            add = NULL_QREG;
 484        }
 485        if ((ext & 0x80) == 0) {
 486            /* base not suppressed */
 487            if (IS_NULL_QREG(base)) {
 488                base = mark_to_release(s, tcg_const_i32(offset + bd));
 489                bd = 0;
 490            }
 491            if (!IS_NULL_QREG(add)) {
 492                tcg_gen_add_i32(tmp, add, base);
 493                add = tmp;
 494            } else {
 495                add = base;
 496            }
 497        }
 498        if (!IS_NULL_QREG(add)) {
 499            if (bd != 0) {
 500                tcg_gen_addi_i32(tmp, add, bd);
 501                add = tmp;
 502            }
 503        } else {
 504            add = mark_to_release(s, tcg_const_i32(bd));
 505        }
 506        if ((ext & 3) != 0) {
 507            /* memory indirect */
 508            base = mark_to_release(s, gen_load(s, OS_LONG, add, 0, IS_USER(s)));
 509            if ((ext & 0x44) == 4) {
 510                add = gen_addr_index(s, ext, tmp);
 511                tcg_gen_add_i32(tmp, add, base);
 512                add = tmp;
 513            } else {
 514                add = base;
 515            }
 516            if ((ext & 3) > 1) {
 517                /* outer displacement */
 518                if ((ext & 3) == 2) {
 519                    od = (int16_t)read_im16(env, s);
 520                } else {
 521                    od = read_im32(env, s);
 522                }
 523            } else {
 524                od = 0;
 525            }
 526            if (od != 0) {
 527                tcg_gen_addi_i32(tmp, add, od);
 528                add = tmp;
 529            }
 530        }
 531    } else {
 532        /* brief extension word format */
 533        tmp = mark_to_release(s, tcg_temp_new());
 534        add = gen_addr_index(s, ext, tmp);
 535        if (!IS_NULL_QREG(base)) {
 536            tcg_gen_add_i32(tmp, add, base);
 537            if ((int8_t)ext)
 538                tcg_gen_addi_i32(tmp, tmp, (int8_t)ext);
 539        } else {
 540            tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext);
 541        }
 542        add = tmp;
 543    }
 544    return add;
 545}
 546
 547/* Sign or zero extend a value.  */
 548
 549static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
 550{
 551    switch (opsize) {
 552    case OS_BYTE:
 553        if (sign) {
 554            tcg_gen_ext8s_i32(res, val);
 555        } else {
 556            tcg_gen_ext8u_i32(res, val);
 557        }
 558        break;
 559    case OS_WORD:
 560        if (sign) {
 561            tcg_gen_ext16s_i32(res, val);
 562        } else {
 563            tcg_gen_ext16u_i32(res, val);
 564        }
 565        break;
 566    case OS_LONG:
 567        tcg_gen_mov_i32(res, val);
 568        break;
 569    default:
 570        g_assert_not_reached();
 571    }
 572}
 573
 574/* Evaluate all the CC flags.  */
 575
 576static void gen_flush_flags(DisasContext *s)
 577{
 578    TCGv t0, t1;
 579
 580    switch (s->cc_op) {
 581    case CC_OP_FLAGS:
 582        return;
 583
 584    case CC_OP_ADDB:
 585    case CC_OP_ADDW:
 586    case CC_OP_ADDL:
 587        tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
 588        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
 589        /* Compute signed overflow for addition.  */
 590        t0 = tcg_temp_new();
 591        t1 = tcg_temp_new();
 592        tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
 593        gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1);
 594        tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
 595        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
 596        tcg_temp_free(t0);
 597        tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V);
 598        tcg_temp_free(t1);
 599        break;
 600
 601    case CC_OP_SUBB:
 602    case CC_OP_SUBW:
 603    case CC_OP_SUBL:
 604        tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
 605        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
 606        /* Compute signed overflow for subtraction.  */
 607        t0 = tcg_temp_new();
 608        t1 = tcg_temp_new();
 609        tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
 610        gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1);
 611        tcg_gen_xor_i32(t1, QREG_CC_N, t0);
 612        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
 613        tcg_temp_free(t0);
 614        tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
 615        tcg_temp_free(t1);
 616        break;
 617
 618    case CC_OP_CMPB:
 619    case CC_OP_CMPW:
 620    case CC_OP_CMPL:
 621        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
 622        tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
 623        gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1);
 624        /* Compute signed overflow for subtraction.  */
 625        t0 = tcg_temp_new();
 626        tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
 627        tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N);
 628        tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0);
 629        tcg_temp_free(t0);
 630        tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z);
 631        break;
 632
 633    case CC_OP_LOGIC:
 634        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
 635        tcg_gen_movi_i32(QREG_CC_C, 0);
 636        tcg_gen_movi_i32(QREG_CC_V, 0);
 637        break;
 638
 639    case CC_OP_DYNAMIC:
 640        gen_helper_flush_flags(cpu_env, QREG_CC_OP);
 641        s->cc_op_synced = 1;
 642        break;
 643
 644    default:
 645        t0 = tcg_const_i32(s->cc_op);
 646        gen_helper_flush_flags(cpu_env, t0);
 647        tcg_temp_free(t0);
 648        s->cc_op_synced = 1;
 649        break;
 650    }
 651
 652    /* Note that flush_flags also assigned to env->cc_op.  */
 653    s->cc_op = CC_OP_FLAGS;
 654}
 655
 656static inline TCGv gen_extend(DisasContext *s, TCGv val, int opsize, int sign)
 657{
 658    TCGv tmp;
 659
 660    if (opsize == OS_LONG) {
 661        tmp = val;
 662    } else {
 663        tmp = mark_to_release(s, tcg_temp_new());
 664        gen_ext(tmp, val, opsize, sign);
 665    }
 666
 667    return tmp;
 668}
 669
 670static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
 671{
 672    gen_ext(QREG_CC_N, val, opsize, 1);
 673    set_cc_op(s, CC_OP_LOGIC);
 674}
 675
 676static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize)
 677{
 678    tcg_gen_mov_i32(QREG_CC_N, dest);
 679    tcg_gen_mov_i32(QREG_CC_V, src);
 680    set_cc_op(s, CC_OP_CMPB + opsize);
 681}
 682
 683static void gen_update_cc_add(TCGv dest, TCGv src, int opsize)
 684{
 685    gen_ext(QREG_CC_N, dest, opsize, 1);
 686    tcg_gen_mov_i32(QREG_CC_V, src);
 687}
 688
 689static inline int opsize_bytes(int opsize)
 690{
 691    switch (opsize) {
 692    case OS_BYTE: return 1;
 693    case OS_WORD: return 2;
 694    case OS_LONG: return 4;
 695    case OS_SINGLE: return 4;
 696    case OS_DOUBLE: return 8;
 697    case OS_EXTENDED: return 12;
 698    case OS_PACKED: return 12;
 699    default:
 700        g_assert_not_reached();
 701    }
 702}
 703
 704static inline int insn_opsize(int insn)
 705{
 706    switch ((insn >> 6) & 3) {
 707    case 0: return OS_BYTE;
 708    case 1: return OS_WORD;
 709    case 2: return OS_LONG;
 710    default:
 711        g_assert_not_reached();
 712    }
 713}
 714
 715static inline int ext_opsize(int ext, int pos)
 716{
 717    switch ((ext >> pos) & 7) {
 718    case 0: return OS_LONG;
 719    case 1: return OS_SINGLE;
 720    case 2: return OS_EXTENDED;
 721    case 3: return OS_PACKED;
 722    case 4: return OS_WORD;
 723    case 5: return OS_DOUBLE;
 724    case 6: return OS_BYTE;
 725    default:
 726        g_assert_not_reached();
 727    }
 728}
 729
 730/*
 731 * Assign value to a register.  If the width is less than the register width
 732 * only the low part of the register is set.
 733 */
 734static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
 735{
 736    TCGv tmp;
 737    switch (opsize) {
 738    case OS_BYTE:
 739        tcg_gen_andi_i32(reg, reg, 0xffffff00);
 740        tmp = tcg_temp_new();
 741        tcg_gen_ext8u_i32(tmp, val);
 742        tcg_gen_or_i32(reg, reg, tmp);
 743        tcg_temp_free(tmp);
 744        break;
 745    case OS_WORD:
 746        tcg_gen_andi_i32(reg, reg, 0xffff0000);
 747        tmp = tcg_temp_new();
 748        tcg_gen_ext16u_i32(tmp, val);
 749        tcg_gen_or_i32(reg, reg, tmp);
 750        tcg_temp_free(tmp);
 751        break;
 752    case OS_LONG:
 753    case OS_SINGLE:
 754        tcg_gen_mov_i32(reg, val);
 755        break;
 756    default:
 757        g_assert_not_reached();
 758    }
 759}
 760
 761/*
 762 * Generate code for an "effective address".  Does not adjust the base
 763 * register for autoincrement addressing modes.
 764 */
 765static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
 766                         int mode, int reg0, int opsize)
 767{
 768    TCGv reg;
 769    TCGv tmp;
 770    uint16_t ext;
 771    uint32_t offset;
 772
 773    switch (mode) {
 774    case 0: /* Data register direct.  */
 775    case 1: /* Address register direct.  */
 776        return NULL_QREG;
 777    case 3: /* Indirect postincrement.  */
 778        if (opsize == OS_UNSIZED) {
 779            return NULL_QREG;
 780        }
 781        /* fallthru */
 782    case 2: /* Indirect register */
 783        return get_areg(s, reg0);
 784    case 4: /* Indirect predecrememnt.  */
 785        if (opsize == OS_UNSIZED) {
 786            return NULL_QREG;
 787        }
 788        reg = get_areg(s, reg0);
 789        tmp = mark_to_release(s, tcg_temp_new());
 790        if (reg0 == 7 && opsize == OS_BYTE &&
 791            m68k_feature(s->env, M68K_FEATURE_M68000)) {
 792            tcg_gen_subi_i32(tmp, reg, 2);
 793        } else {
 794            tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
 795        }
 796        return tmp;
 797    case 5: /* Indirect displacement.  */
 798        reg = get_areg(s, reg0);
 799        tmp = mark_to_release(s, tcg_temp_new());
 800        ext = read_im16(env, s);
 801        tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
 802        return tmp;
 803    case 6: /* Indirect index + displacement.  */
 804        reg = get_areg(s, reg0);
 805        return gen_lea_indexed(env, s, reg);
 806    case 7: /* Other */
 807        switch (reg0) {
 808        case 0: /* Absolute short.  */
 809            offset = (int16_t)read_im16(env, s);
 810            return mark_to_release(s, tcg_const_i32(offset));
 811        case 1: /* Absolute long.  */
 812            offset = read_im32(env, s);
 813            return mark_to_release(s, tcg_const_i32(offset));
 814        case 2: /* pc displacement  */
 815            offset = s->pc;
 816            offset += (int16_t)read_im16(env, s);
 817            return mark_to_release(s, tcg_const_i32(offset));
 818        case 3: /* pc index+displacement.  */
 819            return gen_lea_indexed(env, s, NULL_QREG);
 820        case 4: /* Immediate.  */
 821        default:
 822            return NULL_QREG;
 823        }
 824    }
 825    /* Should never happen.  */
 826    return NULL_QREG;
 827}
 828
 829static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
 830                    int opsize)
 831{
 832    int mode = extract32(insn, 3, 3);
 833    int reg0 = REG(insn, 0);
 834    return gen_lea_mode(env, s, mode, reg0, opsize);
 835}
 836
 837/*
 838 * Generate code to load/store a value from/into an EA.  If WHAT > 0 this is
 839 * a write otherwise it is a read (0 == sign extend, -1 == zero extend).
 840 * ADDRP is non-null for readwrite operands.
 841 */
 842static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
 843                        int opsize, TCGv val, TCGv *addrp, ea_what what,
 844                        int index)
 845{
 846    TCGv reg, tmp, result;
 847    int32_t offset;
 848
 849    switch (mode) {
 850    case 0: /* Data register direct.  */
 851        reg = cpu_dregs[reg0];
 852        if (what == EA_STORE) {
 853            gen_partset_reg(opsize, reg, val);
 854            return store_dummy;
 855        } else {
 856            return gen_extend(s, reg, opsize, what == EA_LOADS);
 857        }
 858    case 1: /* Address register direct.  */
 859        reg = get_areg(s, reg0);
 860        if (what == EA_STORE) {
 861            tcg_gen_mov_i32(reg, val);
 862            return store_dummy;
 863        } else {
 864            return gen_extend(s, reg, opsize, what == EA_LOADS);
 865        }
 866    case 2: /* Indirect register */
 867        reg = get_areg(s, reg0);
 868        return gen_ldst(s, opsize, reg, val, what, index);
 869    case 3: /* Indirect postincrement.  */
 870        reg = get_areg(s, reg0);
 871        result = gen_ldst(s, opsize, reg, val, what, index);
 872        if (what == EA_STORE || !addrp) {
 873            TCGv tmp = tcg_temp_new();
 874            if (reg0 == 7 && opsize == OS_BYTE &&
 875                m68k_feature(s->env, M68K_FEATURE_M68000)) {
 876                tcg_gen_addi_i32(tmp, reg, 2);
 877            } else {
 878                tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize));
 879            }
 880            delay_set_areg(s, reg0, tmp, true);
 881        }
 882        return result;
 883    case 4: /* Indirect predecrememnt.  */
 884        if (addrp && what == EA_STORE) {
 885            tmp = *addrp;
 886        } else {
 887            tmp = gen_lea_mode(env, s, mode, reg0, opsize);
 888            if (IS_NULL_QREG(tmp)) {
 889                return tmp;
 890            }
 891            if (addrp) {
 892                *addrp = tmp;
 893            }
 894        }
 895        result = gen_ldst(s, opsize, tmp, val, what, index);
 896        if (what == EA_STORE || !addrp) {
 897            delay_set_areg(s, reg0, tmp, false);
 898        }
 899        return result;
 900    case 5: /* Indirect displacement.  */
 901    case 6: /* Indirect index + displacement.  */
 902    do_indirect:
 903        if (addrp && what == EA_STORE) {
 904            tmp = *addrp;
 905        } else {
 906            tmp = gen_lea_mode(env, s, mode, reg0, opsize);
 907            if (IS_NULL_QREG(tmp)) {
 908                return tmp;
 909            }
 910            if (addrp) {
 911                *addrp = tmp;
 912            }
 913        }
 914        return gen_ldst(s, opsize, tmp, val, what, index);
 915    case 7: /* Other */
 916        switch (reg0) {
 917        case 0: /* Absolute short.  */
 918        case 1: /* Absolute long.  */
 919        case 2: /* pc displacement  */
 920        case 3: /* pc index+displacement.  */
 921            goto do_indirect;
 922        case 4: /* Immediate.  */
 923            /* Sign extend values for consistency.  */
 924            switch (opsize) {
 925            case OS_BYTE:
 926                if (what == EA_LOADS) {
 927                    offset = (int8_t)read_im8(env, s);
 928                } else {
 929                    offset = read_im8(env, s);
 930                }
 931                break;
 932            case OS_WORD:
 933                if (what == EA_LOADS) {
 934                    offset = (int16_t)read_im16(env, s);
 935                } else {
 936                    offset = read_im16(env, s);
 937                }
 938                break;
 939            case OS_LONG:
 940                offset = read_im32(env, s);
 941                break;
 942            default:
 943                g_assert_not_reached();
 944            }
 945            return mark_to_release(s, tcg_const_i32(offset));
 946        default:
 947            return NULL_QREG;
 948        }
 949    }
 950    /* Should never happen.  */
 951    return NULL_QREG;
 952}
 953
 954static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
 955                   int opsize, TCGv val, TCGv *addrp, ea_what what, int index)
 956{
 957    int mode = extract32(insn, 3, 3);
 958    int reg0 = REG(insn, 0);
 959    return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what, index);
 960}
 961
 962static TCGv_ptr gen_fp_ptr(int freg)
 963{
 964    TCGv_ptr fp = tcg_temp_new_ptr();
 965    tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fregs[freg]));
 966    return fp;
 967}
 968
 969static TCGv_ptr gen_fp_result_ptr(void)
 970{
 971    TCGv_ptr fp = tcg_temp_new_ptr();
 972    tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fp_result));
 973    return fp;
 974}
 975
 976static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src)
 977{
 978    TCGv t32;
 979    TCGv_i64 t64;
 980
 981    t32 = tcg_temp_new();
 982    tcg_gen_ld16u_i32(t32, src, offsetof(FPReg, l.upper));
 983    tcg_gen_st16_i32(t32, dest, offsetof(FPReg, l.upper));
 984    tcg_temp_free(t32);
 985
 986    t64 = tcg_temp_new_i64();
 987    tcg_gen_ld_i64(t64, src, offsetof(FPReg, l.lower));
 988    tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower));
 989    tcg_temp_free_i64(t64);
 990}
 991
 992static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
 993                        int index)
 994{
 995    TCGv tmp;
 996    TCGv_i64 t64;
 997
 998    t64 = tcg_temp_new_i64();
 999    tmp = tcg_temp_new();
1000    switch (opsize) {
1001    case OS_BYTE:
1002        tcg_gen_qemu_ld8s(tmp, addr, index);
1003        gen_helper_exts32(cpu_env, fp, tmp);
1004        break;
1005    case OS_WORD:
1006        tcg_gen_qemu_ld16s(tmp, addr, index);
1007        gen_helper_exts32(cpu_env, fp, tmp);
1008        break;
1009    case OS_LONG:
1010        tcg_gen_qemu_ld32u(tmp, addr, index);
1011        gen_helper_exts32(cpu_env, fp, tmp);
1012        break;
1013    case OS_SINGLE:
1014        tcg_gen_qemu_ld32u(tmp, addr, index);
1015        gen_helper_extf32(cpu_env, fp, tmp);
1016        break;
1017    case OS_DOUBLE:
1018        tcg_gen_qemu_ld64(t64, addr, index);
1019        gen_helper_extf64(cpu_env, fp, t64);
1020        break;
1021    case OS_EXTENDED:
1022        if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1023            gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1024            break;
1025        }
1026        tcg_gen_qemu_ld32u(tmp, addr, index);
1027        tcg_gen_shri_i32(tmp, tmp, 16);
1028        tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
1029        tcg_gen_addi_i32(tmp, addr, 4);
1030        tcg_gen_qemu_ld64(t64, tmp, index);
1031        tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
1032        break;
1033    case OS_PACKED:
1034        /*
1035         * unimplemented data type on 68040/ColdFire
1036         * FIXME if needed for another FPU
1037         */
1038        gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1039        break;
1040    default:
1041        g_assert_not_reached();
1042    }
1043    tcg_temp_free(tmp);
1044    tcg_temp_free_i64(t64);
1045}
1046
1047static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
1048                         int index)
1049{
1050    TCGv tmp;
1051    TCGv_i64 t64;
1052
1053    t64 = tcg_temp_new_i64();
1054    tmp = tcg_temp_new();
1055    switch (opsize) {
1056    case OS_BYTE:
1057        gen_helper_reds32(tmp, cpu_env, fp);
1058        tcg_gen_qemu_st8(tmp, addr, index);
1059        break;
1060    case OS_WORD:
1061        gen_helper_reds32(tmp, cpu_env, fp);
1062        tcg_gen_qemu_st16(tmp, addr, index);
1063        break;
1064    case OS_LONG:
1065        gen_helper_reds32(tmp, cpu_env, fp);
1066        tcg_gen_qemu_st32(tmp, addr, index);
1067        break;
1068    case OS_SINGLE:
1069        gen_helper_redf32(tmp, cpu_env, fp);
1070        tcg_gen_qemu_st32(tmp, addr, index);
1071        break;
1072    case OS_DOUBLE:
1073        gen_helper_redf64(t64, cpu_env, fp);
1074        tcg_gen_qemu_st64(t64, addr, index);
1075        break;
1076    case OS_EXTENDED:
1077        if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1078            gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1079            break;
1080        }
1081        tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
1082        tcg_gen_shli_i32(tmp, tmp, 16);
1083        tcg_gen_qemu_st32(tmp, addr, index);
1084        tcg_gen_addi_i32(tmp, addr, 4);
1085        tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower));
1086        tcg_gen_qemu_st64(t64, tmp, index);
1087        break;
1088    case OS_PACKED:
1089        /*
1090         * unimplemented data type on 68040/ColdFire
1091         * FIXME if needed for another FPU
1092         */
1093        gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1094        break;
1095    default:
1096        g_assert_not_reached();
1097    }
1098    tcg_temp_free(tmp);
1099    tcg_temp_free_i64(t64);
1100}
1101
1102static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr,
1103                        TCGv_ptr fp, ea_what what, int index)
1104{
1105    if (what == EA_STORE) {
1106        gen_store_fp(s, opsize, addr, fp, index);
1107    } else {
1108        gen_load_fp(s, opsize, addr, fp, index);
1109    }
1110}
1111
1112static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
1113                          int reg0, int opsize, TCGv_ptr fp, ea_what what,
1114                          int index)
1115{
1116    TCGv reg, addr, tmp;
1117    TCGv_i64 t64;
1118
1119    switch (mode) {
1120    case 0: /* Data register direct.  */
1121        reg = cpu_dregs[reg0];
1122        if (what == EA_STORE) {
1123            switch (opsize) {
1124            case OS_BYTE:
1125            case OS_WORD:
1126            case OS_LONG:
1127                gen_helper_reds32(reg, cpu_env, fp);
1128                break;
1129            case OS_SINGLE:
1130                gen_helper_redf32(reg, cpu_env, fp);
1131                break;
1132            default:
1133                g_assert_not_reached();
1134            }
1135        } else {
1136            tmp = tcg_temp_new();
1137            switch (opsize) {
1138            case OS_BYTE:
1139                tcg_gen_ext8s_i32(tmp, reg);
1140                gen_helper_exts32(cpu_env, fp, tmp);
1141                break;
1142            case OS_WORD:
1143                tcg_gen_ext16s_i32(tmp, reg);
1144                gen_helper_exts32(cpu_env, fp, tmp);
1145                break;
1146            case OS_LONG:
1147                gen_helper_exts32(cpu_env, fp, reg);
1148                break;
1149            case OS_SINGLE:
1150                gen_helper_extf32(cpu_env, fp, reg);
1151                break;
1152            default:
1153                g_assert_not_reached();
1154            }
1155            tcg_temp_free(tmp);
1156        }
1157        return 0;
1158    case 1: /* Address register direct.  */
1159        return -1;
1160    case 2: /* Indirect register */
1161        addr = get_areg(s, reg0);
1162        gen_ldst_fp(s, opsize, addr, fp, what, index);
1163        return 0;
1164    case 3: /* Indirect postincrement.  */
1165        addr = cpu_aregs[reg0];
1166        gen_ldst_fp(s, opsize, addr, fp, what, index);
1167        tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize));
1168        return 0;
1169    case 4: /* Indirect predecrememnt.  */
1170        addr = gen_lea_mode(env, s, mode, reg0, opsize);
1171        if (IS_NULL_QREG(addr)) {
1172            return -1;
1173        }
1174        gen_ldst_fp(s, opsize, addr, fp, what, index);
1175        tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1176        return 0;
1177    case 5: /* Indirect displacement.  */
1178    case 6: /* Indirect index + displacement.  */
1179    do_indirect:
1180        addr = gen_lea_mode(env, s, mode, reg0, opsize);
1181        if (IS_NULL_QREG(addr)) {
1182            return -1;
1183        }
1184        gen_ldst_fp(s, opsize, addr, fp, what, index);
1185        return 0;
1186    case 7: /* Other */
1187        switch (reg0) {
1188        case 0: /* Absolute short.  */
1189        case 1: /* Absolute long.  */
1190        case 2: /* pc displacement  */
1191        case 3: /* pc index+displacement.  */
1192            goto do_indirect;
1193        case 4: /* Immediate.  */
1194            if (what == EA_STORE) {
1195                return -1;
1196            }
1197            switch (opsize) {
1198            case OS_BYTE:
1199                tmp = tcg_const_i32((int8_t)read_im8(env, s));
1200                gen_helper_exts32(cpu_env, fp, tmp);
1201                tcg_temp_free(tmp);
1202                break;
1203            case OS_WORD:
1204                tmp = tcg_const_i32((int16_t)read_im16(env, s));
1205                gen_helper_exts32(cpu_env, fp, tmp);
1206                tcg_temp_free(tmp);
1207                break;
1208            case OS_LONG:
1209                tmp = tcg_const_i32(read_im32(env, s));
1210                gen_helper_exts32(cpu_env, fp, tmp);
1211                tcg_temp_free(tmp);
1212                break;
1213            case OS_SINGLE:
1214                tmp = tcg_const_i32(read_im32(env, s));
1215                gen_helper_extf32(cpu_env, fp, tmp);
1216                tcg_temp_free(tmp);
1217                break;
1218            case OS_DOUBLE:
1219                t64 = tcg_const_i64(read_im64(env, s));
1220                gen_helper_extf64(cpu_env, fp, t64);
1221                tcg_temp_free_i64(t64);
1222                break;
1223            case OS_EXTENDED:
1224                if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1225                    gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1226                    break;
1227                }
1228                tmp = tcg_const_i32(read_im32(env, s) >> 16);
1229                tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
1230                tcg_temp_free(tmp);
1231                t64 = tcg_const_i64(read_im64(env, s));
1232                tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
1233                tcg_temp_free_i64(t64);
1234                break;
1235            case OS_PACKED:
1236                /*
1237                 * unimplemented data type on 68040/ColdFire
1238                 * FIXME if needed for another FPU
1239                 */
1240                gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1241                break;
1242            default:
1243                g_assert_not_reached();
1244            }
1245            return 0;
1246        default:
1247            return -1;
1248        }
1249    }
1250    return -1;
1251}
1252
1253static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn,
1254                       int opsize, TCGv_ptr fp, ea_what what, int index)
1255{
1256    int mode = extract32(insn, 3, 3);
1257    int reg0 = REG(insn, 0);
1258    return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what, index);
1259}
1260
1261typedef struct {
1262    TCGCond tcond;
1263    bool g1;
1264    bool g2;
1265    TCGv v1;
1266    TCGv v2;
1267} DisasCompare;
1268
1269static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
1270{
1271    TCGv tmp, tmp2;
1272    TCGCond tcond;
1273    CCOp op = s->cc_op;
1274
1275    /* The CC_OP_CMP form can handle most normal comparisons directly.  */
1276    if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) {
1277        c->g1 = c->g2 = 1;
1278        c->v1 = QREG_CC_N;
1279        c->v2 = QREG_CC_V;
1280        switch (cond) {
1281        case 2: /* HI */
1282        case 3: /* LS */
1283            tcond = TCG_COND_LEU;
1284            goto done;
1285        case 4: /* CC */
1286        case 5: /* CS */
1287            tcond = TCG_COND_LTU;
1288            goto done;
1289        case 6: /* NE */
1290        case 7: /* EQ */
1291            tcond = TCG_COND_EQ;
1292            goto done;
1293        case 10: /* PL */
1294        case 11: /* MI */
1295            c->g1 = c->g2 = 0;
1296            c->v2 = tcg_const_i32(0);
1297            c->v1 = tmp = tcg_temp_new();
1298            tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V);
1299            gen_ext(tmp, tmp, op - CC_OP_CMPB, 1);
1300            /* fallthru */
1301        case 12: /* GE */
1302        case 13: /* LT */
1303            tcond = TCG_COND_LT;
1304            goto done;
1305        case 14: /* GT */
1306        case 15: /* LE */
1307            tcond = TCG_COND_LE;
1308            goto done;
1309        }
1310    }
1311
1312    c->g1 = 1;
1313    c->g2 = 0;
1314    c->v2 = tcg_const_i32(0);
1315
1316    switch (cond) {
1317    case 0: /* T */
1318    case 1: /* F */
1319        c->v1 = c->v2;
1320        tcond = TCG_COND_NEVER;
1321        goto done;
1322    case 14: /* GT (!(Z || (N ^ V))) */
1323    case 15: /* LE (Z || (N ^ V)) */
1324        /*
1325         * Logic operations clear V, which simplifies LE to (Z || N),
1326         * and since Z and N are co-located, this becomes a normal
1327         * comparison vs N.
1328         */
1329        if (op == CC_OP_LOGIC) {
1330            c->v1 = QREG_CC_N;
1331            tcond = TCG_COND_LE;
1332            goto done;
1333        }
1334        break;
1335    case 12: /* GE (!(N ^ V)) */
1336    case 13: /* LT (N ^ V) */
1337        /* Logic operations clear V, which simplifies this to N.  */
1338        if (op != CC_OP_LOGIC) {
1339            break;
1340        }
1341        /* fallthru */
1342    case 10: /* PL (!N) */
1343    case 11: /* MI (N) */
1344        /* Several cases represent N normally.  */
1345        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1346            op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1347            op == CC_OP_LOGIC) {
1348            c->v1 = QREG_CC_N;
1349            tcond = TCG_COND_LT;
1350            goto done;
1351        }
1352        break;
1353    case 6: /* NE (!Z) */
1354    case 7: /* EQ (Z) */
1355        /* Some cases fold Z into N.  */
1356        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1357            op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1358            op == CC_OP_LOGIC) {
1359            tcond = TCG_COND_EQ;
1360            c->v1 = QREG_CC_N;
1361            goto done;
1362        }
1363        break;
1364    case 4: /* CC (!C) */
1365    case 5: /* CS (C) */
1366        /* Some cases fold C into X.  */
1367        if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1368            op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL) {
1369            tcond = TCG_COND_NE;
1370            c->v1 = QREG_CC_X;
1371            goto done;
1372        }
1373        /* fallthru */
1374    case 8: /* VC (!V) */
1375    case 9: /* VS (V) */
1376        /* Logic operations clear V and C.  */
1377        if (op == CC_OP_LOGIC) {
1378            tcond = TCG_COND_NEVER;
1379            c->v1 = c->v2;
1380            goto done;
1381        }
1382        break;
1383    }
1384
1385    /* Otherwise, flush flag state to CC_OP_FLAGS.  */
1386    gen_flush_flags(s);
1387
1388    switch (cond) {
1389    case 0: /* T */
1390    case 1: /* F */
1391    default:
1392        /* Invalid, or handled above.  */
1393        abort();
1394    case 2: /* HI (!C && !Z) -> !(C || Z)*/
1395    case 3: /* LS (C || Z) */
1396        c->v1 = tmp = tcg_temp_new();
1397        c->g1 = 0;
1398        tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1399        tcg_gen_or_i32(tmp, tmp, QREG_CC_C);
1400        tcond = TCG_COND_NE;
1401        break;
1402    case 4: /* CC (!C) */
1403    case 5: /* CS (C) */
1404        c->v1 = QREG_CC_C;
1405        tcond = TCG_COND_NE;
1406        break;
1407    case 6: /* NE (!Z) */
1408    case 7: /* EQ (Z) */
1409        c->v1 = QREG_CC_Z;
1410        tcond = TCG_COND_EQ;
1411        break;
1412    case 8: /* VC (!V) */
1413    case 9: /* VS (V) */
1414        c->v1 = QREG_CC_V;
1415        tcond = TCG_COND_LT;
1416        break;
1417    case 10: /* PL (!N) */
1418    case 11: /* MI (N) */
1419        c->v1 = QREG_CC_N;
1420        tcond = TCG_COND_LT;
1421        break;
1422    case 12: /* GE (!(N ^ V)) */
1423    case 13: /* LT (N ^ V) */
1424        c->v1 = tmp = tcg_temp_new();
1425        c->g1 = 0;
1426        tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V);
1427        tcond = TCG_COND_LT;
1428        break;
1429    case 14: /* GT (!(Z || (N ^ V))) */
1430    case 15: /* LE (Z || (N ^ V)) */
1431        c->v1 = tmp = tcg_temp_new();
1432        c->g1 = 0;
1433        tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1434        tcg_gen_neg_i32(tmp, tmp);
1435        tmp2 = tcg_temp_new();
1436        tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
1437        tcg_gen_or_i32(tmp, tmp, tmp2);
1438        tcg_temp_free(tmp2);
1439        tcond = TCG_COND_LT;
1440        break;
1441    }
1442
1443 done:
1444    if ((cond & 1) == 0) {
1445        tcond = tcg_invert_cond(tcond);
1446    }
1447    c->tcond = tcond;
1448}
1449
1450static void free_cond(DisasCompare *c)
1451{
1452    if (!c->g1) {
1453        tcg_temp_free(c->v1);
1454    }
1455    if (!c->g2) {
1456        tcg_temp_free(c->v2);
1457    }
1458}
1459
1460static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
1461{
1462  DisasCompare c;
1463
1464  gen_cc_cond(&c, s, cond);
1465  update_cc_op(s);
1466  tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
1467  free_cond(&c);
1468}
1469
1470/* Force a TB lookup after an instruction that changes the CPU state.  */
1471static void gen_exit_tb(DisasContext *s)
1472{
1473    update_cc_op(s);
1474    tcg_gen_movi_i32(QREG_PC, s->pc);
1475    s->base.is_jmp = DISAS_EXIT;
1476}
1477
1478#define SRC_EA(env, result, opsize, op_sign, addrp) do {                \
1479        result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp,         \
1480                        op_sign ? EA_LOADS : EA_LOADU, IS_USER(s));     \
1481        if (IS_NULL_QREG(result)) {                                     \
1482            gen_addr_fault(s);                                          \
1483            return;                                                     \
1484        }                                                               \
1485    } while (0)
1486
1487#define DEST_EA(env, insn, opsize, val, addrp) do {                     \
1488        TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp,       \
1489                                EA_STORE, IS_USER(s));                  \
1490        if (IS_NULL_QREG(ea_result)) {                                  \
1491            gen_addr_fault(s);                                          \
1492            return;                                                     \
1493        }                                                               \
1494    } while (0)
1495
1496/* Generate a jump to an immediate address.  */
1497static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
1498{
1499    if (unlikely(s->ss_active)) {
1500        update_cc_op(s);
1501        tcg_gen_movi_i32(QREG_PC, dest);
1502        gen_raise_exception(EXCP_TRACE);
1503    } else if (translator_use_goto_tb(&s->base, dest)) {
1504        tcg_gen_goto_tb(n);
1505        tcg_gen_movi_i32(QREG_PC, dest);
1506        tcg_gen_exit_tb(s->base.tb, n);
1507    } else {
1508        gen_jmp_im(s, dest);
1509        tcg_gen_exit_tb(NULL, 0);
1510    }
1511    s->base.is_jmp = DISAS_NORETURN;
1512}
1513
1514DISAS_INSN(scc)
1515{
1516    DisasCompare c;
1517    int cond;
1518    TCGv tmp;
1519
1520    cond = (insn >> 8) & 0xf;
1521    gen_cc_cond(&c, s, cond);
1522
1523    tmp = tcg_temp_new();
1524    tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
1525    free_cond(&c);
1526
1527    tcg_gen_neg_i32(tmp, tmp);
1528    DEST_EA(env, insn, OS_BYTE, tmp, NULL);
1529    tcg_temp_free(tmp);
1530}
1531
1532DISAS_INSN(dbcc)
1533{
1534    TCGLabel *l1;
1535    TCGv reg;
1536    TCGv tmp;
1537    int16_t offset;
1538    uint32_t base;
1539
1540    reg = DREG(insn, 0);
1541    base = s->pc;
1542    offset = (int16_t)read_im16(env, s);
1543    l1 = gen_new_label();
1544    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
1545
1546    tmp = tcg_temp_new();
1547    tcg_gen_ext16s_i32(tmp, reg);
1548    tcg_gen_addi_i32(tmp, tmp, -1);
1549    gen_partset_reg(OS_WORD, reg, tmp);
1550    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
1551    gen_jmp_tb(s, 1, base + offset);
1552    gen_set_label(l1);
1553    gen_jmp_tb(s, 0, s->pc);
1554}
1555
1556DISAS_INSN(undef_mac)
1557{
1558    gen_exception(s, s->base.pc_next, EXCP_LINEA);
1559}
1560
1561DISAS_INSN(undef_fpu)
1562{
1563    gen_exception(s, s->base.pc_next, EXCP_LINEF);
1564}
1565
1566DISAS_INSN(undef)
1567{
1568    /*
1569     * ??? This is both instructions that are as yet unimplemented
1570     * for the 680x0 series, as well as those that are implemented
1571     * but actually illegal for CPU32 or pre-68020.
1572     */
1573    qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n",
1574                  insn, s->base.pc_next);
1575    gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1576}
1577
1578DISAS_INSN(mulw)
1579{
1580    TCGv reg;
1581    TCGv tmp;
1582    TCGv src;
1583    int sign;
1584
1585    sign = (insn & 0x100) != 0;
1586    reg = DREG(insn, 9);
1587    tmp = tcg_temp_new();
1588    if (sign)
1589        tcg_gen_ext16s_i32(tmp, reg);
1590    else
1591        tcg_gen_ext16u_i32(tmp, reg);
1592    SRC_EA(env, src, OS_WORD, sign, NULL);
1593    tcg_gen_mul_i32(tmp, tmp, src);
1594    tcg_gen_mov_i32(reg, tmp);
1595    gen_logic_cc(s, tmp, OS_LONG);
1596    tcg_temp_free(tmp);
1597}
1598
1599DISAS_INSN(divw)
1600{
1601    int sign;
1602    TCGv src;
1603    TCGv destr;
1604
1605    /* divX.w <EA>,Dn    32/16 -> 16r:16q */
1606
1607    sign = (insn & 0x100) != 0;
1608
1609    /* dest.l / src.w */
1610
1611    SRC_EA(env, src, OS_WORD, sign, NULL);
1612    destr = tcg_const_i32(REG(insn, 9));
1613    if (sign) {
1614        gen_helper_divsw(cpu_env, destr, src);
1615    } else {
1616        gen_helper_divuw(cpu_env, destr, src);
1617    }
1618    tcg_temp_free(destr);
1619
1620    set_cc_op(s, CC_OP_FLAGS);
1621}
1622
1623DISAS_INSN(divl)
1624{
1625    TCGv num, reg, den;
1626    int sign;
1627    uint16_t ext;
1628
1629    ext = read_im16(env, s);
1630
1631    sign = (ext & 0x0800) != 0;
1632
1633    if (ext & 0x400) {
1634        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
1635            gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1636            return;
1637        }
1638
1639        /* divX.l <EA>, Dr:Dq    64/32 -> 32r:32q */
1640
1641        SRC_EA(env, den, OS_LONG, 0, NULL);
1642        num = tcg_const_i32(REG(ext, 12));
1643        reg = tcg_const_i32(REG(ext, 0));
1644        if (sign) {
1645            gen_helper_divsll(cpu_env, num, reg, den);
1646        } else {
1647            gen_helper_divull(cpu_env, num, reg, den);
1648        }
1649        tcg_temp_free(reg);
1650        tcg_temp_free(num);
1651        set_cc_op(s, CC_OP_FLAGS);
1652        return;
1653    }
1654
1655    /* divX.l <EA>, Dq        32/32 -> 32q     */
1656    /* divXl.l <EA>, Dr:Dq    32/32 -> 32r:32q */
1657
1658    SRC_EA(env, den, OS_LONG, 0, NULL);
1659    num = tcg_const_i32(REG(ext, 12));
1660    reg = tcg_const_i32(REG(ext, 0));
1661    if (sign) {
1662        gen_helper_divsl(cpu_env, num, reg, den);
1663    } else {
1664        gen_helper_divul(cpu_env, num, reg, den);
1665    }
1666    tcg_temp_free(reg);
1667    tcg_temp_free(num);
1668
1669    set_cc_op(s, CC_OP_FLAGS);
1670}
1671
1672static void bcd_add(TCGv dest, TCGv src)
1673{
1674    TCGv t0, t1;
1675
1676    /*
1677     * dest10 = dest10 + src10 + X
1678     *
1679     *        t1 = src
1680     *        t2 = t1 + 0x066
1681     *        t3 = t2 + dest + X
1682     *        t4 = t2 ^ dest
1683     *        t5 = t3 ^ t4
1684     *        t6 = ~t5 & 0x110
1685     *        t7 = (t6 >> 2) | (t6 >> 3)
1686     *        return t3 - t7
1687     */
1688
1689    /*
1690     * t1 = (src + 0x066) + dest + X
1691     *    = result with some possible exceeding 0x6
1692     */
1693
1694    t0 = tcg_const_i32(0x066);
1695    tcg_gen_add_i32(t0, t0, src);
1696
1697    t1 = tcg_temp_new();
1698    tcg_gen_add_i32(t1, t0, dest);
1699    tcg_gen_add_i32(t1, t1, QREG_CC_X);
1700
1701    /* we will remove exceeding 0x6 where there is no carry */
1702
1703    /*
1704     * t0 = (src + 0x0066) ^ dest
1705     *    = t1 without carries
1706     */
1707
1708    tcg_gen_xor_i32(t0, t0, dest);
1709
1710    /*
1711     * extract the carries
1712     * t0 = t0 ^ t1
1713     *    = only the carries
1714     */
1715
1716    tcg_gen_xor_i32(t0, t0, t1);
1717
1718    /*
1719     * generate 0x1 where there is no carry
1720     * and for each 0x10, generate a 0x6
1721     */
1722
1723    tcg_gen_shri_i32(t0, t0, 3);
1724    tcg_gen_not_i32(t0, t0);
1725    tcg_gen_andi_i32(t0, t0, 0x22);
1726    tcg_gen_add_i32(dest, t0, t0);
1727    tcg_gen_add_i32(dest, dest, t0);
1728    tcg_temp_free(t0);
1729
1730    /*
1731     * remove the exceeding 0x6
1732     * for digits that have not generated a carry
1733     */
1734
1735    tcg_gen_sub_i32(dest, t1, dest);
1736    tcg_temp_free(t1);
1737}
1738
1739static void bcd_sub(TCGv dest, TCGv src)
1740{
1741    TCGv t0, t1, t2;
1742
1743    /*
1744     *  dest10 = dest10 - src10 - X
1745     *         = bcd_add(dest + 1 - X, 0x199 - src)
1746     */
1747
1748    /* t0 = 0x066 + (0x199 - src) */
1749
1750    t0 = tcg_temp_new();
1751    tcg_gen_subfi_i32(t0, 0x1ff, src);
1752
1753    /* t1 = t0 + dest + 1 - X*/
1754
1755    t1 = tcg_temp_new();
1756    tcg_gen_add_i32(t1, t0, dest);
1757    tcg_gen_addi_i32(t1, t1, 1);
1758    tcg_gen_sub_i32(t1, t1, QREG_CC_X);
1759
1760    /* t2 = t0 ^ dest */
1761
1762    t2 = tcg_temp_new();
1763    tcg_gen_xor_i32(t2, t0, dest);
1764
1765    /* t0 = t1 ^ t2 */
1766
1767    tcg_gen_xor_i32(t0, t1, t2);
1768
1769    /*
1770     * t2 = ~t0 & 0x110
1771     * t0 = (t2 >> 2) | (t2 >> 3)
1772     *
1773     * to fit on 8bit operands, changed in:
1774     *
1775     * t2 = ~(t0 >> 3) & 0x22
1776     * t0 = t2 + t2
1777     * t0 = t0 + t2
1778     */
1779
1780    tcg_gen_shri_i32(t2, t0, 3);
1781    tcg_gen_not_i32(t2, t2);
1782    tcg_gen_andi_i32(t2, t2, 0x22);
1783    tcg_gen_add_i32(t0, t2, t2);
1784    tcg_gen_add_i32(t0, t0, t2);
1785    tcg_temp_free(t2);
1786
1787    /* return t1 - t0 */
1788
1789    tcg_gen_sub_i32(dest, t1, t0);
1790    tcg_temp_free(t0);
1791    tcg_temp_free(t1);
1792}
1793
1794static void bcd_flags(TCGv val)
1795{
1796    tcg_gen_andi_i32(QREG_CC_C, val, 0x0ff);
1797    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_C);
1798
1799    tcg_gen_extract_i32(QREG_CC_C, val, 8, 1);
1800
1801    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
1802}
1803
1804DISAS_INSN(abcd_reg)
1805{
1806    TCGv src;
1807    TCGv dest;
1808
1809    gen_flush_flags(s); /* !Z is sticky */
1810
1811    src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1812    dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1813    bcd_add(dest, src);
1814    gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1815
1816    bcd_flags(dest);
1817}
1818
1819DISAS_INSN(abcd_mem)
1820{
1821    TCGv src, dest, addr;
1822
1823    gen_flush_flags(s); /* !Z is sticky */
1824
1825    /* Indirect pre-decrement load (mode 4) */
1826
1827    src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1828                      NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1829    dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1830                       NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1831
1832    bcd_add(dest, src);
1833
1834    gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1835                EA_STORE, IS_USER(s));
1836
1837    bcd_flags(dest);
1838}
1839
1840DISAS_INSN(sbcd_reg)
1841{
1842    TCGv src, dest;
1843
1844    gen_flush_flags(s); /* !Z is sticky */
1845
1846    src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1847    dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1848
1849    bcd_sub(dest, src);
1850
1851    gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1852
1853    bcd_flags(dest);
1854}
1855
1856DISAS_INSN(sbcd_mem)
1857{
1858    TCGv src, dest, addr;
1859
1860    gen_flush_flags(s); /* !Z is sticky */
1861
1862    /* Indirect pre-decrement load (mode 4) */
1863
1864    src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1865                      NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1866    dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1867                       NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1868
1869    bcd_sub(dest, src);
1870
1871    gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1872                EA_STORE, IS_USER(s));
1873
1874    bcd_flags(dest);
1875}
1876
1877DISAS_INSN(nbcd)
1878{
1879    TCGv src, dest;
1880    TCGv addr;
1881
1882    gen_flush_flags(s); /* !Z is sticky */
1883
1884    SRC_EA(env, src, OS_BYTE, 0, &addr);
1885
1886    dest = tcg_const_i32(0);
1887    bcd_sub(dest, src);
1888
1889    DEST_EA(env, insn, OS_BYTE, dest, &addr);
1890
1891    bcd_flags(dest);
1892
1893    tcg_temp_free(dest);
1894}
1895
1896DISAS_INSN(addsub)
1897{
1898    TCGv reg;
1899    TCGv dest;
1900    TCGv src;
1901    TCGv tmp;
1902    TCGv addr;
1903    int add;
1904    int opsize;
1905
1906    add = (insn & 0x4000) != 0;
1907    opsize = insn_opsize(insn);
1908    reg = gen_extend(s, DREG(insn, 9), opsize, 1);
1909    dest = tcg_temp_new();
1910    if (insn & 0x100) {
1911        SRC_EA(env, tmp, opsize, 1, &addr);
1912        src = reg;
1913    } else {
1914        tmp = reg;
1915        SRC_EA(env, src, opsize, 1, NULL);
1916    }
1917    if (add) {
1918        tcg_gen_add_i32(dest, tmp, src);
1919        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
1920        set_cc_op(s, CC_OP_ADDB + opsize);
1921    } else {
1922        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
1923        tcg_gen_sub_i32(dest, tmp, src);
1924        set_cc_op(s, CC_OP_SUBB + opsize);
1925    }
1926    gen_update_cc_add(dest, src, opsize);
1927    if (insn & 0x100) {
1928        DEST_EA(env, insn, opsize, dest, &addr);
1929    } else {
1930        gen_partset_reg(opsize, DREG(insn, 9), dest);
1931    }
1932    tcg_temp_free(dest);
1933}
1934
1935/* Reverse the order of the bits in REG.  */
1936DISAS_INSN(bitrev)
1937{
1938    TCGv reg;
1939    reg = DREG(insn, 0);
1940    gen_helper_bitrev(reg, reg);
1941}
1942
1943DISAS_INSN(bitop_reg)
1944{
1945    int opsize;
1946    int op;
1947    TCGv src1;
1948    TCGv src2;
1949    TCGv tmp;
1950    TCGv addr;
1951    TCGv dest;
1952
1953    if ((insn & 0x38) != 0)
1954        opsize = OS_BYTE;
1955    else
1956        opsize = OS_LONG;
1957    op = (insn >> 6) & 3;
1958    SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
1959
1960    gen_flush_flags(s);
1961    src2 = tcg_temp_new();
1962    if (opsize == OS_BYTE)
1963        tcg_gen_andi_i32(src2, DREG(insn, 9), 7);
1964    else
1965        tcg_gen_andi_i32(src2, DREG(insn, 9), 31);
1966
1967    tmp = tcg_const_i32(1);
1968    tcg_gen_shl_i32(tmp, tmp, src2);
1969    tcg_temp_free(src2);
1970
1971    tcg_gen_and_i32(QREG_CC_Z, src1, tmp);
1972
1973    dest = tcg_temp_new();
1974    switch (op) {
1975    case 1: /* bchg */
1976        tcg_gen_xor_i32(dest, src1, tmp);
1977        break;
1978    case 2: /* bclr */
1979        tcg_gen_andc_i32(dest, src1, tmp);
1980        break;
1981    case 3: /* bset */
1982        tcg_gen_or_i32(dest, src1, tmp);
1983        break;
1984    default: /* btst */
1985        break;
1986    }
1987    tcg_temp_free(tmp);
1988    if (op) {
1989        DEST_EA(env, insn, opsize, dest, &addr);
1990    }
1991    tcg_temp_free(dest);
1992}
1993
1994DISAS_INSN(sats)
1995{
1996    TCGv reg;
1997    reg = DREG(insn, 0);
1998    gen_flush_flags(s);
1999    gen_helper_sats(reg, reg, QREG_CC_V);
2000    gen_logic_cc(s, reg, OS_LONG);
2001}
2002
2003static void gen_push(DisasContext *s, TCGv val)
2004{
2005    TCGv tmp;
2006
2007    tmp = tcg_temp_new();
2008    tcg_gen_subi_i32(tmp, QREG_SP, 4);
2009    gen_store(s, OS_LONG, tmp, val, IS_USER(s));
2010    tcg_gen_mov_i32(QREG_SP, tmp);
2011    tcg_temp_free(tmp);
2012}
2013
2014static TCGv mreg(int reg)
2015{
2016    if (reg < 8) {
2017        /* Dx */
2018        return cpu_dregs[reg];
2019    }
2020    /* Ax */
2021    return cpu_aregs[reg & 7];
2022}
2023
2024DISAS_INSN(movem)
2025{
2026    TCGv addr, incr, tmp, r[16];
2027    int is_load = (insn & 0x0400) != 0;
2028    int opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
2029    uint16_t mask = read_im16(env, s);
2030    int mode = extract32(insn, 3, 3);
2031    int reg0 = REG(insn, 0);
2032    int i;
2033
2034    tmp = cpu_aregs[reg0];
2035
2036    switch (mode) {
2037    case 0: /* data register direct */
2038    case 1: /* addr register direct */
2039    do_addr_fault:
2040        gen_addr_fault(s);
2041        return;
2042
2043    case 2: /* indirect */
2044        break;
2045
2046    case 3: /* indirect post-increment */
2047        if (!is_load) {
2048            /* post-increment is not allowed */
2049            goto do_addr_fault;
2050        }
2051        break;
2052
2053    case 4: /* indirect pre-decrement */
2054        if (is_load) {
2055            /* pre-decrement is not allowed */
2056            goto do_addr_fault;
2057        }
2058        /*
2059         * We want a bare copy of the address reg, without any pre-decrement
2060         * adjustment, as gen_lea would provide.
2061         */
2062        break;
2063
2064    default:
2065        tmp = gen_lea_mode(env, s, mode, reg0, opsize);
2066        if (IS_NULL_QREG(tmp)) {
2067            goto do_addr_fault;
2068        }
2069        break;
2070    }
2071
2072    addr = tcg_temp_new();
2073    tcg_gen_mov_i32(addr, tmp);
2074    incr = tcg_const_i32(opsize_bytes(opsize));
2075
2076    if (is_load) {
2077        /* memory to register */
2078        for (i = 0; i < 16; i++) {
2079            if (mask & (1 << i)) {
2080                r[i] = gen_load(s, opsize, addr, 1, IS_USER(s));
2081                tcg_gen_add_i32(addr, addr, incr);
2082            }
2083        }
2084        for (i = 0; i < 16; i++) {
2085            if (mask & (1 << i)) {
2086                tcg_gen_mov_i32(mreg(i), r[i]);
2087                tcg_temp_free(r[i]);
2088            }
2089        }
2090        if (mode == 3) {
2091            /* post-increment: movem (An)+,X */
2092            tcg_gen_mov_i32(cpu_aregs[reg0], addr);
2093        }
2094    } else {
2095        /* register to memory */
2096        if (mode == 4) {
2097            /* pre-decrement: movem X,-(An) */
2098            for (i = 15; i >= 0; i--) {
2099                if ((mask << i) & 0x8000) {
2100                    tcg_gen_sub_i32(addr, addr, incr);
2101                    if (reg0 + 8 == i &&
2102                        m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
2103                        /*
2104                         * M68020+: if the addressing register is the
2105                         * register moved to memory, the value written
2106                         * is the initial value decremented by the size of
2107                         * the operation, regardless of how many actual
2108                         * stores have been performed until this point.
2109                         * M68000/M68010: the value is the initial value.
2110                         */
2111                        tmp = tcg_temp_new();
2112                        tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr);
2113                        gen_store(s, opsize, addr, tmp, IS_USER(s));
2114                        tcg_temp_free(tmp);
2115                    } else {
2116                        gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2117                    }
2118                }
2119            }
2120            tcg_gen_mov_i32(cpu_aregs[reg0], addr);
2121        } else {
2122            for (i = 0; i < 16; i++) {
2123                if (mask & (1 << i)) {
2124                    gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2125                    tcg_gen_add_i32(addr, addr, incr);
2126                }
2127            }
2128        }
2129    }
2130
2131    tcg_temp_free(incr);
2132    tcg_temp_free(addr);
2133}
2134
2135DISAS_INSN(movep)
2136{
2137    uint8_t i;
2138    int16_t displ;
2139    TCGv reg;
2140    TCGv addr;
2141    TCGv abuf;
2142    TCGv dbuf;
2143
2144    displ = read_im16(env, s);
2145
2146    addr = AREG(insn, 0);
2147    reg = DREG(insn, 9);
2148
2149    abuf = tcg_temp_new();
2150    tcg_gen_addi_i32(abuf, addr, displ);
2151    dbuf = tcg_temp_new();
2152
2153    if (insn & 0x40) {
2154        i = 4;
2155    } else {
2156        i = 2;
2157    }
2158
2159    if (insn & 0x80) {
2160        for ( ; i > 0 ; i--) {
2161            tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8);
2162            tcg_gen_qemu_st8(dbuf, abuf, IS_USER(s));
2163            if (i > 1) {
2164                tcg_gen_addi_i32(abuf, abuf, 2);
2165            }
2166        }
2167    } else {
2168        for ( ; i > 0 ; i--) {
2169            tcg_gen_qemu_ld8u(dbuf, abuf, IS_USER(s));
2170            tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8);
2171            if (i > 1) {
2172                tcg_gen_addi_i32(abuf, abuf, 2);
2173            }
2174        }
2175    }
2176    tcg_temp_free(abuf);
2177    tcg_temp_free(dbuf);
2178}
2179
2180DISAS_INSN(bitop_im)
2181{
2182    int opsize;
2183    int op;
2184    TCGv src1;
2185    uint32_t mask;
2186    int bitnum;
2187    TCGv tmp;
2188    TCGv addr;
2189
2190    if ((insn & 0x38) != 0)
2191        opsize = OS_BYTE;
2192    else
2193        opsize = OS_LONG;
2194    op = (insn >> 6) & 3;
2195
2196    bitnum = read_im16(env, s);
2197    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
2198        if (bitnum & 0xfe00) {
2199            disas_undef(env, s, insn);
2200            return;
2201        }
2202    } else {
2203        if (bitnum & 0xff00) {
2204            disas_undef(env, s, insn);
2205            return;
2206        }
2207    }
2208
2209    SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
2210
2211    gen_flush_flags(s);
2212    if (opsize == OS_BYTE)
2213        bitnum &= 7;
2214    else
2215        bitnum &= 31;
2216    mask = 1 << bitnum;
2217
2218   tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
2219
2220    if (op) {
2221        tmp = tcg_temp_new();
2222        switch (op) {
2223        case 1: /* bchg */
2224            tcg_gen_xori_i32(tmp, src1, mask);
2225            break;
2226        case 2: /* bclr */
2227            tcg_gen_andi_i32(tmp, src1, ~mask);
2228            break;
2229        case 3: /* bset */
2230            tcg_gen_ori_i32(tmp, src1, mask);
2231            break;
2232        default: /* btst */
2233            break;
2234        }
2235        DEST_EA(env, insn, opsize, tmp, &addr);
2236        tcg_temp_free(tmp);
2237    }
2238}
2239
2240static TCGv gen_get_ccr(DisasContext *s)
2241{
2242    TCGv dest;
2243
2244    update_cc_op(s);
2245    dest = tcg_temp_new();
2246    gen_helper_get_ccr(dest, cpu_env);
2247    return dest;
2248}
2249
2250static TCGv gen_get_sr(DisasContext *s)
2251{
2252    TCGv ccr;
2253    TCGv sr;
2254
2255    ccr = gen_get_ccr(s);
2256    sr = tcg_temp_new();
2257    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
2258    tcg_gen_or_i32(sr, sr, ccr);
2259    tcg_temp_free(ccr);
2260    return sr;
2261}
2262
2263static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
2264{
2265    if (ccr_only) {
2266        tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
2267        tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
2268        tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
2269        tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
2270        tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
2271    } else {
2272        TCGv sr = tcg_const_i32(val);
2273        gen_helper_set_sr(cpu_env, sr);
2274        tcg_temp_free(sr);
2275    }
2276    set_cc_op(s, CC_OP_FLAGS);
2277}
2278
2279static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
2280{
2281    if (ccr_only) {
2282        gen_helper_set_ccr(cpu_env, val);
2283    } else {
2284        gen_helper_set_sr(cpu_env, val);
2285    }
2286    set_cc_op(s, CC_OP_FLAGS);
2287}
2288
2289static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
2290                           bool ccr_only)
2291{
2292    if ((insn & 0x3f) == 0x3c) {
2293        uint16_t val;
2294        val = read_im16(env, s);
2295        gen_set_sr_im(s, val, ccr_only);
2296    } else {
2297        TCGv src;
2298        SRC_EA(env, src, OS_WORD, 0, NULL);
2299        gen_set_sr(s, src, ccr_only);
2300    }
2301}
2302
2303DISAS_INSN(arith_im)
2304{
2305    int op;
2306    TCGv im;
2307    TCGv src1;
2308    TCGv dest;
2309    TCGv addr;
2310    int opsize;
2311    bool with_SR = ((insn & 0x3f) == 0x3c);
2312
2313    op = (insn >> 9) & 7;
2314    opsize = insn_opsize(insn);
2315    switch (opsize) {
2316    case OS_BYTE:
2317        im = tcg_const_i32((int8_t)read_im8(env, s));
2318        break;
2319    case OS_WORD:
2320        im = tcg_const_i32((int16_t)read_im16(env, s));
2321        break;
2322    case OS_LONG:
2323        im = tcg_const_i32(read_im32(env, s));
2324        break;
2325    default:
2326        g_assert_not_reached();
2327    }
2328
2329    if (with_SR) {
2330        /* SR/CCR can only be used with andi/eori/ori */
2331        if (op == 2 || op == 3 || op == 6) {
2332            disas_undef(env, s, insn);
2333            return;
2334        }
2335        switch (opsize) {
2336        case OS_BYTE:
2337            src1 = gen_get_ccr(s);
2338            break;
2339        case OS_WORD:
2340            if (IS_USER(s)) {
2341                gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2342                return;
2343            }
2344            src1 = gen_get_sr(s);
2345            break;
2346        default:
2347            /* OS_LONG; others already g_assert_not_reached.  */
2348            disas_undef(env, s, insn);
2349            return;
2350        }
2351    } else {
2352        SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
2353    }
2354    dest = tcg_temp_new();
2355    switch (op) {
2356    case 0: /* ori */
2357        tcg_gen_or_i32(dest, src1, im);
2358        if (with_SR) {
2359            gen_set_sr(s, dest, opsize == OS_BYTE);
2360        } else {
2361            DEST_EA(env, insn, opsize, dest, &addr);
2362            gen_logic_cc(s, dest, opsize);
2363        }
2364        break;
2365    case 1: /* andi */
2366        tcg_gen_and_i32(dest, src1, im);
2367        if (with_SR) {
2368            gen_set_sr(s, dest, opsize == OS_BYTE);
2369        } else {
2370            DEST_EA(env, insn, opsize, dest, &addr);
2371            gen_logic_cc(s, dest, opsize);
2372        }
2373        break;
2374    case 2: /* subi */
2375        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
2376        tcg_gen_sub_i32(dest, src1, im);
2377        gen_update_cc_add(dest, im, opsize);
2378        set_cc_op(s, CC_OP_SUBB + opsize);
2379        DEST_EA(env, insn, opsize, dest, &addr);
2380        break;
2381    case 3: /* addi */
2382        tcg_gen_add_i32(dest, src1, im);
2383        gen_update_cc_add(dest, im, opsize);
2384        tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
2385        set_cc_op(s, CC_OP_ADDB + opsize);
2386        DEST_EA(env, insn, opsize, dest, &addr);
2387        break;
2388    case 5: /* eori */
2389        tcg_gen_xor_i32(dest, src1, im);
2390        if (with_SR) {
2391            gen_set_sr(s, dest, opsize == OS_BYTE);
2392        } else {
2393            DEST_EA(env, insn, opsize, dest, &addr);
2394            gen_logic_cc(s, dest, opsize);
2395        }
2396        break;
2397    case 6: /* cmpi */
2398        gen_update_cc_cmp(s, src1, im, opsize);
2399        break;
2400    default:
2401        abort();
2402    }
2403    tcg_temp_free(im);
2404    tcg_temp_free(dest);
2405}
2406
2407DISAS_INSN(cas)
2408{
2409    int opsize;
2410    TCGv addr;
2411    uint16_t ext;
2412    TCGv load;
2413    TCGv cmp;
2414    MemOp opc;
2415
2416    switch ((insn >> 9) & 3) {
2417    case 1:
2418        opsize = OS_BYTE;
2419        opc = MO_SB;
2420        break;
2421    case 2:
2422        opsize = OS_WORD;
2423        opc = MO_TESW;
2424        break;
2425    case 3:
2426        opsize = OS_LONG;
2427        opc = MO_TESL;
2428        break;
2429    default:
2430        g_assert_not_reached();
2431    }
2432
2433    ext = read_im16(env, s);
2434
2435    /* cas Dc,Du,<EA> */
2436
2437    addr = gen_lea(env, s, insn, opsize);
2438    if (IS_NULL_QREG(addr)) {
2439        gen_addr_fault(s);
2440        return;
2441    }
2442
2443    cmp = gen_extend(s, DREG(ext, 0), opsize, 1);
2444
2445    /*
2446     * if  <EA> == Dc then
2447     *     <EA> = Du
2448     *     Dc = <EA> (because <EA> == Dc)
2449     * else
2450     *     Dc = <EA>
2451     */
2452
2453    load = tcg_temp_new();
2454    tcg_gen_atomic_cmpxchg_i32(load, addr, cmp, DREG(ext, 6),
2455                               IS_USER(s), opc);
2456    /* update flags before setting cmp to load */
2457    gen_update_cc_cmp(s, load, cmp, opsize);
2458    gen_partset_reg(opsize, DREG(ext, 0), load);
2459
2460    tcg_temp_free(load);
2461
2462    switch (extract32(insn, 3, 3)) {
2463    case 3: /* Indirect postincrement.  */
2464        tcg_gen_addi_i32(AREG(insn, 0), addr, opsize_bytes(opsize));
2465        break;
2466    case 4: /* Indirect predecrememnt.  */
2467        tcg_gen_mov_i32(AREG(insn, 0), addr);
2468        break;
2469    }
2470}
2471
2472DISAS_INSN(cas2w)
2473{
2474    uint16_t ext1, ext2;
2475    TCGv addr1, addr2;
2476    TCGv regs;
2477
2478    /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2479
2480    ext1 = read_im16(env, s);
2481
2482    if (ext1 & 0x8000) {
2483        /* Address Register */
2484        addr1 = AREG(ext1, 12);
2485    } else {
2486        /* Data Register */
2487        addr1 = DREG(ext1, 12);
2488    }
2489
2490    ext2 = read_im16(env, s);
2491    if (ext2 & 0x8000) {
2492        /* Address Register */
2493        addr2 = AREG(ext2, 12);
2494    } else {
2495        /* Data Register */
2496        addr2 = DREG(ext2, 12);
2497    }
2498
2499    /*
2500     * if (R1) == Dc1 && (R2) == Dc2 then
2501     *     (R1) = Du1
2502     *     (R2) = Du2
2503     * else
2504     *     Dc1 = (R1)
2505     *     Dc2 = (R2)
2506     */
2507
2508    regs = tcg_const_i32(REG(ext2, 6) |
2509                         (REG(ext1, 6) << 3) |
2510                         (REG(ext2, 0) << 6) |
2511                         (REG(ext1, 0) << 9));
2512    if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2513        gen_helper_exit_atomic(cpu_env);
2514    } else {
2515        gen_helper_cas2w(cpu_env, regs, addr1, addr2);
2516    }
2517    tcg_temp_free(regs);
2518
2519    /* Note that cas2w also assigned to env->cc_op.  */
2520    s->cc_op = CC_OP_CMPW;
2521    s->cc_op_synced = 1;
2522}
2523
2524DISAS_INSN(cas2l)
2525{
2526    uint16_t ext1, ext2;
2527    TCGv addr1, addr2, regs;
2528
2529    /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2530
2531    ext1 = read_im16(env, s);
2532
2533    if (ext1 & 0x8000) {
2534        /* Address Register */
2535        addr1 = AREG(ext1, 12);
2536    } else {
2537        /* Data Register */
2538        addr1 = DREG(ext1, 12);
2539    }
2540
2541    ext2 = read_im16(env, s);
2542    if (ext2 & 0x8000) {
2543        /* Address Register */
2544        addr2 = AREG(ext2, 12);
2545    } else {
2546        /* Data Register */
2547        addr2 = DREG(ext2, 12);
2548    }
2549
2550    /*
2551     * if (R1) == Dc1 && (R2) == Dc2 then
2552     *     (R1) = Du1
2553     *     (R2) = Du2
2554     * else
2555     *     Dc1 = (R1)
2556     *     Dc2 = (R2)
2557     */
2558
2559    regs = tcg_const_i32(REG(ext2, 6) |
2560                         (REG(ext1, 6) << 3) |
2561                         (REG(ext2, 0) << 6) |
2562                         (REG(ext1, 0) << 9));
2563    if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2564        gen_helper_cas2l_parallel(cpu_env, regs, addr1, addr2);
2565    } else {
2566        gen_helper_cas2l(cpu_env, regs, addr1, addr2);
2567    }
2568    tcg_temp_free(regs);
2569
2570    /* Note that cas2l also assigned to env->cc_op.  */
2571    s->cc_op = CC_OP_CMPL;
2572    s->cc_op_synced = 1;
2573}
2574
2575DISAS_INSN(byterev)
2576{
2577    TCGv reg;
2578
2579    reg = DREG(insn, 0);
2580    tcg_gen_bswap32_i32(reg, reg);
2581}
2582
2583DISAS_INSN(move)
2584{
2585    TCGv src;
2586    TCGv dest;
2587    int op;
2588    int opsize;
2589
2590    switch (insn >> 12) {
2591    case 1: /* move.b */
2592        opsize = OS_BYTE;
2593        break;
2594    case 2: /* move.l */
2595        opsize = OS_LONG;
2596        break;
2597    case 3: /* move.w */
2598        opsize = OS_WORD;
2599        break;
2600    default:
2601        abort();
2602    }
2603    SRC_EA(env, src, opsize, 1, NULL);
2604    op = (insn >> 6) & 7;
2605    if (op == 1) {
2606        /* movea */
2607        /* The value will already have been sign extended.  */
2608        dest = AREG(insn, 9);
2609        tcg_gen_mov_i32(dest, src);
2610    } else {
2611        /* normal move */
2612        uint16_t dest_ea;
2613        dest_ea = ((insn >> 9) & 7) | (op << 3);
2614        DEST_EA(env, dest_ea, opsize, src, NULL);
2615        /* This will be correct because loads sign extend.  */
2616        gen_logic_cc(s, src, opsize);
2617    }
2618}
2619
2620DISAS_INSN(negx)
2621{
2622    TCGv z;
2623    TCGv src;
2624    TCGv addr;
2625    int opsize;
2626
2627    opsize = insn_opsize(insn);
2628    SRC_EA(env, src, opsize, 1, &addr);
2629
2630    gen_flush_flags(s); /* compute old Z */
2631
2632    /*
2633     * Perform subtract with borrow.
2634     * (X, N) =  -(src + X);
2635     */
2636
2637    z = tcg_const_i32(0);
2638    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
2639    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X);
2640    tcg_temp_free(z);
2641    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
2642
2643    tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
2644
2645    /*
2646     * Compute signed-overflow for negation.  The normal formula for
2647     * subtraction is (res ^ src) & (src ^ dest), but with dest==0
2648     * this simplifies to res & src.
2649     */
2650
2651    tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src);
2652
2653    /* Copy the rest of the results into place.  */
2654    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
2655    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
2656
2657    set_cc_op(s, CC_OP_FLAGS);
2658
2659    /* result is in QREG_CC_N */
2660
2661    DEST_EA(env, insn, opsize, QREG_CC_N, &addr);
2662}
2663
2664DISAS_INSN(lea)
2665{
2666    TCGv reg;
2667    TCGv tmp;
2668
2669    reg = AREG(insn, 9);
2670    tmp = gen_lea(env, s, insn, OS_LONG);
2671    if (IS_NULL_QREG(tmp)) {
2672        gen_addr_fault(s);
2673        return;
2674    }
2675    tcg_gen_mov_i32(reg, tmp);
2676}
2677
2678DISAS_INSN(clr)
2679{
2680    int opsize;
2681    TCGv zero;
2682
2683    zero = tcg_const_i32(0);
2684
2685    opsize = insn_opsize(insn);
2686    DEST_EA(env, insn, opsize, zero, NULL);
2687    gen_logic_cc(s, zero, opsize);
2688    tcg_temp_free(zero);
2689}
2690
2691DISAS_INSN(move_from_ccr)
2692{
2693    TCGv ccr;
2694
2695    ccr = gen_get_ccr(s);
2696    DEST_EA(env, insn, OS_WORD, ccr, NULL);
2697}
2698
2699DISAS_INSN(neg)
2700{
2701    TCGv src1;
2702    TCGv dest;
2703    TCGv addr;
2704    int opsize;
2705
2706    opsize = insn_opsize(insn);
2707    SRC_EA(env, src1, opsize, 1, &addr);
2708    dest = tcg_temp_new();
2709    tcg_gen_neg_i32(dest, src1);
2710    set_cc_op(s, CC_OP_SUBB + opsize);
2711    gen_update_cc_add(dest, src1, opsize);
2712    tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, dest, 0);
2713    DEST_EA(env, insn, opsize, dest, &addr);
2714    tcg_temp_free(dest);
2715}
2716
2717DISAS_INSN(move_to_ccr)
2718{
2719    gen_move_to_sr(env, s, insn, true);
2720}
2721
2722DISAS_INSN(not)
2723{
2724    TCGv src1;
2725    TCGv dest;
2726    TCGv addr;
2727    int opsize;
2728
2729    opsize = insn_opsize(insn);
2730    SRC_EA(env, src1, opsize, 1, &addr);
2731    dest = tcg_temp_new();
2732    tcg_gen_not_i32(dest, src1);
2733    DEST_EA(env, insn, opsize, dest, &addr);
2734    gen_logic_cc(s, dest, opsize);
2735}
2736
2737DISAS_INSN(swap)
2738{
2739    TCGv src1;
2740    TCGv src2;
2741    TCGv reg;
2742
2743    src1 = tcg_temp_new();
2744    src2 = tcg_temp_new();
2745    reg = DREG(insn, 0);
2746    tcg_gen_shli_i32(src1, reg, 16);
2747    tcg_gen_shri_i32(src2, reg, 16);
2748    tcg_gen_or_i32(reg, src1, src2);
2749    tcg_temp_free(src2);
2750    tcg_temp_free(src1);
2751    gen_logic_cc(s, reg, OS_LONG);
2752}
2753
2754DISAS_INSN(bkpt)
2755{
2756    gen_exception(s, s->base.pc_next, EXCP_DEBUG);
2757}
2758
2759DISAS_INSN(pea)
2760{
2761    TCGv tmp;
2762
2763    tmp = gen_lea(env, s, insn, OS_LONG);
2764    if (IS_NULL_QREG(tmp)) {
2765        gen_addr_fault(s);
2766        return;
2767    }
2768    gen_push(s, tmp);
2769}
2770
2771DISAS_INSN(ext)
2772{
2773    int op;
2774    TCGv reg;
2775    TCGv tmp;
2776
2777    reg = DREG(insn, 0);
2778    op = (insn >> 6) & 7;
2779    tmp = tcg_temp_new();
2780    if (op == 3)
2781        tcg_gen_ext16s_i32(tmp, reg);
2782    else
2783        tcg_gen_ext8s_i32(tmp, reg);
2784    if (op == 2)
2785        gen_partset_reg(OS_WORD, reg, tmp);
2786    else
2787        tcg_gen_mov_i32(reg, tmp);
2788    gen_logic_cc(s, tmp, OS_LONG);
2789    tcg_temp_free(tmp);
2790}
2791
2792DISAS_INSN(tst)
2793{
2794    int opsize;
2795    TCGv tmp;
2796
2797    opsize = insn_opsize(insn);
2798    SRC_EA(env, tmp, opsize, 1, NULL);
2799    gen_logic_cc(s, tmp, opsize);
2800}
2801
2802DISAS_INSN(pulse)
2803{
2804  /* Implemented as a NOP.  */
2805}
2806
2807DISAS_INSN(illegal)
2808{
2809    gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2810}
2811
2812/* ??? This should be atomic.  */
2813DISAS_INSN(tas)
2814{
2815    TCGv dest;
2816    TCGv src1;
2817    TCGv addr;
2818
2819    dest = tcg_temp_new();
2820    SRC_EA(env, src1, OS_BYTE, 1, &addr);
2821    gen_logic_cc(s, src1, OS_BYTE);
2822    tcg_gen_ori_i32(dest, src1, 0x80);
2823    DEST_EA(env, insn, OS_BYTE, dest, &addr);
2824    tcg_temp_free(dest);
2825}
2826
2827DISAS_INSN(mull)
2828{
2829    uint16_t ext;
2830    TCGv src1;
2831    int sign;
2832
2833    ext = read_im16(env, s);
2834
2835    sign = ext & 0x800;
2836
2837    if (ext & 0x400) {
2838        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
2839            gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2840            return;
2841        }
2842
2843        SRC_EA(env, src1, OS_LONG, 0, NULL);
2844
2845        if (sign) {
2846            tcg_gen_muls2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2847        } else {
2848            tcg_gen_mulu2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2849        }
2850        /* if Dl == Dh, 68040 returns low word */
2851        tcg_gen_mov_i32(DREG(ext, 0), QREG_CC_N);
2852        tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_Z);
2853        tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N);
2854
2855        tcg_gen_movi_i32(QREG_CC_V, 0);
2856        tcg_gen_movi_i32(QREG_CC_C, 0);
2857
2858        set_cc_op(s, CC_OP_FLAGS);
2859        return;
2860    }
2861    SRC_EA(env, src1, OS_LONG, 0, NULL);
2862    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
2863        tcg_gen_movi_i32(QREG_CC_C, 0);
2864        if (sign) {
2865            tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2866            /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */
2867            tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31);
2868            tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_Z);
2869        } else {
2870            tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2871            /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */
2872            tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_C);
2873        }
2874        tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
2875        tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
2876
2877        tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
2878
2879        set_cc_op(s, CC_OP_FLAGS);
2880    } else {
2881        /*
2882         * The upper 32 bits of the product are discarded, so
2883         * muls.l and mulu.l are functionally equivalent.
2884         */
2885        tcg_gen_mul_i32(DREG(ext, 12), src1, DREG(ext, 12));
2886        gen_logic_cc(s, DREG(ext, 12), OS_LONG);
2887    }
2888}
2889
2890static void gen_link(DisasContext *s, uint16_t insn, int32_t offset)
2891{
2892    TCGv reg;
2893    TCGv tmp;
2894
2895    reg = AREG(insn, 0);
2896    tmp = tcg_temp_new();
2897    tcg_gen_subi_i32(tmp, QREG_SP, 4);
2898    gen_store(s, OS_LONG, tmp, reg, IS_USER(s));
2899    if ((insn & 7) != 7) {
2900        tcg_gen_mov_i32(reg, tmp);
2901    }
2902    tcg_gen_addi_i32(QREG_SP, tmp, offset);
2903    tcg_temp_free(tmp);
2904}
2905
2906DISAS_INSN(link)
2907{
2908    int16_t offset;
2909
2910    offset = read_im16(env, s);
2911    gen_link(s, insn, offset);
2912}
2913
2914DISAS_INSN(linkl)
2915{
2916    int32_t offset;
2917
2918    offset = read_im32(env, s);
2919    gen_link(s, insn, offset);
2920}
2921
2922DISAS_INSN(unlk)
2923{
2924    TCGv src;
2925    TCGv reg;
2926    TCGv tmp;
2927
2928    src = tcg_temp_new();
2929    reg = AREG(insn, 0);
2930    tcg_gen_mov_i32(src, reg);
2931    tmp = gen_load(s, OS_LONG, src, 0, IS_USER(s));
2932    tcg_gen_mov_i32(reg, tmp);
2933    tcg_gen_addi_i32(QREG_SP, src, 4);
2934    tcg_temp_free(src);
2935    tcg_temp_free(tmp);
2936}
2937
2938#if defined(CONFIG_SOFTMMU)
2939DISAS_INSN(reset)
2940{
2941    if (IS_USER(s)) {
2942        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2943        return;
2944    }
2945
2946    gen_helper_reset(cpu_env);
2947}
2948#endif
2949
2950DISAS_INSN(nop)
2951{
2952}
2953
2954DISAS_INSN(rtd)
2955{
2956    TCGv tmp;
2957    int16_t offset = read_im16(env, s);
2958
2959    tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2960    tcg_gen_addi_i32(QREG_SP, QREG_SP, offset + 4);
2961    gen_jmp(s, tmp);
2962}
2963
2964DISAS_INSN(rtr)
2965{
2966    TCGv tmp;
2967    TCGv ccr;
2968    TCGv sp;
2969
2970    sp = tcg_temp_new();
2971    ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
2972    tcg_gen_addi_i32(sp, QREG_SP, 2);
2973    tmp = gen_load(s, OS_LONG, sp, 0, IS_USER(s));
2974    tcg_gen_addi_i32(QREG_SP, sp, 4);
2975    tcg_temp_free(sp);
2976
2977    gen_set_sr(s, ccr, true);
2978    tcg_temp_free(ccr);
2979
2980    gen_jmp(s, tmp);
2981}
2982
2983DISAS_INSN(rts)
2984{
2985    TCGv tmp;
2986
2987    tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2988    tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
2989    gen_jmp(s, tmp);
2990}
2991
2992DISAS_INSN(jump)
2993{
2994    TCGv tmp;
2995
2996    /*
2997     * Load the target address first to ensure correct exception
2998     * behavior.
2999     */
3000    tmp = gen_lea(env, s, insn, OS_LONG);
3001    if (IS_NULL_QREG(tmp)) {
3002        gen_addr_fault(s);
3003        return;
3004    }
3005    if ((insn & 0x40) == 0) {
3006        /* jsr */
3007        gen_push(s, tcg_const_i32(s->pc));
3008    }
3009    gen_jmp(s, tmp);
3010}
3011
3012DISAS_INSN(addsubq)
3013{
3014    TCGv src;
3015    TCGv dest;
3016    TCGv val;
3017    int imm;
3018    TCGv addr;
3019    int opsize;
3020
3021    if ((insn & 070) == 010) {
3022        /* Operation on address register is always long.  */
3023        opsize = OS_LONG;
3024    } else {
3025        opsize = insn_opsize(insn);
3026    }
3027    SRC_EA(env, src, opsize, 1, &addr);
3028    imm = (insn >> 9) & 7;
3029    if (imm == 0) {
3030        imm = 8;
3031    }
3032    val = tcg_const_i32(imm);
3033    dest = tcg_temp_new();
3034    tcg_gen_mov_i32(dest, src);
3035    if ((insn & 0x38) == 0x08) {
3036        /*
3037         * Don't update condition codes if the destination is an
3038         * address register.
3039         */
3040        if (insn & 0x0100) {
3041            tcg_gen_sub_i32(dest, dest, val);
3042        } else {
3043            tcg_gen_add_i32(dest, dest, val);
3044        }
3045    } else {
3046        if (insn & 0x0100) {
3047            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
3048            tcg_gen_sub_i32(dest, dest, val);
3049            set_cc_op(s, CC_OP_SUBB + opsize);
3050        } else {
3051            tcg_gen_add_i32(dest, dest, val);
3052            tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
3053            set_cc_op(s, CC_OP_ADDB + opsize);
3054        }
3055        gen_update_cc_add(dest, val, opsize);
3056    }
3057    tcg_temp_free(val);
3058    DEST_EA(env, insn, opsize, dest, &addr);
3059    tcg_temp_free(dest);
3060}
3061
3062DISAS_INSN(tpf)
3063{
3064    switch (insn & 7) {
3065    case 2: /* One extension word.  */
3066        s->pc += 2;
3067        break;
3068    case 3: /* Two extension words.  */
3069        s->pc += 4;
3070        break;
3071    case 4: /* No extension words.  */
3072        break;
3073    default:
3074        disas_undef(env, s, insn);
3075    }
3076}
3077
3078DISAS_INSN(branch)
3079{
3080    int32_t offset;
3081    uint32_t base;
3082    int op;
3083
3084    base = s->pc;
3085    op = (insn >> 8) & 0xf;
3086    offset = (int8_t)insn;
3087    if (offset == 0) {
3088        offset = (int16_t)read_im16(env, s);
3089    } else if (offset == -1) {
3090        offset = read_im32(env, s);
3091    }
3092    if (op == 1) {
3093        /* bsr */
3094        gen_push(s, tcg_const_i32(s->pc));
3095    }
3096    if (op > 1) {
3097        /* Bcc */
3098        TCGLabel *l1 = gen_new_label();
3099        gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
3100        gen_jmp_tb(s, 1, base + offset);
3101        gen_set_label(l1);
3102        gen_jmp_tb(s, 0, s->pc);
3103    } else {
3104        /* Unconditional branch.  */
3105        update_cc_op(s);
3106        gen_jmp_tb(s, 0, base + offset);
3107    }
3108}
3109
3110DISAS_INSN(moveq)
3111{
3112    tcg_gen_movi_i32(DREG(insn, 9), (int8_t)insn);
3113    gen_logic_cc(s, DREG(insn, 9), OS_LONG);
3114}
3115
3116DISAS_INSN(mvzs)
3117{
3118    int opsize;
3119    TCGv src;
3120    TCGv reg;
3121
3122    if (insn & 0x40)
3123        opsize = OS_WORD;
3124    else
3125        opsize = OS_BYTE;
3126    SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL);
3127    reg = DREG(insn, 9);
3128    tcg_gen_mov_i32(reg, src);
3129    gen_logic_cc(s, src, opsize);
3130}
3131
3132DISAS_INSN(or)
3133{
3134    TCGv reg;
3135    TCGv dest;
3136    TCGv src;
3137    TCGv addr;
3138    int opsize;
3139
3140    opsize = insn_opsize(insn);
3141    reg = gen_extend(s, DREG(insn, 9), opsize, 0);
3142    dest = tcg_temp_new();
3143    if (insn & 0x100) {
3144        SRC_EA(env, src, opsize, 0, &addr);
3145        tcg_gen_or_i32(dest, src, reg);
3146        DEST_EA(env, insn, opsize, dest, &addr);
3147    } else {
3148        SRC_EA(env, src, opsize, 0, NULL);
3149        tcg_gen_or_i32(dest, src, reg);
3150        gen_partset_reg(opsize, DREG(insn, 9), dest);
3151    }
3152    gen_logic_cc(s, dest, opsize);
3153    tcg_temp_free(dest);
3154}
3155
3156DISAS_INSN(suba)
3157{
3158    TCGv src;
3159    TCGv reg;
3160
3161    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3162    reg = AREG(insn, 9);
3163    tcg_gen_sub_i32(reg, reg, src);
3164}
3165
3166static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3167{
3168    TCGv tmp;
3169
3170    gen_flush_flags(s); /* compute old Z */
3171
3172    /*
3173     * Perform subtract with borrow.
3174     * (X, N) = dest - (src + X);
3175     */
3176
3177    tmp = tcg_const_i32(0);
3178    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, tmp, QREG_CC_X, tmp);
3179    tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, tmp, QREG_CC_N, QREG_CC_X);
3180    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3181    tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
3182
3183    /* Compute signed-overflow for subtract.  */
3184
3185    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest);
3186    tcg_gen_xor_i32(tmp, dest, src);
3187    tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp);
3188    tcg_temp_free(tmp);
3189
3190    /* Copy the rest of the results into place.  */
3191    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3192    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3193
3194    set_cc_op(s, CC_OP_FLAGS);
3195
3196    /* result is in QREG_CC_N */
3197}
3198
3199DISAS_INSN(subx_reg)
3200{
3201    TCGv dest;
3202    TCGv src;
3203    int opsize;
3204
3205    opsize = insn_opsize(insn);
3206
3207    src = gen_extend(s, DREG(insn, 0), opsize, 1);
3208    dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3209
3210    gen_subx(s, src, dest, opsize);
3211
3212    gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3213}
3214
3215DISAS_INSN(subx_mem)
3216{
3217    TCGv src;
3218    TCGv addr_src;
3219    TCGv dest;
3220    TCGv addr_dest;
3221    int opsize;
3222
3223    opsize = insn_opsize(insn);
3224
3225    addr_src = AREG(insn, 0);
3226    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3227    src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3228
3229    addr_dest = AREG(insn, 9);
3230    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3231    dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3232
3233    gen_subx(s, src, dest, opsize);
3234
3235    gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3236
3237    tcg_temp_free(dest);
3238    tcg_temp_free(src);
3239}
3240
3241DISAS_INSN(mov3q)
3242{
3243    TCGv src;
3244    int val;
3245
3246    val = (insn >> 9) & 7;
3247    if (val == 0)
3248        val = -1;
3249    src = tcg_const_i32(val);
3250    gen_logic_cc(s, src, OS_LONG);
3251    DEST_EA(env, insn, OS_LONG, src, NULL);
3252    tcg_temp_free(src);
3253}
3254
3255DISAS_INSN(cmp)
3256{
3257    TCGv src;
3258    TCGv reg;
3259    int opsize;
3260
3261    opsize = insn_opsize(insn);
3262    SRC_EA(env, src, opsize, 1, NULL);
3263    reg = gen_extend(s, DREG(insn, 9), opsize, 1);
3264    gen_update_cc_cmp(s, reg, src, opsize);
3265}
3266
3267DISAS_INSN(cmpa)
3268{
3269    int opsize;
3270    TCGv src;
3271    TCGv reg;
3272
3273    if (insn & 0x100) {
3274        opsize = OS_LONG;
3275    } else {
3276        opsize = OS_WORD;
3277    }
3278    SRC_EA(env, src, opsize, 1, NULL);
3279    reg = AREG(insn, 9);
3280    gen_update_cc_cmp(s, reg, src, OS_LONG);
3281}
3282
3283DISAS_INSN(cmpm)
3284{
3285    int opsize = insn_opsize(insn);
3286    TCGv src, dst;
3287
3288    /* Post-increment load (mode 3) from Ay.  */
3289    src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize,
3290                      NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3291    /* Post-increment load (mode 3) from Ax.  */
3292    dst = gen_ea_mode(env, s, 3, REG(insn, 9), opsize,
3293                      NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3294
3295    gen_update_cc_cmp(s, dst, src, opsize);
3296}
3297
3298DISAS_INSN(eor)
3299{
3300    TCGv src;
3301    TCGv dest;
3302    TCGv addr;
3303    int opsize;
3304
3305    opsize = insn_opsize(insn);
3306
3307    SRC_EA(env, src, opsize, 0, &addr);
3308    dest = tcg_temp_new();
3309    tcg_gen_xor_i32(dest, src, DREG(insn, 9));
3310    gen_logic_cc(s, dest, opsize);
3311    DEST_EA(env, insn, opsize, dest, &addr);
3312    tcg_temp_free(dest);
3313}
3314
3315static void do_exg(TCGv reg1, TCGv reg2)
3316{
3317    TCGv temp = tcg_temp_new();
3318    tcg_gen_mov_i32(temp, reg1);
3319    tcg_gen_mov_i32(reg1, reg2);
3320    tcg_gen_mov_i32(reg2, temp);
3321    tcg_temp_free(temp);
3322}
3323
3324DISAS_INSN(exg_dd)
3325{
3326    /* exchange Dx and Dy */
3327    do_exg(DREG(insn, 9), DREG(insn, 0));
3328}
3329
3330DISAS_INSN(exg_aa)
3331{
3332    /* exchange Ax and Ay */
3333    do_exg(AREG(insn, 9), AREG(insn, 0));
3334}
3335
3336DISAS_INSN(exg_da)
3337{
3338    /* exchange Dx and Ay */
3339    do_exg(DREG(insn, 9), AREG(insn, 0));
3340}
3341
3342DISAS_INSN(and)
3343{
3344    TCGv src;
3345    TCGv reg;
3346    TCGv dest;
3347    TCGv addr;
3348    int opsize;
3349
3350    dest = tcg_temp_new();
3351
3352    opsize = insn_opsize(insn);
3353    reg = DREG(insn, 9);
3354    if (insn & 0x100) {
3355        SRC_EA(env, src, opsize, 0, &addr);
3356        tcg_gen_and_i32(dest, src, reg);
3357        DEST_EA(env, insn, opsize, dest, &addr);
3358    } else {
3359        SRC_EA(env, src, opsize, 0, NULL);
3360        tcg_gen_and_i32(dest, src, reg);
3361        gen_partset_reg(opsize, reg, dest);
3362    }
3363    gen_logic_cc(s, dest, opsize);
3364    tcg_temp_free(dest);
3365}
3366
3367DISAS_INSN(adda)
3368{
3369    TCGv src;
3370    TCGv reg;
3371
3372    SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3373    reg = AREG(insn, 9);
3374    tcg_gen_add_i32(reg, reg, src);
3375}
3376
3377static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3378{
3379    TCGv tmp;
3380
3381    gen_flush_flags(s); /* compute old Z */
3382
3383    /*
3384     * Perform addition with carry.
3385     * (X, N) = src + dest + X;
3386     */
3387
3388    tmp = tcg_const_i32(0);
3389    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, tmp, dest, tmp);
3390    tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, tmp);
3391    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3392
3393    /* Compute signed-overflow for addition.  */
3394
3395    tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3396    tcg_gen_xor_i32(tmp, dest, src);
3397    tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp);
3398    tcg_temp_free(tmp);
3399
3400    /* Copy the rest of the results into place.  */
3401    tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3402    tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3403
3404    set_cc_op(s, CC_OP_FLAGS);
3405
3406    /* result is in QREG_CC_N */
3407}
3408
3409DISAS_INSN(addx_reg)
3410{
3411    TCGv dest;
3412    TCGv src;
3413    int opsize;
3414
3415    opsize = insn_opsize(insn);
3416
3417    dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3418    src = gen_extend(s, DREG(insn, 0), opsize, 1);
3419
3420    gen_addx(s, src, dest, opsize);
3421
3422    gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3423}
3424
3425DISAS_INSN(addx_mem)
3426{
3427    TCGv src;
3428    TCGv addr_src;
3429    TCGv dest;
3430    TCGv addr_dest;
3431    int opsize;
3432
3433    opsize = insn_opsize(insn);
3434
3435    addr_src = AREG(insn, 0);
3436    tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3437    src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3438
3439    addr_dest = AREG(insn, 9);
3440    tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3441    dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3442
3443    gen_addx(s, src, dest, opsize);
3444
3445    gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3446
3447    tcg_temp_free(dest);
3448    tcg_temp_free(src);
3449}
3450
3451static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
3452{
3453    int count = (insn >> 9) & 7;
3454    int logical = insn & 8;
3455    int left = insn & 0x100;
3456    int bits = opsize_bytes(opsize) * 8;
3457    TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3458
3459    if (count == 0) {
3460        count = 8;
3461    }
3462
3463    tcg_gen_movi_i32(QREG_CC_V, 0);
3464    if (left) {
3465        tcg_gen_shri_i32(QREG_CC_C, reg, bits - count);
3466        tcg_gen_shli_i32(QREG_CC_N, reg, count);
3467
3468        /*
3469         * Note that ColdFire always clears V (done above),
3470         * while M68000 sets if the most significant bit is changed at
3471         * any time during the shift operation.
3472         */
3473        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
3474            /* if shift count >= bits, V is (reg != 0) */
3475            if (count >= bits) {
3476                tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V);
3477            } else {
3478                TCGv t0 = tcg_temp_new();
3479                tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1);
3480                tcg_gen_sari_i32(t0, reg, bits - count - 1);
3481                tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0);
3482                tcg_temp_free(t0);
3483            }
3484            tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
3485        }
3486    } else {
3487        tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
3488        if (logical) {
3489            tcg_gen_shri_i32(QREG_CC_N, reg, count);
3490        } else {
3491            tcg_gen_sari_i32(QREG_CC_N, reg, count);
3492        }
3493    }
3494
3495    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3496    tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3497    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3498    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3499
3500    gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3501    set_cc_op(s, CC_OP_FLAGS);
3502}
3503
3504static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
3505{
3506    int logical = insn & 8;
3507    int left = insn & 0x100;
3508    int bits = opsize_bytes(opsize) * 8;
3509    TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3510    TCGv s32;
3511    TCGv_i64 t64, s64;
3512
3513    t64 = tcg_temp_new_i64();
3514    s64 = tcg_temp_new_i64();
3515    s32 = tcg_temp_new();
3516
3517    /*
3518     * Note that m68k truncates the shift count modulo 64, not 32.
3519     * In addition, a 64-bit shift makes it easy to find "the last
3520     * bit shifted out", for the carry flag.
3521     */
3522    tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
3523    tcg_gen_extu_i32_i64(s64, s32);
3524    tcg_gen_extu_i32_i64(t64, reg);
3525
3526    /* Optimistically set V=0.  Also used as a zero source below.  */
3527    tcg_gen_movi_i32(QREG_CC_V, 0);
3528    if (left) {
3529        tcg_gen_shl_i64(t64, t64, s64);
3530
3531        if (opsize == OS_LONG) {
3532            tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
3533            /* Note that C=0 if shift count is 0, and we get that for free.  */
3534        } else {
3535            TCGv zero = tcg_const_i32(0);
3536            tcg_gen_extrl_i64_i32(QREG_CC_N, t64);
3537            tcg_gen_shri_i32(QREG_CC_C, QREG_CC_N, bits);
3538            tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3539                                s32, zero, zero, QREG_CC_C);
3540            tcg_temp_free(zero);
3541        }
3542        tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3543
3544        /* X = C, but only if the shift count was non-zero.  */
3545        tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3546                            QREG_CC_C, QREG_CC_X);
3547
3548        /*
3549         * M68000 sets V if the most significant bit is changed at
3550         * any time during the shift operation.  Do this via creating
3551         * an extension of the sign bit, comparing, and discarding
3552         * the bits below the sign bit.  I.e.
3553         *     int64_t s = (intN_t)reg;
3554         *     int64_t t = (int64_t)(intN_t)reg << count;
3555         *     V = ((s ^ t) & (-1 << (bits - 1))) != 0
3556         */
3557        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
3558            TCGv_i64 tt = tcg_const_i64(32);
3559            /* if shift is greater than 32, use 32 */
3560            tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64);
3561            tcg_temp_free_i64(tt);
3562            /* Sign extend the input to 64 bits; re-do the shift.  */
3563            tcg_gen_ext_i32_i64(t64, reg);
3564            tcg_gen_shl_i64(s64, t64, s64);
3565            /* Clear all bits that are unchanged.  */
3566            tcg_gen_xor_i64(t64, t64, s64);
3567            /* Ignore the bits below the sign bit.  */
3568            tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
3569            /* If any bits remain set, we have overflow.  */
3570            tcg_gen_setcondi_i64(TCG_COND_NE, t64, t64, 0);
3571            tcg_gen_extrl_i64_i32(QREG_CC_V, t64);
3572            tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
3573        }
3574    } else {
3575        tcg_gen_shli_i64(t64, t64, 32);
3576        if (logical) {
3577            tcg_gen_shr_i64(t64, t64, s64);
3578        } else {
3579            tcg_gen_sar_i64(t64, t64, s64);
3580        }
3581        tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
3582
3583        /* Note that C=0 if shift count is 0, and we get that for free.  */
3584        tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
3585
3586        /* X = C, but only if the shift count was non-zero.  */
3587        tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3588                            QREG_CC_C, QREG_CC_X);
3589    }
3590    gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3591    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3592
3593    tcg_temp_free(s32);
3594    tcg_temp_free_i64(s64);
3595    tcg_temp_free_i64(t64);
3596
3597    /* Write back the result.  */
3598    gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3599    set_cc_op(s, CC_OP_FLAGS);
3600}
3601
3602DISAS_INSN(shift8_im)
3603{
3604    shift_im(s, insn, OS_BYTE);
3605}
3606
3607DISAS_INSN(shift16_im)
3608{
3609    shift_im(s, insn, OS_WORD);
3610}
3611
3612DISAS_INSN(shift_im)
3613{
3614    shift_im(s, insn, OS_LONG);
3615}
3616
3617DISAS_INSN(shift8_reg)
3618{
3619    shift_reg(s, insn, OS_BYTE);
3620}
3621
3622DISAS_INSN(shift16_reg)
3623{
3624    shift_reg(s, insn, OS_WORD);
3625}
3626
3627DISAS_INSN(shift_reg)
3628{
3629    shift_reg(s, insn, OS_LONG);
3630}
3631
3632DISAS_INSN(shift_mem)
3633{
3634    int logical = insn & 8;
3635    int left = insn & 0x100;
3636    TCGv src;
3637    TCGv addr;
3638
3639    SRC_EA(env, src, OS_WORD, !logical, &addr);
3640    tcg_gen_movi_i32(QREG_CC_V, 0);
3641    if (left) {
3642        tcg_gen_shri_i32(QREG_CC_C, src, 15);
3643        tcg_gen_shli_i32(QREG_CC_N, src, 1);
3644
3645        /*
3646         * Note that ColdFire always clears V,
3647         * while M68000 sets if the most significant bit is changed at
3648         * any time during the shift operation
3649         */
3650        if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
3651            src = gen_extend(s, src, OS_WORD, 1);
3652            tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3653        }
3654    } else {
3655        tcg_gen_mov_i32(QREG_CC_C, src);
3656        if (logical) {
3657            tcg_gen_shri_i32(QREG_CC_N, src, 1);
3658        } else {
3659            tcg_gen_sari_i32(QREG_CC_N, src, 1);
3660        }
3661    }
3662
3663    gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1);
3664    tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3665    tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3666    tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3667
3668    DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr);
3669    set_cc_op(s, CC_OP_FLAGS);
3670}
3671
3672static void rotate(TCGv reg, TCGv shift, int left, int size)
3673{
3674    switch (size) {
3675    case 8:
3676        /* Replicate the 8-bit input so that a 32-bit rotate works.  */
3677        tcg_gen_ext8u_i32(reg, reg);
3678        tcg_gen_muli_i32(reg, reg, 0x01010101);
3679        goto do_long;
3680    case 16:
3681        /* Replicate the 16-bit input so that a 32-bit rotate works.  */
3682        tcg_gen_deposit_i32(reg, reg, reg, 16, 16);
3683        goto do_long;
3684    do_long:
3685    default:
3686        if (left) {
3687            tcg_gen_rotl_i32(reg, reg, shift);
3688        } else {
3689            tcg_gen_rotr_i32(reg, reg, shift);
3690        }
3691    }
3692
3693    /* compute flags */
3694
3695    switch (size) {
3696    case 8:
3697        tcg_gen_ext8s_i32(reg, reg);
3698        break;
3699    case 16:
3700        tcg_gen_ext16s_i32(reg, reg);
3701        break;
3702    default:
3703        break;
3704    }
3705
3706    /* QREG_CC_X is not affected */
3707
3708    tcg_gen_mov_i32(QREG_CC_N, reg);
3709    tcg_gen_mov_i32(QREG_CC_Z, reg);
3710
3711    if (left) {
3712        tcg_gen_andi_i32(QREG_CC_C, reg, 1);
3713    } else {
3714        tcg_gen_shri_i32(QREG_CC_C, reg, 31);
3715    }
3716
3717    tcg_gen_movi_i32(QREG_CC_V, 0); /* always cleared */
3718}
3719
3720static void rotate_x_flags(TCGv reg, TCGv X, int size)
3721{
3722    switch (size) {
3723    case 8:
3724        tcg_gen_ext8s_i32(reg, reg);
3725        break;
3726    case 16:
3727        tcg_gen_ext16s_i32(reg, reg);
3728        break;
3729    default:
3730        break;
3731    }
3732    tcg_gen_mov_i32(QREG_CC_N, reg);
3733    tcg_gen_mov_i32(QREG_CC_Z, reg);
3734    tcg_gen_mov_i32(QREG_CC_X, X);
3735    tcg_gen_mov_i32(QREG_CC_C, X);
3736    tcg_gen_movi_i32(QREG_CC_V, 0);
3737}
3738
3739/* Result of rotate_x() is valid if 0 <= shift <= size */
3740static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size)
3741{
3742    TCGv X, shl, shr, shx, sz, zero;
3743
3744    sz = tcg_const_i32(size);
3745
3746    shr = tcg_temp_new();
3747    shl = tcg_temp_new();
3748    shx = tcg_temp_new();
3749    if (left) {
3750        tcg_gen_mov_i32(shl, shift);      /* shl = shift */
3751        tcg_gen_movi_i32(shr, size + 1);
3752        tcg_gen_sub_i32(shr, shr, shift); /* shr = size + 1 - shift */
3753        tcg_gen_subi_i32(shx, shift, 1);  /* shx = shift - 1 */
3754        /* shx = shx < 0 ? size : shx; */
3755        zero = tcg_const_i32(0);
3756        tcg_gen_movcond_i32(TCG_COND_LT, shx, shx, zero, sz, shx);
3757        tcg_temp_free(zero);
3758    } else {
3759        tcg_gen_mov_i32(shr, shift);      /* shr = shift */
3760        tcg_gen_movi_i32(shl, size + 1);
3761        tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */
3762        tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */
3763    }
3764    tcg_temp_free_i32(sz);
3765
3766    /* reg = (reg << shl) | (reg >> shr) | (x << shx); */
3767
3768    tcg_gen_shl_i32(shl, reg, shl);
3769    tcg_gen_shr_i32(shr, reg, shr);
3770    tcg_gen_or_i32(reg, shl, shr);
3771    tcg_temp_free(shl);
3772    tcg_temp_free(shr);
3773    tcg_gen_shl_i32(shx, QREG_CC_X, shx);
3774    tcg_gen_or_i32(reg, reg, shx);
3775    tcg_temp_free(shx);
3776
3777    /* X = (reg >> size) & 1 */
3778
3779    X = tcg_temp_new();
3780    tcg_gen_extract_i32(X, reg, size, 1);
3781
3782    return X;
3783}
3784
3785/* Result of rotate32_x() is valid if 0 <= shift < 33 */
3786static TCGv rotate32_x(TCGv reg, TCGv shift, int left)
3787{
3788    TCGv_i64 t0, shift64;
3789    TCGv X, lo, hi, zero;
3790
3791    shift64 = tcg_temp_new_i64();
3792    tcg_gen_extu_i32_i64(shift64, shift);
3793
3794    t0 = tcg_temp_new_i64();
3795
3796    X = tcg_temp_new();
3797    lo = tcg_temp_new();
3798    hi = tcg_temp_new();
3799
3800    if (left) {
3801        /* create [reg:X:..] */
3802
3803        tcg_gen_shli_i32(lo, QREG_CC_X, 31);
3804        tcg_gen_concat_i32_i64(t0, lo, reg);
3805
3806        /* rotate */
3807
3808        tcg_gen_rotl_i64(t0, t0, shift64);
3809        tcg_temp_free_i64(shift64);
3810
3811        /* result is [reg:..:reg:X] */
3812
3813        tcg_gen_extr_i64_i32(lo, hi, t0);
3814        tcg_gen_andi_i32(X, lo, 1);
3815
3816        tcg_gen_shri_i32(lo, lo, 1);
3817    } else {
3818        /* create [..:X:reg] */
3819
3820        tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X);
3821
3822        tcg_gen_rotr_i64(t0, t0, shift64);
3823        tcg_temp_free_i64(shift64);
3824
3825        /* result is value: [X:reg:..:reg] */
3826
3827        tcg_gen_extr_i64_i32(lo, hi, t0);
3828
3829        /* extract X */
3830
3831        tcg_gen_shri_i32(X, hi, 31);
3832
3833        /* extract result */
3834
3835        tcg_gen_shli_i32(hi, hi, 1);
3836    }
3837    tcg_temp_free_i64(t0);
3838    tcg_gen_or_i32(lo, lo, hi);
3839    tcg_temp_free(hi);
3840
3841    /* if shift == 0, register and X are not affected */
3842
3843    zero = tcg_const_i32(0);
3844    tcg_gen_movcond_i32(TCG_COND_EQ, X, shift, zero, QREG_CC_X, X);
3845    tcg_gen_movcond_i32(TCG_COND_EQ, reg, shift, zero, reg, lo);
3846    tcg_temp_free(zero);
3847    tcg_temp_free(lo);
3848
3849    return X;
3850}
3851
3852DISAS_INSN(rotate_im)
3853{
3854    TCGv shift;
3855    int tmp;
3856    int left = (insn & 0x100);
3857
3858    tmp = (insn >> 9) & 7;
3859    if (tmp == 0) {
3860        tmp = 8;
3861    }
3862
3863    shift = tcg_const_i32(tmp);
3864    if (insn & 8) {
3865        rotate(DREG(insn, 0), shift, left, 32);
3866    } else {
3867        TCGv X = rotate32_x(DREG(insn, 0), shift, left);
3868        rotate_x_flags(DREG(insn, 0), X, 32);
3869        tcg_temp_free(X);
3870    }
3871    tcg_temp_free(shift);
3872
3873    set_cc_op(s, CC_OP_FLAGS);
3874}
3875
3876DISAS_INSN(rotate8_im)
3877{
3878    int left = (insn & 0x100);
3879    TCGv reg;
3880    TCGv shift;
3881    int tmp;
3882
3883    reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3884
3885    tmp = (insn >> 9) & 7;
3886    if (tmp == 0) {
3887        tmp = 8;
3888    }
3889
3890    shift = tcg_const_i32(tmp);
3891    if (insn & 8) {
3892        rotate(reg, shift, left, 8);
3893    } else {
3894        TCGv X = rotate_x(reg, shift, left, 8);
3895        rotate_x_flags(reg, X, 8);
3896        tcg_temp_free(X);
3897    }
3898    tcg_temp_free(shift);
3899    gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3900    set_cc_op(s, CC_OP_FLAGS);
3901}
3902
3903DISAS_INSN(rotate16_im)
3904{
3905    int left = (insn & 0x100);
3906    TCGv reg;
3907    TCGv shift;
3908    int tmp;
3909
3910    reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
3911    tmp = (insn >> 9) & 7;
3912    if (tmp == 0) {
3913        tmp = 8;
3914    }
3915
3916    shift = tcg_const_i32(tmp);
3917    if (insn & 8) {
3918        rotate(reg, shift, left, 16);
3919    } else {
3920        TCGv X = rotate_x(reg, shift, left, 16);
3921        rotate_x_flags(reg, X, 16);
3922        tcg_temp_free(X);
3923    }
3924    tcg_temp_free(shift);
3925    gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
3926    set_cc_op(s, CC_OP_FLAGS);
3927}
3928
3929DISAS_INSN(rotate_reg)
3930{
3931    TCGv reg;
3932    TCGv src;
3933    TCGv t0, t1;
3934    int left = (insn & 0x100);
3935
3936    reg = DREG(insn, 0);
3937    src = DREG(insn, 9);
3938    /* shift in [0..63] */
3939    t0 = tcg_temp_new();
3940    tcg_gen_andi_i32(t0, src, 63);
3941    t1 = tcg_temp_new_i32();
3942    if (insn & 8) {
3943        tcg_gen_andi_i32(t1, src, 31);
3944        rotate(reg, t1, left, 32);
3945        /* if shift == 0, clear C */
3946        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3947                            t0, QREG_CC_V /* 0 */,
3948                            QREG_CC_V /* 0 */, QREG_CC_C);
3949    } else {
3950        TCGv X;
3951        /* modulo 33 */
3952        tcg_gen_movi_i32(t1, 33);
3953        tcg_gen_remu_i32(t1, t0, t1);
3954        X = rotate32_x(DREG(insn, 0), t1, left);
3955        rotate_x_flags(DREG(insn, 0), X, 32);
3956        tcg_temp_free(X);
3957    }
3958    tcg_temp_free(t1);
3959    tcg_temp_free(t0);
3960    set_cc_op(s, CC_OP_FLAGS);
3961}
3962
3963DISAS_INSN(rotate8_reg)
3964{
3965    TCGv reg;
3966    TCGv src;
3967    TCGv t0, t1;
3968    int left = (insn & 0x100);
3969
3970    reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3971    src = DREG(insn, 9);
3972    /* shift in [0..63] */
3973    t0 = tcg_temp_new_i32();
3974    tcg_gen_andi_i32(t0, src, 63);
3975    t1 = tcg_temp_new_i32();
3976    if (insn & 8) {
3977        tcg_gen_andi_i32(t1, src, 7);
3978        rotate(reg, t1, left, 8);
3979        /* if shift == 0, clear C */
3980        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3981                            t0, QREG_CC_V /* 0 */,
3982                            QREG_CC_V /* 0 */, QREG_CC_C);
3983    } else {
3984        TCGv X;
3985        /* modulo 9 */
3986        tcg_gen_movi_i32(t1, 9);
3987        tcg_gen_remu_i32(t1, t0, t1);
3988        X = rotate_x(reg, t1, left, 8);
3989        rotate_x_flags(reg, X, 8);
3990        tcg_temp_free(X);
3991    }
3992    tcg_temp_free(t1);
3993    tcg_temp_free(t0);
3994    gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3995    set_cc_op(s, CC_OP_FLAGS);
3996}
3997
3998DISAS_INSN(rotate16_reg)
3999{
4000    TCGv reg;
4001    TCGv src;
4002    TCGv t0, t1;
4003    int left = (insn & 0x100);
4004
4005    reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
4006    src = DREG(insn, 9);
4007    /* shift in [0..63] */
4008    t0 = tcg_temp_new_i32();
4009    tcg_gen_andi_i32(t0, src, 63);
4010    t1 = tcg_temp_new_i32();
4011    if (insn & 8) {
4012        tcg_gen_andi_i32(t1, src, 15);
4013        rotate(reg, t1, left, 16);
4014        /* if shift == 0, clear C */
4015        tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
4016                            t0, QREG_CC_V /* 0 */,
4017                            QREG_CC_V /* 0 */, QREG_CC_C);
4018    } else {
4019        TCGv X;
4020        /* modulo 17 */
4021        tcg_gen_movi_i32(t1, 17);
4022        tcg_gen_remu_i32(t1, t0, t1);
4023        X = rotate_x(reg, t1, left, 16);
4024        rotate_x_flags(reg, X, 16);
4025        tcg_temp_free(X);
4026    }
4027    tcg_temp_free(t1);
4028    tcg_temp_free(t0);
4029    gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
4030    set_cc_op(s, CC_OP_FLAGS);
4031}
4032
4033DISAS_INSN(rotate_mem)
4034{
4035    TCGv src;
4036    TCGv addr;
4037    TCGv shift;
4038    int left = (insn & 0x100);
4039
4040    SRC_EA(env, src, OS_WORD, 0, &addr);
4041
4042    shift = tcg_const_i32(1);
4043    if (insn & 0x0200) {
4044        rotate(src, shift, left, 16);
4045    } else {
4046        TCGv X = rotate_x(src, shift, left, 16);
4047        rotate_x_flags(src, X, 16);
4048        tcg_temp_free(X);
4049    }
4050    tcg_temp_free(shift);
4051    DEST_EA(env, insn, OS_WORD, src, &addr);
4052    set_cc_op(s, CC_OP_FLAGS);
4053}
4054
4055DISAS_INSN(bfext_reg)
4056{
4057    int ext = read_im16(env, s);
4058    int is_sign = insn & 0x200;
4059    TCGv src = DREG(insn, 0);
4060    TCGv dst = DREG(ext, 12);
4061    int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4062    int ofs = extract32(ext, 6, 5);  /* big bit-endian */
4063    int pos = 32 - ofs - len;        /* little bit-endian */
4064    TCGv tmp = tcg_temp_new();
4065    TCGv shift;
4066
4067    /*
4068     * In general, we're going to rotate the field so that it's at the
4069     * top of the word and then right-shift by the complement of the
4070     * width to extend the field.
4071     */
4072    if (ext & 0x20) {
4073        /* Variable width.  */
4074        if (ext & 0x800) {
4075            /* Variable offset.  */
4076            tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
4077            tcg_gen_rotl_i32(tmp, src, tmp);
4078        } else {
4079            tcg_gen_rotli_i32(tmp, src, ofs);
4080        }
4081
4082        shift = tcg_temp_new();
4083        tcg_gen_neg_i32(shift, DREG(ext, 0));
4084        tcg_gen_andi_i32(shift, shift, 31);
4085        tcg_gen_sar_i32(QREG_CC_N, tmp, shift);
4086        if (is_sign) {
4087            tcg_gen_mov_i32(dst, QREG_CC_N);
4088        } else {
4089            tcg_gen_shr_i32(dst, tmp, shift);
4090        }
4091        tcg_temp_free(shift);
4092    } else {
4093        /* Immediate width.  */
4094        if (ext & 0x800) {
4095            /* Variable offset */
4096            tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
4097            tcg_gen_rotl_i32(tmp, src, tmp);
4098            src = tmp;
4099            pos = 32 - len;
4100        } else {
4101            /*
4102             * Immediate offset.  If the field doesn't wrap around the
4103             * end of the word, rely on (s)extract completely.
4104             */
4105            if (pos < 0) {
4106                tcg_gen_rotli_i32(tmp, src, ofs);
4107                src = tmp;
4108                pos = 32 - len;
4109            }
4110        }
4111
4112        tcg_gen_sextract_i32(QREG_CC_N, src, pos, len);
4113        if (is_sign) {
4114            tcg_gen_mov_i32(dst, QREG_CC_N);
4115        } else {
4116            tcg_gen_extract_i32(dst, src, pos, len);
4117        }
4118    }
4119
4120    tcg_temp_free(tmp);
4121    set_cc_op(s, CC_OP_LOGIC);
4122}
4123
4124DISAS_INSN(bfext_mem)
4125{
4126    int ext = read_im16(env, s);
4127    int is_sign = insn & 0x200;
4128    TCGv dest = DREG(ext, 12);
4129    TCGv addr, len, ofs;
4130
4131    addr = gen_lea(env, s, insn, OS_UNSIZED);
4132    if (IS_NULL_QREG(addr)) {
4133        gen_addr_fault(s);
4134        return;
4135    }
4136
4137    if (ext & 0x20) {
4138        len = DREG(ext, 0);
4139    } else {
4140        len = tcg_const_i32(extract32(ext, 0, 5));
4141    }
4142    if (ext & 0x800) {
4143        ofs = DREG(ext, 6);
4144    } else {
4145        ofs = tcg_const_i32(extract32(ext, 6, 5));
4146    }
4147
4148    if (is_sign) {
4149        gen_helper_bfexts_mem(dest, cpu_env, addr, ofs, len);
4150        tcg_gen_mov_i32(QREG_CC_N, dest);
4151    } else {
4152        TCGv_i64 tmp = tcg_temp_new_i64();
4153        gen_helper_bfextu_mem(tmp, cpu_env, addr, ofs, len);
4154        tcg_gen_extr_i64_i32(dest, QREG_CC_N, tmp);
4155        tcg_temp_free_i64(tmp);
4156    }
4157    set_cc_op(s, CC_OP_LOGIC);
4158
4159    if (!(ext & 0x20)) {
4160        tcg_temp_free(len);
4161    }
4162    if (!(ext & 0x800)) {
4163        tcg_temp_free(ofs);
4164    }
4165}
4166
4167DISAS_INSN(bfop_reg)
4168{
4169    int ext = read_im16(env, s);
4170    TCGv src = DREG(insn, 0);
4171    int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4172    int ofs = extract32(ext, 6, 5);  /* big bit-endian */
4173    TCGv mask, tofs, tlen;
4174
4175    tofs = NULL;
4176    tlen = NULL;
4177    if ((insn & 0x0f00) == 0x0d00) { /* bfffo */
4178        tofs = tcg_temp_new();
4179        tlen = tcg_temp_new();
4180    }
4181
4182    if ((ext & 0x820) == 0) {
4183        /* Immediate width and offset.  */
4184        uint32_t maski = 0x7fffffffu >> (len - 1);
4185        if (ofs + len <= 32) {
4186            tcg_gen_shli_i32(QREG_CC_N, src, ofs);
4187        } else {
4188            tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4189        }
4190        tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski);
4191        mask = tcg_const_i32(ror32(maski, ofs));
4192        if (tofs) {
4193            tcg_gen_movi_i32(tofs, ofs);
4194            tcg_gen_movi_i32(tlen, len);
4195        }
4196    } else {
4197        TCGv tmp = tcg_temp_new();
4198        if (ext & 0x20) {
4199            /* Variable width */
4200            tcg_gen_subi_i32(tmp, DREG(ext, 0), 1);
4201            tcg_gen_andi_i32(tmp, tmp, 31);
4202            mask = tcg_const_i32(0x7fffffffu);
4203            tcg_gen_shr_i32(mask, mask, tmp);
4204            if (tlen) {
4205                tcg_gen_addi_i32(tlen, tmp, 1);
4206            }
4207        } else {
4208            /* Immediate width */
4209            mask = tcg_const_i32(0x7fffffffu >> (len - 1));
4210            if (tlen) {
4211                tcg_gen_movi_i32(tlen, len);
4212            }
4213        }
4214        if (ext & 0x800) {
4215            /* Variable offset */
4216            tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
4217            tcg_gen_rotl_i32(QREG_CC_N, src, tmp);
4218            tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4219            tcg_gen_rotr_i32(mask, mask, tmp);
4220            if (tofs) {
4221                tcg_gen_mov_i32(tofs, tmp);
4222            }
4223        } else {
4224            /* Immediate offset (and variable width) */
4225            tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4226            tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4227            tcg_gen_rotri_i32(mask, mask, ofs);
4228            if (tofs) {
4229                tcg_gen_movi_i32(tofs, ofs);
4230            }
4231        }
4232        tcg_temp_free(tmp);
4233    }
4234    set_cc_op(s, CC_OP_LOGIC);
4235
4236    switch (insn & 0x0f00) {
4237    case 0x0a00: /* bfchg */
4238        tcg_gen_eqv_i32(src, src, mask);
4239        break;
4240    case 0x0c00: /* bfclr */
4241        tcg_gen_and_i32(src, src, mask);
4242        break;
4243    case 0x0d00: /* bfffo */
4244        gen_helper_bfffo_reg(DREG(ext, 12), QREG_CC_N, tofs, tlen);
4245        tcg_temp_free(tlen);
4246        tcg_temp_free(tofs);
4247        break;
4248    case 0x0e00: /* bfset */
4249        tcg_gen_orc_i32(src, src, mask);
4250        break;
4251    case 0x0800: /* bftst */
4252        /* flags already set; no other work to do.  */
4253        break;
4254    default:
4255        g_assert_not_reached();
4256    }
4257    tcg_temp_free(mask);
4258}
4259
4260DISAS_INSN(bfop_mem)
4261{
4262    int ext = read_im16(env, s);
4263    TCGv addr, len, ofs;
4264    TCGv_i64 t64;
4265
4266    addr = gen_lea(env, s, insn, OS_UNSIZED);
4267    if (IS_NULL_QREG(addr)) {
4268        gen_addr_fault(s);
4269        return;
4270    }
4271
4272    if (ext & 0x20) {
4273        len = DREG(ext, 0);
4274    } else {
4275        len = tcg_const_i32(extract32(ext, 0, 5));
4276    }
4277    if (ext & 0x800) {
4278        ofs = DREG(ext, 6);
4279    } else {
4280        ofs = tcg_const_i32(extract32(ext, 6, 5));
4281    }
4282
4283    switch (insn & 0x0f00) {
4284    case 0x0a00: /* bfchg */
4285        gen_helper_bfchg_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4286        break;
4287    case 0x0c00: /* bfclr */
4288        gen_helper_bfclr_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4289        break;
4290    case 0x0d00: /* bfffo */
4291        t64 = tcg_temp_new_i64();
4292        gen_helper_bfffo_mem(t64, cpu_env, addr, ofs, len);
4293        tcg_gen_extr_i64_i32(DREG(ext, 12), QREG_CC_N, t64);
4294        tcg_temp_free_i64(t64);
4295        break;
4296    case 0x0e00: /* bfset */
4297        gen_helper_bfset_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4298        break;
4299    case 0x0800: /* bftst */
4300        gen_helper_bfexts_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4301        break;
4302    default:
4303        g_assert_not_reached();
4304    }
4305    set_cc_op(s, CC_OP_LOGIC);
4306
4307    if (!(ext & 0x20)) {
4308        tcg_temp_free(len);
4309    }
4310    if (!(ext & 0x800)) {
4311        tcg_temp_free(ofs);
4312    }
4313}
4314
4315DISAS_INSN(bfins_reg)
4316{
4317    int ext = read_im16(env, s);
4318    TCGv dst = DREG(insn, 0);
4319    TCGv src = DREG(ext, 12);
4320    int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4321    int ofs = extract32(ext, 6, 5);  /* big bit-endian */
4322    int pos = 32 - ofs - len;        /* little bit-endian */
4323    TCGv tmp;
4324
4325    tmp = tcg_temp_new();
4326
4327    if (ext & 0x20) {
4328        /* Variable width */
4329        tcg_gen_neg_i32(tmp, DREG(ext, 0));
4330        tcg_gen_andi_i32(tmp, tmp, 31);
4331        tcg_gen_shl_i32(QREG_CC_N, src, tmp);
4332    } else {
4333        /* Immediate width */
4334        tcg_gen_shli_i32(QREG_CC_N, src, 32 - len);
4335    }
4336    set_cc_op(s, CC_OP_LOGIC);
4337
4338    /* Immediate width and offset */
4339    if ((ext & 0x820) == 0) {
4340        /* Check for suitability for deposit.  */
4341        if (pos >= 0) {
4342            tcg_gen_deposit_i32(dst, dst, src, pos, len);
4343        } else {
4344            uint32_t maski = -2U << (len - 1);
4345            uint32_t roti = (ofs + len) & 31;
4346            tcg_gen_andi_i32(tmp, src, ~maski);
4347            tcg_gen_rotri_i32(tmp, tmp, roti);
4348            tcg_gen_andi_i32(dst, dst, ror32(maski, roti));
4349            tcg_gen_or_i32(dst, dst, tmp);
4350        }
4351    } else {
4352        TCGv mask = tcg_temp_new();
4353        TCGv rot = tcg_temp_new();
4354
4355        if (ext & 0x20) {
4356            /* Variable width */
4357            tcg_gen_subi_i32(rot, DREG(ext, 0), 1);
4358            tcg_gen_andi_i32(rot, rot, 31);
4359            tcg_gen_movi_i32(mask, -2);
4360            tcg_gen_shl_i32(mask, mask, rot);
4361            tcg_gen_mov_i32(rot, DREG(ext, 0));
4362            tcg_gen_andc_i32(tmp, src, mask);
4363        } else {
4364            /* Immediate width (variable offset) */
4365            uint32_t maski = -2U << (len - 1);
4366            tcg_gen_andi_i32(tmp, src, ~maski);
4367            tcg_gen_movi_i32(mask, maski);
4368            tcg_gen_movi_i32(rot, len & 31);
4369        }
4370        if (ext & 0x800) {
4371            /* Variable offset */
4372            tcg_gen_add_i32(rot, rot, DREG(ext, 6));
4373        } else {
4374            /* Immediate offset (variable width) */
4375            tcg_gen_addi_i32(rot, rot, ofs);
4376        }
4377        tcg_gen_andi_i32(rot, rot, 31);
4378        tcg_gen_rotr_i32(mask, mask, rot);
4379        tcg_gen_rotr_i32(tmp, tmp, rot);
4380        tcg_gen_and_i32(dst, dst, mask);
4381        tcg_gen_or_i32(dst, dst, tmp);
4382
4383        tcg_temp_free(rot);
4384        tcg_temp_free(mask);
4385    }
4386    tcg_temp_free(tmp);
4387}
4388
4389DISAS_INSN(bfins_mem)
4390{
4391    int ext = read_im16(env, s);
4392    TCGv src = DREG(ext, 12);
4393    TCGv addr, len, ofs;
4394
4395    addr = gen_lea(env, s, insn, OS_UNSIZED);
4396    if (IS_NULL_QREG(addr)) {
4397        gen_addr_fault(s);
4398        return;
4399    }
4400
4401    if (ext & 0x20) {
4402        len = DREG(ext, 0);
4403    } else {
4404        len = tcg_const_i32(extract32(ext, 0, 5));
4405    }
4406    if (ext & 0x800) {
4407        ofs = DREG(ext, 6);
4408    } else {
4409        ofs = tcg_const_i32(extract32(ext, 6, 5));
4410    }
4411
4412    gen_helper_bfins_mem(QREG_CC_N, cpu_env, addr, src, ofs, len);
4413    set_cc_op(s, CC_OP_LOGIC);
4414
4415    if (!(ext & 0x20)) {
4416        tcg_temp_free(len);
4417    }
4418    if (!(ext & 0x800)) {
4419        tcg_temp_free(ofs);
4420    }
4421}
4422
4423DISAS_INSN(ff1)
4424{
4425    TCGv reg;
4426    reg = DREG(insn, 0);
4427    gen_logic_cc(s, reg, OS_LONG);
4428    gen_helper_ff1(reg, reg);
4429}
4430
4431DISAS_INSN(chk)
4432{
4433    TCGv src, reg;
4434    int opsize;
4435
4436    switch ((insn >> 7) & 3) {
4437    case 3:
4438        opsize = OS_WORD;
4439        break;
4440    case 2:
4441        if (m68k_feature(env, M68K_FEATURE_CHK2)) {
4442            opsize = OS_LONG;
4443            break;
4444        }
4445        /* fallthru */
4446    default:
4447        gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4448        return;
4449    }
4450    SRC_EA(env, src, opsize, 1, NULL);
4451    reg = gen_extend(s, DREG(insn, 9), opsize, 1);
4452
4453    gen_flush_flags(s);
4454    gen_helper_chk(cpu_env, reg, src);
4455}
4456
4457DISAS_INSN(chk2)
4458{
4459    uint16_t ext;
4460    TCGv addr1, addr2, bound1, bound2, reg;
4461    int opsize;
4462
4463    switch ((insn >> 9) & 3) {
4464    case 0:
4465        opsize = OS_BYTE;
4466        break;
4467    case 1:
4468        opsize = OS_WORD;
4469        break;
4470    case 2:
4471        opsize = OS_LONG;
4472        break;
4473    default:
4474        gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4475        return;
4476    }
4477
4478    ext = read_im16(env, s);
4479    if ((ext & 0x0800) == 0) {
4480        gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4481        return;
4482    }
4483
4484    addr1 = gen_lea(env, s, insn, OS_UNSIZED);
4485    addr2 = tcg_temp_new();
4486    tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
4487
4488    bound1 = gen_load(s, opsize, addr1, 1, IS_USER(s));
4489    tcg_temp_free(addr1);
4490    bound2 = gen_load(s, opsize, addr2, 1, IS_USER(s));
4491    tcg_temp_free(addr2);
4492
4493    reg = tcg_temp_new();
4494    if (ext & 0x8000) {
4495        tcg_gen_mov_i32(reg, AREG(ext, 12));
4496    } else {
4497        gen_ext(reg, DREG(ext, 12), opsize, 1);
4498    }
4499
4500    gen_flush_flags(s);
4501    gen_helper_chk2(cpu_env, reg, bound1, bound2);
4502    tcg_temp_free(reg);
4503    tcg_temp_free(bound1);
4504    tcg_temp_free(bound2);
4505}
4506
4507static void m68k_copy_line(TCGv dst, TCGv src, int index)
4508{
4509    TCGv addr;
4510    TCGv_i64 t0, t1;
4511
4512    addr = tcg_temp_new();
4513
4514    t0 = tcg_temp_new_i64();
4515    t1 = tcg_temp_new_i64();
4516
4517    tcg_gen_andi_i32(addr, src, ~15);
4518    tcg_gen_qemu_ld64(t0, addr, index);
4519    tcg_gen_addi_i32(addr, addr, 8);
4520    tcg_gen_qemu_ld64(t1, addr, index);
4521
4522    tcg_gen_andi_i32(addr, dst, ~15);
4523    tcg_gen_qemu_st64(t0, addr, index);
4524    tcg_gen_addi_i32(addr, addr, 8);
4525    tcg_gen_qemu_st64(t1, addr, index);
4526
4527    tcg_temp_free_i64(t0);
4528    tcg_temp_free_i64(t1);
4529    tcg_temp_free(addr);
4530}
4531
4532DISAS_INSN(move16_reg)
4533{
4534    int index = IS_USER(s);
4535    TCGv tmp;
4536    uint16_t ext;
4537
4538    ext = read_im16(env, s);
4539    if ((ext & (1 << 15)) == 0) {
4540        gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4541    }
4542
4543    m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);
4544
4545    /* Ax can be Ay, so save Ay before incrementing Ax */
4546    tmp = tcg_temp_new();
4547    tcg_gen_mov_i32(tmp, AREG(ext, 12));
4548    tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
4549    tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
4550    tcg_temp_free(tmp);
4551}
4552
4553DISAS_INSN(move16_mem)
4554{
4555    int index = IS_USER(s);
4556    TCGv reg, addr;
4557
4558    reg = AREG(insn, 0);
4559    addr = tcg_const_i32(read_im32(env, s));
4560
4561    if ((insn >> 3) & 1) {
4562        /* MOVE16 (xxx).L, (Ay) */
4563        m68k_copy_line(reg, addr, index);
4564    } else {
4565        /* MOVE16 (Ay), (xxx).L */
4566        m68k_copy_line(addr, reg, index);
4567    }
4568
4569    tcg_temp_free(addr);
4570
4571    if (((insn >> 3) & 2) == 0) {
4572        /* (Ay)+ */
4573        tcg_gen_addi_i32(reg, reg, 16);
4574    }
4575}
4576
4577DISAS_INSN(strldsr)
4578{
4579    uint16_t ext;
4580    uint32_t addr;
4581
4582    addr = s->pc - 2;
4583    ext = read_im16(env, s);
4584    if (ext != 0x46FC) {
4585        gen_exception(s, addr, EXCP_ILLEGAL);
4586        return;
4587    }
4588    ext = read_im16(env, s);
4589    if (IS_USER(s) || (ext & SR_S) == 0) {
4590        gen_exception(s, addr, EXCP_PRIVILEGE);
4591        return;
4592    }
4593    gen_push(s, gen_get_sr(s));
4594    gen_set_sr_im(s, ext, 0);
4595}
4596
4597DISAS_INSN(move_from_sr)
4598{
4599    TCGv sr;
4600
4601    if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) {
4602        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4603        return;
4604    }
4605    sr = gen_get_sr(s);
4606    DEST_EA(env, insn, OS_WORD, sr, NULL);
4607}
4608
4609#if defined(CONFIG_SOFTMMU)
4610DISAS_INSN(moves)
4611{
4612    int opsize;
4613    uint16_t ext;
4614    TCGv reg;
4615    TCGv addr;
4616    int extend;
4617
4618    if (IS_USER(s)) {
4619        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4620        return;
4621    }
4622
4623    ext = read_im16(env, s);
4624
4625    opsize = insn_opsize(insn);
4626
4627    if (ext & 0x8000) {
4628        /* address register */
4629        reg = AREG(ext, 12);
4630        extend = 1;
4631    } else {
4632        /* data register */
4633        reg = DREG(ext, 12);
4634        extend = 0;
4635    }
4636
4637    addr = gen_lea(env, s, insn, opsize);
4638    if (IS_NULL_QREG(addr)) {
4639        gen_addr_fault(s);
4640        return;
4641    }
4642
4643    if (ext & 0x0800) {
4644        /* from reg to ea */
4645        gen_store(s, opsize, addr, reg, DFC_INDEX(s));
4646    } else {
4647        /* from ea to reg */
4648        TCGv tmp = gen_load(s, opsize, addr, 0, SFC_INDEX(s));
4649        if (extend) {
4650            gen_ext(reg, tmp, opsize, 1);
4651        } else {
4652            gen_partset_reg(opsize, reg, tmp);
4653        }
4654        tcg_temp_free(tmp);
4655    }
4656    switch (extract32(insn, 3, 3)) {
4657    case 3: /* Indirect postincrement.  */
4658        tcg_gen_addi_i32(AREG(insn, 0), addr,
4659                         REG(insn, 0) == 7 && opsize == OS_BYTE
4660                         ? 2
4661                         : opsize_bytes(opsize));
4662        break;
4663    case 4: /* Indirect predecrememnt.  */
4664        tcg_gen_mov_i32(AREG(insn, 0), addr);
4665        break;
4666    }
4667}
4668
4669DISAS_INSN(move_to_sr)
4670{
4671    if (IS_USER(s)) {
4672        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4673        return;
4674    }
4675    gen_move_to_sr(env, s, insn, false);
4676    gen_exit_tb(s);
4677}
4678
4679DISAS_INSN(move_from_usp)
4680{
4681    if (IS_USER(s)) {
4682        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4683        return;
4684    }
4685    tcg_gen_ld_i32(AREG(insn, 0), cpu_env,
4686                   offsetof(CPUM68KState, sp[M68K_USP]));
4687}
4688
4689DISAS_INSN(move_to_usp)
4690{
4691    if (IS_USER(s)) {
4692        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4693        return;
4694    }
4695    tcg_gen_st_i32(AREG(insn, 0), cpu_env,
4696                   offsetof(CPUM68KState, sp[M68K_USP]));
4697}
4698
4699DISAS_INSN(halt)
4700{
4701    if (IS_USER(s)) {
4702        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4703        return;
4704    }
4705
4706    gen_exception(s, s->pc, EXCP_HALT_INSN);
4707}
4708
4709DISAS_INSN(stop)
4710{
4711    uint16_t ext;
4712
4713    if (IS_USER(s)) {
4714        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4715        return;
4716    }
4717
4718    ext = read_im16(env, s);
4719
4720    gen_set_sr_im(s, ext, 0);
4721    tcg_gen_movi_i32(cpu_halted, 1);
4722    gen_exception(s, s->pc, EXCP_HLT);
4723}
4724
4725DISAS_INSN(rte)
4726{
4727    if (IS_USER(s)) {
4728        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4729        return;
4730    }
4731    gen_exception(s, s->base.pc_next, EXCP_RTE);
4732}
4733
4734DISAS_INSN(cf_movec)
4735{
4736    uint16_t ext;
4737    TCGv reg;
4738
4739    if (IS_USER(s)) {
4740        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4741        return;
4742    }
4743
4744    ext = read_im16(env, s);
4745
4746    if (ext & 0x8000) {
4747        reg = AREG(ext, 12);
4748    } else {
4749        reg = DREG(ext, 12);
4750    }
4751    gen_helper_cf_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
4752    gen_exit_tb(s);
4753}
4754
4755DISAS_INSN(m68k_movec)
4756{
4757    uint16_t ext;
4758    TCGv reg;
4759
4760    if (IS_USER(s)) {
4761        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4762        return;
4763    }
4764
4765    ext = read_im16(env, s);
4766
4767    if (ext & 0x8000) {
4768        reg = AREG(ext, 12);
4769    } else {
4770        reg = DREG(ext, 12);
4771    }
4772    if (insn & 1) {
4773        gen_helper_m68k_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
4774    } else {
4775        gen_helper_m68k_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff));
4776    }
4777    gen_exit_tb(s);
4778}
4779
4780DISAS_INSN(intouch)
4781{
4782    if (IS_USER(s)) {
4783        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4784        return;
4785    }
4786    /* ICache fetch.  Implement as no-op.  */
4787}
4788
4789DISAS_INSN(cpushl)
4790{
4791    if (IS_USER(s)) {
4792        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4793        return;
4794    }
4795    /* Cache push/invalidate.  Implement as no-op.  */
4796}
4797
4798DISAS_INSN(cpush)
4799{
4800    if (IS_USER(s)) {
4801        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4802        return;
4803    }
4804    /* Cache push/invalidate.  Implement as no-op.  */
4805}
4806
4807DISAS_INSN(cinv)
4808{
4809    if (IS_USER(s)) {
4810        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4811        return;
4812    }
4813    /* Invalidate cache line.  Implement as no-op.  */
4814}
4815
4816#if defined(CONFIG_SOFTMMU)
4817DISAS_INSN(pflush)
4818{
4819    TCGv opmode;
4820
4821    if (IS_USER(s)) {
4822        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4823        return;
4824    }
4825
4826    opmode = tcg_const_i32((insn >> 3) & 3);
4827    gen_helper_pflush(cpu_env, AREG(insn, 0), opmode);
4828    tcg_temp_free(opmode);
4829}
4830
4831DISAS_INSN(ptest)
4832{
4833    TCGv is_read;
4834
4835    if (IS_USER(s)) {
4836        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4837        return;
4838    }
4839    is_read = tcg_const_i32((insn >> 5) & 1);
4840    gen_helper_ptest(cpu_env, AREG(insn, 0), is_read);
4841    tcg_temp_free(is_read);
4842}
4843#endif
4844
4845DISAS_INSN(wddata)
4846{
4847    gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4848}
4849
4850DISAS_INSN(wdebug)
4851{
4852    if (IS_USER(s)) {
4853        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4854        return;
4855    }
4856    /* TODO: Implement wdebug.  */
4857    cpu_abort(env_cpu(env), "WDEBUG not implemented");
4858}
4859#endif
4860
4861DISAS_INSN(trap)
4862{
4863    gen_exception(s, s->base.pc_next, EXCP_TRAP0 + (insn & 0xf));
4864}
4865
4866static void gen_load_fcr(DisasContext *s, TCGv res, int reg)
4867{
4868    switch (reg) {
4869    case M68K_FPIAR:
4870        tcg_gen_movi_i32(res, 0);
4871        break;
4872    case M68K_FPSR:
4873        tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpsr));
4874        break;
4875    case M68K_FPCR:
4876        tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpcr));
4877        break;
4878    }
4879}
4880
4881static void gen_store_fcr(DisasContext *s, TCGv val, int reg)
4882{
4883    switch (reg) {
4884    case M68K_FPIAR:
4885        break;
4886    case M68K_FPSR:
4887        tcg_gen_st_i32(val, cpu_env, offsetof(CPUM68KState, fpsr));
4888        break;
4889    case M68K_FPCR:
4890        gen_helper_set_fpcr(cpu_env, val);
4891        break;
4892    }
4893}
4894
4895static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg)
4896{
4897    int index = IS_USER(s);
4898    TCGv tmp;
4899
4900    tmp = tcg_temp_new();
4901    gen_load_fcr(s, tmp, reg);
4902    tcg_gen_qemu_st32(tmp, addr, index);
4903    tcg_temp_free(tmp);
4904}
4905
4906static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg)
4907{
4908    int index = IS_USER(s);
4909    TCGv tmp;
4910
4911    tmp = tcg_temp_new();
4912    tcg_gen_qemu_ld32u(tmp, addr, index);
4913    gen_store_fcr(s, tmp, reg);
4914    tcg_temp_free(tmp);
4915}
4916
4917
4918static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
4919                             uint32_t insn, uint32_t ext)
4920{
4921    int mask = (ext >> 10) & 7;
4922    int is_write = (ext >> 13) & 1;
4923    int mode = extract32(insn, 3, 3);
4924    int i;
4925    TCGv addr, tmp;
4926
4927    switch (mode) {
4928    case 0: /* Dn */
4929        if (mask != M68K_FPIAR && mask != M68K_FPSR && mask != M68K_FPCR) {
4930            gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4931            return;
4932        }
4933        if (is_write) {
4934            gen_load_fcr(s, DREG(insn, 0), mask);
4935        } else {
4936            gen_store_fcr(s, DREG(insn, 0), mask);
4937        }
4938        return;
4939    case 1: /* An, only with FPIAR */
4940        if (mask != M68K_FPIAR) {
4941            gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4942            return;
4943        }
4944        if (is_write) {
4945            gen_load_fcr(s, AREG(insn, 0), mask);
4946        } else {
4947            gen_store_fcr(s, AREG(insn, 0), mask);
4948        }
4949        return;
4950    case 7: /* Immediate */
4951        if (REG(insn, 0) == 4) {
4952            if (is_write ||
4953                (mask != M68K_FPIAR && mask != M68K_FPSR &&
4954                 mask != M68K_FPCR)) {
4955                gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4956                return;
4957            }
4958            tmp = tcg_const_i32(read_im32(env, s));
4959            gen_store_fcr(s, tmp, mask);
4960            tcg_temp_free(tmp);
4961            return;
4962        }
4963        break;
4964    default:
4965        break;
4966    }
4967
4968    tmp = gen_lea(env, s, insn, OS_LONG);
4969    if (IS_NULL_QREG(tmp)) {
4970        gen_addr_fault(s);
4971        return;
4972    }
4973
4974    addr = tcg_temp_new();
4975    tcg_gen_mov_i32(addr, tmp);
4976
4977    /*
4978     * mask:
4979     *
4980     * 0b100 Floating-Point Control Register
4981     * 0b010 Floating-Point Status Register
4982     * 0b001 Floating-Point Instruction Address Register
4983     *
4984     */
4985
4986    if (is_write && mode == 4) {
4987        for (i = 2; i >= 0; i--, mask >>= 1) {
4988            if (mask & 1) {
4989                gen_qemu_store_fcr(s, addr, 1 << i);
4990                if (mask != 1) {
4991                    tcg_gen_subi_i32(addr, addr, opsize_bytes(OS_LONG));
4992                }
4993            }
4994       }
4995       tcg_gen_mov_i32(AREG(insn, 0), addr);
4996    } else {
4997        for (i = 0; i < 3; i++, mask >>= 1) {
4998            if (mask & 1) {
4999                if (is_write) {
5000                    gen_qemu_store_fcr(s, addr, 1 << i);
5001                } else {
5002                    gen_qemu_load_fcr(s, addr, 1 << i);
5003                }
5004                if (mask != 1 || mode == 3) {
5005                    tcg_gen_addi_i32(addr, addr, opsize_bytes(OS_LONG));
5006                }
5007            }
5008        }
5009        if (mode == 3) {
5010            tcg_gen_mov_i32(AREG(insn, 0), addr);
5011        }
5012    }
5013    tcg_temp_free_i32(addr);
5014}
5015
5016static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
5017                          uint32_t insn, uint32_t ext)
5018{
5019    int opsize;
5020    TCGv addr, tmp;
5021    int mode = (ext >> 11) & 0x3;
5022    int is_load = ((ext & 0x2000) == 0);
5023
5024    if (m68k_feature(s->env, M68K_FEATURE_FPU)) {
5025        opsize = OS_EXTENDED;
5026    } else {
5027        opsize = OS_DOUBLE;  /* FIXME */
5028    }
5029
5030    addr = gen_lea(env, s, insn, opsize);
5031    if (IS_NULL_QREG(addr)) {
5032        gen_addr_fault(s);
5033        return;
5034    }
5035
5036    tmp = tcg_temp_new();
5037    if (mode & 0x1) {
5038        /* Dynamic register list */
5039        tcg_gen_ext8u_i32(tmp, DREG(ext, 4));
5040    } else {
5041        /* Static register list */
5042        tcg_gen_movi_i32(tmp, ext & 0xff);
5043    }
5044
5045    if (!is_load && (mode & 2) == 0) {
5046        /*
5047         * predecrement addressing mode
5048         * only available to store register to memory
5049         */
5050        if (opsize == OS_EXTENDED) {
5051            gen_helper_fmovemx_st_predec(tmp, cpu_env, addr, tmp);
5052        } else {
5053            gen_helper_fmovemd_st_predec(tmp, cpu_env, addr, tmp);
5054        }
5055    } else {
5056        /* postincrement addressing mode */
5057        if (opsize == OS_EXTENDED) {
5058            if (is_load) {
5059                gen_helper_fmovemx_ld_postinc(tmp, cpu_env, addr, tmp);
5060            } else {
5061                gen_helper_fmovemx_st_postinc(tmp, cpu_env, addr, tmp);
5062            }
5063        } else {
5064            if (is_load) {
5065                gen_helper_fmovemd_ld_postinc(tmp, cpu_env, addr, tmp);
5066            } else {
5067                gen_helper_fmovemd_st_postinc(tmp, cpu_env, addr, tmp);
5068            }
5069        }
5070    }
5071    if ((insn & 070) == 030 || (insn & 070) == 040) {
5072        tcg_gen_mov_i32(AREG(insn, 0), tmp);
5073    }
5074    tcg_temp_free(tmp);
5075}
5076
5077/*
5078 * ??? FP exceptions are not implemented.  Most exceptions are deferred until
5079 * immediately before the next FP instruction is executed.
5080 */
5081DISAS_INSN(fpu)
5082{
5083    uint16_t ext;
5084    int opmode;
5085    int opsize;
5086    TCGv_ptr cpu_src, cpu_dest;
5087
5088    ext = read_im16(env, s);
5089    opmode = ext & 0x7f;
5090    switch ((ext >> 13) & 7) {
5091    case 0:
5092        break;
5093    case 1:
5094        goto undef;
5095    case 2:
5096        if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
5097            /* fmovecr */
5098            TCGv rom_offset = tcg_const_i32(opmode);
5099            cpu_dest = gen_fp_ptr(REG(ext, 7));
5100            gen_helper_fconst(cpu_env, cpu_dest, rom_offset);
5101            tcg_temp_free_ptr(cpu_dest);
5102            tcg_temp_free(rom_offset);
5103            return;
5104        }
5105        break;
5106    case 3: /* fmove out */
5107        cpu_src = gen_fp_ptr(REG(ext, 7));
5108        opsize = ext_opsize(ext, 10);
5109        if (gen_ea_fp(env, s, insn, opsize, cpu_src,
5110                      EA_STORE, IS_USER(s)) == -1) {
5111            gen_addr_fault(s);
5112        }
5113        gen_helper_ftst(cpu_env, cpu_src);
5114        tcg_temp_free_ptr(cpu_src);
5115        return;
5116    case 4: /* fmove to control register.  */
5117    case 5: /* fmove from control register.  */
5118        gen_op_fmove_fcr(env, s, insn, ext);
5119        return;
5120    case 6: /* fmovem */
5121    case 7:
5122        if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) {
5123            goto undef;
5124        }
5125        gen_op_fmovem(env, s, insn, ext);
5126        return;
5127    }
5128    if (ext & (1 << 14)) {
5129        /* Source effective address.  */
5130        opsize = ext_opsize(ext, 10);
5131        cpu_src = gen_fp_result_ptr();
5132        if (gen_ea_fp(env, s, insn, opsize, cpu_src,
5133                      EA_LOADS, IS_USER(s)) == -1) {
5134            gen_addr_fault(s);
5135            return;
5136        }
5137    } else {
5138        /* Source register.  */
5139        opsize = OS_EXTENDED;
5140        cpu_src = gen_fp_ptr(REG(ext, 10));
5141    }
5142    cpu_dest = gen_fp_ptr(REG(ext, 7));
5143    switch (opmode) {
5144    case 0: /* fmove */
5145        gen_fp_move(cpu_dest, cpu_src);
5146        break;
5147    case 0x40: /* fsmove */
5148        gen_helper_fsround(cpu_env, cpu_dest, cpu_src);
5149        break;
5150    case 0x44: /* fdmove */
5151        gen_helper_fdround(cpu_env, cpu_dest, cpu_src);
5152        break;
5153    case 1: /* fint */
5154        gen_helper_firound(cpu_env, cpu_dest, cpu_src);
5155        break;
5156    case 2: /* fsinh */
5157        gen_helper_fsinh(cpu_env, cpu_dest, cpu_src);
5158        break;
5159    case 3: /* fintrz */
5160        gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src);
5161        break;
5162    case 4: /* fsqrt */
5163        gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src);
5164        break;
5165    case 0x41: /* fssqrt */
5166        gen_helper_fssqrt(cpu_env, cpu_dest, cpu_src);
5167        break;
5168    case 0x45: /* fdsqrt */
5169        gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
5170        break;
5171    case 0x06: /* flognp1 */
5172        gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
5173        break;
5174    case 0x08: /* fetoxm1 */
5175        gen_helper_fetoxm1(cpu_env, cpu_dest, cpu_src);
5176        break;
5177    case 0x09: /* ftanh */
5178        gen_helper_ftanh(cpu_env, cpu_dest, cpu_src);
5179        break;
5180    case 0x0a: /* fatan */
5181        gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
5182        break;
5183    case 0x0c: /* fasin */
5184        gen_helper_fasin(cpu_env, cpu_dest, cpu_src);
5185        break;
5186    case 0x0d: /* fatanh */
5187        gen_helper_fatanh(cpu_env, cpu_dest, cpu_src);
5188        break;
5189    case 0x0e: /* fsin */
5190        gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
5191        break;
5192    case 0x0f: /* ftan */
5193        gen_helper_ftan(cpu_env, cpu_dest, cpu_src);
5194        break;
5195    case 0x10: /* fetox */
5196        gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
5197        break;
5198    case 0x11: /* ftwotox */
5199        gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src);
5200        break;
5201    case 0x12: /* ftentox */
5202        gen_helper_ftentox(cpu_env, cpu_dest, cpu_src);
5203        break;
5204    case 0x14: /* flogn */
5205        gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
5206        break;
5207    case 0x15: /* flog10 */
5208        gen_helper_flog10(cpu_env, cpu_dest, cpu_src);
5209        break;
5210    case 0x16: /* flog2 */
5211        gen_helper_flog2(cpu_env, cpu_dest, cpu_src);
5212        break;
5213    case 0x18: /* fabs */
5214        gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
5215        break;
5216    case 0x58: /* fsabs */
5217        gen_helper_fsabs(cpu_env, cpu_dest, cpu_src);
5218        break;
5219    case 0x5c: /* fdabs */
5220        gen_helper_fdabs(cpu_env, cpu_dest, cpu_src);
5221        break;
5222    case 0x19: /* fcosh */
5223        gen_helper_fcosh(cpu_env, cpu_dest, cpu_src);
5224        break;
5225    case 0x1a: /* fneg */
5226        gen_helper_fneg(cpu_env, cpu_dest, cpu_src);
5227        break;
5228    case 0x5a: /* fsneg */
5229        gen_helper_fsneg(cpu_env, cpu_dest, cpu_src);
5230        break;
5231    case 0x5e: /* fdneg */
5232        gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
5233        break;
5234    case 0x1c: /* facos */
5235        gen_helper_facos(cpu_env, cpu_dest, cpu_src);
5236        break;
5237    case 0x1d: /* fcos */
5238        gen_helper_fcos(cpu_env, cpu_dest, cpu_src);
5239        break;
5240    case 0x1e: /* fgetexp */
5241        gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src);
5242        break;
5243    case 0x1f: /* fgetman */
5244        gen_helper_fgetman(cpu_env, cpu_dest, cpu_src);
5245        break;
5246    case 0x20: /* fdiv */
5247        gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5248        break;
5249    case 0x60: /* fsdiv */
5250        gen_helper_fsdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5251        break;
5252    case 0x64: /* fddiv */
5253        gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5254        break;
5255    case 0x21: /* fmod */
5256        gen_helper_fmod(cpu_env, cpu_dest, cpu_src, cpu_dest);
5257        break;
5258    case 0x22: /* fadd */
5259        gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5260        break;
5261    case 0x62: /* fsadd */
5262        gen_helper_fsadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5263        break;
5264    case 0x66: /* fdadd */
5265        gen_helper_fdadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5266        break;
5267    case 0x23: /* fmul */
5268        gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5269        break;
5270    case 0x63: /* fsmul */
5271        gen_helper_fsmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5272        break;
5273    case 0x67: /* fdmul */
5274        gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5275        break;
5276    case 0x24: /* fsgldiv */
5277        gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5278        break;
5279    case 0x25: /* frem */
5280        gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest);
5281        break;
5282    case 0x26: /* fscale */
5283        gen_helper_fscale(cpu_env, cpu_dest, cpu_src, cpu_dest);
5284        break;
5285    case 0x27: /* fsglmul */
5286        gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5287        break;
5288    case 0x28: /* fsub */
5289        gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5290        break;
5291    case 0x68: /* fssub */
5292        gen_helper_fssub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5293        break;
5294    case 0x6c: /* fdsub */
5295        gen_helper_fdsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5296        break;
5297    case 0x30: case 0x31: case 0x32:
5298    case 0x33: case 0x34: case 0x35:
5299    case 0x36: case 0x37: {
5300            TCGv_ptr cpu_dest2 = gen_fp_ptr(REG(ext, 0));
5301            gen_helper_fsincos(cpu_env, cpu_dest, cpu_dest2, cpu_src);
5302            tcg_temp_free_ptr(cpu_dest2);
5303        }
5304        break;
5305    case 0x38: /* fcmp */
5306        gen_helper_fcmp(cpu_env, cpu_src, cpu_dest);
5307        return;
5308    case 0x3a: /* ftst */
5309        gen_helper_ftst(cpu_env, cpu_src);
5310        return;
5311    default:
5312        goto undef;
5313    }
5314    tcg_temp_free_ptr(cpu_src);
5315    gen_helper_ftst(cpu_env, cpu_dest);
5316    tcg_temp_free_ptr(cpu_dest);
5317    return;
5318undef:
5319    /* FIXME: Is this right for offset addressing modes?  */
5320    s->pc -= 2;
5321    disas_undef_fpu(env, s, insn);
5322}
5323
5324static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond)
5325{
5326    TCGv fpsr;
5327
5328    c->g1 = 1;
5329    c->v2 = tcg_const_i32(0);
5330    c->g2 = 0;
5331    /* TODO: Raise BSUN exception.  */
5332    fpsr = tcg_temp_new();
5333    gen_load_fcr(s, fpsr, M68K_FPSR);
5334    switch (cond) {
5335    case 0:  /* False */
5336    case 16: /* Signaling False */
5337        c->v1 = c->v2;
5338        c->tcond = TCG_COND_NEVER;
5339        break;
5340    case 1:  /* EQual Z */
5341    case 17: /* Signaling EQual Z */
5342        c->v1 = tcg_temp_new();
5343        c->g1 = 0;
5344        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5345        c->tcond = TCG_COND_NE;
5346        break;
5347    case 2:  /* Ordered Greater Than !(A || Z || N) */
5348    case 18: /* Greater Than !(A || Z || N) */
5349        c->v1 = tcg_temp_new();
5350        c->g1 = 0;
5351        tcg_gen_andi_i32(c->v1, fpsr,
5352                         FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5353        c->tcond = TCG_COND_EQ;
5354        break;
5355    case 3:  /* Ordered Greater than or Equal Z || !(A || N) */
5356    case 19: /* Greater than or Equal Z || !(A || N) */
5357        c->v1 = tcg_temp_new();
5358        c->g1 = 0;
5359        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5360        tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A));
5361        tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_Z | FPSR_CC_N);
5362        tcg_gen_or_i32(c->v1, c->v1, fpsr);
5363        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5364        c->tcond = TCG_COND_NE;
5365        break;
5366    case 4:  /* Ordered Less Than !(!N || A || Z); */
5367    case 20: /* Less Than !(!N || A || Z); */
5368        c->v1 = tcg_temp_new();
5369        c->g1 = 0;
5370        tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N);
5371        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z);
5372        c->tcond = TCG_COND_EQ;
5373        break;
5374    case 5:  /* Ordered Less than or Equal Z || (N && !A) */
5375    case 21: /* Less than or Equal Z || (N && !A) */
5376        c->v1 = tcg_temp_new();
5377        c->g1 = 0;
5378        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5379        tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A));
5380        tcg_gen_andc_i32(c->v1, fpsr, c->v1);
5381        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_Z | FPSR_CC_N);
5382        c->tcond = TCG_COND_NE;
5383        break;
5384    case 6:  /* Ordered Greater or Less than !(A || Z) */
5385    case 22: /* Greater or Less than !(A || Z) */
5386        c->v1 = tcg_temp_new();
5387        c->g1 = 0;
5388        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
5389        c->tcond = TCG_COND_EQ;
5390        break;
5391    case 7:  /* Ordered !A */
5392    case 23: /* Greater, Less or Equal !A */
5393        c->v1 = tcg_temp_new();
5394        c->g1 = 0;
5395        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5396        c->tcond = TCG_COND_EQ;
5397        break;
5398    case 8:  /* Unordered A */
5399    case 24: /* Not Greater, Less or Equal A */
5400        c->v1 = tcg_temp_new();
5401        c->g1 = 0;
5402        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5403        c->tcond = TCG_COND_NE;
5404        break;
5405    case 9:  /* Unordered or Equal A || Z */
5406    case 25: /* Not Greater or Less then A || Z */
5407        c->v1 = tcg_temp_new();
5408        c->g1 = 0;
5409        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
5410        c->tcond = TCG_COND_NE;
5411        break;
5412    case 10: /* Unordered or Greater Than A || !(N || Z)) */
5413    case 26: /* Not Less or Equal A || !(N || Z)) */
5414        c->v1 = tcg_temp_new();
5415        c->g1 = 0;
5416        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5417        tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z));
5418        tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_A | FPSR_CC_N);
5419        tcg_gen_or_i32(c->v1, c->v1, fpsr);
5420        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5421        c->tcond = TCG_COND_NE;
5422        break;
5423    case 11: /* Unordered or Greater or Equal A || Z || !N */
5424    case 27: /* Not Less Than A || Z || !N */
5425        c->v1 = tcg_temp_new();
5426        c->g1 = 0;
5427        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5428        tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5429        c->tcond = TCG_COND_NE;
5430        break;
5431    case 12: /* Unordered or Less Than A || (N && !Z) */
5432    case 28: /* Not Greater than or Equal A || (N && !Z) */
5433        c->v1 = tcg_temp_new();
5434        c->g1 = 0;
5435        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5436        tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z));
5437        tcg_gen_andc_i32(c->v1, fpsr, c->v1);
5438        tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N);
5439        c->tcond = TCG_COND_NE;
5440        break;
5441    case 13: /* Unordered or Less or Equal A || Z || N */
5442    case 29: /* Not Greater Than A || Z || N */
5443        c->v1 = tcg_temp_new();
5444        c->g1 = 0;
5445        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5446        c->tcond = TCG_COND_NE;
5447        break;
5448    case 14: /* Not Equal !Z */
5449    case 30: /* Signaling Not Equal !Z */
5450        c->v1 = tcg_temp_new();
5451        c->g1 = 0;
5452        tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5453        c->tcond = TCG_COND_EQ;
5454        break;
5455    case 15: /* True */
5456    case 31: /* Signaling True */
5457        c->v1 = c->v2;
5458        c->tcond = TCG_COND_ALWAYS;
5459        break;
5460    }
5461    tcg_temp_free(fpsr);
5462}
5463
5464static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1)
5465{
5466    DisasCompare c;
5467
5468    gen_fcc_cond(&c, s, cond);
5469    update_cc_op(s);
5470    tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
5471    free_cond(&c);
5472}
5473
5474DISAS_INSN(fbcc)
5475{
5476    uint32_t offset;
5477    uint32_t base;
5478    TCGLabel *l1;
5479
5480    base = s->pc;
5481    offset = (int16_t)read_im16(env, s);
5482    if (insn & (1 << 6)) {
5483        offset = (offset << 16) | read_im16(env, s);
5484    }
5485
5486    l1 = gen_new_label();
5487    update_cc_op(s);
5488    gen_fjmpcc(s, insn & 0x3f, l1);
5489    gen_jmp_tb(s, 0, s->pc);
5490    gen_set_label(l1);
5491    gen_jmp_tb(s, 1, base + offset);
5492}
5493
5494DISAS_INSN(fscc)
5495{
5496    DisasCompare c;
5497    int cond;
5498    TCGv tmp;
5499    uint16_t ext;
5500
5501    ext = read_im16(env, s);
5502    cond = ext & 0x3f;
5503    gen_fcc_cond(&c, s, cond);
5504
5505    tmp = tcg_temp_new();
5506    tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
5507    free_cond(&c);
5508
5509    tcg_gen_neg_i32(tmp, tmp);
5510    DEST_EA(env, insn, OS_BYTE, tmp, NULL);
5511    tcg_temp_free(tmp);
5512}
5513
5514#if defined(CONFIG_SOFTMMU)
5515DISAS_INSN(frestore)
5516{
5517    TCGv addr;
5518
5519    if (IS_USER(s)) {
5520        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
5521        return;
5522    }
5523    if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
5524        SRC_EA(env, addr, OS_LONG, 0, NULL);
5525        /* FIXME: check the state frame */
5526    } else {
5527        disas_undef(env, s, insn);
5528    }
5529}
5530
5531DISAS_INSN(fsave)
5532{
5533    if (IS_USER(s)) {
5534        gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
5535        return;
5536    }
5537
5538    if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
5539        /* always write IDLE */
5540        TCGv idle = tcg_const_i32(0x41000000);
5541        DEST_EA(env, insn, OS_LONG, idle, NULL);
5542        tcg_temp_free(idle);
5543    } else {
5544        disas_undef(env, s, insn);
5545    }
5546}
5547#endif
5548
5549static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
5550{
5551    TCGv tmp = tcg_temp_new();
5552    if (s->env->macsr & MACSR_FI) {
5553        if (upper)
5554            tcg_gen_andi_i32(tmp, val, 0xffff0000);
5555        else
5556            tcg_gen_shli_i32(tmp, val, 16);
5557    } else if (s->env->macsr & MACSR_SU) {
5558        if (upper)
5559            tcg_gen_sari_i32(tmp, val, 16);
5560        else
5561            tcg_gen_ext16s_i32(tmp, val);
5562    } else {
5563        if (upper)
5564            tcg_gen_shri_i32(tmp, val, 16);
5565        else
5566            tcg_gen_ext16u_i32(tmp, val);
5567    }
5568    return tmp;
5569}
5570
5571static void gen_mac_clear_flags(void)
5572{
5573    tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR,
5574                     ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV));
5575}
5576
5577DISAS_INSN(mac)
5578{
5579    TCGv rx;
5580    TCGv ry;
5581    uint16_t ext;
5582    int acc;
5583    TCGv tmp;
5584    TCGv addr;
5585    TCGv loadval;
5586    int dual;
5587    TCGv saved_flags;
5588
5589    if (!s->done_mac) {
5590        s->mactmp = tcg_temp_new_i64();
5591        s->done_mac = 1;
5592    }
5593
5594    ext = read_im16(env, s);
5595
5596    acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
5597    dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
5598    if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
5599        disas_undef(env, s, insn);
5600        return;
5601    }
5602    if (insn & 0x30) {
5603        /* MAC with load.  */
5604        tmp = gen_lea(env, s, insn, OS_LONG);
5605        addr = tcg_temp_new();
5606        tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
5607        /*
5608         * Load the value now to ensure correct exception behavior.
5609         * Perform writeback after reading the MAC inputs.
5610         */
5611        loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
5612
5613        acc ^= 1;
5614        rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
5615        ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
5616    } else {
5617        loadval = addr = NULL_QREG;
5618        rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
5619        ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5620    }
5621
5622    gen_mac_clear_flags();
5623#if 0
5624    l1 = -1;
5625    /* Disabled because conditional branches clobber temporary vars.  */
5626    if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
5627        /* Skip the multiply if we know we will ignore it.  */
5628        l1 = gen_new_label();
5629        tmp = tcg_temp_new();
5630        tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8));
5631        gen_op_jmp_nz32(tmp, l1);
5632    }
5633#endif
5634
5635    if ((ext & 0x0800) == 0) {
5636        /* Word.  */
5637        rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
5638        ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
5639    }
5640    if (s->env->macsr & MACSR_FI) {
5641        gen_helper_macmulf(s->mactmp, cpu_env, rx, ry);
5642    } else {
5643        if (s->env->macsr & MACSR_SU)
5644            gen_helper_macmuls(s->mactmp, cpu_env, rx, ry);
5645        else
5646            gen_helper_macmulu(s->mactmp, cpu_env, rx, ry);
5647        switch ((ext >> 9) & 3) {
5648        case 1:
5649            tcg_gen_shli_i64(s->mactmp, s->mactmp, 1);
5650            break;
5651        case 3:
5652            tcg_gen_shri_i64(s->mactmp, s->mactmp, 1);
5653            break;
5654        }
5655    }
5656
5657    if (dual) {
5658        /* Save the overflow flag from the multiply.  */
5659        saved_flags = tcg_temp_new();
5660        tcg_gen_mov_i32(saved_flags, QREG_MACSR);
5661    } else {
5662        saved_flags = NULL_QREG;
5663    }
5664
5665#if 0
5666    /* Disabled because conditional branches clobber temporary vars.  */
5667    if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
5668        /* Skip the accumulate if the value is already saturated.  */
5669        l1 = gen_new_label();
5670        tmp = tcg_temp_new();
5671        gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
5672        gen_op_jmp_nz32(tmp, l1);
5673    }
5674#endif
5675
5676    if (insn & 0x100)
5677        tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
5678    else
5679        tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
5680
5681    if (s->env->macsr & MACSR_FI)
5682        gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
5683    else if (s->env->macsr & MACSR_SU)
5684        gen_helper_macsats(cpu_env, tcg_const_i32(acc));
5685    else
5686        gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
5687
5688#if 0
5689    /* Disabled because conditional branches clobber temporary vars.  */
5690    if (l1 != -1)
5691        gen_set_label(l1);
5692#endif
5693
5694    if (dual) {
5695        /* Dual accumulate variant.  */
5696        acc = (ext >> 2) & 3;
5697        /* Restore the overflow flag from the multiplier.  */
5698        tcg_gen_mov_i32(QREG_MACSR, saved_flags);
5699#if 0
5700        /* Disabled because conditional branches clobber temporary vars.  */
5701        if ((s->env->macsr & MACSR_OMC) != 0) {
5702            /* Skip the accumulate if the value is already saturated.  */
5703            l1 = gen_new_label();
5704            tmp = tcg_temp_new();
5705            gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
5706            gen_op_jmp_nz32(tmp, l1);
5707        }
5708#endif
5709        if (ext & 2)
5710            tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
5711        else
5712            tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
5713        if (s->env->macsr & MACSR_FI)
5714            gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
5715        else if (s->env->macsr & MACSR_SU)
5716            gen_helper_macsats(cpu_env, tcg_const_i32(acc));
5717        else
5718            gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
5719#if 0
5720        /* Disabled because conditional branches clobber temporary vars.  */
5721        if (l1 != -1)
5722            gen_set_label(l1);
5723#endif
5724    }
5725    gen_helper_mac_set_flags(cpu_env, tcg_const_i32(acc));
5726
5727    if (insn & 0x30) {
5728        TCGv rw;
5729        rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
5730        tcg_gen_mov_i32(rw, loadval);
5731        /*
5732         * FIXME: Should address writeback happen with the masked or
5733         * unmasked value?
5734         */
5735        switch ((insn >> 3) & 7) {
5736        case 3: /* Post-increment.  */
5737            tcg_gen_addi_i32(AREG(insn, 0), addr, 4);
5738            break;
5739        case 4: /* Pre-decrement.  */
5740            tcg_gen_mov_i32(AREG(insn, 0), addr);
5741        }
5742        tcg_temp_free(loadval);
5743    }
5744}
5745
5746DISAS_INSN(from_mac)
5747{
5748    TCGv rx;
5749    TCGv_i64 acc;
5750    int accnum;
5751
5752    rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5753    accnum = (insn >> 9) & 3;
5754    acc = MACREG(accnum);
5755    if (s->env->macsr & MACSR_FI) {
5756        gen_helper_get_macf(rx, cpu_env, acc);
5757    } else if ((s->env->macsr & MACSR_OMC) == 0) {
5758        tcg_gen_extrl_i64_i32(rx, acc);
5759    } else if (s->env->macsr & MACSR_SU) {
5760        gen_helper_get_macs(rx, acc);
5761    } else {
5762        gen_helper_get_macu(rx, acc);
5763    }
5764    if (insn & 0x40) {
5765        tcg_gen_movi_i64(acc, 0);
5766        tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
5767    }
5768}
5769
5770DISAS_INSN(move_mac)
5771{
5772    /* FIXME: This can be done without a helper.  */
5773    int src;
5774    TCGv dest;
5775    src = insn & 3;
5776    dest = tcg_const_i32((insn >> 9) & 3);
5777    gen_helper_mac_move(cpu_env, dest, tcg_const_i32(src));
5778    gen_mac_clear_flags();
5779    gen_helper_mac_set_flags(cpu_env, dest);
5780}
5781
5782DISAS_INSN(from_macsr)
5783{
5784    TCGv reg;
5785
5786    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5787    tcg_gen_mov_i32(reg, QREG_MACSR);
5788}
5789
5790DISAS_INSN(from_mask)
5791{
5792    TCGv reg;
5793    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5794    tcg_gen_mov_i32(reg, QREG_MAC_MASK);
5795}
5796
5797DISAS_INSN(from_mext)
5798{
5799    TCGv reg;
5800    TCGv acc;
5801    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5802    acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
5803    if (s->env->macsr & MACSR_FI)
5804        gen_helper_get_mac_extf(reg, cpu_env, acc);
5805    else
5806        gen_helper_get_mac_exti(reg, cpu_env, acc);
5807}
5808
5809DISAS_INSN(macsr_to_ccr)
5810{
5811    TCGv tmp = tcg_temp_new();
5812    tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf);
5813    gen_helper_set_sr(cpu_env, tmp);
5814    tcg_temp_free(tmp);
5815    set_cc_op(s, CC_OP_FLAGS);
5816}
5817
5818DISAS_INSN(to_mac)
5819{
5820    TCGv_i64 acc;
5821    TCGv val;
5822    int accnum;
5823    accnum = (insn >> 9) & 3;
5824    acc = MACREG(accnum);
5825    SRC_EA(env, val, OS_LONG, 0, NULL);
5826    if (s->env->macsr & MACSR_FI) {
5827        tcg_gen_ext_i32_i64(acc, val);
5828        tcg_gen_shli_i64(acc, acc, 8);
5829    } else if (s->env->macsr & MACSR_SU) {
5830        tcg_gen_ext_i32_i64(acc, val);
5831    } else {
5832        tcg_gen_extu_i32_i64(acc, val);
5833    }
5834    tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
5835    gen_mac_clear_flags();
5836    gen_helper_mac_set_flags(cpu_env, tcg_const_i32(accnum));
5837}
5838
5839DISAS_INSN(to_macsr)
5840{
5841    TCGv val;
5842    SRC_EA(env, val, OS_LONG, 0, NULL);
5843    gen_helper_set_macsr(cpu_env, val);
5844    gen_exit_tb(s);
5845}
5846
5847DISAS_INSN(to_mask)
5848{
5849    TCGv val;
5850    SRC_EA(env, val, OS_LONG, 0, NULL);
5851    tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000);
5852}
5853
5854DISAS_INSN(to_mext)
5855{
5856    TCGv val;
5857    TCGv acc;
5858    SRC_EA(env, val, OS_LONG, 0, NULL);
5859    acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
5860    if (s->env->macsr & MACSR_FI)
5861        gen_helper_set_mac_extf(cpu_env, val, acc);
5862    else if (s->env->macsr & MACSR_SU)
5863        gen_helper_set_mac_exts(cpu_env, val, acc);
5864    else
5865        gen_helper_set_mac_extu(cpu_env, val, acc);
5866}
5867
5868static disas_proc opcode_table[65536];
5869
5870static void
5871register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
5872{
5873  int i;
5874  int from;
5875  int to;
5876
5877  /* Sanity check.  All set bits must be included in the mask.  */
5878  if (opcode & ~mask) {
5879      fprintf(stderr,
5880              "qemu internal error: bogus opcode definition %04x/%04x\n",
5881              opcode, mask);
5882      abort();
5883  }
5884  /*
5885   * This could probably be cleverer.  For now just optimize the case where
5886   * the top bits are known.
5887   */
5888  /* Find the first zero bit in the mask.  */
5889  i = 0x8000;
5890  while ((i & mask) != 0)
5891      i >>= 1;
5892  /* Iterate over all combinations of this and lower bits.  */
5893  if (i == 0)
5894      i = 1;
5895  else
5896      i <<= 1;
5897  from = opcode & ~(i - 1);
5898  to = from + i;
5899  for (i = from; i < to; i++) {
5900      if ((i & mask) == opcode)
5901          opcode_table[i] = proc;
5902  }
5903}
5904
5905/*
5906 * Register m68k opcode handlers.  Order is important.
5907 * Later insn override earlier ones.
5908 */
5909void register_m68k_insns (CPUM68KState *env)
5910{
5911    /*
5912     * Build the opcode table only once to avoid
5913     * multithreading issues.
5914     */
5915    if (opcode_table[0] != NULL) {
5916        return;
5917    }
5918
5919    /*
5920     * use BASE() for instruction available
5921     * for CF_ISA_A and M68000.
5922     */
5923#define BASE(name, opcode, mask) \
5924    register_opcode(disas_##name, 0x##opcode, 0x##mask)
5925#define INSN(name, opcode, mask, feature) do { \
5926    if (m68k_feature(env, M68K_FEATURE_##feature)) \
5927        BASE(name, opcode, mask); \
5928    } while(0)
5929    BASE(undef,     0000, 0000);
5930    INSN(arith_im,  0080, fff8, CF_ISA_A);
5931    INSN(arith_im,  0000, ff00, M68000);
5932    INSN(chk2,      00c0, f9c0, CHK2);
5933    INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
5934    BASE(bitop_reg, 0100, f1c0);
5935    BASE(bitop_reg, 0140, f1c0);
5936    BASE(bitop_reg, 0180, f1c0);
5937    BASE(bitop_reg, 01c0, f1c0);
5938    INSN(movep,     0108, f138, MOVEP);
5939    INSN(arith_im,  0280, fff8, CF_ISA_A);
5940    INSN(arith_im,  0200, ff00, M68000);
5941    INSN(undef,     02c0, ffc0, M68000);
5942    INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
5943    INSN(arith_im,  0480, fff8, CF_ISA_A);
5944    INSN(arith_im,  0400, ff00, M68000);
5945    INSN(undef,     04c0, ffc0, M68000);
5946    INSN(arith_im,  0600, ff00, M68000);
5947    INSN(undef,     06c0, ffc0, M68000);
5948    INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
5949    INSN(arith_im,  0680, fff8, CF_ISA_A);
5950    INSN(arith_im,  0c00, ff38, CF_ISA_A);
5951    INSN(arith_im,  0c00, ff00, M68000);
5952    BASE(bitop_im,  0800, ffc0);
5953    BASE(bitop_im,  0840, ffc0);
5954    BASE(bitop_im,  0880, ffc0);
5955    BASE(bitop_im,  08c0, ffc0);
5956    INSN(arith_im,  0a80, fff8, CF_ISA_A);
5957    INSN(arith_im,  0a00, ff00, M68000);
5958#if defined(CONFIG_SOFTMMU)
5959    INSN(moves,     0e00, ff00, M68000);
5960#endif
5961    INSN(cas,       0ac0, ffc0, CAS);
5962    INSN(cas,       0cc0, ffc0, CAS);
5963    INSN(cas,       0ec0, ffc0, CAS);
5964    INSN(cas2w,     0cfc, ffff, CAS);
5965    INSN(cas2l,     0efc, ffff, CAS);
5966    BASE(move,      1000, f000);
5967    BASE(move,      2000, f000);
5968    BASE(move,      3000, f000);
5969    INSN(chk,       4000, f040, M68000);
5970    INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
5971    INSN(negx,      4080, fff8, CF_ISA_A);
5972    INSN(negx,      4000, ff00, M68000);
5973    INSN(undef,     40c0, ffc0, M68000);
5974    INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
5975    INSN(move_from_sr, 40c0, ffc0, M68000);
5976    BASE(lea,       41c0, f1c0);
5977    BASE(clr,       4200, ff00);
5978    BASE(undef,     42c0, ffc0);
5979    INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
5980    INSN(move_from_ccr, 42c0, ffc0, M68000);
5981    INSN(neg,       4480, fff8, CF_ISA_A);
5982    INSN(neg,       4400, ff00, M68000);
5983    INSN(undef,     44c0, ffc0, M68000);
5984    BASE(move_to_ccr, 44c0, ffc0);
5985    INSN(not,       4680, fff8, CF_ISA_A);
5986    INSN(not,       4600, ff00, M68000);
5987#if defined(CONFIG_SOFTMMU)
5988    BASE(move_to_sr, 46c0, ffc0);
5989#endif
5990    INSN(nbcd,      4800, ffc0, M68000);
5991    INSN(linkl,     4808, fff8, M68000);
5992    BASE(pea,       4840, ffc0);
5993    BASE(swap,      4840, fff8);
5994    INSN(bkpt,      4848, fff8, BKPT);
5995    INSN(movem,     48d0, fbf8, CF_ISA_A);
5996    INSN(movem,     48e8, fbf8, CF_ISA_A);
5997    INSN(movem,     4880, fb80, M68000);
5998    BASE(ext,       4880, fff8);
5999    BASE(ext,       48c0, fff8);
6000    BASE(ext,       49c0, fff8);
6001    BASE(tst,       4a00, ff00);
6002    INSN(tas,       4ac0, ffc0, CF_ISA_B);
6003    INSN(tas,       4ac0, ffc0, M68000);
6004#if defined(CONFIG_SOFTMMU)
6005    INSN(halt,      4ac8, ffff, CF_ISA_A);
6006#endif
6007    INSN(pulse,     4acc, ffff, CF_ISA_A);
6008    BASE(illegal,   4afc, ffff);
6009    INSN(mull,      4c00, ffc0, CF_ISA_A);
6010    INSN(mull,      4c00, ffc0, LONG_MULDIV);
6011    INSN(divl,      4c40, ffc0, CF_ISA_A);
6012    INSN(divl,      4c40, ffc0, LONG_MULDIV);
6013    INSN(sats,      4c80, fff8, CF_ISA_B);
6014    BASE(trap,      4e40, fff0);
6015    BASE(link,      4e50, fff8);
6016    BASE(unlk,      4e58, fff8);
6017#if defined(CONFIG_SOFTMMU)
6018    INSN(move_to_usp, 4e60, fff8, USP);
6019    INSN(move_from_usp, 4e68, fff8, USP);
6020    INSN(reset,     4e70, ffff, M68000);
6021    BASE(stop,      4e72, ffff);
6022    BASE(rte,       4e73, ffff);
6023    INSN(cf_movec,  4e7b, ffff, CF_ISA_A);
6024    INSN(m68k_movec, 4e7a, fffe, MOVEC);
6025#endif
6026    BASE(nop,       4e71, ffff);
6027    INSN(rtd,       4e74, ffff, RTD);
6028    BASE(rts,       4e75, ffff);
6029    INSN(rtr,       4e77, ffff, M68000);
6030    BASE(jump,      4e80, ffc0);
6031    BASE(jump,      4ec0, ffc0);
6032    INSN(addsubq,   5000, f080, M68000);
6033    BASE(addsubq,   5080, f0c0);
6034    INSN(scc,       50c0, f0f8, CF_ISA_A); /* Scc.B Dx   */
6035    INSN(scc,       50c0, f0c0, M68000);   /* Scc.B <EA> */
6036    INSN(dbcc,      50c8, f0f8, M68000);
6037    INSN(tpf,       51f8, fff8, CF_ISA_A);
6038
6039    /* Branch instructions.  */
6040    BASE(branch,    6000, f000);
6041    /* Disable long branch instructions, then add back the ones we want.  */
6042    BASE(undef,     60ff, f0ff); /* All long branches.  */
6043    INSN(branch,    60ff, f0ff, CF_ISA_B);
6044    INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
6045    INSN(branch,    60ff, ffff, BRAL);
6046    INSN(branch,    60ff, f0ff, BCCL);
6047
6048    BASE(moveq,     7000, f100);
6049    INSN(mvzs,      7100, f100, CF_ISA_B);
6050    BASE(or,        8000, f000);
6051    BASE(divw,      80c0, f0c0);
6052    INSN(sbcd_reg,  8100, f1f8, M68000);
6053    INSN(sbcd_mem,  8108, f1f8, M68000);
6054    BASE(addsub,    9000, f000);
6055    INSN(undef,     90c0, f0c0, CF_ISA_A);
6056    INSN(subx_reg,  9180, f1f8, CF_ISA_A);
6057    INSN(subx_reg,  9100, f138, M68000);
6058    INSN(subx_mem,  9108, f138, M68000);
6059    INSN(suba,      91c0, f1c0, CF_ISA_A);
6060    INSN(suba,      90c0, f0c0, M68000);
6061
6062    BASE(undef_mac, a000, f000);
6063    INSN(mac,       a000, f100, CF_EMAC);
6064    INSN(from_mac,  a180, f9b0, CF_EMAC);
6065    INSN(move_mac,  a110, f9fc, CF_EMAC);
6066    INSN(from_macsr,a980, f9f0, CF_EMAC);
6067    INSN(from_mask, ad80, fff0, CF_EMAC);
6068    INSN(from_mext, ab80, fbf0, CF_EMAC);
6069    INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
6070    INSN(to_mac,    a100, f9c0, CF_EMAC);
6071    INSN(to_macsr,  a900, ffc0, CF_EMAC);
6072    INSN(to_mext,   ab00, fbc0, CF_EMAC);
6073    INSN(to_mask,   ad00, ffc0, CF_EMAC);
6074
6075    INSN(mov3q,     a140, f1c0, CF_ISA_B);
6076    INSN(cmp,       b000, f1c0, CF_ISA_B); /* cmp.b */
6077    INSN(cmp,       b040, f1c0, CF_ISA_B); /* cmp.w */
6078    INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
6079    INSN(cmp,       b080, f1c0, CF_ISA_A);
6080    INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
6081    INSN(cmp,       b000, f100, M68000);
6082    INSN(eor,       b100, f100, M68000);
6083    INSN(cmpm,      b108, f138, M68000);
6084    INSN(cmpa,      b0c0, f0c0, M68000);
6085    INSN(eor,       b180, f1c0, CF_ISA_A);
6086    BASE(and,       c000, f000);
6087    INSN(exg_dd,    c140, f1f8, M68000);
6088    INSN(exg_aa,    c148, f1f8, M68000);
6089    INSN(exg_da,    c188, f1f8, M68000);
6090    BASE(mulw,      c0c0, f0c0);
6091    INSN(abcd_reg,  c100, f1f8, M68000);
6092    INSN(abcd_mem,  c108, f1f8, M68000);
6093    BASE(addsub,    d000, f000);
6094    INSN(undef,     d0c0, f0c0, CF_ISA_A);
6095    INSN(addx_reg,      d180, f1f8, CF_ISA_A);
6096    INSN(addx_reg,  d100, f138, M68000);
6097    INSN(addx_mem,  d108, f138, M68000);
6098    INSN(adda,      d1c0, f1c0, CF_ISA_A);
6099    INSN(adda,      d0c0, f0c0, M68000);
6100    INSN(shift_im,  e080, f0f0, CF_ISA_A);
6101    INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
6102    INSN(shift8_im, e000, f0f0, M68000);
6103    INSN(shift16_im, e040, f0f0, M68000);
6104    INSN(shift_im,  e080, f0f0, M68000);
6105    INSN(shift8_reg, e020, f0f0, M68000);
6106    INSN(shift16_reg, e060, f0f0, M68000);
6107    INSN(shift_reg, e0a0, f0f0, M68000);
6108    INSN(shift_mem, e0c0, fcc0, M68000);
6109    INSN(rotate_im, e090, f0f0, M68000);
6110    INSN(rotate8_im, e010, f0f0, M68000);
6111    INSN(rotate16_im, e050, f0f0, M68000);
6112    INSN(rotate_reg, e0b0, f0f0, M68000);
6113    INSN(rotate8_reg, e030, f0f0, M68000);
6114    INSN(rotate16_reg, e070, f0f0, M68000);
6115    INSN(rotate_mem, e4c0, fcc0, M68000);
6116    INSN(bfext_mem, e9c0, fdc0, BITFIELD);  /* bfextu & bfexts */
6117    INSN(bfext_reg, e9c0, fdf8, BITFIELD);
6118    INSN(bfins_mem, efc0, ffc0, BITFIELD);
6119    INSN(bfins_reg, efc0, fff8, BITFIELD);
6120    INSN(bfop_mem, eac0, ffc0, BITFIELD);   /* bfchg */
6121    INSN(bfop_reg, eac0, fff8, BITFIELD);   /* bfchg */
6122    INSN(bfop_mem, ecc0, ffc0, BITFIELD);   /* bfclr */
6123    INSN(bfop_reg, ecc0, fff8, BITFIELD);   /* bfclr */
6124    INSN(bfop_mem, edc0, ffc0, BITFIELD);   /* bfffo */
6125    INSN(bfop_reg, edc0, fff8, BITFIELD);   /* bfffo */
6126    INSN(bfop_mem, eec0, ffc0, BITFIELD);   /* bfset */
6127    INSN(bfop_reg, eec0, fff8, BITFIELD);   /* bfset */
6128    INSN(bfop_mem, e8c0, ffc0, BITFIELD);   /* bftst */
6129    INSN(bfop_reg, e8c0, fff8, BITFIELD);   /* bftst */
6130    BASE(undef_fpu, f000, f000);
6131    INSN(fpu,       f200, ffc0, CF_FPU);
6132    INSN(fbcc,      f280, ffc0, CF_FPU);
6133    INSN(fpu,       f200, ffc0, FPU);
6134    INSN(fscc,      f240, ffc0, FPU);
6135    INSN(fbcc,      f280, ff80, FPU);
6136#if defined(CONFIG_SOFTMMU)
6137    INSN(frestore,  f340, ffc0, CF_FPU);
6138    INSN(fsave,     f300, ffc0, CF_FPU);
6139    INSN(frestore,  f340, ffc0, FPU);
6140    INSN(fsave,     f300, ffc0, FPU);
6141    INSN(intouch,   f340, ffc0, CF_ISA_A);
6142    INSN(cpushl,    f428, ff38, CF_ISA_A);
6143    INSN(cpush,     f420, ff20, M68040);
6144    INSN(cinv,      f400, ff20, M68040);
6145    INSN(pflush,    f500, ffe0, M68040);
6146    INSN(ptest,     f548, ffd8, M68040);
6147    INSN(wddata,    fb00, ff00, CF_ISA_A);
6148    INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
6149#endif
6150    INSN(move16_mem, f600, ffe0, M68040);
6151    INSN(move16_reg, f620, fff8, M68040);
6152#undef INSN
6153}
6154
6155static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
6156{
6157    DisasContext *dc = container_of(dcbase, DisasContext, base);
6158    CPUM68KState *env = cpu->env_ptr;
6159
6160    dc->env = env;
6161    dc->pc = dc->base.pc_first;
6162    dc->cc_op = CC_OP_DYNAMIC;
6163    dc->cc_op_synced = 1;
6164    dc->done_mac = 0;
6165    dc->writeback_mask = 0;
6166    init_release_array(dc);
6167
6168    dc->ss_active = (M68K_SR_TRACE(env->sr) == M68K_SR_TRACE_ANY_INS);
6169    /* If architectural single step active, limit to 1 */
6170    if (dc->ss_active) {
6171        dc->base.max_insns = 1;
6172    }
6173}
6174
6175static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
6176{
6177}
6178
6179static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
6180{
6181    DisasContext *dc = container_of(dcbase, DisasContext, base);
6182    tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
6183}
6184
6185static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
6186{
6187    DisasContext *dc = container_of(dcbase, DisasContext, base);
6188    CPUM68KState *env = cpu->env_ptr;
6189    uint16_t insn = read_im16(env, dc);
6190
6191    opcode_table[insn](env, dc, insn);
6192    do_writebacks(dc);
6193    do_release(dc);
6194
6195    dc->base.pc_next = dc->pc;
6196
6197    if (dc->base.is_jmp == DISAS_NEXT) {
6198        /*
6199         * Stop translation when the next insn might touch a new page.
6200         * This ensures that prefetch aborts at the right place.
6201         *
6202         * We cannot determine the size of the next insn without
6203         * completely decoding it.  However, the maximum insn size
6204         * is 32 bytes, so end if we do not have that much remaining.
6205         * This may produce several small TBs at the end of each page,
6206         * but they will all be linked with goto_tb.
6207         *
6208         * ??? ColdFire maximum is 4 bytes; MC68000's maximum is also
6209         * smaller than MC68020's.
6210         */
6211        target_ulong start_page_offset
6212            = dc->pc - (dc->base.pc_first & TARGET_PAGE_MASK);
6213
6214        if (start_page_offset >= TARGET_PAGE_SIZE - 32) {
6215            dc->base.is_jmp = DISAS_TOO_MANY;
6216        }
6217    }
6218}
6219
6220static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
6221{
6222    DisasContext *dc = container_of(dcbase, DisasContext, base);
6223
6224    switch (dc->base.is_jmp) {
6225    case DISAS_NORETURN:
6226        break;
6227    case DISAS_TOO_MANY:
6228        update_cc_op(dc);
6229        if (dc->ss_active) {
6230            tcg_gen_movi_i32(QREG_PC, dc->pc);
6231            gen_raise_exception(EXCP_TRACE);
6232        } else {
6233            gen_jmp_tb(dc, 0, dc->pc);
6234        }
6235        break;
6236    case DISAS_JUMP:
6237        /* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
6238        if (dc->ss_active) {
6239            gen_raise_exception(EXCP_TRACE);
6240        } else {
6241            tcg_gen_lookup_and_goto_ptr();
6242        }
6243        break;
6244    case DISAS_EXIT:
6245        /*
6246         * We updated CC_OP and PC in gen_exit_tb, but also modified
6247         * other state that may require returning to the main loop.
6248         */
6249        if (dc->ss_active) {
6250            gen_raise_exception(EXCP_TRACE);
6251        } else {
6252            tcg_gen_exit_tb(NULL, 0);
6253        }
6254        break;
6255    default:
6256        g_assert_not_reached();
6257    }
6258}
6259
6260static void m68k_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
6261{
6262    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
6263    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
6264}
6265
6266static const TranslatorOps m68k_tr_ops = {
6267    .init_disas_context = m68k_tr_init_disas_context,
6268    .tb_start           = m68k_tr_tb_start,
6269    .insn_start         = m68k_tr_insn_start,
6270    .translate_insn     = m68k_tr_translate_insn,
6271    .tb_stop            = m68k_tr_tb_stop,
6272    .disas_log          = m68k_tr_disas_log,
6273};
6274
6275void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
6276{
6277    DisasContext dc;
6278    translator_loop(&m68k_tr_ops, &dc.base, cpu, tb, max_insns);
6279}
6280
6281static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low)
6282{
6283    floatx80 a = { .high = high, .low = low };
6284    union {
6285        float64 f64;
6286        double d;
6287    } u;
6288
6289    u.f64 = floatx80_to_float64(a, &env->fp_status);
6290    return u.d;
6291}
6292
6293void m68k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6294{
6295    M68kCPU *cpu = M68K_CPU(cs);
6296    CPUM68KState *env = &cpu->env;
6297    int i;
6298    uint16_t sr;
6299    for (i = 0; i < 8; i++) {
6300        qemu_fprintf(f, "D%d = %08x   A%d = %08x   "
6301                     "F%d = %04x %016"PRIx64"  (%12g)\n",
6302                     i, env->dregs[i], i, env->aregs[i],
6303                     i, env->fregs[i].l.upper, env->fregs[i].l.lower,
6304                     floatx80_to_double(env, env->fregs[i].l.upper,
6305                                        env->fregs[i].l.lower));
6306    }
6307    qemu_fprintf(f, "PC = %08x   ", env->pc);
6308    sr = env->sr | cpu_m68k_get_ccr(env);
6309    qemu_fprintf(f, "SR = %04x T:%x I:%x %c%c %c%c%c%c%c\n",
6310                 sr, (sr & SR_T) >> SR_T_SHIFT, (sr & SR_I) >> SR_I_SHIFT,
6311                 (sr & SR_S) ? 'S' : 'U', (sr & SR_M) ? '%' : 'I',
6312                 (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-',
6313                 (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-',
6314                 (sr & CCF_C) ? 'C' : '-');
6315    qemu_fprintf(f, "FPSR = %08x %c%c%c%c ", env->fpsr,
6316                 (env->fpsr & FPSR_CC_A) ? 'A' : '-',
6317                 (env->fpsr & FPSR_CC_I) ? 'I' : '-',
6318                 (env->fpsr & FPSR_CC_Z) ? 'Z' : '-',
6319                 (env->fpsr & FPSR_CC_N) ? 'N' : '-');
6320    qemu_fprintf(f, "\n                                "
6321                 "FPCR =     %04x ", env->fpcr);
6322    switch (env->fpcr & FPCR_PREC_MASK) {
6323    case FPCR_PREC_X:
6324        qemu_fprintf(f, "X ");
6325        break;
6326    case FPCR_PREC_S:
6327        qemu_fprintf(f, "S ");
6328        break;
6329    case FPCR_PREC_D:
6330        qemu_fprintf(f, "D ");
6331        break;
6332    }
6333    switch (env->fpcr & FPCR_RND_MASK) {
6334    case FPCR_RND_N:
6335        qemu_fprintf(f, "RN ");
6336        break;
6337    case FPCR_RND_Z:
6338        qemu_fprintf(f, "RZ ");
6339        break;
6340    case FPCR_RND_M:
6341        qemu_fprintf(f, "RM ");
6342        break;
6343    case FPCR_RND_P:
6344        qemu_fprintf(f, "RP ");
6345        break;
6346    }
6347    qemu_fprintf(f, "\n");
6348#ifdef CONFIG_SOFTMMU
6349    qemu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n",
6350                 env->current_sp == M68K_SSP ? "->" : "  ", env->sp[M68K_SSP],
6351                 env->current_sp == M68K_USP ? "->" : "  ", env->sp[M68K_USP],
6352                 env->current_sp == M68K_ISP ? "->" : "  ", env->sp[M68K_ISP]);
6353    qemu_fprintf(f, "VBR = 0x%08x\n", env->vbr);
6354    qemu_fprintf(f, "SFC = %x DFC %x\n", env->sfc, env->dfc);
6355    qemu_fprintf(f, "SSW %08x TCR %08x URP %08x SRP %08x\n",
6356                 env->mmu.ssw, env->mmu.tcr, env->mmu.urp, env->mmu.srp);
6357    qemu_fprintf(f, "DTTR0/1: %08x/%08x ITTR0/1: %08x/%08x\n",
6358                 env->mmu.ttr[M68K_DTTR0], env->mmu.ttr[M68K_DTTR1],
6359                 env->mmu.ttr[M68K_ITTR0], env->mmu.ttr[M68K_ITTR1]);
6360    qemu_fprintf(f, "MMUSR %08x, fault at %08x\n",
6361                 env->mmu.mmusr, env->mmu.ar);
6362#endif
6363}
6364
6365void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
6366                          target_ulong *data)
6367{
6368    int cc_op = data[1];
6369    env->pc = data[0];
6370    if (cc_op != CC_OP_DYNAMIC) {
6371        env->cc_op = cc_op;
6372    }
6373}
6374