qemu/target-ppc/translate.c
<<
>>
Prefs
   1/*
   2 *  PowerPC emulation for qemu: main translation routines.
   3 *
   4 *  Copyright (c) 2003-2007 Jocelyn Mayer
   5 *  Copyright (C) 2011 Freescale Semiconductor, Inc.
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * 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 "tcg-op.h"
  25#include "qemu/host-utils.h"
  26#include "exec/cpu_ldst.h"
  27
  28#include "exec/helper-proto.h"
  29#include "exec/helper-gen.h"
  30
  31#include "trace-tcg.h"
  32#include "exec/log.h"
  33
  34
  35#define CPU_SINGLE_STEP 0x1
  36#define CPU_BRANCH_STEP 0x2
  37#define GDBSTUB_SINGLE_STEP 0x4
  38
  39/* Include definitions for instructions classes and implementations flags */
  40//#define PPC_DEBUG_DISAS
  41//#define DO_PPC_STATISTICS
  42
  43#ifdef PPC_DEBUG_DISAS
  44#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
  45#else
  46#  define LOG_DISAS(...) do { } while (0)
  47#endif
  48/*****************************************************************************/
  49/* Code translation helpers                                                  */
  50
  51/* global register indexes */
  52static TCGv_env cpu_env;
  53static char cpu_reg_names[10*3 + 22*4 /* GPR */
  54    + 10*4 + 22*5 /* SPE GPRh */
  55    + 10*4 + 22*5 /* FPR */
  56    + 2*(10*6 + 22*7) /* AVRh, AVRl */
  57    + 10*5 + 22*6 /* VSR */
  58    + 8*5 /* CRF */];
  59static TCGv cpu_gpr[32];
  60static TCGv cpu_gprh[32];
  61static TCGv_i64 cpu_fpr[32];
  62static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
  63static TCGv_i64 cpu_vsr[32];
  64static TCGv_i32 cpu_crf[8];
  65static TCGv cpu_nip;
  66static TCGv cpu_msr;
  67static TCGv cpu_ctr;
  68static TCGv cpu_lr;
  69#if defined(TARGET_PPC64)
  70static TCGv cpu_cfar;
  71#endif
  72static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
  73static TCGv cpu_reserve;
  74static TCGv cpu_fpscr;
  75static TCGv_i32 cpu_access_type;
  76
  77#include "exec/gen-icount.h"
  78
  79void ppc_translate_init(void)
  80{
  81    int i;
  82    char* p;
  83    size_t cpu_reg_names_size;
  84    static int done_init = 0;
  85
  86    if (done_init)
  87        return;
  88
  89    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
  90
  91    p = cpu_reg_names;
  92    cpu_reg_names_size = sizeof(cpu_reg_names);
  93
  94    for (i = 0; i < 8; i++) {
  95        snprintf(p, cpu_reg_names_size, "crf%d", i);
  96        cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
  97                                            offsetof(CPUPPCState, crf[i]), p);
  98        p += 5;
  99        cpu_reg_names_size -= 5;
 100    }
 101
 102    for (i = 0; i < 32; i++) {
 103        snprintf(p, cpu_reg_names_size, "r%d", i);
 104        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 105                                        offsetof(CPUPPCState, gpr[i]), p);
 106        p += (i < 10) ? 3 : 4;
 107        cpu_reg_names_size -= (i < 10) ? 3 : 4;
 108        snprintf(p, cpu_reg_names_size, "r%dH", i);
 109        cpu_gprh[i] = tcg_global_mem_new(cpu_env,
 110                                         offsetof(CPUPPCState, gprh[i]), p);
 111        p += (i < 10) ? 4 : 5;
 112        cpu_reg_names_size -= (i < 10) ? 4 : 5;
 113
 114        snprintf(p, cpu_reg_names_size, "fp%d", i);
 115        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
 116                                            offsetof(CPUPPCState, fpr[i]), p);
 117        p += (i < 10) ? 4 : 5;
 118        cpu_reg_names_size -= (i < 10) ? 4 : 5;
 119
 120        snprintf(p, cpu_reg_names_size, "avr%dH", i);
 121#ifdef HOST_WORDS_BIGENDIAN
 122        cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
 123                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 124#else
 125        cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
 126                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 127#endif
 128        p += (i < 10) ? 6 : 7;
 129        cpu_reg_names_size -= (i < 10) ? 6 : 7;
 130
 131        snprintf(p, cpu_reg_names_size, "avr%dL", i);
 132#ifdef HOST_WORDS_BIGENDIAN
 133        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
 134                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 135#else
 136        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
 137                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 138#endif
 139        p += (i < 10) ? 6 : 7;
 140        cpu_reg_names_size -= (i < 10) ? 6 : 7;
 141        snprintf(p, cpu_reg_names_size, "vsr%d", i);
 142        cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env,
 143                                            offsetof(CPUPPCState, vsr[i]), p);
 144        p += (i < 10) ? 5 : 6;
 145        cpu_reg_names_size -= (i < 10) ? 5 : 6;
 146    }
 147
 148    cpu_nip = tcg_global_mem_new(cpu_env,
 149                                 offsetof(CPUPPCState, nip), "nip");
 150
 151    cpu_msr = tcg_global_mem_new(cpu_env,
 152                                 offsetof(CPUPPCState, msr), "msr");
 153
 154    cpu_ctr = tcg_global_mem_new(cpu_env,
 155                                 offsetof(CPUPPCState, ctr), "ctr");
 156
 157    cpu_lr = tcg_global_mem_new(cpu_env,
 158                                offsetof(CPUPPCState, lr), "lr");
 159
 160#if defined(TARGET_PPC64)
 161    cpu_cfar = tcg_global_mem_new(cpu_env,
 162                                  offsetof(CPUPPCState, cfar), "cfar");
 163#endif
 164
 165    cpu_xer = tcg_global_mem_new(cpu_env,
 166                                 offsetof(CPUPPCState, xer), "xer");
 167    cpu_so = tcg_global_mem_new(cpu_env,
 168                                offsetof(CPUPPCState, so), "SO");
 169    cpu_ov = tcg_global_mem_new(cpu_env,
 170                                offsetof(CPUPPCState, ov), "OV");
 171    cpu_ca = tcg_global_mem_new(cpu_env,
 172                                offsetof(CPUPPCState, ca), "CA");
 173
 174    cpu_reserve = tcg_global_mem_new(cpu_env,
 175                                     offsetof(CPUPPCState, reserve_addr),
 176                                     "reserve_addr");
 177
 178    cpu_fpscr = tcg_global_mem_new(cpu_env,
 179                                   offsetof(CPUPPCState, fpscr), "fpscr");
 180
 181    cpu_access_type = tcg_global_mem_new_i32(cpu_env,
 182                                             offsetof(CPUPPCState, access_type), "access_type");
 183
 184    done_init = 1;
 185}
 186
 187/* internal defines */
 188struct DisasContext {
 189    struct TranslationBlock *tb;
 190    target_ulong nip;
 191    uint32_t opcode;
 192    uint32_t exception;
 193    /* Routine used to access memory */
 194    bool pr, hv;
 195    int mem_idx;
 196    int access_type;
 197    /* Translation flags */
 198    int le_mode;
 199    TCGMemOp default_tcg_memop_mask;
 200#if defined(TARGET_PPC64)
 201    int sf_mode;
 202    int has_cfar;
 203#endif
 204    int fpu_enabled;
 205    int altivec_enabled;
 206    int vsx_enabled;
 207    int spe_enabled;
 208    int tm_enabled;
 209    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
 210    int singlestep_enabled;
 211    uint64_t insns_flags;
 212    uint64_t insns_flags2;
 213};
 214
 215/* Return true iff byteswap is needed in a scalar memop */
 216static inline bool need_byteswap(const DisasContext *ctx)
 217{
 218#if defined(TARGET_WORDS_BIGENDIAN)
 219     return ctx->le_mode;
 220#else
 221     return !ctx->le_mode;
 222#endif
 223}
 224
 225/* True when active word size < size of target_long.  */
 226#ifdef TARGET_PPC64
 227# define NARROW_MODE(C)  (!(C)->sf_mode)
 228#else
 229# define NARROW_MODE(C)  0
 230#endif
 231
 232struct opc_handler_t {
 233    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
 234    uint32_t inval1;
 235    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
 236    uint32_t inval2;
 237    /* instruction type */
 238    uint64_t type;
 239    /* extended instruction type */
 240    uint64_t type2;
 241    /* handler */
 242    void (*handler)(DisasContext *ctx);
 243#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
 244    const char *oname;
 245#endif
 246#if defined(DO_PPC_STATISTICS)
 247    uint64_t count;
 248#endif
 249};
 250
 251static inline void gen_reset_fpstatus(void)
 252{
 253    gen_helper_reset_fpstatus(cpu_env);
 254}
 255
 256static inline void gen_compute_fprf(TCGv_i64 arg)
 257{
 258    gen_helper_compute_fprf(cpu_env, arg);
 259    gen_helper_float_check_status(cpu_env);
 260}
 261
 262static inline void gen_set_access_type(DisasContext *ctx, int access_type)
 263{
 264    if (ctx->access_type != access_type) {
 265        tcg_gen_movi_i32(cpu_access_type, access_type);
 266        ctx->access_type = access_type;
 267    }
 268}
 269
 270static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
 271{
 272    if (NARROW_MODE(ctx)) {
 273        nip = (uint32_t)nip;
 274    }
 275    tcg_gen_movi_tl(cpu_nip, nip);
 276}
 277
 278void gen_update_current_nip(void *opaque)
 279{
 280    DisasContext *ctx = opaque;
 281
 282    tcg_gen_movi_tl(cpu_nip, ctx->nip);
 283}
 284
 285static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
 286{
 287    TCGv_i32 t0, t1;
 288    if (ctx->exception == POWERPC_EXCP_NONE) {
 289        gen_update_nip(ctx, ctx->nip);
 290    }
 291    t0 = tcg_const_i32(excp);
 292    t1 = tcg_const_i32(error);
 293    gen_helper_raise_exception_err(cpu_env, t0, t1);
 294    tcg_temp_free_i32(t0);
 295    tcg_temp_free_i32(t1);
 296    ctx->exception = (excp);
 297}
 298
 299static inline void gen_exception(DisasContext *ctx, uint32_t excp)
 300{
 301    TCGv_i32 t0;
 302    if (ctx->exception == POWERPC_EXCP_NONE) {
 303        gen_update_nip(ctx, ctx->nip);
 304    }
 305    t0 = tcg_const_i32(excp);
 306    gen_helper_raise_exception(cpu_env, t0);
 307    tcg_temp_free_i32(t0);
 308    ctx->exception = (excp);
 309}
 310
 311static inline void gen_debug_exception(DisasContext *ctx)
 312{
 313    TCGv_i32 t0;
 314
 315    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
 316        (ctx->exception != POWERPC_EXCP_SYNC)) {
 317        gen_update_nip(ctx, ctx->nip);
 318    }
 319    t0 = tcg_const_i32(EXCP_DEBUG);
 320    gen_helper_raise_exception(cpu_env, t0);
 321    tcg_temp_free_i32(t0);
 322}
 323
 324static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
 325{
 326    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
 327}
 328
 329/* Stop translation */
 330static inline void gen_stop_exception(DisasContext *ctx)
 331{
 332    gen_update_nip(ctx, ctx->nip);
 333    ctx->exception = POWERPC_EXCP_STOP;
 334}
 335
 336#ifndef CONFIG_USER_ONLY
 337/* No need to update nip here, as execution flow will change */
 338static inline void gen_sync_exception(DisasContext *ctx)
 339{
 340    ctx->exception = POWERPC_EXCP_SYNC;
 341}
 342#endif
 343
 344#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
 345GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
 346
 347#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2)             \
 348GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
 349
 350#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
 351GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
 352
 353#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2)      \
 354GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
 355
 356typedef struct opcode_t {
 357    unsigned char opc1, opc2, opc3;
 358#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
 359    unsigned char pad[5];
 360#else
 361    unsigned char pad[1];
 362#endif
 363    opc_handler_t handler;
 364    const char *oname;
 365} opcode_t;
 366
 367/*****************************************************************************/
 368/***                           Instruction decoding                        ***/
 369#define EXTRACT_HELPER(name, shift, nb)                                       \
 370static inline uint32_t name(uint32_t opcode)                                  \
 371{                                                                             \
 372    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
 373}
 374
 375#define EXTRACT_SHELPER(name, shift, nb)                                      \
 376static inline int32_t name(uint32_t opcode)                                   \
 377{                                                                             \
 378    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
 379}
 380
 381#define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2)                  \
 382static inline uint32_t name(uint32_t opcode)                                  \
 383{                                                                             \
 384    return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) |             \
 385            ((opcode >> (shift2)) & ((1 << (nb2)) - 1));                      \
 386}
 387/* Opcode part 1 */
 388EXTRACT_HELPER(opc1, 26, 6);
 389/* Opcode part 2 */
 390EXTRACT_HELPER(opc2, 1, 5);
 391/* Opcode part 3 */
 392EXTRACT_HELPER(opc3, 6, 5);
 393/* Update Cr0 flags */
 394EXTRACT_HELPER(Rc, 0, 1);
 395/* Update Cr6 flags (Altivec) */
 396EXTRACT_HELPER(Rc21, 10, 1);
 397/* Destination */
 398EXTRACT_HELPER(rD, 21, 5);
 399/* Source */
 400EXTRACT_HELPER(rS, 21, 5);
 401/* First operand */
 402EXTRACT_HELPER(rA, 16, 5);
 403/* Second operand */
 404EXTRACT_HELPER(rB, 11, 5);
 405/* Third operand */
 406EXTRACT_HELPER(rC, 6, 5);
 407/***                               Get CRn                                 ***/
 408EXTRACT_HELPER(crfD, 23, 3);
 409EXTRACT_HELPER(crfS, 18, 3);
 410EXTRACT_HELPER(crbD, 21, 5);
 411EXTRACT_HELPER(crbA, 16, 5);
 412EXTRACT_HELPER(crbB, 11, 5);
 413/* SPR / TBL */
 414EXTRACT_HELPER(_SPR, 11, 10);
 415static inline uint32_t SPR(uint32_t opcode)
 416{
 417    uint32_t sprn = _SPR(opcode);
 418
 419    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
 420}
 421/***                              Get constants                            ***/
 422/* 16 bits signed immediate value */
 423EXTRACT_SHELPER(SIMM, 0, 16);
 424/* 16 bits unsigned immediate value */
 425EXTRACT_HELPER(UIMM, 0, 16);
 426/* 5 bits signed immediate value */
 427EXTRACT_HELPER(SIMM5, 16, 5);
 428/* 5 bits signed immediate value */
 429EXTRACT_HELPER(UIMM5, 16, 5);
 430/* Bit count */
 431EXTRACT_HELPER(NB, 11, 5);
 432/* Shift count */
 433EXTRACT_HELPER(SH, 11, 5);
 434/* Vector shift count */
 435EXTRACT_HELPER(VSH, 6, 4);
 436/* Mask start */
 437EXTRACT_HELPER(MB, 6, 5);
 438/* Mask end */
 439EXTRACT_HELPER(ME, 1, 5);
 440/* Trap operand */
 441EXTRACT_HELPER(TO, 21, 5);
 442
 443EXTRACT_HELPER(CRM, 12, 8);
 444
 445#ifndef CONFIG_USER_ONLY
 446EXTRACT_HELPER(SR, 16, 4);
 447#endif
 448
 449/* mtfsf/mtfsfi */
 450EXTRACT_HELPER(FPBF, 23, 3);
 451EXTRACT_HELPER(FPIMM, 12, 4);
 452EXTRACT_HELPER(FPL, 25, 1);
 453EXTRACT_HELPER(FPFLM, 17, 8);
 454EXTRACT_HELPER(FPW, 16, 1);
 455
 456/***                            Jump target decoding                       ***/
 457/* Immediate address */
 458static inline target_ulong LI(uint32_t opcode)
 459{
 460    return (opcode >> 0) & 0x03FFFFFC;
 461}
 462
 463static inline uint32_t BD(uint32_t opcode)
 464{
 465    return (opcode >> 0) & 0xFFFC;
 466}
 467
 468EXTRACT_HELPER(BO, 21, 5);
 469EXTRACT_HELPER(BI, 16, 5);
 470/* Absolute/relative address */
 471EXTRACT_HELPER(AA, 1, 1);
 472/* Link */
 473EXTRACT_HELPER(LK, 0, 1);
 474
 475/* DFP Z22-form */
 476EXTRACT_HELPER(DCM, 10, 6)
 477
 478/* DFP Z23-form */
 479EXTRACT_HELPER(RMC, 9, 2)
 480
 481/* Create a mask between <start> and <end> bits */
 482static inline target_ulong MASK(uint32_t start, uint32_t end)
 483{
 484    target_ulong ret;
 485
 486#if defined(TARGET_PPC64)
 487    if (likely(start == 0)) {
 488        ret = UINT64_MAX << (63 - end);
 489    } else if (likely(end == 63)) {
 490        ret = UINT64_MAX >> start;
 491    }
 492#else
 493    if (likely(start == 0)) {
 494        ret = UINT32_MAX << (31  - end);
 495    } else if (likely(end == 31)) {
 496        ret = UINT32_MAX >> start;
 497    }
 498#endif
 499    else {
 500        ret = (((target_ulong)(-1ULL)) >> (start)) ^
 501            (((target_ulong)(-1ULL) >> (end)) >> 1);
 502        if (unlikely(start > end))
 503            return ~ret;
 504    }
 505
 506    return ret;
 507}
 508
 509EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
 510EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
 511EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
 512EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
 513EXTRACT_HELPER_SPLIT(xC, 3, 1,  6, 5);
 514EXTRACT_HELPER(DM, 8, 2);
 515EXTRACT_HELPER(UIM, 16, 2);
 516EXTRACT_HELPER(SHW, 8, 2);
 517EXTRACT_HELPER(SP, 19, 2);
 518/*****************************************************************************/
 519/* PowerPC instructions table                                                */
 520
 521#if defined(DO_PPC_STATISTICS)
 522#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
 523{                                                                             \
 524    .opc1 = op1,                                                              \
 525    .opc2 = op2,                                                              \
 526    .opc3 = op3,                                                              \
 527    .pad  = { 0, },                                                           \
 528    .handler = {                                                              \
 529        .inval1  = invl,                                                      \
 530        .type = _typ,                                                         \
 531        .type2 = _typ2,                                                       \
 532        .handler = &gen_##name,                                               \
 533        .oname = stringify(name),                                             \
 534    },                                                                        \
 535    .oname = stringify(name),                                                 \
 536}
 537#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
 538{                                                                             \
 539    .opc1 = op1,                                                              \
 540    .opc2 = op2,                                                              \
 541    .opc3 = op3,                                                              \
 542    .pad  = { 0, },                                                           \
 543    .handler = {                                                              \
 544        .inval1  = invl1,                                                     \
 545        .inval2  = invl2,                                                     \
 546        .type = _typ,                                                         \
 547        .type2 = _typ2,                                                       \
 548        .handler = &gen_##name,                                               \
 549        .oname = stringify(name),                                             \
 550    },                                                                        \
 551    .oname = stringify(name),                                                 \
 552}
 553#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
 554{                                                                             \
 555    .opc1 = op1,                                                              \
 556    .opc2 = op2,                                                              \
 557    .opc3 = op3,                                                              \
 558    .pad  = { 0, },                                                           \
 559    .handler = {                                                              \
 560        .inval1  = invl,                                                      \
 561        .type = _typ,                                                         \
 562        .type2 = _typ2,                                                       \
 563        .handler = &gen_##name,                                               \
 564        .oname = onam,                                                        \
 565    },                                                                        \
 566    .oname = onam,                                                            \
 567}
 568#else
 569#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
 570{                                                                             \
 571    .opc1 = op1,                                                              \
 572    .opc2 = op2,                                                              \
 573    .opc3 = op3,                                                              \
 574    .pad  = { 0, },                                                           \
 575    .handler = {                                                              \
 576        .inval1  = invl,                                                      \
 577        .type = _typ,                                                         \
 578        .type2 = _typ2,                                                       \
 579        .handler = &gen_##name,                                               \
 580    },                                                                        \
 581    .oname = stringify(name),                                                 \
 582}
 583#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
 584{                                                                             \
 585    .opc1 = op1,                                                              \
 586    .opc2 = op2,                                                              \
 587    .opc3 = op3,                                                              \
 588    .pad  = { 0, },                                                           \
 589    .handler = {                                                              \
 590        .inval1  = invl1,                                                     \
 591        .inval2  = invl2,                                                     \
 592        .type = _typ,                                                         \
 593        .type2 = _typ2,                                                       \
 594        .handler = &gen_##name,                                               \
 595    },                                                                        \
 596    .oname = stringify(name),                                                 \
 597}
 598#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
 599{                                                                             \
 600    .opc1 = op1,                                                              \
 601    .opc2 = op2,                                                              \
 602    .opc3 = op3,                                                              \
 603    .pad  = { 0, },                                                           \
 604    .handler = {                                                              \
 605        .inval1  = invl,                                                      \
 606        .type = _typ,                                                         \
 607        .type2 = _typ2,                                                       \
 608        .handler = &gen_##name,                                               \
 609    },                                                                        \
 610    .oname = onam,                                                            \
 611}
 612#endif
 613
 614/* SPR load/store helpers */
 615static inline void gen_load_spr(TCGv t, int reg)
 616{
 617    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 618}
 619
 620static inline void gen_store_spr(int reg, TCGv t)
 621{
 622    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 623}
 624
 625/* Invalid instruction */
 626static void gen_invalid(DisasContext *ctx)
 627{
 628    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
 629}
 630
 631static opc_handler_t invalid_handler = {
 632    .inval1  = 0xFFFFFFFF,
 633    .inval2  = 0xFFFFFFFF,
 634    .type    = PPC_NONE,
 635    .type2   = PPC_NONE,
 636    .handler = gen_invalid,
 637};
 638
 639/***                           Integer comparison                          ***/
 640
 641static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
 642{
 643    TCGv t0 = tcg_temp_new();
 644    TCGv_i32 t1 = tcg_temp_new_i32();
 645
 646    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
 647
 648    tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
 649    tcg_gen_trunc_tl_i32(t1, t0);
 650    tcg_gen_shli_i32(t1, t1, CRF_LT);
 651    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 652
 653    tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
 654    tcg_gen_trunc_tl_i32(t1, t0);
 655    tcg_gen_shli_i32(t1, t1, CRF_GT);
 656    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 657
 658    tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
 659    tcg_gen_trunc_tl_i32(t1, t0);
 660    tcg_gen_shli_i32(t1, t1, CRF_EQ);
 661    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 662
 663    tcg_temp_free(t0);
 664    tcg_temp_free_i32(t1);
 665}
 666
 667static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
 668{
 669    TCGv t0 = tcg_const_tl(arg1);
 670    gen_op_cmp(arg0, t0, s, crf);
 671    tcg_temp_free(t0);
 672}
 673
 674static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
 675{
 676    TCGv t0, t1;
 677    t0 = tcg_temp_new();
 678    t1 = tcg_temp_new();
 679    if (s) {
 680        tcg_gen_ext32s_tl(t0, arg0);
 681        tcg_gen_ext32s_tl(t1, arg1);
 682    } else {
 683        tcg_gen_ext32u_tl(t0, arg0);
 684        tcg_gen_ext32u_tl(t1, arg1);
 685    }
 686    gen_op_cmp(t0, t1, s, crf);
 687    tcg_temp_free(t1);
 688    tcg_temp_free(t0);
 689}
 690
 691static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
 692{
 693    TCGv t0 = tcg_const_tl(arg1);
 694    gen_op_cmp32(arg0, t0, s, crf);
 695    tcg_temp_free(t0);
 696}
 697
 698static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
 699{
 700    if (NARROW_MODE(ctx)) {
 701        gen_op_cmpi32(reg, 0, 1, 0);
 702    } else {
 703        gen_op_cmpi(reg, 0, 1, 0);
 704    }
 705}
 706
 707/* cmp */
 708static void gen_cmp(DisasContext *ctx)
 709{
 710    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 711        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 712                   1, crfD(ctx->opcode));
 713    } else {
 714        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 715                     1, crfD(ctx->opcode));
 716    }
 717}
 718
 719/* cmpi */
 720static void gen_cmpi(DisasContext *ctx)
 721{
 722    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 723        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
 724                    1, crfD(ctx->opcode));
 725    } else {
 726        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
 727                      1, crfD(ctx->opcode));
 728    }
 729}
 730
 731/* cmpl */
 732static void gen_cmpl(DisasContext *ctx)
 733{
 734    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 735        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 736                   0, crfD(ctx->opcode));
 737    } else {
 738        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 739                     0, crfD(ctx->opcode));
 740    }
 741}
 742
 743/* cmpli */
 744static void gen_cmpli(DisasContext *ctx)
 745{
 746    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 747        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
 748                    0, crfD(ctx->opcode));
 749    } else {
 750        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
 751                      0, crfD(ctx->opcode));
 752    }
 753}
 754
 755/* isel (PowerPC 2.03 specification) */
 756static void gen_isel(DisasContext *ctx)
 757{
 758    TCGLabel *l1, *l2;
 759    uint32_t bi = rC(ctx->opcode);
 760    uint32_t mask;
 761    TCGv_i32 t0;
 762
 763    l1 = gen_new_label();
 764    l2 = gen_new_label();
 765
 766    mask = 0x08 >> (bi & 0x03);
 767    t0 = tcg_temp_new_i32();
 768    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
 769    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
 770    if (rA(ctx->opcode) == 0)
 771        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
 772    else
 773        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
 774    tcg_gen_br(l2);
 775    gen_set_label(l1);
 776    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
 777    gen_set_label(l2);
 778    tcg_temp_free_i32(t0);
 779}
 780
 781/* cmpb: PowerPC 2.05 specification */
 782static void gen_cmpb(DisasContext *ctx)
 783{
 784    gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
 785                    cpu_gpr[rB(ctx->opcode)]);
 786}
 787
 788/***                           Integer arithmetic                          ***/
 789
 790static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
 791                                           TCGv arg1, TCGv arg2, int sub)
 792{
 793    TCGv t0 = tcg_temp_new();
 794
 795    tcg_gen_xor_tl(cpu_ov, arg0, arg2);
 796    tcg_gen_xor_tl(t0, arg1, arg2);
 797    if (sub) {
 798        tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
 799    } else {
 800        tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
 801    }
 802    tcg_temp_free(t0);
 803    if (NARROW_MODE(ctx)) {
 804        tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
 805    }
 806    tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
 807    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
 808}
 809
 810/* Common add function */
 811static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
 812                                    TCGv arg2, bool add_ca, bool compute_ca,
 813                                    bool compute_ov, bool compute_rc0)
 814{
 815    TCGv t0 = ret;
 816
 817    if (compute_ca || compute_ov) {
 818        t0 = tcg_temp_new();
 819    }
 820
 821    if (compute_ca) {
 822        if (NARROW_MODE(ctx)) {
 823            /* Caution: a non-obvious corner case of the spec is that we
 824               must produce the *entire* 64-bit addition, but produce the
 825               carry into bit 32.  */
 826            TCGv t1 = tcg_temp_new();
 827            tcg_gen_xor_tl(t1, arg1, arg2);        /* add without carry */
 828            tcg_gen_add_tl(t0, arg1, arg2);
 829            if (add_ca) {
 830                tcg_gen_add_tl(t0, t0, cpu_ca);
 831            }
 832            tcg_gen_xor_tl(cpu_ca, t0, t1);        /* bits changed w/ carry */
 833            tcg_temp_free(t1);
 834            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);   /* extract bit 32 */
 835            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
 836        } else {
 837            TCGv zero = tcg_const_tl(0);
 838            if (add_ca) {
 839                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
 840                tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
 841            } else {
 842                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
 843            }
 844            tcg_temp_free(zero);
 845        }
 846    } else {
 847        tcg_gen_add_tl(t0, arg1, arg2);
 848        if (add_ca) {
 849            tcg_gen_add_tl(t0, t0, cpu_ca);
 850        }
 851    }
 852
 853    if (compute_ov) {
 854        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
 855    }
 856    if (unlikely(compute_rc0)) {
 857        gen_set_Rc0(ctx, t0);
 858    }
 859
 860    if (!TCGV_EQUAL(t0, ret)) {
 861        tcg_gen_mov_tl(ret, t0);
 862        tcg_temp_free(t0);
 863    }
 864}
 865/* Add functions with two operands */
 866#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
 867static void glue(gen_, name)(DisasContext *ctx)                               \
 868{                                                                             \
 869    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
 870                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
 871                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
 872}
 873/* Add functions with one operand and one immediate */
 874#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
 875                                add_ca, compute_ca, compute_ov)               \
 876static void glue(gen_, name)(DisasContext *ctx)                               \
 877{                                                                             \
 878    TCGv t0 = tcg_const_tl(const_val);                                        \
 879    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
 880                     cpu_gpr[rA(ctx->opcode)], t0,                            \
 881                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
 882    tcg_temp_free(t0);                                                        \
 883}
 884
 885/* add  add.  addo  addo. */
 886GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
 887GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
 888/* addc  addc.  addco  addco. */
 889GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
 890GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
 891/* adde  adde.  addeo  addeo. */
 892GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
 893GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
 894/* addme  addme.  addmeo  addmeo.  */
 895GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
 896GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
 897/* addze  addze.  addzeo  addzeo.*/
 898GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
 899GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
 900/* addi */
 901static void gen_addi(DisasContext *ctx)
 902{
 903    target_long simm = SIMM(ctx->opcode);
 904
 905    if (rA(ctx->opcode) == 0) {
 906        /* li case */
 907        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
 908    } else {
 909        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
 910                        cpu_gpr[rA(ctx->opcode)], simm);
 911    }
 912}
 913/* addic  addic.*/
 914static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
 915{
 916    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
 917    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
 918                     c, 0, 1, 0, compute_rc0);
 919    tcg_temp_free(c);
 920}
 921
 922static void gen_addic(DisasContext *ctx)
 923{
 924    gen_op_addic(ctx, 0);
 925}
 926
 927static void gen_addic_(DisasContext *ctx)
 928{
 929    gen_op_addic(ctx, 1);
 930}
 931
 932/* addis */
 933static void gen_addis(DisasContext *ctx)
 934{
 935    target_long simm = SIMM(ctx->opcode);
 936
 937    if (rA(ctx->opcode) == 0) {
 938        /* lis case */
 939        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
 940    } else {
 941        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
 942                        cpu_gpr[rA(ctx->opcode)], simm << 16);
 943    }
 944}
 945
 946static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
 947                                     TCGv arg2, int sign, int compute_ov)
 948{
 949    TCGLabel *l1 = gen_new_label();
 950    TCGLabel *l2 = gen_new_label();
 951    TCGv_i32 t0 = tcg_temp_local_new_i32();
 952    TCGv_i32 t1 = tcg_temp_local_new_i32();
 953
 954    tcg_gen_trunc_tl_i32(t0, arg1);
 955    tcg_gen_trunc_tl_i32(t1, arg2);
 956    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
 957    if (sign) {
 958        TCGLabel *l3 = gen_new_label();
 959        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
 960        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
 961        gen_set_label(l3);
 962        tcg_gen_div_i32(t0, t0, t1);
 963    } else {
 964        tcg_gen_divu_i32(t0, t0, t1);
 965    }
 966    if (compute_ov) {
 967        tcg_gen_movi_tl(cpu_ov, 0);
 968    }
 969    tcg_gen_br(l2);
 970    gen_set_label(l1);
 971    if (sign) {
 972        tcg_gen_sari_i32(t0, t0, 31);
 973    } else {
 974        tcg_gen_movi_i32(t0, 0);
 975    }
 976    if (compute_ov) {
 977        tcg_gen_movi_tl(cpu_ov, 1);
 978        tcg_gen_movi_tl(cpu_so, 1);
 979    }
 980    gen_set_label(l2);
 981    tcg_gen_extu_i32_tl(ret, t0);
 982    tcg_temp_free_i32(t0);
 983    tcg_temp_free_i32(t1);
 984    if (unlikely(Rc(ctx->opcode) != 0))
 985        gen_set_Rc0(ctx, ret);
 986}
 987/* Div functions */
 988#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
 989static void glue(gen_, name)(DisasContext *ctx)                                       \
 990{                                                                             \
 991    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
 992                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
 993                     sign, compute_ov);                                       \
 994}
 995/* divwu  divwu.  divwuo  divwuo.   */
 996GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
 997GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
 998/* divw  divw.  divwo  divwo.   */
 999GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1000GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1001
1002/* div[wd]eu[o][.] */
1003#define GEN_DIVE(name, hlpr, compute_ov)                                      \
1004static void gen_##name(DisasContext *ctx)                                     \
1005{                                                                             \
1006    TCGv_i32 t0 = tcg_const_i32(compute_ov);                                  \
1007    gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
1008                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
1009    tcg_temp_free_i32(t0);                                                    \
1010    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
1011        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1012    }                                                                         \
1013}
1014
1015GEN_DIVE(divweu, divweu, 0);
1016GEN_DIVE(divweuo, divweu, 1);
1017GEN_DIVE(divwe, divwe, 0);
1018GEN_DIVE(divweo, divwe, 1);
1019
1020#if defined(TARGET_PPC64)
1021static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1022                                     TCGv arg2, int sign, int compute_ov)
1023{
1024    TCGLabel *l1 = gen_new_label();
1025    TCGLabel *l2 = gen_new_label();
1026
1027    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1028    if (sign) {
1029        TCGLabel *l3 = gen_new_label();
1030        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1031        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1032        gen_set_label(l3);
1033        tcg_gen_div_i64(ret, arg1, arg2);
1034    } else {
1035        tcg_gen_divu_i64(ret, arg1, arg2);
1036    }
1037    if (compute_ov) {
1038        tcg_gen_movi_tl(cpu_ov, 0);
1039    }
1040    tcg_gen_br(l2);
1041    gen_set_label(l1);
1042    if (sign) {
1043        tcg_gen_sari_i64(ret, arg1, 63);
1044    } else {
1045        tcg_gen_movi_i64(ret, 0);
1046    }
1047    if (compute_ov) {
1048        tcg_gen_movi_tl(cpu_ov, 1);
1049        tcg_gen_movi_tl(cpu_so, 1);
1050    }
1051    gen_set_label(l2);
1052    if (unlikely(Rc(ctx->opcode) != 0))
1053        gen_set_Rc0(ctx, ret);
1054}
1055#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
1056static void glue(gen_, name)(DisasContext *ctx)                                       \
1057{                                                                             \
1058    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1059                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1060                      sign, compute_ov);                                      \
1061}
1062/* divwu  divwu.  divwuo  divwuo.   */
1063GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1064GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1065/* divw  divw.  divwo  divwo.   */
1066GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1067GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1068
1069GEN_DIVE(divdeu, divdeu, 0);
1070GEN_DIVE(divdeuo, divdeu, 1);
1071GEN_DIVE(divde, divde, 0);
1072GEN_DIVE(divdeo, divde, 1);
1073#endif
1074
1075/* mulhw  mulhw. */
1076static void gen_mulhw(DisasContext *ctx)
1077{
1078    TCGv_i32 t0 = tcg_temp_new_i32();
1079    TCGv_i32 t1 = tcg_temp_new_i32();
1080
1081    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1082    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1083    tcg_gen_muls2_i32(t0, t1, t0, t1);
1084    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1085    tcg_temp_free_i32(t0);
1086    tcg_temp_free_i32(t1);
1087    if (unlikely(Rc(ctx->opcode) != 0))
1088        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1089}
1090
1091/* mulhwu  mulhwu.  */
1092static void gen_mulhwu(DisasContext *ctx)
1093{
1094    TCGv_i32 t0 = tcg_temp_new_i32();
1095    TCGv_i32 t1 = tcg_temp_new_i32();
1096
1097    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1098    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1099    tcg_gen_mulu2_i32(t0, t1, t0, t1);
1100    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1101    tcg_temp_free_i32(t0);
1102    tcg_temp_free_i32(t1);
1103    if (unlikely(Rc(ctx->opcode) != 0))
1104        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1105}
1106
1107/* mullw  mullw. */
1108static void gen_mullw(DisasContext *ctx)
1109{
1110#if defined(TARGET_PPC64)
1111    TCGv_i64 t0, t1;
1112    t0 = tcg_temp_new_i64();
1113    t1 = tcg_temp_new_i64();
1114    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1115    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1116    tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1117    tcg_temp_free(t0);
1118    tcg_temp_free(t1);
1119#else
1120    tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1121                    cpu_gpr[rB(ctx->opcode)]);
1122#endif
1123    if (unlikely(Rc(ctx->opcode) != 0))
1124        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1125}
1126
1127/* mullwo  mullwo. */
1128static void gen_mullwo(DisasContext *ctx)
1129{
1130    TCGv_i32 t0 = tcg_temp_new_i32();
1131    TCGv_i32 t1 = tcg_temp_new_i32();
1132
1133    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1134    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1135    tcg_gen_muls2_i32(t0, t1, t0, t1);
1136#if defined(TARGET_PPC64)
1137    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1138#else
1139    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
1140#endif
1141
1142    tcg_gen_sari_i32(t0, t0, 31);
1143    tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
1144    tcg_gen_extu_i32_tl(cpu_ov, t0);
1145    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1146
1147    tcg_temp_free_i32(t0);
1148    tcg_temp_free_i32(t1);
1149    if (unlikely(Rc(ctx->opcode) != 0))
1150        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1151}
1152
1153/* mulli */
1154static void gen_mulli(DisasContext *ctx)
1155{
1156    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1157                    SIMM(ctx->opcode));
1158}
1159
1160#if defined(TARGET_PPC64)
1161/* mulhd  mulhd. */
1162static void gen_mulhd(DisasContext *ctx)
1163{
1164    TCGv lo = tcg_temp_new();
1165    tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1166                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1167    tcg_temp_free(lo);
1168    if (unlikely(Rc(ctx->opcode) != 0)) {
1169        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1170    }
1171}
1172
1173/* mulhdu  mulhdu. */
1174static void gen_mulhdu(DisasContext *ctx)
1175{
1176    TCGv lo = tcg_temp_new();
1177    tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1178                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1179    tcg_temp_free(lo);
1180    if (unlikely(Rc(ctx->opcode) != 0)) {
1181        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1182    }
1183}
1184
1185/* mulld  mulld. */
1186static void gen_mulld(DisasContext *ctx)
1187{
1188    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1189                   cpu_gpr[rB(ctx->opcode)]);
1190    if (unlikely(Rc(ctx->opcode) != 0))
1191        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1192}
1193
1194/* mulldo  mulldo. */
1195static void gen_mulldo(DisasContext *ctx)
1196{
1197    TCGv_i64 t0 = tcg_temp_new_i64();
1198    TCGv_i64 t1 = tcg_temp_new_i64();
1199
1200    tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
1201                      cpu_gpr[rB(ctx->opcode)]);
1202    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
1203
1204    tcg_gen_sari_i64(t0, t0, 63);
1205    tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
1206    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1207
1208    tcg_temp_free_i64(t0);
1209    tcg_temp_free_i64(t1);
1210
1211    if (unlikely(Rc(ctx->opcode) != 0)) {
1212        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1213    }
1214}
1215#endif
1216
1217/* Common subf function */
1218static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1219                                     TCGv arg2, bool add_ca, bool compute_ca,
1220                                     bool compute_ov, bool compute_rc0)
1221{
1222    TCGv t0 = ret;
1223
1224    if (compute_ca || compute_ov) {
1225        t0 = tcg_temp_new();
1226    }
1227
1228    if (compute_ca) {
1229        /* dest = ~arg1 + arg2 [+ ca].  */
1230        if (NARROW_MODE(ctx)) {
1231            /* Caution: a non-obvious corner case of the spec is that we
1232               must produce the *entire* 64-bit addition, but produce the
1233               carry into bit 32.  */
1234            TCGv inv1 = tcg_temp_new();
1235            TCGv t1 = tcg_temp_new();
1236            tcg_gen_not_tl(inv1, arg1);
1237            if (add_ca) {
1238                tcg_gen_add_tl(t0, arg2, cpu_ca);
1239            } else {
1240                tcg_gen_addi_tl(t0, arg2, 1);
1241            }
1242            tcg_gen_xor_tl(t1, arg2, inv1);         /* add without carry */
1243            tcg_gen_add_tl(t0, t0, inv1);
1244            tcg_temp_free(inv1);
1245            tcg_gen_xor_tl(cpu_ca, t0, t1);         /* bits changes w/ carry */
1246            tcg_temp_free(t1);
1247            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);    /* extract bit 32 */
1248            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
1249        } else if (add_ca) {
1250            TCGv zero, inv1 = tcg_temp_new();
1251            tcg_gen_not_tl(inv1, arg1);
1252            zero = tcg_const_tl(0);
1253            tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
1254            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
1255            tcg_temp_free(zero);
1256            tcg_temp_free(inv1);
1257        } else {
1258            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
1259            tcg_gen_sub_tl(t0, arg2, arg1);
1260        }
1261    } else if (add_ca) {
1262        /* Since we're ignoring carry-out, we can simplify the
1263           standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.  */
1264        tcg_gen_sub_tl(t0, arg2, arg1);
1265        tcg_gen_add_tl(t0, t0, cpu_ca);
1266        tcg_gen_subi_tl(t0, t0, 1);
1267    } else {
1268        tcg_gen_sub_tl(t0, arg2, arg1);
1269    }
1270
1271    if (compute_ov) {
1272        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1273    }
1274    if (unlikely(compute_rc0)) {
1275        gen_set_Rc0(ctx, t0);
1276    }
1277
1278    if (!TCGV_EQUAL(t0, ret)) {
1279        tcg_gen_mov_tl(ret, t0);
1280        tcg_temp_free(t0);
1281    }
1282}
1283/* Sub functions with Two operands functions */
1284#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1285static void glue(gen_, name)(DisasContext *ctx)                               \
1286{                                                                             \
1287    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1288                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1289                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1290}
1291/* Sub functions with one operand and one immediate */
1292#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1293                                add_ca, compute_ca, compute_ov)               \
1294static void glue(gen_, name)(DisasContext *ctx)                               \
1295{                                                                             \
1296    TCGv t0 = tcg_const_tl(const_val);                                        \
1297    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1298                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1299                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1300    tcg_temp_free(t0);                                                        \
1301}
1302/* subf  subf.  subfo  subfo. */
1303GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1304GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1305/* subfc  subfc.  subfco  subfco. */
1306GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1307GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1308/* subfe  subfe.  subfeo  subfo. */
1309GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1310GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1311/* subfme  subfme.  subfmeo  subfmeo.  */
1312GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1313GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1314/* subfze  subfze.  subfzeo  subfzeo.*/
1315GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1316GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1317
1318/* subfic */
1319static void gen_subfic(DisasContext *ctx)
1320{
1321    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1322    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1323                      c, 0, 1, 0, 0);
1324    tcg_temp_free(c);
1325}
1326
1327/* neg neg. nego nego. */
1328static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
1329{
1330    TCGv zero = tcg_const_tl(0);
1331    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1332                      zero, 0, 0, compute_ov, Rc(ctx->opcode));
1333    tcg_temp_free(zero);
1334}
1335
1336static void gen_neg(DisasContext *ctx)
1337{
1338    gen_op_arith_neg(ctx, 0);
1339}
1340
1341static void gen_nego(DisasContext *ctx)
1342{
1343    gen_op_arith_neg(ctx, 1);
1344}
1345
1346/***                            Integer logical                            ***/
1347#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1348static void glue(gen_, name)(DisasContext *ctx)                                       \
1349{                                                                             \
1350    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1351       cpu_gpr[rB(ctx->opcode)]);                                             \
1352    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1353        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1354}
1355
1356#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1357static void glue(gen_, name)(DisasContext *ctx)                                       \
1358{                                                                             \
1359    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1360    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1361        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1362}
1363
1364/* and & and. */
1365GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1366/* andc & andc. */
1367GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1368
1369/* andi. */
1370static void gen_andi_(DisasContext *ctx)
1371{
1372    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1373    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1374}
1375
1376/* andis. */
1377static void gen_andis_(DisasContext *ctx)
1378{
1379    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1380    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1381}
1382
1383/* cntlzw */
1384static void gen_cntlzw(DisasContext *ctx)
1385{
1386    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1387    if (unlikely(Rc(ctx->opcode) != 0))
1388        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1389}
1390/* eqv & eqv. */
1391GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1392/* extsb & extsb. */
1393GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1394/* extsh & extsh. */
1395GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1396/* nand & nand. */
1397GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1398/* nor & nor. */
1399GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1400
1401/* or & or. */
1402static void gen_or(DisasContext *ctx)
1403{
1404    int rs, ra, rb;
1405
1406    rs = rS(ctx->opcode);
1407    ra = rA(ctx->opcode);
1408    rb = rB(ctx->opcode);
1409    /* Optimisation for mr. ri case */
1410    if (rs != ra || rs != rb) {
1411        if (rs != rb)
1412            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1413        else
1414            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1415        if (unlikely(Rc(ctx->opcode) != 0))
1416            gen_set_Rc0(ctx, cpu_gpr[ra]);
1417    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1418        gen_set_Rc0(ctx, cpu_gpr[rs]);
1419#if defined(TARGET_PPC64)
1420    } else {
1421        int prio = 0;
1422
1423        switch (rs) {
1424        case 1:
1425            /* Set process priority to low */
1426            prio = 2;
1427            break;
1428        case 6:
1429            /* Set process priority to medium-low */
1430            prio = 3;
1431            break;
1432        case 2:
1433            /* Set process priority to normal */
1434            prio = 4;
1435            break;
1436#if !defined(CONFIG_USER_ONLY)
1437        case 31:
1438            if (!ctx->pr) {
1439                /* Set process priority to very low */
1440                prio = 1;
1441            }
1442            break;
1443        case 5:
1444            if (!ctx->pr) {
1445                /* Set process priority to medium-hight */
1446                prio = 5;
1447            }
1448            break;
1449        case 3:
1450            if (!ctx->pr) {
1451                /* Set process priority to high */
1452                prio = 6;
1453            }
1454            break;
1455        case 7:
1456            if (ctx->hv) {
1457                /* Set process priority to very high */
1458                prio = 7;
1459            }
1460            break;
1461#endif
1462        default:
1463            /* nop */
1464            break;
1465        }
1466        if (prio) {
1467            TCGv t0 = tcg_temp_new();
1468            gen_load_spr(t0, SPR_PPR);
1469            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1470            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1471            gen_store_spr(SPR_PPR, t0);
1472            tcg_temp_free(t0);
1473        }
1474#endif
1475    }
1476}
1477/* orc & orc. */
1478GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1479
1480/* xor & xor. */
1481static void gen_xor(DisasContext *ctx)
1482{
1483    /* Optimisation for "set to zero" case */
1484    if (rS(ctx->opcode) != rB(ctx->opcode))
1485        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1486    else
1487        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1488    if (unlikely(Rc(ctx->opcode) != 0))
1489        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1490}
1491
1492/* ori */
1493static void gen_ori(DisasContext *ctx)
1494{
1495    target_ulong uimm = UIMM(ctx->opcode);
1496
1497    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1498        /* NOP */
1499        /* XXX: should handle special NOPs for POWER series */
1500        return;
1501    }
1502    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1503}
1504
1505/* oris */
1506static void gen_oris(DisasContext *ctx)
1507{
1508    target_ulong uimm = UIMM(ctx->opcode);
1509
1510    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1511        /* NOP */
1512        return;
1513    }
1514    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1515}
1516
1517/* xori */
1518static void gen_xori(DisasContext *ctx)
1519{
1520    target_ulong uimm = UIMM(ctx->opcode);
1521
1522    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1523        /* NOP */
1524        return;
1525    }
1526    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1527}
1528
1529/* xoris */
1530static void gen_xoris(DisasContext *ctx)
1531{
1532    target_ulong uimm = UIMM(ctx->opcode);
1533
1534    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1535        /* NOP */
1536        return;
1537    }
1538    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1539}
1540
1541/* popcntb : PowerPC 2.03 specification */
1542static void gen_popcntb(DisasContext *ctx)
1543{
1544    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1545}
1546
1547static void gen_popcntw(DisasContext *ctx)
1548{
1549    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1550}
1551
1552#if defined(TARGET_PPC64)
1553/* popcntd: PowerPC 2.06 specification */
1554static void gen_popcntd(DisasContext *ctx)
1555{
1556    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1557}
1558#endif
1559
1560/* prtyw: PowerPC 2.05 specification */
1561static void gen_prtyw(DisasContext *ctx)
1562{
1563    TCGv ra = cpu_gpr[rA(ctx->opcode)];
1564    TCGv rs = cpu_gpr[rS(ctx->opcode)];
1565    TCGv t0 = tcg_temp_new();
1566    tcg_gen_shri_tl(t0, rs, 16);
1567    tcg_gen_xor_tl(ra, rs, t0);
1568    tcg_gen_shri_tl(t0, ra, 8);
1569    tcg_gen_xor_tl(ra, ra, t0);
1570    tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
1571    tcg_temp_free(t0);
1572}
1573
1574#if defined(TARGET_PPC64)
1575/* prtyd: PowerPC 2.05 specification */
1576static void gen_prtyd(DisasContext *ctx)
1577{
1578    TCGv ra = cpu_gpr[rA(ctx->opcode)];
1579    TCGv rs = cpu_gpr[rS(ctx->opcode)];
1580    TCGv t0 = tcg_temp_new();
1581    tcg_gen_shri_tl(t0, rs, 32);
1582    tcg_gen_xor_tl(ra, rs, t0);
1583    tcg_gen_shri_tl(t0, ra, 16);
1584    tcg_gen_xor_tl(ra, ra, t0);
1585    tcg_gen_shri_tl(t0, ra, 8);
1586    tcg_gen_xor_tl(ra, ra, t0);
1587    tcg_gen_andi_tl(ra, ra, 1);
1588    tcg_temp_free(t0);
1589}
1590#endif
1591
1592#if defined(TARGET_PPC64)
1593/* bpermd */
1594static void gen_bpermd(DisasContext *ctx)
1595{
1596    gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
1597                      cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1598}
1599#endif
1600
1601#if defined(TARGET_PPC64)
1602/* extsw & extsw. */
1603GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1604
1605/* cntlzd */
1606static void gen_cntlzd(DisasContext *ctx)
1607{
1608    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1609    if (unlikely(Rc(ctx->opcode) != 0))
1610        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1611}
1612#endif
1613
1614/***                             Integer rotate                            ***/
1615
1616/* rlwimi & rlwimi. */
1617static void gen_rlwimi(DisasContext *ctx)
1618{
1619    uint32_t mb, me, sh;
1620
1621    mb = MB(ctx->opcode);
1622    me = ME(ctx->opcode);
1623    sh = SH(ctx->opcode);
1624    if (likely(sh == (31-me) && mb <= me)) {
1625        tcg_gen_deposit_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1626                           cpu_gpr[rS(ctx->opcode)], sh, me - mb + 1);
1627    } else {
1628        target_ulong mask;
1629        TCGv t1;
1630        TCGv t0 = tcg_temp_new();
1631#if defined(TARGET_PPC64)
1632        tcg_gen_deposit_i64(t0, cpu_gpr[rS(ctx->opcode)],
1633            cpu_gpr[rS(ctx->opcode)], 32, 32);
1634        tcg_gen_rotli_i64(t0, t0, sh);
1635#else
1636        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1637#endif
1638#if defined(TARGET_PPC64)
1639        mb += 32;
1640        me += 32;
1641#endif
1642        mask = MASK(mb, me);
1643        t1 = tcg_temp_new();
1644        tcg_gen_andi_tl(t0, t0, mask);
1645        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1646        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1647        tcg_temp_free(t0);
1648        tcg_temp_free(t1);
1649    }
1650    if (unlikely(Rc(ctx->opcode) != 0))
1651        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1652}
1653
1654/* rlwinm & rlwinm. */
1655static void gen_rlwinm(DisasContext *ctx)
1656{
1657    uint32_t mb, me, sh;
1658
1659    sh = SH(ctx->opcode);
1660    mb = MB(ctx->opcode);
1661    me = ME(ctx->opcode);
1662
1663    if (likely(mb == 0 && me == (31 - sh))) {
1664        if (likely(sh == 0)) {
1665            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1666        } else {
1667            TCGv t0 = tcg_temp_new();
1668            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1669            tcg_gen_shli_tl(t0, t0, sh);
1670            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1671            tcg_temp_free(t0);
1672        }
1673    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1674        TCGv t0 = tcg_temp_new();
1675        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1676        tcg_gen_shri_tl(t0, t0, mb);
1677        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1678        tcg_temp_free(t0);
1679    } else if (likely(mb == 0 && me == 31)) {
1680        TCGv_i32 t0 = tcg_temp_new_i32();
1681        tcg_gen_trunc_tl_i32(t0, cpu_gpr[rS(ctx->opcode)]);
1682        tcg_gen_rotli_i32(t0, t0, sh);
1683        tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t0);
1684        tcg_temp_free_i32(t0);
1685    } else {
1686        TCGv t0 = tcg_temp_new();
1687#if defined(TARGET_PPC64)
1688        tcg_gen_deposit_i64(t0, cpu_gpr[rS(ctx->opcode)],
1689            cpu_gpr[rS(ctx->opcode)], 32, 32);
1690        tcg_gen_rotli_i64(t0, t0, sh);
1691#else
1692        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1693#endif
1694#if defined(TARGET_PPC64)
1695        mb += 32;
1696        me += 32;
1697#endif
1698        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1699        tcg_temp_free(t0);
1700    }
1701    if (unlikely(Rc(ctx->opcode) != 0))
1702        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1703}
1704
1705/* rlwnm & rlwnm. */
1706static void gen_rlwnm(DisasContext *ctx)
1707{
1708    uint32_t mb, me;
1709    mb = MB(ctx->opcode);
1710    me = ME(ctx->opcode);
1711
1712    if (likely(mb == 0 && me == 31)) {
1713        TCGv_i32 t0, t1;
1714        t0 = tcg_temp_new_i32();
1715        t1 = tcg_temp_new_i32();
1716        tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);
1717        tcg_gen_trunc_tl_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1718        tcg_gen_andi_i32(t0, t0, 0x1f);
1719        tcg_gen_rotl_i32(t1, t1, t0);
1720        tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t1);
1721        tcg_temp_free_i32(t0);
1722        tcg_temp_free_i32(t1);
1723    } else {
1724        TCGv t0;
1725#if defined(TARGET_PPC64)
1726        TCGv t1;
1727#endif
1728
1729        t0 = tcg_temp_new();
1730        tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1731#if defined(TARGET_PPC64)
1732        t1 = tcg_temp_new_i64();
1733        tcg_gen_deposit_i64(t1, cpu_gpr[rS(ctx->opcode)],
1734                            cpu_gpr[rS(ctx->opcode)], 32, 32);
1735        tcg_gen_rotl_i64(t0, t1, t0);
1736        tcg_temp_free_i64(t1);
1737#else
1738        tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1739#endif
1740        if (unlikely(mb != 0 || me != 31)) {
1741#if defined(TARGET_PPC64)
1742            mb += 32;
1743            me += 32;
1744#endif
1745            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1746        } else {
1747            tcg_gen_andi_tl(t0, t0, MASK(32, 63));
1748            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1749        }
1750        tcg_temp_free(t0);
1751    }
1752    if (unlikely(Rc(ctx->opcode) != 0))
1753        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1754}
1755
1756#if defined(TARGET_PPC64)
1757#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1758static void glue(gen_, name##0)(DisasContext *ctx)                            \
1759{                                                                             \
1760    gen_##name(ctx, 0);                                                       \
1761}                                                                             \
1762                                                                              \
1763static void glue(gen_, name##1)(DisasContext *ctx)                            \
1764{                                                                             \
1765    gen_##name(ctx, 1);                                                       \
1766}
1767#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1768static void glue(gen_, name##0)(DisasContext *ctx)                            \
1769{                                                                             \
1770    gen_##name(ctx, 0, 0);                                                    \
1771}                                                                             \
1772                                                                              \
1773static void glue(gen_, name##1)(DisasContext *ctx)                            \
1774{                                                                             \
1775    gen_##name(ctx, 0, 1);                                                    \
1776}                                                                             \
1777                                                                              \
1778static void glue(gen_, name##2)(DisasContext *ctx)                            \
1779{                                                                             \
1780    gen_##name(ctx, 1, 0);                                                    \
1781}                                                                             \
1782                                                                              \
1783static void glue(gen_, name##3)(DisasContext *ctx)                            \
1784{                                                                             \
1785    gen_##name(ctx, 1, 1);                                                    \
1786}
1787
1788static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1789                              uint32_t sh)
1790{
1791    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1792        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1793    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1794        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1795    } else {
1796        TCGv t0 = tcg_temp_new();
1797        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1798        if (likely(mb == 0 && me == 63)) {
1799            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1800        } else {
1801            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1802        }
1803        tcg_temp_free(t0);
1804    }
1805    if (unlikely(Rc(ctx->opcode) != 0))
1806        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1807}
1808/* rldicl - rldicl. */
1809static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1810{
1811    uint32_t sh, mb;
1812
1813    sh = SH(ctx->opcode) | (shn << 5);
1814    mb = MB(ctx->opcode) | (mbn << 5);
1815    gen_rldinm(ctx, mb, 63, sh);
1816}
1817GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1818/* rldicr - rldicr. */
1819static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1820{
1821    uint32_t sh, me;
1822
1823    sh = SH(ctx->opcode) | (shn << 5);
1824    me = MB(ctx->opcode) | (men << 5);
1825    gen_rldinm(ctx, 0, me, sh);
1826}
1827GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1828/* rldic - rldic. */
1829static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1830{
1831    uint32_t sh, mb;
1832
1833    sh = SH(ctx->opcode) | (shn << 5);
1834    mb = MB(ctx->opcode) | (mbn << 5);
1835    gen_rldinm(ctx, mb, 63 - sh, sh);
1836}
1837GEN_PPC64_R4(rldic, 0x1E, 0x04);
1838
1839static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
1840{
1841    TCGv t0;
1842
1843    t0 = tcg_temp_new();
1844    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1845    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1846    if (unlikely(mb != 0 || me != 63)) {
1847        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1848    } else {
1849        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1850    }
1851    tcg_temp_free(t0);
1852    if (unlikely(Rc(ctx->opcode) != 0))
1853        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1854}
1855
1856/* rldcl - rldcl. */
1857static inline void gen_rldcl(DisasContext *ctx, int mbn)
1858{
1859    uint32_t mb;
1860
1861    mb = MB(ctx->opcode) | (mbn << 5);
1862    gen_rldnm(ctx, mb, 63);
1863}
1864GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1865/* rldcr - rldcr. */
1866static inline void gen_rldcr(DisasContext *ctx, int men)
1867{
1868    uint32_t me;
1869
1870    me = MB(ctx->opcode) | (men << 5);
1871    gen_rldnm(ctx, 0, me);
1872}
1873GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1874/* rldimi - rldimi. */
1875static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1876{
1877    uint32_t sh, mb, me;
1878
1879    sh = SH(ctx->opcode) | (shn << 5);
1880    mb = MB(ctx->opcode) | (mbn << 5);
1881    me = 63 - sh;
1882    if (unlikely(sh == 0 && mb == 0)) {
1883        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1884    } else {
1885        TCGv t0, t1;
1886        target_ulong mask;
1887
1888        t0 = tcg_temp_new();
1889        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1890        t1 = tcg_temp_new();
1891        mask = MASK(mb, me);
1892        tcg_gen_andi_tl(t0, t0, mask);
1893        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1894        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1895        tcg_temp_free(t0);
1896        tcg_temp_free(t1);
1897    }
1898    if (unlikely(Rc(ctx->opcode) != 0))
1899        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1900}
1901GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1902#endif
1903
1904/***                             Integer shift                             ***/
1905
1906/* slw & slw. */
1907static void gen_slw(DisasContext *ctx)
1908{
1909    TCGv t0, t1;
1910
1911    t0 = tcg_temp_new();
1912    /* AND rS with a mask that is 0 when rB >= 0x20 */
1913#if defined(TARGET_PPC64)
1914    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1915    tcg_gen_sari_tl(t0, t0, 0x3f);
1916#else
1917    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1918    tcg_gen_sari_tl(t0, t0, 0x1f);
1919#endif
1920    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1921    t1 = tcg_temp_new();
1922    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1923    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1924    tcg_temp_free(t1);
1925    tcg_temp_free(t0);
1926    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1927    if (unlikely(Rc(ctx->opcode) != 0))
1928        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1929}
1930
1931/* sraw & sraw. */
1932static void gen_sraw(DisasContext *ctx)
1933{
1934    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
1935                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1936    if (unlikely(Rc(ctx->opcode) != 0))
1937        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1938}
1939
1940/* srawi & srawi. */
1941static void gen_srawi(DisasContext *ctx)
1942{
1943    int sh = SH(ctx->opcode);
1944    TCGv dst = cpu_gpr[rA(ctx->opcode)];
1945    TCGv src = cpu_gpr[rS(ctx->opcode)];
1946    if (sh == 0) {
1947        tcg_gen_ext32s_tl(dst, src);
1948        tcg_gen_movi_tl(cpu_ca, 0);
1949    } else {
1950        TCGv t0;
1951        tcg_gen_ext32s_tl(dst, src);
1952        tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
1953        t0 = tcg_temp_new();
1954        tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
1955        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
1956        tcg_temp_free(t0);
1957        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
1958        tcg_gen_sari_tl(dst, dst, sh);
1959    }
1960    if (unlikely(Rc(ctx->opcode) != 0)) {
1961        gen_set_Rc0(ctx, dst);
1962    }
1963}
1964
1965/* srw & srw. */
1966static void gen_srw(DisasContext *ctx)
1967{
1968    TCGv t0, t1;
1969
1970    t0 = tcg_temp_new();
1971    /* AND rS with a mask that is 0 when rB >= 0x20 */
1972#if defined(TARGET_PPC64)
1973    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1974    tcg_gen_sari_tl(t0, t0, 0x3f);
1975#else
1976    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1977    tcg_gen_sari_tl(t0, t0, 0x1f);
1978#endif
1979    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1980    tcg_gen_ext32u_tl(t0, t0);
1981    t1 = tcg_temp_new();
1982    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1983    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1984    tcg_temp_free(t1);
1985    tcg_temp_free(t0);
1986    if (unlikely(Rc(ctx->opcode) != 0))
1987        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1988}
1989
1990#if defined(TARGET_PPC64)
1991/* sld & sld. */
1992static void gen_sld(DisasContext *ctx)
1993{
1994    TCGv t0, t1;
1995
1996    t0 = tcg_temp_new();
1997    /* AND rS with a mask that is 0 when rB >= 0x40 */
1998    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1999    tcg_gen_sari_tl(t0, t0, 0x3f);
2000    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2001    t1 = tcg_temp_new();
2002    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2003    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2004    tcg_temp_free(t1);
2005    tcg_temp_free(t0);
2006    if (unlikely(Rc(ctx->opcode) != 0))
2007        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2008}
2009
2010/* srad & srad. */
2011static void gen_srad(DisasContext *ctx)
2012{
2013    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
2014                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2015    if (unlikely(Rc(ctx->opcode) != 0))
2016        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2017}
2018/* sradi & sradi. */
2019static inline void gen_sradi(DisasContext *ctx, int n)
2020{
2021    int sh = SH(ctx->opcode) + (n << 5);
2022    TCGv dst = cpu_gpr[rA(ctx->opcode)];
2023    TCGv src = cpu_gpr[rS(ctx->opcode)];
2024    if (sh == 0) {
2025        tcg_gen_mov_tl(dst, src);
2026        tcg_gen_movi_tl(cpu_ca, 0);
2027    } else {
2028        TCGv t0;
2029        tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
2030        t0 = tcg_temp_new();
2031        tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
2032        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2033        tcg_temp_free(t0);
2034        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2035        tcg_gen_sari_tl(dst, src, sh);
2036    }
2037    if (unlikely(Rc(ctx->opcode) != 0)) {
2038        gen_set_Rc0(ctx, dst);
2039    }
2040}
2041
2042static void gen_sradi0(DisasContext *ctx)
2043{
2044    gen_sradi(ctx, 0);
2045}
2046
2047static void gen_sradi1(DisasContext *ctx)
2048{
2049    gen_sradi(ctx, 1);
2050}
2051
2052/* srd & srd. */
2053static void gen_srd(DisasContext *ctx)
2054{
2055    TCGv t0, t1;
2056
2057    t0 = tcg_temp_new();
2058    /* AND rS with a mask that is 0 when rB >= 0x40 */
2059    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2060    tcg_gen_sari_tl(t0, t0, 0x3f);
2061    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2062    t1 = tcg_temp_new();
2063    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2064    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2065    tcg_temp_free(t1);
2066    tcg_temp_free(t0);
2067    if (unlikely(Rc(ctx->opcode) != 0))
2068        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2069}
2070#endif
2071
2072#if defined(TARGET_PPC64)
2073static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2074{
2075    TCGv_i32 tmp = tcg_temp_new_i32();
2076    tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
2077    tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
2078    tcg_temp_free_i32(tmp);
2079}
2080#else
2081static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2082{
2083    tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
2084}
2085#endif
2086
2087/***                       Floating-Point arithmetic                       ***/
2088#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2089static void gen_f##name(DisasContext *ctx)                                    \
2090{                                                                             \
2091    if (unlikely(!ctx->fpu_enabled)) {                                        \
2092        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2093        return;                                                               \
2094    }                                                                         \
2095    /* NIP cannot be restored if the memory exception comes from an helper */ \
2096    gen_update_nip(ctx, ctx->nip - 4);                                        \
2097    gen_reset_fpstatus();                                                     \
2098    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
2099                     cpu_fpr[rA(ctx->opcode)],                                \
2100                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2101    if (isfloat) {                                                            \
2102        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
2103                        cpu_fpr[rD(ctx->opcode)]);                            \
2104    }                                                                         \
2105    if (set_fprf) {                                                           \
2106        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2107    }                                                                         \
2108    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2109        gen_set_cr1_from_fpscr(ctx);                                          \
2110    }                                                                         \
2111}
2112
2113#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
2114_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
2115_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2116
2117#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2118static void gen_f##name(DisasContext *ctx)                                    \
2119{                                                                             \
2120    if (unlikely(!ctx->fpu_enabled)) {                                        \
2121        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2122        return;                                                               \
2123    }                                                                         \
2124    /* NIP cannot be restored if the memory exception comes from an helper */ \
2125    gen_update_nip(ctx, ctx->nip - 4);                                        \
2126    gen_reset_fpstatus();                                                     \
2127    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
2128                     cpu_fpr[rA(ctx->opcode)],                                \
2129                     cpu_fpr[rB(ctx->opcode)]);                               \
2130    if (isfloat) {                                                            \
2131        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
2132                        cpu_fpr[rD(ctx->opcode)]);                            \
2133    }                                                                         \
2134    if (set_fprf) {                                                           \
2135        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2136    }                                                                         \
2137    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2138        gen_set_cr1_from_fpscr(ctx);                                          \
2139    }                                                                         \
2140}
2141#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2142_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2143_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2144
2145#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2146static void gen_f##name(DisasContext *ctx)                                    \
2147{                                                                             \
2148    if (unlikely(!ctx->fpu_enabled)) {                                        \
2149        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2150        return;                                                               \
2151    }                                                                         \
2152    /* NIP cannot be restored if the memory exception comes from an helper */ \
2153    gen_update_nip(ctx, ctx->nip - 4);                                        \
2154    gen_reset_fpstatus();                                                     \
2155    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
2156                     cpu_fpr[rA(ctx->opcode)],                                \
2157                     cpu_fpr[rC(ctx->opcode)]);                               \
2158    if (isfloat) {                                                            \
2159        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
2160                        cpu_fpr[rD(ctx->opcode)]);                            \
2161    }                                                                         \
2162    if (set_fprf) {                                                           \
2163        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2164    }                                                                         \
2165    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2166        gen_set_cr1_from_fpscr(ctx);                                          \
2167    }                                                                         \
2168}
2169#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2170_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2171_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2172
2173#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2174static void gen_f##name(DisasContext *ctx)                                    \
2175{                                                                             \
2176    if (unlikely(!ctx->fpu_enabled)) {                                        \
2177        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2178        return;                                                               \
2179    }                                                                         \
2180    /* NIP cannot be restored if the memory exception comes from an helper */ \
2181    gen_update_nip(ctx, ctx->nip - 4);                                        \
2182    gen_reset_fpstatus();                                                     \
2183    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
2184                       cpu_fpr[rB(ctx->opcode)]);                             \
2185    if (set_fprf) {                                                           \
2186        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2187    }                                                                         \
2188    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2189        gen_set_cr1_from_fpscr(ctx);                                          \
2190    }                                                                         \
2191}
2192
2193#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2194static void gen_f##name(DisasContext *ctx)                                    \
2195{                                                                             \
2196    if (unlikely(!ctx->fpu_enabled)) {                                        \
2197        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2198        return;                                                               \
2199    }                                                                         \
2200    /* NIP cannot be restored if the memory exception comes from an helper */ \
2201    gen_update_nip(ctx, ctx->nip - 4);                                        \
2202    gen_reset_fpstatus();                                                     \
2203    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
2204                       cpu_fpr[rB(ctx->opcode)]);                             \
2205    if (set_fprf) {                                                           \
2206        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2207    }                                                                         \
2208    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2209        gen_set_cr1_from_fpscr(ctx);                                          \
2210    }                                                                         \
2211}
2212
2213/* fadd - fadds */
2214GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2215/* fdiv - fdivs */
2216GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2217/* fmul - fmuls */
2218GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2219
2220/* fre */
2221GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2222
2223/* fres */
2224GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2225
2226/* frsqrte */
2227GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2228
2229/* frsqrtes */
2230static void gen_frsqrtes(DisasContext *ctx)
2231{
2232    if (unlikely(!ctx->fpu_enabled)) {
2233        gen_exception(ctx, POWERPC_EXCP_FPU);
2234        return;
2235    }
2236    /* NIP cannot be restored if the memory exception comes from an helper */
2237    gen_update_nip(ctx, ctx->nip - 4);
2238    gen_reset_fpstatus();
2239    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
2240                       cpu_fpr[rB(ctx->opcode)]);
2241    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2242                    cpu_fpr[rD(ctx->opcode)]);
2243    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2244    if (unlikely(Rc(ctx->opcode) != 0)) {
2245        gen_set_cr1_from_fpscr(ctx);
2246    }
2247}
2248
2249/* fsel */
2250_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2251/* fsub - fsubs */
2252GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2253/* Optional: */
2254
2255/* fsqrt */
2256static void gen_fsqrt(DisasContext *ctx)
2257{
2258    if (unlikely(!ctx->fpu_enabled)) {
2259        gen_exception(ctx, POWERPC_EXCP_FPU);
2260        return;
2261    }
2262    /* NIP cannot be restored if the memory exception comes from an helper */
2263    gen_update_nip(ctx, ctx->nip - 4);
2264    gen_reset_fpstatus();
2265    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2266                     cpu_fpr[rB(ctx->opcode)]);
2267    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2268    if (unlikely(Rc(ctx->opcode) != 0)) {
2269        gen_set_cr1_from_fpscr(ctx);
2270    }
2271}
2272
2273static void gen_fsqrts(DisasContext *ctx)
2274{
2275    if (unlikely(!ctx->fpu_enabled)) {
2276        gen_exception(ctx, POWERPC_EXCP_FPU);
2277        return;
2278    }
2279    /* NIP cannot be restored if the memory exception comes from an helper */
2280    gen_update_nip(ctx, ctx->nip - 4);
2281    gen_reset_fpstatus();
2282    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2283                     cpu_fpr[rB(ctx->opcode)]);
2284    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2285                    cpu_fpr[rD(ctx->opcode)]);
2286    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2287    if (unlikely(Rc(ctx->opcode) != 0)) {
2288        gen_set_cr1_from_fpscr(ctx);
2289    }
2290}
2291
2292/***                     Floating-Point multiply-and-add                   ***/
2293/* fmadd - fmadds */
2294GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2295/* fmsub - fmsubs */
2296GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2297/* fnmadd - fnmadds */
2298GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2299/* fnmsub - fnmsubs */
2300GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2301
2302/***                     Floating-Point round & convert                    ***/
2303/* fctiw */
2304GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2305/* fctiwu */
2306GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
2307/* fctiwz */
2308GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2309/* fctiwuz */
2310GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
2311/* frsp */
2312GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2313/* fcfid */
2314GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
2315/* fcfids */
2316GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
2317/* fcfidu */
2318GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
2319/* fcfidus */
2320GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
2321/* fctid */
2322GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
2323/* fctidu */
2324GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
2325/* fctidz */
2326GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
2327/* fctidu */
2328GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
2329
2330/* frin */
2331GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2332/* friz */
2333GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2334/* frip */
2335GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2336/* frim */
2337GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2338
2339static void gen_ftdiv(DisasContext *ctx)
2340{
2341    if (unlikely(!ctx->fpu_enabled)) {
2342        gen_exception(ctx, POWERPC_EXCP_FPU);
2343        return;
2344    }
2345    gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2346                     cpu_fpr[rB(ctx->opcode)]);
2347}
2348
2349static void gen_ftsqrt(DisasContext *ctx)
2350{
2351    if (unlikely(!ctx->fpu_enabled)) {
2352        gen_exception(ctx, POWERPC_EXCP_FPU);
2353        return;
2354    }
2355    gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2356}
2357
2358
2359
2360/***                         Floating-Point compare                        ***/
2361
2362/* fcmpo */
2363static void gen_fcmpo(DisasContext *ctx)
2364{
2365    TCGv_i32 crf;
2366    if (unlikely(!ctx->fpu_enabled)) {
2367        gen_exception(ctx, POWERPC_EXCP_FPU);
2368        return;
2369    }
2370    /* NIP cannot be restored if the memory exception comes from an helper */
2371    gen_update_nip(ctx, ctx->nip - 4);
2372    gen_reset_fpstatus();
2373    crf = tcg_const_i32(crfD(ctx->opcode));
2374    gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
2375                     cpu_fpr[rB(ctx->opcode)], crf);
2376    tcg_temp_free_i32(crf);
2377    gen_helper_float_check_status(cpu_env);
2378}
2379
2380/* fcmpu */
2381static void gen_fcmpu(DisasContext *ctx)
2382{
2383    TCGv_i32 crf;
2384    if (unlikely(!ctx->fpu_enabled)) {
2385        gen_exception(ctx, POWERPC_EXCP_FPU);
2386        return;
2387    }
2388    /* NIP cannot be restored if the memory exception comes from an helper */
2389    gen_update_nip(ctx, ctx->nip - 4);
2390    gen_reset_fpstatus();
2391    crf = tcg_const_i32(crfD(ctx->opcode));
2392    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
2393                     cpu_fpr[rB(ctx->opcode)], crf);
2394    tcg_temp_free_i32(crf);
2395    gen_helper_float_check_status(cpu_env);
2396}
2397
2398/***                         Floating-point move                           ***/
2399/* fabs */
2400/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2401static void gen_fabs(DisasContext *ctx)
2402{
2403    if (unlikely(!ctx->fpu_enabled)) {
2404        gen_exception(ctx, POWERPC_EXCP_FPU);
2405        return;
2406    }
2407    tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2408                     ~(1ULL << 63));
2409    if (unlikely(Rc(ctx->opcode))) {
2410        gen_set_cr1_from_fpscr(ctx);
2411    }
2412}
2413
2414/* fmr  - fmr. */
2415/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2416static void gen_fmr(DisasContext *ctx)
2417{
2418    if (unlikely(!ctx->fpu_enabled)) {
2419        gen_exception(ctx, POWERPC_EXCP_FPU);
2420        return;
2421    }
2422    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2423    if (unlikely(Rc(ctx->opcode))) {
2424        gen_set_cr1_from_fpscr(ctx);
2425    }
2426}
2427
2428/* fnabs */
2429/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2430static void gen_fnabs(DisasContext *ctx)
2431{
2432    if (unlikely(!ctx->fpu_enabled)) {
2433        gen_exception(ctx, POWERPC_EXCP_FPU);
2434        return;
2435    }
2436    tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2437                    1ULL << 63);
2438    if (unlikely(Rc(ctx->opcode))) {
2439        gen_set_cr1_from_fpscr(ctx);
2440    }
2441}
2442
2443/* fneg */
2444/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2445static void gen_fneg(DisasContext *ctx)
2446{
2447    if (unlikely(!ctx->fpu_enabled)) {
2448        gen_exception(ctx, POWERPC_EXCP_FPU);
2449        return;
2450    }
2451    tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2452                     1ULL << 63);
2453    if (unlikely(Rc(ctx->opcode))) {
2454        gen_set_cr1_from_fpscr(ctx);
2455    }
2456}
2457
2458/* fcpsgn: PowerPC 2.05 specification */
2459/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
2460static void gen_fcpsgn(DisasContext *ctx)
2461{
2462    if (unlikely(!ctx->fpu_enabled)) {
2463        gen_exception(ctx, POWERPC_EXCP_FPU);
2464        return;
2465    }
2466    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2467                        cpu_fpr[rB(ctx->opcode)], 0, 63);
2468    if (unlikely(Rc(ctx->opcode))) {
2469        gen_set_cr1_from_fpscr(ctx);
2470    }
2471}
2472
2473static void gen_fmrgew(DisasContext *ctx)
2474{
2475    TCGv_i64 b0;
2476    if (unlikely(!ctx->fpu_enabled)) {
2477        gen_exception(ctx, POWERPC_EXCP_FPU);
2478        return;
2479    }
2480    b0 = tcg_temp_new_i64();
2481    tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
2482    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2483                        b0, 0, 32);
2484    tcg_temp_free_i64(b0);
2485}
2486
2487static void gen_fmrgow(DisasContext *ctx)
2488{
2489    if (unlikely(!ctx->fpu_enabled)) {
2490        gen_exception(ctx, POWERPC_EXCP_FPU);
2491        return;
2492    }
2493    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
2494                        cpu_fpr[rB(ctx->opcode)],
2495                        cpu_fpr[rA(ctx->opcode)],
2496                        32, 32);
2497}
2498
2499/***                  Floating-Point status & ctrl register                ***/
2500
2501/* mcrfs */
2502static void gen_mcrfs(DisasContext *ctx)
2503{
2504    TCGv tmp = tcg_temp_new();
2505    TCGv_i32 tmask;
2506    TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
2507    int bfa;
2508    int nibble;
2509    int shift;
2510
2511    if (unlikely(!ctx->fpu_enabled)) {
2512        gen_exception(ctx, POWERPC_EXCP_FPU);
2513        return;
2514    }
2515    bfa = crfS(ctx->opcode);
2516    nibble = 7 - bfa;
2517    shift = 4 * nibble;
2518    tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
2519    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
2520    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2521    tcg_temp_free(tmp);
2522    tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
2523    /* Only the exception bits (including FX) should be cleared if read */
2524    tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS));
2525    /* FEX and VX need to be updated, so don't set fpscr directly */
2526    tmask = tcg_const_i32(1 << nibble);
2527    gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
2528    tcg_temp_free_i32(tmask);
2529    tcg_temp_free_i64(tnew_fpscr);
2530}
2531
2532/* mffs */
2533static void gen_mffs(DisasContext *ctx)
2534{
2535    if (unlikely(!ctx->fpu_enabled)) {
2536        gen_exception(ctx, POWERPC_EXCP_FPU);
2537        return;
2538    }
2539    gen_reset_fpstatus();
2540    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2541    if (unlikely(Rc(ctx->opcode))) {
2542        gen_set_cr1_from_fpscr(ctx);
2543    }
2544}
2545
2546/* mtfsb0 */
2547static void gen_mtfsb0(DisasContext *ctx)
2548{
2549    uint8_t crb;
2550
2551    if (unlikely(!ctx->fpu_enabled)) {
2552        gen_exception(ctx, POWERPC_EXCP_FPU);
2553        return;
2554    }
2555    crb = 31 - crbD(ctx->opcode);
2556    gen_reset_fpstatus();
2557    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2558        TCGv_i32 t0;
2559        /* NIP cannot be restored if the memory exception comes from an helper */
2560        gen_update_nip(ctx, ctx->nip - 4);
2561        t0 = tcg_const_i32(crb);
2562        gen_helper_fpscr_clrbit(cpu_env, t0);
2563        tcg_temp_free_i32(t0);
2564    }
2565    if (unlikely(Rc(ctx->opcode) != 0)) {
2566        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2567        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2568    }
2569}
2570
2571/* mtfsb1 */
2572static void gen_mtfsb1(DisasContext *ctx)
2573{
2574    uint8_t crb;
2575
2576    if (unlikely(!ctx->fpu_enabled)) {
2577        gen_exception(ctx, POWERPC_EXCP_FPU);
2578        return;
2579    }
2580    crb = 31 - crbD(ctx->opcode);
2581    gen_reset_fpstatus();
2582    /* XXX: we pretend we can only do IEEE floating-point computations */
2583    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2584        TCGv_i32 t0;
2585        /* NIP cannot be restored if the memory exception comes from an helper */
2586        gen_update_nip(ctx, ctx->nip - 4);
2587        t0 = tcg_const_i32(crb);
2588        gen_helper_fpscr_setbit(cpu_env, t0);
2589        tcg_temp_free_i32(t0);
2590    }
2591    if (unlikely(Rc(ctx->opcode) != 0)) {
2592        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2593        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2594    }
2595    /* We can raise a differed exception */
2596    gen_helper_float_check_status(cpu_env);
2597}
2598
2599/* mtfsf */
2600static void gen_mtfsf(DisasContext *ctx)
2601{
2602    TCGv_i32 t0;
2603    int flm, l, w;
2604
2605    if (unlikely(!ctx->fpu_enabled)) {
2606        gen_exception(ctx, POWERPC_EXCP_FPU);
2607        return;
2608    }
2609    flm = FPFLM(ctx->opcode);
2610    l = FPL(ctx->opcode);
2611    w = FPW(ctx->opcode);
2612    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2613        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2614        return;
2615    }
2616    /* NIP cannot be restored if the memory exception comes from an helper */
2617    gen_update_nip(ctx, ctx->nip - 4);
2618    gen_reset_fpstatus();
2619    if (l) {
2620        t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
2621    } else {
2622        t0 = tcg_const_i32(flm << (w * 8));
2623    }
2624    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2625    tcg_temp_free_i32(t0);
2626    if (unlikely(Rc(ctx->opcode) != 0)) {
2627        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2628        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2629    }
2630    /* We can raise a differed exception */
2631    gen_helper_float_check_status(cpu_env);
2632}
2633
2634/* mtfsfi */
2635static void gen_mtfsfi(DisasContext *ctx)
2636{
2637    int bf, sh, w;
2638    TCGv_i64 t0;
2639    TCGv_i32 t1;
2640
2641    if (unlikely(!ctx->fpu_enabled)) {
2642        gen_exception(ctx, POWERPC_EXCP_FPU);
2643        return;
2644    }
2645    w = FPW(ctx->opcode);
2646    bf = FPBF(ctx->opcode);
2647    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2648        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2649        return;
2650    }
2651    sh = (8 * w) + 7 - bf;
2652    /* NIP cannot be restored if the memory exception comes from an helper */
2653    gen_update_nip(ctx, ctx->nip - 4);
2654    gen_reset_fpstatus();
2655    t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
2656    t1 = tcg_const_i32(1 << sh);
2657    gen_helper_store_fpscr(cpu_env, t0, t1);
2658    tcg_temp_free_i64(t0);
2659    tcg_temp_free_i32(t1);
2660    if (unlikely(Rc(ctx->opcode) != 0)) {
2661        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2662        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2663    }
2664    /* We can raise a differed exception */
2665    gen_helper_float_check_status(cpu_env);
2666}
2667
2668/***                           Addressing modes                            ***/
2669/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2670static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2671                                      target_long maskl)
2672{
2673    target_long simm = SIMM(ctx->opcode);
2674
2675    simm &= ~maskl;
2676    if (rA(ctx->opcode) == 0) {
2677        if (NARROW_MODE(ctx)) {
2678            simm = (uint32_t)simm;
2679        }
2680        tcg_gen_movi_tl(EA, simm);
2681    } else if (likely(simm != 0)) {
2682        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2683        if (NARROW_MODE(ctx)) {
2684            tcg_gen_ext32u_tl(EA, EA);
2685        }
2686    } else {
2687        if (NARROW_MODE(ctx)) {
2688            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2689        } else {
2690            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2691        }
2692    }
2693}
2694
2695static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2696{
2697    if (rA(ctx->opcode) == 0) {
2698        if (NARROW_MODE(ctx)) {
2699            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2700        } else {
2701            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2702        }
2703    } else {
2704        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2705        if (NARROW_MODE(ctx)) {
2706            tcg_gen_ext32u_tl(EA, EA);
2707        }
2708    }
2709}
2710
2711static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2712{
2713    if (rA(ctx->opcode) == 0) {
2714        tcg_gen_movi_tl(EA, 0);
2715    } else if (NARROW_MODE(ctx)) {
2716        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2717    } else {
2718        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2719    }
2720}
2721
2722static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2723                                target_long val)
2724{
2725    tcg_gen_addi_tl(ret, arg1, val);
2726    if (NARROW_MODE(ctx)) {
2727        tcg_gen_ext32u_tl(ret, ret);
2728    }
2729}
2730
2731static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2732{
2733    TCGLabel *l1 = gen_new_label();
2734    TCGv t0 = tcg_temp_new();
2735    TCGv_i32 t1, t2;
2736    /* NIP cannot be restored if the memory exception comes from an helper */
2737    gen_update_nip(ctx, ctx->nip - 4);
2738    tcg_gen_andi_tl(t0, EA, mask);
2739    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2740    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2741    t2 = tcg_const_i32(0);
2742    gen_helper_raise_exception_err(cpu_env, t1, t2);
2743    tcg_temp_free_i32(t1);
2744    tcg_temp_free_i32(t2);
2745    gen_set_label(l1);
2746    tcg_temp_free(t0);
2747}
2748
2749/***                             Integer load                              ***/
2750static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2751{
2752    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2753}
2754
2755static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2756{
2757    TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2758    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2759}
2760
2761static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2762{
2763    TCGMemOp op = MO_SW | ctx->default_tcg_memop_mask;
2764    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2765}
2766
2767static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2768{
2769    TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2770    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2771}
2772
2773static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2774{
2775    TCGv tmp = tcg_temp_new();
2776    gen_qemu_ld32u(ctx, tmp, addr);
2777    tcg_gen_extu_tl_i64(val, tmp);
2778    tcg_temp_free(tmp);
2779}
2780
2781static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2782{
2783    TCGMemOp op = MO_SL | ctx->default_tcg_memop_mask;
2784    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2785}
2786
2787static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2788{
2789    TCGv tmp = tcg_temp_new();
2790    gen_qemu_ld32s(ctx, tmp, addr);
2791    tcg_gen_ext_tl_i64(val, tmp);
2792    tcg_temp_free(tmp);
2793}
2794
2795static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2796{
2797    TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2798    tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
2799}
2800
2801static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2802{
2803    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2804}
2805
2806static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2807{
2808    TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2809    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
2810}
2811
2812static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2813{
2814    TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2815    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
2816}
2817
2818static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2819{
2820    TCGv tmp = tcg_temp_new();
2821    tcg_gen_trunc_i64_tl(tmp, val);
2822    gen_qemu_st32(ctx, tmp, addr);
2823    tcg_temp_free(tmp);
2824}
2825
2826static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2827{
2828    TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2829    tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
2830}
2831
2832#define GEN_LD(name, ldop, opc, type)                                         \
2833static void glue(gen_, name)(DisasContext *ctx)                                       \
2834{                                                                             \
2835    TCGv EA;                                                                  \
2836    gen_set_access_type(ctx, ACCESS_INT);                                     \
2837    EA = tcg_temp_new();                                                      \
2838    gen_addr_imm_index(ctx, EA, 0);                                           \
2839    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2840    tcg_temp_free(EA);                                                        \
2841}
2842
2843#define GEN_LDU(name, ldop, opc, type)                                        \
2844static void glue(gen_, name##u)(DisasContext *ctx)                                    \
2845{                                                                             \
2846    TCGv EA;                                                                  \
2847    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2848                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2849        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2850        return;                                                               \
2851    }                                                                         \
2852    gen_set_access_type(ctx, ACCESS_INT);                                     \
2853    EA = tcg_temp_new();                                                      \
2854    if (type == PPC_64B)                                                      \
2855        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2856    else                                                                      \
2857        gen_addr_imm_index(ctx, EA, 0);                                       \
2858    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2859    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2860    tcg_temp_free(EA);                                                        \
2861}
2862
2863#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2864static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2865{                                                                             \
2866    TCGv EA;                                                                  \
2867    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2868                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2869        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2870        return;                                                               \
2871    }                                                                         \
2872    gen_set_access_type(ctx, ACCESS_INT);                                     \
2873    EA = tcg_temp_new();                                                      \
2874    gen_addr_reg_index(ctx, EA);                                              \
2875    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2876    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2877    tcg_temp_free(EA);                                                        \
2878}
2879
2880#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
2881static void glue(gen_, name##x)(DisasContext *ctx)                            \
2882{                                                                             \
2883    TCGv EA;                                                                  \
2884    gen_set_access_type(ctx, ACCESS_INT);                                     \
2885    EA = tcg_temp_new();                                                      \
2886    gen_addr_reg_index(ctx, EA);                                              \
2887    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2888    tcg_temp_free(EA);                                                        \
2889}
2890#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2891    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
2892
2893#define GEN_LDS(name, ldop, op, type)                                         \
2894GEN_LD(name, ldop, op | 0x20, type);                                          \
2895GEN_LDU(name, ldop, op | 0x21, type);                                         \
2896GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2897GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2898
2899/* lbz lbzu lbzux lbzx */
2900GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2901/* lha lhau lhaux lhax */
2902GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2903/* lhz lhzu lhzux lhzx */
2904GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2905/* lwz lwzu lwzux lwzx */
2906GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2907#if defined(TARGET_PPC64)
2908/* lwaux */
2909GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2910/* lwax */
2911GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2912/* ldux */
2913GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2914/* ldx */
2915GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2916
2917static void gen_ld(DisasContext *ctx)
2918{
2919    TCGv EA;
2920    if (Rc(ctx->opcode)) {
2921        if (unlikely(rA(ctx->opcode) == 0 ||
2922                     rA(ctx->opcode) == rD(ctx->opcode))) {
2923            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2924            return;
2925        }
2926    }
2927    gen_set_access_type(ctx, ACCESS_INT);
2928    EA = tcg_temp_new();
2929    gen_addr_imm_index(ctx, EA, 0x03);
2930    if (ctx->opcode & 0x02) {
2931        /* lwa (lwau is undefined) */
2932        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2933    } else {
2934        /* ld - ldu */
2935        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2936    }
2937    if (Rc(ctx->opcode))
2938        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2939    tcg_temp_free(EA);
2940}
2941
2942/* lq */
2943static void gen_lq(DisasContext *ctx)
2944{
2945    int ra, rd;
2946    TCGv EA;
2947
2948    /* lq is a legal user mode instruction starting in ISA 2.07 */
2949    bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
2950    bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
2951
2952    if (!legal_in_user_mode && ctx->pr) {
2953        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2954        return;
2955    }
2956
2957    if (!le_is_supported && ctx->le_mode) {
2958        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2959        return;
2960    }
2961
2962    ra = rA(ctx->opcode);
2963    rd = rD(ctx->opcode);
2964    if (unlikely((rd & 1) || rd == ra)) {
2965        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2966        return;
2967    }
2968
2969    gen_set_access_type(ctx, ACCESS_INT);
2970    EA = tcg_temp_new();
2971    gen_addr_imm_index(ctx, EA, 0x0F);
2972
2973    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
2974       64-bit byteswap already. */
2975    if (unlikely(ctx->le_mode)) {
2976        gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2977        gen_addr_add(ctx, EA, EA, 8);
2978        gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2979    } else {
2980        gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2981        gen_addr_add(ctx, EA, EA, 8);
2982        gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2983    }
2984    tcg_temp_free(EA);
2985}
2986#endif
2987
2988/***                              Integer store                            ***/
2989#define GEN_ST(name, stop, opc, type)                                         \
2990static void glue(gen_, name)(DisasContext *ctx)                                       \
2991{                                                                             \
2992    TCGv EA;                                                                  \
2993    gen_set_access_type(ctx, ACCESS_INT);                                     \
2994    EA = tcg_temp_new();                                                      \
2995    gen_addr_imm_index(ctx, EA, 0);                                           \
2996    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2997    tcg_temp_free(EA);                                                        \
2998}
2999
3000#define GEN_STU(name, stop, opc, type)                                        \
3001static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
3002{                                                                             \
3003    TCGv EA;                                                                  \
3004    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3005        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3006        return;                                                               \
3007    }                                                                         \
3008    gen_set_access_type(ctx, ACCESS_INT);                                     \
3009    EA = tcg_temp_new();                                                      \
3010    if (type == PPC_64B)                                                      \
3011        gen_addr_imm_index(ctx, EA, 0x03);                                    \
3012    else                                                                      \
3013        gen_addr_imm_index(ctx, EA, 0);                                       \
3014    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3015    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3016    tcg_temp_free(EA);                                                        \
3017}
3018
3019#define GEN_STUX(name, stop, opc2, opc3, type)                                \
3020static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3021{                                                                             \
3022    TCGv EA;                                                                  \
3023    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3024        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3025        return;                                                               \
3026    }                                                                         \
3027    gen_set_access_type(ctx, ACCESS_INT);                                     \
3028    EA = tcg_temp_new();                                                      \
3029    gen_addr_reg_index(ctx, EA);                                              \
3030    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3031    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3032    tcg_temp_free(EA);                                                        \
3033}
3034
3035#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
3036static void glue(gen_, name##x)(DisasContext *ctx)                            \
3037{                                                                             \
3038    TCGv EA;                                                                  \
3039    gen_set_access_type(ctx, ACCESS_INT);                                     \
3040    EA = tcg_temp_new();                                                      \
3041    gen_addr_reg_index(ctx, EA);                                              \
3042    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3043    tcg_temp_free(EA);                                                        \
3044}
3045#define GEN_STX(name, stop, opc2, opc3, type)                                 \
3046    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
3047
3048#define GEN_STS(name, stop, op, type)                                         \
3049GEN_ST(name, stop, op | 0x20, type);                                          \
3050GEN_STU(name, stop, op | 0x21, type);                                         \
3051GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
3052GEN_STX(name, stop, 0x17, op | 0x00, type)
3053
3054/* stb stbu stbux stbx */
3055GEN_STS(stb, st8, 0x06, PPC_INTEGER);
3056/* sth sthu sthux sthx */
3057GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
3058/* stw stwu stwux stwx */
3059GEN_STS(stw, st32, 0x04, PPC_INTEGER);
3060#if defined(TARGET_PPC64)
3061GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
3062GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
3063
3064static void gen_std(DisasContext *ctx)
3065{
3066    int rs;
3067    TCGv EA;
3068
3069    rs = rS(ctx->opcode);
3070    if ((ctx->opcode & 0x3) == 0x2) { /* stq */
3071
3072        bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3073        bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3074
3075        if (!legal_in_user_mode && ctx->pr) {
3076            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3077            return;
3078        }
3079
3080        if (!le_is_supported && ctx->le_mode) {
3081            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
3082            return;
3083        }
3084
3085        if (unlikely(rs & 1)) {
3086            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3087            return;
3088        }
3089        gen_set_access_type(ctx, ACCESS_INT);
3090        EA = tcg_temp_new();
3091        gen_addr_imm_index(ctx, EA, 0x03);
3092
3093        /* We only need to swap high and low halves. gen_qemu_st64 does
3094           necessary 64-bit byteswap already. */
3095        if (unlikely(ctx->le_mode)) {
3096            gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3097            gen_addr_add(ctx, EA, EA, 8);
3098            gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3099        } else {
3100            gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3101            gen_addr_add(ctx, EA, EA, 8);
3102            gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3103        }
3104        tcg_temp_free(EA);
3105    } else {
3106        /* std / stdu*/
3107        if (Rc(ctx->opcode)) {
3108            if (unlikely(rA(ctx->opcode) == 0)) {
3109                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3110                return;
3111            }
3112        }
3113        gen_set_access_type(ctx, ACCESS_INT);
3114        EA = tcg_temp_new();
3115        gen_addr_imm_index(ctx, EA, 0x03);
3116        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3117        if (Rc(ctx->opcode))
3118            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
3119        tcg_temp_free(EA);
3120    }
3121}
3122#endif
3123/***                Integer load and store with byte reverse               ***/
3124
3125/* lhbrx */
3126static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3127{
3128    TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3129    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
3130}
3131GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
3132
3133/* lwbrx */
3134static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3135{
3136    TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3137    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
3138}
3139GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
3140
3141#if defined(TARGET_PPC64)
3142/* ldbrx */
3143static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3144{
3145    TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3146    tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
3147}
3148GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
3149#endif  /* TARGET_PPC64 */
3150
3151/* sthbrx */
3152static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3153{
3154    TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3155    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
3156}
3157GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
3158
3159/* stwbrx */
3160static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3161{
3162    TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3163    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
3164}
3165GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
3166
3167#if defined(TARGET_PPC64)
3168/* stdbrx */
3169static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3170{
3171    TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3172    tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
3173}
3174GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
3175#endif  /* TARGET_PPC64 */
3176
3177/***                    Integer load and store multiple                    ***/
3178
3179/* lmw */
3180static void gen_lmw(DisasContext *ctx)
3181{
3182    TCGv t0;
3183    TCGv_i32 t1;
3184    gen_set_access_type(ctx, ACCESS_INT);
3185    /* NIP cannot be restored if the memory exception comes from an helper */
3186    gen_update_nip(ctx, ctx->nip - 4);
3187    t0 = tcg_temp_new();
3188    t1 = tcg_const_i32(rD(ctx->opcode));
3189    gen_addr_imm_index(ctx, t0, 0);
3190    gen_helper_lmw(cpu_env, t0, t1);
3191    tcg_temp_free(t0);
3192    tcg_temp_free_i32(t1);
3193}
3194
3195/* stmw */
3196static void gen_stmw(DisasContext *ctx)
3197{
3198    TCGv t0;
3199    TCGv_i32 t1;
3200    gen_set_access_type(ctx, ACCESS_INT);
3201    /* NIP cannot be restored if the memory exception comes from an helper */
3202    gen_update_nip(ctx, ctx->nip - 4);
3203    t0 = tcg_temp_new();
3204    t1 = tcg_const_i32(rS(ctx->opcode));
3205    gen_addr_imm_index(ctx, t0, 0);
3206    gen_helper_stmw(cpu_env, t0, t1);
3207    tcg_temp_free(t0);
3208    tcg_temp_free_i32(t1);
3209}
3210
3211/***                    Integer load and store strings                     ***/
3212
3213/* lswi */
3214/* PowerPC32 specification says we must generate an exception if
3215 * rA is in the range of registers to be loaded.
3216 * In an other hand, IBM says this is valid, but rA won't be loaded.
3217 * For now, I'll follow the spec...
3218 */
3219static void gen_lswi(DisasContext *ctx)
3220{
3221    TCGv t0;
3222    TCGv_i32 t1, t2;
3223    int nb = NB(ctx->opcode);
3224    int start = rD(ctx->opcode);
3225    int ra = rA(ctx->opcode);
3226    int nr;
3227
3228    if (nb == 0)
3229        nb = 32;
3230    nr = (nb + 3) / 4;
3231    if (unlikely(lsw_reg_in_range(start, nr, ra))) {
3232        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3233        return;
3234    }
3235    gen_set_access_type(ctx, ACCESS_INT);
3236    /* NIP cannot be restored if the memory exception comes from an helper */
3237    gen_update_nip(ctx, ctx->nip - 4);
3238    t0 = tcg_temp_new();
3239    gen_addr_register(ctx, t0);
3240    t1 = tcg_const_i32(nb);
3241    t2 = tcg_const_i32(start);
3242    gen_helper_lsw(cpu_env, t0, t1, t2);
3243    tcg_temp_free(t0);
3244    tcg_temp_free_i32(t1);
3245    tcg_temp_free_i32(t2);
3246}
3247
3248/* lswx */
3249static void gen_lswx(DisasContext *ctx)
3250{
3251    TCGv t0;
3252    TCGv_i32 t1, t2, t3;
3253    gen_set_access_type(ctx, ACCESS_INT);
3254    /* NIP cannot be restored if the memory exception comes from an helper */
3255    gen_update_nip(ctx, ctx->nip - 4);
3256    t0 = tcg_temp_new();
3257    gen_addr_reg_index(ctx, t0);
3258    t1 = tcg_const_i32(rD(ctx->opcode));
3259    t2 = tcg_const_i32(rA(ctx->opcode));
3260    t3 = tcg_const_i32(rB(ctx->opcode));
3261    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3262    tcg_temp_free(t0);
3263    tcg_temp_free_i32(t1);
3264    tcg_temp_free_i32(t2);
3265    tcg_temp_free_i32(t3);
3266}
3267
3268/* stswi */
3269static void gen_stswi(DisasContext *ctx)
3270{
3271    TCGv t0;
3272    TCGv_i32 t1, t2;
3273    int nb = NB(ctx->opcode);
3274    gen_set_access_type(ctx, ACCESS_INT);
3275    /* NIP cannot be restored if the memory exception comes from an helper */
3276    gen_update_nip(ctx, ctx->nip - 4);
3277    t0 = tcg_temp_new();
3278    gen_addr_register(ctx, t0);
3279    if (nb == 0)
3280        nb = 32;
3281    t1 = tcg_const_i32(nb);
3282    t2 = tcg_const_i32(rS(ctx->opcode));
3283    gen_helper_stsw(cpu_env, t0, t1, t2);
3284    tcg_temp_free(t0);
3285    tcg_temp_free_i32(t1);
3286    tcg_temp_free_i32(t2);
3287}
3288
3289/* stswx */
3290static void gen_stswx(DisasContext *ctx)
3291{
3292    TCGv t0;
3293    TCGv_i32 t1, t2;
3294    gen_set_access_type(ctx, ACCESS_INT);
3295    /* NIP cannot be restored if the memory exception comes from an helper */
3296    gen_update_nip(ctx, ctx->nip - 4);
3297    t0 = tcg_temp_new();
3298    gen_addr_reg_index(ctx, t0);
3299    t1 = tcg_temp_new_i32();
3300    tcg_gen_trunc_tl_i32(t1, cpu_xer);
3301    tcg_gen_andi_i32(t1, t1, 0x7F);
3302    t2 = tcg_const_i32(rS(ctx->opcode));
3303    gen_helper_stsw(cpu_env, t0, t1, t2);
3304    tcg_temp_free(t0);
3305    tcg_temp_free_i32(t1);
3306    tcg_temp_free_i32(t2);
3307}
3308
3309/***                        Memory synchronisation                         ***/
3310/* eieio */
3311static void gen_eieio(DisasContext *ctx)
3312{
3313}
3314
3315/* isync */
3316static void gen_isync(DisasContext *ctx)
3317{
3318    gen_stop_exception(ctx);
3319}
3320
3321#define LARX(name, len, loadop)                                      \
3322static void gen_##name(DisasContext *ctx)                            \
3323{                                                                    \
3324    TCGv t0;                                                         \
3325    TCGv gpr = cpu_gpr[rD(ctx->opcode)];                             \
3326    gen_set_access_type(ctx, ACCESS_RES);                            \
3327    t0 = tcg_temp_local_new();                                       \
3328    gen_addr_reg_index(ctx, t0);                                     \
3329    if ((len) > 1) {                                                 \
3330        gen_check_align(ctx, t0, (len)-1);                           \
3331    }                                                                \
3332    gen_qemu_##loadop(ctx, gpr, t0);                                 \
3333    tcg_gen_mov_tl(cpu_reserve, t0);                                 \
3334    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \
3335    tcg_temp_free(t0);                                               \
3336}
3337
3338/* lwarx */
3339LARX(lbarx, 1, ld8u);
3340LARX(lharx, 2, ld16u);
3341LARX(lwarx, 4, ld32u);
3342
3343
3344#if defined(CONFIG_USER_ONLY)
3345static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3346                                  int reg, int size)
3347{
3348    TCGv t0 = tcg_temp_new();
3349    uint32_t save_exception = ctx->exception;
3350
3351    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3352    tcg_gen_movi_tl(t0, (size << 5) | reg);
3353    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3354    tcg_temp_free(t0);
3355    gen_update_nip(ctx, ctx->nip-4);
3356    ctx->exception = POWERPC_EXCP_BRANCH;
3357    gen_exception(ctx, POWERPC_EXCP_STCX);
3358    ctx->exception = save_exception;
3359}
3360#else
3361static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3362                                  int reg, int size)
3363{
3364    TCGLabel *l1;
3365
3366    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3367    l1 = gen_new_label();
3368    tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
3369    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3370#if defined(TARGET_PPC64)
3371    if (size == 8) {
3372        gen_qemu_st64(ctx, cpu_gpr[reg], EA);
3373    } else
3374#endif
3375    if (size == 4) {
3376        gen_qemu_st32(ctx, cpu_gpr[reg], EA);
3377    } else if (size == 2) {
3378        gen_qemu_st16(ctx, cpu_gpr[reg], EA);
3379#if defined(TARGET_PPC64)
3380    } else if (size == 16) {
3381        TCGv gpr1, gpr2 , EA8;
3382        if (unlikely(ctx->le_mode)) {
3383            gpr1 = cpu_gpr[reg+1];
3384            gpr2 = cpu_gpr[reg];
3385        } else {
3386            gpr1 = cpu_gpr[reg];
3387            gpr2 = cpu_gpr[reg+1];
3388        }
3389        gen_qemu_st64(ctx, gpr1, EA);
3390        EA8 = tcg_temp_local_new();
3391        gen_addr_add(ctx, EA8, EA, 8);
3392        gen_qemu_st64(ctx, gpr2, EA8);
3393        tcg_temp_free(EA8);
3394#endif
3395    } else {
3396        gen_qemu_st8(ctx, cpu_gpr[reg], EA);
3397    }
3398    gen_set_label(l1);
3399    tcg_gen_movi_tl(cpu_reserve, -1);
3400}
3401#endif
3402
3403#define STCX(name, len)                                   \
3404static void gen_##name(DisasContext *ctx)                 \
3405{                                                         \
3406    TCGv t0;                                              \
3407    if (unlikely((len == 16) && (rD(ctx->opcode) & 1))) { \
3408        gen_inval_exception(ctx,                          \
3409                            POWERPC_EXCP_INVAL_INVAL);    \
3410        return;                                           \
3411    }                                                     \
3412    gen_set_access_type(ctx, ACCESS_RES);                 \
3413    t0 = tcg_temp_local_new();                            \
3414    gen_addr_reg_index(ctx, t0);                          \
3415    if (len > 1) {                                        \
3416        gen_check_align(ctx, t0, (len)-1);                \
3417    }                                                     \
3418    gen_conditional_store(ctx, t0, rS(ctx->opcode), len); \
3419    tcg_temp_free(t0);                                    \
3420}
3421
3422STCX(stbcx_, 1);
3423STCX(sthcx_, 2);
3424STCX(stwcx_, 4);
3425
3426#if defined(TARGET_PPC64)
3427/* ldarx */
3428LARX(ldarx, 8, ld64);
3429
3430/* lqarx */
3431static void gen_lqarx(DisasContext *ctx)
3432{
3433    TCGv EA;
3434    int rd = rD(ctx->opcode);
3435    TCGv gpr1, gpr2;
3436
3437    if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
3438                 (rd == rB(ctx->opcode)))) {
3439        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3440        return;
3441    }
3442
3443    gen_set_access_type(ctx, ACCESS_RES);
3444    EA = tcg_temp_local_new();
3445    gen_addr_reg_index(ctx, EA);
3446    gen_check_align(ctx, EA, 15);
3447    if (unlikely(ctx->le_mode)) {
3448        gpr1 = cpu_gpr[rd+1];
3449        gpr2 = cpu_gpr[rd];
3450    } else {
3451        gpr1 = cpu_gpr[rd];
3452        gpr2 = cpu_gpr[rd+1];
3453    }
3454    gen_qemu_ld64(ctx, gpr1, EA);
3455    tcg_gen_mov_tl(cpu_reserve, EA);
3456
3457    gen_addr_add(ctx, EA, EA, 8);
3458    gen_qemu_ld64(ctx, gpr2, EA);
3459
3460    tcg_gen_st_tl(gpr1, cpu_env, offsetof(CPUPPCState, reserve_val));
3461    tcg_gen_st_tl(gpr2, cpu_env, offsetof(CPUPPCState, reserve_val2));
3462
3463    tcg_temp_free(EA);
3464}
3465
3466/* stdcx. */
3467STCX(stdcx_, 8);
3468STCX(stqcx_, 16);
3469#endif /* defined(TARGET_PPC64) */
3470
3471/* sync */
3472static void gen_sync(DisasContext *ctx)
3473{
3474}
3475
3476/* wait */
3477static void gen_wait(DisasContext *ctx)
3478{
3479    TCGv_i32 t0 = tcg_temp_new_i32();
3480    tcg_gen_st_i32(t0, cpu_env,
3481                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3482    tcg_temp_free_i32(t0);
3483    /* Stop translation, as the CPU is supposed to sleep from now */
3484    gen_exception_err(ctx, EXCP_HLT, 1);
3485}
3486
3487/***                         Floating-point load                           ***/
3488#define GEN_LDF(name, ldop, opc, type)                                        \
3489static void glue(gen_, name)(DisasContext *ctx)                                       \
3490{                                                                             \
3491    TCGv EA;                                                                  \
3492    if (unlikely(!ctx->fpu_enabled)) {                                        \
3493        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3494        return;                                                               \
3495    }                                                                         \
3496    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3497    EA = tcg_temp_new();                                                      \
3498    gen_addr_imm_index(ctx, EA, 0);                                           \
3499    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3500    tcg_temp_free(EA);                                                        \
3501}
3502
3503#define GEN_LDUF(name, ldop, opc, type)                                       \
3504static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3505{                                                                             \
3506    TCGv EA;                                                                  \
3507    if (unlikely(!ctx->fpu_enabled)) {                                        \
3508        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3509        return;                                                               \
3510    }                                                                         \
3511    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3512        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3513        return;                                                               \
3514    }                                                                         \
3515    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3516    EA = tcg_temp_new();                                                      \
3517    gen_addr_imm_index(ctx, EA, 0);                                           \
3518    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3519    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3520    tcg_temp_free(EA);                                                        \
3521}
3522
3523#define GEN_LDUXF(name, ldop, opc, type)                                      \
3524static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3525{                                                                             \
3526    TCGv EA;                                                                  \
3527    if (unlikely(!ctx->fpu_enabled)) {                                        \
3528        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3529        return;                                                               \
3530    }                                                                         \
3531    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3532        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3533        return;                                                               \
3534    }                                                                         \
3535    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3536    EA = tcg_temp_new();                                                      \
3537    gen_addr_reg_index(ctx, EA);                                              \
3538    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3539    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3540    tcg_temp_free(EA);                                                        \
3541}
3542
3543#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3544static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3545{                                                                             \
3546    TCGv EA;                                                                  \
3547    if (unlikely(!ctx->fpu_enabled)) {                                        \
3548        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3549        return;                                                               \
3550    }                                                                         \
3551    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3552    EA = tcg_temp_new();                                                      \
3553    gen_addr_reg_index(ctx, EA);                                              \
3554    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3555    tcg_temp_free(EA);                                                        \
3556}
3557
3558#define GEN_LDFS(name, ldop, op, type)                                        \
3559GEN_LDF(name, ldop, op | 0x20, type);                                         \
3560GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3561GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3562GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3563
3564static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3565{
3566    TCGv t0 = tcg_temp_new();
3567    TCGv_i32 t1 = tcg_temp_new_i32();
3568    gen_qemu_ld32u(ctx, t0, arg2);
3569    tcg_gen_trunc_tl_i32(t1, t0);
3570    tcg_temp_free(t0);
3571    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3572    tcg_temp_free_i32(t1);
3573}
3574
3575 /* lfd lfdu lfdux lfdx */
3576GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3577 /* lfs lfsu lfsux lfsx */
3578GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3579
3580/* lfdp */
3581static void gen_lfdp(DisasContext *ctx)
3582{
3583    TCGv EA;
3584    if (unlikely(!ctx->fpu_enabled)) {
3585        gen_exception(ctx, POWERPC_EXCP_FPU);
3586        return;
3587    }
3588    gen_set_access_type(ctx, ACCESS_FLOAT);
3589    EA = tcg_temp_new();
3590    gen_addr_imm_index(ctx, EA, 0);
3591    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3592       64-bit byteswap already. */
3593    if (unlikely(ctx->le_mode)) {
3594        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3595        tcg_gen_addi_tl(EA, EA, 8);
3596        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3597    } else {
3598        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3599        tcg_gen_addi_tl(EA, EA, 8);
3600        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3601    }
3602    tcg_temp_free(EA);
3603}
3604
3605/* lfdpx */
3606static void gen_lfdpx(DisasContext *ctx)
3607{
3608    TCGv EA;
3609    if (unlikely(!ctx->fpu_enabled)) {
3610        gen_exception(ctx, POWERPC_EXCP_FPU);
3611        return;
3612    }
3613    gen_set_access_type(ctx, ACCESS_FLOAT);
3614    EA = tcg_temp_new();
3615    gen_addr_reg_index(ctx, EA);
3616    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3617       64-bit byteswap already. */
3618    if (unlikely(ctx->le_mode)) {
3619        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3620        tcg_gen_addi_tl(EA, EA, 8);
3621        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3622    } else {
3623        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3624        tcg_gen_addi_tl(EA, EA, 8);
3625        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3626    }
3627    tcg_temp_free(EA);
3628}
3629
3630/* lfiwax */
3631static void gen_lfiwax(DisasContext *ctx)
3632{
3633    TCGv EA;
3634    TCGv t0;
3635    if (unlikely(!ctx->fpu_enabled)) {
3636        gen_exception(ctx, POWERPC_EXCP_FPU);
3637        return;
3638    }
3639    gen_set_access_type(ctx, ACCESS_FLOAT);
3640    EA = tcg_temp_new();
3641    t0 = tcg_temp_new();
3642    gen_addr_reg_index(ctx, EA);
3643    gen_qemu_ld32s(ctx, t0, EA);
3644    tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
3645    tcg_temp_free(EA);
3646    tcg_temp_free(t0);
3647}
3648
3649/* lfiwzx */
3650static void gen_lfiwzx(DisasContext *ctx)
3651{
3652    TCGv EA;
3653    if (unlikely(!ctx->fpu_enabled)) {
3654        gen_exception(ctx, POWERPC_EXCP_FPU);
3655        return;
3656    }
3657    gen_set_access_type(ctx, ACCESS_FLOAT);
3658    EA = tcg_temp_new();
3659    gen_addr_reg_index(ctx, EA);
3660    gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3661    tcg_temp_free(EA);
3662}
3663/***                         Floating-point store                          ***/
3664#define GEN_STF(name, stop, opc, type)                                        \
3665static void glue(gen_, name)(DisasContext *ctx)                                       \
3666{                                                                             \
3667    TCGv EA;                                                                  \
3668    if (unlikely(!ctx->fpu_enabled)) {                                        \
3669        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3670        return;                                                               \
3671    }                                                                         \
3672    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3673    EA = tcg_temp_new();                                                      \
3674    gen_addr_imm_index(ctx, EA, 0);                                           \
3675    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3676    tcg_temp_free(EA);                                                        \
3677}
3678
3679#define GEN_STUF(name, stop, opc, type)                                       \
3680static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3681{                                                                             \
3682    TCGv EA;                                                                  \
3683    if (unlikely(!ctx->fpu_enabled)) {                                        \
3684        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3685        return;                                                               \
3686    }                                                                         \
3687    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3688        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3689        return;                                                               \
3690    }                                                                         \
3691    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3692    EA = tcg_temp_new();                                                      \
3693    gen_addr_imm_index(ctx, EA, 0);                                           \
3694    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3695    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3696    tcg_temp_free(EA);                                                        \
3697}
3698
3699#define GEN_STUXF(name, stop, opc, type)                                      \
3700static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3701{                                                                             \
3702    TCGv EA;                                                                  \
3703    if (unlikely(!ctx->fpu_enabled)) {                                        \
3704        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3705        return;                                                               \
3706    }                                                                         \
3707    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3708        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3709        return;                                                               \
3710    }                                                                         \
3711    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3712    EA = tcg_temp_new();                                                      \
3713    gen_addr_reg_index(ctx, EA);                                              \
3714    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3715    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3716    tcg_temp_free(EA);                                                        \
3717}
3718
3719#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3720static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3721{                                                                             \
3722    TCGv EA;                                                                  \
3723    if (unlikely(!ctx->fpu_enabled)) {                                        \
3724        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3725        return;                                                               \
3726    }                                                                         \
3727    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3728    EA = tcg_temp_new();                                                      \
3729    gen_addr_reg_index(ctx, EA);                                              \
3730    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3731    tcg_temp_free(EA);                                                        \
3732}
3733
3734#define GEN_STFS(name, stop, op, type)                                        \
3735GEN_STF(name, stop, op | 0x20, type);                                         \
3736GEN_STUF(name, stop, op | 0x21, type);                                        \
3737GEN_STUXF(name, stop, op | 0x01, type);                                       \
3738GEN_STXF(name, stop, 0x17, op | 0x00, type)
3739
3740static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3741{
3742    TCGv_i32 t0 = tcg_temp_new_i32();
3743    TCGv t1 = tcg_temp_new();
3744    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3745    tcg_gen_extu_i32_tl(t1, t0);
3746    tcg_temp_free_i32(t0);
3747    gen_qemu_st32(ctx, t1, arg2);
3748    tcg_temp_free(t1);
3749}
3750
3751/* stfd stfdu stfdux stfdx */
3752GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3753/* stfs stfsu stfsux stfsx */
3754GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3755
3756/* stfdp */
3757static void gen_stfdp(DisasContext *ctx)
3758{
3759    TCGv EA;
3760    if (unlikely(!ctx->fpu_enabled)) {
3761        gen_exception(ctx, POWERPC_EXCP_FPU);
3762        return;
3763    }
3764    gen_set_access_type(ctx, ACCESS_FLOAT);
3765    EA = tcg_temp_new();
3766    gen_addr_imm_index(ctx, EA, 0);
3767    /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3768       64-bit byteswap already. */
3769    if (unlikely(ctx->le_mode)) {
3770        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3771        tcg_gen_addi_tl(EA, EA, 8);
3772        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3773    } else {
3774        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3775        tcg_gen_addi_tl(EA, EA, 8);
3776        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3777    }
3778    tcg_temp_free(EA);
3779}
3780
3781/* stfdpx */
3782static void gen_stfdpx(DisasContext *ctx)
3783{
3784    TCGv EA;
3785    if (unlikely(!ctx->fpu_enabled)) {
3786        gen_exception(ctx, POWERPC_EXCP_FPU);
3787        return;
3788    }
3789    gen_set_access_type(ctx, ACCESS_FLOAT);
3790    EA = tcg_temp_new();
3791    gen_addr_reg_index(ctx, EA);
3792    /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3793       64-bit byteswap already. */
3794    if (unlikely(ctx->le_mode)) {
3795        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3796        tcg_gen_addi_tl(EA, EA, 8);
3797        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3798    } else {
3799        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3800        tcg_gen_addi_tl(EA, EA, 8);
3801        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3802    }
3803    tcg_temp_free(EA);
3804}
3805
3806/* Optional: */
3807static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3808{
3809    TCGv t0 = tcg_temp_new();
3810    tcg_gen_trunc_i64_tl(t0, arg1),
3811    gen_qemu_st32(ctx, t0, arg2);
3812    tcg_temp_free(t0);
3813}
3814/* stfiwx */
3815GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3816
3817static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
3818{
3819#if defined(TARGET_PPC64)
3820    if (ctx->has_cfar)
3821        tcg_gen_movi_tl(cpu_cfar, nip);
3822#endif
3823}
3824
3825/***                                Branch                                 ***/
3826static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3827{
3828    TranslationBlock *tb;
3829    tb = ctx->tb;
3830    if (NARROW_MODE(ctx)) {
3831        dest = (uint32_t) dest;
3832    }
3833    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3834        likely(!ctx->singlestep_enabled)) {
3835        tcg_gen_goto_tb(n);
3836        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3837        tcg_gen_exit_tb((uintptr_t)tb + n);
3838    } else {
3839        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3840        if (unlikely(ctx->singlestep_enabled)) {
3841            if ((ctx->singlestep_enabled &
3842                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3843                (ctx->exception == POWERPC_EXCP_BRANCH ||
3844                 ctx->exception == POWERPC_EXCP_TRACE)) {
3845                target_ulong tmp = ctx->nip;
3846                ctx->nip = dest;
3847                gen_exception(ctx, POWERPC_EXCP_TRACE);
3848                ctx->nip = tmp;
3849            }
3850            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3851                gen_debug_exception(ctx);
3852            }
3853        }
3854        tcg_gen_exit_tb(0);
3855    }
3856}
3857
3858static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3859{
3860    if (NARROW_MODE(ctx)) {
3861        nip = (uint32_t)nip;
3862    }
3863    tcg_gen_movi_tl(cpu_lr, nip);
3864}
3865
3866/* b ba bl bla */
3867static void gen_b(DisasContext *ctx)
3868{
3869    target_ulong li, target;
3870
3871    ctx->exception = POWERPC_EXCP_BRANCH;
3872    /* sign extend LI */
3873    li = LI(ctx->opcode);
3874    li = (li ^ 0x02000000) - 0x02000000;
3875    if (likely(AA(ctx->opcode) == 0)) {
3876        target = ctx->nip + li - 4;
3877    } else {
3878        target = li;
3879    }
3880    if (LK(ctx->opcode)) {
3881        gen_setlr(ctx, ctx->nip);
3882    }
3883    gen_update_cfar(ctx, ctx->nip);
3884    gen_goto_tb(ctx, 0, target);
3885}
3886
3887#define BCOND_IM  0
3888#define BCOND_LR  1
3889#define BCOND_CTR 2
3890#define BCOND_TAR 3
3891
3892static inline void gen_bcond(DisasContext *ctx, int type)
3893{
3894    uint32_t bo = BO(ctx->opcode);
3895    TCGLabel *l1;
3896    TCGv target;
3897
3898    ctx->exception = POWERPC_EXCP_BRANCH;
3899    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
3900        target = tcg_temp_local_new();
3901        if (type == BCOND_CTR)
3902            tcg_gen_mov_tl(target, cpu_ctr);
3903        else if (type == BCOND_TAR)
3904            gen_load_spr(target, SPR_TAR);
3905        else
3906            tcg_gen_mov_tl(target, cpu_lr);
3907    } else {
3908        TCGV_UNUSED(target);
3909    }
3910    if (LK(ctx->opcode))
3911        gen_setlr(ctx, ctx->nip);
3912    l1 = gen_new_label();
3913    if ((bo & 0x4) == 0) {
3914        /* Decrement and test CTR */
3915        TCGv temp = tcg_temp_new();
3916        if (unlikely(type == BCOND_CTR)) {
3917            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3918            return;
3919        }
3920        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3921        if (NARROW_MODE(ctx)) {
3922            tcg_gen_ext32u_tl(temp, cpu_ctr);
3923        } else {
3924            tcg_gen_mov_tl(temp, cpu_ctr);
3925        }
3926        if (bo & 0x2) {
3927            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3928        } else {
3929            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3930        }
3931        tcg_temp_free(temp);
3932    }
3933    if ((bo & 0x10) == 0) {
3934        /* Test CR */
3935        uint32_t bi = BI(ctx->opcode);
3936        uint32_t mask = 0x08 >> (bi & 0x03);
3937        TCGv_i32 temp = tcg_temp_new_i32();
3938
3939        if (bo & 0x8) {
3940            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3941            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3942        } else {
3943            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3944            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3945        }
3946        tcg_temp_free_i32(temp);
3947    }
3948    gen_update_cfar(ctx, ctx->nip);
3949    if (type == BCOND_IM) {
3950        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3951        if (likely(AA(ctx->opcode) == 0)) {
3952            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3953        } else {
3954            gen_goto_tb(ctx, 0, li);
3955        }
3956        gen_set_label(l1);
3957        gen_goto_tb(ctx, 1, ctx->nip);
3958    } else {
3959        if (NARROW_MODE(ctx)) {
3960            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3961        } else {
3962            tcg_gen_andi_tl(cpu_nip, target, ~3);
3963        }
3964        tcg_gen_exit_tb(0);
3965        gen_set_label(l1);
3966        gen_update_nip(ctx, ctx->nip);
3967        tcg_gen_exit_tb(0);
3968    }
3969    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
3970        tcg_temp_free(target);
3971    }
3972}
3973
3974static void gen_bc(DisasContext *ctx)
3975{
3976    gen_bcond(ctx, BCOND_IM);
3977}
3978
3979static void gen_bcctr(DisasContext *ctx)
3980{
3981    gen_bcond(ctx, BCOND_CTR);
3982}
3983
3984static void gen_bclr(DisasContext *ctx)
3985{
3986    gen_bcond(ctx, BCOND_LR);
3987}
3988
3989static void gen_bctar(DisasContext *ctx)
3990{
3991    gen_bcond(ctx, BCOND_TAR);
3992}
3993
3994/***                      Condition register logical                       ***/
3995#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
3996static void glue(gen_, name)(DisasContext *ctx)                                       \
3997{                                                                             \
3998    uint8_t bitmask;                                                          \
3999    int sh;                                                                   \
4000    TCGv_i32 t0, t1;                                                          \
4001    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
4002    t0 = tcg_temp_new_i32();                                                  \
4003    if (sh > 0)                                                               \
4004        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
4005    else if (sh < 0)                                                          \
4006        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
4007    else                                                                      \
4008        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
4009    t1 = tcg_temp_new_i32();                                                  \
4010    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
4011    if (sh > 0)                                                               \
4012        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
4013    else if (sh < 0)                                                          \
4014        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
4015    else                                                                      \
4016        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
4017    tcg_op(t0, t0, t1);                                                       \
4018    bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03);                             \
4019    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
4020    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
4021    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
4022    tcg_temp_free_i32(t0);                                                    \
4023    tcg_temp_free_i32(t1);                                                    \
4024}
4025
4026/* crand */
4027GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
4028/* crandc */
4029GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
4030/* creqv */
4031GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
4032/* crnand */
4033GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
4034/* crnor */
4035GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
4036/* cror */
4037GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
4038/* crorc */
4039GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
4040/* crxor */
4041GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
4042
4043/* mcrf */
4044static void gen_mcrf(DisasContext *ctx)
4045{
4046    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
4047}
4048
4049/***                           System linkage                              ***/
4050
4051/* rfi (supervisor only) */
4052static void gen_rfi(DisasContext *ctx)
4053{
4054#if defined(CONFIG_USER_ONLY)
4055    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4056#else
4057    /* Restore CPU state */
4058    if (unlikely(ctx->pr)) {
4059        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4060        return;
4061    }
4062    gen_update_cfar(ctx, ctx->nip);
4063    gen_helper_rfi(cpu_env);
4064    gen_sync_exception(ctx);
4065#endif
4066}
4067
4068#if defined(TARGET_PPC64)
4069static void gen_rfid(DisasContext *ctx)
4070{
4071#if defined(CONFIG_USER_ONLY)
4072    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4073#else
4074    /* Restore CPU state */
4075    if (unlikely(ctx->pr)) {
4076        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4077        return;
4078    }
4079    gen_update_cfar(ctx, ctx->nip);
4080    gen_helper_rfid(cpu_env);
4081    gen_sync_exception(ctx);
4082#endif
4083}
4084
4085static void gen_hrfid(DisasContext *ctx)
4086{
4087#if defined(CONFIG_USER_ONLY)
4088    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4089#else
4090    /* Restore CPU state */
4091    if (unlikely(!ctx->hv)) {
4092        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4093        return;
4094    }
4095    gen_helper_hrfid(cpu_env);
4096    gen_sync_exception(ctx);
4097#endif
4098}
4099#endif
4100
4101/* sc */
4102#if defined(CONFIG_USER_ONLY)
4103#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
4104#else
4105#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
4106#endif
4107static void gen_sc(DisasContext *ctx)
4108{
4109    uint32_t lev;
4110
4111    lev = (ctx->opcode >> 5) & 0x7F;
4112    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
4113}
4114
4115/***                                Trap                                   ***/
4116
4117/* tw */
4118static void gen_tw(DisasContext *ctx)
4119{
4120    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
4121    /* Update the nip since this might generate a trap exception */
4122    gen_update_nip(ctx, ctx->nip);
4123    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4124                  t0);
4125    tcg_temp_free_i32(t0);
4126}
4127
4128/* twi */
4129static void gen_twi(DisasContext *ctx)
4130{
4131    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4132    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
4133    /* Update the nip since this might generate a trap exception */
4134    gen_update_nip(ctx, ctx->nip);
4135    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4136    tcg_temp_free(t0);
4137    tcg_temp_free_i32(t1);
4138}
4139
4140#if defined(TARGET_PPC64)
4141/* td */
4142static void gen_td(DisasContext *ctx)
4143{
4144    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
4145    /* Update the nip since this might generate a trap exception */
4146    gen_update_nip(ctx, ctx->nip);
4147    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4148                  t0);
4149    tcg_temp_free_i32(t0);
4150}
4151
4152/* tdi */
4153static void gen_tdi(DisasContext *ctx)
4154{
4155    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4156    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
4157    /* Update the nip since this might generate a trap exception */
4158    gen_update_nip(ctx, ctx->nip);
4159    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4160    tcg_temp_free(t0);
4161    tcg_temp_free_i32(t1);
4162}
4163#endif
4164
4165/***                          Processor control                            ***/
4166
4167static void gen_read_xer(TCGv dst)
4168{
4169    TCGv t0 = tcg_temp_new();
4170    TCGv t1 = tcg_temp_new();
4171    TCGv t2 = tcg_temp_new();
4172    tcg_gen_mov_tl(dst, cpu_xer);
4173    tcg_gen_shli_tl(t0, cpu_so, XER_SO);
4174    tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
4175    tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
4176    tcg_gen_or_tl(t0, t0, t1);
4177    tcg_gen_or_tl(dst, dst, t2);
4178    tcg_gen_or_tl(dst, dst, t0);
4179    tcg_temp_free(t0);
4180    tcg_temp_free(t1);
4181    tcg_temp_free(t2);
4182}
4183
4184static void gen_write_xer(TCGv src)
4185{
4186    tcg_gen_andi_tl(cpu_xer, src,
4187                    ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
4188    tcg_gen_shri_tl(cpu_so, src, XER_SO);
4189    tcg_gen_shri_tl(cpu_ov, src, XER_OV);
4190    tcg_gen_shri_tl(cpu_ca, src, XER_CA);
4191    tcg_gen_andi_tl(cpu_so, cpu_so, 1);
4192    tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
4193    tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
4194}
4195
4196/* mcrxr */
4197static void gen_mcrxr(DisasContext *ctx)
4198{
4199    TCGv_i32 t0 = tcg_temp_new_i32();
4200    TCGv_i32 t1 = tcg_temp_new_i32();
4201    TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4202
4203    tcg_gen_trunc_tl_i32(t0, cpu_so);
4204    tcg_gen_trunc_tl_i32(t1, cpu_ov);
4205    tcg_gen_trunc_tl_i32(dst, cpu_ca);
4206    tcg_gen_shli_i32(t0, t0, 3);
4207    tcg_gen_shli_i32(t1, t1, 2);
4208    tcg_gen_shli_i32(dst, dst, 1);
4209    tcg_gen_or_i32(dst, dst, t0);
4210    tcg_gen_or_i32(dst, dst, t1);
4211    tcg_temp_free_i32(t0);
4212    tcg_temp_free_i32(t1);
4213
4214    tcg_gen_movi_tl(cpu_so, 0);
4215    tcg_gen_movi_tl(cpu_ov, 0);
4216    tcg_gen_movi_tl(cpu_ca, 0);
4217}
4218
4219/* mfcr mfocrf */
4220static void gen_mfcr(DisasContext *ctx)
4221{
4222    uint32_t crm, crn;
4223
4224    if (likely(ctx->opcode & 0x00100000)) {
4225        crm = CRM(ctx->opcode);
4226        if (likely(crm && ((crm & (crm - 1)) == 0))) {
4227            crn = ctz32 (crm);
4228            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
4229            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
4230                            cpu_gpr[rD(ctx->opcode)], crn * 4);
4231        }
4232    } else {
4233        TCGv_i32 t0 = tcg_temp_new_i32();
4234        tcg_gen_mov_i32(t0, cpu_crf[0]);
4235        tcg_gen_shli_i32(t0, t0, 4);
4236        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
4237        tcg_gen_shli_i32(t0, t0, 4);
4238        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
4239        tcg_gen_shli_i32(t0, t0, 4);
4240        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
4241        tcg_gen_shli_i32(t0, t0, 4);
4242        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
4243        tcg_gen_shli_i32(t0, t0, 4);
4244        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
4245        tcg_gen_shli_i32(t0, t0, 4);
4246        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
4247        tcg_gen_shli_i32(t0, t0, 4);
4248        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
4249        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
4250        tcg_temp_free_i32(t0);
4251    }
4252}
4253
4254/* mfmsr */
4255static void gen_mfmsr(DisasContext *ctx)
4256{
4257#if defined(CONFIG_USER_ONLY)
4258    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4259#else
4260    if (unlikely(ctx->pr)) {
4261        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4262        return;
4263    }
4264    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
4265#endif
4266}
4267
4268static void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
4269{
4270#if 0
4271    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
4272    printf("ERROR: try to access SPR %d !\n", sprn);
4273#endif
4274}
4275#define SPR_NOACCESS (&spr_noaccess)
4276
4277/* mfspr */
4278static inline void gen_op_mfspr(DisasContext *ctx)
4279{
4280    void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
4281    uint32_t sprn = SPR(ctx->opcode);
4282
4283#if defined(CONFIG_USER_ONLY)
4284    read_cb = ctx->spr_cb[sprn].uea_read;
4285#else
4286    if (ctx->pr) {
4287        read_cb = ctx->spr_cb[sprn].uea_read;
4288    } else if (ctx->hv) {
4289        read_cb = ctx->spr_cb[sprn].hea_read;
4290    } else {
4291        read_cb = ctx->spr_cb[sprn].oea_read;
4292    }
4293#endif
4294    if (likely(read_cb != NULL)) {
4295        if (likely(read_cb != SPR_NOACCESS)) {
4296            (*read_cb)(ctx, rD(ctx->opcode), sprn);
4297        } else {
4298            /* Privilege exception */
4299            /* This is a hack to avoid warnings when running Linux:
4300             * this OS breaks the PowerPC virtualisation model,
4301             * allowing userland application to read the PVR
4302             */
4303            if (sprn != SPR_PVR) {
4304                fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at "
4305                        TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4306                if (qemu_log_separate()) {
4307                    qemu_log("Trying to read privileged spr %d (0x%03x) at "
4308                             TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4309                }
4310            }
4311            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4312        }
4313    } else {
4314        /* Not defined */
4315        fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at "
4316                TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4317        if (qemu_log_separate()) {
4318            qemu_log("Trying to read invalid spr %d (0x%03x) at "
4319                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4320        }
4321        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4322    }
4323}
4324
4325static void gen_mfspr(DisasContext *ctx)
4326{
4327    gen_op_mfspr(ctx);
4328}
4329
4330/* mftb */
4331static void gen_mftb(DisasContext *ctx)
4332{
4333    gen_op_mfspr(ctx);
4334}
4335
4336/* mtcrf mtocrf*/
4337static void gen_mtcrf(DisasContext *ctx)
4338{
4339    uint32_t crm, crn;
4340
4341    crm = CRM(ctx->opcode);
4342    if (likely((ctx->opcode & 0x00100000))) {
4343        if (crm && ((crm & (crm - 1)) == 0)) {
4344            TCGv_i32 temp = tcg_temp_new_i32();
4345            crn = ctz32 (crm);
4346            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4347            tcg_gen_shri_i32(temp, temp, crn * 4);
4348            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
4349            tcg_temp_free_i32(temp);
4350        }
4351    } else {
4352        TCGv_i32 temp = tcg_temp_new_i32();
4353        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4354        for (crn = 0 ; crn < 8 ; crn++) {
4355            if (crm & (1 << crn)) {
4356                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4357                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4358            }
4359        }
4360        tcg_temp_free_i32(temp);
4361    }
4362}
4363
4364/* mtmsr */
4365#if defined(TARGET_PPC64)
4366static void gen_mtmsrd(DisasContext *ctx)
4367{
4368#if defined(CONFIG_USER_ONLY)
4369    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4370#else
4371    if (unlikely(ctx->pr)) {
4372        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4373        return;
4374    }
4375    if (ctx->opcode & 0x00010000) {
4376        /* Special form that does not need any synchronisation */
4377        TCGv t0 = tcg_temp_new();
4378        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4379        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
4380        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4381        tcg_temp_free(t0);
4382    } else {
4383        /* XXX: we need to update nip before the store
4384         *      if we enter power saving mode, we will exit the loop
4385         *      directly from ppc_store_msr
4386         */
4387        gen_update_nip(ctx, ctx->nip);
4388        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
4389        /* Must stop the translation as machine state (may have) changed */
4390        /* Note that mtmsr is not always defined as context-synchronizing */
4391        gen_stop_exception(ctx);
4392    }
4393#endif
4394}
4395#endif
4396
4397static void gen_mtmsr(DisasContext *ctx)
4398{
4399#if defined(CONFIG_USER_ONLY)
4400    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4401#else
4402    if (unlikely(ctx->pr)) {
4403        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4404        return;
4405    }
4406    if (ctx->opcode & 0x00010000) {
4407        /* Special form that does not need any synchronisation */
4408        TCGv t0 = tcg_temp_new();
4409        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4410        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
4411        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4412        tcg_temp_free(t0);
4413    } else {
4414        TCGv msr = tcg_temp_new();
4415
4416        /* XXX: we need to update nip before the store
4417         *      if we enter power saving mode, we will exit the loop
4418         *      directly from ppc_store_msr
4419         */
4420        gen_update_nip(ctx, ctx->nip);
4421#if defined(TARGET_PPC64)
4422        tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
4423#else
4424        tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
4425#endif
4426        gen_helper_store_msr(cpu_env, msr);
4427        tcg_temp_free(msr);
4428        /* Must stop the translation as machine state (may have) changed */
4429        /* Note that mtmsr is not always defined as context-synchronizing */
4430        gen_stop_exception(ctx);
4431    }
4432#endif
4433}
4434
4435/* mtspr */
4436static void gen_mtspr(DisasContext *ctx)
4437{
4438    void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
4439    uint32_t sprn = SPR(ctx->opcode);
4440
4441#if defined(CONFIG_USER_ONLY)
4442    write_cb = ctx->spr_cb[sprn].uea_write;
4443#else
4444    if (ctx->pr) {
4445        write_cb = ctx->spr_cb[sprn].uea_write;
4446    } else if (ctx->hv) {
4447        write_cb = ctx->spr_cb[sprn].hea_write;
4448    } else {
4449        write_cb = ctx->spr_cb[sprn].oea_write;
4450    }
4451#endif
4452    if (likely(write_cb != NULL)) {
4453        if (likely(write_cb != SPR_NOACCESS)) {
4454            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4455        } else {
4456            /* Privilege exception */
4457            fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at "
4458                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4459            if (qemu_log_separate()) {
4460                qemu_log("Trying to write privileged spr %d (0x%03x) at "
4461                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4462            }
4463            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4464        }
4465    } else {
4466        /* Not defined */
4467        if (qemu_log_separate()) {
4468            qemu_log("Trying to write invalid spr %d (0x%03x) at "
4469                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4470        }
4471        fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
4472                TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4473        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4474    }
4475}
4476
4477/***                         Cache management                              ***/
4478
4479/* dcbf */
4480static void gen_dcbf(DisasContext *ctx)
4481{
4482    /* XXX: specification says this is treated as a load by the MMU */
4483    TCGv t0;
4484    gen_set_access_type(ctx, ACCESS_CACHE);
4485    t0 = tcg_temp_new();
4486    gen_addr_reg_index(ctx, t0);
4487    gen_qemu_ld8u(ctx, t0, t0);
4488    tcg_temp_free(t0);
4489}
4490
4491/* dcbi (Supervisor only) */
4492static void gen_dcbi(DisasContext *ctx)
4493{
4494#if defined(CONFIG_USER_ONLY)
4495    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4496#else
4497    TCGv EA, val;
4498    if (unlikely(ctx->pr)) {
4499        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4500        return;
4501    }
4502    EA = tcg_temp_new();
4503    gen_set_access_type(ctx, ACCESS_CACHE);
4504    gen_addr_reg_index(ctx, EA);
4505    val = tcg_temp_new();
4506    /* XXX: specification says this should be treated as a store by the MMU */
4507    gen_qemu_ld8u(ctx, val, EA);
4508    gen_qemu_st8(ctx, val, EA);
4509    tcg_temp_free(val);
4510    tcg_temp_free(EA);
4511#endif
4512}
4513
4514/* dcdst */
4515static void gen_dcbst(DisasContext *ctx)
4516{
4517    /* XXX: specification say this is treated as a load by the MMU */
4518    TCGv t0;
4519    gen_set_access_type(ctx, ACCESS_CACHE);
4520    t0 = tcg_temp_new();
4521    gen_addr_reg_index(ctx, t0);
4522    gen_qemu_ld8u(ctx, t0, t0);
4523    tcg_temp_free(t0);
4524}
4525
4526/* dcbt */
4527static void gen_dcbt(DisasContext *ctx)
4528{
4529    /* interpreted as no-op */
4530    /* XXX: specification say this is treated as a load by the MMU
4531     *      but does not generate any exception
4532     */
4533}
4534
4535/* dcbtst */
4536static void gen_dcbtst(DisasContext *ctx)
4537{
4538    /* interpreted as no-op */
4539    /* XXX: specification say this is treated as a load by the MMU
4540     *      but does not generate any exception
4541     */
4542}
4543
4544/* dcbtls */
4545static void gen_dcbtls(DisasContext *ctx)
4546{
4547    /* Always fails locking the cache */
4548    TCGv t0 = tcg_temp_new();
4549    gen_load_spr(t0, SPR_Exxx_L1CSR0);
4550    tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
4551    gen_store_spr(SPR_Exxx_L1CSR0, t0);
4552    tcg_temp_free(t0);
4553}
4554
4555/* dcbz */
4556static void gen_dcbz(DisasContext *ctx)
4557{
4558    TCGv tcgv_addr;
4559    TCGv_i32 tcgv_is_dcbzl;
4560    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4561
4562    gen_set_access_type(ctx, ACCESS_CACHE);
4563    /* NIP cannot be restored if the memory exception comes from an helper */
4564    gen_update_nip(ctx, ctx->nip - 4);
4565    tcgv_addr = tcg_temp_new();
4566    tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
4567
4568    gen_addr_reg_index(ctx, tcgv_addr);
4569    gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
4570
4571    tcg_temp_free(tcgv_addr);
4572    tcg_temp_free_i32(tcgv_is_dcbzl);
4573}
4574
4575/* dst / dstt */
4576static void gen_dst(DisasContext *ctx)
4577{
4578    if (rA(ctx->opcode) == 0) {
4579        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4580    } else {
4581        /* interpreted as no-op */
4582    }
4583}
4584
4585/* dstst /dststt */
4586static void gen_dstst(DisasContext *ctx)
4587{
4588    if (rA(ctx->opcode) == 0) {
4589        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4590    } else {
4591        /* interpreted as no-op */
4592    }
4593
4594}
4595
4596/* dss / dssall */
4597static void gen_dss(DisasContext *ctx)
4598{
4599    /* interpreted as no-op */
4600}
4601
4602/* icbi */
4603static void gen_icbi(DisasContext *ctx)
4604{
4605    TCGv t0;
4606    gen_set_access_type(ctx, ACCESS_CACHE);
4607    /* NIP cannot be restored if the memory exception comes from an helper */
4608    gen_update_nip(ctx, ctx->nip - 4);
4609    t0 = tcg_temp_new();
4610    gen_addr_reg_index(ctx, t0);
4611    gen_helper_icbi(cpu_env, t0);
4612    tcg_temp_free(t0);
4613}
4614
4615/* Optional: */
4616/* dcba */
4617static void gen_dcba(DisasContext *ctx)
4618{
4619    /* interpreted as no-op */
4620    /* XXX: specification say this is treated as a store by the MMU
4621     *      but does not generate any exception
4622     */
4623}
4624
4625/***                    Segment register manipulation                      ***/
4626/* Supervisor only: */
4627
4628/* mfsr */
4629static void gen_mfsr(DisasContext *ctx)
4630{
4631#if defined(CONFIG_USER_ONLY)
4632    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4633#else
4634    TCGv t0;
4635    if (unlikely(ctx->pr)) {
4636        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4637        return;
4638    }
4639    t0 = tcg_const_tl(SR(ctx->opcode));
4640    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4641    tcg_temp_free(t0);
4642#endif
4643}
4644
4645/* mfsrin */
4646static void gen_mfsrin(DisasContext *ctx)
4647{
4648#if defined(CONFIG_USER_ONLY)
4649    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4650#else
4651    TCGv t0;
4652    if (unlikely(ctx->pr)) {
4653        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4654        return;
4655    }
4656    t0 = tcg_temp_new();
4657    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4658    tcg_gen_andi_tl(t0, t0, 0xF);
4659    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4660    tcg_temp_free(t0);
4661#endif
4662}
4663
4664/* mtsr */
4665static void gen_mtsr(DisasContext *ctx)
4666{
4667#if defined(CONFIG_USER_ONLY)
4668    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4669#else
4670    TCGv t0;
4671    if (unlikely(ctx->pr)) {
4672        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4673        return;
4674    }
4675    t0 = tcg_const_tl(SR(ctx->opcode));
4676    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4677    tcg_temp_free(t0);
4678#endif
4679}
4680
4681/* mtsrin */
4682static void gen_mtsrin(DisasContext *ctx)
4683{
4684#if defined(CONFIG_USER_ONLY)
4685    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4686#else
4687    TCGv t0;
4688    if (unlikely(ctx->pr)) {
4689        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4690        return;
4691    }
4692    t0 = tcg_temp_new();
4693    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4694    tcg_gen_andi_tl(t0, t0, 0xF);
4695    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4696    tcg_temp_free(t0);
4697#endif
4698}
4699
4700#if defined(TARGET_PPC64)
4701/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4702
4703/* mfsr */
4704static void gen_mfsr_64b(DisasContext *ctx)
4705{
4706#if defined(CONFIG_USER_ONLY)
4707    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4708#else
4709    TCGv t0;
4710    if (unlikely(ctx->pr)) {
4711        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4712        return;
4713    }
4714    t0 = tcg_const_tl(SR(ctx->opcode));
4715    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4716    tcg_temp_free(t0);
4717#endif
4718}
4719
4720/* mfsrin */
4721static void gen_mfsrin_64b(DisasContext *ctx)
4722{
4723#if defined(CONFIG_USER_ONLY)
4724    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4725#else
4726    TCGv t0;
4727    if (unlikely(ctx->pr)) {
4728        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4729        return;
4730    }
4731    t0 = tcg_temp_new();
4732    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4733    tcg_gen_andi_tl(t0, t0, 0xF);
4734    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4735    tcg_temp_free(t0);
4736#endif
4737}
4738
4739/* mtsr */
4740static void gen_mtsr_64b(DisasContext *ctx)
4741{
4742#if defined(CONFIG_USER_ONLY)
4743    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4744#else
4745    TCGv t0;
4746    if (unlikely(ctx->pr)) {
4747        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4748        return;
4749    }
4750    t0 = tcg_const_tl(SR(ctx->opcode));
4751    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4752    tcg_temp_free(t0);
4753#endif
4754}
4755
4756/* mtsrin */
4757static void gen_mtsrin_64b(DisasContext *ctx)
4758{
4759#if defined(CONFIG_USER_ONLY)
4760    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4761#else
4762    TCGv t0;
4763    if (unlikely(ctx->pr)) {
4764        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4765        return;
4766    }
4767    t0 = tcg_temp_new();
4768    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4769    tcg_gen_andi_tl(t0, t0, 0xF);
4770    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4771    tcg_temp_free(t0);
4772#endif
4773}
4774
4775/* slbmte */
4776static void gen_slbmte(DisasContext *ctx)
4777{
4778#if defined(CONFIG_USER_ONLY)
4779    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4780#else
4781    if (unlikely(ctx->pr)) {
4782        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4783        return;
4784    }
4785    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
4786                         cpu_gpr[rS(ctx->opcode)]);
4787#endif
4788}
4789
4790static void gen_slbmfee(DisasContext *ctx)
4791{
4792#if defined(CONFIG_USER_ONLY)
4793    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4794#else
4795    if (unlikely(ctx->pr)) {
4796        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4797        return;
4798    }
4799    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4800                             cpu_gpr[rB(ctx->opcode)]);
4801#endif
4802}
4803
4804static void gen_slbmfev(DisasContext *ctx)
4805{
4806#if defined(CONFIG_USER_ONLY)
4807    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4808#else
4809    if (unlikely(ctx->pr)) {
4810        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4811        return;
4812    }
4813    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4814                             cpu_gpr[rB(ctx->opcode)]);
4815#endif
4816}
4817#endif /* defined(TARGET_PPC64) */
4818
4819/***                      Lookaside buffer management                      ***/
4820/* Optional & supervisor only: */
4821
4822/* tlbia */
4823static void gen_tlbia(DisasContext *ctx)
4824{
4825#if defined(CONFIG_USER_ONLY)
4826    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4827#else
4828    if (unlikely(ctx->pr)) {
4829        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4830        return;
4831    }
4832    gen_helper_tlbia(cpu_env);
4833#endif
4834}
4835
4836/* tlbiel */
4837static void gen_tlbiel(DisasContext *ctx)
4838{
4839#if defined(CONFIG_USER_ONLY)
4840    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4841#else
4842    if (unlikely(ctx->pr)) {
4843        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4844        return;
4845    }
4846    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4847#endif
4848}
4849
4850/* tlbie */
4851static void gen_tlbie(DisasContext *ctx)
4852{
4853#if defined(CONFIG_USER_ONLY)
4854    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4855#else
4856    if (unlikely(ctx->pr)) {
4857        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4858        return;
4859    }
4860    if (NARROW_MODE(ctx)) {
4861        TCGv t0 = tcg_temp_new();
4862        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4863        gen_helper_tlbie(cpu_env, t0);
4864        tcg_temp_free(t0);
4865    } else {
4866        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4867    }
4868#endif
4869}
4870
4871/* tlbsync */
4872static void gen_tlbsync(DisasContext *ctx)
4873{
4874#if defined(CONFIG_USER_ONLY)
4875    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4876#else
4877    if (unlikely(ctx->pr)) {
4878        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4879        return;
4880    }
4881    /* This has no effect: it should ensure that all previous
4882     * tlbie have completed
4883     */
4884    gen_stop_exception(ctx);
4885#endif
4886}
4887
4888#if defined(TARGET_PPC64)
4889/* slbia */
4890static void gen_slbia(DisasContext *ctx)
4891{
4892#if defined(CONFIG_USER_ONLY)
4893    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4894#else
4895    if (unlikely(ctx->pr)) {
4896        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4897        return;
4898    }
4899    gen_helper_slbia(cpu_env);
4900#endif
4901}
4902
4903/* slbie */
4904static void gen_slbie(DisasContext *ctx)
4905{
4906#if defined(CONFIG_USER_ONLY)
4907    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4908#else
4909    if (unlikely(ctx->pr)) {
4910        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4911        return;
4912    }
4913    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4914#endif
4915}
4916#endif
4917
4918/***                              External control                         ***/
4919/* Optional: */
4920
4921/* eciwx */
4922static void gen_eciwx(DisasContext *ctx)
4923{
4924    TCGv t0;
4925    /* Should check EAR[E] ! */
4926    gen_set_access_type(ctx, ACCESS_EXT);
4927    t0 = tcg_temp_new();
4928    gen_addr_reg_index(ctx, t0);
4929    gen_check_align(ctx, t0, 0x03);
4930    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4931    tcg_temp_free(t0);
4932}
4933
4934/* ecowx */
4935static void gen_ecowx(DisasContext *ctx)
4936{
4937    TCGv t0;
4938    /* Should check EAR[E] ! */
4939    gen_set_access_type(ctx, ACCESS_EXT);
4940    t0 = tcg_temp_new();
4941    gen_addr_reg_index(ctx, t0);
4942    gen_check_align(ctx, t0, 0x03);
4943    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4944    tcg_temp_free(t0);
4945}
4946
4947/* PowerPC 601 specific instructions */
4948
4949/* abs - abs. */
4950static void gen_abs(DisasContext *ctx)
4951{
4952    TCGLabel *l1 = gen_new_label();
4953    TCGLabel *l2 = gen_new_label();
4954    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4955    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4956    tcg_gen_br(l2);
4957    gen_set_label(l1);
4958    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4959    gen_set_label(l2);
4960    if (unlikely(Rc(ctx->opcode) != 0))
4961        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4962}
4963
4964/* abso - abso. */
4965static void gen_abso(DisasContext *ctx)
4966{
4967    TCGLabel *l1 = gen_new_label();
4968    TCGLabel *l2 = gen_new_label();
4969    TCGLabel *l3 = gen_new_label();
4970    /* Start with XER OV disabled, the most likely case */
4971    tcg_gen_movi_tl(cpu_ov, 0);
4972    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4973    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4974    tcg_gen_movi_tl(cpu_ov, 1);
4975    tcg_gen_movi_tl(cpu_so, 1);
4976    tcg_gen_br(l2);
4977    gen_set_label(l1);
4978    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4979    tcg_gen_br(l3);
4980    gen_set_label(l2);
4981    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4982    gen_set_label(l3);
4983    if (unlikely(Rc(ctx->opcode) != 0))
4984        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4985}
4986
4987/* clcs */
4988static void gen_clcs(DisasContext *ctx)
4989{
4990    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4991    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4992    tcg_temp_free_i32(t0);
4993    /* Rc=1 sets CR0 to an undefined state */
4994}
4995
4996/* div - div. */
4997static void gen_div(DisasContext *ctx)
4998{
4999    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5000                   cpu_gpr[rB(ctx->opcode)]);
5001    if (unlikely(Rc(ctx->opcode) != 0))
5002        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5003}
5004
5005/* divo - divo. */
5006static void gen_divo(DisasContext *ctx)
5007{
5008    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5009                    cpu_gpr[rB(ctx->opcode)]);
5010    if (unlikely(Rc(ctx->opcode) != 0))
5011        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5012}
5013
5014/* divs - divs. */
5015static void gen_divs(DisasContext *ctx)
5016{
5017    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5018                    cpu_gpr[rB(ctx->opcode)]);
5019    if (unlikely(Rc(ctx->opcode) != 0))
5020        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5021}
5022
5023/* divso - divso. */
5024static void gen_divso(DisasContext *ctx)
5025{
5026    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
5027                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5028    if (unlikely(Rc(ctx->opcode) != 0))
5029        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5030}
5031
5032/* doz - doz. */
5033static void gen_doz(DisasContext *ctx)
5034{
5035    TCGLabel *l1 = gen_new_label();
5036    TCGLabel *l2 = gen_new_label();
5037    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5038    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5039    tcg_gen_br(l2);
5040    gen_set_label(l1);
5041    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5042    gen_set_label(l2);
5043    if (unlikely(Rc(ctx->opcode) != 0))
5044        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5045}
5046
5047/* dozo - dozo. */
5048static void gen_dozo(DisasContext *ctx)
5049{
5050    TCGLabel *l1 = gen_new_label();
5051    TCGLabel *l2 = gen_new_label();
5052    TCGv t0 = tcg_temp_new();
5053    TCGv t1 = tcg_temp_new();
5054    TCGv t2 = tcg_temp_new();
5055    /* Start with XER OV disabled, the most likely case */
5056    tcg_gen_movi_tl(cpu_ov, 0);
5057    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5058    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5059    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5060    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
5061    tcg_gen_andc_tl(t1, t1, t2);
5062    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
5063    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5064    tcg_gen_movi_tl(cpu_ov, 1);
5065    tcg_gen_movi_tl(cpu_so, 1);
5066    tcg_gen_br(l2);
5067    gen_set_label(l1);
5068    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5069    gen_set_label(l2);
5070    tcg_temp_free(t0);
5071    tcg_temp_free(t1);
5072    tcg_temp_free(t2);
5073    if (unlikely(Rc(ctx->opcode) != 0))
5074        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5075}
5076
5077/* dozi */
5078static void gen_dozi(DisasContext *ctx)
5079{
5080    target_long simm = SIMM(ctx->opcode);
5081    TCGLabel *l1 = gen_new_label();
5082    TCGLabel *l2 = gen_new_label();
5083    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
5084    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
5085    tcg_gen_br(l2);
5086    gen_set_label(l1);
5087    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5088    gen_set_label(l2);
5089    if (unlikely(Rc(ctx->opcode) != 0))
5090        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5091}
5092
5093/* lscbx - lscbx. */
5094static void gen_lscbx(DisasContext *ctx)
5095{
5096    TCGv t0 = tcg_temp_new();
5097    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
5098    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
5099    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
5100
5101    gen_addr_reg_index(ctx, t0);
5102    /* NIP cannot be restored if the memory exception comes from an helper */
5103    gen_update_nip(ctx, ctx->nip - 4);
5104    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
5105    tcg_temp_free_i32(t1);
5106    tcg_temp_free_i32(t2);
5107    tcg_temp_free_i32(t3);
5108    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
5109    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
5110    if (unlikely(Rc(ctx->opcode) != 0))
5111        gen_set_Rc0(ctx, t0);
5112    tcg_temp_free(t0);
5113}
5114
5115/* maskg - maskg. */
5116static void gen_maskg(DisasContext *ctx)
5117{
5118    TCGLabel *l1 = gen_new_label();
5119    TCGv t0 = tcg_temp_new();
5120    TCGv t1 = tcg_temp_new();
5121    TCGv t2 = tcg_temp_new();
5122    TCGv t3 = tcg_temp_new();
5123    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
5124    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5125    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
5126    tcg_gen_addi_tl(t2, t0, 1);
5127    tcg_gen_shr_tl(t2, t3, t2);
5128    tcg_gen_shr_tl(t3, t3, t1);
5129    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
5130    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5131    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5132    gen_set_label(l1);
5133    tcg_temp_free(t0);
5134    tcg_temp_free(t1);
5135    tcg_temp_free(t2);
5136    tcg_temp_free(t3);
5137    if (unlikely(Rc(ctx->opcode) != 0))
5138        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5139}
5140
5141/* maskir - maskir. */
5142static void gen_maskir(DisasContext *ctx)
5143{
5144    TCGv t0 = tcg_temp_new();
5145    TCGv t1 = tcg_temp_new();
5146    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5147    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5148    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5149    tcg_temp_free(t0);
5150    tcg_temp_free(t1);
5151    if (unlikely(Rc(ctx->opcode) != 0))
5152        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5153}
5154
5155/* mul - mul. */
5156static void gen_mul(DisasContext *ctx)
5157{
5158    TCGv_i64 t0 = tcg_temp_new_i64();
5159    TCGv_i64 t1 = tcg_temp_new_i64();
5160    TCGv t2 = tcg_temp_new();
5161    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5162    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5163    tcg_gen_mul_i64(t0, t0, t1);
5164    tcg_gen_trunc_i64_tl(t2, t0);
5165    gen_store_spr(SPR_MQ, t2);
5166    tcg_gen_shri_i64(t1, t0, 32);
5167    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5168    tcg_temp_free_i64(t0);
5169    tcg_temp_free_i64(t1);
5170    tcg_temp_free(t2);
5171    if (unlikely(Rc(ctx->opcode) != 0))
5172        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5173}
5174
5175/* mulo - mulo. */
5176static void gen_mulo(DisasContext *ctx)
5177{
5178    TCGLabel *l1 = gen_new_label();
5179    TCGv_i64 t0 = tcg_temp_new_i64();
5180    TCGv_i64 t1 = tcg_temp_new_i64();
5181    TCGv t2 = tcg_temp_new();
5182    /* Start with XER OV disabled, the most likely case */
5183    tcg_gen_movi_tl(cpu_ov, 0);
5184    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5185    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5186    tcg_gen_mul_i64(t0, t0, t1);
5187    tcg_gen_trunc_i64_tl(t2, t0);
5188    gen_store_spr(SPR_MQ, t2);
5189    tcg_gen_shri_i64(t1, t0, 32);
5190    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5191    tcg_gen_ext32s_i64(t1, t0);
5192    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
5193    tcg_gen_movi_tl(cpu_ov, 1);
5194    tcg_gen_movi_tl(cpu_so, 1);
5195    gen_set_label(l1);
5196    tcg_temp_free_i64(t0);
5197    tcg_temp_free_i64(t1);
5198    tcg_temp_free(t2);
5199    if (unlikely(Rc(ctx->opcode) != 0))
5200        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5201}
5202
5203/* nabs - nabs. */
5204static void gen_nabs(DisasContext *ctx)
5205{
5206    TCGLabel *l1 = gen_new_label();
5207    TCGLabel *l2 = gen_new_label();
5208    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5209    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5210    tcg_gen_br(l2);
5211    gen_set_label(l1);
5212    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5213    gen_set_label(l2);
5214    if (unlikely(Rc(ctx->opcode) != 0))
5215        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5216}
5217
5218/* nabso - nabso. */
5219static void gen_nabso(DisasContext *ctx)
5220{
5221    TCGLabel *l1 = gen_new_label();
5222    TCGLabel *l2 = gen_new_label();
5223    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5224    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5225    tcg_gen_br(l2);
5226    gen_set_label(l1);
5227    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5228    gen_set_label(l2);
5229    /* nabs never overflows */
5230    tcg_gen_movi_tl(cpu_ov, 0);
5231    if (unlikely(Rc(ctx->opcode) != 0))
5232        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5233}
5234
5235/* rlmi - rlmi. */
5236static void gen_rlmi(DisasContext *ctx)
5237{
5238    uint32_t mb = MB(ctx->opcode);
5239    uint32_t me = ME(ctx->opcode);
5240    TCGv t0 = tcg_temp_new();
5241    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5242    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5243    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
5244    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
5245    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
5246    tcg_temp_free(t0);
5247    if (unlikely(Rc(ctx->opcode) != 0))
5248        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5249}
5250
5251/* rrib - rrib. */
5252static void gen_rrib(DisasContext *ctx)
5253{
5254    TCGv t0 = tcg_temp_new();
5255    TCGv t1 = tcg_temp_new();
5256    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5257    tcg_gen_movi_tl(t1, 0x80000000);
5258    tcg_gen_shr_tl(t1, t1, t0);
5259    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5260    tcg_gen_and_tl(t0, t0, t1);
5261    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
5262    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5263    tcg_temp_free(t0);
5264    tcg_temp_free(t1);
5265    if (unlikely(Rc(ctx->opcode) != 0))
5266        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5267}
5268
5269/* sle - sle. */
5270static void gen_sle(DisasContext *ctx)
5271{
5272    TCGv t0 = tcg_temp_new();
5273    TCGv t1 = tcg_temp_new();
5274    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5275    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5276    tcg_gen_subfi_tl(t1, 32, t1);
5277    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5278    tcg_gen_or_tl(t1, t0, t1);
5279    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5280    gen_store_spr(SPR_MQ, t1);
5281    tcg_temp_free(t0);
5282    tcg_temp_free(t1);
5283    if (unlikely(Rc(ctx->opcode) != 0))
5284        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5285}
5286
5287/* sleq - sleq. */
5288static void gen_sleq(DisasContext *ctx)
5289{
5290    TCGv t0 = tcg_temp_new();
5291    TCGv t1 = tcg_temp_new();
5292    TCGv t2 = tcg_temp_new();
5293    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5294    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
5295    tcg_gen_shl_tl(t2, t2, t0);
5296    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5297    gen_load_spr(t1, SPR_MQ);
5298    gen_store_spr(SPR_MQ, t0);
5299    tcg_gen_and_tl(t0, t0, t2);
5300    tcg_gen_andc_tl(t1, t1, t2);
5301    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5302    tcg_temp_free(t0);
5303    tcg_temp_free(t1);
5304    tcg_temp_free(t2);
5305    if (unlikely(Rc(ctx->opcode) != 0))
5306        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5307}
5308
5309/* sliq - sliq. */
5310static void gen_sliq(DisasContext *ctx)
5311{
5312    int sh = SH(ctx->opcode);
5313    TCGv t0 = tcg_temp_new();
5314    TCGv t1 = tcg_temp_new();
5315    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5316    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5317    tcg_gen_or_tl(t1, t0, t1);
5318    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5319    gen_store_spr(SPR_MQ, t1);
5320    tcg_temp_free(t0);
5321    tcg_temp_free(t1);
5322    if (unlikely(Rc(ctx->opcode) != 0))
5323        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5324}
5325
5326/* slliq - slliq. */
5327static void gen_slliq(DisasContext *ctx)
5328{
5329    int sh = SH(ctx->opcode);
5330    TCGv t0 = tcg_temp_new();
5331    TCGv t1 = tcg_temp_new();
5332    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5333    gen_load_spr(t1, SPR_MQ);
5334    gen_store_spr(SPR_MQ, t0);
5335    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
5336    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
5337    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5338    tcg_temp_free(t0);
5339    tcg_temp_free(t1);
5340    if (unlikely(Rc(ctx->opcode) != 0))
5341        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5342}
5343
5344/* sllq - sllq. */
5345static void gen_sllq(DisasContext *ctx)
5346{
5347    TCGLabel *l1 = gen_new_label();
5348    TCGLabel *l2 = gen_new_label();
5349    TCGv t0 = tcg_temp_local_new();
5350    TCGv t1 = tcg_temp_local_new();
5351    TCGv t2 = tcg_temp_local_new();
5352    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5353    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5354    tcg_gen_shl_tl(t1, t1, t2);
5355    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5356    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5357    gen_load_spr(t0, SPR_MQ);
5358    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5359    tcg_gen_br(l2);
5360    gen_set_label(l1);
5361    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5362    gen_load_spr(t2, SPR_MQ);
5363    tcg_gen_andc_tl(t1, t2, t1);
5364    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5365    gen_set_label(l2);
5366    tcg_temp_free(t0);
5367    tcg_temp_free(t1);
5368    tcg_temp_free(t2);
5369    if (unlikely(Rc(ctx->opcode) != 0))
5370        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5371}
5372
5373/* slq - slq. */
5374static void gen_slq(DisasContext *ctx)
5375{
5376    TCGLabel *l1 = gen_new_label();
5377    TCGv t0 = tcg_temp_new();
5378    TCGv t1 = tcg_temp_new();
5379    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5380    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5381    tcg_gen_subfi_tl(t1, 32, t1);
5382    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5383    tcg_gen_or_tl(t1, t0, t1);
5384    gen_store_spr(SPR_MQ, t1);
5385    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5386    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5387    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5388    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5389    gen_set_label(l1);
5390    tcg_temp_free(t0);
5391    tcg_temp_free(t1);
5392    if (unlikely(Rc(ctx->opcode) != 0))
5393        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5394}
5395
5396/* sraiq - sraiq. */
5397static void gen_sraiq(DisasContext *ctx)
5398{
5399    int sh = SH(ctx->opcode);
5400    TCGLabel *l1 = gen_new_label();
5401    TCGv t0 = tcg_temp_new();
5402    TCGv t1 = tcg_temp_new();
5403    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5404    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5405    tcg_gen_or_tl(t0, t0, t1);
5406    gen_store_spr(SPR_MQ, t0);
5407    tcg_gen_movi_tl(cpu_ca, 0);
5408    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5409    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
5410    tcg_gen_movi_tl(cpu_ca, 1);
5411    gen_set_label(l1);
5412    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
5413    tcg_temp_free(t0);
5414    tcg_temp_free(t1);
5415    if (unlikely(Rc(ctx->opcode) != 0))
5416        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5417}
5418
5419/* sraq - sraq. */
5420static void gen_sraq(DisasContext *ctx)
5421{
5422    TCGLabel *l1 = gen_new_label();
5423    TCGLabel *l2 = gen_new_label();
5424    TCGv t0 = tcg_temp_new();
5425    TCGv t1 = tcg_temp_local_new();
5426    TCGv t2 = tcg_temp_local_new();
5427    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5428    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5429    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
5430    tcg_gen_subfi_tl(t2, 32, t2);
5431    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
5432    tcg_gen_or_tl(t0, t0, t2);
5433    gen_store_spr(SPR_MQ, t0);
5434    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5435    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
5436    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
5437    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
5438    gen_set_label(l1);
5439    tcg_temp_free(t0);
5440    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
5441    tcg_gen_movi_tl(cpu_ca, 0);
5442    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5443    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
5444    tcg_gen_movi_tl(cpu_ca, 1);
5445    gen_set_label(l2);
5446    tcg_temp_free(t1);
5447    tcg_temp_free(t2);
5448    if (unlikely(Rc(ctx->opcode) != 0))
5449        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5450}
5451
5452/* sre - sre. */
5453static void gen_sre(DisasContext *ctx)
5454{
5455    TCGv t0 = tcg_temp_new();
5456    TCGv t1 = tcg_temp_new();
5457    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5458    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5459    tcg_gen_subfi_tl(t1, 32, t1);
5460    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5461    tcg_gen_or_tl(t1, t0, t1);
5462    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5463    gen_store_spr(SPR_MQ, t1);
5464    tcg_temp_free(t0);
5465    tcg_temp_free(t1);
5466    if (unlikely(Rc(ctx->opcode) != 0))
5467        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5468}
5469
5470/* srea - srea. */
5471static void gen_srea(DisasContext *ctx)
5472{
5473    TCGv t0 = tcg_temp_new();
5474    TCGv t1 = tcg_temp_new();
5475    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5476    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5477    gen_store_spr(SPR_MQ, t0);
5478    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
5479    tcg_temp_free(t0);
5480    tcg_temp_free(t1);
5481    if (unlikely(Rc(ctx->opcode) != 0))
5482        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5483}
5484
5485/* sreq */
5486static void gen_sreq(DisasContext *ctx)
5487{
5488    TCGv t0 = tcg_temp_new();
5489    TCGv t1 = tcg_temp_new();
5490    TCGv t2 = tcg_temp_new();
5491    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5492    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5493    tcg_gen_shr_tl(t1, t1, t0);
5494    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5495    gen_load_spr(t2, SPR_MQ);
5496    gen_store_spr(SPR_MQ, t0);
5497    tcg_gen_and_tl(t0, t0, t1);
5498    tcg_gen_andc_tl(t2, t2, t1);
5499    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5500    tcg_temp_free(t0);
5501    tcg_temp_free(t1);
5502    tcg_temp_free(t2);
5503    if (unlikely(Rc(ctx->opcode) != 0))
5504        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5505}
5506
5507/* sriq */
5508static void gen_sriq(DisasContext *ctx)
5509{
5510    int sh = SH(ctx->opcode);
5511    TCGv t0 = tcg_temp_new();
5512    TCGv t1 = tcg_temp_new();
5513    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5514    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5515    tcg_gen_or_tl(t1, t0, t1);
5516    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5517    gen_store_spr(SPR_MQ, t1);
5518    tcg_temp_free(t0);
5519    tcg_temp_free(t1);
5520    if (unlikely(Rc(ctx->opcode) != 0))
5521        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5522}
5523
5524/* srliq */
5525static void gen_srliq(DisasContext *ctx)
5526{
5527    int sh = SH(ctx->opcode);
5528    TCGv t0 = tcg_temp_new();
5529    TCGv t1 = tcg_temp_new();
5530    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5531    gen_load_spr(t1, SPR_MQ);
5532    gen_store_spr(SPR_MQ, t0);
5533    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
5534    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5535    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5536    tcg_temp_free(t0);
5537    tcg_temp_free(t1);
5538    if (unlikely(Rc(ctx->opcode) != 0))
5539        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5540}
5541
5542/* srlq */
5543static void gen_srlq(DisasContext *ctx)
5544{
5545    TCGLabel *l1 = gen_new_label();
5546    TCGLabel *l2 = gen_new_label();
5547    TCGv t0 = tcg_temp_local_new();
5548    TCGv t1 = tcg_temp_local_new();
5549    TCGv t2 = tcg_temp_local_new();
5550    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5551    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5552    tcg_gen_shr_tl(t2, t1, t2);
5553    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5554    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5555    gen_load_spr(t0, SPR_MQ);
5556    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5557    tcg_gen_br(l2);
5558    gen_set_label(l1);
5559    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5560    tcg_gen_and_tl(t0, t0, t2);
5561    gen_load_spr(t1, SPR_MQ);
5562    tcg_gen_andc_tl(t1, t1, t2);
5563    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5564    gen_set_label(l2);
5565    tcg_temp_free(t0);
5566    tcg_temp_free(t1);
5567    tcg_temp_free(t2);
5568    if (unlikely(Rc(ctx->opcode) != 0))
5569        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5570}
5571
5572/* srq */
5573static void gen_srq(DisasContext *ctx)
5574{
5575    TCGLabel *l1 = gen_new_label();
5576    TCGv t0 = tcg_temp_new();
5577    TCGv t1 = tcg_temp_new();
5578    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5579    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5580    tcg_gen_subfi_tl(t1, 32, t1);
5581    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5582    tcg_gen_or_tl(t1, t0, t1);
5583    gen_store_spr(SPR_MQ, t1);
5584    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5585    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5586    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5587    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5588    gen_set_label(l1);
5589    tcg_temp_free(t0);
5590    tcg_temp_free(t1);
5591    if (unlikely(Rc(ctx->opcode) != 0))
5592        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5593}
5594
5595/* PowerPC 602 specific instructions */
5596
5597/* dsa  */
5598static void gen_dsa(DisasContext *ctx)
5599{
5600    /* XXX: TODO */
5601    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5602}
5603
5604/* esa */
5605static void gen_esa(DisasContext *ctx)
5606{
5607    /* XXX: TODO */
5608    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5609}
5610
5611/* mfrom */
5612static void gen_mfrom(DisasContext *ctx)
5613{
5614#if defined(CONFIG_USER_ONLY)
5615    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5616#else
5617    if (unlikely(ctx->pr)) {
5618        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5619        return;
5620    }
5621    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5622#endif
5623}
5624
5625/* 602 - 603 - G2 TLB management */
5626
5627/* tlbld */
5628static void gen_tlbld_6xx(DisasContext *ctx)
5629{
5630#if defined(CONFIG_USER_ONLY)
5631    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5632#else
5633    if (unlikely(ctx->pr)) {
5634        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5635        return;
5636    }
5637    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5638#endif
5639}
5640
5641/* tlbli */
5642static void gen_tlbli_6xx(DisasContext *ctx)
5643{
5644#if defined(CONFIG_USER_ONLY)
5645    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5646#else
5647    if (unlikely(ctx->pr)) {
5648        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5649        return;
5650    }
5651    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5652#endif
5653}
5654
5655/* 74xx TLB management */
5656
5657/* tlbld */
5658static void gen_tlbld_74xx(DisasContext *ctx)
5659{
5660#if defined(CONFIG_USER_ONLY)
5661    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5662#else
5663    if (unlikely(ctx->pr)) {
5664        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5665        return;
5666    }
5667    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5668#endif
5669}
5670
5671/* tlbli */
5672static void gen_tlbli_74xx(DisasContext *ctx)
5673{
5674#if defined(CONFIG_USER_ONLY)
5675    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5676#else
5677    if (unlikely(ctx->pr)) {
5678        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5679        return;
5680    }
5681    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5682#endif
5683}
5684
5685/* POWER instructions not in PowerPC 601 */
5686
5687/* clf */
5688static void gen_clf(DisasContext *ctx)
5689{
5690    /* Cache line flush: implemented as no-op */
5691}
5692
5693/* cli */
5694static void gen_cli(DisasContext *ctx)
5695{
5696    /* Cache line invalidate: privileged and treated as no-op */
5697#if defined(CONFIG_USER_ONLY)
5698    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5699#else
5700    if (unlikely(ctx->pr)) {
5701        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5702        return;
5703    }
5704#endif
5705}
5706
5707/* dclst */
5708static void gen_dclst(DisasContext *ctx)
5709{
5710    /* Data cache line store: treated as no-op */
5711}
5712
5713static void gen_mfsri(DisasContext *ctx)
5714{
5715#if defined(CONFIG_USER_ONLY)
5716    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5717#else
5718    int ra = rA(ctx->opcode);
5719    int rd = rD(ctx->opcode);
5720    TCGv t0;
5721    if (unlikely(ctx->pr)) {
5722        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5723        return;
5724    }
5725    t0 = tcg_temp_new();
5726    gen_addr_reg_index(ctx, t0);
5727    tcg_gen_shri_tl(t0, t0, 28);
5728    tcg_gen_andi_tl(t0, t0, 0xF);
5729    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5730    tcg_temp_free(t0);
5731    if (ra != 0 && ra != rd)
5732        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5733#endif
5734}
5735
5736static void gen_rac(DisasContext *ctx)
5737{
5738#if defined(CONFIG_USER_ONLY)
5739    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5740#else
5741    TCGv t0;
5742    if (unlikely(ctx->pr)) {
5743        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5744        return;
5745    }
5746    t0 = tcg_temp_new();
5747    gen_addr_reg_index(ctx, t0);
5748    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5749    tcg_temp_free(t0);
5750#endif
5751}
5752
5753static void gen_rfsvc(DisasContext *ctx)
5754{
5755#if defined(CONFIG_USER_ONLY)
5756    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5757#else
5758    if (unlikely(ctx->pr)) {
5759        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5760        return;
5761    }
5762    gen_helper_rfsvc(cpu_env);
5763    gen_sync_exception(ctx);
5764#endif
5765}
5766
5767/* svc is not implemented for now */
5768
5769/* POWER2 specific instructions */
5770/* Quad manipulation (load/store two floats at a time) */
5771
5772/* lfq */
5773static void gen_lfq(DisasContext *ctx)
5774{
5775    int rd = rD(ctx->opcode);
5776    TCGv t0;
5777    gen_set_access_type(ctx, ACCESS_FLOAT);
5778    t0 = tcg_temp_new();
5779    gen_addr_imm_index(ctx, t0, 0);
5780    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5781    gen_addr_add(ctx, t0, t0, 8);
5782    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5783    tcg_temp_free(t0);
5784}
5785
5786/* lfqu */
5787static void gen_lfqu(DisasContext *ctx)
5788{
5789    int ra = rA(ctx->opcode);
5790    int rd = rD(ctx->opcode);
5791    TCGv t0, t1;
5792    gen_set_access_type(ctx, ACCESS_FLOAT);
5793    t0 = tcg_temp_new();
5794    t1 = tcg_temp_new();
5795    gen_addr_imm_index(ctx, t0, 0);
5796    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5797    gen_addr_add(ctx, t1, t0, 8);
5798    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5799    if (ra != 0)
5800        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5801    tcg_temp_free(t0);
5802    tcg_temp_free(t1);
5803}
5804
5805/* lfqux */
5806static void gen_lfqux(DisasContext *ctx)
5807{
5808    int ra = rA(ctx->opcode);
5809    int rd = rD(ctx->opcode);
5810    gen_set_access_type(ctx, ACCESS_FLOAT);
5811    TCGv t0, t1;
5812    t0 = tcg_temp_new();
5813    gen_addr_reg_index(ctx, t0);
5814    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5815    t1 = tcg_temp_new();
5816    gen_addr_add(ctx, t1, t0, 8);
5817    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5818    tcg_temp_free(t1);
5819    if (ra != 0)
5820        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5821    tcg_temp_free(t0);
5822}
5823
5824/* lfqx */
5825static void gen_lfqx(DisasContext *ctx)
5826{
5827    int rd = rD(ctx->opcode);
5828    TCGv t0;
5829    gen_set_access_type(ctx, ACCESS_FLOAT);
5830    t0 = tcg_temp_new();
5831    gen_addr_reg_index(ctx, t0);
5832    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5833    gen_addr_add(ctx, t0, t0, 8);
5834    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5835    tcg_temp_free(t0);
5836}
5837
5838/* stfq */
5839static void gen_stfq(DisasContext *ctx)
5840{
5841    int rd = rD(ctx->opcode);
5842    TCGv t0;
5843    gen_set_access_type(ctx, ACCESS_FLOAT);
5844    t0 = tcg_temp_new();
5845    gen_addr_imm_index(ctx, t0, 0);
5846    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5847    gen_addr_add(ctx, t0, t0, 8);
5848    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5849    tcg_temp_free(t0);
5850}
5851
5852/* stfqu */
5853static void gen_stfqu(DisasContext *ctx)
5854{
5855    int ra = rA(ctx->opcode);
5856    int rd = rD(ctx->opcode);
5857    TCGv t0, t1;
5858    gen_set_access_type(ctx, ACCESS_FLOAT);
5859    t0 = tcg_temp_new();
5860    gen_addr_imm_index(ctx, t0, 0);
5861    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5862    t1 = tcg_temp_new();
5863    gen_addr_add(ctx, t1, t0, 8);
5864    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5865    tcg_temp_free(t1);
5866    if (ra != 0)
5867        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5868    tcg_temp_free(t0);
5869}
5870
5871/* stfqux */
5872static void gen_stfqux(DisasContext *ctx)
5873{
5874    int ra = rA(ctx->opcode);
5875    int rd = rD(ctx->opcode);
5876    TCGv t0, t1;
5877    gen_set_access_type(ctx, ACCESS_FLOAT);
5878    t0 = tcg_temp_new();
5879    gen_addr_reg_index(ctx, t0);
5880    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5881    t1 = tcg_temp_new();
5882    gen_addr_add(ctx, t1, t0, 8);
5883    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5884    tcg_temp_free(t1);
5885    if (ra != 0)
5886        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5887    tcg_temp_free(t0);
5888}
5889
5890/* stfqx */
5891static void gen_stfqx(DisasContext *ctx)
5892{
5893    int rd = rD(ctx->opcode);
5894    TCGv t0;
5895    gen_set_access_type(ctx, ACCESS_FLOAT);
5896    t0 = tcg_temp_new();
5897    gen_addr_reg_index(ctx, t0);
5898    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5899    gen_addr_add(ctx, t0, t0, 8);
5900    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5901    tcg_temp_free(t0);
5902}
5903
5904/* BookE specific instructions */
5905
5906/* XXX: not implemented on 440 ? */
5907static void gen_mfapidi(DisasContext *ctx)
5908{
5909    /* XXX: TODO */
5910    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5911}
5912
5913/* XXX: not implemented on 440 ? */
5914static void gen_tlbiva(DisasContext *ctx)
5915{
5916#if defined(CONFIG_USER_ONLY)
5917    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5918#else
5919    TCGv t0;
5920    if (unlikely(ctx->pr)) {
5921        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5922        return;
5923    }
5924    t0 = tcg_temp_new();
5925    gen_addr_reg_index(ctx, t0);
5926    gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5927    tcg_temp_free(t0);
5928#endif
5929}
5930
5931/* All 405 MAC instructions are translated here */
5932static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5933                                        int ra, int rb, int rt, int Rc)
5934{
5935    TCGv t0, t1;
5936
5937    t0 = tcg_temp_local_new();
5938    t1 = tcg_temp_local_new();
5939
5940    switch (opc3 & 0x0D) {
5941    case 0x05:
5942        /* macchw    - macchw.    - macchwo   - macchwo.   */
5943        /* macchws   - macchws.   - macchwso  - macchwso.  */
5944        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
5945        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
5946        /* mulchw - mulchw. */
5947        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5948        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5949        tcg_gen_ext16s_tl(t1, t1);
5950        break;
5951    case 0x04:
5952        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
5953        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
5954        /* mulchwu - mulchwu. */
5955        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5956        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5957        tcg_gen_ext16u_tl(t1, t1);
5958        break;
5959    case 0x01:
5960        /* machhw    - machhw.    - machhwo   - machhwo.   */
5961        /* machhws   - machhws.   - machhwso  - machhwso.  */
5962        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
5963        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
5964        /* mulhhw - mulhhw. */
5965        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5966        tcg_gen_ext16s_tl(t0, t0);
5967        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5968        tcg_gen_ext16s_tl(t1, t1);
5969        break;
5970    case 0x00:
5971        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
5972        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
5973        /* mulhhwu - mulhhwu. */
5974        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5975        tcg_gen_ext16u_tl(t0, t0);
5976        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5977        tcg_gen_ext16u_tl(t1, t1);
5978        break;
5979    case 0x0D:
5980        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
5981        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
5982        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
5983        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
5984        /* mullhw - mullhw. */
5985        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5986        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5987        break;
5988    case 0x0C:
5989        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
5990        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
5991        /* mullhwu - mullhwu. */
5992        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5993        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5994        break;
5995    }
5996    if (opc2 & 0x04) {
5997        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5998        tcg_gen_mul_tl(t1, t0, t1);
5999        if (opc2 & 0x02) {
6000            /* nmultiply-and-accumulate (0x0E) */
6001            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
6002        } else {
6003            /* multiply-and-accumulate (0x0C) */
6004            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
6005        }
6006
6007        if (opc3 & 0x12) {
6008            /* Check overflow and/or saturate */
6009            TCGLabel *l1 = gen_new_label();
6010
6011            if (opc3 & 0x10) {
6012                /* Start with XER OV disabled, the most likely case */
6013                tcg_gen_movi_tl(cpu_ov, 0);
6014            }
6015            if (opc3 & 0x01) {
6016                /* Signed */
6017                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
6018                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
6019                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
6020                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
6021                if (opc3 & 0x02) {
6022                    /* Saturate */
6023                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
6024                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
6025                }
6026            } else {
6027                /* Unsigned */
6028                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6029                if (opc3 & 0x02) {
6030                    /* Saturate */
6031                    tcg_gen_movi_tl(t0, UINT32_MAX);
6032                }
6033            }
6034            if (opc3 & 0x10) {
6035                /* Check overflow */
6036                tcg_gen_movi_tl(cpu_ov, 1);
6037                tcg_gen_movi_tl(cpu_so, 1);
6038            }
6039            gen_set_label(l1);
6040            tcg_gen_mov_tl(cpu_gpr[rt], t0);
6041        }
6042    } else {
6043        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
6044    }
6045    tcg_temp_free(t0);
6046    tcg_temp_free(t1);
6047    if (unlikely(Rc) != 0) {
6048        /* Update Rc0 */
6049        gen_set_Rc0(ctx, cpu_gpr[rt]);
6050    }
6051}
6052
6053#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
6054static void glue(gen_, name)(DisasContext *ctx)                               \
6055{                                                                             \
6056    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
6057                         rD(ctx->opcode), Rc(ctx->opcode));                   \
6058}
6059
6060/* macchw    - macchw.    */
6061GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
6062/* macchwo   - macchwo.   */
6063GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
6064/* macchws   - macchws.   */
6065GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
6066/* macchwso  - macchwso.  */
6067GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
6068/* macchwsu  - macchwsu.  */
6069GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
6070/* macchwsuo - macchwsuo. */
6071GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
6072/* macchwu   - macchwu.   */
6073GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
6074/* macchwuo  - macchwuo.  */
6075GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
6076/* machhw    - machhw.    */
6077GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
6078/* machhwo   - machhwo.   */
6079GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
6080/* machhws   - machhws.   */
6081GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
6082/* machhwso  - machhwso.  */
6083GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
6084/* machhwsu  - machhwsu.  */
6085GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
6086/* machhwsuo - machhwsuo. */
6087GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
6088/* machhwu   - machhwu.   */
6089GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
6090/* machhwuo  - machhwuo.  */
6091GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
6092/* maclhw    - maclhw.    */
6093GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
6094/* maclhwo   - maclhwo.   */
6095GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
6096/* maclhws   - maclhws.   */
6097GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
6098/* maclhwso  - maclhwso.  */
6099GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
6100/* maclhwu   - maclhwu.   */
6101GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
6102/* maclhwuo  - maclhwuo.  */
6103GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
6104/* maclhwsu  - maclhwsu.  */
6105GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
6106/* maclhwsuo - maclhwsuo. */
6107GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
6108/* nmacchw   - nmacchw.   */
6109GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
6110/* nmacchwo  - nmacchwo.  */
6111GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
6112/* nmacchws  - nmacchws.  */
6113GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
6114/* nmacchwso - nmacchwso. */
6115GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
6116/* nmachhw   - nmachhw.   */
6117GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
6118/* nmachhwo  - nmachhwo.  */
6119GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
6120/* nmachhws  - nmachhws.  */
6121GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
6122/* nmachhwso - nmachhwso. */
6123GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
6124/* nmaclhw   - nmaclhw.   */
6125GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
6126/* nmaclhwo  - nmaclhwo.  */
6127GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
6128/* nmaclhws  - nmaclhws.  */
6129GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
6130/* nmaclhwso - nmaclhwso. */
6131GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
6132
6133/* mulchw  - mulchw.  */
6134GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
6135/* mulchwu - mulchwu. */
6136GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
6137/* mulhhw  - mulhhw.  */
6138GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
6139/* mulhhwu - mulhhwu. */
6140GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
6141/* mullhw  - mullhw.  */
6142GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
6143/* mullhwu - mullhwu. */
6144GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
6145
6146/* mfdcr */
6147static void gen_mfdcr(DisasContext *ctx)
6148{
6149#if defined(CONFIG_USER_ONLY)
6150    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6151#else
6152    TCGv dcrn;
6153    if (unlikely(ctx->pr)) {
6154        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6155        return;
6156    }
6157    /* NIP cannot be restored if the memory exception comes from an helper */
6158    gen_update_nip(ctx, ctx->nip - 4);
6159    dcrn = tcg_const_tl(SPR(ctx->opcode));
6160    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
6161    tcg_temp_free(dcrn);
6162#endif
6163}
6164
6165/* mtdcr */
6166static void gen_mtdcr(DisasContext *ctx)
6167{
6168#if defined(CONFIG_USER_ONLY)
6169    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6170#else
6171    TCGv dcrn;
6172    if (unlikely(ctx->pr)) {
6173        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6174        return;
6175    }
6176    /* NIP cannot be restored if the memory exception comes from an helper */
6177    gen_update_nip(ctx, ctx->nip - 4);
6178    dcrn = tcg_const_tl(SPR(ctx->opcode));
6179    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
6180    tcg_temp_free(dcrn);
6181#endif
6182}
6183
6184/* mfdcrx */
6185/* XXX: not implemented on 440 ? */
6186static void gen_mfdcrx(DisasContext *ctx)
6187{
6188#if defined(CONFIG_USER_ONLY)
6189    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6190#else
6191    if (unlikely(ctx->pr)) {
6192        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6193        return;
6194    }
6195    /* NIP cannot be restored if the memory exception comes from an helper */
6196    gen_update_nip(ctx, ctx->nip - 4);
6197    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6198                        cpu_gpr[rA(ctx->opcode)]);
6199    /* Note: Rc update flag set leads to undefined state of Rc0 */
6200#endif
6201}
6202
6203/* mtdcrx */
6204/* XXX: not implemented on 440 ? */
6205static void gen_mtdcrx(DisasContext *ctx)
6206{
6207#if defined(CONFIG_USER_ONLY)
6208    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6209#else
6210    if (unlikely(ctx->pr)) {
6211        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
6212        return;
6213    }
6214    /* NIP cannot be restored if the memory exception comes from an helper */
6215    gen_update_nip(ctx, ctx->nip - 4);
6216    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
6217                         cpu_gpr[rS(ctx->opcode)]);
6218    /* Note: Rc update flag set leads to undefined state of Rc0 */
6219#endif
6220}
6221
6222/* mfdcrux (PPC 460) : user-mode access to DCR */
6223static void gen_mfdcrux(DisasContext *ctx)
6224{
6225    /* NIP cannot be restored if the memory exception comes from an helper */
6226    gen_update_nip(ctx, ctx->nip - 4);
6227    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6228                        cpu_gpr[rA(ctx->opcode)]);
6229    /* Note: Rc update flag set leads to undefined state of Rc0 */
6230}
6231
6232/* mtdcrux (PPC 460) : user-mode access to DCR */
6233static void gen_mtdcrux(DisasContext *ctx)
6234{
6235    /* NIP cannot be restored if the memory exception comes from an helper */
6236    gen_update_nip(ctx, ctx->nip - 4);
6237    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
6238                         cpu_gpr[rS(ctx->opcode)]);
6239    /* Note: Rc update flag set leads to undefined state of Rc0 */
6240}
6241
6242/* dccci */
6243static void gen_dccci(DisasContext *ctx)
6244{
6245#if defined(CONFIG_USER_ONLY)
6246    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6247#else
6248    if (unlikely(ctx->pr)) {
6249        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6250        return;
6251    }
6252    /* interpreted as no-op */
6253#endif
6254}
6255
6256/* dcread */
6257static void gen_dcread(DisasContext *ctx)
6258{
6259#if defined(CONFIG_USER_ONLY)
6260    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6261#else
6262    TCGv EA, val;
6263    if (unlikely(ctx->pr)) {
6264        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6265        return;
6266    }
6267    gen_set_access_type(ctx, ACCESS_CACHE);
6268    EA = tcg_temp_new();
6269    gen_addr_reg_index(ctx, EA);
6270    val = tcg_temp_new();
6271    gen_qemu_ld32u(ctx, val, EA);
6272    tcg_temp_free(val);
6273    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
6274    tcg_temp_free(EA);
6275#endif
6276}
6277
6278/* icbt */
6279static void gen_icbt_40x(DisasContext *ctx)
6280{
6281    /* interpreted as no-op */
6282    /* XXX: specification say this is treated as a load by the MMU
6283     *      but does not generate any exception
6284     */
6285}
6286
6287/* iccci */
6288static void gen_iccci(DisasContext *ctx)
6289{
6290#if defined(CONFIG_USER_ONLY)
6291    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6292#else
6293    if (unlikely(ctx->pr)) {
6294        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6295        return;
6296    }
6297    /* interpreted as no-op */
6298#endif
6299}
6300
6301/* icread */
6302static void gen_icread(DisasContext *ctx)
6303{
6304#if defined(CONFIG_USER_ONLY)
6305    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6306#else
6307    if (unlikely(ctx->pr)) {
6308        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6309        return;
6310    }
6311    /* interpreted as no-op */
6312#endif
6313}
6314
6315/* rfci (supervisor only) */
6316static void gen_rfci_40x(DisasContext *ctx)
6317{
6318#if defined(CONFIG_USER_ONLY)
6319    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6320#else
6321    if (unlikely(ctx->pr)) {
6322        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6323        return;
6324    }
6325    /* Restore CPU state */
6326    gen_helper_40x_rfci(cpu_env);
6327    gen_sync_exception(ctx);
6328#endif
6329}
6330
6331static void gen_rfci(DisasContext *ctx)
6332{
6333#if defined(CONFIG_USER_ONLY)
6334    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6335#else
6336    if (unlikely(ctx->pr)) {
6337        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6338        return;
6339    }
6340    /* Restore CPU state */
6341    gen_helper_rfci(cpu_env);
6342    gen_sync_exception(ctx);
6343#endif
6344}
6345
6346/* BookE specific */
6347
6348/* XXX: not implemented on 440 ? */
6349static void gen_rfdi(DisasContext *ctx)
6350{
6351#if defined(CONFIG_USER_ONLY)
6352    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6353#else
6354    if (unlikely(ctx->pr)) {
6355        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6356        return;
6357    }
6358    /* Restore CPU state */
6359    gen_helper_rfdi(cpu_env);
6360    gen_sync_exception(ctx);
6361#endif
6362}
6363
6364/* XXX: not implemented on 440 ? */
6365static void gen_rfmci(DisasContext *ctx)
6366{
6367#if defined(CONFIG_USER_ONLY)
6368    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6369#else
6370    if (unlikely(ctx->pr)) {
6371        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6372        return;
6373    }
6374    /* Restore CPU state */
6375    gen_helper_rfmci(cpu_env);
6376    gen_sync_exception(ctx);
6377#endif
6378}
6379
6380/* TLB management - PowerPC 405 implementation */
6381
6382/* tlbre */
6383static void gen_tlbre_40x(DisasContext *ctx)
6384{
6385#if defined(CONFIG_USER_ONLY)
6386    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6387#else
6388    if (unlikely(ctx->pr)) {
6389        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6390        return;
6391    }
6392    switch (rB(ctx->opcode)) {
6393    case 0:
6394        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
6395                                cpu_gpr[rA(ctx->opcode)]);
6396        break;
6397    case 1:
6398        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
6399                                cpu_gpr[rA(ctx->opcode)]);
6400        break;
6401    default:
6402        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6403        break;
6404    }
6405#endif
6406}
6407
6408/* tlbsx - tlbsx. */
6409static void gen_tlbsx_40x(DisasContext *ctx)
6410{
6411#if defined(CONFIG_USER_ONLY)
6412    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6413#else
6414    TCGv t0;
6415    if (unlikely(ctx->pr)) {
6416        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6417        return;
6418    }
6419    t0 = tcg_temp_new();
6420    gen_addr_reg_index(ctx, t0);
6421    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6422    tcg_temp_free(t0);
6423    if (Rc(ctx->opcode)) {
6424        TCGLabel *l1 = gen_new_label();
6425        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6426        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6427        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6428        gen_set_label(l1);
6429    }
6430#endif
6431}
6432
6433/* tlbwe */
6434static void gen_tlbwe_40x(DisasContext *ctx)
6435{
6436#if defined(CONFIG_USER_ONLY)
6437    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6438#else
6439    if (unlikely(ctx->pr)) {
6440        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6441        return;
6442    }
6443    switch (rB(ctx->opcode)) {
6444    case 0:
6445        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6446                                cpu_gpr[rS(ctx->opcode)]);
6447        break;
6448    case 1:
6449        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6450                                cpu_gpr[rS(ctx->opcode)]);
6451        break;
6452    default:
6453        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6454        break;
6455    }
6456#endif
6457}
6458
6459/* TLB management - PowerPC 440 implementation */
6460
6461/* tlbre */
6462static void gen_tlbre_440(DisasContext *ctx)
6463{
6464#if defined(CONFIG_USER_ONLY)
6465    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6466#else
6467    if (unlikely(ctx->pr)) {
6468        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6469        return;
6470    }
6471    switch (rB(ctx->opcode)) {
6472    case 0:
6473    case 1:
6474    case 2:
6475        {
6476            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6477            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6478                                 t0, cpu_gpr[rA(ctx->opcode)]);
6479            tcg_temp_free_i32(t0);
6480        }
6481        break;
6482    default:
6483        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6484        break;
6485    }
6486#endif
6487}
6488
6489/* tlbsx - tlbsx. */
6490static void gen_tlbsx_440(DisasContext *ctx)
6491{
6492#if defined(CONFIG_USER_ONLY)
6493    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6494#else
6495    TCGv t0;
6496    if (unlikely(ctx->pr)) {
6497        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6498        return;
6499    }
6500    t0 = tcg_temp_new();
6501    gen_addr_reg_index(ctx, t0);
6502    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6503    tcg_temp_free(t0);
6504    if (Rc(ctx->opcode)) {
6505        TCGLabel *l1 = gen_new_label();
6506        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6507        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6508        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6509        gen_set_label(l1);
6510    }
6511#endif
6512}
6513
6514/* tlbwe */
6515static void gen_tlbwe_440(DisasContext *ctx)
6516{
6517#if defined(CONFIG_USER_ONLY)
6518    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6519#else
6520    if (unlikely(ctx->pr)) {
6521        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6522        return;
6523    }
6524    switch (rB(ctx->opcode)) {
6525    case 0:
6526    case 1:
6527    case 2:
6528        {
6529            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6530            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6531                                 cpu_gpr[rS(ctx->opcode)]);
6532            tcg_temp_free_i32(t0);
6533        }
6534        break;
6535    default:
6536        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6537        break;
6538    }
6539#endif
6540}
6541
6542/* TLB management - PowerPC BookE 2.06 implementation */
6543
6544/* tlbre */
6545static void gen_tlbre_booke206(DisasContext *ctx)
6546{
6547#if defined(CONFIG_USER_ONLY)
6548    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6549#else
6550    if (unlikely(ctx->pr)) {
6551        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6552        return;
6553    }
6554
6555    gen_helper_booke206_tlbre(cpu_env);
6556#endif
6557}
6558
6559/* tlbsx - tlbsx. */
6560static void gen_tlbsx_booke206(DisasContext *ctx)
6561{
6562#if defined(CONFIG_USER_ONLY)
6563    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6564#else
6565    TCGv t0;
6566    if (unlikely(ctx->pr)) {
6567        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6568        return;
6569    }
6570
6571    if (rA(ctx->opcode)) {
6572        t0 = tcg_temp_new();
6573        tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6574    } else {
6575        t0 = tcg_const_tl(0);
6576    }
6577
6578    tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6579    gen_helper_booke206_tlbsx(cpu_env, t0);
6580    tcg_temp_free(t0);
6581#endif
6582}
6583
6584/* tlbwe */
6585static void gen_tlbwe_booke206(DisasContext *ctx)
6586{
6587#if defined(CONFIG_USER_ONLY)
6588    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6589#else
6590    if (unlikely(ctx->pr)) {
6591        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6592        return;
6593    }
6594    gen_update_nip(ctx, ctx->nip - 4);
6595    gen_helper_booke206_tlbwe(cpu_env);
6596#endif
6597}
6598
6599static void gen_tlbivax_booke206(DisasContext *ctx)
6600{
6601#if defined(CONFIG_USER_ONLY)
6602    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6603#else
6604    TCGv t0;
6605    if (unlikely(ctx->pr)) {
6606        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6607        return;
6608    }
6609
6610    t0 = tcg_temp_new();
6611    gen_addr_reg_index(ctx, t0);
6612
6613    gen_helper_booke206_tlbivax(cpu_env, t0);
6614    tcg_temp_free(t0);
6615#endif
6616}
6617
6618static void gen_tlbilx_booke206(DisasContext *ctx)
6619{
6620#if defined(CONFIG_USER_ONLY)
6621    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6622#else
6623    TCGv t0;
6624    if (unlikely(ctx->pr)) {
6625        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6626        return;
6627    }
6628
6629    t0 = tcg_temp_new();
6630    gen_addr_reg_index(ctx, t0);
6631
6632    switch((ctx->opcode >> 21) & 0x3) {
6633    case 0:
6634        gen_helper_booke206_tlbilx0(cpu_env, t0);
6635        break;
6636    case 1:
6637        gen_helper_booke206_tlbilx1(cpu_env, t0);
6638        break;
6639    case 3:
6640        gen_helper_booke206_tlbilx3(cpu_env, t0);
6641        break;
6642    default:
6643        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6644        break;
6645    }
6646
6647    tcg_temp_free(t0);
6648#endif
6649}
6650
6651
6652/* wrtee */
6653static void gen_wrtee(DisasContext *ctx)
6654{
6655#if defined(CONFIG_USER_ONLY)
6656    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6657#else
6658    TCGv t0;
6659    if (unlikely(ctx->pr)) {
6660        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6661        return;
6662    }
6663    t0 = tcg_temp_new();
6664    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6665    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6666    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6667    tcg_temp_free(t0);
6668    /* Stop translation to have a chance to raise an exception
6669     * if we just set msr_ee to 1
6670     */
6671    gen_stop_exception(ctx);
6672#endif
6673}
6674
6675/* wrteei */
6676static void gen_wrteei(DisasContext *ctx)
6677{
6678#if defined(CONFIG_USER_ONLY)
6679    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6680#else
6681    if (unlikely(ctx->pr)) {
6682        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6683        return;
6684    }
6685    if (ctx->opcode & 0x00008000) {
6686        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6687        /* Stop translation to have a chance to raise an exception */
6688        gen_stop_exception(ctx);
6689    } else {
6690        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6691    }
6692#endif
6693}
6694
6695/* PowerPC 440 specific instructions */
6696
6697/* dlmzb */
6698static void gen_dlmzb(DisasContext *ctx)
6699{
6700    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6701    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6702                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6703    tcg_temp_free_i32(t0);
6704}
6705
6706/* mbar replaces eieio on 440 */
6707static void gen_mbar(DisasContext *ctx)
6708{
6709    /* interpreted as no-op */
6710}
6711
6712/* msync replaces sync on 440 */
6713static void gen_msync_4xx(DisasContext *ctx)
6714{
6715    /* interpreted as no-op */
6716}
6717
6718/* icbt */
6719static void gen_icbt_440(DisasContext *ctx)
6720{
6721    /* interpreted as no-op */
6722    /* XXX: specification say this is treated as a load by the MMU
6723     *      but does not generate any exception
6724     */
6725}
6726
6727/* Embedded.Processor Control */
6728
6729static void gen_msgclr(DisasContext *ctx)
6730{
6731#if defined(CONFIG_USER_ONLY)
6732    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6733#else
6734    if (unlikely(ctx->pr)) {
6735        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6736        return;
6737    }
6738
6739    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
6740#endif
6741}
6742
6743static void gen_msgsnd(DisasContext *ctx)
6744{
6745#if defined(CONFIG_USER_ONLY)
6746    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6747#else
6748    if (unlikely(ctx->pr)) {
6749        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6750        return;
6751    }
6752
6753    gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
6754#endif
6755}
6756
6757/***                      Altivec vector extension                         ***/
6758/* Altivec registers moves */
6759
6760static inline TCGv_ptr gen_avr_ptr(int reg)
6761{
6762    TCGv_ptr r = tcg_temp_new_ptr();
6763    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6764    return r;
6765}
6766
6767#define GEN_VR_LDX(name, opc2, opc3)                                          \
6768static void glue(gen_, name)(DisasContext *ctx)                                       \
6769{                                                                             \
6770    TCGv EA;                                                                  \
6771    if (unlikely(!ctx->altivec_enabled)) {                                    \
6772        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6773        return;                                                               \
6774    }                                                                         \
6775    gen_set_access_type(ctx, ACCESS_INT);                                     \
6776    EA = tcg_temp_new();                                                      \
6777    gen_addr_reg_index(ctx, EA);                                              \
6778    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6779    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
6780       64-bit byteswap already. */                                            \
6781    if (ctx->le_mode) {                                                       \
6782        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6783        tcg_gen_addi_tl(EA, EA, 8);                                           \
6784        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6785    } else {                                                                  \
6786        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6787        tcg_gen_addi_tl(EA, EA, 8);                                           \
6788        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6789    }                                                                         \
6790    tcg_temp_free(EA);                                                        \
6791}
6792
6793#define GEN_VR_STX(name, opc2, opc3)                                          \
6794static void gen_st##name(DisasContext *ctx)                                   \
6795{                                                                             \
6796    TCGv EA;                                                                  \
6797    if (unlikely(!ctx->altivec_enabled)) {                                    \
6798        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6799        return;                                                               \
6800    }                                                                         \
6801    gen_set_access_type(ctx, ACCESS_INT);                                     \
6802    EA = tcg_temp_new();                                                      \
6803    gen_addr_reg_index(ctx, EA);                                              \
6804    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6805    /* We only need to swap high and low halves. gen_qemu_st64 does necessary \
6806       64-bit byteswap already. */                                            \
6807    if (ctx->le_mode) {                                                       \
6808        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6809        tcg_gen_addi_tl(EA, EA, 8);                                           \
6810        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6811    } else {                                                                  \
6812        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6813        tcg_gen_addi_tl(EA, EA, 8);                                           \
6814        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6815    }                                                                         \
6816    tcg_temp_free(EA);                                                        \
6817}
6818
6819#define GEN_VR_LVE(name, opc2, opc3, size)                              \
6820static void gen_lve##name(DisasContext *ctx)                            \
6821    {                                                                   \
6822        TCGv EA;                                                        \
6823        TCGv_ptr rs;                                                    \
6824        if (unlikely(!ctx->altivec_enabled)) {                          \
6825            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6826            return;                                                     \
6827        }                                                               \
6828        gen_set_access_type(ctx, ACCESS_INT);                           \
6829        EA = tcg_temp_new();                                            \
6830        gen_addr_reg_index(ctx, EA);                                    \
6831        if (size > 1) {                                                 \
6832            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
6833        }                                                               \
6834        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6835        gen_helper_lve##name(cpu_env, rs, EA);                          \
6836        tcg_temp_free(EA);                                              \
6837        tcg_temp_free_ptr(rs);                                          \
6838    }
6839
6840#define GEN_VR_STVE(name, opc2, opc3, size)                             \
6841static void gen_stve##name(DisasContext *ctx)                           \
6842    {                                                                   \
6843        TCGv EA;                                                        \
6844        TCGv_ptr rs;                                                    \
6845        if (unlikely(!ctx->altivec_enabled)) {                          \
6846            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6847            return;                                                     \
6848        }                                                               \
6849        gen_set_access_type(ctx, ACCESS_INT);                           \
6850        EA = tcg_temp_new();                                            \
6851        gen_addr_reg_index(ctx, EA);                                    \
6852        if (size > 1) {                                                 \
6853            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
6854        }                                                               \
6855        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6856        gen_helper_stve##name(cpu_env, rs, EA);                         \
6857        tcg_temp_free(EA);                                              \
6858        tcg_temp_free_ptr(rs);                                          \
6859    }
6860
6861GEN_VR_LDX(lvx, 0x07, 0x03);
6862/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6863GEN_VR_LDX(lvxl, 0x07, 0x0B);
6864
6865GEN_VR_LVE(bx, 0x07, 0x00, 1);
6866GEN_VR_LVE(hx, 0x07, 0x01, 2);
6867GEN_VR_LVE(wx, 0x07, 0x02, 4);
6868
6869GEN_VR_STX(svx, 0x07, 0x07);
6870/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6871GEN_VR_STX(svxl, 0x07, 0x0F);
6872
6873GEN_VR_STVE(bx, 0x07, 0x04, 1);
6874GEN_VR_STVE(hx, 0x07, 0x05, 2);
6875GEN_VR_STVE(wx, 0x07, 0x06, 4);
6876
6877static void gen_lvsl(DisasContext *ctx)
6878{
6879    TCGv_ptr rd;
6880    TCGv EA;
6881    if (unlikely(!ctx->altivec_enabled)) {
6882        gen_exception(ctx, POWERPC_EXCP_VPU);
6883        return;
6884    }
6885    EA = tcg_temp_new();
6886    gen_addr_reg_index(ctx, EA);
6887    rd = gen_avr_ptr(rD(ctx->opcode));
6888    gen_helper_lvsl(rd, EA);
6889    tcg_temp_free(EA);
6890    tcg_temp_free_ptr(rd);
6891}
6892
6893static void gen_lvsr(DisasContext *ctx)
6894{
6895    TCGv_ptr rd;
6896    TCGv EA;
6897    if (unlikely(!ctx->altivec_enabled)) {
6898        gen_exception(ctx, POWERPC_EXCP_VPU);
6899        return;
6900    }
6901    EA = tcg_temp_new();
6902    gen_addr_reg_index(ctx, EA);
6903    rd = gen_avr_ptr(rD(ctx->opcode));
6904    gen_helper_lvsr(rd, EA);
6905    tcg_temp_free(EA);
6906    tcg_temp_free_ptr(rd);
6907}
6908
6909static void gen_mfvscr(DisasContext *ctx)
6910{
6911    TCGv_i32 t;
6912    if (unlikely(!ctx->altivec_enabled)) {
6913        gen_exception(ctx, POWERPC_EXCP_VPU);
6914        return;
6915    }
6916    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6917    t = tcg_temp_new_i32();
6918    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6919    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6920    tcg_temp_free_i32(t);
6921}
6922
6923static void gen_mtvscr(DisasContext *ctx)
6924{
6925    TCGv_ptr p;
6926    if (unlikely(!ctx->altivec_enabled)) {
6927        gen_exception(ctx, POWERPC_EXCP_VPU);
6928        return;
6929    }
6930    p = gen_avr_ptr(rB(ctx->opcode));
6931    gen_helper_mtvscr(cpu_env, p);
6932    tcg_temp_free_ptr(p);
6933}
6934
6935/* Logical operations */
6936#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
6937static void glue(gen_, name)(DisasContext *ctx)                                 \
6938{                                                                       \
6939    if (unlikely(!ctx->altivec_enabled)) {                              \
6940        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6941        return;                                                         \
6942    }                                                                   \
6943    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6944    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6945}
6946
6947GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6948GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6949GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6950GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6951GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6952GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
6953GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
6954GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
6955
6956#define GEN_VXFORM(name, opc2, opc3)                                    \
6957static void glue(gen_, name)(DisasContext *ctx)                                 \
6958{                                                                       \
6959    TCGv_ptr ra, rb, rd;                                                \
6960    if (unlikely(!ctx->altivec_enabled)) {                              \
6961        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6962        return;                                                         \
6963    }                                                                   \
6964    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
6965    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
6966    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
6967    gen_helper_##name (rd, ra, rb);                                     \
6968    tcg_temp_free_ptr(ra);                                              \
6969    tcg_temp_free_ptr(rb);                                              \
6970    tcg_temp_free_ptr(rd);                                              \
6971}
6972
6973#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
6974static void glue(gen_, name)(DisasContext *ctx)                         \
6975{                                                                       \
6976    TCGv_ptr ra, rb, rd;                                                \
6977    if (unlikely(!ctx->altivec_enabled)) {                              \
6978        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6979        return;                                                         \
6980    }                                                                   \
6981    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
6982    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
6983    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
6984    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6985    tcg_temp_free_ptr(ra);                                              \
6986    tcg_temp_free_ptr(rb);                                              \
6987    tcg_temp_free_ptr(rd);                                              \
6988}
6989
6990#define GEN_VXFORM3(name, opc2, opc3)                                   \
6991static void glue(gen_, name)(DisasContext *ctx)                         \
6992{                                                                       \
6993    TCGv_ptr ra, rb, rc, rd;                                            \
6994    if (unlikely(!ctx->altivec_enabled)) {                              \
6995        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6996        return;                                                         \
6997    }                                                                   \
6998    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
6999    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
7000    rc = gen_avr_ptr(rC(ctx->opcode));                                  \
7001    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
7002    gen_helper_##name(rd, ra, rb, rc);                                  \
7003    tcg_temp_free_ptr(ra);                                              \
7004    tcg_temp_free_ptr(rb);                                              \
7005    tcg_temp_free_ptr(rc);                                              \
7006    tcg_temp_free_ptr(rd);                                              \
7007}
7008
7009/*
7010 * Support for Altivec instruction pairs that use bit 31 (Rc) as
7011 * an opcode bit.  In general, these pairs come from different
7012 * versions of the ISA, so we must also support a pair of flags for
7013 * each instruction.
7014 */
7015#define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)          \
7016static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
7017{                                                                      \
7018    if ((Rc(ctx->opcode) == 0) &&                                      \
7019        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7020        gen_##name0(ctx);                                              \
7021    } else if ((Rc(ctx->opcode) == 1) &&                               \
7022        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7023        gen_##name1(ctx);                                              \
7024    } else {                                                           \
7025        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
7026    }                                                                  \
7027}
7028
7029GEN_VXFORM(vaddubm, 0, 0);
7030GEN_VXFORM(vadduhm, 0, 1);
7031GEN_VXFORM(vadduwm, 0, 2);
7032GEN_VXFORM(vaddudm, 0, 3);
7033GEN_VXFORM(vsububm, 0, 16);
7034GEN_VXFORM(vsubuhm, 0, 17);
7035GEN_VXFORM(vsubuwm, 0, 18);
7036GEN_VXFORM(vsubudm, 0, 19);
7037GEN_VXFORM(vmaxub, 1, 0);
7038GEN_VXFORM(vmaxuh, 1, 1);
7039GEN_VXFORM(vmaxuw, 1, 2);
7040GEN_VXFORM(vmaxud, 1, 3);
7041GEN_VXFORM(vmaxsb, 1, 4);
7042GEN_VXFORM(vmaxsh, 1, 5);
7043GEN_VXFORM(vmaxsw, 1, 6);
7044GEN_VXFORM(vmaxsd, 1, 7);
7045GEN_VXFORM(vminub, 1, 8);
7046GEN_VXFORM(vminuh, 1, 9);
7047GEN_VXFORM(vminuw, 1, 10);
7048GEN_VXFORM(vminud, 1, 11);
7049GEN_VXFORM(vminsb, 1, 12);
7050GEN_VXFORM(vminsh, 1, 13);
7051GEN_VXFORM(vminsw, 1, 14);
7052GEN_VXFORM(vminsd, 1, 15);
7053GEN_VXFORM(vavgub, 1, 16);
7054GEN_VXFORM(vavguh, 1, 17);
7055GEN_VXFORM(vavguw, 1, 18);
7056GEN_VXFORM(vavgsb, 1, 20);
7057GEN_VXFORM(vavgsh, 1, 21);
7058GEN_VXFORM(vavgsw, 1, 22);
7059GEN_VXFORM(vmrghb, 6, 0);
7060GEN_VXFORM(vmrghh, 6, 1);
7061GEN_VXFORM(vmrghw, 6, 2);
7062GEN_VXFORM(vmrglb, 6, 4);
7063GEN_VXFORM(vmrglh, 6, 5);
7064GEN_VXFORM(vmrglw, 6, 6);
7065
7066static void gen_vmrgew(DisasContext *ctx)
7067{
7068    TCGv_i64 tmp;
7069    int VT, VA, VB;
7070    if (unlikely(!ctx->altivec_enabled)) {
7071        gen_exception(ctx, POWERPC_EXCP_VPU);
7072        return;
7073    }
7074    VT = rD(ctx->opcode);
7075    VA = rA(ctx->opcode);
7076    VB = rB(ctx->opcode);
7077    tmp = tcg_temp_new_i64();
7078    tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32);
7079    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32);
7080    tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32);
7081    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32);
7082    tcg_temp_free_i64(tmp);
7083}
7084
7085static void gen_vmrgow(DisasContext *ctx)
7086{
7087    int VT, VA, VB;
7088    if (unlikely(!ctx->altivec_enabled)) {
7089        gen_exception(ctx, POWERPC_EXCP_VPU);
7090        return;
7091    }
7092    VT = rD(ctx->opcode);
7093    VA = rA(ctx->opcode);
7094    VB = rB(ctx->opcode);
7095
7096    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32);
7097    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32);
7098}
7099
7100GEN_VXFORM(vmuloub, 4, 0);
7101GEN_VXFORM(vmulouh, 4, 1);
7102GEN_VXFORM(vmulouw, 4, 2);
7103GEN_VXFORM(vmuluwm, 4, 2);
7104GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
7105                vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
7106GEN_VXFORM(vmulosb, 4, 4);
7107GEN_VXFORM(vmulosh, 4, 5);
7108GEN_VXFORM(vmulosw, 4, 6);
7109GEN_VXFORM(vmuleub, 4, 8);
7110GEN_VXFORM(vmuleuh, 4, 9);
7111GEN_VXFORM(vmuleuw, 4, 10);
7112GEN_VXFORM(vmulesb, 4, 12);
7113GEN_VXFORM(vmulesh, 4, 13);
7114GEN_VXFORM(vmulesw, 4, 14);
7115GEN_VXFORM(vslb, 2, 4);
7116GEN_VXFORM(vslh, 2, 5);
7117GEN_VXFORM(vslw, 2, 6);
7118GEN_VXFORM(vsld, 2, 23);
7119GEN_VXFORM(vsrb, 2, 8);
7120GEN_VXFORM(vsrh, 2, 9);
7121GEN_VXFORM(vsrw, 2, 10);
7122GEN_VXFORM(vsrd, 2, 27);
7123GEN_VXFORM(vsrab, 2, 12);
7124GEN_VXFORM(vsrah, 2, 13);
7125GEN_VXFORM(vsraw, 2, 14);
7126GEN_VXFORM(vsrad, 2, 15);
7127GEN_VXFORM(vslo, 6, 16);
7128GEN_VXFORM(vsro, 6, 17);
7129GEN_VXFORM(vaddcuw, 0, 6);
7130GEN_VXFORM(vsubcuw, 0, 22);
7131GEN_VXFORM_ENV(vaddubs, 0, 8);
7132GEN_VXFORM_ENV(vadduhs, 0, 9);
7133GEN_VXFORM_ENV(vadduws, 0, 10);
7134GEN_VXFORM_ENV(vaddsbs, 0, 12);
7135GEN_VXFORM_ENV(vaddshs, 0, 13);
7136GEN_VXFORM_ENV(vaddsws, 0, 14);
7137GEN_VXFORM_ENV(vsububs, 0, 24);
7138GEN_VXFORM_ENV(vsubuhs, 0, 25);
7139GEN_VXFORM_ENV(vsubuws, 0, 26);
7140GEN_VXFORM_ENV(vsubsbs, 0, 28);
7141GEN_VXFORM_ENV(vsubshs, 0, 29);
7142GEN_VXFORM_ENV(vsubsws, 0, 30);
7143GEN_VXFORM(vadduqm, 0, 4);
7144GEN_VXFORM(vaddcuq, 0, 5);
7145GEN_VXFORM3(vaddeuqm, 30, 0);
7146GEN_VXFORM3(vaddecuq, 30, 0);
7147GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7148            vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
7149GEN_VXFORM(vsubuqm, 0, 20);
7150GEN_VXFORM(vsubcuq, 0, 21);
7151GEN_VXFORM3(vsubeuqm, 31, 0);
7152GEN_VXFORM3(vsubecuq, 31, 0);
7153GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7154            vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
7155GEN_VXFORM(vrlb, 2, 0);
7156GEN_VXFORM(vrlh, 2, 1);
7157GEN_VXFORM(vrlw, 2, 2);
7158GEN_VXFORM(vrld, 2, 3);
7159GEN_VXFORM(vsl, 2, 7);
7160GEN_VXFORM(vsr, 2, 11);
7161GEN_VXFORM_ENV(vpkuhum, 7, 0);
7162GEN_VXFORM_ENV(vpkuwum, 7, 1);
7163GEN_VXFORM_ENV(vpkudum, 7, 17);
7164GEN_VXFORM_ENV(vpkuhus, 7, 2);
7165GEN_VXFORM_ENV(vpkuwus, 7, 3);
7166GEN_VXFORM_ENV(vpkudus, 7, 19);
7167GEN_VXFORM_ENV(vpkshus, 7, 4);
7168GEN_VXFORM_ENV(vpkswus, 7, 5);
7169GEN_VXFORM_ENV(vpksdus, 7, 21);
7170GEN_VXFORM_ENV(vpkshss, 7, 6);
7171GEN_VXFORM_ENV(vpkswss, 7, 7);
7172GEN_VXFORM_ENV(vpksdss, 7, 23);
7173GEN_VXFORM(vpkpx, 7, 12);
7174GEN_VXFORM_ENV(vsum4ubs, 4, 24);
7175GEN_VXFORM_ENV(vsum4sbs, 4, 28);
7176GEN_VXFORM_ENV(vsum4shs, 4, 25);
7177GEN_VXFORM_ENV(vsum2sws, 4, 26);
7178GEN_VXFORM_ENV(vsumsws, 4, 30);
7179GEN_VXFORM_ENV(vaddfp, 5, 0);
7180GEN_VXFORM_ENV(vsubfp, 5, 1);
7181GEN_VXFORM_ENV(vmaxfp, 5, 16);
7182GEN_VXFORM_ENV(vminfp, 5, 17);
7183
7184#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
7185static void glue(gen_, name)(DisasContext *ctx)                         \
7186    {                                                                   \
7187        TCGv_ptr ra, rb, rd;                                            \
7188        if (unlikely(!ctx->altivec_enabled)) {                          \
7189            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7190            return;                                                     \
7191        }                                                               \
7192        ra = gen_avr_ptr(rA(ctx->opcode));                              \
7193        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7194        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7195        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
7196        tcg_temp_free_ptr(ra);                                          \
7197        tcg_temp_free_ptr(rb);                                          \
7198        tcg_temp_free_ptr(rd);                                          \
7199    }
7200
7201#define GEN_VXRFORM(name, opc2, opc3)                                \
7202    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
7203    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
7204
7205/*
7206 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
7207 * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
7208 * come from different versions of the ISA, so we must also support a
7209 * pair of flags for each instruction.
7210 */
7211#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
7212static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
7213{                                                                      \
7214    if ((Rc(ctx->opcode) == 0) &&                                      \
7215        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7216        if (Rc21(ctx->opcode) == 0) {                                  \
7217            gen_##name0(ctx);                                          \
7218        } else {                                                       \
7219            gen_##name0##_(ctx);                                       \
7220        }                                                              \
7221    } else if ((Rc(ctx->opcode) == 1) &&                               \
7222        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7223        if (Rc21(ctx->opcode) == 0) {                                  \
7224            gen_##name1(ctx);                                          \
7225        } else {                                                       \
7226            gen_##name1##_(ctx);                                       \
7227        }                                                              \
7228    } else {                                                           \
7229        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
7230    }                                                                  \
7231}
7232
7233GEN_VXRFORM(vcmpequb, 3, 0)
7234GEN_VXRFORM(vcmpequh, 3, 1)
7235GEN_VXRFORM(vcmpequw, 3, 2)
7236GEN_VXRFORM(vcmpequd, 3, 3)
7237GEN_VXRFORM(vcmpgtsb, 3, 12)
7238GEN_VXRFORM(vcmpgtsh, 3, 13)
7239GEN_VXRFORM(vcmpgtsw, 3, 14)
7240GEN_VXRFORM(vcmpgtsd, 3, 15)
7241GEN_VXRFORM(vcmpgtub, 3, 8)
7242GEN_VXRFORM(vcmpgtuh, 3, 9)
7243GEN_VXRFORM(vcmpgtuw, 3, 10)
7244GEN_VXRFORM(vcmpgtud, 3, 11)
7245GEN_VXRFORM(vcmpeqfp, 3, 3)
7246GEN_VXRFORM(vcmpgefp, 3, 7)
7247GEN_VXRFORM(vcmpgtfp, 3, 11)
7248GEN_VXRFORM(vcmpbfp, 3, 15)
7249
7250GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
7251                 vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
7252GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
7253                 vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
7254GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
7255                 vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
7256
7257#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
7258static void glue(gen_, name)(DisasContext *ctx)                         \
7259    {                                                                   \
7260        TCGv_ptr rd;                                                    \
7261        TCGv_i32 simm;                                                  \
7262        if (unlikely(!ctx->altivec_enabled)) {                          \
7263            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7264            return;                                                     \
7265        }                                                               \
7266        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
7267        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7268        gen_helper_##name (rd, simm);                                   \
7269        tcg_temp_free_i32(simm);                                        \
7270        tcg_temp_free_ptr(rd);                                          \
7271    }
7272
7273GEN_VXFORM_SIMM(vspltisb, 6, 12);
7274GEN_VXFORM_SIMM(vspltish, 6, 13);
7275GEN_VXFORM_SIMM(vspltisw, 6, 14);
7276
7277#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
7278static void glue(gen_, name)(DisasContext *ctx)                                 \
7279    {                                                                   \
7280        TCGv_ptr rb, rd;                                                \
7281        if (unlikely(!ctx->altivec_enabled)) {                          \
7282            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7283            return;                                                     \
7284        }                                                               \
7285        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7286        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7287        gen_helper_##name (rd, rb);                                     \
7288        tcg_temp_free_ptr(rb);                                          \
7289        tcg_temp_free_ptr(rd);                                         \
7290    }
7291
7292#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
7293static void glue(gen_, name)(DisasContext *ctx)                         \
7294    {                                                                   \
7295        TCGv_ptr rb, rd;                                                \
7296                                                                        \
7297        if (unlikely(!ctx->altivec_enabled)) {                          \
7298            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7299            return;                                                     \
7300        }                                                               \
7301        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7302        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7303        gen_helper_##name(cpu_env, rd, rb);                             \
7304        tcg_temp_free_ptr(rb);                                          \
7305        tcg_temp_free_ptr(rd);                                          \
7306    }
7307
7308GEN_VXFORM_NOA(vupkhsb, 7, 8);
7309GEN_VXFORM_NOA(vupkhsh, 7, 9);
7310GEN_VXFORM_NOA(vupkhsw, 7, 25);
7311GEN_VXFORM_NOA(vupklsb, 7, 10);
7312GEN_VXFORM_NOA(vupklsh, 7, 11);
7313GEN_VXFORM_NOA(vupklsw, 7, 27);
7314GEN_VXFORM_NOA(vupkhpx, 7, 13);
7315GEN_VXFORM_NOA(vupklpx, 7, 15);
7316GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
7317GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
7318GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
7319GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
7320GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
7321GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
7322GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
7323GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
7324
7325#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
7326static void glue(gen_, name)(DisasContext *ctx)                                 \
7327    {                                                                   \
7328        TCGv_ptr rd;                                                    \
7329        TCGv_i32 simm;                                                  \
7330        if (unlikely(!ctx->altivec_enabled)) {                          \
7331            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7332            return;                                                     \
7333        }                                                               \
7334        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
7335        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7336        gen_helper_##name (rd, simm);                                   \
7337        tcg_temp_free_i32(simm);                                        \
7338        tcg_temp_free_ptr(rd);                                          \
7339    }
7340
7341#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
7342static void glue(gen_, name)(DisasContext *ctx)                                 \
7343    {                                                                   \
7344        TCGv_ptr rb, rd;                                                \
7345        TCGv_i32 uimm;                                                  \
7346        if (unlikely(!ctx->altivec_enabled)) {                          \
7347            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7348            return;                                                     \
7349        }                                                               \
7350        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
7351        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7352        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7353        gen_helper_##name (rd, rb, uimm);                               \
7354        tcg_temp_free_i32(uimm);                                        \
7355        tcg_temp_free_ptr(rb);                                          \
7356        tcg_temp_free_ptr(rd);                                          \
7357    }
7358
7359#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
7360static void glue(gen_, name)(DisasContext *ctx)                         \
7361    {                                                                   \
7362        TCGv_ptr rb, rd;                                                \
7363        TCGv_i32 uimm;                                                  \
7364                                                                        \
7365        if (unlikely(!ctx->altivec_enabled)) {                          \
7366            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7367            return;                                                     \
7368        }                                                               \
7369        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
7370        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7371        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7372        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
7373        tcg_temp_free_i32(uimm);                                        \
7374        tcg_temp_free_ptr(rb);                                          \
7375        tcg_temp_free_ptr(rd);                                          \
7376    }
7377
7378GEN_VXFORM_UIMM(vspltb, 6, 8);
7379GEN_VXFORM_UIMM(vsplth, 6, 9);
7380GEN_VXFORM_UIMM(vspltw, 6, 10);
7381GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
7382GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
7383GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
7384GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
7385
7386static void gen_vsldoi(DisasContext *ctx)
7387{
7388    TCGv_ptr ra, rb, rd;
7389    TCGv_i32 sh;
7390    if (unlikely(!ctx->altivec_enabled)) {
7391        gen_exception(ctx, POWERPC_EXCP_VPU);
7392        return;
7393    }
7394    ra = gen_avr_ptr(rA(ctx->opcode));
7395    rb = gen_avr_ptr(rB(ctx->opcode));
7396    rd = gen_avr_ptr(rD(ctx->opcode));
7397    sh = tcg_const_i32(VSH(ctx->opcode));
7398    gen_helper_vsldoi (rd, ra, rb, sh);
7399    tcg_temp_free_ptr(ra);
7400    tcg_temp_free_ptr(rb);
7401    tcg_temp_free_ptr(rd);
7402    tcg_temp_free_i32(sh);
7403}
7404
7405#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
7406static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
7407    {                                                                   \
7408        TCGv_ptr ra, rb, rc, rd;                                        \
7409        if (unlikely(!ctx->altivec_enabled)) {                          \
7410            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7411            return;                                                     \
7412        }                                                               \
7413        ra = gen_avr_ptr(rA(ctx->opcode));                              \
7414        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7415        rc = gen_avr_ptr(rC(ctx->opcode));                              \
7416        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7417        if (Rc(ctx->opcode)) {                                          \
7418            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
7419        } else {                                                        \
7420            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
7421        }                                                               \
7422        tcg_temp_free_ptr(ra);                                          \
7423        tcg_temp_free_ptr(rb);                                          \
7424        tcg_temp_free_ptr(rc);                                          \
7425        tcg_temp_free_ptr(rd);                                          \
7426    }
7427
7428GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
7429
7430static void gen_vmladduhm(DisasContext *ctx)
7431{
7432    TCGv_ptr ra, rb, rc, rd;
7433    if (unlikely(!ctx->altivec_enabled)) {
7434        gen_exception(ctx, POWERPC_EXCP_VPU);
7435        return;
7436    }
7437    ra = gen_avr_ptr(rA(ctx->opcode));
7438    rb = gen_avr_ptr(rB(ctx->opcode));
7439    rc = gen_avr_ptr(rC(ctx->opcode));
7440    rd = gen_avr_ptr(rD(ctx->opcode));
7441    gen_helper_vmladduhm(rd, ra, rb, rc);
7442    tcg_temp_free_ptr(ra);
7443    tcg_temp_free_ptr(rb);
7444    tcg_temp_free_ptr(rc);
7445    tcg_temp_free_ptr(rd);
7446}
7447
7448GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
7449GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
7450GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
7451GEN_VAFORM_PAIRED(vsel, vperm, 21)
7452GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
7453
7454GEN_VXFORM_NOA(vclzb, 1, 28)
7455GEN_VXFORM_NOA(vclzh, 1, 29)
7456GEN_VXFORM_NOA(vclzw, 1, 30)
7457GEN_VXFORM_NOA(vclzd, 1, 31)
7458GEN_VXFORM_NOA(vpopcntb, 1, 28)
7459GEN_VXFORM_NOA(vpopcnth, 1, 29)
7460GEN_VXFORM_NOA(vpopcntw, 1, 30)
7461GEN_VXFORM_NOA(vpopcntd, 1, 31)
7462GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
7463                vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
7464GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
7465                vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
7466GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
7467                vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
7468GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
7469                vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
7470GEN_VXFORM(vbpermq, 6, 21);
7471GEN_VXFORM_NOA(vgbbd, 6, 20);
7472GEN_VXFORM(vpmsumb, 4, 16)
7473GEN_VXFORM(vpmsumh, 4, 17)
7474GEN_VXFORM(vpmsumw, 4, 18)
7475GEN_VXFORM(vpmsumd, 4, 19)
7476
7477#define GEN_BCD(op)                                 \
7478static void gen_##op(DisasContext *ctx)             \
7479{                                                   \
7480    TCGv_ptr ra, rb, rd;                            \
7481    TCGv_i32 ps;                                    \
7482                                                    \
7483    if (unlikely(!ctx->altivec_enabled)) {          \
7484        gen_exception(ctx, POWERPC_EXCP_VPU);       \
7485        return;                                     \
7486    }                                               \
7487                                                    \
7488    ra = gen_avr_ptr(rA(ctx->opcode));              \
7489    rb = gen_avr_ptr(rB(ctx->opcode));              \
7490    rd = gen_avr_ptr(rD(ctx->opcode));              \
7491                                                    \
7492    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
7493                                                    \
7494    gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
7495                                                    \
7496    tcg_temp_free_ptr(ra);                          \
7497    tcg_temp_free_ptr(rb);                          \
7498    tcg_temp_free_ptr(rd);                          \
7499    tcg_temp_free_i32(ps);                          \
7500}
7501
7502GEN_BCD(bcdadd)
7503GEN_BCD(bcdsub)
7504
7505GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
7506                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7507GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
7508                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7509GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
7510                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7511GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
7512                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7513
7514static void gen_vsbox(DisasContext *ctx)
7515{
7516    TCGv_ptr ra, rd;
7517    if (unlikely(!ctx->altivec_enabled)) {
7518        gen_exception(ctx, POWERPC_EXCP_VPU);
7519        return;
7520    }
7521    ra = gen_avr_ptr(rA(ctx->opcode));
7522    rd = gen_avr_ptr(rD(ctx->opcode));
7523    gen_helper_vsbox(rd, ra);
7524    tcg_temp_free_ptr(ra);
7525    tcg_temp_free_ptr(rd);
7526}
7527
7528GEN_VXFORM(vcipher, 4, 20)
7529GEN_VXFORM(vcipherlast, 4, 20)
7530GEN_VXFORM(vncipher, 4, 21)
7531GEN_VXFORM(vncipherlast, 4, 21)
7532
7533GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
7534                vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7535GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
7536                vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7537
7538#define VSHASIGMA(op)                         \
7539static void gen_##op(DisasContext *ctx)       \
7540{                                             \
7541    TCGv_ptr ra, rd;                          \
7542    TCGv_i32 st_six;                          \
7543    if (unlikely(!ctx->altivec_enabled)) {    \
7544        gen_exception(ctx, POWERPC_EXCP_VPU); \
7545        return;                               \
7546    }                                         \
7547    ra = gen_avr_ptr(rA(ctx->opcode));        \
7548    rd = gen_avr_ptr(rD(ctx->opcode));        \
7549    st_six = tcg_const_i32(rB(ctx->opcode));  \
7550    gen_helper_##op(rd, ra, st_six);          \
7551    tcg_temp_free_ptr(ra);                    \
7552    tcg_temp_free_ptr(rd);                    \
7553    tcg_temp_free_i32(st_six);                \
7554}
7555
7556VSHASIGMA(vshasigmaw)
7557VSHASIGMA(vshasigmad)
7558
7559GEN_VXFORM3(vpermxor, 22, 0xFF)
7560GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
7561                vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
7562
7563/***                           VSX extension                               ***/
7564
7565static inline TCGv_i64 cpu_vsrh(int n)
7566{
7567    if (n < 32) {
7568        return cpu_fpr[n];
7569    } else {
7570        return cpu_avrh[n-32];
7571    }
7572}
7573
7574static inline TCGv_i64 cpu_vsrl(int n)
7575{
7576    if (n < 32) {
7577        return cpu_vsr[n];
7578    } else {
7579        return cpu_avrl[n-32];
7580    }
7581}
7582
7583#define VSX_LOAD_SCALAR(name, operation)                      \
7584static void gen_##name(DisasContext *ctx)                     \
7585{                                                             \
7586    TCGv EA;                                                  \
7587    if (unlikely(!ctx->vsx_enabled)) {                        \
7588        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7589        return;                                               \
7590    }                                                         \
7591    gen_set_access_type(ctx, ACCESS_INT);                     \
7592    EA = tcg_temp_new();                                      \
7593    gen_addr_reg_index(ctx, EA);                              \
7594    gen_qemu_##operation(ctx, cpu_vsrh(xT(ctx->opcode)), EA); \
7595    /* NOTE: cpu_vsrl is undefined */                         \
7596    tcg_temp_free(EA);                                        \
7597}
7598
7599VSX_LOAD_SCALAR(lxsdx, ld64)
7600VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
7601VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
7602VSX_LOAD_SCALAR(lxsspx, ld32fs)
7603
7604static void gen_lxvd2x(DisasContext *ctx)
7605{
7606    TCGv EA;
7607    if (unlikely(!ctx->vsx_enabled)) {
7608        gen_exception(ctx, POWERPC_EXCP_VSXU);
7609        return;
7610    }
7611    gen_set_access_type(ctx, ACCESS_INT);
7612    EA = tcg_temp_new();
7613    gen_addr_reg_index(ctx, EA);
7614    gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7615    tcg_gen_addi_tl(EA, EA, 8);
7616    gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
7617    tcg_temp_free(EA);
7618}
7619
7620static void gen_lxvdsx(DisasContext *ctx)
7621{
7622    TCGv EA;
7623    if (unlikely(!ctx->vsx_enabled)) {
7624        gen_exception(ctx, POWERPC_EXCP_VSXU);
7625        return;
7626    }
7627    gen_set_access_type(ctx, ACCESS_INT);
7628    EA = tcg_temp_new();
7629    gen_addr_reg_index(ctx, EA);
7630    gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7631    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
7632    tcg_temp_free(EA);
7633}
7634
7635static void gen_lxvw4x(DisasContext *ctx)
7636{
7637    TCGv EA;
7638    TCGv_i64 tmp;
7639    TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
7640    TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
7641    if (unlikely(!ctx->vsx_enabled)) {
7642        gen_exception(ctx, POWERPC_EXCP_VSXU);
7643        return;
7644    }
7645    gen_set_access_type(ctx, ACCESS_INT);
7646    EA = tcg_temp_new();
7647    tmp = tcg_temp_new_i64();
7648
7649    gen_addr_reg_index(ctx, EA);
7650    gen_qemu_ld32u_i64(ctx, tmp, EA);
7651    tcg_gen_addi_tl(EA, EA, 4);
7652    gen_qemu_ld32u_i64(ctx, xth, EA);
7653    tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
7654
7655    tcg_gen_addi_tl(EA, EA, 4);
7656    gen_qemu_ld32u_i64(ctx, tmp, EA);
7657    tcg_gen_addi_tl(EA, EA, 4);
7658    gen_qemu_ld32u_i64(ctx, xtl, EA);
7659    tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
7660
7661    tcg_temp_free(EA);
7662    tcg_temp_free_i64(tmp);
7663}
7664
7665#define VSX_STORE_SCALAR(name, operation)                     \
7666static void gen_##name(DisasContext *ctx)                     \
7667{                                                             \
7668    TCGv EA;                                                  \
7669    if (unlikely(!ctx->vsx_enabled)) {                        \
7670        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7671        return;                                               \
7672    }                                                         \
7673    gen_set_access_type(ctx, ACCESS_INT);                     \
7674    EA = tcg_temp_new();                                      \
7675    gen_addr_reg_index(ctx, EA);                              \
7676    gen_qemu_##operation(ctx, cpu_vsrh(xS(ctx->opcode)), EA); \
7677    tcg_temp_free(EA);                                        \
7678}
7679
7680VSX_STORE_SCALAR(stxsdx, st64)
7681VSX_STORE_SCALAR(stxsiwx, st32_i64)
7682VSX_STORE_SCALAR(stxsspx, st32fs)
7683
7684static void gen_stxvd2x(DisasContext *ctx)
7685{
7686    TCGv EA;
7687    if (unlikely(!ctx->vsx_enabled)) {
7688        gen_exception(ctx, POWERPC_EXCP_VSXU);
7689        return;
7690    }
7691    gen_set_access_type(ctx, ACCESS_INT);
7692    EA = tcg_temp_new();
7693    gen_addr_reg_index(ctx, EA);
7694    gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7695    tcg_gen_addi_tl(EA, EA, 8);
7696    gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7697    tcg_temp_free(EA);
7698}
7699
7700static void gen_stxvw4x(DisasContext *ctx)
7701{
7702    TCGv_i64 tmp;
7703    TCGv EA;
7704    if (unlikely(!ctx->vsx_enabled)) {
7705        gen_exception(ctx, POWERPC_EXCP_VSXU);
7706        return;
7707    }
7708    gen_set_access_type(ctx, ACCESS_INT);
7709    EA = tcg_temp_new();
7710    gen_addr_reg_index(ctx, EA);
7711    tmp = tcg_temp_new_i64();
7712
7713    tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
7714    gen_qemu_st32_i64(ctx, tmp, EA);
7715    tcg_gen_addi_tl(EA, EA, 4);
7716    gen_qemu_st32_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7717
7718    tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
7719    tcg_gen_addi_tl(EA, EA, 4);
7720    gen_qemu_st32_i64(ctx, tmp, EA);
7721    tcg_gen_addi_tl(EA, EA, 4);
7722    gen_qemu_st32_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7723
7724    tcg_temp_free(EA);
7725    tcg_temp_free_i64(tmp);
7726}
7727
7728#define MV_VSRW(name, tcgop1, tcgop2, target, source)           \
7729static void gen_##name(DisasContext *ctx)                       \
7730{                                                               \
7731    if (xS(ctx->opcode) < 32) {                                 \
7732        if (unlikely(!ctx->fpu_enabled)) {                      \
7733            gen_exception(ctx, POWERPC_EXCP_FPU);               \
7734            return;                                             \
7735        }                                                       \
7736    } else {                                                    \
7737        if (unlikely(!ctx->altivec_enabled)) {                  \
7738            gen_exception(ctx, POWERPC_EXCP_VPU);               \
7739            return;                                             \
7740        }                                                       \
7741    }                                                           \
7742    TCGv_i64 tmp = tcg_temp_new_i64();                          \
7743    tcg_gen_##tcgop1(tmp, source);                              \
7744    tcg_gen_##tcgop2(target, tmp);                              \
7745    tcg_temp_free_i64(tmp);                                     \
7746}
7747
7748
7749MV_VSRW(mfvsrwz, ext32u_i64, trunc_i64_tl, cpu_gpr[rA(ctx->opcode)], \
7750        cpu_vsrh(xS(ctx->opcode)))
7751MV_VSRW(mtvsrwa, extu_tl_i64, ext32s_i64, cpu_vsrh(xT(ctx->opcode)), \
7752        cpu_gpr[rA(ctx->opcode)])
7753MV_VSRW(mtvsrwz, extu_tl_i64, ext32u_i64, cpu_vsrh(xT(ctx->opcode)), \
7754        cpu_gpr[rA(ctx->opcode)])
7755
7756#if defined(TARGET_PPC64)
7757#define MV_VSRD(name, target, source)                           \
7758static void gen_##name(DisasContext *ctx)                       \
7759{                                                               \
7760    if (xS(ctx->opcode) < 32) {                                 \
7761        if (unlikely(!ctx->fpu_enabled)) {                      \
7762            gen_exception(ctx, POWERPC_EXCP_FPU);               \
7763            return;                                             \
7764        }                                                       \
7765    } else {                                                    \
7766        if (unlikely(!ctx->altivec_enabled)) {                  \
7767            gen_exception(ctx, POWERPC_EXCP_VPU);               \
7768            return;                                             \
7769        }                                                       \
7770    }                                                           \
7771    tcg_gen_mov_i64(target, source);                            \
7772}
7773
7774MV_VSRD(mfvsrd, cpu_gpr[rA(ctx->opcode)], cpu_vsrh(xS(ctx->opcode)))
7775MV_VSRD(mtvsrd, cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)])
7776
7777#endif
7778
7779static void gen_xxpermdi(DisasContext *ctx)
7780{
7781    if (unlikely(!ctx->vsx_enabled)) {
7782        gen_exception(ctx, POWERPC_EXCP_VSXU);
7783        return;
7784    }
7785
7786    if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
7787                 (xT(ctx->opcode) == xB(ctx->opcode)))) {
7788        TCGv_i64 xh, xl;
7789
7790        xh = tcg_temp_new_i64();
7791        xl = tcg_temp_new_i64();
7792
7793        if ((DM(ctx->opcode) & 2) == 0) {
7794            tcg_gen_mov_i64(xh, cpu_vsrh(xA(ctx->opcode)));
7795        } else {
7796            tcg_gen_mov_i64(xh, cpu_vsrl(xA(ctx->opcode)));
7797        }
7798        if ((DM(ctx->opcode) & 1) == 0) {
7799            tcg_gen_mov_i64(xl, cpu_vsrh(xB(ctx->opcode)));
7800        } else {
7801            tcg_gen_mov_i64(xl, cpu_vsrl(xB(ctx->opcode)));
7802        }
7803
7804        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xh);
7805        tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xl);
7806
7807        tcg_temp_free_i64(xh);
7808        tcg_temp_free_i64(xl);
7809    } else {
7810        if ((DM(ctx->opcode) & 2) == 0) {
7811            tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
7812        } else {
7813            tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
7814        }
7815        if ((DM(ctx->opcode) & 1) == 0) {
7816            tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
7817        } else {
7818            tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
7819        }
7820    }
7821}
7822
7823#define OP_ABS 1
7824#define OP_NABS 2
7825#define OP_NEG 3
7826#define OP_CPSGN 4
7827#define SGN_MASK_DP  0x8000000000000000ull
7828#define SGN_MASK_SP 0x8000000080000000ull
7829
7830#define VSX_SCALAR_MOVE(name, op, sgn_mask)                       \
7831static void glue(gen_, name)(DisasContext * ctx)                  \
7832    {                                                             \
7833        TCGv_i64 xb, sgm;                                         \
7834        if (unlikely(!ctx->vsx_enabled)) {                        \
7835            gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7836            return;                                               \
7837        }                                                         \
7838        xb = tcg_temp_new_i64();                                  \
7839        sgm = tcg_temp_new_i64();                                 \
7840        tcg_gen_mov_i64(xb, cpu_vsrh(xB(ctx->opcode)));           \
7841        tcg_gen_movi_i64(sgm, sgn_mask);                          \
7842        switch (op) {                                             \
7843            case OP_ABS: {                                        \
7844                tcg_gen_andc_i64(xb, xb, sgm);                    \
7845                break;                                            \
7846            }                                                     \
7847            case OP_NABS: {                                       \
7848                tcg_gen_or_i64(xb, xb, sgm);                      \
7849                break;                                            \
7850            }                                                     \
7851            case OP_NEG: {                                        \
7852                tcg_gen_xor_i64(xb, xb, sgm);                     \
7853                break;                                            \
7854            }                                                     \
7855            case OP_CPSGN: {                                      \
7856                TCGv_i64 xa = tcg_temp_new_i64();                 \
7857                tcg_gen_mov_i64(xa, cpu_vsrh(xA(ctx->opcode)));   \
7858                tcg_gen_and_i64(xa, xa, sgm);                     \
7859                tcg_gen_andc_i64(xb, xb, sgm);                    \
7860                tcg_gen_or_i64(xb, xb, xa);                       \
7861                tcg_temp_free_i64(xa);                            \
7862                break;                                            \
7863            }                                                     \
7864        }                                                         \
7865        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xb);           \
7866        tcg_temp_free_i64(xb);                                    \
7867        tcg_temp_free_i64(sgm);                                   \
7868    }
7869
7870VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
7871VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
7872VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
7873VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
7874
7875#define VSX_VECTOR_MOVE(name, op, sgn_mask)                      \
7876static void glue(gen_, name)(DisasContext * ctx)                 \
7877    {                                                            \
7878        TCGv_i64 xbh, xbl, sgm;                                  \
7879        if (unlikely(!ctx->vsx_enabled)) {                       \
7880            gen_exception(ctx, POWERPC_EXCP_VSXU);               \
7881            return;                                              \
7882        }                                                        \
7883        xbh = tcg_temp_new_i64();                                \
7884        xbl = tcg_temp_new_i64();                                \
7885        sgm = tcg_temp_new_i64();                                \
7886        tcg_gen_mov_i64(xbh, cpu_vsrh(xB(ctx->opcode)));         \
7887        tcg_gen_mov_i64(xbl, cpu_vsrl(xB(ctx->opcode)));         \
7888        tcg_gen_movi_i64(sgm, sgn_mask);                         \
7889        switch (op) {                                            \
7890            case OP_ABS: {                                       \
7891                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
7892                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
7893                break;                                           \
7894            }                                                    \
7895            case OP_NABS: {                                      \
7896                tcg_gen_or_i64(xbh, xbh, sgm);                   \
7897                tcg_gen_or_i64(xbl, xbl, sgm);                   \
7898                break;                                           \
7899            }                                                    \
7900            case OP_NEG: {                                       \
7901                tcg_gen_xor_i64(xbh, xbh, sgm);                  \
7902                tcg_gen_xor_i64(xbl, xbl, sgm);                  \
7903                break;                                           \
7904            }                                                    \
7905            case OP_CPSGN: {                                     \
7906                TCGv_i64 xah = tcg_temp_new_i64();               \
7907                TCGv_i64 xal = tcg_temp_new_i64();               \
7908                tcg_gen_mov_i64(xah, cpu_vsrh(xA(ctx->opcode))); \
7909                tcg_gen_mov_i64(xal, cpu_vsrl(xA(ctx->opcode))); \
7910                tcg_gen_and_i64(xah, xah, sgm);                  \
7911                tcg_gen_and_i64(xal, xal, sgm);                  \
7912                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
7913                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
7914                tcg_gen_or_i64(xbh, xbh, xah);                   \
7915                tcg_gen_or_i64(xbl, xbl, xal);                   \
7916                tcg_temp_free_i64(xah);                          \
7917                tcg_temp_free_i64(xal);                          \
7918                break;                                           \
7919            }                                                    \
7920        }                                                        \
7921        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xbh);         \
7922        tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xbl);         \
7923        tcg_temp_free_i64(xbh);                                  \
7924        tcg_temp_free_i64(xbl);                                  \
7925        tcg_temp_free_i64(sgm);                                  \
7926    }
7927
7928VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
7929VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
7930VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
7931VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
7932VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
7933VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
7934VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
7935VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
7936
7937#define GEN_VSX_HELPER_2(name, op1, op2, inval, type)                         \
7938static void gen_##name(DisasContext * ctx)                                    \
7939{                                                                             \
7940    TCGv_i32 opc;                                                             \
7941    if (unlikely(!ctx->vsx_enabled)) {                                        \
7942        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
7943        return;                                                               \
7944    }                                                                         \
7945    /* NIP cannot be restored if the memory exception comes from an helper */ \
7946    gen_update_nip(ctx, ctx->nip - 4);                                        \
7947    opc = tcg_const_i32(ctx->opcode);                                         \
7948    gen_helper_##name(cpu_env, opc);                                          \
7949    tcg_temp_free_i32(opc);                                                   \
7950}
7951
7952#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
7953static void gen_##name(DisasContext * ctx)                    \
7954{                                                             \
7955    if (unlikely(!ctx->vsx_enabled)) {                        \
7956        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7957        return;                                               \
7958    }                                                         \
7959    /* NIP cannot be restored if the exception comes */       \
7960    /* from a helper. */                                      \
7961    gen_update_nip(ctx, ctx->nip - 4);                        \
7962                                                              \
7963    gen_helper_##name(cpu_vsrh(xT(ctx->opcode)), cpu_env,     \
7964                      cpu_vsrh(xB(ctx->opcode)));             \
7965}
7966
7967GEN_VSX_HELPER_2(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
7968GEN_VSX_HELPER_2(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
7969GEN_VSX_HELPER_2(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
7970GEN_VSX_HELPER_2(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
7971GEN_VSX_HELPER_2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
7972GEN_VSX_HELPER_2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
7973GEN_VSX_HELPER_2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
7974GEN_VSX_HELPER_2(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
7975GEN_VSX_HELPER_2(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
7976GEN_VSX_HELPER_2(xsmaddadp, 0x04, 0x04, 0, PPC2_VSX)
7977GEN_VSX_HELPER_2(xsmaddmdp, 0x04, 0x05, 0, PPC2_VSX)
7978GEN_VSX_HELPER_2(xsmsubadp, 0x04, 0x06, 0, PPC2_VSX)
7979GEN_VSX_HELPER_2(xsmsubmdp, 0x04, 0x07, 0, PPC2_VSX)
7980GEN_VSX_HELPER_2(xsnmaddadp, 0x04, 0x14, 0, PPC2_VSX)
7981GEN_VSX_HELPER_2(xsnmaddmdp, 0x04, 0x15, 0, PPC2_VSX)
7982GEN_VSX_HELPER_2(xsnmsubadp, 0x04, 0x16, 0, PPC2_VSX)
7983GEN_VSX_HELPER_2(xsnmsubmdp, 0x04, 0x17, 0, PPC2_VSX)
7984GEN_VSX_HELPER_2(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
7985GEN_VSX_HELPER_2(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
7986GEN_VSX_HELPER_2(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
7987GEN_VSX_HELPER_2(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
7988GEN_VSX_HELPER_2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
7989GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207)
7990GEN_VSX_HELPER_2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
7991GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
7992GEN_VSX_HELPER_2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
7993GEN_VSX_HELPER_2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
7994GEN_VSX_HELPER_2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
7995GEN_VSX_HELPER_2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
7996GEN_VSX_HELPER_2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
7997GEN_VSX_HELPER_2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
7998GEN_VSX_HELPER_2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
7999GEN_VSX_HELPER_2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
8000GEN_VSX_HELPER_2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
8001GEN_VSX_HELPER_2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
8002GEN_VSX_HELPER_2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
8003GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207)
8004
8005GEN_VSX_HELPER_2(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
8006GEN_VSX_HELPER_2(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
8007GEN_VSX_HELPER_2(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
8008GEN_VSX_HELPER_2(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
8009GEN_VSX_HELPER_2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
8010GEN_VSX_HELPER_2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
8011GEN_VSX_HELPER_2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
8012GEN_VSX_HELPER_2(xsmaddasp, 0x04, 0x00, 0, PPC2_VSX207)
8013GEN_VSX_HELPER_2(xsmaddmsp, 0x04, 0x01, 0, PPC2_VSX207)
8014GEN_VSX_HELPER_2(xsmsubasp, 0x04, 0x02, 0, PPC2_VSX207)
8015GEN_VSX_HELPER_2(xsmsubmsp, 0x04, 0x03, 0, PPC2_VSX207)
8016GEN_VSX_HELPER_2(xsnmaddasp, 0x04, 0x10, 0, PPC2_VSX207)
8017GEN_VSX_HELPER_2(xsnmaddmsp, 0x04, 0x11, 0, PPC2_VSX207)
8018GEN_VSX_HELPER_2(xsnmsubasp, 0x04, 0x12, 0, PPC2_VSX207)
8019GEN_VSX_HELPER_2(xsnmsubmsp, 0x04, 0x13, 0, PPC2_VSX207)
8020GEN_VSX_HELPER_2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
8021GEN_VSX_HELPER_2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
8022
8023GEN_VSX_HELPER_2(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
8024GEN_VSX_HELPER_2(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
8025GEN_VSX_HELPER_2(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
8026GEN_VSX_HELPER_2(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
8027GEN_VSX_HELPER_2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
8028GEN_VSX_HELPER_2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
8029GEN_VSX_HELPER_2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
8030GEN_VSX_HELPER_2(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
8031GEN_VSX_HELPER_2(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
8032GEN_VSX_HELPER_2(xvmaddadp, 0x04, 0x0C, 0, PPC2_VSX)
8033GEN_VSX_HELPER_2(xvmaddmdp, 0x04, 0x0D, 0, PPC2_VSX)
8034GEN_VSX_HELPER_2(xvmsubadp, 0x04, 0x0E, 0, PPC2_VSX)
8035GEN_VSX_HELPER_2(xvmsubmdp, 0x04, 0x0F, 0, PPC2_VSX)
8036GEN_VSX_HELPER_2(xvnmaddadp, 0x04, 0x1C, 0, PPC2_VSX)
8037GEN_VSX_HELPER_2(xvnmaddmdp, 0x04, 0x1D, 0, PPC2_VSX)
8038GEN_VSX_HELPER_2(xvnmsubadp, 0x04, 0x1E, 0, PPC2_VSX)
8039GEN_VSX_HELPER_2(xvnmsubmdp, 0x04, 0x1F, 0, PPC2_VSX)
8040GEN_VSX_HELPER_2(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
8041GEN_VSX_HELPER_2(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
8042GEN_VSX_HELPER_2(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
8043GEN_VSX_HELPER_2(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
8044GEN_VSX_HELPER_2(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
8045GEN_VSX_HELPER_2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
8046GEN_VSX_HELPER_2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
8047GEN_VSX_HELPER_2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
8048GEN_VSX_HELPER_2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
8049GEN_VSX_HELPER_2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
8050GEN_VSX_HELPER_2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
8051GEN_VSX_HELPER_2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
8052GEN_VSX_HELPER_2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
8053GEN_VSX_HELPER_2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
8054GEN_VSX_HELPER_2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
8055GEN_VSX_HELPER_2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
8056GEN_VSX_HELPER_2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
8057GEN_VSX_HELPER_2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
8058GEN_VSX_HELPER_2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
8059
8060GEN_VSX_HELPER_2(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
8061GEN_VSX_HELPER_2(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
8062GEN_VSX_HELPER_2(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
8063GEN_VSX_HELPER_2(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
8064GEN_VSX_HELPER_2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
8065GEN_VSX_HELPER_2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
8066GEN_VSX_HELPER_2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
8067GEN_VSX_HELPER_2(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
8068GEN_VSX_HELPER_2(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
8069GEN_VSX_HELPER_2(xvmaddasp, 0x04, 0x08, 0, PPC2_VSX)
8070GEN_VSX_HELPER_2(xvmaddmsp, 0x04, 0x09, 0, PPC2_VSX)
8071GEN_VSX_HELPER_2(xvmsubasp, 0x04, 0x0A, 0, PPC2_VSX)
8072GEN_VSX_HELPER_2(xvmsubmsp, 0x04, 0x0B, 0, PPC2_VSX)
8073GEN_VSX_HELPER_2(xvnmaddasp, 0x04, 0x18, 0, PPC2_VSX)
8074GEN_VSX_HELPER_2(xvnmaddmsp, 0x04, 0x19, 0, PPC2_VSX)
8075GEN_VSX_HELPER_2(xvnmsubasp, 0x04, 0x1A, 0, PPC2_VSX)
8076GEN_VSX_HELPER_2(xvnmsubmsp, 0x04, 0x1B, 0, PPC2_VSX)
8077GEN_VSX_HELPER_2(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
8078GEN_VSX_HELPER_2(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
8079GEN_VSX_HELPER_2(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
8080GEN_VSX_HELPER_2(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
8081GEN_VSX_HELPER_2(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
8082GEN_VSX_HELPER_2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
8083GEN_VSX_HELPER_2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
8084GEN_VSX_HELPER_2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
8085GEN_VSX_HELPER_2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
8086GEN_VSX_HELPER_2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
8087GEN_VSX_HELPER_2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
8088GEN_VSX_HELPER_2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
8089GEN_VSX_HELPER_2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
8090GEN_VSX_HELPER_2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
8091GEN_VSX_HELPER_2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
8092GEN_VSX_HELPER_2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
8093GEN_VSX_HELPER_2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
8094GEN_VSX_HELPER_2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
8095GEN_VSX_HELPER_2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
8096
8097#define VSX_LOGICAL(name, tcg_op)                                    \
8098static void glue(gen_, name)(DisasContext * ctx)                     \
8099    {                                                                \
8100        if (unlikely(!ctx->vsx_enabled)) {                           \
8101            gen_exception(ctx, POWERPC_EXCP_VSXU);                   \
8102            return;                                                  \
8103        }                                                            \
8104        tcg_op(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)), \
8105            cpu_vsrh(xB(ctx->opcode)));                              \
8106        tcg_op(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)), \
8107            cpu_vsrl(xB(ctx->opcode)));                              \
8108    }
8109
8110VSX_LOGICAL(xxland, tcg_gen_and_i64)
8111VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
8112VSX_LOGICAL(xxlor, tcg_gen_or_i64)
8113VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
8114VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
8115VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
8116VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
8117VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
8118
8119#define VSX_XXMRG(name, high)                               \
8120static void glue(gen_, name)(DisasContext * ctx)            \
8121    {                                                       \
8122        TCGv_i64 a0, a1, b0, b1;                            \
8123        if (unlikely(!ctx->vsx_enabled)) {                  \
8124            gen_exception(ctx, POWERPC_EXCP_VSXU);          \
8125            return;                                         \
8126        }                                                   \
8127        a0 = tcg_temp_new_i64();                            \
8128        a1 = tcg_temp_new_i64();                            \
8129        b0 = tcg_temp_new_i64();                            \
8130        b1 = tcg_temp_new_i64();                            \
8131        if (high) {                                         \
8132            tcg_gen_mov_i64(a0, cpu_vsrh(xA(ctx->opcode))); \
8133            tcg_gen_mov_i64(a1, cpu_vsrh(xA(ctx->opcode))); \
8134            tcg_gen_mov_i64(b0, cpu_vsrh(xB(ctx->opcode))); \
8135            tcg_gen_mov_i64(b1, cpu_vsrh(xB(ctx->opcode))); \
8136        } else {                                            \
8137            tcg_gen_mov_i64(a0, cpu_vsrl(xA(ctx->opcode))); \
8138            tcg_gen_mov_i64(a1, cpu_vsrl(xA(ctx->opcode))); \
8139            tcg_gen_mov_i64(b0, cpu_vsrl(xB(ctx->opcode))); \
8140            tcg_gen_mov_i64(b1, cpu_vsrl(xB(ctx->opcode))); \
8141        }                                                   \
8142        tcg_gen_shri_i64(a0, a0, 32);                       \
8143        tcg_gen_shri_i64(b0, b0, 32);                       \
8144        tcg_gen_deposit_i64(cpu_vsrh(xT(ctx->opcode)),      \
8145                            b0, a0, 32, 32);                \
8146        tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)),      \
8147                            b1, a1, 32, 32);                \
8148        tcg_temp_free_i64(a0);                              \
8149        tcg_temp_free_i64(a1);                              \
8150        tcg_temp_free_i64(b0);                              \
8151        tcg_temp_free_i64(b1);                              \
8152    }
8153
8154VSX_XXMRG(xxmrghw, 1)
8155VSX_XXMRG(xxmrglw, 0)
8156
8157static void gen_xxsel(DisasContext * ctx)
8158{
8159    TCGv_i64 a, b, c;
8160    if (unlikely(!ctx->vsx_enabled)) {
8161        gen_exception(ctx, POWERPC_EXCP_VSXU);
8162        return;
8163    }
8164    a = tcg_temp_new_i64();
8165    b = tcg_temp_new_i64();
8166    c = tcg_temp_new_i64();
8167
8168    tcg_gen_mov_i64(a, cpu_vsrh(xA(ctx->opcode)));
8169    tcg_gen_mov_i64(b, cpu_vsrh(xB(ctx->opcode)));
8170    tcg_gen_mov_i64(c, cpu_vsrh(xC(ctx->opcode)));
8171
8172    tcg_gen_and_i64(b, b, c);
8173    tcg_gen_andc_i64(a, a, c);
8174    tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), a, b);
8175
8176    tcg_gen_mov_i64(a, cpu_vsrl(xA(ctx->opcode)));
8177    tcg_gen_mov_i64(b, cpu_vsrl(xB(ctx->opcode)));
8178    tcg_gen_mov_i64(c, cpu_vsrl(xC(ctx->opcode)));
8179
8180    tcg_gen_and_i64(b, b, c);
8181    tcg_gen_andc_i64(a, a, c);
8182    tcg_gen_or_i64(cpu_vsrl(xT(ctx->opcode)), a, b);
8183
8184    tcg_temp_free_i64(a);
8185    tcg_temp_free_i64(b);
8186    tcg_temp_free_i64(c);
8187}
8188
8189static void gen_xxspltw(DisasContext *ctx)
8190{
8191    TCGv_i64 b, b2;
8192    TCGv_i64 vsr = (UIM(ctx->opcode) & 2) ?
8193                   cpu_vsrl(xB(ctx->opcode)) :
8194                   cpu_vsrh(xB(ctx->opcode));
8195
8196    if (unlikely(!ctx->vsx_enabled)) {
8197        gen_exception(ctx, POWERPC_EXCP_VSXU);
8198        return;
8199    }
8200
8201    b = tcg_temp_new_i64();
8202    b2 = tcg_temp_new_i64();
8203
8204    if (UIM(ctx->opcode) & 1) {
8205        tcg_gen_ext32u_i64(b, vsr);
8206    } else {
8207        tcg_gen_shri_i64(b, vsr, 32);
8208    }
8209
8210    tcg_gen_shli_i64(b2, b, 32);
8211    tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), b, b2);
8212    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
8213
8214    tcg_temp_free_i64(b);
8215    tcg_temp_free_i64(b2);
8216}
8217
8218static void gen_xxsldwi(DisasContext *ctx)
8219{
8220    TCGv_i64 xth, xtl;
8221    if (unlikely(!ctx->vsx_enabled)) {
8222        gen_exception(ctx, POWERPC_EXCP_VSXU);
8223        return;
8224    }
8225    xth = tcg_temp_new_i64();
8226    xtl = tcg_temp_new_i64();
8227
8228    switch (SHW(ctx->opcode)) {
8229        case 0: {
8230            tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8231            tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8232            break;
8233        }
8234        case 1: {
8235            TCGv_i64 t0 = tcg_temp_new_i64();
8236            tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8237            tcg_gen_shli_i64(xth, xth, 32);
8238            tcg_gen_mov_i64(t0, cpu_vsrl(xA(ctx->opcode)));
8239            tcg_gen_shri_i64(t0, t0, 32);
8240            tcg_gen_or_i64(xth, xth, t0);
8241            tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8242            tcg_gen_shli_i64(xtl, xtl, 32);
8243            tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8244            tcg_gen_shri_i64(t0, t0, 32);
8245            tcg_gen_or_i64(xtl, xtl, t0);
8246            tcg_temp_free_i64(t0);
8247            break;
8248        }
8249        case 2: {
8250            tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8251            tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8252            break;
8253        }
8254        case 3: {
8255            TCGv_i64 t0 = tcg_temp_new_i64();
8256            tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8257            tcg_gen_shli_i64(xth, xth, 32);
8258            tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8259            tcg_gen_shri_i64(t0, t0, 32);
8260            tcg_gen_or_i64(xth, xth, t0);
8261            tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8262            tcg_gen_shli_i64(xtl, xtl, 32);
8263            tcg_gen_mov_i64(t0, cpu_vsrl(xB(ctx->opcode)));
8264            tcg_gen_shri_i64(t0, t0, 32);
8265            tcg_gen_or_i64(xtl, xtl, t0);
8266            tcg_temp_free_i64(t0);
8267            break;
8268        }
8269    }
8270
8271    tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xth);
8272    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xtl);
8273
8274    tcg_temp_free_i64(xth);
8275    tcg_temp_free_i64(xtl);
8276}
8277
8278/*** Decimal Floating Point ***/
8279
8280static inline TCGv_ptr gen_fprp_ptr(int reg)
8281{
8282    TCGv_ptr r = tcg_temp_new_ptr();
8283    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
8284    return r;
8285}
8286
8287#define GEN_DFP_T_A_B_Rc(name)                   \
8288static void gen_##name(DisasContext *ctx)        \
8289{                                                \
8290    TCGv_ptr rd, ra, rb;                         \
8291    if (unlikely(!ctx->fpu_enabled)) {           \
8292        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8293        return;                                  \
8294    }                                            \
8295    gen_update_nip(ctx, ctx->nip - 4);           \
8296    rd = gen_fprp_ptr(rD(ctx->opcode));          \
8297    ra = gen_fprp_ptr(rA(ctx->opcode));          \
8298    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8299    gen_helper_##name(cpu_env, rd, ra, rb);      \
8300    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8301        gen_set_cr1_from_fpscr(ctx);             \
8302    }                                            \
8303    tcg_temp_free_ptr(rd);                       \
8304    tcg_temp_free_ptr(ra);                       \
8305    tcg_temp_free_ptr(rb);                       \
8306}
8307
8308#define GEN_DFP_BF_A_B(name)                      \
8309static void gen_##name(DisasContext *ctx)         \
8310{                                                 \
8311    TCGv_ptr ra, rb;                              \
8312    if (unlikely(!ctx->fpu_enabled)) {            \
8313        gen_exception(ctx, POWERPC_EXCP_FPU);     \
8314        return;                                   \
8315    }                                             \
8316    gen_update_nip(ctx, ctx->nip - 4);            \
8317    ra = gen_fprp_ptr(rA(ctx->opcode));           \
8318    rb = gen_fprp_ptr(rB(ctx->opcode));           \
8319    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8320                      cpu_env, ra, rb);           \
8321    tcg_temp_free_ptr(ra);                        \
8322    tcg_temp_free_ptr(rb);                        \
8323}
8324
8325#define GEN_DFP_BF_A_DCM(name)                    \
8326static void gen_##name(DisasContext *ctx)         \
8327{                                                 \
8328    TCGv_ptr ra;                                  \
8329    TCGv_i32 dcm;                                 \
8330    if (unlikely(!ctx->fpu_enabled)) {            \
8331        gen_exception(ctx, POWERPC_EXCP_FPU);     \
8332        return;                                   \
8333    }                                             \
8334    gen_update_nip(ctx, ctx->nip - 4);            \
8335    ra = gen_fprp_ptr(rA(ctx->opcode));           \
8336    dcm = tcg_const_i32(DCM(ctx->opcode));        \
8337    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8338                      cpu_env, ra, dcm);          \
8339    tcg_temp_free_ptr(ra);                        \
8340    tcg_temp_free_i32(dcm);                       \
8341}
8342
8343#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2)    \
8344static void gen_##name(DisasContext *ctx)             \
8345{                                                     \
8346    TCGv_ptr rt, rb;                                  \
8347    TCGv_i32 u32_1, u32_2;                            \
8348    if (unlikely(!ctx->fpu_enabled)) {                \
8349        gen_exception(ctx, POWERPC_EXCP_FPU);         \
8350        return;                                       \
8351    }                                                 \
8352    gen_update_nip(ctx, ctx->nip - 4);                \
8353    rt = gen_fprp_ptr(rD(ctx->opcode));               \
8354    rb = gen_fprp_ptr(rB(ctx->opcode));               \
8355    u32_1 = tcg_const_i32(u32f1(ctx->opcode));        \
8356    u32_2 = tcg_const_i32(u32f2(ctx->opcode));        \
8357    gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
8358    if (unlikely(Rc(ctx->opcode) != 0)) {             \
8359        gen_set_cr1_from_fpscr(ctx);                  \
8360    }                                                 \
8361    tcg_temp_free_ptr(rt);                            \
8362    tcg_temp_free_ptr(rb);                            \
8363    tcg_temp_free_i32(u32_1);                         \
8364    tcg_temp_free_i32(u32_2);                         \
8365}
8366
8367#define GEN_DFP_T_A_B_I32_Rc(name, i32fld)       \
8368static void gen_##name(DisasContext *ctx)        \
8369{                                                \
8370    TCGv_ptr rt, ra, rb;                         \
8371    TCGv_i32 i32;                                \
8372    if (unlikely(!ctx->fpu_enabled)) {           \
8373        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8374        return;                                  \
8375    }                                            \
8376    gen_update_nip(ctx, ctx->nip - 4);           \
8377    rt = gen_fprp_ptr(rD(ctx->opcode));          \
8378    ra = gen_fprp_ptr(rA(ctx->opcode));          \
8379    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8380    i32 = tcg_const_i32(i32fld(ctx->opcode));    \
8381    gen_helper_##name(cpu_env, rt, ra, rb, i32); \
8382    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8383        gen_set_cr1_from_fpscr(ctx);             \
8384    }                                            \
8385    tcg_temp_free_ptr(rt);                       \
8386    tcg_temp_free_ptr(rb);                       \
8387    tcg_temp_free_ptr(ra);                       \
8388    tcg_temp_free_i32(i32);                      \
8389    }
8390
8391#define GEN_DFP_T_B_Rc(name)                     \
8392static void gen_##name(DisasContext *ctx)        \
8393{                                                \
8394    TCGv_ptr rt, rb;                             \
8395    if (unlikely(!ctx->fpu_enabled)) {           \
8396        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8397        return;                                  \
8398    }                                            \
8399    gen_update_nip(ctx, ctx->nip - 4);           \
8400    rt = gen_fprp_ptr(rD(ctx->opcode));          \
8401    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8402    gen_helper_##name(cpu_env, rt, rb);          \
8403    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8404        gen_set_cr1_from_fpscr(ctx);             \
8405    }                                            \
8406    tcg_temp_free_ptr(rt);                       \
8407    tcg_temp_free_ptr(rb);                       \
8408    }
8409
8410#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \
8411static void gen_##name(DisasContext *ctx)          \
8412{                                                  \
8413    TCGv_ptr rt, rs;                               \
8414    TCGv_i32 i32;                                  \
8415    if (unlikely(!ctx->fpu_enabled)) {             \
8416        gen_exception(ctx, POWERPC_EXCP_FPU);      \
8417        return;                                    \
8418    }                                              \
8419    gen_update_nip(ctx, ctx->nip - 4);             \
8420    rt = gen_fprp_ptr(rD(ctx->opcode));            \
8421    rs = gen_fprp_ptr(fprfld(ctx->opcode));        \
8422    i32 = tcg_const_i32(i32fld(ctx->opcode));      \
8423    gen_helper_##name(cpu_env, rt, rs, i32);       \
8424    if (unlikely(Rc(ctx->opcode) != 0)) {          \
8425        gen_set_cr1_from_fpscr(ctx);               \
8426    }                                              \
8427    tcg_temp_free_ptr(rt);                         \
8428    tcg_temp_free_ptr(rs);                         \
8429    tcg_temp_free_i32(i32);                        \
8430}
8431
8432GEN_DFP_T_A_B_Rc(dadd)
8433GEN_DFP_T_A_B_Rc(daddq)
8434GEN_DFP_T_A_B_Rc(dsub)
8435GEN_DFP_T_A_B_Rc(dsubq)
8436GEN_DFP_T_A_B_Rc(dmul)
8437GEN_DFP_T_A_B_Rc(dmulq)
8438GEN_DFP_T_A_B_Rc(ddiv)
8439GEN_DFP_T_A_B_Rc(ddivq)
8440GEN_DFP_BF_A_B(dcmpu)
8441GEN_DFP_BF_A_B(dcmpuq)
8442GEN_DFP_BF_A_B(dcmpo)
8443GEN_DFP_BF_A_B(dcmpoq)
8444GEN_DFP_BF_A_DCM(dtstdc)
8445GEN_DFP_BF_A_DCM(dtstdcq)
8446GEN_DFP_BF_A_DCM(dtstdg)
8447GEN_DFP_BF_A_DCM(dtstdgq)
8448GEN_DFP_BF_A_B(dtstex)
8449GEN_DFP_BF_A_B(dtstexq)
8450GEN_DFP_BF_A_B(dtstsf)
8451GEN_DFP_BF_A_B(dtstsfq)
8452GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC)
8453GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC)
8454GEN_DFP_T_A_B_I32_Rc(dqua, RMC)
8455GEN_DFP_T_A_B_I32_Rc(dquaq, RMC)
8456GEN_DFP_T_A_B_I32_Rc(drrnd, RMC)
8457GEN_DFP_T_A_B_I32_Rc(drrndq, RMC)
8458GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC)
8459GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC)
8460GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC)
8461GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC)
8462GEN_DFP_T_B_Rc(dctdp)
8463GEN_DFP_T_B_Rc(dctqpq)
8464GEN_DFP_T_B_Rc(drsp)
8465GEN_DFP_T_B_Rc(drdpq)
8466GEN_DFP_T_B_Rc(dcffix)
8467GEN_DFP_T_B_Rc(dcffixq)
8468GEN_DFP_T_B_Rc(dctfix)
8469GEN_DFP_T_B_Rc(dctfixq)
8470GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
8471GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
8472GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
8473GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
8474GEN_DFP_T_B_Rc(dxex)
8475GEN_DFP_T_B_Rc(dxexq)
8476GEN_DFP_T_A_B_Rc(diex)
8477GEN_DFP_T_A_B_Rc(diexq)
8478GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
8479GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
8480GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
8481GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
8482
8483/***                           SPE extension                               ***/
8484/* Register moves */
8485
8486static inline void gen_evmra(DisasContext *ctx)
8487{
8488
8489    if (unlikely(!ctx->spe_enabled)) {
8490        gen_exception(ctx, POWERPC_EXCP_SPEU);
8491        return;
8492    }
8493
8494    TCGv_i64 tmp = tcg_temp_new_i64();
8495
8496    /* tmp := rA_lo + rA_hi << 32 */
8497    tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8498
8499    /* spe_acc := tmp */
8500    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
8501    tcg_temp_free_i64(tmp);
8502
8503    /* rD := rA */
8504    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8505    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8506}
8507
8508static inline void gen_load_gpr64(TCGv_i64 t, int reg)
8509{
8510    tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
8511}
8512
8513static inline void gen_store_gpr64(int reg, TCGv_i64 t)
8514{
8515    tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
8516}
8517
8518#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
8519static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
8520{                                                                             \
8521    if (Rc(ctx->opcode))                                                      \
8522        gen_##name1(ctx);                                                     \
8523    else                                                                      \
8524        gen_##name0(ctx);                                                     \
8525}
8526
8527/* Handler for undefined SPE opcodes */
8528static inline void gen_speundef(DisasContext *ctx)
8529{
8530    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
8531}
8532
8533/* SPE logic */
8534#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
8535static inline void gen_##name(DisasContext *ctx)                              \
8536{                                                                             \
8537    if (unlikely(!ctx->spe_enabled)) {                                        \
8538        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8539        return;                                                               \
8540    }                                                                         \
8541    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
8542           cpu_gpr[rB(ctx->opcode)]);                                         \
8543    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
8544           cpu_gprh[rB(ctx->opcode)]);                                        \
8545}
8546
8547GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
8548GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
8549GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
8550GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
8551GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
8552GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
8553GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
8554GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
8555
8556/* SPE logic immediate */
8557#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
8558static inline void gen_##name(DisasContext *ctx)                              \
8559{                                                                             \
8560    TCGv_i32 t0;                                                              \
8561    if (unlikely(!ctx->spe_enabled)) {                                        \
8562        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8563        return;                                                               \
8564    }                                                                         \
8565    t0 = tcg_temp_new_i32();                                                  \
8566                                                                              \
8567    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8568    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
8569    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8570                                                                              \
8571    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8572    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
8573    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8574                                                                              \
8575    tcg_temp_free_i32(t0);                                                    \
8576}
8577GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
8578GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
8579GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
8580GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
8581
8582/* SPE arithmetic */
8583#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
8584static inline void gen_##name(DisasContext *ctx)                              \
8585{                                                                             \
8586    TCGv_i32 t0;                                                              \
8587    if (unlikely(!ctx->spe_enabled)) {                                        \
8588        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8589        return;                                                               \
8590    }                                                                         \
8591    t0 = tcg_temp_new_i32();                                                  \
8592                                                                              \
8593    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8594    tcg_op(t0, t0);                                                           \
8595    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8596                                                                              \
8597    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8598    tcg_op(t0, t0);                                                           \
8599    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8600                                                                              \
8601    tcg_temp_free_i32(t0);                                                    \
8602}
8603
8604static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
8605{
8606    TCGLabel *l1 = gen_new_label();
8607    TCGLabel *l2 = gen_new_label();
8608
8609    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
8610    tcg_gen_neg_i32(ret, arg1);
8611    tcg_gen_br(l2);
8612    gen_set_label(l1);
8613    tcg_gen_mov_i32(ret, arg1);
8614    gen_set_label(l2);
8615}
8616GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
8617GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
8618GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
8619GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
8620static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
8621{
8622    tcg_gen_addi_i32(ret, arg1, 0x8000);
8623    tcg_gen_ext16u_i32(ret, ret);
8624}
8625GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
8626GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
8627GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
8628
8629#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
8630static inline void gen_##name(DisasContext *ctx)                              \
8631{                                                                             \
8632    TCGv_i32 t0, t1;                                                          \
8633    if (unlikely(!ctx->spe_enabled)) {                                        \
8634        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8635        return;                                                               \
8636    }                                                                         \
8637    t0 = tcg_temp_new_i32();                                                  \
8638    t1 = tcg_temp_new_i32();                                                  \
8639                                                                              \
8640    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8641    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
8642    tcg_op(t0, t0, t1);                                                       \
8643    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8644                                                                              \
8645    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8646    tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]);                      \
8647    tcg_op(t0, t0, t1);                                                       \
8648    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8649                                                                              \
8650    tcg_temp_free_i32(t0);                                                    \
8651    tcg_temp_free_i32(t1);                                                    \
8652}
8653
8654static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8655{
8656    TCGLabel *l1 = gen_new_label();
8657    TCGLabel *l2 = gen_new_label();
8658    TCGv_i32 t0 = tcg_temp_local_new_i32();
8659
8660    /* No error here: 6 bits are used */
8661    tcg_gen_andi_i32(t0, arg2, 0x3F);
8662    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8663    tcg_gen_shr_i32(ret, arg1, t0);
8664    tcg_gen_br(l2);
8665    gen_set_label(l1);
8666    tcg_gen_movi_i32(ret, 0);
8667    gen_set_label(l2);
8668    tcg_temp_free_i32(t0);
8669}
8670GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
8671static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8672{
8673    TCGLabel *l1 = gen_new_label();
8674    TCGLabel *l2 = gen_new_label();
8675    TCGv_i32 t0 = tcg_temp_local_new_i32();
8676
8677    /* No error here: 6 bits are used */
8678    tcg_gen_andi_i32(t0, arg2, 0x3F);
8679    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8680    tcg_gen_sar_i32(ret, arg1, t0);
8681    tcg_gen_br(l2);
8682    gen_set_label(l1);
8683    tcg_gen_movi_i32(ret, 0);
8684    gen_set_label(l2);
8685    tcg_temp_free_i32(t0);
8686}
8687GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
8688static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8689{
8690    TCGLabel *l1 = gen_new_label();
8691    TCGLabel *l2 = gen_new_label();
8692    TCGv_i32 t0 = tcg_temp_local_new_i32();
8693
8694    /* No error here: 6 bits are used */
8695    tcg_gen_andi_i32(t0, arg2, 0x3F);
8696    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8697    tcg_gen_shl_i32(ret, arg1, t0);
8698    tcg_gen_br(l2);
8699    gen_set_label(l1);
8700    tcg_gen_movi_i32(ret, 0);
8701    gen_set_label(l2);
8702    tcg_temp_free_i32(t0);
8703}
8704GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
8705static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8706{
8707    TCGv_i32 t0 = tcg_temp_new_i32();
8708    tcg_gen_andi_i32(t0, arg2, 0x1F);
8709    tcg_gen_rotl_i32(ret, arg1, t0);
8710    tcg_temp_free_i32(t0);
8711}
8712GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
8713static inline void gen_evmergehi(DisasContext *ctx)
8714{
8715    if (unlikely(!ctx->spe_enabled)) {
8716        gen_exception(ctx, POWERPC_EXCP_SPEU);
8717        return;
8718    }
8719    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8720    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8721}
8722GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
8723static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8724{
8725    tcg_gen_sub_i32(ret, arg2, arg1);
8726}
8727GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
8728
8729/* SPE arithmetic immediate */
8730#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
8731static inline void gen_##name(DisasContext *ctx)                              \
8732{                                                                             \
8733    TCGv_i32 t0;                                                              \
8734    if (unlikely(!ctx->spe_enabled)) {                                        \
8735        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8736        return;                                                               \
8737    }                                                                         \
8738    t0 = tcg_temp_new_i32();                                                  \
8739                                                                              \
8740    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8741    tcg_op(t0, t0, rA(ctx->opcode));                                          \
8742    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8743                                                                              \
8744    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]);                      \
8745    tcg_op(t0, t0, rA(ctx->opcode));                                          \
8746    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8747                                                                              \
8748    tcg_temp_free_i32(t0);                                                    \
8749}
8750GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
8751GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
8752
8753/* SPE comparison */
8754#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
8755static inline void gen_##name(DisasContext *ctx)                              \
8756{                                                                             \
8757    if (unlikely(!ctx->spe_enabled)) {                                        \
8758        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8759        return;                                                               \
8760    }                                                                         \
8761    TCGLabel *l1 = gen_new_label();                                           \
8762    TCGLabel *l2 = gen_new_label();                                           \
8763    TCGLabel *l3 = gen_new_label();                                           \
8764    TCGLabel *l4 = gen_new_label();                                           \
8765                                                                              \
8766    tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);    \
8767    tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8768    tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);  \
8769    tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);  \
8770                                                                              \
8771    tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)],                     \
8772                       cpu_gpr[rB(ctx->opcode)], l1);                         \
8773    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
8774    tcg_gen_br(l2);                                                           \
8775    gen_set_label(l1);                                                        \
8776    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
8777                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
8778    gen_set_label(l2);                                                        \
8779    tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)],                    \
8780                       cpu_gprh[rB(ctx->opcode)], l3);                        \
8781    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
8782                     ~(CRF_CH | CRF_CH_AND_CL));                              \
8783    tcg_gen_br(l4);                                                           \
8784    gen_set_label(l3);                                                        \
8785    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
8786                    CRF_CH | CRF_CH_OR_CL);                                   \
8787    gen_set_label(l4);                                                        \
8788}
8789GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
8790GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
8791GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
8792GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
8793GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
8794
8795/* SPE misc */
8796static inline void gen_brinc(DisasContext *ctx)
8797{
8798    /* Note: brinc is usable even if SPE is disabled */
8799    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
8800                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8801}
8802static inline void gen_evmergelo(DisasContext *ctx)
8803{
8804    if (unlikely(!ctx->spe_enabled)) {
8805        gen_exception(ctx, POWERPC_EXCP_SPEU);
8806        return;
8807    }
8808    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8809    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8810}
8811static inline void gen_evmergehilo(DisasContext *ctx)
8812{
8813    if (unlikely(!ctx->spe_enabled)) {
8814        gen_exception(ctx, POWERPC_EXCP_SPEU);
8815        return;
8816    }
8817    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8818    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8819}
8820static inline void gen_evmergelohi(DisasContext *ctx)
8821{
8822    if (unlikely(!ctx->spe_enabled)) {
8823        gen_exception(ctx, POWERPC_EXCP_SPEU);
8824        return;
8825    }
8826    if (rD(ctx->opcode) == rA(ctx->opcode)) {
8827        TCGv tmp = tcg_temp_new();
8828        tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
8829        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8830        tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
8831        tcg_temp_free(tmp);
8832    } else {
8833        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8834        tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8835    }
8836}
8837static inline void gen_evsplati(DisasContext *ctx)
8838{
8839    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
8840
8841    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8842    tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
8843}
8844static inline void gen_evsplatfi(DisasContext *ctx)
8845{
8846    uint64_t imm = rA(ctx->opcode) << 27;
8847
8848    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8849    tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
8850}
8851
8852static inline void gen_evsel(DisasContext *ctx)
8853{
8854    TCGLabel *l1 = gen_new_label();
8855    TCGLabel *l2 = gen_new_label();
8856    TCGLabel *l3 = gen_new_label();
8857    TCGLabel *l4 = gen_new_label();
8858    TCGv_i32 t0 = tcg_temp_local_new_i32();
8859
8860    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
8861    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
8862    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8863    tcg_gen_br(l2);
8864    gen_set_label(l1);
8865    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8866    gen_set_label(l2);
8867    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
8868    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
8869    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8870    tcg_gen_br(l4);
8871    gen_set_label(l3);
8872    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8873    gen_set_label(l4);
8874    tcg_temp_free_i32(t0);
8875}
8876
8877static void gen_evsel0(DisasContext *ctx)
8878{
8879    gen_evsel(ctx);
8880}
8881
8882static void gen_evsel1(DisasContext *ctx)
8883{
8884    gen_evsel(ctx);
8885}
8886
8887static void gen_evsel2(DisasContext *ctx)
8888{
8889    gen_evsel(ctx);
8890}
8891
8892static void gen_evsel3(DisasContext *ctx)
8893{
8894    gen_evsel(ctx);
8895}
8896
8897/* Multiply */
8898
8899static inline void gen_evmwumi(DisasContext *ctx)
8900{
8901    TCGv_i64 t0, t1;
8902
8903    if (unlikely(!ctx->spe_enabled)) {
8904        gen_exception(ctx, POWERPC_EXCP_SPEU);
8905        return;
8906    }
8907
8908    t0 = tcg_temp_new_i64();
8909    t1 = tcg_temp_new_i64();
8910
8911    /* t0 := rA; t1 := rB */
8912    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
8913    tcg_gen_ext32u_i64(t0, t0);
8914    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
8915    tcg_gen_ext32u_i64(t1, t1);
8916
8917    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
8918
8919    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
8920
8921    tcg_temp_free_i64(t0);
8922    tcg_temp_free_i64(t1);
8923}
8924
8925static inline void gen_evmwumia(DisasContext *ctx)
8926{
8927    TCGv_i64 tmp;
8928
8929    if (unlikely(!ctx->spe_enabled)) {
8930        gen_exception(ctx, POWERPC_EXCP_SPEU);
8931        return;
8932    }
8933
8934    gen_evmwumi(ctx);            /* rD := rA * rB */
8935
8936    tmp = tcg_temp_new_i64();
8937
8938    /* acc := rD */
8939    gen_load_gpr64(tmp, rD(ctx->opcode));
8940    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
8941    tcg_temp_free_i64(tmp);
8942}
8943
8944static inline void gen_evmwumiaa(DisasContext *ctx)
8945{
8946    TCGv_i64 acc;
8947    TCGv_i64 tmp;
8948
8949    if (unlikely(!ctx->spe_enabled)) {
8950        gen_exception(ctx, POWERPC_EXCP_SPEU);
8951        return;
8952    }
8953
8954    gen_evmwumi(ctx);           /* rD := rA * rB */
8955
8956    acc = tcg_temp_new_i64();
8957    tmp = tcg_temp_new_i64();
8958
8959    /* tmp := rD */
8960    gen_load_gpr64(tmp, rD(ctx->opcode));
8961
8962    /* Load acc */
8963    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
8964
8965    /* acc := tmp + acc */
8966    tcg_gen_add_i64(acc, acc, tmp);
8967
8968    /* Store acc */
8969    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
8970
8971    /* rD := acc */
8972    gen_store_gpr64(rD(ctx->opcode), acc);
8973
8974    tcg_temp_free_i64(acc);
8975    tcg_temp_free_i64(tmp);
8976}
8977
8978static inline void gen_evmwsmi(DisasContext *ctx)
8979{
8980    TCGv_i64 t0, t1;
8981
8982    if (unlikely(!ctx->spe_enabled)) {
8983        gen_exception(ctx, POWERPC_EXCP_SPEU);
8984        return;
8985    }
8986
8987    t0 = tcg_temp_new_i64();
8988    t1 = tcg_temp_new_i64();
8989
8990    /* t0 := rA; t1 := rB */
8991    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
8992    tcg_gen_ext32s_i64(t0, t0);
8993    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
8994    tcg_gen_ext32s_i64(t1, t1);
8995
8996    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
8997
8998    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
8999
9000    tcg_temp_free_i64(t0);
9001    tcg_temp_free_i64(t1);
9002}
9003
9004static inline void gen_evmwsmia(DisasContext *ctx)
9005{
9006    TCGv_i64 tmp;
9007
9008    gen_evmwsmi(ctx);            /* rD := rA * rB */
9009
9010    tmp = tcg_temp_new_i64();
9011
9012    /* acc := rD */
9013    gen_load_gpr64(tmp, rD(ctx->opcode));
9014    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
9015
9016    tcg_temp_free_i64(tmp);
9017}
9018
9019static inline void gen_evmwsmiaa(DisasContext *ctx)
9020{
9021    TCGv_i64 acc = tcg_temp_new_i64();
9022    TCGv_i64 tmp = tcg_temp_new_i64();
9023
9024    gen_evmwsmi(ctx);           /* rD := rA * rB */
9025
9026    acc = tcg_temp_new_i64();
9027    tmp = tcg_temp_new_i64();
9028
9029    /* tmp := rD */
9030    gen_load_gpr64(tmp, rD(ctx->opcode));
9031
9032    /* Load acc */
9033    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9034
9035    /* acc := tmp + acc */
9036    tcg_gen_add_i64(acc, acc, tmp);
9037
9038    /* Store acc */
9039    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9040
9041    /* rD := acc */
9042    gen_store_gpr64(rD(ctx->opcode), acc);
9043
9044    tcg_temp_free_i64(acc);
9045    tcg_temp_free_i64(tmp);
9046}
9047
9048GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9049GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9050GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9051GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9052GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9053GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9054GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9055GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
9056GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
9057GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9058GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9059GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9060GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9061GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9062GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9063GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9064GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9065GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9066GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9067GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
9068GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9069GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9070GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
9071GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
9072GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9073GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9074GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9075GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9076GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
9077
9078/* SPE load and stores */
9079static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
9080{
9081    target_ulong uimm = rB(ctx->opcode);
9082
9083    if (rA(ctx->opcode) == 0) {
9084        tcg_gen_movi_tl(EA, uimm << sh);
9085    } else {
9086        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
9087        if (NARROW_MODE(ctx)) {
9088            tcg_gen_ext32u_tl(EA, EA);
9089        }
9090    }
9091}
9092
9093static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
9094{
9095    TCGv_i64 t0 = tcg_temp_new_i64();
9096    gen_qemu_ld64(ctx, t0, addr);
9097    gen_store_gpr64(rD(ctx->opcode), t0);
9098    tcg_temp_free_i64(t0);
9099}
9100
9101static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
9102{
9103    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9104    gen_addr_add(ctx, addr, addr, 4);
9105    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9106}
9107
9108static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
9109{
9110    TCGv t0 = tcg_temp_new();
9111    gen_qemu_ld16u(ctx, t0, addr);
9112    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9113    gen_addr_add(ctx, addr, addr, 2);
9114    gen_qemu_ld16u(ctx, t0, addr);
9115    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9116    gen_addr_add(ctx, addr, addr, 2);
9117    gen_qemu_ld16u(ctx, t0, addr);
9118    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9119    gen_addr_add(ctx, addr, addr, 2);
9120    gen_qemu_ld16u(ctx, t0, addr);
9121    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
9122    tcg_temp_free(t0);
9123}
9124
9125static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
9126{
9127    TCGv t0 = tcg_temp_new();
9128    gen_qemu_ld16u(ctx, t0, addr);
9129    tcg_gen_shli_tl(t0, t0, 16);
9130    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9131    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9132    tcg_temp_free(t0);
9133}
9134
9135static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
9136{
9137    TCGv t0 = tcg_temp_new();
9138    gen_qemu_ld16u(ctx, t0, addr);
9139    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9140    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9141    tcg_temp_free(t0);
9142}
9143
9144static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
9145{
9146    TCGv t0 = tcg_temp_new();
9147    gen_qemu_ld16s(ctx, t0, addr);
9148    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9149    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9150    tcg_temp_free(t0);
9151}
9152
9153static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
9154{
9155    TCGv t0 = tcg_temp_new();
9156    gen_qemu_ld16u(ctx, t0, addr);
9157    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9158    gen_addr_add(ctx, addr, addr, 2);
9159    gen_qemu_ld16u(ctx, t0, addr);
9160    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
9161    tcg_temp_free(t0);
9162}
9163
9164static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
9165{
9166    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9167    gen_addr_add(ctx, addr, addr, 2);
9168    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9169}
9170
9171static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
9172{
9173    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9174    gen_addr_add(ctx, addr, addr, 2);
9175    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9176}
9177
9178static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
9179{
9180    TCGv t0 = tcg_temp_new();
9181    gen_qemu_ld32u(ctx, t0, addr);
9182    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9183    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9184    tcg_temp_free(t0);
9185}
9186
9187static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
9188{
9189    TCGv t0 = tcg_temp_new();
9190    gen_qemu_ld16u(ctx, t0, addr);
9191    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9192    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9193    gen_addr_add(ctx, addr, addr, 2);
9194    gen_qemu_ld16u(ctx, t0, addr);
9195    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
9196    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9197    tcg_temp_free(t0);
9198}
9199
9200static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
9201{
9202    TCGv_i64 t0 = tcg_temp_new_i64();
9203    gen_load_gpr64(t0, rS(ctx->opcode));
9204    gen_qemu_st64(ctx, t0, addr);
9205    tcg_temp_free_i64(t0);
9206}
9207
9208static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
9209{
9210    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9211    gen_addr_add(ctx, addr, addr, 4);
9212    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9213}
9214
9215static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
9216{
9217    TCGv t0 = tcg_temp_new();
9218    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
9219    gen_qemu_st16(ctx, t0, addr);
9220    gen_addr_add(ctx, addr, addr, 2);
9221    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9222    gen_addr_add(ctx, addr, addr, 2);
9223    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
9224    gen_qemu_st16(ctx, t0, addr);
9225    tcg_temp_free(t0);
9226    gen_addr_add(ctx, addr, addr, 2);
9227    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9228}
9229
9230static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
9231{
9232    TCGv t0 = tcg_temp_new();
9233    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
9234    gen_qemu_st16(ctx, t0, addr);
9235    gen_addr_add(ctx, addr, addr, 2);
9236    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
9237    gen_qemu_st16(ctx, t0, addr);
9238    tcg_temp_free(t0);
9239}
9240
9241static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
9242{
9243    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9244    gen_addr_add(ctx, addr, addr, 2);
9245    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9246}
9247
9248static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
9249{
9250    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9251}
9252
9253static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
9254{
9255    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9256}
9257
9258#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
9259static void glue(gen_, name)(DisasContext *ctx)                                       \
9260{                                                                             \
9261    TCGv t0;                                                                  \
9262    if (unlikely(!ctx->spe_enabled)) {                                        \
9263        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9264        return;                                                               \
9265    }                                                                         \
9266    gen_set_access_type(ctx, ACCESS_INT);                                     \
9267    t0 = tcg_temp_new();                                                      \
9268    if (Rc(ctx->opcode)) {                                                    \
9269        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
9270    } else {                                                                  \
9271        gen_addr_reg_index(ctx, t0);                                          \
9272    }                                                                         \
9273    gen_op_##name(ctx, t0);                                                   \
9274    tcg_temp_free(t0);                                                        \
9275}
9276
9277GEN_SPEOP_LDST(evldd, 0x00, 3);
9278GEN_SPEOP_LDST(evldw, 0x01, 3);
9279GEN_SPEOP_LDST(evldh, 0x02, 3);
9280GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
9281GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
9282GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
9283GEN_SPEOP_LDST(evlwhe, 0x08, 2);
9284GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
9285GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
9286GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
9287GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
9288
9289GEN_SPEOP_LDST(evstdd, 0x10, 3);
9290GEN_SPEOP_LDST(evstdw, 0x11, 3);
9291GEN_SPEOP_LDST(evstdh, 0x12, 3);
9292GEN_SPEOP_LDST(evstwhe, 0x18, 2);
9293GEN_SPEOP_LDST(evstwho, 0x1A, 2);
9294GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
9295GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
9296
9297/* Multiply and add - TODO */
9298#if 0
9299GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
9300GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9301GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9302GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9303GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9304GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9305GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9306GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9307GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9308GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9309GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9310GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9311
9312GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9313GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9314GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9315GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9316GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9317GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9318GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9319GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9320GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9321GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9322GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9323GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9324
9325GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9326GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9327GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9328GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9329GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
9330
9331GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9332GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9333GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9334GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9335GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9336GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9337GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9338GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9339GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9340GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9341GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9342GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9343
9344GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9345GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9346GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9347GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9348
9349GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9350GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9351GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9352GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9353GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9354GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9355GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9356GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9357GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9358GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9359GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9360GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9361
9362GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9363GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9364GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9365GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9366GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9367#endif
9368
9369/***                      SPE floating-point extension                     ***/
9370#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
9371static inline void gen_##name(DisasContext *ctx)                              \
9372{                                                                             \
9373    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
9374    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
9375    gen_helper_##name(t0, cpu_env, t0);                                       \
9376    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
9377    tcg_temp_free_i32(t0);                                                    \
9378}
9379#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
9380static inline void gen_##name(DisasContext *ctx)                              \
9381{                                                                             \
9382    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9383    TCGv_i32 t1 = tcg_temp_new_i32();                                         \
9384    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
9385    gen_helper_##name(t1, cpu_env, t0);                                       \
9386    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);                        \
9387    tcg_temp_free_i64(t0);                                                    \
9388    tcg_temp_free_i32(t1);                                                    \
9389}
9390#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
9391static inline void gen_##name(DisasContext *ctx)                              \
9392{                                                                             \
9393    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9394    TCGv_i32 t1 = tcg_temp_new_i32();                                         \
9395    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9396    gen_helper_##name(t0, cpu_env, t1);                                       \
9397    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9398    tcg_temp_free_i64(t0);                                                    \
9399    tcg_temp_free_i32(t1);                                                    \
9400}
9401#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
9402static inline void gen_##name(DisasContext *ctx)                              \
9403{                                                                             \
9404    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9405    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
9406    gen_helper_##name(t0, cpu_env, t0);                                       \
9407    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9408    tcg_temp_free_i64(t0);                                                    \
9409}
9410#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
9411static inline void gen_##name(DisasContext *ctx)                              \
9412{                                                                             \
9413    TCGv_i32 t0, t1;                                                          \
9414    if (unlikely(!ctx->spe_enabled)) {                                        \
9415        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9416        return;                                                               \
9417    }                                                                         \
9418    t0 = tcg_temp_new_i32();                                                  \
9419    t1 = tcg_temp_new_i32();                                                  \
9420    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
9421    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9422    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
9423    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
9424                                                                              \
9425    tcg_temp_free_i32(t0);                                                    \
9426    tcg_temp_free_i32(t1);                                                    \
9427}
9428#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
9429static inline void gen_##name(DisasContext *ctx)                              \
9430{                                                                             \
9431    TCGv_i64 t0, t1;                                                          \
9432    if (unlikely(!ctx->spe_enabled)) {                                        \
9433        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9434        return;                                                               \
9435    }                                                                         \
9436    t0 = tcg_temp_new_i64();                                                  \
9437    t1 = tcg_temp_new_i64();                                                  \
9438    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
9439    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
9440    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
9441    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9442    tcg_temp_free_i64(t0);                                                    \
9443    tcg_temp_free_i64(t1);                                                    \
9444}
9445#define GEN_SPEFPUOP_COMP_32(name)                                            \
9446static inline void gen_##name(DisasContext *ctx)                              \
9447{                                                                             \
9448    TCGv_i32 t0, t1;                                                          \
9449    if (unlikely(!ctx->spe_enabled)) {                                        \
9450        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9451        return;                                                               \
9452    }                                                                         \
9453    t0 = tcg_temp_new_i32();                                                  \
9454    t1 = tcg_temp_new_i32();                                                  \
9455                                                                              \
9456    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
9457    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9458    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
9459                                                                              \
9460    tcg_temp_free_i32(t0);                                                    \
9461    tcg_temp_free_i32(t1);                                                    \
9462}
9463#define GEN_SPEFPUOP_COMP_64(name)                                            \
9464static inline void gen_##name(DisasContext *ctx)                              \
9465{                                                                             \
9466    TCGv_i64 t0, t1;                                                          \
9467    if (unlikely(!ctx->spe_enabled)) {                                        \
9468        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9469        return;                                                               \
9470    }                                                                         \
9471    t0 = tcg_temp_new_i64();                                                  \
9472    t1 = tcg_temp_new_i64();                                                  \
9473    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
9474    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
9475    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
9476    tcg_temp_free_i64(t0);                                                    \
9477    tcg_temp_free_i64(t1);                                                    \
9478}
9479
9480/* Single precision floating-point vectors operations */
9481/* Arithmetic */
9482GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
9483GEN_SPEFPUOP_ARITH2_64_64(evfssub);
9484GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
9485GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
9486static inline void gen_evfsabs(DisasContext *ctx)
9487{
9488    if (unlikely(!ctx->spe_enabled)) {
9489        gen_exception(ctx, POWERPC_EXCP_SPEU);
9490        return;
9491    }
9492    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9493                    ~0x80000000);
9494    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9495                    ~0x80000000);
9496}
9497static inline void gen_evfsnabs(DisasContext *ctx)
9498{
9499    if (unlikely(!ctx->spe_enabled)) {
9500        gen_exception(ctx, POWERPC_EXCP_SPEU);
9501        return;
9502    }
9503    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9504                   0x80000000);
9505    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9506                   0x80000000);
9507}
9508static inline void gen_evfsneg(DisasContext *ctx)
9509{
9510    if (unlikely(!ctx->spe_enabled)) {
9511        gen_exception(ctx, POWERPC_EXCP_SPEU);
9512        return;
9513    }
9514    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9515                    0x80000000);
9516    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9517                    0x80000000);
9518}
9519
9520/* Conversion */
9521GEN_SPEFPUOP_CONV_64_64(evfscfui);
9522GEN_SPEFPUOP_CONV_64_64(evfscfsi);
9523GEN_SPEFPUOP_CONV_64_64(evfscfuf);
9524GEN_SPEFPUOP_CONV_64_64(evfscfsf);
9525GEN_SPEFPUOP_CONV_64_64(evfsctui);
9526GEN_SPEFPUOP_CONV_64_64(evfsctsi);
9527GEN_SPEFPUOP_CONV_64_64(evfsctuf);
9528GEN_SPEFPUOP_CONV_64_64(evfsctsf);
9529GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
9530GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
9531
9532/* Comparison */
9533GEN_SPEFPUOP_COMP_64(evfscmpgt);
9534GEN_SPEFPUOP_COMP_64(evfscmplt);
9535GEN_SPEFPUOP_COMP_64(evfscmpeq);
9536GEN_SPEFPUOP_COMP_64(evfststgt);
9537GEN_SPEFPUOP_COMP_64(evfststlt);
9538GEN_SPEFPUOP_COMP_64(evfststeq);
9539
9540/* Opcodes definitions */
9541GEN_SPE(evfsadd,   evfssub,   0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9542GEN_SPE(evfsabs,   evfsnabs,  0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9543GEN_SPE(evfsneg,   speundef,  0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9544GEN_SPE(evfsmul,   evfsdiv,   0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9545GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9546GEN_SPE(evfscmpeq, speundef,  0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9547GEN_SPE(evfscfui,  evfscfsi,  0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9548GEN_SPE(evfscfuf,  evfscfsf,  0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9549GEN_SPE(evfsctui,  evfsctsi,  0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9550GEN_SPE(evfsctuf,  evfsctsf,  0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9551GEN_SPE(evfsctuiz, speundef,  0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9552GEN_SPE(evfsctsiz, speundef,  0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9553GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9554GEN_SPE(evfststeq, speundef,  0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9555
9556/* Single precision floating-point operations */
9557/* Arithmetic */
9558GEN_SPEFPUOP_ARITH2_32_32(efsadd);
9559GEN_SPEFPUOP_ARITH2_32_32(efssub);
9560GEN_SPEFPUOP_ARITH2_32_32(efsmul);
9561GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
9562static inline void gen_efsabs(DisasContext *ctx)
9563{
9564    if (unlikely(!ctx->spe_enabled)) {
9565        gen_exception(ctx, POWERPC_EXCP_SPEU);
9566        return;
9567    }
9568    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
9569}
9570static inline void gen_efsnabs(DisasContext *ctx)
9571{
9572    if (unlikely(!ctx->spe_enabled)) {
9573        gen_exception(ctx, POWERPC_EXCP_SPEU);
9574        return;
9575    }
9576    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
9577}
9578static inline void gen_efsneg(DisasContext *ctx)
9579{
9580    if (unlikely(!ctx->spe_enabled)) {
9581        gen_exception(ctx, POWERPC_EXCP_SPEU);
9582        return;
9583    }
9584    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
9585}
9586
9587/* Conversion */
9588GEN_SPEFPUOP_CONV_32_32(efscfui);
9589GEN_SPEFPUOP_CONV_32_32(efscfsi);
9590GEN_SPEFPUOP_CONV_32_32(efscfuf);
9591GEN_SPEFPUOP_CONV_32_32(efscfsf);
9592GEN_SPEFPUOP_CONV_32_32(efsctui);
9593GEN_SPEFPUOP_CONV_32_32(efsctsi);
9594GEN_SPEFPUOP_CONV_32_32(efsctuf);
9595GEN_SPEFPUOP_CONV_32_32(efsctsf);
9596GEN_SPEFPUOP_CONV_32_32(efsctuiz);
9597GEN_SPEFPUOP_CONV_32_32(efsctsiz);
9598GEN_SPEFPUOP_CONV_32_64(efscfd);
9599
9600/* Comparison */
9601GEN_SPEFPUOP_COMP_32(efscmpgt);
9602GEN_SPEFPUOP_COMP_32(efscmplt);
9603GEN_SPEFPUOP_COMP_32(efscmpeq);
9604GEN_SPEFPUOP_COMP_32(efststgt);
9605GEN_SPEFPUOP_COMP_32(efststlt);
9606GEN_SPEFPUOP_COMP_32(efststeq);
9607
9608/* Opcodes definitions */
9609GEN_SPE(efsadd,   efssub,   0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9610GEN_SPE(efsabs,   efsnabs,  0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9611GEN_SPE(efsneg,   speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9612GEN_SPE(efsmul,   efsdiv,   0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9613GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9614GEN_SPE(efscmpeq, efscfd,   0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
9615GEN_SPE(efscfui,  efscfsi,  0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9616GEN_SPE(efscfuf,  efscfsf,  0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9617GEN_SPE(efsctui,  efsctsi,  0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9618GEN_SPE(efsctuf,  efsctsf,  0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9619GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9620GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9621GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9622GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9623
9624/* Double precision floating-point operations */
9625/* Arithmetic */
9626GEN_SPEFPUOP_ARITH2_64_64(efdadd);
9627GEN_SPEFPUOP_ARITH2_64_64(efdsub);
9628GEN_SPEFPUOP_ARITH2_64_64(efdmul);
9629GEN_SPEFPUOP_ARITH2_64_64(efddiv);
9630static inline void gen_efdabs(DisasContext *ctx)
9631{
9632    if (unlikely(!ctx->spe_enabled)) {
9633        gen_exception(ctx, POWERPC_EXCP_SPEU);
9634        return;
9635    }
9636    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9637    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9638                    ~0x80000000);
9639}
9640static inline void gen_efdnabs(DisasContext *ctx)
9641{
9642    if (unlikely(!ctx->spe_enabled)) {
9643        gen_exception(ctx, POWERPC_EXCP_SPEU);
9644        return;
9645    }
9646    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9647    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9648                   0x80000000);
9649}
9650static inline void gen_efdneg(DisasContext *ctx)
9651{
9652    if (unlikely(!ctx->spe_enabled)) {
9653        gen_exception(ctx, POWERPC_EXCP_SPEU);
9654        return;
9655    }
9656    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9657    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9658                    0x80000000);
9659}
9660
9661/* Conversion */
9662GEN_SPEFPUOP_CONV_64_32(efdcfui);
9663GEN_SPEFPUOP_CONV_64_32(efdcfsi);
9664GEN_SPEFPUOP_CONV_64_32(efdcfuf);
9665GEN_SPEFPUOP_CONV_64_32(efdcfsf);
9666GEN_SPEFPUOP_CONV_32_64(efdctui);
9667GEN_SPEFPUOP_CONV_32_64(efdctsi);
9668GEN_SPEFPUOP_CONV_32_64(efdctuf);
9669GEN_SPEFPUOP_CONV_32_64(efdctsf);
9670GEN_SPEFPUOP_CONV_32_64(efdctuiz);
9671GEN_SPEFPUOP_CONV_32_64(efdctsiz);
9672GEN_SPEFPUOP_CONV_64_32(efdcfs);
9673GEN_SPEFPUOP_CONV_64_64(efdcfuid);
9674GEN_SPEFPUOP_CONV_64_64(efdcfsid);
9675GEN_SPEFPUOP_CONV_64_64(efdctuidz);
9676GEN_SPEFPUOP_CONV_64_64(efdctsidz);
9677
9678/* Comparison */
9679GEN_SPEFPUOP_COMP_64(efdcmpgt);
9680GEN_SPEFPUOP_COMP_64(efdcmplt);
9681GEN_SPEFPUOP_COMP_64(efdcmpeq);
9682GEN_SPEFPUOP_COMP_64(efdtstgt);
9683GEN_SPEFPUOP_COMP_64(efdtstlt);
9684GEN_SPEFPUOP_COMP_64(efdtsteq);
9685
9686/* Opcodes definitions */
9687GEN_SPE(efdadd,    efdsub,    0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9688GEN_SPE(efdcfuid,  efdcfsid,  0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9689GEN_SPE(efdabs,    efdnabs,   0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
9690GEN_SPE(efdneg,    speundef,  0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9691GEN_SPE(efdmul,    efddiv,    0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9692GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9693GEN_SPE(efdcmpgt,  efdcmplt,  0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9694GEN_SPE(efdcmpeq,  efdcfs,    0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
9695GEN_SPE(efdcfui,   efdcfsi,   0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9696GEN_SPE(efdcfuf,   efdcfsf,   0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9697GEN_SPE(efdctui,   efdctsi,   0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9698GEN_SPE(efdctuf,   efdctsf,   0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9699GEN_SPE(efdctuiz,  speundef,  0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9700GEN_SPE(efdctsiz,  speundef,  0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9701GEN_SPE(efdtstgt,  efdtstlt,  0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9702GEN_SPE(efdtsteq,  speundef,  0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9703
9704static void gen_tbegin(DisasContext *ctx)
9705{
9706    if (unlikely(!ctx->tm_enabled)) {
9707        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9708        return;
9709    }
9710    gen_helper_tbegin(cpu_env);
9711}
9712
9713#define GEN_TM_NOOP(name)                                      \
9714static inline void gen_##name(DisasContext *ctx)               \
9715{                                                              \
9716    if (unlikely(!ctx->tm_enabled)) {                          \
9717        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
9718        return;                                                \
9719    }                                                          \
9720    /* Because tbegin always fails in QEMU, these user         \
9721     * space instructions all have a simple implementation:    \
9722     *                                                         \
9723     *     CR[0] = 0b0 || MSR[TS] || 0b0                       \
9724     *           = 0b0 || 0b00    || 0b0                       \
9725     */                                                        \
9726    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
9727}
9728
9729GEN_TM_NOOP(tend);
9730GEN_TM_NOOP(tabort);
9731GEN_TM_NOOP(tabortwc);
9732GEN_TM_NOOP(tabortwci);
9733GEN_TM_NOOP(tabortdc);
9734GEN_TM_NOOP(tabortdci);
9735GEN_TM_NOOP(tsr);
9736
9737static void gen_tcheck(DisasContext *ctx)
9738{
9739    if (unlikely(!ctx->tm_enabled)) {
9740        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9741        return;
9742    }
9743    /* Because tbegin always fails, the tcheck implementation
9744     * is simple:
9745     *
9746     * CR[CRF] = TDOOMED || MSR[TS] || 0b0
9747     *         = 0b1 || 0b00 || 0b0
9748     */
9749    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
9750}
9751
9752#if defined(CONFIG_USER_ONLY)
9753#define GEN_TM_PRIV_NOOP(name)                                 \
9754static inline void gen_##name(DisasContext *ctx)               \
9755{                                                              \
9756    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);           \
9757}
9758
9759#else
9760
9761#define GEN_TM_PRIV_NOOP(name)                                 \
9762static inline void gen_##name(DisasContext *ctx)               \
9763{                                                              \
9764    if (unlikely(ctx->pr)) {                                   \
9765        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);       \
9766        return;                                                \
9767    }                                                          \
9768    if (unlikely(!ctx->tm_enabled)) {                          \
9769        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
9770        return;                                                \
9771    }                                                          \
9772    /* Because tbegin always fails, the implementation is      \
9773     * simple:                                                 \
9774     *                                                         \
9775     *   CR[0] = 0b0 || MSR[TS] || 0b0                         \
9776     *         = 0b0 || 0b00 | 0b0                             \
9777     */                                                        \
9778    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
9779}
9780
9781#endif
9782
9783GEN_TM_PRIV_NOOP(treclaim);
9784GEN_TM_PRIV_NOOP(trechkpt);
9785
9786static opcode_t opcodes[] = {
9787GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
9788GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
9789GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
9790GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
9791GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
9792GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
9793GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
9794GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9795GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9796GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9797GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9798GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
9799GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
9800GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
9801GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
9802GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9803#if defined(TARGET_PPC64)
9804GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
9805#endif
9806GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
9807GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
9808GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9809GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9810GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9811GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
9812GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
9813GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
9814GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9815GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9816GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9817GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9818GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
9819GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
9820GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
9821#if defined(TARGET_PPC64)
9822GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
9823GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
9824GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
9825GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
9826#endif
9827GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9828GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9829GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9830GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
9831GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
9832GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
9833GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
9834#if defined(TARGET_PPC64)
9835GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
9836GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
9837GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
9838GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
9839GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
9840#endif
9841GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
9842GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9843GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9844GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
9845GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
9846GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
9847GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
9848GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
9849GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
9850GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
9851GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x00000001, PPC_NONE, PPC2_VSX207),
9852GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x00000001, PPC_NONE, PPC2_VSX207),
9853GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
9854GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
9855GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
9856GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
9857GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
9858GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
9859#if defined(TARGET_PPC64)
9860GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
9861GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
9862GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
9863#endif
9864GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9865GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9866GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
9867GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
9868GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
9869GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
9870GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
9871GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
9872GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9873GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9874GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
9875GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9876GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9877GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
9878#if defined(TARGET_PPC64)
9879GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
9880GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
9881GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
9882GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
9883#endif
9884GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
9885GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
9886GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9887GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9888GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
9889GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
9890GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0, PPC_NONE, PPC2_BCTAR_ISA207),
9891GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
9892GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
9893#if defined(TARGET_PPC64)
9894GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
9895GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
9896#endif
9897GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
9898GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
9899GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9900#if defined(TARGET_PPC64)
9901GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
9902GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
9903#endif
9904GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
9905GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
9906GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
9907GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
9908GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
9909GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
9910#if defined(TARGET_PPC64)
9911GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
9912#endif
9913GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
9914GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
9915GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
9916GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
9917GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
9918GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
9919GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
9920GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
9921GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
9922GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
9923GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
9924GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
9925GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
9926GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
9927GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
9928GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
9929GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
9930GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
9931#if defined(TARGET_PPC64)
9932GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
9933GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
9934             PPC_SEGMENT_64B),
9935GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
9936GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
9937             PPC_SEGMENT_64B),
9938GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
9939GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
9940GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
9941#endif
9942GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
9943GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
9944GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
9945GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
9946#if defined(TARGET_PPC64)
9947GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
9948GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
9949#endif
9950GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
9951GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
9952GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
9953GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
9954GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
9955GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
9956GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
9957GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
9958GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
9959GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
9960GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
9961GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9962GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
9963GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
9964GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
9965GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
9966GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
9967GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
9968GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
9969GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9970GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
9971GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
9972GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
9973GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
9974GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
9975GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
9976GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
9977GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
9978GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
9979GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
9980GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
9981GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
9982GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
9983GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
9984GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
9985GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
9986GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
9987GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
9988GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
9989GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
9990GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
9991GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
9992GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
9993GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
9994GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
9995GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
9996GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
9997GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
9998GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
9999GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10000GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10001GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
10002GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
10003GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10004GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10005GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
10006GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
10007GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
10008GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
10009GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
10010GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
10011GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
10012GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
10013GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
10014GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
10015GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
10016GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
10017GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
10018GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
10019GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
10020GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
10021GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
10022GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
10023GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
10024GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
10025GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
10026GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
10027GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
10028GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
10029GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
10030GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
10031               PPC_NONE, PPC2_BOOKE206),
10032GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
10033               PPC_NONE, PPC2_BOOKE206),
10034GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
10035               PPC_NONE, PPC2_BOOKE206),
10036GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
10037               PPC_NONE, PPC2_BOOKE206),
10038GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
10039               PPC_NONE, PPC2_BOOKE206),
10040GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
10041               PPC_NONE, PPC2_PRCNTL),
10042GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
10043               PPC_NONE, PPC2_PRCNTL),
10044GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
10045GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
10046GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
10047GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
10048              PPC_BOOKE, PPC2_BOOKE206),
10049GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
10050GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
10051               PPC_BOOKE, PPC2_BOOKE206),
10052GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
10053GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
10054GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
10055GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
10056GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
10057GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
10058GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
10059GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
10060GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
10061
10062#undef GEN_INT_ARITH_ADD
10063#undef GEN_INT_ARITH_ADD_CONST
10064#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
10065GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
10066#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
10067                                add_ca, compute_ca, compute_ov)               \
10068GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
10069GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
10070GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
10071GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
10072GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
10073GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
10074GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
10075GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
10076GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
10077GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
10078GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
10079
10080#undef GEN_INT_ARITH_DIVW
10081#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
10082GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
10083GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
10084GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
10085GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
10086GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
10087GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10088GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10089GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10090GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10091
10092#if defined(TARGET_PPC64)
10093#undef GEN_INT_ARITH_DIVD
10094#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
10095GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10096GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
10097GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
10098GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
10099GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
10100
10101GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10102GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10103GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10104GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10105
10106#undef GEN_INT_ARITH_MUL_HELPER
10107#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
10108GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10109GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
10110GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
10111GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
10112#endif
10113
10114#undef GEN_INT_ARITH_SUBF
10115#undef GEN_INT_ARITH_SUBF_CONST
10116#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
10117GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
10118#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
10119                                add_ca, compute_ca, compute_ov)               \
10120GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
10121GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
10122GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
10123GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
10124GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
10125GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
10126GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
10127GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
10128GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
10129GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
10130GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
10131
10132#undef GEN_LOGICAL1
10133#undef GEN_LOGICAL2
10134#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
10135GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
10136#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
10137GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
10138GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
10139GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
10140GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
10141GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
10142GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
10143GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
10144GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
10145GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
10146#if defined(TARGET_PPC64)
10147GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
10148#endif
10149
10150#if defined(TARGET_PPC64)
10151#undef GEN_PPC64_R2
10152#undef GEN_PPC64_R4
10153#define GEN_PPC64_R2(name, opc1, opc2)                                        \
10154GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10155GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
10156             PPC_64B)
10157#define GEN_PPC64_R4(name, opc1, opc2)                                        \
10158GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10159GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
10160             PPC_64B),                                                        \
10161GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
10162             PPC_64B),                                                        \
10163GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
10164             PPC_64B)
10165GEN_PPC64_R4(rldicl, 0x1E, 0x00),
10166GEN_PPC64_R4(rldicr, 0x1E, 0x02),
10167GEN_PPC64_R4(rldic, 0x1E, 0x04),
10168GEN_PPC64_R2(rldcl, 0x1E, 0x08),
10169GEN_PPC64_R2(rldcr, 0x1E, 0x09),
10170GEN_PPC64_R4(rldimi, 0x1E, 0x06),
10171#endif
10172
10173#undef _GEN_FLOAT_ACB
10174#undef GEN_FLOAT_ACB
10175#undef _GEN_FLOAT_AB
10176#undef GEN_FLOAT_AB
10177#undef _GEN_FLOAT_AC
10178#undef GEN_FLOAT_AC
10179#undef GEN_FLOAT_B
10180#undef GEN_FLOAT_BS
10181#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
10182GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
10183#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
10184_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type),                     \
10185_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
10186#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
10187GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10188#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
10189_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
10190_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10191#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
10192GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10193#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
10194_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
10195_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10196#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
10197GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
10198#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
10199GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
10200
10201GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
10202GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
10203GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
10204GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
10205GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
10206GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
10207_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
10208GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
10209GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
10210GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
10211GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
10212GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
10213GEN_HANDLER_E(ftdiv, 0x3F, 0x00, 0x04, 1, PPC_NONE, PPC2_FP_TST_ISA206),
10214GEN_HANDLER_E(ftsqrt, 0x3F, 0x00, 0x05, 1, PPC_NONE, PPC2_FP_TST_ISA206),
10215GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
10216GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10217GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
10218GEN_HANDLER_E(fctiwuz, 0x3F, 0x0F, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10219GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
10220GEN_HANDLER_E(fcfid, 0x3F, 0x0E, 0x1A, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10221GEN_HANDLER_E(fcfids, 0x3B, 0x0E, 0x1A, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10222GEN_HANDLER_E(fcfidu, 0x3F, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10223GEN_HANDLER_E(fcfidus, 0x3B, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10224GEN_HANDLER_E(fctid, 0x3F, 0x0E, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10225GEN_HANDLER_E(fctidu, 0x3F, 0x0E, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10226GEN_HANDLER_E(fctidz, 0x3F, 0x0F, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10227GEN_HANDLER_E(fctiduz, 0x3F, 0x0F, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10228GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
10229GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
10230GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
10231GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
10232
10233#undef GEN_LD
10234#undef GEN_LDU
10235#undef GEN_LDUX
10236#undef GEN_LDX_E
10237#undef GEN_LDS
10238#define GEN_LD(name, ldop, opc, type)                                         \
10239GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10240#define GEN_LDU(name, ldop, opc, type)                                        \
10241GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10242#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
10243GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
10244#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
10245GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
10246#define GEN_LDS(name, ldop, op, type)                                         \
10247GEN_LD(name, ldop, op | 0x20, type)                                           \
10248GEN_LDU(name, ldop, op | 0x21, type)                                          \
10249GEN_LDUX(name, ldop, 0x17, op | 0x01, type)                                   \
10250GEN_LDX(name, ldop, 0x17, op | 0x00, type)
10251
10252GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
10253GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
10254GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
10255GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
10256#if defined(TARGET_PPC64)
10257GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
10258GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
10259GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
10260GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
10261GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
10262#endif
10263GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
10264GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
10265
10266#undef GEN_ST
10267#undef GEN_STU
10268#undef GEN_STUX
10269#undef GEN_STX_E
10270#undef GEN_STS
10271#define GEN_ST(name, stop, opc, type)                                         \
10272GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10273#define GEN_STU(name, stop, opc, type)                                        \
10274GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
10275#define GEN_STUX(name, stop, opc2, opc3, type)                                \
10276GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
10277#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
10278GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
10279#define GEN_STS(name, stop, op, type)                                         \
10280GEN_ST(name, stop, op | 0x20, type)                                           \
10281GEN_STU(name, stop, op | 0x21, type)                                          \
10282GEN_STUX(name, stop, 0x17, op | 0x01, type)                                   \
10283GEN_STX(name, stop, 0x17, op | 0x00, type)
10284
10285GEN_STS(stb, st8, 0x06, PPC_INTEGER)
10286GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
10287GEN_STS(stw, st32, 0x04, PPC_INTEGER)
10288#if defined(TARGET_PPC64)
10289GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
10290GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
10291GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
10292#endif
10293GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
10294GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
10295
10296#undef GEN_LDF
10297#undef GEN_LDUF
10298#undef GEN_LDUXF
10299#undef GEN_LDXF
10300#undef GEN_LDFS
10301#define GEN_LDF(name, ldop, opc, type)                                        \
10302GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10303#define GEN_LDUF(name, ldop, opc, type)                                       \
10304GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10305#define GEN_LDUXF(name, ldop, opc, type)                                      \
10306GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10307#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
10308GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10309#define GEN_LDFS(name, ldop, op, type)                                        \
10310GEN_LDF(name, ldop, op | 0x20, type)                                          \
10311GEN_LDUF(name, ldop, op | 0x21, type)                                         \
10312GEN_LDUXF(name, ldop, op | 0x01, type)                                        \
10313GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
10314
10315GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
10316GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
10317GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
10318GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x1, PPC_NONE, PPC2_FP_CVT_ISA206),
10319GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10320GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
10321
10322#undef GEN_STF
10323#undef GEN_STUF
10324#undef GEN_STUXF
10325#undef GEN_STXF
10326#undef GEN_STFS
10327#define GEN_STF(name, stop, opc, type)                                        \
10328GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10329#define GEN_STUF(name, stop, opc, type)                                       \
10330GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10331#define GEN_STUXF(name, stop, opc, type)                                      \
10332GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10333#define GEN_STXF(name, stop, opc2, opc3, type)                                \
10334GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10335#define GEN_STFS(name, stop, op, type)                                        \
10336GEN_STF(name, stop, op | 0x20, type)                                          \
10337GEN_STUF(name, stop, op | 0x21, type)                                         \
10338GEN_STUXF(name, stop, op | 0x01, type)                                        \
10339GEN_STXF(name, stop, 0x17, op | 0x00, type)
10340
10341GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
10342GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
10343GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
10344GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10345GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
10346
10347#undef GEN_CRLOGIC
10348#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
10349GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
10350GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
10351GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
10352GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
10353GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
10354GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
10355GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
10356GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
10357GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
10358
10359#undef GEN_MAC_HANDLER
10360#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
10361GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
10362GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
10363GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
10364GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
10365GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
10366GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
10367GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
10368GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
10369GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
10370GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
10371GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
10372GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
10373GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
10374GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
10375GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
10376GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
10377GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
10378GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
10379GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
10380GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
10381GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
10382GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
10383GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
10384GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
10385GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
10386GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
10387GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
10388GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
10389GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
10390GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
10391GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
10392GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
10393GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
10394GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
10395GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
10396GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
10397GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
10398GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
10399GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
10400GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
10401GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
10402GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
10403GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
10404
10405#undef GEN_VR_LDX
10406#undef GEN_VR_STX
10407#undef GEN_VR_LVE
10408#undef GEN_VR_STVE
10409#define GEN_VR_LDX(name, opc2, opc3)                                          \
10410GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10411#define GEN_VR_STX(name, opc2, opc3)                                          \
10412GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10413#define GEN_VR_LVE(name, opc2, opc3)                                    \
10414    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10415#define GEN_VR_STVE(name, opc2, opc3)                                   \
10416    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10417GEN_VR_LDX(lvx, 0x07, 0x03),
10418GEN_VR_LDX(lvxl, 0x07, 0x0B),
10419GEN_VR_LVE(bx, 0x07, 0x00),
10420GEN_VR_LVE(hx, 0x07, 0x01),
10421GEN_VR_LVE(wx, 0x07, 0x02),
10422GEN_VR_STX(svx, 0x07, 0x07),
10423GEN_VR_STX(svxl, 0x07, 0x0F),
10424GEN_VR_STVE(bx, 0x07, 0x04),
10425GEN_VR_STVE(hx, 0x07, 0x05),
10426GEN_VR_STVE(wx, 0x07, 0x06),
10427
10428#undef GEN_VX_LOGICAL
10429#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
10430GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10431
10432#undef GEN_VX_LOGICAL_207
10433#define GEN_VX_LOGICAL_207(name, tcg_op, opc2, opc3) \
10434GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10435
10436GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
10437GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
10438GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
10439GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
10440GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
10441GEN_VX_LOGICAL_207(veqv, tcg_gen_eqv_i64, 2, 26),
10442GEN_VX_LOGICAL_207(vnand, tcg_gen_nand_i64, 2, 22),
10443GEN_VX_LOGICAL_207(vorc, tcg_gen_orc_i64, 2, 21),
10444
10445#undef GEN_VXFORM
10446#define GEN_VXFORM(name, opc2, opc3)                                    \
10447GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10448
10449#undef GEN_VXFORM_207
10450#define GEN_VXFORM_207(name, opc2, opc3) \
10451GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10452
10453#undef GEN_VXFORM_DUAL
10454#define GEN_VXFORM_DUAL(name0, name1, opc2, opc3, type0, type1) \
10455GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, type0, type1)
10456
10457#undef GEN_VXRFORM_DUAL
10458#define GEN_VXRFORM_DUAL(name0, name1, opc2, opc3, tp0, tp1) \
10459GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, tp0, tp1), \
10460GEN_HANDLER_E(name0##_##name1, 0x4, opc2, (opc3 | 0x10), 0x00000000, tp0, tp1),
10461
10462GEN_VXFORM(vaddubm, 0, 0),
10463GEN_VXFORM(vadduhm, 0, 1),
10464GEN_VXFORM(vadduwm, 0, 2),
10465GEN_VXFORM_207(vaddudm, 0, 3),
10466GEN_VXFORM_DUAL(vsububm, bcdadd, 0, 16, PPC_ALTIVEC, PPC_NONE),
10467GEN_VXFORM_DUAL(vsubuhm, bcdsub, 0, 17, PPC_ALTIVEC, PPC_NONE),
10468GEN_VXFORM(vsubuwm, 0, 18),
10469GEN_VXFORM_207(vsubudm, 0, 19),
10470GEN_VXFORM(vmaxub, 1, 0),
10471GEN_VXFORM(vmaxuh, 1, 1),
10472GEN_VXFORM(vmaxuw, 1, 2),
10473GEN_VXFORM_207(vmaxud, 1, 3),
10474GEN_VXFORM(vmaxsb, 1, 4),
10475GEN_VXFORM(vmaxsh, 1, 5),
10476GEN_VXFORM(vmaxsw, 1, 6),
10477GEN_VXFORM_207(vmaxsd, 1, 7),
10478GEN_VXFORM(vminub, 1, 8),
10479GEN_VXFORM(vminuh, 1, 9),
10480GEN_VXFORM(vminuw, 1, 10),
10481GEN_VXFORM_207(vminud, 1, 11),
10482GEN_VXFORM(vminsb, 1, 12),
10483GEN_VXFORM(vminsh, 1, 13),
10484GEN_VXFORM(vminsw, 1, 14),
10485GEN_VXFORM_207(vminsd, 1, 15),
10486GEN_VXFORM(vavgub, 1, 16),
10487GEN_VXFORM(vavguh, 1, 17),
10488GEN_VXFORM(vavguw, 1, 18),
10489GEN_VXFORM(vavgsb, 1, 20),
10490GEN_VXFORM(vavgsh, 1, 21),
10491GEN_VXFORM(vavgsw, 1, 22),
10492GEN_VXFORM(vmrghb, 6, 0),
10493GEN_VXFORM(vmrghh, 6, 1),
10494GEN_VXFORM(vmrghw, 6, 2),
10495GEN_VXFORM(vmrglb, 6, 4),
10496GEN_VXFORM(vmrglh, 6, 5),
10497GEN_VXFORM(vmrglw, 6, 6),
10498GEN_VXFORM_207(vmrgew, 6, 30),
10499GEN_VXFORM_207(vmrgow, 6, 26),
10500GEN_VXFORM(vmuloub, 4, 0),
10501GEN_VXFORM(vmulouh, 4, 1),
10502GEN_VXFORM_DUAL(vmulouw, vmuluwm, 4, 2, PPC_ALTIVEC, PPC_NONE),
10503GEN_VXFORM(vmulosb, 4, 4),
10504GEN_VXFORM(vmulosh, 4, 5),
10505GEN_VXFORM_207(vmulosw, 4, 6),
10506GEN_VXFORM(vmuleub, 4, 8),
10507GEN_VXFORM(vmuleuh, 4, 9),
10508GEN_VXFORM_207(vmuleuw, 4, 10),
10509GEN_VXFORM(vmulesb, 4, 12),
10510GEN_VXFORM(vmulesh, 4, 13),
10511GEN_VXFORM_207(vmulesw, 4, 14),
10512GEN_VXFORM(vslb, 2, 4),
10513GEN_VXFORM(vslh, 2, 5),
10514GEN_VXFORM(vslw, 2, 6),
10515GEN_VXFORM_207(vsld, 2, 23),
10516GEN_VXFORM(vsrb, 2, 8),
10517GEN_VXFORM(vsrh, 2, 9),
10518GEN_VXFORM(vsrw, 2, 10),
10519GEN_VXFORM_207(vsrd, 2, 27),
10520GEN_VXFORM(vsrab, 2, 12),
10521GEN_VXFORM(vsrah, 2, 13),
10522GEN_VXFORM(vsraw, 2, 14),
10523GEN_VXFORM_207(vsrad, 2, 15),
10524GEN_VXFORM(vslo, 6, 16),
10525GEN_VXFORM(vsro, 6, 17),
10526GEN_VXFORM(vaddcuw, 0, 6),
10527GEN_VXFORM(vsubcuw, 0, 22),
10528GEN_VXFORM(vaddubs, 0, 8),
10529GEN_VXFORM(vadduhs, 0, 9),
10530GEN_VXFORM(vadduws, 0, 10),
10531GEN_VXFORM(vaddsbs, 0, 12),
10532GEN_VXFORM(vaddshs, 0, 13),
10533GEN_VXFORM(vaddsws, 0, 14),
10534GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
10535GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
10536GEN_VXFORM(vsubuws, 0, 26),
10537GEN_VXFORM(vsubsbs, 0, 28),
10538GEN_VXFORM(vsubshs, 0, 29),
10539GEN_VXFORM(vsubsws, 0, 30),
10540GEN_VXFORM_207(vadduqm, 0, 4),
10541GEN_VXFORM_207(vaddcuq, 0, 5),
10542GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
10543GEN_VXFORM_207(vsubuqm, 0, 20),
10544GEN_VXFORM_207(vsubcuq, 0, 21),
10545GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
10546GEN_VXFORM(vrlb, 2, 0),
10547GEN_VXFORM(vrlh, 2, 1),
10548GEN_VXFORM(vrlw, 2, 2),
10549GEN_VXFORM_207(vrld, 2, 3),
10550GEN_VXFORM(vsl, 2, 7),
10551GEN_VXFORM(vsr, 2, 11),
10552GEN_VXFORM(vpkuhum, 7, 0),
10553GEN_VXFORM(vpkuwum, 7, 1),
10554GEN_VXFORM_207(vpkudum, 7, 17),
10555GEN_VXFORM(vpkuhus, 7, 2),
10556GEN_VXFORM(vpkuwus, 7, 3),
10557GEN_VXFORM_207(vpkudus, 7, 19),
10558GEN_VXFORM(vpkshus, 7, 4),
10559GEN_VXFORM(vpkswus, 7, 5),
10560GEN_VXFORM_207(vpksdus, 7, 21),
10561GEN_VXFORM(vpkshss, 7, 6),
10562GEN_VXFORM(vpkswss, 7, 7),
10563GEN_VXFORM_207(vpksdss, 7, 23),
10564GEN_VXFORM(vpkpx, 7, 12),
10565GEN_VXFORM(vsum4ubs, 4, 24),
10566GEN_VXFORM(vsum4sbs, 4, 28),
10567GEN_VXFORM(vsum4shs, 4, 25),
10568GEN_VXFORM(vsum2sws, 4, 26),
10569GEN_VXFORM(vsumsws, 4, 30),
10570GEN_VXFORM(vaddfp, 5, 0),
10571GEN_VXFORM(vsubfp, 5, 1),
10572GEN_VXFORM(vmaxfp, 5, 16),
10573GEN_VXFORM(vminfp, 5, 17),
10574
10575#undef GEN_VXRFORM1
10576#undef GEN_VXRFORM
10577#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
10578    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
10579#define GEN_VXRFORM(name, opc2, opc3)                                \
10580    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
10581    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
10582GEN_VXRFORM(vcmpequb, 3, 0)
10583GEN_VXRFORM(vcmpequh, 3, 1)
10584GEN_VXRFORM(vcmpequw, 3, 2)
10585GEN_VXRFORM(vcmpgtsb, 3, 12)
10586GEN_VXRFORM(vcmpgtsh, 3, 13)
10587GEN_VXRFORM(vcmpgtsw, 3, 14)
10588GEN_VXRFORM(vcmpgtub, 3, 8)
10589GEN_VXRFORM(vcmpgtuh, 3, 9)
10590GEN_VXRFORM(vcmpgtuw, 3, 10)
10591GEN_VXRFORM_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
10592GEN_VXRFORM(vcmpgefp, 3, 7)
10593GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
10594GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
10595
10596#undef GEN_VXFORM_SIMM
10597#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
10598    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10599GEN_VXFORM_SIMM(vspltisb, 6, 12),
10600GEN_VXFORM_SIMM(vspltish, 6, 13),
10601GEN_VXFORM_SIMM(vspltisw, 6, 14),
10602
10603#undef GEN_VXFORM_NOA
10604#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
10605    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
10606GEN_VXFORM_NOA(vupkhsb, 7, 8),
10607GEN_VXFORM_NOA(vupkhsh, 7, 9),
10608GEN_VXFORM_207(vupkhsw, 7, 25),
10609GEN_VXFORM_NOA(vupklsb, 7, 10),
10610GEN_VXFORM_NOA(vupklsh, 7, 11),
10611GEN_VXFORM_207(vupklsw, 7, 27),
10612GEN_VXFORM_NOA(vupkhpx, 7, 13),
10613GEN_VXFORM_NOA(vupklpx, 7, 15),
10614GEN_VXFORM_NOA(vrefp, 5, 4),
10615GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
10616GEN_VXFORM_NOA(vexptefp, 5, 6),
10617GEN_VXFORM_NOA(vlogefp, 5, 7),
10618GEN_VXFORM_NOA(vrfim, 5, 11),
10619GEN_VXFORM_NOA(vrfin, 5, 8),
10620GEN_VXFORM_NOA(vrfip, 5, 10),
10621GEN_VXFORM_NOA(vrfiz, 5, 9),
10622
10623#undef GEN_VXFORM_UIMM
10624#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
10625    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10626GEN_VXFORM_UIMM(vspltb, 6, 8),
10627GEN_VXFORM_UIMM(vsplth, 6, 9),
10628GEN_VXFORM_UIMM(vspltw, 6, 10),
10629GEN_VXFORM_UIMM(vcfux, 5, 12),
10630GEN_VXFORM_UIMM(vcfsx, 5, 13),
10631GEN_VXFORM_UIMM(vctuxs, 5, 14),
10632GEN_VXFORM_UIMM(vctsxs, 5, 15),
10633
10634#undef GEN_VAFORM_PAIRED
10635#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
10636    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
10637GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
10638GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
10639GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
10640GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
10641GEN_VAFORM_PAIRED(vsel, vperm, 21),
10642GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
10643
10644GEN_VXFORM_DUAL(vclzb, vpopcntb, 1, 28, PPC_NONE, PPC2_ALTIVEC_207),
10645GEN_VXFORM_DUAL(vclzh, vpopcnth, 1, 29, PPC_NONE, PPC2_ALTIVEC_207),
10646GEN_VXFORM_DUAL(vclzw, vpopcntw, 1, 30, PPC_NONE, PPC2_ALTIVEC_207),
10647GEN_VXFORM_DUAL(vclzd, vpopcntd, 1, 31, PPC_NONE, PPC2_ALTIVEC_207),
10648
10649GEN_VXFORM_207(vbpermq, 6, 21),
10650GEN_VXFORM_207(vgbbd, 6, 20),
10651GEN_VXFORM_207(vpmsumb, 4, 16),
10652GEN_VXFORM_207(vpmsumh, 4, 17),
10653GEN_VXFORM_207(vpmsumw, 4, 18),
10654GEN_VXFORM_207(vpmsumd, 4, 19),
10655
10656GEN_VXFORM_207(vsbox, 4, 23),
10657
10658GEN_VXFORM_DUAL(vcipher, vcipherlast, 4, 20, PPC_NONE, PPC2_ALTIVEC_207),
10659GEN_VXFORM_DUAL(vncipher, vncipherlast, 4, 21, PPC_NONE, PPC2_ALTIVEC_207),
10660
10661GEN_VXFORM_207(vshasigmaw, 1, 26),
10662GEN_VXFORM_207(vshasigmad, 1, 27),
10663
10664GEN_VXFORM_DUAL(vsldoi, vpermxor, 22, 0xFF, PPC_ALTIVEC, PPC_NONE),
10665
10666GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
10667GEN_HANDLER_E(lxsiwax, 0x1F, 0x0C, 0x02, 0, PPC_NONE, PPC2_VSX207),
10668GEN_HANDLER_E(lxsiwzx, 0x1F, 0x0C, 0x00, 0, PPC_NONE, PPC2_VSX207),
10669GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
10670GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
10671GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
10672GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
10673
10674GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
10675GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
10676GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
10677GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
10678GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
10679
10680GEN_HANDLER_E(mfvsrwz, 0x1F, 0x13, 0x03, 0x0000F800, PPC_NONE, PPC2_VSX207),
10681GEN_HANDLER_E(mtvsrwa, 0x1F, 0x13, 0x06, 0x0000F800, PPC_NONE, PPC2_VSX207),
10682GEN_HANDLER_E(mtvsrwz, 0x1F, 0x13, 0x07, 0x0000F800, PPC_NONE, PPC2_VSX207),
10683#if defined(TARGET_PPC64)
10684GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
10685GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
10686#endif
10687
10688#undef GEN_XX2FORM
10689#define GEN_XX2FORM(name, opc2, opc3, fl2)                           \
10690GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10691GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
10692
10693#undef GEN_XX3FORM
10694#define GEN_XX3FORM(name, opc2, opc3, fl2)                           \
10695GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10696GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
10697GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
10698GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
10699
10700#undef GEN_XX2IFORM
10701#define GEN_XX2IFORM(name, opc2, opc3, fl2)                           \
10702GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 1, PPC_NONE, fl2), \
10703GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 1, PPC_NONE, fl2), \
10704GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 1, PPC_NONE, fl2), \
10705GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 1, PPC_NONE, fl2)
10706
10707#undef GEN_XX3_RC_FORM
10708#define GEN_XX3_RC_FORM(name, opc2, opc3, fl2)                          \
10709GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x00, 0, PPC_NONE, fl2), \
10710GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x00, 0, PPC_NONE, fl2), \
10711GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x00, 0, PPC_NONE, fl2), \
10712GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x00, 0, PPC_NONE, fl2), \
10713GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x10, 0, PPC_NONE, fl2), \
10714GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x10, 0, PPC_NONE, fl2), \
10715GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x10, 0, PPC_NONE, fl2), \
10716GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x10, 0, PPC_NONE, fl2)
10717
10718#undef GEN_XX3FORM_DM
10719#define GEN_XX3FORM_DM(name, opc2, opc3) \
10720GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10721GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10722GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10723GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10724GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10725GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10726GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10727GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10728GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10729GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10730GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10731GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10732GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10733GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10734GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10735GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x0C, 0, PPC_NONE, PPC2_VSX)
10736
10737GEN_XX2FORM(xsabsdp, 0x12, 0x15, PPC2_VSX),
10738GEN_XX2FORM(xsnabsdp, 0x12, 0x16, PPC2_VSX),
10739GEN_XX2FORM(xsnegdp, 0x12, 0x17, PPC2_VSX),
10740GEN_XX3FORM(xscpsgndp, 0x00, 0x16, PPC2_VSX),
10741
10742GEN_XX2FORM(xvabsdp, 0x12, 0x1D, PPC2_VSX),
10743GEN_XX2FORM(xvnabsdp, 0x12, 0x1E, PPC2_VSX),
10744GEN_XX2FORM(xvnegdp, 0x12, 0x1F, PPC2_VSX),
10745GEN_XX3FORM(xvcpsgndp, 0x00, 0x1E, PPC2_VSX),
10746GEN_XX2FORM(xvabssp, 0x12, 0x19, PPC2_VSX),
10747GEN_XX2FORM(xvnabssp, 0x12, 0x1A, PPC2_VSX),
10748GEN_XX2FORM(xvnegsp, 0x12, 0x1B, PPC2_VSX),
10749GEN_XX3FORM(xvcpsgnsp, 0x00, 0x1A, PPC2_VSX),
10750
10751GEN_XX3FORM(xsadddp, 0x00, 0x04, PPC2_VSX),
10752GEN_XX3FORM(xssubdp, 0x00, 0x05, PPC2_VSX),
10753GEN_XX3FORM(xsmuldp, 0x00, 0x06, PPC2_VSX),
10754GEN_XX3FORM(xsdivdp, 0x00, 0x07, PPC2_VSX),
10755GEN_XX2FORM(xsredp,  0x14, 0x05, PPC2_VSX),
10756GEN_XX2FORM(xssqrtdp,  0x16, 0x04, PPC2_VSX),
10757GEN_XX2FORM(xsrsqrtedp,  0x14, 0x04, PPC2_VSX),
10758GEN_XX3FORM(xstdivdp,  0x14, 0x07, PPC2_VSX),
10759GEN_XX2FORM(xstsqrtdp,  0x14, 0x06, PPC2_VSX),
10760GEN_XX3FORM(xsmaddadp, 0x04, 0x04, PPC2_VSX),
10761GEN_XX3FORM(xsmaddmdp, 0x04, 0x05, PPC2_VSX),
10762GEN_XX3FORM(xsmsubadp, 0x04, 0x06, PPC2_VSX),
10763GEN_XX3FORM(xsmsubmdp, 0x04, 0x07, PPC2_VSX),
10764GEN_XX3FORM(xsnmaddadp, 0x04, 0x14, PPC2_VSX),
10765GEN_XX3FORM(xsnmaddmdp, 0x04, 0x15, PPC2_VSX),
10766GEN_XX3FORM(xsnmsubadp, 0x04, 0x16, PPC2_VSX),
10767GEN_XX3FORM(xsnmsubmdp, 0x04, 0x17, PPC2_VSX),
10768GEN_XX2IFORM(xscmpodp,  0x0C, 0x05, PPC2_VSX),
10769GEN_XX2IFORM(xscmpudp,  0x0C, 0x04, PPC2_VSX),
10770GEN_XX3FORM(xsmaxdp, 0x00, 0x14, PPC2_VSX),
10771GEN_XX3FORM(xsmindp, 0x00, 0x15, PPC2_VSX),
10772GEN_XX2FORM(xscvdpsp, 0x12, 0x10, PPC2_VSX),
10773GEN_XX2FORM(xscvdpspn, 0x16, 0x10, PPC2_VSX207),
10774GEN_XX2FORM(xscvspdp, 0x12, 0x14, PPC2_VSX),
10775GEN_XX2FORM(xscvspdpn, 0x16, 0x14, PPC2_VSX207),
10776GEN_XX2FORM(xscvdpsxds, 0x10, 0x15, PPC2_VSX),
10777GEN_XX2FORM(xscvdpsxws, 0x10, 0x05, PPC2_VSX),
10778GEN_XX2FORM(xscvdpuxds, 0x10, 0x14, PPC2_VSX),
10779GEN_XX2FORM(xscvdpuxws, 0x10, 0x04, PPC2_VSX),
10780GEN_XX2FORM(xscvsxddp, 0x10, 0x17, PPC2_VSX),
10781GEN_XX2FORM(xscvuxddp, 0x10, 0x16, PPC2_VSX),
10782GEN_XX2FORM(xsrdpi, 0x12, 0x04, PPC2_VSX),
10783GEN_XX2FORM(xsrdpic, 0x16, 0x06, PPC2_VSX),
10784GEN_XX2FORM(xsrdpim, 0x12, 0x07, PPC2_VSX),
10785GEN_XX2FORM(xsrdpip, 0x12, 0x06, PPC2_VSX),
10786GEN_XX2FORM(xsrdpiz, 0x12, 0x05, PPC2_VSX),
10787
10788GEN_XX3FORM(xsaddsp, 0x00, 0x00, PPC2_VSX207),
10789GEN_XX3FORM(xssubsp, 0x00, 0x01, PPC2_VSX207),
10790GEN_XX3FORM(xsmulsp, 0x00, 0x02, PPC2_VSX207),
10791GEN_XX3FORM(xsdivsp, 0x00, 0x03, PPC2_VSX207),
10792GEN_XX2FORM(xsresp,  0x14, 0x01, PPC2_VSX207),
10793GEN_XX2FORM(xsrsp, 0x12, 0x11, PPC2_VSX207),
10794GEN_XX2FORM(xssqrtsp,  0x16, 0x00, PPC2_VSX207),
10795GEN_XX2FORM(xsrsqrtesp,  0x14, 0x00, PPC2_VSX207),
10796GEN_XX3FORM(xsmaddasp, 0x04, 0x00, PPC2_VSX207),
10797GEN_XX3FORM(xsmaddmsp, 0x04, 0x01, PPC2_VSX207),
10798GEN_XX3FORM(xsmsubasp, 0x04, 0x02, PPC2_VSX207),
10799GEN_XX3FORM(xsmsubmsp, 0x04, 0x03, PPC2_VSX207),
10800GEN_XX3FORM(xsnmaddasp, 0x04, 0x10, PPC2_VSX207),
10801GEN_XX3FORM(xsnmaddmsp, 0x04, 0x11, PPC2_VSX207),
10802GEN_XX3FORM(xsnmsubasp, 0x04, 0x12, PPC2_VSX207),
10803GEN_XX3FORM(xsnmsubmsp, 0x04, 0x13, PPC2_VSX207),
10804GEN_XX2FORM(xscvsxdsp, 0x10, 0x13, PPC2_VSX207),
10805GEN_XX2FORM(xscvuxdsp, 0x10, 0x12, PPC2_VSX207),
10806
10807GEN_XX3FORM(xvadddp, 0x00, 0x0C, PPC2_VSX),
10808GEN_XX3FORM(xvsubdp, 0x00, 0x0D, PPC2_VSX),
10809GEN_XX3FORM(xvmuldp, 0x00, 0x0E, PPC2_VSX),
10810GEN_XX3FORM(xvdivdp, 0x00, 0x0F, PPC2_VSX),
10811GEN_XX2FORM(xvredp,  0x14, 0x0D, PPC2_VSX),
10812GEN_XX2FORM(xvsqrtdp,  0x16, 0x0C, PPC2_VSX),
10813GEN_XX2FORM(xvrsqrtedp,  0x14, 0x0C, PPC2_VSX),
10814GEN_XX3FORM(xvtdivdp, 0x14, 0x0F, PPC2_VSX),
10815GEN_XX2FORM(xvtsqrtdp, 0x14, 0x0E, PPC2_VSX),
10816GEN_XX3FORM(xvmaddadp, 0x04, 0x0C, PPC2_VSX),
10817GEN_XX3FORM(xvmaddmdp, 0x04, 0x0D, PPC2_VSX),
10818GEN_XX3FORM(xvmsubadp, 0x04, 0x0E, PPC2_VSX),
10819GEN_XX3FORM(xvmsubmdp, 0x04, 0x0F, PPC2_VSX),
10820GEN_XX3FORM(xvnmaddadp, 0x04, 0x1C, PPC2_VSX),
10821GEN_XX3FORM(xvnmaddmdp, 0x04, 0x1D, PPC2_VSX),
10822GEN_XX3FORM(xvnmsubadp, 0x04, 0x1E, PPC2_VSX),
10823GEN_XX3FORM(xvnmsubmdp, 0x04, 0x1F, PPC2_VSX),
10824GEN_XX3FORM(xvmaxdp, 0x00, 0x1C, PPC2_VSX),
10825GEN_XX3FORM(xvmindp, 0x00, 0x1D, PPC2_VSX),
10826GEN_XX3_RC_FORM(xvcmpeqdp, 0x0C, 0x0C, PPC2_VSX),
10827GEN_XX3_RC_FORM(xvcmpgtdp, 0x0C, 0x0D, PPC2_VSX),
10828GEN_XX3_RC_FORM(xvcmpgedp, 0x0C, 0x0E, PPC2_VSX),
10829GEN_XX2FORM(xvcvdpsp, 0x12, 0x18, PPC2_VSX),
10830GEN_XX2FORM(xvcvdpsxds, 0x10, 0x1D, PPC2_VSX),
10831GEN_XX2FORM(xvcvdpsxws, 0x10, 0x0D, PPC2_VSX),
10832GEN_XX2FORM(xvcvdpuxds, 0x10, 0x1C, PPC2_VSX),
10833GEN_XX2FORM(xvcvdpuxws, 0x10, 0x0C, PPC2_VSX),
10834GEN_XX2FORM(xvcvsxddp, 0x10, 0x1F, PPC2_VSX),
10835GEN_XX2FORM(xvcvuxddp, 0x10, 0x1E, PPC2_VSX),
10836GEN_XX2FORM(xvcvsxwdp, 0x10, 0x0F, PPC2_VSX),
10837GEN_XX2FORM(xvcvuxwdp, 0x10, 0x0E, PPC2_VSX),
10838GEN_XX2FORM(xvrdpi, 0x12, 0x0C, PPC2_VSX),
10839GEN_XX2FORM(xvrdpic, 0x16, 0x0E, PPC2_VSX),
10840GEN_XX2FORM(xvrdpim, 0x12, 0x0F, PPC2_VSX),
10841GEN_XX2FORM(xvrdpip, 0x12, 0x0E, PPC2_VSX),
10842GEN_XX2FORM(xvrdpiz, 0x12, 0x0D, PPC2_VSX),
10843
10844GEN_XX3FORM(xvaddsp, 0x00, 0x08, PPC2_VSX),
10845GEN_XX3FORM(xvsubsp, 0x00, 0x09, PPC2_VSX),
10846GEN_XX3FORM(xvmulsp, 0x00, 0x0A, PPC2_VSX),
10847GEN_XX3FORM(xvdivsp, 0x00, 0x0B, PPC2_VSX),
10848GEN_XX2FORM(xvresp, 0x14, 0x09, PPC2_VSX),
10849GEN_XX2FORM(xvsqrtsp, 0x16, 0x08, PPC2_VSX),
10850GEN_XX2FORM(xvrsqrtesp, 0x14, 0x08, PPC2_VSX),
10851GEN_XX3FORM(xvtdivsp, 0x14, 0x0B, PPC2_VSX),
10852GEN_XX2FORM(xvtsqrtsp, 0x14, 0x0A, PPC2_VSX),
10853GEN_XX3FORM(xvmaddasp, 0x04, 0x08, PPC2_VSX),
10854GEN_XX3FORM(xvmaddmsp, 0x04, 0x09, PPC2_VSX),
10855GEN_XX3FORM(xvmsubasp, 0x04, 0x0A, PPC2_VSX),
10856GEN_XX3FORM(xvmsubmsp, 0x04, 0x0B, PPC2_VSX),
10857GEN_XX3FORM(xvnmaddasp, 0x04, 0x18, PPC2_VSX),
10858GEN_XX3FORM(xvnmaddmsp, 0x04, 0x19, PPC2_VSX),
10859GEN_XX3FORM(xvnmsubasp, 0x04, 0x1A, PPC2_VSX),
10860GEN_XX3FORM(xvnmsubmsp, 0x04, 0x1B, PPC2_VSX),
10861GEN_XX3FORM(xvmaxsp, 0x00, 0x18, PPC2_VSX),
10862GEN_XX3FORM(xvminsp, 0x00, 0x19, PPC2_VSX),
10863GEN_XX3_RC_FORM(xvcmpeqsp, 0x0C, 0x08, PPC2_VSX),
10864GEN_XX3_RC_FORM(xvcmpgtsp, 0x0C, 0x09, PPC2_VSX),
10865GEN_XX3_RC_FORM(xvcmpgesp, 0x0C, 0x0A, PPC2_VSX),
10866GEN_XX2FORM(xvcvspdp, 0x12, 0x1C, PPC2_VSX),
10867GEN_XX2FORM(xvcvspsxds, 0x10, 0x19, PPC2_VSX),
10868GEN_XX2FORM(xvcvspsxws, 0x10, 0x09, PPC2_VSX),
10869GEN_XX2FORM(xvcvspuxds, 0x10, 0x18, PPC2_VSX),
10870GEN_XX2FORM(xvcvspuxws, 0x10, 0x08, PPC2_VSX),
10871GEN_XX2FORM(xvcvsxdsp, 0x10, 0x1B, PPC2_VSX),
10872GEN_XX2FORM(xvcvuxdsp, 0x10, 0x1A, PPC2_VSX),
10873GEN_XX2FORM(xvcvsxwsp, 0x10, 0x0B, PPC2_VSX),
10874GEN_XX2FORM(xvcvuxwsp, 0x10, 0x0A, PPC2_VSX),
10875GEN_XX2FORM(xvrspi, 0x12, 0x08, PPC2_VSX),
10876GEN_XX2FORM(xvrspic, 0x16, 0x0A, PPC2_VSX),
10877GEN_XX2FORM(xvrspim, 0x12, 0x0B, PPC2_VSX),
10878GEN_XX2FORM(xvrspip, 0x12, 0x0A, PPC2_VSX),
10879GEN_XX2FORM(xvrspiz, 0x12, 0x09, PPC2_VSX),
10880
10881#undef VSX_LOGICAL
10882#define VSX_LOGICAL(name, opc2, opc3, fl2) \
10883GEN_XX3FORM(name, opc2, opc3, fl2)
10884
10885VSX_LOGICAL(xxland, 0x8, 0x10, PPC2_VSX),
10886VSX_LOGICAL(xxlandc, 0x8, 0x11, PPC2_VSX),
10887VSX_LOGICAL(xxlor, 0x8, 0x12, PPC2_VSX),
10888VSX_LOGICAL(xxlxor, 0x8, 0x13, PPC2_VSX),
10889VSX_LOGICAL(xxlnor, 0x8, 0x14, PPC2_VSX),
10890VSX_LOGICAL(xxleqv, 0x8, 0x17, PPC2_VSX207),
10891VSX_LOGICAL(xxlnand, 0x8, 0x16, PPC2_VSX207),
10892VSX_LOGICAL(xxlorc, 0x8, 0x15, PPC2_VSX207),
10893GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
10894GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
10895GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
10896GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
10897
10898#define GEN_XXSEL_ROW(opc3) \
10899GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x18, opc3, 0, PPC_NONE, PPC2_VSX), \
10900GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x19, opc3, 0, PPC_NONE, PPC2_VSX), \
10901GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1A, opc3, 0, PPC_NONE, PPC2_VSX), \
10902GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1B, opc3, 0, PPC_NONE, PPC2_VSX), \
10903GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1C, opc3, 0, PPC_NONE, PPC2_VSX), \
10904GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1D, opc3, 0, PPC_NONE, PPC2_VSX), \
10905GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1E, opc3, 0, PPC_NONE, PPC2_VSX), \
10906GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1F, opc3, 0, PPC_NONE, PPC2_VSX), \
10907
10908GEN_XXSEL_ROW(0x00)
10909GEN_XXSEL_ROW(0x01)
10910GEN_XXSEL_ROW(0x02)
10911GEN_XXSEL_ROW(0x03)
10912GEN_XXSEL_ROW(0x04)
10913GEN_XXSEL_ROW(0x05)
10914GEN_XXSEL_ROW(0x06)
10915GEN_XXSEL_ROW(0x07)
10916GEN_XXSEL_ROW(0x08)
10917GEN_XXSEL_ROW(0x09)
10918GEN_XXSEL_ROW(0x0A)
10919GEN_XXSEL_ROW(0x0B)
10920GEN_XXSEL_ROW(0x0C)
10921GEN_XXSEL_ROW(0x0D)
10922GEN_XXSEL_ROW(0x0E)
10923GEN_XXSEL_ROW(0x0F)
10924GEN_XXSEL_ROW(0x10)
10925GEN_XXSEL_ROW(0x11)
10926GEN_XXSEL_ROW(0x12)
10927GEN_XXSEL_ROW(0x13)
10928GEN_XXSEL_ROW(0x14)
10929GEN_XXSEL_ROW(0x15)
10930GEN_XXSEL_ROW(0x16)
10931GEN_XXSEL_ROW(0x17)
10932GEN_XXSEL_ROW(0x18)
10933GEN_XXSEL_ROW(0x19)
10934GEN_XXSEL_ROW(0x1A)
10935GEN_XXSEL_ROW(0x1B)
10936GEN_XXSEL_ROW(0x1C)
10937GEN_XXSEL_ROW(0x1D)
10938GEN_XXSEL_ROW(0x1E)
10939GEN_XXSEL_ROW(0x1F)
10940
10941GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
10942
10943#undef GEN_DFP_T_A_B_Rc
10944#undef GEN_DFP_BF_A_B
10945#undef GEN_DFP_BF_A_DCM
10946#undef GEN_DFP_T_B_U32_U32_Rc
10947#undef GEN_DFP_T_A_B_I32_Rc
10948#undef GEN_DFP_T_B_Rc
10949#undef GEN_DFP_T_FPR_I32_Rc
10950
10951#define _GEN_DFP_LONG(name, op1, op2, mask) \
10952GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP)
10953
10954#define _GEN_DFP_LONGx2(name, op1, op2, mask) \
10955GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10956GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
10957
10958#define _GEN_DFP_LONGx4(name, op1, op2, mask) \
10959GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10960GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
10961GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
10962GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
10963
10964#define _GEN_DFP_QUAD(name, op1, op2, mask) \
10965GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP)
10966
10967#define _GEN_DFP_QUADx2(name, op1, op2, mask) \
10968GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10969GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
10970
10971#define _GEN_DFP_QUADx4(name, op1, op2, mask)                         \
10972GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10973GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
10974GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
10975GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
10976
10977#define GEN_DFP_T_A_B_Rc(name, op1, op2) \
10978_GEN_DFP_LONG(name, op1, op2, 0x00000000)
10979
10980#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \
10981_GEN_DFP_QUAD(name, op1, op2, 0x00210800)
10982
10983#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \
10984_GEN_DFP_QUAD(name, op1, op2, 0x00200800)
10985
10986#define GEN_DFP_T_B_Rc(name, op1, op2) \
10987_GEN_DFP_LONG(name, op1, op2, 0x001F0000)
10988
10989#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \
10990_GEN_DFP_QUAD(name, op1, op2, 0x003F0800)
10991
10992#define GEN_DFP_Tp_B_Rc(name, op1, op2) \
10993_GEN_DFP_QUAD(name, op1, op2, 0x003F0000)
10994
10995#define GEN_DFP_T_Bp_Rc(name, op1, op2) \
10996_GEN_DFP_QUAD(name, op1, op2, 0x001F0800)
10997
10998#define GEN_DFP_BF_A_B(name, op1, op2) \
10999_GEN_DFP_LONG(name, op1, op2, 0x00000001)
11000
11001#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \
11002_GEN_DFP_QUAD(name, op1, op2, 0x00610801)
11003
11004#define GEN_DFP_BF_A_Bp(name, op1, op2) \
11005_GEN_DFP_QUAD(name, op1, op2, 0x00600801)
11006
11007#define GEN_DFP_BF_A_DCM(name, op1, op2) \
11008_GEN_DFP_LONGx2(name, op1, op2, 0x00600001)
11009
11010#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \
11011_GEN_DFP_QUADx2(name, op1, op2, 0x00610001)
11012
11013#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \
11014_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11015
11016#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \
11017_GEN_DFP_QUADx4(name, op1, op2, 0x02010800)
11018
11019#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \
11020_GEN_DFP_QUADx4(name, op1, op2, 0x02000800)
11021
11022#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \
11023_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11024
11025#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \
11026_GEN_DFP_QUADx4(name, op1, op2, 0x00200800)
11027
11028#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \
11029_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000)
11030
11031#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \
11032_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800)
11033
11034#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \
11035_GEN_DFP_LONG(name, op1, op2, 0x00070000)
11036
11037#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \
11038_GEN_DFP_QUAD(name, op1, op2, 0x00270800)
11039
11040#define GEN_DFP_S_T_B_Rc(name, op1, op2) \
11041_GEN_DFP_LONG(name, op1, op2, 0x000F0000)
11042
11043#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \
11044_GEN_DFP_QUAD(name, op1, op2, 0x002F0800)
11045
11046#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \
11047_GEN_DFP_LONGx2(name, op1, op2, 0x00000000)
11048
11049#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \
11050_GEN_DFP_QUADx2(name, op1, op2, 0x00210000)
11051
11052GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00),
11053GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00),
11054GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10),
11055GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10),
11056GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01),
11057GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01),
11058GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11),
11059GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11),
11060GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14),
11061GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14),
11062GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04),
11063GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04),
11064GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06),
11065GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06),
11066GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07),
11067GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07),
11068GEN_DFP_BF_A_B(dtstex, 0x02, 0x05),
11069GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05),
11070GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15),
11071GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15),
11072GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02),
11073GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02),
11074GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00),
11075GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00),
11076GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01),
11077GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01),
11078GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03),
11079GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03),
11080GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07),
11081GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07),
11082GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08),
11083GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08),
11084GEN_DFP_T_B_Rc(drsp, 0x02, 0x18),
11085GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18),
11086GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19),
11087GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19),
11088GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
11089GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
11090GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
11091GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
11092GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
11093GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
11094GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
11095GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
11096GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
11097GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
11098GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
11099GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
11100GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
11101GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
11102
11103#undef GEN_SPE
11104#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
11105    GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
11106GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11107GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11108GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11109GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11110GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11111GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11112GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11113GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
11114GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
11115GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11116GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11117GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11118GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11119GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11120GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11121GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
11122GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11123GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11124GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11125GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11126GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11127GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11128GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11129GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11130GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11131GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11132GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11133GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11134GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
11135
11136GEN_SPE(evfsadd,     evfssub,     0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11137GEN_SPE(evfsabs,     evfsnabs,    0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11138GEN_SPE(evfsneg,     speundef,    0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11139GEN_SPE(evfsmul,     evfsdiv,     0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11140GEN_SPE(evfscmpgt,   evfscmplt,   0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11141GEN_SPE(evfscmpeq,   speundef,    0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11142GEN_SPE(evfscfui,    evfscfsi,    0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11143GEN_SPE(evfscfuf,    evfscfsf,    0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11144GEN_SPE(evfsctui,    evfsctsi,    0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11145GEN_SPE(evfsctuf,    evfsctsf,    0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11146GEN_SPE(evfsctuiz,   speundef,    0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11147GEN_SPE(evfsctsiz,   speundef,    0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11148GEN_SPE(evfststgt,   evfststlt,   0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11149GEN_SPE(evfststeq,   speundef,    0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11150
11151GEN_SPE(efsadd,      efssub,      0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11152GEN_SPE(efsabs,      efsnabs,     0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11153GEN_SPE(efsneg,      speundef,    0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11154GEN_SPE(efsmul,      efsdiv,      0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11155GEN_SPE(efscmpgt,    efscmplt,    0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11156GEN_SPE(efscmpeq,    efscfd,      0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
11157GEN_SPE(efscfui,     efscfsi,     0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11158GEN_SPE(efscfuf,     efscfsf,     0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11159GEN_SPE(efsctui,     efsctsi,     0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11160GEN_SPE(efsctuf,     efsctsf,     0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11161GEN_SPE(efsctuiz,    speundef,    0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11162GEN_SPE(efsctsiz,    speundef,    0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11163GEN_SPE(efststgt,    efststlt,    0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11164GEN_SPE(efststeq,    speundef,    0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11165
11166GEN_SPE(efdadd,      efdsub,      0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11167GEN_SPE(efdcfuid,    efdcfsid,    0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11168GEN_SPE(efdabs,      efdnabs,     0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
11169GEN_SPE(efdneg,      speundef,    0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11170GEN_SPE(efdmul,      efddiv,      0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11171GEN_SPE(efdctuidz,   efdctsidz,   0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11172GEN_SPE(efdcmpgt,    efdcmplt,    0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11173GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
11174GEN_SPE(efdcfui,     efdcfsi,     0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11175GEN_SPE(efdcfuf,     efdcfsf,     0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11176GEN_SPE(efdctui,     efdctsi,     0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11177GEN_SPE(efdctuf,     efdctsf,     0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11178GEN_SPE(efdctuiz,    speundef,    0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11179GEN_SPE(efdctsiz,    speundef,    0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11180GEN_SPE(efdtstgt,    efdtstlt,    0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11181GEN_SPE(efdtsteq,    speundef,    0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11182
11183#undef GEN_SPEOP_LDST
11184#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
11185GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
11186GEN_SPEOP_LDST(evldd, 0x00, 3),
11187GEN_SPEOP_LDST(evldw, 0x01, 3),
11188GEN_SPEOP_LDST(evldh, 0x02, 3),
11189GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
11190GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
11191GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
11192GEN_SPEOP_LDST(evlwhe, 0x08, 2),
11193GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
11194GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
11195GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
11196GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
11197
11198GEN_SPEOP_LDST(evstdd, 0x10, 3),
11199GEN_SPEOP_LDST(evstdw, 0x11, 3),
11200GEN_SPEOP_LDST(evstdh, 0x12, 3),
11201GEN_SPEOP_LDST(evstwhe, 0x18, 2),
11202GEN_SPEOP_LDST(evstwho, 0x1A, 2),
11203GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
11204GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
11205
11206GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
11207               PPC_NONE, PPC2_TM),
11208GEN_HANDLER2_E(tend,   "tend",   0x1F, 0x0E, 0x15, 0x01FFF800, \
11209               PPC_NONE, PPC2_TM),
11210GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
11211               PPC_NONE, PPC2_TM),
11212GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
11213               PPC_NONE, PPC2_TM),
11214GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
11215               PPC_NONE, PPC2_TM),
11216GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
11217               PPC_NONE, PPC2_TM),
11218GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
11219               PPC_NONE, PPC2_TM),
11220GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
11221               PPC_NONE, PPC2_TM),
11222GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
11223               PPC_NONE, PPC2_TM),
11224GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
11225               PPC_NONE, PPC2_TM),
11226GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
11227               PPC_NONE, PPC2_TM),
11228};
11229
11230#include "helper_regs.h"
11231#include "translate_init.c"
11232
11233/*****************************************************************************/
11234/* Misc PowerPC helpers */
11235void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11236                        int flags)
11237{
11238#define RGPL  4
11239#define RFPL  4
11240
11241    PowerPCCPU *cpu = POWERPC_CPU(cs);
11242    CPUPPCState *env = &cpu->env;
11243    int i;
11244
11245    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
11246                TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n",
11247                env->nip, env->lr, env->ctr, cpu_read_xer(env),
11248                cs->cpu_index);
11249    cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx "  HF "
11250                TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
11251                env->hflags, env->mmu_idx);
11252#if !defined(NO_TIMER_DUMP)
11253    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
11254#if !defined(CONFIG_USER_ONLY)
11255                " DECR %08" PRIu32
11256#endif
11257                "\n",
11258                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
11259#if !defined(CONFIG_USER_ONLY)
11260                , cpu_ppc_load_decr(env)
11261#endif
11262                );
11263#endif
11264    for (i = 0; i < 32; i++) {
11265        if ((i & (RGPL - 1)) == 0)
11266            cpu_fprintf(f, "GPR%02d", i);
11267        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
11268        if ((i & (RGPL - 1)) == (RGPL - 1))
11269            cpu_fprintf(f, "\n");
11270    }
11271    cpu_fprintf(f, "CR ");
11272    for (i = 0; i < 8; i++)
11273        cpu_fprintf(f, "%01x", env->crf[i]);
11274    cpu_fprintf(f, "  [");
11275    for (i = 0; i < 8; i++) {
11276        char a = '-';
11277        if (env->crf[i] & 0x08)
11278            a = 'L';
11279        else if (env->crf[i] & 0x04)
11280            a = 'G';
11281        else if (env->crf[i] & 0x02)
11282            a = 'E';
11283        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
11284    }
11285    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
11286                env->reserve_addr);
11287    for (i = 0; i < 32; i++) {
11288        if ((i & (RFPL - 1)) == 0)
11289            cpu_fprintf(f, "FPR%02d", i);
11290        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
11291        if ((i & (RFPL - 1)) == (RFPL - 1))
11292            cpu_fprintf(f, "\n");
11293    }
11294    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
11295#if !defined(CONFIG_USER_ONLY)
11296    cpu_fprintf(f, " SRR0 " TARGET_FMT_lx "  SRR1 " TARGET_FMT_lx
11297                   "    PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
11298                env->spr[SPR_SRR0], env->spr[SPR_SRR1],
11299                env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
11300
11301    cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
11302                   "  SPRG2 " TARGET_FMT_lx "  SPRG3 " TARGET_FMT_lx "\n",
11303                env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
11304                env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
11305
11306    cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
11307                   "  SPRG6 " TARGET_FMT_lx "  SPRG7 " TARGET_FMT_lx "\n",
11308                env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
11309                env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
11310
11311    if (env->excp_model == POWERPC_EXCP_BOOKE) {
11312        cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
11313                       " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
11314                    env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
11315                    env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
11316
11317        cpu_fprintf(f, "  TCR " TARGET_FMT_lx "   TSR " TARGET_FMT_lx
11318                       "    ESR " TARGET_FMT_lx "   DEAR " TARGET_FMT_lx "\n",
11319                    env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
11320                    env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
11321
11322        cpu_fprintf(f, "  PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
11323                       "   IVPR " TARGET_FMT_lx "   EPCR " TARGET_FMT_lx "\n",
11324                    env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
11325                    env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
11326
11327        cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
11328                       "    EPR " TARGET_FMT_lx "\n",
11329                    env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
11330                    env->spr[SPR_BOOKE_EPR]);
11331
11332        /* FSL-specific */
11333        cpu_fprintf(f, " MCAR " TARGET_FMT_lx "  PID1 " TARGET_FMT_lx
11334                       "   PID2 " TARGET_FMT_lx "    SVR " TARGET_FMT_lx "\n",
11335                    env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
11336                    env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
11337
11338        /*
11339         * IVORs are left out as they are large and do not change often --
11340         * they can be read with "p $ivor0", "p $ivor1", etc.
11341         */
11342    }
11343
11344#if defined(TARGET_PPC64)
11345    if (env->flags & POWERPC_FLAG_CFAR) {
11346        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
11347    }
11348#endif
11349
11350    switch (env->mmu_model) {
11351    case POWERPC_MMU_32B:
11352    case POWERPC_MMU_601:
11353    case POWERPC_MMU_SOFT_6xx:
11354    case POWERPC_MMU_SOFT_74xx:
11355#if defined(TARGET_PPC64)
11356    case POWERPC_MMU_64B:
11357    case POWERPC_MMU_2_03:
11358    case POWERPC_MMU_2_06:
11359    case POWERPC_MMU_2_06a:
11360    case POWERPC_MMU_2_07:
11361    case POWERPC_MMU_2_07a:
11362#endif
11363        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "   DAR " TARGET_FMT_lx
11364                       "  DSISR " TARGET_FMT_lx "\n", env->spr[SPR_SDR1],
11365                    env->spr[SPR_DAR], env->spr[SPR_DSISR]);
11366        break;
11367    case POWERPC_MMU_BOOKE206:
11368        cpu_fprintf(f, " MAS0 " TARGET_FMT_lx "  MAS1 " TARGET_FMT_lx
11369                       "   MAS2 " TARGET_FMT_lx "   MAS3 " TARGET_FMT_lx "\n",
11370                    env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
11371                    env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
11372
11373        cpu_fprintf(f, " MAS4 " TARGET_FMT_lx "  MAS6 " TARGET_FMT_lx
11374                       "   MAS7 " TARGET_FMT_lx "    PID " TARGET_FMT_lx "\n",
11375                    env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
11376                    env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
11377
11378        cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
11379                       " TLB1CFG " TARGET_FMT_lx "\n",
11380                    env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
11381                    env->spr[SPR_BOOKE_TLB1CFG]);
11382        break;
11383    default:
11384        break;
11385    }
11386#endif
11387
11388#undef RGPL
11389#undef RFPL
11390}
11391
11392void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
11393                             fprintf_function cpu_fprintf, int flags)
11394{
11395#if defined(DO_PPC_STATISTICS)
11396    PowerPCCPU *cpu = POWERPC_CPU(cs);
11397    opc_handler_t **t1, **t2, **t3, *handler;
11398    int op1, op2, op3;
11399
11400    t1 = cpu->env.opcodes;
11401    for (op1 = 0; op1 < 64; op1++) {
11402        handler = t1[op1];
11403        if (is_indirect_opcode(handler)) {
11404            t2 = ind_table(handler);
11405            for (op2 = 0; op2 < 32; op2++) {
11406                handler = t2[op2];
11407                if (is_indirect_opcode(handler)) {
11408                    t3 = ind_table(handler);
11409                    for (op3 = 0; op3 < 32; op3++) {
11410                        handler = t3[op3];
11411                        if (handler->count == 0)
11412                            continue;
11413                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
11414                                    "%016" PRIx64 " %" PRId64 "\n",
11415                                    op1, op2, op3, op1, (op3 << 5) | op2,
11416                                    handler->oname,
11417                                    handler->count, handler->count);
11418                    }
11419                } else {
11420                    if (handler->count == 0)
11421                        continue;
11422                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
11423                                "%016" PRIx64 " %" PRId64 "\n",
11424                                op1, op2, op1, op2, handler->oname,
11425                                handler->count, handler->count);
11426                }
11427            }
11428        } else {
11429            if (handler->count == 0)
11430                continue;
11431            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
11432                        " %" PRId64 "\n",
11433                        op1, op1, handler->oname,
11434                        handler->count, handler->count);
11435        }
11436    }
11437#endif
11438}
11439
11440/*****************************************************************************/
11441void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
11442{
11443    PowerPCCPU *cpu = ppc_env_get_cpu(env);
11444    CPUState *cs = CPU(cpu);
11445    DisasContext ctx, *ctxp = &ctx;
11446    opc_handler_t **table, *handler;
11447    target_ulong pc_start;
11448    int num_insns;
11449    int max_insns;
11450
11451    pc_start = tb->pc;
11452    ctx.nip = pc_start;
11453    ctx.tb = tb;
11454    ctx.exception = POWERPC_EXCP_NONE;
11455    ctx.spr_cb = env->spr_cb;
11456    ctx.pr = msr_pr;
11457    ctx.hv = !msr_pr && msr_hv;
11458    ctx.mem_idx = env->mmu_idx;
11459    ctx.insns_flags = env->insns_flags;
11460    ctx.insns_flags2 = env->insns_flags2;
11461    ctx.access_type = -1;
11462    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
11463    ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE;
11464#if defined(TARGET_PPC64)
11465    ctx.sf_mode = msr_is_64bit(env, env->msr);
11466    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
11467#endif
11468    ctx.fpu_enabled = msr_fp;
11469    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
11470        ctx.spe_enabled = msr_spe;
11471    else
11472        ctx.spe_enabled = 0;
11473    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
11474        ctx.altivec_enabled = msr_vr;
11475    else
11476        ctx.altivec_enabled = 0;
11477    if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
11478        ctx.vsx_enabled = msr_vsx;
11479    } else {
11480        ctx.vsx_enabled = 0;
11481    }
11482#if defined(TARGET_PPC64)
11483    if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
11484        ctx.tm_enabled = msr_tm;
11485    } else {
11486        ctx.tm_enabled = 0;
11487    }
11488#endif
11489    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
11490        ctx.singlestep_enabled = CPU_SINGLE_STEP;
11491    else
11492        ctx.singlestep_enabled = 0;
11493    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
11494        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
11495    if (unlikely(cs->singlestep_enabled)) {
11496        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
11497    }
11498#if defined (DO_SINGLE_STEP) && 0
11499    /* Single step trace mode */
11500    msr_se = 1;
11501#endif
11502    num_insns = 0;
11503    max_insns = tb->cflags & CF_COUNT_MASK;
11504    if (max_insns == 0) {
11505        max_insns = CF_COUNT_MASK;
11506    }
11507    if (max_insns > TCG_MAX_INSNS) {
11508        max_insns = TCG_MAX_INSNS;
11509    }
11510
11511    gen_tb_start(tb);
11512    tcg_clear_temp_count();
11513    /* Set env in case of segfault during code fetch */
11514    while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
11515        tcg_gen_insn_start(ctx.nip);
11516        num_insns++;
11517
11518        if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
11519            gen_debug_exception(ctxp);
11520            /* The address covered by the breakpoint must be included in
11521               [tb->pc, tb->pc + tb->size) in order to for it to be
11522               properly cleared -- thus we increment the PC here so that
11523               the logic setting tb->size below does the right thing.  */
11524            ctx.nip += 4;
11525            break;
11526        }
11527
11528        LOG_DISAS("----------------\n");
11529        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
11530                  ctx.nip, ctx.mem_idx, (int)msr_ir);
11531        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
11532            gen_io_start();
11533        if (unlikely(need_byteswap(&ctx))) {
11534            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
11535        } else {
11536            ctx.opcode = cpu_ldl_code(env, ctx.nip);
11537        }
11538        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
11539                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
11540                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
11541        ctx.nip += 4;
11542        table = env->opcodes;
11543        handler = table[opc1(ctx.opcode)];
11544        if (is_indirect_opcode(handler)) {
11545            table = ind_table(handler);
11546            handler = table[opc2(ctx.opcode)];
11547            if (is_indirect_opcode(handler)) {
11548                table = ind_table(handler);
11549                handler = table[opc3(ctx.opcode)];
11550            }
11551        }
11552        /* Is opcode *REALLY* valid ? */
11553        if (unlikely(handler->handler == &gen_invalid)) {
11554            qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
11555                          "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
11556                          opc1(ctx.opcode), opc2(ctx.opcode),
11557                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
11558        } else {
11559            uint32_t inval;
11560
11561            if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
11562                inval = handler->inval2;
11563            } else {
11564                inval = handler->inval1;
11565            }
11566
11567            if (unlikely((ctx.opcode & inval) != 0)) {
11568                qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
11569                              "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
11570                              ctx.opcode & inval, opc1(ctx.opcode),
11571                              opc2(ctx.opcode), opc3(ctx.opcode),
11572                              ctx.opcode, ctx.nip - 4);
11573                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
11574                break;
11575            }
11576        }
11577        (*(handler->handler))(&ctx);
11578#if defined(DO_PPC_STATISTICS)
11579        handler->count++;
11580#endif
11581        /* Check trace mode exceptions */
11582        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
11583                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
11584                     ctx.exception != POWERPC_SYSCALL &&
11585                     ctx.exception != POWERPC_EXCP_TRAP &&
11586                     ctx.exception != POWERPC_EXCP_BRANCH)) {
11587            gen_exception(ctxp, POWERPC_EXCP_TRACE);
11588        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
11589                            (cs->singlestep_enabled) ||
11590                            singlestep ||
11591                            num_insns >= max_insns)) {
11592            /* if we reach a page boundary or are single stepping, stop
11593             * generation
11594             */
11595            break;
11596        }
11597        if (tcg_check_temp_count()) {
11598            fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked temporaries\n",
11599                    opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
11600                    ctx.opcode);
11601            exit(1);
11602        }
11603    }
11604    if (tb->cflags & CF_LAST_IO)
11605        gen_io_end();
11606    if (ctx.exception == POWERPC_EXCP_NONE) {
11607        gen_goto_tb(&ctx, 0, ctx.nip);
11608    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
11609        if (unlikely(cs->singlestep_enabled)) {
11610            gen_debug_exception(ctxp);
11611        }
11612        /* Generate the return instruction */
11613        tcg_gen_exit_tb(0);
11614    }
11615    gen_tb_end(tb, num_insns);
11616
11617    tb->size = ctx.nip - pc_start;
11618    tb->icount = num_insns;
11619
11620#if defined(DEBUG_DISAS)
11621    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
11622        int flags;
11623        flags = env->bfd_mach;
11624        flags |= ctx.le_mode << 16;
11625        qemu_log("IN: %s\n", lookup_symbol(pc_start));
11626        log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
11627        qemu_log("\n");
11628    }
11629#endif
11630}
11631
11632void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
11633                          target_ulong *data)
11634{
11635    env->nip = data[0];
11636}
11637