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