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