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