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 "exec/exec-all.h"
  25#include "tcg-op.h"
  26#include "qemu/host-utils.h"
  27#include "exec/cpu_ldst.h"
  28
  29#include "exec/helper-proto.h"
  30#include "exec/helper-gen.h"
  31
  32#include "trace-tcg.h"
  33#include "exec/log.h"
  34
  35
  36#define CPU_SINGLE_STEP 0x1
  37#define CPU_BRANCH_STEP 0x2
  38#define GDBSTUB_SINGLE_STEP 0x4
  39
  40/* Include definitions for instructions classes and implementations flags */
  41//#define PPC_DEBUG_DISAS
  42//#define DO_PPC_STATISTICS
  43
  44#ifdef PPC_DEBUG_DISAS
  45#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
  46#else
  47#  define LOG_DISAS(...) do { } while (0)
  48#endif
  49/*****************************************************************************/
  50/* Code translation helpers                                                  */
  51
  52/* global register indexes */
  53static TCGv_env cpu_env;
  54static char cpu_reg_names[10*3 + 22*4 /* GPR */
  55    + 10*4 + 22*5 /* SPE GPRh */
  56    + 10*4 + 22*5 /* FPR */
  57    + 2*(10*6 + 22*7) /* AVRh, AVRl */
  58    + 10*5 + 22*6 /* VSR */
  59    + 8*5 /* CRF */];
  60static TCGv cpu_gpr[32];
  61static TCGv cpu_gprh[32];
  62static TCGv_i64 cpu_fpr[32];
  63static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
  64static TCGv_i64 cpu_vsr[32];
  65static TCGv_i32 cpu_crf[8];
  66static TCGv cpu_nip;
  67static TCGv cpu_msr;
  68static TCGv cpu_ctr;
  69static TCGv cpu_lr;
  70#if defined(TARGET_PPC64)
  71static TCGv cpu_cfar;
  72#endif
  73static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
  74static TCGv cpu_reserve;
  75static TCGv cpu_fpscr;
  76static TCGv_i32 cpu_access_type;
  77
  78#include "exec/gen-icount.h"
  79
  80void ppc_translate_init(void)
  81{
  82    int i;
  83    char* p;
  84    size_t cpu_reg_names_size;
  85    static int done_init = 0;
  86
  87    if (done_init)
  88        return;
  89
  90    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
  91    tcg_ctx.tcg_env = cpu_env;
  92
  93    p = cpu_reg_names;
  94    cpu_reg_names_size = sizeof(cpu_reg_names);
  95
  96    for (i = 0; i < 8; i++) {
  97        snprintf(p, cpu_reg_names_size, "crf%d", i);
  98        cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
  99                                            offsetof(CPUPPCState, crf[i]), p);
 100        p += 5;
 101        cpu_reg_names_size -= 5;
 102    }
 103
 104    for (i = 0; i < 32; i++) {
 105        snprintf(p, cpu_reg_names_size, "r%d", i);
 106        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
 107                                        offsetof(CPUPPCState, gpr[i]), p);
 108        p += (i < 10) ? 3 : 4;
 109        cpu_reg_names_size -= (i < 10) ? 3 : 4;
 110        snprintf(p, cpu_reg_names_size, "r%dH", i);
 111        cpu_gprh[i] = tcg_global_mem_new(cpu_env,
 112                                         offsetof(CPUPPCState, gprh[i]), p);
 113        p += (i < 10) ? 4 : 5;
 114        cpu_reg_names_size -= (i < 10) ? 4 : 5;
 115
 116        snprintf(p, cpu_reg_names_size, "fp%d", i);
 117        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
 118                                            offsetof(CPUPPCState, fpr[i]), p);
 119        p += (i < 10) ? 4 : 5;
 120        cpu_reg_names_size -= (i < 10) ? 4 : 5;
 121
 122        snprintf(p, cpu_reg_names_size, "avr%dH", i);
 123#ifdef HOST_WORDS_BIGENDIAN
 124        cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
 125                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 126#else
 127        cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
 128                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 129#endif
 130        p += (i < 10) ? 6 : 7;
 131        cpu_reg_names_size -= (i < 10) ? 6 : 7;
 132
 133        snprintf(p, cpu_reg_names_size, "avr%dL", i);
 134#ifdef HOST_WORDS_BIGENDIAN
 135        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
 136                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
 137#else
 138        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
 139                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
 140#endif
 141        p += (i < 10) ? 6 : 7;
 142        cpu_reg_names_size -= (i < 10) ? 6 : 7;
 143        snprintf(p, cpu_reg_names_size, "vsr%d", i);
 144        cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env,
 145                                            offsetof(CPUPPCState, vsr[i]), p);
 146        p += (i < 10) ? 5 : 6;
 147        cpu_reg_names_size -= (i < 10) ? 5 : 6;
 148    }
 149
 150    cpu_nip = tcg_global_mem_new(cpu_env,
 151                                 offsetof(CPUPPCState, nip), "nip");
 152
 153    cpu_msr = tcg_global_mem_new(cpu_env,
 154                                 offsetof(CPUPPCState, msr), "msr");
 155
 156    cpu_ctr = tcg_global_mem_new(cpu_env,
 157                                 offsetof(CPUPPCState, ctr), "ctr");
 158
 159    cpu_lr = tcg_global_mem_new(cpu_env,
 160                                offsetof(CPUPPCState, lr), "lr");
 161
 162#if defined(TARGET_PPC64)
 163    cpu_cfar = tcg_global_mem_new(cpu_env,
 164                                  offsetof(CPUPPCState, cfar), "cfar");
 165#endif
 166
 167    cpu_xer = tcg_global_mem_new(cpu_env,
 168                                 offsetof(CPUPPCState, xer), "xer");
 169    cpu_so = tcg_global_mem_new(cpu_env,
 170                                offsetof(CPUPPCState, so), "SO");
 171    cpu_ov = tcg_global_mem_new(cpu_env,
 172                                offsetof(CPUPPCState, ov), "OV");
 173    cpu_ca = tcg_global_mem_new(cpu_env,
 174                                offsetof(CPUPPCState, ca), "CA");
 175
 176    cpu_reserve = tcg_global_mem_new(cpu_env,
 177                                     offsetof(CPUPPCState, reserve_addr),
 178                                     "reserve_addr");
 179
 180    cpu_fpscr = tcg_global_mem_new(cpu_env,
 181                                   offsetof(CPUPPCState, fpscr), "fpscr");
 182
 183    cpu_access_type = tcg_global_mem_new_i32(cpu_env,
 184                                             offsetof(CPUPPCState, access_type), "access_type");
 185
 186    done_init = 1;
 187}
 188
 189/* internal defines */
 190struct DisasContext {
 191    struct TranslationBlock *tb;
 192    target_ulong nip;
 193    uint32_t opcode;
 194    uint32_t exception;
 195    /* Routine used to access memory */
 196    bool pr, hv, dr, le_mode;
 197    bool lazy_tlb_flush;
 198    int mem_idx;
 199    int access_type;
 200    /* Translation flags */
 201    TCGMemOp default_tcg_memop_mask;
 202#if defined(TARGET_PPC64)
 203    bool sf_mode;
 204    bool has_cfar;
 205#endif
 206    bool fpu_enabled;
 207    bool altivec_enabled;
 208    bool vsx_enabled;
 209    bool spe_enabled;
 210    bool tm_enabled;
 211    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
 212    int singlestep_enabled;
 213    uint64_t insns_flags;
 214    uint64_t insns_flags2;
 215};
 216
 217/* Return true iff byteswap is needed in a scalar memop */
 218static inline bool need_byteswap(const DisasContext *ctx)
 219{
 220#if defined(TARGET_WORDS_BIGENDIAN)
 221     return ctx->le_mode;
 222#else
 223     return !ctx->le_mode;
 224#endif
 225}
 226
 227/* True when active word size < size of target_long.  */
 228#ifdef TARGET_PPC64
 229# define NARROW_MODE(C)  (!(C)->sf_mode)
 230#else
 231# define NARROW_MODE(C)  0
 232#endif
 233
 234struct opc_handler_t {
 235    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
 236    uint32_t inval1;
 237    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
 238    uint32_t inval2;
 239    /* instruction type */
 240    uint64_t type;
 241    /* extended instruction type */
 242    uint64_t type2;
 243    /* handler */
 244    void (*handler)(DisasContext *ctx);
 245#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
 246    const char *oname;
 247#endif
 248#if defined(DO_PPC_STATISTICS)
 249    uint64_t count;
 250#endif
 251};
 252
 253static inline void gen_reset_fpstatus(void)
 254{
 255    gen_helper_reset_fpstatus(cpu_env);
 256}
 257
 258static inline void gen_compute_fprf(TCGv_i64 arg)
 259{
 260    gen_helper_compute_fprf(cpu_env, arg);
 261    gen_helper_float_check_status(cpu_env);
 262}
 263
 264static inline void gen_set_access_type(DisasContext *ctx, int access_type)
 265{
 266    if (ctx->access_type != access_type) {
 267        tcg_gen_movi_i32(cpu_access_type, access_type);
 268        ctx->access_type = access_type;
 269    }
 270}
 271
 272static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
 273{
 274    if (NARROW_MODE(ctx)) {
 275        nip = (uint32_t)nip;
 276    }
 277    tcg_gen_movi_tl(cpu_nip, nip);
 278}
 279
 280void gen_update_current_nip(void *opaque)
 281{
 282    DisasContext *ctx = opaque;
 283
 284    tcg_gen_movi_tl(cpu_nip, ctx->nip);
 285}
 286
 287static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
 288{
 289    TCGv_i32 t0, t1;
 290    if (ctx->exception == POWERPC_EXCP_NONE) {
 291        gen_update_nip(ctx, ctx->nip);
 292    }
 293    t0 = tcg_const_i32(excp);
 294    t1 = tcg_const_i32(error);
 295    gen_helper_raise_exception_err(cpu_env, t0, t1);
 296    tcg_temp_free_i32(t0);
 297    tcg_temp_free_i32(t1);
 298    ctx->exception = (excp);
 299}
 300
 301static void gen_exception(DisasContext *ctx, uint32_t excp)
 302{
 303    TCGv_i32 t0;
 304    if (ctx->exception == POWERPC_EXCP_NONE) {
 305        gen_update_nip(ctx, ctx->nip);
 306    }
 307    t0 = tcg_const_i32(excp);
 308    gen_helper_raise_exception(cpu_env, t0);
 309    tcg_temp_free_i32(t0);
 310    ctx->exception = (excp);
 311}
 312
 313static void gen_debug_exception(DisasContext *ctx)
 314{
 315    TCGv_i32 t0;
 316
 317    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
 318        (ctx->exception != POWERPC_EXCP_SYNC)) {
 319        gen_update_nip(ctx, ctx->nip);
 320    }
 321    t0 = tcg_const_i32(EXCP_DEBUG);
 322    gen_helper_raise_exception(cpu_env, t0);
 323    tcg_temp_free_i32(t0);
 324}
 325
 326static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
 327{
 328    /* Will be converted to program check if needed */
 329    gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error);
 330}
 331
 332static inline void gen_priv_exception(DisasContext *ctx, uint32_t error)
 333{
 334    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error);
 335}
 336
 337static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error)
 338{
 339    /* Will be converted to program check if needed */
 340    gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
 341}
 342
 343/* Stop translation */
 344static inline void gen_stop_exception(DisasContext *ctx)
 345{
 346    gen_update_nip(ctx, ctx->nip);
 347    ctx->exception = POWERPC_EXCP_STOP;
 348}
 349
 350#ifndef CONFIG_USER_ONLY
 351/* No need to update nip here, as execution flow will change */
 352static inline void gen_sync_exception(DisasContext *ctx)
 353{
 354    ctx->exception = POWERPC_EXCP_SYNC;
 355}
 356#endif
 357
 358#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
 359GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
 360
 361#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2)             \
 362GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
 363
 364#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
 365GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
 366
 367#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2)      \
 368GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
 369
 370typedef struct opcode_t {
 371    unsigned char opc1, opc2, opc3;
 372#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
 373    unsigned char pad[5];
 374#else
 375    unsigned char pad[1];
 376#endif
 377    opc_handler_t handler;
 378    const char *oname;
 379} opcode_t;
 380
 381/* Helpers for priv. check */
 382#define GEN_PRIV                                                \
 383    do {                                                        \
 384        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; \
 385    } while (0)
 386
 387#if defined(CONFIG_USER_ONLY)
 388#define CHK_HV GEN_PRIV
 389#define CHK_SV GEN_PRIV
 390#define CHK_HVRM GEN_PRIV
 391#else
 392#define CHK_HV                                                          \
 393    do {                                                                \
 394        if (unlikely(ctx->pr || !ctx->hv)) {                            \
 395            GEN_PRIV;                                                   \
 396        }                                                               \
 397    } while (0)
 398#define CHK_SV                   \
 399    do {                         \
 400        if (unlikely(ctx->pr)) { \
 401            GEN_PRIV;            \
 402        }                        \
 403    } while (0)
 404#define CHK_HVRM                                            \
 405    do {                                                    \
 406        if (unlikely(ctx->pr || !ctx->hv || ctx->dr)) {     \
 407            GEN_PRIV;                                       \
 408        }                                                   \
 409    } while (0)
 410#endif
 411
 412#define CHK_NONE
 413
 414
 415/*****************************************************************************/
 416/***                           Instruction decoding                        ***/
 417#define EXTRACT_HELPER(name, shift, nb)                                       \
 418static inline uint32_t name(uint32_t opcode)                                  \
 419{                                                                             \
 420    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
 421}
 422
 423#define EXTRACT_SHELPER(name, shift, nb)                                      \
 424static inline int32_t name(uint32_t opcode)                                   \
 425{                                                                             \
 426    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
 427}
 428
 429#define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2)                  \
 430static inline uint32_t name(uint32_t opcode)                                  \
 431{                                                                             \
 432    return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) |             \
 433            ((opcode >> (shift2)) & ((1 << (nb2)) - 1));                      \
 434}
 435/* Opcode part 1 */
 436EXTRACT_HELPER(opc1, 26, 6);
 437/* Opcode part 2 */
 438EXTRACT_HELPER(opc2, 1, 5);
 439/* Opcode part 3 */
 440EXTRACT_HELPER(opc3, 6, 5);
 441/* Update Cr0 flags */
 442EXTRACT_HELPER(Rc, 0, 1);
 443/* Update Cr6 flags (Altivec) */
 444EXTRACT_HELPER(Rc21, 10, 1);
 445/* Destination */
 446EXTRACT_HELPER(rD, 21, 5);
 447/* Source */
 448EXTRACT_HELPER(rS, 21, 5);
 449/* First operand */
 450EXTRACT_HELPER(rA, 16, 5);
 451/* Second operand */
 452EXTRACT_HELPER(rB, 11, 5);
 453/* Third operand */
 454EXTRACT_HELPER(rC, 6, 5);
 455/***                               Get CRn                                 ***/
 456EXTRACT_HELPER(crfD, 23, 3);
 457EXTRACT_HELPER(crfS, 18, 3);
 458EXTRACT_HELPER(crbD, 21, 5);
 459EXTRACT_HELPER(crbA, 16, 5);
 460EXTRACT_HELPER(crbB, 11, 5);
 461/* SPR / TBL */
 462EXTRACT_HELPER(_SPR, 11, 10);
 463static inline uint32_t SPR(uint32_t opcode)
 464{
 465    uint32_t sprn = _SPR(opcode);
 466
 467    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
 468}
 469/***                              Get constants                            ***/
 470/* 16 bits signed immediate value */
 471EXTRACT_SHELPER(SIMM, 0, 16);
 472/* 16 bits unsigned immediate value */
 473EXTRACT_HELPER(UIMM, 0, 16);
 474/* 5 bits signed immediate value */
 475EXTRACT_HELPER(SIMM5, 16, 5);
 476/* 5 bits signed immediate value */
 477EXTRACT_HELPER(UIMM5, 16, 5);
 478/* Bit count */
 479EXTRACT_HELPER(NB, 11, 5);
 480/* Shift count */
 481EXTRACT_HELPER(SH, 11, 5);
 482/* Vector shift count */
 483EXTRACT_HELPER(VSH, 6, 4);
 484/* Mask start */
 485EXTRACT_HELPER(MB, 6, 5);
 486/* Mask end */
 487EXTRACT_HELPER(ME, 1, 5);
 488/* Trap operand */
 489EXTRACT_HELPER(TO, 21, 5);
 490
 491EXTRACT_HELPER(CRM, 12, 8);
 492
 493#ifndef CONFIG_USER_ONLY
 494EXTRACT_HELPER(SR, 16, 4);
 495#endif
 496
 497/* mtfsf/mtfsfi */
 498EXTRACT_HELPER(FPBF, 23, 3);
 499EXTRACT_HELPER(FPIMM, 12, 4);
 500EXTRACT_HELPER(FPL, 25, 1);
 501EXTRACT_HELPER(FPFLM, 17, 8);
 502EXTRACT_HELPER(FPW, 16, 1);
 503
 504/***                            Jump target decoding                       ***/
 505/* Immediate address */
 506static inline target_ulong LI(uint32_t opcode)
 507{
 508    return (opcode >> 0) & 0x03FFFFFC;
 509}
 510
 511static inline uint32_t BD(uint32_t opcode)
 512{
 513    return (opcode >> 0) & 0xFFFC;
 514}
 515
 516EXTRACT_HELPER(BO, 21, 5);
 517EXTRACT_HELPER(BI, 16, 5);
 518/* Absolute/relative address */
 519EXTRACT_HELPER(AA, 1, 1);
 520/* Link */
 521EXTRACT_HELPER(LK, 0, 1);
 522
 523/* DFP Z22-form */
 524EXTRACT_HELPER(DCM, 10, 6)
 525
 526/* DFP Z23-form */
 527EXTRACT_HELPER(RMC, 9, 2)
 528
 529/* Create a mask between <start> and <end> bits */
 530static inline target_ulong MASK(uint32_t start, uint32_t end)
 531{
 532    target_ulong ret;
 533
 534#if defined(TARGET_PPC64)
 535    if (likely(start == 0)) {
 536        ret = UINT64_MAX << (63 - end);
 537    } else if (likely(end == 63)) {
 538        ret = UINT64_MAX >> start;
 539    }
 540#else
 541    if (likely(start == 0)) {
 542        ret = UINT32_MAX << (31  - end);
 543    } else if (likely(end == 31)) {
 544        ret = UINT32_MAX >> start;
 545    }
 546#endif
 547    else {
 548        ret = (((target_ulong)(-1ULL)) >> (start)) ^
 549            (((target_ulong)(-1ULL) >> (end)) >> 1);
 550        if (unlikely(start > end))
 551            return ~ret;
 552    }
 553
 554    return ret;
 555}
 556
 557EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
 558EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
 559EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
 560EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
 561EXTRACT_HELPER_SPLIT(xC, 3, 1,  6, 5);
 562EXTRACT_HELPER(DM, 8, 2);
 563EXTRACT_HELPER(UIM, 16, 2);
 564EXTRACT_HELPER(SHW, 8, 2);
 565EXTRACT_HELPER(SP, 19, 2);
 566/*****************************************************************************/
 567/* PowerPC instructions table                                                */
 568
 569#if defined(DO_PPC_STATISTICS)
 570#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
 571{                                                                             \
 572    .opc1 = op1,                                                              \
 573    .opc2 = op2,                                                              \
 574    .opc3 = op3,                                                              \
 575    .pad  = { 0, },                                                           \
 576    .handler = {                                                              \
 577        .inval1  = invl,                                                      \
 578        .type = _typ,                                                         \
 579        .type2 = _typ2,                                                       \
 580        .handler = &gen_##name,                                               \
 581        .oname = stringify(name),                                             \
 582    },                                                                        \
 583    .oname = stringify(name),                                                 \
 584}
 585#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
 586{                                                                             \
 587    .opc1 = op1,                                                              \
 588    .opc2 = op2,                                                              \
 589    .opc3 = op3,                                                              \
 590    .pad  = { 0, },                                                           \
 591    .handler = {                                                              \
 592        .inval1  = invl1,                                                     \
 593        .inval2  = invl2,                                                     \
 594        .type = _typ,                                                         \
 595        .type2 = _typ2,                                                       \
 596        .handler = &gen_##name,                                               \
 597        .oname = stringify(name),                                             \
 598    },                                                                        \
 599    .oname = stringify(name),                                                 \
 600}
 601#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
 602{                                                                             \
 603    .opc1 = op1,                                                              \
 604    .opc2 = op2,                                                              \
 605    .opc3 = op3,                                                              \
 606    .pad  = { 0, },                                                           \
 607    .handler = {                                                              \
 608        .inval1  = invl,                                                      \
 609        .type = _typ,                                                         \
 610        .type2 = _typ2,                                                       \
 611        .handler = &gen_##name,                                               \
 612        .oname = onam,                                                        \
 613    },                                                                        \
 614    .oname = onam,                                                            \
 615}
 616#else
 617#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
 618{                                                                             \
 619    .opc1 = op1,                                                              \
 620    .opc2 = op2,                                                              \
 621    .opc3 = op3,                                                              \
 622    .pad  = { 0, },                                                           \
 623    .handler = {                                                              \
 624        .inval1  = invl,                                                      \
 625        .type = _typ,                                                         \
 626        .type2 = _typ2,                                                       \
 627        .handler = &gen_##name,                                               \
 628    },                                                                        \
 629    .oname = stringify(name),                                                 \
 630}
 631#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
 632{                                                                             \
 633    .opc1 = op1,                                                              \
 634    .opc2 = op2,                                                              \
 635    .opc3 = op3,                                                              \
 636    .pad  = { 0, },                                                           \
 637    .handler = {                                                              \
 638        .inval1  = invl1,                                                     \
 639        .inval2  = invl2,                                                     \
 640        .type = _typ,                                                         \
 641        .type2 = _typ2,                                                       \
 642        .handler = &gen_##name,                                               \
 643    },                                                                        \
 644    .oname = stringify(name),                                                 \
 645}
 646#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
 647{                                                                             \
 648    .opc1 = op1,                                                              \
 649    .opc2 = op2,                                                              \
 650    .opc3 = op3,                                                              \
 651    .pad  = { 0, },                                                           \
 652    .handler = {                                                              \
 653        .inval1  = invl,                                                      \
 654        .type = _typ,                                                         \
 655        .type2 = _typ2,                                                       \
 656        .handler = &gen_##name,                                               \
 657    },                                                                        \
 658    .oname = onam,                                                            \
 659}
 660#endif
 661
 662/* SPR load/store helpers */
 663static inline void gen_load_spr(TCGv t, int reg)
 664{
 665    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 666}
 667
 668static inline void gen_store_spr(int reg, TCGv t)
 669{
 670    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
 671}
 672
 673/* Invalid instruction */
 674static void gen_invalid(DisasContext *ctx)
 675{
 676    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
 677}
 678
 679static opc_handler_t invalid_handler = {
 680    .inval1  = 0xFFFFFFFF,
 681    .inval2  = 0xFFFFFFFF,
 682    .type    = PPC_NONE,
 683    .type2   = PPC_NONE,
 684    .handler = gen_invalid,
 685};
 686
 687/***                           Integer comparison                          ***/
 688
 689static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
 690{
 691    TCGv t0 = tcg_temp_new();
 692    TCGv_i32 t1 = tcg_temp_new_i32();
 693
 694    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
 695
 696    tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
 697    tcg_gen_trunc_tl_i32(t1, t0);
 698    tcg_gen_shli_i32(t1, t1, CRF_LT);
 699    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 700
 701    tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
 702    tcg_gen_trunc_tl_i32(t1, t0);
 703    tcg_gen_shli_i32(t1, t1, CRF_GT);
 704    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 705
 706    tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
 707    tcg_gen_trunc_tl_i32(t1, t0);
 708    tcg_gen_shli_i32(t1, t1, CRF_EQ);
 709    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
 710
 711    tcg_temp_free(t0);
 712    tcg_temp_free_i32(t1);
 713}
 714
 715static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
 716{
 717    TCGv t0 = tcg_const_tl(arg1);
 718    gen_op_cmp(arg0, t0, s, crf);
 719    tcg_temp_free(t0);
 720}
 721
 722static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
 723{
 724    TCGv t0, t1;
 725    t0 = tcg_temp_new();
 726    t1 = tcg_temp_new();
 727    if (s) {
 728        tcg_gen_ext32s_tl(t0, arg0);
 729        tcg_gen_ext32s_tl(t1, arg1);
 730    } else {
 731        tcg_gen_ext32u_tl(t0, arg0);
 732        tcg_gen_ext32u_tl(t1, arg1);
 733    }
 734    gen_op_cmp(t0, t1, s, crf);
 735    tcg_temp_free(t1);
 736    tcg_temp_free(t0);
 737}
 738
 739static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
 740{
 741    TCGv t0 = tcg_const_tl(arg1);
 742    gen_op_cmp32(arg0, t0, s, crf);
 743    tcg_temp_free(t0);
 744}
 745
 746static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
 747{
 748    if (NARROW_MODE(ctx)) {
 749        gen_op_cmpi32(reg, 0, 1, 0);
 750    } else {
 751        gen_op_cmpi(reg, 0, 1, 0);
 752    }
 753}
 754
 755/* cmp */
 756static void gen_cmp(DisasContext *ctx)
 757{
 758    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 759        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 760                   1, crfD(ctx->opcode));
 761    } else {
 762        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 763                     1, crfD(ctx->opcode));
 764    }
 765}
 766
 767/* cmpi */
 768static void gen_cmpi(DisasContext *ctx)
 769{
 770    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 771        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
 772                    1, crfD(ctx->opcode));
 773    } else {
 774        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
 775                      1, crfD(ctx->opcode));
 776    }
 777}
 778
 779/* cmpl */
 780static void gen_cmpl(DisasContext *ctx)
 781{
 782    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 783        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 784                   0, crfD(ctx->opcode));
 785    } else {
 786        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
 787                     0, crfD(ctx->opcode));
 788    }
 789}
 790
 791/* cmpli */
 792static void gen_cmpli(DisasContext *ctx)
 793{
 794    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
 795        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
 796                    0, crfD(ctx->opcode));
 797    } else {
 798        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
 799                      0, crfD(ctx->opcode));
 800    }
 801}
 802
 803/* isel (PowerPC 2.03 specification) */
 804static void gen_isel(DisasContext *ctx)
 805{
 806    uint32_t bi = rC(ctx->opcode);
 807    uint32_t mask = 0x08 >> (bi & 0x03);
 808    TCGv t0 = tcg_temp_new();
 809    TCGv zr;
 810
 811    tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
 812    tcg_gen_andi_tl(t0, t0, mask);
 813
 814    zr = tcg_const_tl(0);
 815    tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
 816                       rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
 817                       cpu_gpr[rB(ctx->opcode)]);
 818    tcg_temp_free(zr);
 819    tcg_temp_free(t0);
 820}
 821
 822/* cmpb: PowerPC 2.05 specification */
 823static void gen_cmpb(DisasContext *ctx)
 824{
 825    gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
 826                    cpu_gpr[rB(ctx->opcode)]);
 827}
 828
 829/***                           Integer arithmetic                          ***/
 830
 831static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
 832                                           TCGv arg1, TCGv arg2, int sub)
 833{
 834    TCGv t0 = tcg_temp_new();
 835
 836    tcg_gen_xor_tl(cpu_ov, arg0, arg2);
 837    tcg_gen_xor_tl(t0, arg1, arg2);
 838    if (sub) {
 839        tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
 840    } else {
 841        tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
 842    }
 843    tcg_temp_free(t0);
 844    if (NARROW_MODE(ctx)) {
 845        tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
 846    }
 847    tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
 848    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
 849}
 850
 851/* Common add function */
 852static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
 853                                    TCGv arg2, bool add_ca, bool compute_ca,
 854                                    bool compute_ov, bool compute_rc0)
 855{
 856    TCGv t0 = ret;
 857
 858    if (compute_ca || compute_ov) {
 859        t0 = tcg_temp_new();
 860    }
 861
 862    if (compute_ca) {
 863        if (NARROW_MODE(ctx)) {
 864            /* Caution: a non-obvious corner case of the spec is that we
 865               must produce the *entire* 64-bit addition, but produce the
 866               carry into bit 32.  */
 867            TCGv t1 = tcg_temp_new();
 868            tcg_gen_xor_tl(t1, arg1, arg2);        /* add without carry */
 869            tcg_gen_add_tl(t0, arg1, arg2);
 870            if (add_ca) {
 871                tcg_gen_add_tl(t0, t0, cpu_ca);
 872            }
 873            tcg_gen_xor_tl(cpu_ca, t0, t1);        /* bits changed w/ carry */
 874            tcg_temp_free(t1);
 875            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);   /* extract bit 32 */
 876            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
 877        } else {
 878            TCGv zero = tcg_const_tl(0);
 879            if (add_ca) {
 880                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
 881                tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
 882            } else {
 883                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
 884            }
 885            tcg_temp_free(zero);
 886        }
 887    } else {
 888        tcg_gen_add_tl(t0, arg1, arg2);
 889        if (add_ca) {
 890            tcg_gen_add_tl(t0, t0, cpu_ca);
 891        }
 892    }
 893
 894    if (compute_ov) {
 895        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
 896    }
 897    if (unlikely(compute_rc0)) {
 898        gen_set_Rc0(ctx, t0);
 899    }
 900
 901    if (!TCGV_EQUAL(t0, ret)) {
 902        tcg_gen_mov_tl(ret, t0);
 903        tcg_temp_free(t0);
 904    }
 905}
 906/* Add functions with two operands */
 907#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
 908static void glue(gen_, name)(DisasContext *ctx)                               \
 909{                                                                             \
 910    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
 911                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
 912                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
 913}
 914/* Add functions with one operand and one immediate */
 915#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
 916                                add_ca, compute_ca, compute_ov)               \
 917static void glue(gen_, name)(DisasContext *ctx)                               \
 918{                                                                             \
 919    TCGv t0 = tcg_const_tl(const_val);                                        \
 920    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
 921                     cpu_gpr[rA(ctx->opcode)], t0,                            \
 922                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
 923    tcg_temp_free(t0);                                                        \
 924}
 925
 926/* add  add.  addo  addo. */
 927GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
 928GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
 929/* addc  addc.  addco  addco. */
 930GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
 931GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
 932/* adde  adde.  addeo  addeo. */
 933GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
 934GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
 935/* addme  addme.  addmeo  addmeo.  */
 936GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
 937GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
 938/* addze  addze.  addzeo  addzeo.*/
 939GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
 940GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
 941/* addi */
 942static void gen_addi(DisasContext *ctx)
 943{
 944    target_long simm = SIMM(ctx->opcode);
 945
 946    if (rA(ctx->opcode) == 0) {
 947        /* li case */
 948        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
 949    } else {
 950        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
 951                        cpu_gpr[rA(ctx->opcode)], simm);
 952    }
 953}
 954/* addic  addic.*/
 955static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
 956{
 957    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
 958    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
 959                     c, 0, 1, 0, compute_rc0);
 960    tcg_temp_free(c);
 961}
 962
 963static void gen_addic(DisasContext *ctx)
 964{
 965    gen_op_addic(ctx, 0);
 966}
 967
 968static void gen_addic_(DisasContext *ctx)
 969{
 970    gen_op_addic(ctx, 1);
 971}
 972
 973/* addis */
 974static void gen_addis(DisasContext *ctx)
 975{
 976    target_long simm = SIMM(ctx->opcode);
 977
 978    if (rA(ctx->opcode) == 0) {
 979        /* lis case */
 980        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
 981    } else {
 982        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
 983                        cpu_gpr[rA(ctx->opcode)], simm << 16);
 984    }
 985}
 986
 987static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
 988                                     TCGv arg2, int sign, int compute_ov)
 989{
 990    TCGLabel *l1 = gen_new_label();
 991    TCGLabel *l2 = gen_new_label();
 992    TCGv_i32 t0 = tcg_temp_local_new_i32();
 993    TCGv_i32 t1 = tcg_temp_local_new_i32();
 994
 995    tcg_gen_trunc_tl_i32(t0, arg1);
 996    tcg_gen_trunc_tl_i32(t1, arg2);
 997    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
 998    if (sign) {
 999        TCGLabel *l3 = gen_new_label();
1000        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
1001        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
1002        gen_set_label(l3);
1003        tcg_gen_div_i32(t0, t0, t1);
1004    } else {
1005        tcg_gen_divu_i32(t0, t0, t1);
1006    }
1007    if (compute_ov) {
1008        tcg_gen_movi_tl(cpu_ov, 0);
1009    }
1010    tcg_gen_br(l2);
1011    gen_set_label(l1);
1012    if (sign) {
1013        tcg_gen_sari_i32(t0, t0, 31);
1014    } else {
1015        tcg_gen_movi_i32(t0, 0);
1016    }
1017    if (compute_ov) {
1018        tcg_gen_movi_tl(cpu_ov, 1);
1019        tcg_gen_movi_tl(cpu_so, 1);
1020    }
1021    gen_set_label(l2);
1022    tcg_gen_extu_i32_tl(ret, t0);
1023    tcg_temp_free_i32(t0);
1024    tcg_temp_free_i32(t1);
1025    if (unlikely(Rc(ctx->opcode) != 0))
1026        gen_set_Rc0(ctx, ret);
1027}
1028/* Div functions */
1029#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
1030static void glue(gen_, name)(DisasContext *ctx)                                       \
1031{                                                                             \
1032    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1033                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
1034                     sign, compute_ov);                                       \
1035}
1036/* divwu  divwu.  divwuo  divwuo.   */
1037GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1038GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1039/* divw  divw.  divwo  divwo.   */
1040GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1041GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1042
1043/* div[wd]eu[o][.] */
1044#define GEN_DIVE(name, hlpr, compute_ov)                                      \
1045static void gen_##name(DisasContext *ctx)                                     \
1046{                                                                             \
1047    TCGv_i32 t0 = tcg_const_i32(compute_ov);                                  \
1048    gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
1049                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
1050    tcg_temp_free_i32(t0);                                                    \
1051    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
1052        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1053    }                                                                         \
1054}
1055
1056GEN_DIVE(divweu, divweu, 0);
1057GEN_DIVE(divweuo, divweu, 1);
1058GEN_DIVE(divwe, divwe, 0);
1059GEN_DIVE(divweo, divwe, 1);
1060
1061#if defined(TARGET_PPC64)
1062static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1063                                     TCGv arg2, int sign, int compute_ov)
1064{
1065    TCGLabel *l1 = gen_new_label();
1066    TCGLabel *l2 = gen_new_label();
1067
1068    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1069    if (sign) {
1070        TCGLabel *l3 = gen_new_label();
1071        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1072        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1073        gen_set_label(l3);
1074        tcg_gen_div_i64(ret, arg1, arg2);
1075    } else {
1076        tcg_gen_divu_i64(ret, arg1, arg2);
1077    }
1078    if (compute_ov) {
1079        tcg_gen_movi_tl(cpu_ov, 0);
1080    }
1081    tcg_gen_br(l2);
1082    gen_set_label(l1);
1083    if (sign) {
1084        tcg_gen_sari_i64(ret, arg1, 63);
1085    } else {
1086        tcg_gen_movi_i64(ret, 0);
1087    }
1088    if (compute_ov) {
1089        tcg_gen_movi_tl(cpu_ov, 1);
1090        tcg_gen_movi_tl(cpu_so, 1);
1091    }
1092    gen_set_label(l2);
1093    if (unlikely(Rc(ctx->opcode) != 0))
1094        gen_set_Rc0(ctx, ret);
1095}
1096#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
1097static void glue(gen_, name)(DisasContext *ctx)                                       \
1098{                                                                             \
1099    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1100                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1101                      sign, compute_ov);                                      \
1102}
1103/* divwu  divwu.  divwuo  divwuo.   */
1104GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1105GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1106/* divw  divw.  divwo  divwo.   */
1107GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1108GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1109
1110GEN_DIVE(divdeu, divdeu, 0);
1111GEN_DIVE(divdeuo, divdeu, 1);
1112GEN_DIVE(divde, divde, 0);
1113GEN_DIVE(divdeo, divde, 1);
1114#endif
1115
1116/* mulhw  mulhw. */
1117static void gen_mulhw(DisasContext *ctx)
1118{
1119    TCGv_i32 t0 = tcg_temp_new_i32();
1120    TCGv_i32 t1 = tcg_temp_new_i32();
1121
1122    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1123    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1124    tcg_gen_muls2_i32(t0, t1, t0, t1);
1125    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1126    tcg_temp_free_i32(t0);
1127    tcg_temp_free_i32(t1);
1128    if (unlikely(Rc(ctx->opcode) != 0))
1129        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1130}
1131
1132/* mulhwu  mulhwu.  */
1133static void gen_mulhwu(DisasContext *ctx)
1134{
1135    TCGv_i32 t0 = tcg_temp_new_i32();
1136    TCGv_i32 t1 = tcg_temp_new_i32();
1137
1138    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1139    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1140    tcg_gen_mulu2_i32(t0, t1, t0, t1);
1141    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1142    tcg_temp_free_i32(t0);
1143    tcg_temp_free_i32(t1);
1144    if (unlikely(Rc(ctx->opcode) != 0))
1145        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1146}
1147
1148/* mullw  mullw. */
1149static void gen_mullw(DisasContext *ctx)
1150{
1151#if defined(TARGET_PPC64)
1152    TCGv_i64 t0, t1;
1153    t0 = tcg_temp_new_i64();
1154    t1 = tcg_temp_new_i64();
1155    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1156    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1157    tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1158    tcg_temp_free(t0);
1159    tcg_temp_free(t1);
1160#else
1161    tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1162                    cpu_gpr[rB(ctx->opcode)]);
1163#endif
1164    if (unlikely(Rc(ctx->opcode) != 0))
1165        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1166}
1167
1168/* mullwo  mullwo. */
1169static void gen_mullwo(DisasContext *ctx)
1170{
1171    TCGv_i32 t0 = tcg_temp_new_i32();
1172    TCGv_i32 t1 = tcg_temp_new_i32();
1173
1174    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1175    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1176    tcg_gen_muls2_i32(t0, t1, t0, t1);
1177#if defined(TARGET_PPC64)
1178    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1179#else
1180    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
1181#endif
1182
1183    tcg_gen_sari_i32(t0, t0, 31);
1184    tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
1185    tcg_gen_extu_i32_tl(cpu_ov, t0);
1186    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1187
1188    tcg_temp_free_i32(t0);
1189    tcg_temp_free_i32(t1);
1190    if (unlikely(Rc(ctx->opcode) != 0))
1191        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1192}
1193
1194/* mulli */
1195static void gen_mulli(DisasContext *ctx)
1196{
1197    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1198                    SIMM(ctx->opcode));
1199}
1200
1201#if defined(TARGET_PPC64)
1202/* mulhd  mulhd. */
1203static void gen_mulhd(DisasContext *ctx)
1204{
1205    TCGv lo = tcg_temp_new();
1206    tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1207                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1208    tcg_temp_free(lo);
1209    if (unlikely(Rc(ctx->opcode) != 0)) {
1210        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1211    }
1212}
1213
1214/* mulhdu  mulhdu. */
1215static void gen_mulhdu(DisasContext *ctx)
1216{
1217    TCGv lo = tcg_temp_new();
1218    tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1219                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1220    tcg_temp_free(lo);
1221    if (unlikely(Rc(ctx->opcode) != 0)) {
1222        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1223    }
1224}
1225
1226/* mulld  mulld. */
1227static void gen_mulld(DisasContext *ctx)
1228{
1229    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1230                   cpu_gpr[rB(ctx->opcode)]);
1231    if (unlikely(Rc(ctx->opcode) != 0))
1232        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1233}
1234
1235/* mulldo  mulldo. */
1236static void gen_mulldo(DisasContext *ctx)
1237{
1238    TCGv_i64 t0 = tcg_temp_new_i64();
1239    TCGv_i64 t1 = tcg_temp_new_i64();
1240
1241    tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
1242                      cpu_gpr[rB(ctx->opcode)]);
1243    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
1244
1245    tcg_gen_sari_i64(t0, t0, 63);
1246    tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
1247    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1248
1249    tcg_temp_free_i64(t0);
1250    tcg_temp_free_i64(t1);
1251
1252    if (unlikely(Rc(ctx->opcode) != 0)) {
1253        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1254    }
1255}
1256#endif
1257
1258/* Common subf function */
1259static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1260                                     TCGv arg2, bool add_ca, bool compute_ca,
1261                                     bool compute_ov, bool compute_rc0)
1262{
1263    TCGv t0 = ret;
1264
1265    if (compute_ca || compute_ov) {
1266        t0 = tcg_temp_new();
1267    }
1268
1269    if (compute_ca) {
1270        /* dest = ~arg1 + arg2 [+ ca].  */
1271        if (NARROW_MODE(ctx)) {
1272            /* Caution: a non-obvious corner case of the spec is that we
1273               must produce the *entire* 64-bit addition, but produce the
1274               carry into bit 32.  */
1275            TCGv inv1 = tcg_temp_new();
1276            TCGv t1 = tcg_temp_new();
1277            tcg_gen_not_tl(inv1, arg1);
1278            if (add_ca) {
1279                tcg_gen_add_tl(t0, arg2, cpu_ca);
1280            } else {
1281                tcg_gen_addi_tl(t0, arg2, 1);
1282            }
1283            tcg_gen_xor_tl(t1, arg2, inv1);         /* add without carry */
1284            tcg_gen_add_tl(t0, t0, inv1);
1285            tcg_temp_free(inv1);
1286            tcg_gen_xor_tl(cpu_ca, t0, t1);         /* bits changes w/ carry */
1287            tcg_temp_free(t1);
1288            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);    /* extract bit 32 */
1289            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
1290        } else if (add_ca) {
1291            TCGv zero, inv1 = tcg_temp_new();
1292            tcg_gen_not_tl(inv1, arg1);
1293            zero = tcg_const_tl(0);
1294            tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
1295            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
1296            tcg_temp_free(zero);
1297            tcg_temp_free(inv1);
1298        } else {
1299            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
1300            tcg_gen_sub_tl(t0, arg2, arg1);
1301        }
1302    } else if (add_ca) {
1303        /* Since we're ignoring carry-out, we can simplify the
1304           standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.  */
1305        tcg_gen_sub_tl(t0, arg2, arg1);
1306        tcg_gen_add_tl(t0, t0, cpu_ca);
1307        tcg_gen_subi_tl(t0, t0, 1);
1308    } else {
1309        tcg_gen_sub_tl(t0, arg2, arg1);
1310    }
1311
1312    if (compute_ov) {
1313        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1314    }
1315    if (unlikely(compute_rc0)) {
1316        gen_set_Rc0(ctx, t0);
1317    }
1318
1319    if (!TCGV_EQUAL(t0, ret)) {
1320        tcg_gen_mov_tl(ret, t0);
1321        tcg_temp_free(t0);
1322    }
1323}
1324/* Sub functions with Two operands functions */
1325#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1326static void glue(gen_, name)(DisasContext *ctx)                               \
1327{                                                                             \
1328    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1329                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1330                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1331}
1332/* Sub functions with one operand and one immediate */
1333#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1334                                add_ca, compute_ca, compute_ov)               \
1335static void glue(gen_, name)(DisasContext *ctx)                               \
1336{                                                                             \
1337    TCGv t0 = tcg_const_tl(const_val);                                        \
1338    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1339                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1340                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1341    tcg_temp_free(t0);                                                        \
1342}
1343/* subf  subf.  subfo  subfo. */
1344GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1345GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1346/* subfc  subfc.  subfco  subfco. */
1347GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1348GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1349/* subfe  subfe.  subfeo  subfo. */
1350GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1351GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1352/* subfme  subfme.  subfmeo  subfmeo.  */
1353GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1354GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1355/* subfze  subfze.  subfzeo  subfzeo.*/
1356GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1357GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1358
1359/* subfic */
1360static void gen_subfic(DisasContext *ctx)
1361{
1362    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1363    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1364                      c, 0, 1, 0, 0);
1365    tcg_temp_free(c);
1366}
1367
1368/* neg neg. nego nego. */
1369static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
1370{
1371    TCGv zero = tcg_const_tl(0);
1372    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1373                      zero, 0, 0, compute_ov, Rc(ctx->opcode));
1374    tcg_temp_free(zero);
1375}
1376
1377static void gen_neg(DisasContext *ctx)
1378{
1379    gen_op_arith_neg(ctx, 0);
1380}
1381
1382static void gen_nego(DisasContext *ctx)
1383{
1384    gen_op_arith_neg(ctx, 1);
1385}
1386
1387/***                            Integer logical                            ***/
1388#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1389static void glue(gen_, name)(DisasContext *ctx)                                       \
1390{                                                                             \
1391    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1392       cpu_gpr[rB(ctx->opcode)]);                                             \
1393    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1394        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1395}
1396
1397#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1398static void glue(gen_, name)(DisasContext *ctx)                                       \
1399{                                                                             \
1400    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1401    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1402        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1403}
1404
1405/* and & and. */
1406GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1407/* andc & andc. */
1408GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1409
1410/* andi. */
1411static void gen_andi_(DisasContext *ctx)
1412{
1413    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1414    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1415}
1416
1417/* andis. */
1418static void gen_andis_(DisasContext *ctx)
1419{
1420    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1421    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1422}
1423
1424/* cntlzw */
1425static void gen_cntlzw(DisasContext *ctx)
1426{
1427    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1428    if (unlikely(Rc(ctx->opcode) != 0))
1429        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1430}
1431/* eqv & eqv. */
1432GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1433/* extsb & extsb. */
1434GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1435/* extsh & extsh. */
1436GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1437/* nand & nand. */
1438GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1439/* nor & nor. */
1440GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1441
1442#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
1443static void gen_pause(DisasContext *ctx)
1444{
1445    TCGv_i32 t0 = tcg_const_i32(0);
1446    tcg_gen_st_i32(t0, cpu_env,
1447                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
1448    tcg_temp_free_i32(t0);
1449
1450    /* Stop translation, this gives other CPUs a chance to run */
1451    gen_exception_err(ctx, EXCP_HLT, 1);
1452}
1453#endif /* defined(TARGET_PPC64) */
1454
1455/* or & or. */
1456static void gen_or(DisasContext *ctx)
1457{
1458    int rs, ra, rb;
1459
1460    rs = rS(ctx->opcode);
1461    ra = rA(ctx->opcode);
1462    rb = rB(ctx->opcode);
1463    /* Optimisation for mr. ri case */
1464    if (rs != ra || rs != rb) {
1465        if (rs != rb)
1466            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1467        else
1468            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1469        if (unlikely(Rc(ctx->opcode) != 0))
1470            gen_set_Rc0(ctx, cpu_gpr[ra]);
1471    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1472        gen_set_Rc0(ctx, cpu_gpr[rs]);
1473#if defined(TARGET_PPC64)
1474    } else if (rs != 0) { /* 0 is nop */
1475        int prio = 0;
1476
1477        switch (rs) {
1478        case 1:
1479            /* Set process priority to low */
1480            prio = 2;
1481            break;
1482        case 6:
1483            /* Set process priority to medium-low */
1484            prio = 3;
1485            break;
1486        case 2:
1487            /* Set process priority to normal */
1488            prio = 4;
1489            break;
1490#if !defined(CONFIG_USER_ONLY)
1491        case 31:
1492            if (!ctx->pr) {
1493                /* Set process priority to very low */
1494                prio = 1;
1495            }
1496            break;
1497        case 5:
1498            if (!ctx->pr) {
1499                /* Set process priority to medium-hight */
1500                prio = 5;
1501            }
1502            break;
1503        case 3:
1504            if (!ctx->pr) {
1505                /* Set process priority to high */
1506                prio = 6;
1507            }
1508            break;
1509        case 7:
1510            if (ctx->hv && !ctx->pr) {
1511                /* Set process priority to very high */
1512                prio = 7;
1513            }
1514            break;
1515#endif
1516        default:
1517            break;
1518        }
1519        if (prio) {
1520            TCGv t0 = tcg_temp_new();
1521            gen_load_spr(t0, SPR_PPR);
1522            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1523            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1524            gen_store_spr(SPR_PPR, t0);
1525            tcg_temp_free(t0);
1526        }
1527#if !defined(CONFIG_USER_ONLY)
1528        /* Pause out of TCG otherwise spin loops with smt_low eat too much
1529         * CPU and the kernel hangs.  This applies to all encodings other
1530         * than no-op, e.g., miso(rs=26), yield(27), mdoio(29), mdoom(30),
1531         * and all currently undefined.
1532         */
1533        gen_pause(ctx);
1534#endif
1535#endif
1536    }
1537}
1538/* orc & orc. */
1539GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1540
1541/* xor & xor. */
1542static void gen_xor(DisasContext *ctx)
1543{
1544    /* Optimisation for "set to zero" case */
1545    if (rS(ctx->opcode) != rB(ctx->opcode))
1546        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1547    else
1548        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1549    if (unlikely(Rc(ctx->opcode) != 0))
1550        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1551}
1552
1553/* ori */
1554static void gen_ori(DisasContext *ctx)
1555{
1556    target_ulong uimm = UIMM(ctx->opcode);
1557
1558    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1559        return;
1560    }
1561    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1562}
1563
1564/* oris */
1565static void gen_oris(DisasContext *ctx)
1566{
1567    target_ulong uimm = UIMM(ctx->opcode);
1568
1569    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1570        /* NOP */
1571        return;
1572    }
1573    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1574}
1575
1576/* xori */
1577static void gen_xori(DisasContext *ctx)
1578{
1579    target_ulong uimm = UIMM(ctx->opcode);
1580
1581    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1582        /* NOP */
1583        return;
1584    }
1585    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1586}
1587
1588/* xoris */
1589static void gen_xoris(DisasContext *ctx)
1590{
1591    target_ulong uimm = UIMM(ctx->opcode);
1592
1593    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1594        /* NOP */
1595        return;
1596    }
1597    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1598}
1599
1600/* popcntb : PowerPC 2.03 specification */
1601static void gen_popcntb(DisasContext *ctx)
1602{
1603    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1604}
1605
1606static void gen_popcntw(DisasContext *ctx)
1607{
1608    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1609}
1610
1611#if defined(TARGET_PPC64)
1612/* popcntd: PowerPC 2.06 specification */
1613static void gen_popcntd(DisasContext *ctx)
1614{
1615    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1616}
1617#endif
1618
1619/* prtyw: PowerPC 2.05 specification */
1620static void gen_prtyw(DisasContext *ctx)
1621{
1622    TCGv ra = cpu_gpr[rA(ctx->opcode)];
1623    TCGv rs = cpu_gpr[rS(ctx->opcode)];
1624    TCGv t0 = tcg_temp_new();
1625    tcg_gen_shri_tl(t0, rs, 16);
1626    tcg_gen_xor_tl(ra, rs, t0);
1627    tcg_gen_shri_tl(t0, ra, 8);
1628    tcg_gen_xor_tl(ra, ra, t0);
1629    tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
1630    tcg_temp_free(t0);
1631}
1632
1633#if defined(TARGET_PPC64)
1634/* prtyd: PowerPC 2.05 specification */
1635static void gen_prtyd(DisasContext *ctx)
1636{
1637    TCGv ra = cpu_gpr[rA(ctx->opcode)];
1638    TCGv rs = cpu_gpr[rS(ctx->opcode)];
1639    TCGv t0 = tcg_temp_new();
1640    tcg_gen_shri_tl(t0, rs, 32);
1641    tcg_gen_xor_tl(ra, rs, t0);
1642    tcg_gen_shri_tl(t0, ra, 16);
1643    tcg_gen_xor_tl(ra, ra, t0);
1644    tcg_gen_shri_tl(t0, ra, 8);
1645    tcg_gen_xor_tl(ra, ra, t0);
1646    tcg_gen_andi_tl(ra, ra, 1);
1647    tcg_temp_free(t0);
1648}
1649#endif
1650
1651#if defined(TARGET_PPC64)
1652/* bpermd */
1653static void gen_bpermd(DisasContext *ctx)
1654{
1655    gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
1656                      cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1657}
1658#endif
1659
1660#if defined(TARGET_PPC64)
1661/* extsw & extsw. */
1662GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1663
1664/* cntlzd */
1665static void gen_cntlzd(DisasContext *ctx)
1666{
1667    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1668    if (unlikely(Rc(ctx->opcode) != 0))
1669        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1670}
1671#endif
1672
1673/***                             Integer rotate                            ***/
1674
1675/* rlwimi & rlwimi. */
1676static void gen_rlwimi(DisasContext *ctx)
1677{
1678    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1679    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1680    uint32_t sh = SH(ctx->opcode);
1681    uint32_t mb = MB(ctx->opcode);
1682    uint32_t me = ME(ctx->opcode);
1683
1684    if (sh == (31-me) && mb <= me) {
1685        tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
1686    } else {
1687        target_ulong mask;
1688        TCGv t1;
1689
1690#if defined(TARGET_PPC64)
1691        mb += 32;
1692        me += 32;
1693#endif
1694        mask = MASK(mb, me);
1695
1696        t1 = tcg_temp_new();
1697        if (mask <= 0xffffffffu) {
1698            TCGv_i32 t0 = tcg_temp_new_i32();
1699            tcg_gen_trunc_tl_i32(t0, t_rs);
1700            tcg_gen_rotli_i32(t0, t0, sh);
1701            tcg_gen_extu_i32_tl(t1, t0);
1702            tcg_temp_free_i32(t0);
1703        } else {
1704#if defined(TARGET_PPC64)
1705            tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
1706            tcg_gen_rotli_i64(t1, t1, sh);
1707#else
1708            g_assert_not_reached();
1709#endif
1710        }
1711
1712        tcg_gen_andi_tl(t1, t1, mask);
1713        tcg_gen_andi_tl(t_ra, t_ra, ~mask);
1714        tcg_gen_or_tl(t_ra, t_ra, t1);
1715        tcg_temp_free(t1);
1716    }
1717    if (unlikely(Rc(ctx->opcode) != 0)) {
1718        gen_set_Rc0(ctx, t_ra);
1719    }
1720}
1721
1722/* rlwinm & rlwinm. */
1723static void gen_rlwinm(DisasContext *ctx)
1724{
1725    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1726    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1727    uint32_t sh = SH(ctx->opcode);
1728    uint32_t mb = MB(ctx->opcode);
1729    uint32_t me = ME(ctx->opcode);
1730
1731    if (mb == 0 && me == (31 - sh)) {
1732        tcg_gen_shli_tl(t_ra, t_rs, sh);
1733        tcg_gen_ext32u_tl(t_ra, t_ra);
1734    } else if (sh != 0 && me == 31 && sh == (32 - mb)) {
1735        tcg_gen_ext32u_tl(t_ra, t_rs);
1736        tcg_gen_shri_tl(t_ra, t_ra, mb);
1737    } else {
1738        target_ulong mask;
1739#if defined(TARGET_PPC64)
1740        mb += 32;
1741        me += 32;
1742#endif
1743        mask = MASK(mb, me);
1744
1745        if (mask <= 0xffffffffu) {
1746            TCGv_i32 t0 = tcg_temp_new_i32();
1747            tcg_gen_trunc_tl_i32(t0, t_rs);
1748            tcg_gen_rotli_i32(t0, t0, sh);
1749            tcg_gen_andi_i32(t0, t0, mask);
1750            tcg_gen_extu_i32_tl(t_ra, t0);
1751            tcg_temp_free_i32(t0);
1752        } else {
1753#if defined(TARGET_PPC64)
1754            tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
1755            tcg_gen_rotli_i64(t_ra, t_ra, sh);
1756            tcg_gen_andi_i64(t_ra, t_ra, mask);
1757#else
1758            g_assert_not_reached();
1759#endif
1760        }
1761    }
1762    if (unlikely(Rc(ctx->opcode) != 0)) {
1763        gen_set_Rc0(ctx, t_ra);
1764    }
1765}
1766
1767/* rlwnm & rlwnm. */
1768static void gen_rlwnm(DisasContext *ctx)
1769{
1770    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1771    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1772    TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
1773    uint32_t mb = MB(ctx->opcode);
1774    uint32_t me = ME(ctx->opcode);
1775    target_ulong mask;
1776
1777#if defined(TARGET_PPC64)
1778    mb += 32;
1779    me += 32;
1780#endif
1781    mask = MASK(mb, me);
1782
1783    if (mask <= 0xffffffffu) {
1784        TCGv_i32 t0 = tcg_temp_new_i32();
1785        TCGv_i32 t1 = tcg_temp_new_i32();
1786        tcg_gen_trunc_tl_i32(t0, t_rb);
1787        tcg_gen_trunc_tl_i32(t1, t_rs);
1788        tcg_gen_andi_i32(t0, t0, 0x1f);
1789        tcg_gen_rotl_i32(t1, t1, t0);
1790        tcg_gen_extu_i32_tl(t_ra, t1);
1791        tcg_temp_free_i32(t0);
1792        tcg_temp_free_i32(t1);
1793    } else {
1794#if defined(TARGET_PPC64)
1795        TCGv_i64 t0 = tcg_temp_new_i64();
1796        tcg_gen_andi_i64(t0, t_rb, 0x1f);
1797        tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
1798        tcg_gen_rotl_i64(t_ra, t_ra, t0);
1799        tcg_temp_free_i64(t0);
1800#else
1801        g_assert_not_reached();
1802#endif
1803    }
1804
1805    tcg_gen_andi_tl(t_ra, t_ra, mask);
1806
1807    if (unlikely(Rc(ctx->opcode) != 0)) {
1808        gen_set_Rc0(ctx, t_ra);
1809    }
1810}
1811
1812#if defined(TARGET_PPC64)
1813#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1814static void glue(gen_, name##0)(DisasContext *ctx)                            \
1815{                                                                             \
1816    gen_##name(ctx, 0);                                                       \
1817}                                                                             \
1818                                                                              \
1819static void glue(gen_, name##1)(DisasContext *ctx)                            \
1820{                                                                             \
1821    gen_##name(ctx, 1);                                                       \
1822}
1823#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1824static void glue(gen_, name##0)(DisasContext *ctx)                            \
1825{                                                                             \
1826    gen_##name(ctx, 0, 0);                                                    \
1827}                                                                             \
1828                                                                              \
1829static void glue(gen_, name##1)(DisasContext *ctx)                            \
1830{                                                                             \
1831    gen_##name(ctx, 0, 1);                                                    \
1832}                                                                             \
1833                                                                              \
1834static void glue(gen_, name##2)(DisasContext *ctx)                            \
1835{                                                                             \
1836    gen_##name(ctx, 1, 0);                                                    \
1837}                                                                             \
1838                                                                              \
1839static void glue(gen_, name##3)(DisasContext *ctx)                            \
1840{                                                                             \
1841    gen_##name(ctx, 1, 1);                                                    \
1842}
1843
1844static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
1845{
1846    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1847    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1848
1849    if (sh != 0 && mb == 0 && me == (63 - sh)) {
1850        tcg_gen_shli_tl(t_ra, t_rs, sh);
1851    } else if (sh != 0 && me == 63 && sh == (64 - mb)) {
1852        tcg_gen_shri_tl(t_ra, t_rs, mb);
1853    } else {
1854        tcg_gen_rotli_tl(t_ra, t_rs, sh);
1855        tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
1856    }
1857    if (unlikely(Rc(ctx->opcode) != 0)) {
1858        gen_set_Rc0(ctx, t_ra);
1859    }
1860}
1861
1862/* rldicl - rldicl. */
1863static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1864{
1865    uint32_t sh, mb;
1866
1867    sh = SH(ctx->opcode) | (shn << 5);
1868    mb = MB(ctx->opcode) | (mbn << 5);
1869    gen_rldinm(ctx, mb, 63, sh);
1870}
1871GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1872
1873/* rldicr - rldicr. */
1874static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1875{
1876    uint32_t sh, me;
1877
1878    sh = SH(ctx->opcode) | (shn << 5);
1879    me = MB(ctx->opcode) | (men << 5);
1880    gen_rldinm(ctx, 0, me, sh);
1881}
1882GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1883
1884/* rldic - rldic. */
1885static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1886{
1887    uint32_t sh, mb;
1888
1889    sh = SH(ctx->opcode) | (shn << 5);
1890    mb = MB(ctx->opcode) | (mbn << 5);
1891    gen_rldinm(ctx, mb, 63 - sh, sh);
1892}
1893GEN_PPC64_R4(rldic, 0x1E, 0x04);
1894
1895static void gen_rldnm(DisasContext *ctx, int mb, int me)
1896{
1897    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1898    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1899    TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
1900    TCGv t0;
1901
1902    t0 = tcg_temp_new();
1903    tcg_gen_andi_tl(t0, t_rb, 0x3f);
1904    tcg_gen_rotl_tl(t_ra, t_rs, t0);
1905    tcg_temp_free(t0);
1906
1907    tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
1908    if (unlikely(Rc(ctx->opcode) != 0)) {
1909        gen_set_Rc0(ctx, t_ra);
1910    }
1911}
1912
1913/* rldcl - rldcl. */
1914static inline void gen_rldcl(DisasContext *ctx, int mbn)
1915{
1916    uint32_t mb;
1917
1918    mb = MB(ctx->opcode) | (mbn << 5);
1919    gen_rldnm(ctx, mb, 63);
1920}
1921GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1922
1923/* rldcr - rldcr. */
1924static inline void gen_rldcr(DisasContext *ctx, int men)
1925{
1926    uint32_t me;
1927
1928    me = MB(ctx->opcode) | (men << 5);
1929    gen_rldnm(ctx, 0, me);
1930}
1931GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1932
1933/* rldimi - rldimi. */
1934static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1935{
1936    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1937    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1938    uint32_t sh = SH(ctx->opcode) | (shn << 5);
1939    uint32_t mb = MB(ctx->opcode) | (mbn << 5);
1940    uint32_t me = 63 - sh;
1941
1942    if (mb <= me) {
1943        tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
1944    } else {
1945        target_ulong mask = MASK(mb, me);
1946        TCGv t1 = tcg_temp_new();
1947
1948        tcg_gen_rotli_tl(t1, t_rs, sh);
1949        tcg_gen_andi_tl(t1, t1, mask);
1950        tcg_gen_andi_tl(t_ra, t_ra, ~mask);
1951        tcg_gen_or_tl(t_ra, t_ra, t1);
1952        tcg_temp_free(t1);
1953    }
1954    if (unlikely(Rc(ctx->opcode) != 0)) {
1955        gen_set_Rc0(ctx, t_ra);
1956    }
1957}
1958GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1959#endif
1960
1961/***                             Integer shift                             ***/
1962
1963/* slw & slw. */
1964static void gen_slw(DisasContext *ctx)
1965{
1966    TCGv t0, t1;
1967
1968    t0 = tcg_temp_new();
1969    /* AND rS with a mask that is 0 when rB >= 0x20 */
1970#if defined(TARGET_PPC64)
1971    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1972    tcg_gen_sari_tl(t0, t0, 0x3f);
1973#else
1974    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1975    tcg_gen_sari_tl(t0, t0, 0x1f);
1976#endif
1977    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1978    t1 = tcg_temp_new();
1979    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1980    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1981    tcg_temp_free(t1);
1982    tcg_temp_free(t0);
1983    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1984    if (unlikely(Rc(ctx->opcode) != 0))
1985        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1986}
1987
1988/* sraw & sraw. */
1989static void gen_sraw(DisasContext *ctx)
1990{
1991    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
1992                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1993    if (unlikely(Rc(ctx->opcode) != 0))
1994        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1995}
1996
1997/* srawi & srawi. */
1998static void gen_srawi(DisasContext *ctx)
1999{
2000    int sh = SH(ctx->opcode);
2001    TCGv dst = cpu_gpr[rA(ctx->opcode)];
2002    TCGv src = cpu_gpr[rS(ctx->opcode)];
2003    if (sh == 0) {
2004        tcg_gen_ext32s_tl(dst, src);
2005        tcg_gen_movi_tl(cpu_ca, 0);
2006    } else {
2007        TCGv t0;
2008        tcg_gen_ext32s_tl(dst, src);
2009        tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
2010        t0 = tcg_temp_new();
2011        tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
2012        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2013        tcg_temp_free(t0);
2014        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2015        tcg_gen_sari_tl(dst, dst, sh);
2016    }
2017    if (unlikely(Rc(ctx->opcode) != 0)) {
2018        gen_set_Rc0(ctx, dst);
2019    }
2020}
2021
2022/* srw & srw. */
2023static void gen_srw(DisasContext *ctx)
2024{
2025    TCGv t0, t1;
2026
2027    t0 = tcg_temp_new();
2028    /* AND rS with a mask that is 0 when rB >= 0x20 */
2029#if defined(TARGET_PPC64)
2030    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2031    tcg_gen_sari_tl(t0, t0, 0x3f);
2032#else
2033    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2034    tcg_gen_sari_tl(t0, t0, 0x1f);
2035#endif
2036    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2037    tcg_gen_ext32u_tl(t0, t0);
2038    t1 = tcg_temp_new();
2039    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2040    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2041    tcg_temp_free(t1);
2042    tcg_temp_free(t0);
2043    if (unlikely(Rc(ctx->opcode) != 0))
2044        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2045}
2046
2047#if defined(TARGET_PPC64)
2048/* sld & sld. */
2049static void gen_sld(DisasContext *ctx)
2050{
2051    TCGv t0, t1;
2052
2053    t0 = tcg_temp_new();
2054    /* AND rS with a mask that is 0 when rB >= 0x40 */
2055    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2056    tcg_gen_sari_tl(t0, t0, 0x3f);
2057    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2058    t1 = tcg_temp_new();
2059    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2060    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2061    tcg_temp_free(t1);
2062    tcg_temp_free(t0);
2063    if (unlikely(Rc(ctx->opcode) != 0))
2064        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2065}
2066
2067/* srad & srad. */
2068static void gen_srad(DisasContext *ctx)
2069{
2070    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
2071                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2072    if (unlikely(Rc(ctx->opcode) != 0))
2073        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2074}
2075/* sradi & sradi. */
2076static inline void gen_sradi(DisasContext *ctx, int n)
2077{
2078    int sh = SH(ctx->opcode) + (n << 5);
2079    TCGv dst = cpu_gpr[rA(ctx->opcode)];
2080    TCGv src = cpu_gpr[rS(ctx->opcode)];
2081    if (sh == 0) {
2082        tcg_gen_mov_tl(dst, src);
2083        tcg_gen_movi_tl(cpu_ca, 0);
2084    } else {
2085        TCGv t0;
2086        tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
2087        t0 = tcg_temp_new();
2088        tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
2089        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2090        tcg_temp_free(t0);
2091        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2092        tcg_gen_sari_tl(dst, src, sh);
2093    }
2094    if (unlikely(Rc(ctx->opcode) != 0)) {
2095        gen_set_Rc0(ctx, dst);
2096    }
2097}
2098
2099static void gen_sradi0(DisasContext *ctx)
2100{
2101    gen_sradi(ctx, 0);
2102}
2103
2104static void gen_sradi1(DisasContext *ctx)
2105{
2106    gen_sradi(ctx, 1);
2107}
2108
2109/* srd & srd. */
2110static void gen_srd(DisasContext *ctx)
2111{
2112    TCGv t0, t1;
2113
2114    t0 = tcg_temp_new();
2115    /* AND rS with a mask that is 0 when rB >= 0x40 */
2116    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2117    tcg_gen_sari_tl(t0, t0, 0x3f);
2118    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2119    t1 = tcg_temp_new();
2120    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2121    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2122    tcg_temp_free(t1);
2123    tcg_temp_free(t0);
2124    if (unlikely(Rc(ctx->opcode) != 0))
2125        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2126}
2127#endif
2128
2129#if defined(TARGET_PPC64)
2130static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2131{
2132    TCGv_i32 tmp = tcg_temp_new_i32();
2133    tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
2134    tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
2135    tcg_temp_free_i32(tmp);
2136}
2137#else
2138static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2139{
2140    tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
2141}
2142#endif
2143
2144/***                       Floating-Point arithmetic                       ***/
2145#define _GEN_FLOAT_ACB(name, op, op1, op2, 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)], cpu_fpr[rB(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
2170#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
2171_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
2172_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2173
2174#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2175static void gen_f##name(DisasContext *ctx)                                    \
2176{                                                                             \
2177    if (unlikely(!ctx->fpu_enabled)) {                                        \
2178        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2179        return;                                                               \
2180    }                                                                         \
2181    /* NIP cannot be restored if the memory exception comes from an helper */ \
2182    gen_update_nip(ctx, ctx->nip - 4);                                        \
2183    gen_reset_fpstatus();                                                     \
2184    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
2185                     cpu_fpr[rA(ctx->opcode)],                                \
2186                     cpu_fpr[rB(ctx->opcode)]);                               \
2187    if (isfloat) {                                                            \
2188        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
2189                        cpu_fpr[rD(ctx->opcode)]);                            \
2190    }                                                                         \
2191    if (set_fprf) {                                                           \
2192        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2193    }                                                                         \
2194    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2195        gen_set_cr1_from_fpscr(ctx);                                          \
2196    }                                                                         \
2197}
2198#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2199_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2200_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2201
2202#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2203static void gen_f##name(DisasContext *ctx)                                    \
2204{                                                                             \
2205    if (unlikely(!ctx->fpu_enabled)) {                                        \
2206        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2207        return;                                                               \
2208    }                                                                         \
2209    /* NIP cannot be restored if the memory exception comes from an helper */ \
2210    gen_update_nip(ctx, ctx->nip - 4);                                        \
2211    gen_reset_fpstatus();                                                     \
2212    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
2213                     cpu_fpr[rA(ctx->opcode)],                                \
2214                     cpu_fpr[rC(ctx->opcode)]);                               \
2215    if (isfloat) {                                                            \
2216        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
2217                        cpu_fpr[rD(ctx->opcode)]);                            \
2218    }                                                                         \
2219    if (set_fprf) {                                                           \
2220        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2221    }                                                                         \
2222    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2223        gen_set_cr1_from_fpscr(ctx);                                          \
2224    }                                                                         \
2225}
2226#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2227_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2228_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2229
2230#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2231static void gen_f##name(DisasContext *ctx)                                    \
2232{                                                                             \
2233    if (unlikely(!ctx->fpu_enabled)) {                                        \
2234        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2235        return;                                                               \
2236    }                                                                         \
2237    /* NIP cannot be restored if the memory exception comes from an helper */ \
2238    gen_update_nip(ctx, ctx->nip - 4);                                        \
2239    gen_reset_fpstatus();                                                     \
2240    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
2241                       cpu_fpr[rB(ctx->opcode)]);                             \
2242    if (set_fprf) {                                                           \
2243        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2244    }                                                                         \
2245    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2246        gen_set_cr1_from_fpscr(ctx);                                          \
2247    }                                                                         \
2248}
2249
2250#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2251static void gen_f##name(DisasContext *ctx)                                    \
2252{                                                                             \
2253    if (unlikely(!ctx->fpu_enabled)) {                                        \
2254        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2255        return;                                                               \
2256    }                                                                         \
2257    /* NIP cannot be restored if the memory exception comes from an helper */ \
2258    gen_update_nip(ctx, ctx->nip - 4);                                        \
2259    gen_reset_fpstatus();                                                     \
2260    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
2261                       cpu_fpr[rB(ctx->opcode)]);                             \
2262    if (set_fprf) {                                                           \
2263        gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);                           \
2264    }                                                                         \
2265    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
2266        gen_set_cr1_from_fpscr(ctx);                                          \
2267    }                                                                         \
2268}
2269
2270/* fadd - fadds */
2271GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2272/* fdiv - fdivs */
2273GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2274/* fmul - fmuls */
2275GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2276
2277/* fre */
2278GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2279
2280/* fres */
2281GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2282
2283/* frsqrte */
2284GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2285
2286/* frsqrtes */
2287static void gen_frsqrtes(DisasContext *ctx)
2288{
2289    if (unlikely(!ctx->fpu_enabled)) {
2290        gen_exception(ctx, POWERPC_EXCP_FPU);
2291        return;
2292    }
2293    /* NIP cannot be restored if the memory exception comes from an helper */
2294    gen_update_nip(ctx, ctx->nip - 4);
2295    gen_reset_fpstatus();
2296    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
2297                       cpu_fpr[rB(ctx->opcode)]);
2298    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2299                    cpu_fpr[rD(ctx->opcode)]);
2300    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2301    if (unlikely(Rc(ctx->opcode) != 0)) {
2302        gen_set_cr1_from_fpscr(ctx);
2303    }
2304}
2305
2306/* fsel */
2307_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2308/* fsub - fsubs */
2309GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2310/* Optional: */
2311
2312/* fsqrt */
2313static void gen_fsqrt(DisasContext *ctx)
2314{
2315    if (unlikely(!ctx->fpu_enabled)) {
2316        gen_exception(ctx, POWERPC_EXCP_FPU);
2317        return;
2318    }
2319    /* NIP cannot be restored if the memory exception comes from an helper */
2320    gen_update_nip(ctx, ctx->nip - 4);
2321    gen_reset_fpstatus();
2322    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2323                     cpu_fpr[rB(ctx->opcode)]);
2324    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2325    if (unlikely(Rc(ctx->opcode) != 0)) {
2326        gen_set_cr1_from_fpscr(ctx);
2327    }
2328}
2329
2330static void gen_fsqrts(DisasContext *ctx)
2331{
2332    if (unlikely(!ctx->fpu_enabled)) {
2333        gen_exception(ctx, POWERPC_EXCP_FPU);
2334        return;
2335    }
2336    /* NIP cannot be restored if the memory exception comes from an helper */
2337    gen_update_nip(ctx, ctx->nip - 4);
2338    gen_reset_fpstatus();
2339    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2340                     cpu_fpr[rB(ctx->opcode)]);
2341    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2342                    cpu_fpr[rD(ctx->opcode)]);
2343    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
2344    if (unlikely(Rc(ctx->opcode) != 0)) {
2345        gen_set_cr1_from_fpscr(ctx);
2346    }
2347}
2348
2349/***                     Floating-Point multiply-and-add                   ***/
2350/* fmadd - fmadds */
2351GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2352/* fmsub - fmsubs */
2353GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2354/* fnmadd - fnmadds */
2355GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2356/* fnmsub - fnmsubs */
2357GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2358
2359/***                     Floating-Point round & convert                    ***/
2360/* fctiw */
2361GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2362/* fctiwu */
2363GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
2364/* fctiwz */
2365GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2366/* fctiwuz */
2367GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
2368/* frsp */
2369GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2370/* fcfid */
2371GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
2372/* fcfids */
2373GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
2374/* fcfidu */
2375GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
2376/* fcfidus */
2377GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
2378/* fctid */
2379GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
2380/* fctidu */
2381GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
2382/* fctidz */
2383GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
2384/* fctidu */
2385GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
2386
2387/* frin */
2388GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2389/* friz */
2390GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2391/* frip */
2392GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2393/* frim */
2394GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2395
2396static void gen_ftdiv(DisasContext *ctx)
2397{
2398    if (unlikely(!ctx->fpu_enabled)) {
2399        gen_exception(ctx, POWERPC_EXCP_FPU);
2400        return;
2401    }
2402    gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2403                     cpu_fpr[rB(ctx->opcode)]);
2404}
2405
2406static void gen_ftsqrt(DisasContext *ctx)
2407{
2408    if (unlikely(!ctx->fpu_enabled)) {
2409        gen_exception(ctx, POWERPC_EXCP_FPU);
2410        return;
2411    }
2412    gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2413}
2414
2415
2416
2417/***                         Floating-Point compare                        ***/
2418
2419/* fcmpo */
2420static void gen_fcmpo(DisasContext *ctx)
2421{
2422    TCGv_i32 crf;
2423    if (unlikely(!ctx->fpu_enabled)) {
2424        gen_exception(ctx, POWERPC_EXCP_FPU);
2425        return;
2426    }
2427    /* NIP cannot be restored if the memory exception comes from an helper */
2428    gen_update_nip(ctx, ctx->nip - 4);
2429    gen_reset_fpstatus();
2430    crf = tcg_const_i32(crfD(ctx->opcode));
2431    gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
2432                     cpu_fpr[rB(ctx->opcode)], crf);
2433    tcg_temp_free_i32(crf);
2434    gen_helper_float_check_status(cpu_env);
2435}
2436
2437/* fcmpu */
2438static void gen_fcmpu(DisasContext *ctx)
2439{
2440    TCGv_i32 crf;
2441    if (unlikely(!ctx->fpu_enabled)) {
2442        gen_exception(ctx, POWERPC_EXCP_FPU);
2443        return;
2444    }
2445    /* NIP cannot be restored if the memory exception comes from an helper */
2446    gen_update_nip(ctx, ctx->nip - 4);
2447    gen_reset_fpstatus();
2448    crf = tcg_const_i32(crfD(ctx->opcode));
2449    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
2450                     cpu_fpr[rB(ctx->opcode)], crf);
2451    tcg_temp_free_i32(crf);
2452    gen_helper_float_check_status(cpu_env);
2453}
2454
2455/***                         Floating-point move                           ***/
2456/* fabs */
2457/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2458static void gen_fabs(DisasContext *ctx)
2459{
2460    if (unlikely(!ctx->fpu_enabled)) {
2461        gen_exception(ctx, POWERPC_EXCP_FPU);
2462        return;
2463    }
2464    tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2465                     ~(1ULL << 63));
2466    if (unlikely(Rc(ctx->opcode))) {
2467        gen_set_cr1_from_fpscr(ctx);
2468    }
2469}
2470
2471/* fmr  - fmr. */
2472/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2473static void gen_fmr(DisasContext *ctx)
2474{
2475    if (unlikely(!ctx->fpu_enabled)) {
2476        gen_exception(ctx, POWERPC_EXCP_FPU);
2477        return;
2478    }
2479    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2480    if (unlikely(Rc(ctx->opcode))) {
2481        gen_set_cr1_from_fpscr(ctx);
2482    }
2483}
2484
2485/* fnabs */
2486/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2487static void gen_fnabs(DisasContext *ctx)
2488{
2489    if (unlikely(!ctx->fpu_enabled)) {
2490        gen_exception(ctx, POWERPC_EXCP_FPU);
2491        return;
2492    }
2493    tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2494                    1ULL << 63);
2495    if (unlikely(Rc(ctx->opcode))) {
2496        gen_set_cr1_from_fpscr(ctx);
2497    }
2498}
2499
2500/* fneg */
2501/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2502static void gen_fneg(DisasContext *ctx)
2503{
2504    if (unlikely(!ctx->fpu_enabled)) {
2505        gen_exception(ctx, POWERPC_EXCP_FPU);
2506        return;
2507    }
2508    tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2509                     1ULL << 63);
2510    if (unlikely(Rc(ctx->opcode))) {
2511        gen_set_cr1_from_fpscr(ctx);
2512    }
2513}
2514
2515/* fcpsgn: PowerPC 2.05 specification */
2516/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
2517static void gen_fcpsgn(DisasContext *ctx)
2518{
2519    if (unlikely(!ctx->fpu_enabled)) {
2520        gen_exception(ctx, POWERPC_EXCP_FPU);
2521        return;
2522    }
2523    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2524                        cpu_fpr[rB(ctx->opcode)], 0, 63);
2525    if (unlikely(Rc(ctx->opcode))) {
2526        gen_set_cr1_from_fpscr(ctx);
2527    }
2528}
2529
2530static void gen_fmrgew(DisasContext *ctx)
2531{
2532    TCGv_i64 b0;
2533    if (unlikely(!ctx->fpu_enabled)) {
2534        gen_exception(ctx, POWERPC_EXCP_FPU);
2535        return;
2536    }
2537    b0 = tcg_temp_new_i64();
2538    tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
2539    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2540                        b0, 0, 32);
2541    tcg_temp_free_i64(b0);
2542}
2543
2544static void gen_fmrgow(DisasContext *ctx)
2545{
2546    if (unlikely(!ctx->fpu_enabled)) {
2547        gen_exception(ctx, POWERPC_EXCP_FPU);
2548        return;
2549    }
2550    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
2551                        cpu_fpr[rB(ctx->opcode)],
2552                        cpu_fpr[rA(ctx->opcode)],
2553                        32, 32);
2554}
2555
2556/***                  Floating-Point status & ctrl register                ***/
2557
2558/* mcrfs */
2559static void gen_mcrfs(DisasContext *ctx)
2560{
2561    TCGv tmp = tcg_temp_new();
2562    TCGv_i32 tmask;
2563    TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
2564    int bfa;
2565    int nibble;
2566    int shift;
2567
2568    if (unlikely(!ctx->fpu_enabled)) {
2569        gen_exception(ctx, POWERPC_EXCP_FPU);
2570        return;
2571    }
2572    bfa = crfS(ctx->opcode);
2573    nibble = 7 - bfa;
2574    shift = 4 * nibble;
2575    tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
2576    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
2577    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2578    tcg_temp_free(tmp);
2579    tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
2580    /* Only the exception bits (including FX) should be cleared if read */
2581    tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS));
2582    /* FEX and VX need to be updated, so don't set fpscr directly */
2583    tmask = tcg_const_i32(1 << nibble);
2584    gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
2585    tcg_temp_free_i32(tmask);
2586    tcg_temp_free_i64(tnew_fpscr);
2587}
2588
2589/* mffs */
2590static void gen_mffs(DisasContext *ctx)
2591{
2592    if (unlikely(!ctx->fpu_enabled)) {
2593        gen_exception(ctx, POWERPC_EXCP_FPU);
2594        return;
2595    }
2596    gen_reset_fpstatus();
2597    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2598    if (unlikely(Rc(ctx->opcode))) {
2599        gen_set_cr1_from_fpscr(ctx);
2600    }
2601}
2602
2603/* mtfsb0 */
2604static void gen_mtfsb0(DisasContext *ctx)
2605{
2606    uint8_t crb;
2607
2608    if (unlikely(!ctx->fpu_enabled)) {
2609        gen_exception(ctx, POWERPC_EXCP_FPU);
2610        return;
2611    }
2612    crb = 31 - crbD(ctx->opcode);
2613    gen_reset_fpstatus();
2614    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2615        TCGv_i32 t0;
2616        /* NIP cannot be restored if the memory exception comes from an helper */
2617        gen_update_nip(ctx, ctx->nip - 4);
2618        t0 = tcg_const_i32(crb);
2619        gen_helper_fpscr_clrbit(cpu_env, t0);
2620        tcg_temp_free_i32(t0);
2621    }
2622    if (unlikely(Rc(ctx->opcode) != 0)) {
2623        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2624        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2625    }
2626}
2627
2628/* mtfsb1 */
2629static void gen_mtfsb1(DisasContext *ctx)
2630{
2631    uint8_t crb;
2632
2633    if (unlikely(!ctx->fpu_enabled)) {
2634        gen_exception(ctx, POWERPC_EXCP_FPU);
2635        return;
2636    }
2637    crb = 31 - crbD(ctx->opcode);
2638    gen_reset_fpstatus();
2639    /* XXX: we pretend we can only do IEEE floating-point computations */
2640    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2641        TCGv_i32 t0;
2642        /* NIP cannot be restored if the memory exception comes from an helper */
2643        gen_update_nip(ctx, ctx->nip - 4);
2644        t0 = tcg_const_i32(crb);
2645        gen_helper_fpscr_setbit(cpu_env, t0);
2646        tcg_temp_free_i32(t0);
2647    }
2648    if (unlikely(Rc(ctx->opcode) != 0)) {
2649        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2650        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2651    }
2652    /* We can raise a differed exception */
2653    gen_helper_float_check_status(cpu_env);
2654}
2655
2656/* mtfsf */
2657static void gen_mtfsf(DisasContext *ctx)
2658{
2659    TCGv_i32 t0;
2660    int flm, l, w;
2661
2662    if (unlikely(!ctx->fpu_enabled)) {
2663        gen_exception(ctx, POWERPC_EXCP_FPU);
2664        return;
2665    }
2666    flm = FPFLM(ctx->opcode);
2667    l = FPL(ctx->opcode);
2668    w = FPW(ctx->opcode);
2669    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2670        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2671        return;
2672    }
2673    /* NIP cannot be restored if the memory exception comes from an helper */
2674    gen_update_nip(ctx, ctx->nip - 4);
2675    gen_reset_fpstatus();
2676    if (l) {
2677        t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
2678    } else {
2679        t0 = tcg_const_i32(flm << (w * 8));
2680    }
2681    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2682    tcg_temp_free_i32(t0);
2683    if (unlikely(Rc(ctx->opcode) != 0)) {
2684        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2685        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2686    }
2687    /* We can raise a differed exception */
2688    gen_helper_float_check_status(cpu_env);
2689}
2690
2691/* mtfsfi */
2692static void gen_mtfsfi(DisasContext *ctx)
2693{
2694    int bf, sh, w;
2695    TCGv_i64 t0;
2696    TCGv_i32 t1;
2697
2698    if (unlikely(!ctx->fpu_enabled)) {
2699        gen_exception(ctx, POWERPC_EXCP_FPU);
2700        return;
2701    }
2702    w = FPW(ctx->opcode);
2703    bf = FPBF(ctx->opcode);
2704    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2705        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2706        return;
2707    }
2708    sh = (8 * w) + 7 - bf;
2709    /* NIP cannot be restored if the memory exception comes from an helper */
2710    gen_update_nip(ctx, ctx->nip - 4);
2711    gen_reset_fpstatus();
2712    t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
2713    t1 = tcg_const_i32(1 << sh);
2714    gen_helper_store_fpscr(cpu_env, t0, t1);
2715    tcg_temp_free_i64(t0);
2716    tcg_temp_free_i32(t1);
2717    if (unlikely(Rc(ctx->opcode) != 0)) {
2718        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2719        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2720    }
2721    /* We can raise a differed exception */
2722    gen_helper_float_check_status(cpu_env);
2723}
2724
2725/***                           Addressing modes                            ***/
2726/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2727static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2728                                      target_long maskl)
2729{
2730    target_long simm = SIMM(ctx->opcode);
2731
2732    simm &= ~maskl;
2733    if (rA(ctx->opcode) == 0) {
2734        if (NARROW_MODE(ctx)) {
2735            simm = (uint32_t)simm;
2736        }
2737        tcg_gen_movi_tl(EA, simm);
2738    } else if (likely(simm != 0)) {
2739        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2740        if (NARROW_MODE(ctx)) {
2741            tcg_gen_ext32u_tl(EA, EA);
2742        }
2743    } else {
2744        if (NARROW_MODE(ctx)) {
2745            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2746        } else {
2747            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2748        }
2749    }
2750}
2751
2752static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2753{
2754    if (rA(ctx->opcode) == 0) {
2755        if (NARROW_MODE(ctx)) {
2756            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2757        } else {
2758            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2759        }
2760    } else {
2761        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2762        if (NARROW_MODE(ctx)) {
2763            tcg_gen_ext32u_tl(EA, EA);
2764        }
2765    }
2766}
2767
2768static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2769{
2770    if (rA(ctx->opcode) == 0) {
2771        tcg_gen_movi_tl(EA, 0);
2772    } else if (NARROW_MODE(ctx)) {
2773        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2774    } else {
2775        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2776    }
2777}
2778
2779static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2780                                target_long val)
2781{
2782    tcg_gen_addi_tl(ret, arg1, val);
2783    if (NARROW_MODE(ctx)) {
2784        tcg_gen_ext32u_tl(ret, ret);
2785    }
2786}
2787
2788static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2789{
2790    TCGLabel *l1 = gen_new_label();
2791    TCGv t0 = tcg_temp_new();
2792    TCGv_i32 t1, t2;
2793    /* NIP cannot be restored if the memory exception comes from an helper */
2794    gen_update_nip(ctx, ctx->nip - 4);
2795    tcg_gen_andi_tl(t0, EA, mask);
2796    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2797    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2798    t2 = tcg_const_i32(0);
2799    gen_helper_raise_exception_err(cpu_env, t1, t2);
2800    tcg_temp_free_i32(t1);
2801    tcg_temp_free_i32(t2);
2802    gen_set_label(l1);
2803    tcg_temp_free(t0);
2804}
2805
2806/***                             Integer load                              ***/
2807static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2808{
2809    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2810}
2811
2812static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2813{
2814    TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2815    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2816}
2817
2818static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2819{
2820    TCGMemOp op = MO_SW | ctx->default_tcg_memop_mask;
2821    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2822}
2823
2824static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2825{
2826    TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2827    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2828}
2829
2830static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2831{
2832    TCGv tmp = tcg_temp_new();
2833    gen_qemu_ld32u(ctx, tmp, addr);
2834    tcg_gen_extu_tl_i64(val, tmp);
2835    tcg_temp_free(tmp);
2836}
2837
2838static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2839{
2840    TCGMemOp op = MO_SL | ctx->default_tcg_memop_mask;
2841    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
2842}
2843
2844static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2845{
2846    TCGv tmp = tcg_temp_new();
2847    gen_qemu_ld32s(ctx, tmp, addr);
2848    tcg_gen_ext_tl_i64(val, tmp);
2849    tcg_temp_free(tmp);
2850}
2851
2852static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2853{
2854    TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2855    tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
2856}
2857
2858static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2859{
2860    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2861}
2862
2863static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2864{
2865    TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2866    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
2867}
2868
2869static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2870{
2871    TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2872    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
2873}
2874
2875static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2876{
2877    TCGv tmp = tcg_temp_new();
2878    tcg_gen_trunc_i64_tl(tmp, val);
2879    gen_qemu_st32(ctx, tmp, addr);
2880    tcg_temp_free(tmp);
2881}
2882
2883static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2884{
2885    TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2886    tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
2887}
2888
2889#define GEN_LD(name, ldop, opc, type)                                         \
2890static void glue(gen_, name)(DisasContext *ctx)                                       \
2891{                                                                             \
2892    TCGv EA;                                                                  \
2893    gen_set_access_type(ctx, ACCESS_INT);                                     \
2894    EA = tcg_temp_new();                                                      \
2895    gen_addr_imm_index(ctx, EA, 0);                                           \
2896    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2897    tcg_temp_free(EA);                                                        \
2898}
2899
2900#define GEN_LDU(name, ldop, opc, type)                                        \
2901static void glue(gen_, name##u)(DisasContext *ctx)                                    \
2902{                                                                             \
2903    TCGv EA;                                                                  \
2904    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2905                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2906        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2907        return;                                                               \
2908    }                                                                         \
2909    gen_set_access_type(ctx, ACCESS_INT);                                     \
2910    EA = tcg_temp_new();                                                      \
2911    if (type == PPC_64B)                                                      \
2912        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2913    else                                                                      \
2914        gen_addr_imm_index(ctx, EA, 0);                                       \
2915    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2916    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2917    tcg_temp_free(EA);                                                        \
2918}
2919
2920#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2921static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2922{                                                                             \
2923    TCGv EA;                                                                  \
2924    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2925                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2926        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2927        return;                                                               \
2928    }                                                                         \
2929    gen_set_access_type(ctx, ACCESS_INT);                                     \
2930    EA = tcg_temp_new();                                                      \
2931    gen_addr_reg_index(ctx, EA);                                              \
2932    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2933    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2934    tcg_temp_free(EA);                                                        \
2935}
2936
2937#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk)                   \
2938static void glue(gen_, name##x)(DisasContext *ctx)                            \
2939{                                                                             \
2940    TCGv EA;                                                                  \
2941    chk;                                                                      \
2942    gen_set_access_type(ctx, ACCESS_INT);                                     \
2943    EA = tcg_temp_new();                                                      \
2944    gen_addr_reg_index(ctx, EA);                                              \
2945    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2946    tcg_temp_free(EA);                                                        \
2947}
2948
2949#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2950    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_NONE)
2951
2952#define GEN_LDX_HVRM(name, ldop, opc2, opc3, type)                            \
2953    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
2954
2955#define GEN_LDS(name, ldop, op, type)                                         \
2956GEN_LD(name, ldop, op | 0x20, type);                                          \
2957GEN_LDU(name, ldop, op | 0x21, type);                                         \
2958GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2959GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2960
2961/* lbz lbzu lbzux lbzx */
2962GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2963/* lha lhau lhaux lhax */
2964GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2965/* lhz lhzu lhzux lhzx */
2966GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2967/* lwz lwzu lwzux lwzx */
2968GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2969#if defined(TARGET_PPC64)
2970/* lwaux */
2971GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2972/* lwax */
2973GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2974/* ldux */
2975GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2976/* ldx */
2977GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2978
2979/* CI load/store variants */
2980GEN_LDX_HVRM(ldcix, ld64, 0x15, 0x1b, PPC_CILDST)
2981GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST)
2982GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
2983GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
2984
2985static void gen_ld(DisasContext *ctx)
2986{
2987    TCGv EA;
2988    if (Rc(ctx->opcode)) {
2989        if (unlikely(rA(ctx->opcode) == 0 ||
2990                     rA(ctx->opcode) == rD(ctx->opcode))) {
2991            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2992            return;
2993        }
2994    }
2995    gen_set_access_type(ctx, ACCESS_INT);
2996    EA = tcg_temp_new();
2997    gen_addr_imm_index(ctx, EA, 0x03);
2998    if (ctx->opcode & 0x02) {
2999        /* lwa (lwau is undefined) */
3000        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
3001    } else {
3002        /* ld - ldu */
3003        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
3004    }
3005    if (Rc(ctx->opcode))
3006        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
3007    tcg_temp_free(EA);
3008}
3009
3010/* lq */
3011static void gen_lq(DisasContext *ctx)
3012{
3013    int ra, rd;
3014    TCGv EA;
3015
3016    /* lq is a legal user mode instruction starting in ISA 2.07 */
3017    bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3018    bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3019
3020    if (!legal_in_user_mode && ctx->pr) {
3021        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3022        return;
3023    }
3024
3025    if (!le_is_supported && ctx->le_mode) {
3026        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
3027        return;
3028    }
3029
3030    ra = rA(ctx->opcode);
3031    rd = rD(ctx->opcode);
3032    if (unlikely((rd & 1) || rd == ra)) {
3033        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3034        return;
3035    }
3036
3037    gen_set_access_type(ctx, ACCESS_INT);
3038    EA = tcg_temp_new();
3039    gen_addr_imm_index(ctx, EA, 0x0F);
3040
3041    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3042       64-bit byteswap already. */
3043    if (unlikely(ctx->le_mode)) {
3044        gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
3045        gen_addr_add(ctx, EA, EA, 8);
3046        gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
3047    } else {
3048        gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
3049        gen_addr_add(ctx, EA, EA, 8);
3050        gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
3051    }
3052    tcg_temp_free(EA);
3053}
3054#endif
3055
3056/***                              Integer store                            ***/
3057#define GEN_ST(name, stop, opc, type)                                         \
3058static void glue(gen_, name)(DisasContext *ctx)                                       \
3059{                                                                             \
3060    TCGv EA;                                                                  \
3061    gen_set_access_type(ctx, ACCESS_INT);                                     \
3062    EA = tcg_temp_new();                                                      \
3063    gen_addr_imm_index(ctx, EA, 0);                                           \
3064    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3065    tcg_temp_free(EA);                                                        \
3066}
3067
3068#define GEN_STU(name, stop, opc, type)                                        \
3069static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
3070{                                                                             \
3071    TCGv EA;                                                                  \
3072    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3073        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3074        return;                                                               \
3075    }                                                                         \
3076    gen_set_access_type(ctx, ACCESS_INT);                                     \
3077    EA = tcg_temp_new();                                                      \
3078    if (type == PPC_64B)                                                      \
3079        gen_addr_imm_index(ctx, EA, 0x03);                                    \
3080    else                                                                      \
3081        gen_addr_imm_index(ctx, EA, 0);                                       \
3082    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3083    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3084    tcg_temp_free(EA);                                                        \
3085}
3086
3087#define GEN_STUX(name, stop, opc2, opc3, type)                                \
3088static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3089{                                                                             \
3090    TCGv EA;                                                                  \
3091    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3092        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3093        return;                                                               \
3094    }                                                                         \
3095    gen_set_access_type(ctx, ACCESS_INT);                                     \
3096    EA = tcg_temp_new();                                                      \
3097    gen_addr_reg_index(ctx, EA);                                              \
3098    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3099    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3100    tcg_temp_free(EA);                                                        \
3101}
3102
3103#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk)                   \
3104static void glue(gen_, name##x)(DisasContext *ctx)                            \
3105{                                                                             \
3106    TCGv EA;                                                                  \
3107    chk;                                                                      \
3108    gen_set_access_type(ctx, ACCESS_INT);                                     \
3109    EA = tcg_temp_new();                                                      \
3110    gen_addr_reg_index(ctx, EA);                                              \
3111    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
3112    tcg_temp_free(EA);                                                        \
3113}
3114#define GEN_STX(name, stop, opc2, opc3, type)                                 \
3115    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_NONE)
3116
3117#define GEN_STX_HVRM(name, stop, opc2, opc3, type)                            \
3118    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
3119
3120#define GEN_STS(name, stop, op, type)                                         \
3121GEN_ST(name, stop, op | 0x20, type);                                          \
3122GEN_STU(name, stop, op | 0x21, type);                                         \
3123GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
3124GEN_STX(name, stop, 0x17, op | 0x00, type)
3125
3126/* stb stbu stbux stbx */
3127GEN_STS(stb, st8, 0x06, PPC_INTEGER);
3128/* sth sthu sthux sthx */
3129GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
3130/* stw stwu stwux stwx */
3131GEN_STS(stw, st32, 0x04, PPC_INTEGER);
3132#if defined(TARGET_PPC64)
3133GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
3134GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
3135GEN_STX_HVRM(stdcix, st64, 0x15, 0x1f, PPC_CILDST)
3136GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
3137GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
3138GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
3139
3140static void gen_std(DisasContext *ctx)
3141{
3142    int rs;
3143    TCGv EA;
3144
3145    rs = rS(ctx->opcode);
3146    if ((ctx->opcode & 0x3) == 0x2) { /* stq */
3147        bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3148        bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3149
3150        if (!(ctx->insns_flags & PPC_64BX)) {
3151            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3152        }
3153
3154        if (!legal_in_user_mode && ctx->pr) {
3155            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3156            return;
3157        }
3158
3159        if (!le_is_supported && ctx->le_mode) {
3160            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
3161            return;
3162        }
3163
3164        if (unlikely(rs & 1)) {
3165            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3166            return;
3167        }
3168        gen_set_access_type(ctx, ACCESS_INT);
3169        EA = tcg_temp_new();
3170        gen_addr_imm_index(ctx, EA, 0x03);
3171
3172        /* We only need to swap high and low halves. gen_qemu_st64 does
3173           necessary 64-bit byteswap already. */
3174        if (unlikely(ctx->le_mode)) {
3175            gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3176            gen_addr_add(ctx, EA, EA, 8);
3177            gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3178        } else {
3179            gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3180            gen_addr_add(ctx, EA, EA, 8);
3181            gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3182        }
3183        tcg_temp_free(EA);
3184    } else {
3185        /* std / stdu*/
3186        if (Rc(ctx->opcode)) {
3187            if (unlikely(rA(ctx->opcode) == 0)) {
3188                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3189                return;
3190            }
3191        }
3192        gen_set_access_type(ctx, ACCESS_INT);
3193        EA = tcg_temp_new();
3194        gen_addr_imm_index(ctx, EA, 0x03);
3195        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3196        if (Rc(ctx->opcode))
3197            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
3198        tcg_temp_free(EA);
3199    }
3200}
3201#endif
3202/***                Integer load and store with byte reverse               ***/
3203
3204/* lhbrx */
3205static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3206{
3207    TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3208    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
3209}
3210GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
3211
3212/* lwbrx */
3213static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3214{
3215    TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3216    tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
3217}
3218GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
3219
3220#if defined(TARGET_PPC64)
3221/* ldbrx */
3222static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3223{
3224    TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3225    tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
3226}
3227GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
3228#endif  /* TARGET_PPC64 */
3229
3230/* sthbrx */
3231static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3232{
3233    TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3234    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
3235}
3236GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
3237
3238/* stwbrx */
3239static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3240{
3241    TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3242    tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
3243}
3244GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
3245
3246#if defined(TARGET_PPC64)
3247/* stdbrx */
3248static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3249{
3250    TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3251    tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
3252}
3253GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
3254#endif  /* TARGET_PPC64 */
3255
3256/***                    Integer load and store multiple                    ***/
3257
3258/* lmw */
3259static void gen_lmw(DisasContext *ctx)
3260{
3261    TCGv t0;
3262    TCGv_i32 t1;
3263    gen_set_access_type(ctx, ACCESS_INT);
3264    /* NIP cannot be restored if the memory exception comes from an helper */
3265    gen_update_nip(ctx, ctx->nip - 4);
3266    t0 = tcg_temp_new();
3267    t1 = tcg_const_i32(rD(ctx->opcode));
3268    gen_addr_imm_index(ctx, t0, 0);
3269    gen_helper_lmw(cpu_env, t0, t1);
3270    tcg_temp_free(t0);
3271    tcg_temp_free_i32(t1);
3272}
3273
3274/* stmw */
3275static void gen_stmw(DisasContext *ctx)
3276{
3277    TCGv t0;
3278    TCGv_i32 t1;
3279    gen_set_access_type(ctx, ACCESS_INT);
3280    /* NIP cannot be restored if the memory exception comes from an helper */
3281    gen_update_nip(ctx, ctx->nip - 4);
3282    t0 = tcg_temp_new();
3283    t1 = tcg_const_i32(rS(ctx->opcode));
3284    gen_addr_imm_index(ctx, t0, 0);
3285    gen_helper_stmw(cpu_env, t0, t1);
3286    tcg_temp_free(t0);
3287    tcg_temp_free_i32(t1);
3288}
3289
3290/***                    Integer load and store strings                     ***/
3291
3292/* lswi */
3293/* PowerPC32 specification says we must generate an exception if
3294 * rA is in the range of registers to be loaded.
3295 * In an other hand, IBM says this is valid, but rA won't be loaded.
3296 * For now, I'll follow the spec...
3297 */
3298static void gen_lswi(DisasContext *ctx)
3299{
3300    TCGv t0;
3301    TCGv_i32 t1, t2;
3302    int nb = NB(ctx->opcode);
3303    int start = rD(ctx->opcode);
3304    int ra = rA(ctx->opcode);
3305    int nr;
3306
3307    if (nb == 0)
3308        nb = 32;
3309    nr = (nb + 3) / 4;
3310    if (unlikely(lsw_reg_in_range(start, nr, ra))) {
3311        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3312        return;
3313    }
3314    gen_set_access_type(ctx, ACCESS_INT);
3315    /* NIP cannot be restored if the memory exception comes from an helper */
3316    gen_update_nip(ctx, ctx->nip - 4);
3317    t0 = tcg_temp_new();
3318    gen_addr_register(ctx, t0);
3319    t1 = tcg_const_i32(nb);
3320    t2 = tcg_const_i32(start);
3321    gen_helper_lsw(cpu_env, t0, t1, t2);
3322    tcg_temp_free(t0);
3323    tcg_temp_free_i32(t1);
3324    tcg_temp_free_i32(t2);
3325}
3326
3327/* lswx */
3328static void gen_lswx(DisasContext *ctx)
3329{
3330    TCGv t0;
3331    TCGv_i32 t1, t2, t3;
3332    gen_set_access_type(ctx, ACCESS_INT);
3333    /* NIP cannot be restored if the memory exception comes from an helper */
3334    gen_update_nip(ctx, ctx->nip - 4);
3335    t0 = tcg_temp_new();
3336    gen_addr_reg_index(ctx, t0);
3337    t1 = tcg_const_i32(rD(ctx->opcode));
3338    t2 = tcg_const_i32(rA(ctx->opcode));
3339    t3 = tcg_const_i32(rB(ctx->opcode));
3340    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3341    tcg_temp_free(t0);
3342    tcg_temp_free_i32(t1);
3343    tcg_temp_free_i32(t2);
3344    tcg_temp_free_i32(t3);
3345}
3346
3347/* stswi */
3348static void gen_stswi(DisasContext *ctx)
3349{
3350    TCGv t0;
3351    TCGv_i32 t1, t2;
3352    int nb = NB(ctx->opcode);
3353    gen_set_access_type(ctx, ACCESS_INT);
3354    /* NIP cannot be restored if the memory exception comes from an helper */
3355    gen_update_nip(ctx, ctx->nip - 4);
3356    t0 = tcg_temp_new();
3357    gen_addr_register(ctx, t0);
3358    if (nb == 0)
3359        nb = 32;
3360    t1 = tcg_const_i32(nb);
3361    t2 = tcg_const_i32(rS(ctx->opcode));
3362    gen_helper_stsw(cpu_env, t0, t1, t2);
3363    tcg_temp_free(t0);
3364    tcg_temp_free_i32(t1);
3365    tcg_temp_free_i32(t2);
3366}
3367
3368/* stswx */
3369static void gen_stswx(DisasContext *ctx)
3370{
3371    TCGv t0;
3372    TCGv_i32 t1, t2;
3373    gen_set_access_type(ctx, ACCESS_INT);
3374    /* NIP cannot be restored if the memory exception comes from an helper */
3375    gen_update_nip(ctx, ctx->nip - 4);
3376    t0 = tcg_temp_new();
3377    gen_addr_reg_index(ctx, t0);
3378    t1 = tcg_temp_new_i32();
3379    tcg_gen_trunc_tl_i32(t1, cpu_xer);
3380    tcg_gen_andi_i32(t1, t1, 0x7F);
3381    t2 = tcg_const_i32(rS(ctx->opcode));
3382    gen_helper_stsw(cpu_env, t0, t1, t2);
3383    tcg_temp_free(t0);
3384    tcg_temp_free_i32(t1);
3385    tcg_temp_free_i32(t2);
3386}
3387
3388/***                        Memory synchronisation                         ***/
3389/* eieio */
3390static void gen_eieio(DisasContext *ctx)
3391{
3392}
3393
3394#if !defined(CONFIG_USER_ONLY)
3395static inline void gen_check_tlb_flush(DisasContext *ctx)
3396{
3397    TCGv_i32 t;
3398    TCGLabel *l;
3399
3400    if (!ctx->lazy_tlb_flush) {
3401        return;
3402    }
3403    l = gen_new_label();
3404    t = tcg_temp_new_i32();
3405    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
3406    tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
3407    gen_helper_check_tlb_flush(cpu_env);
3408    gen_set_label(l);
3409    tcg_temp_free_i32(t);
3410}
3411#else
3412static inline void gen_check_tlb_flush(DisasContext *ctx) { }
3413#endif
3414
3415/* isync */
3416static void gen_isync(DisasContext *ctx)
3417{
3418    /*
3419     * We need to check for a pending TLB flush. This can only happen in
3420     * kernel mode however so check MSR_PR
3421     */
3422    if (!ctx->pr) {
3423        gen_check_tlb_flush(ctx);
3424    }
3425    gen_stop_exception(ctx);
3426}
3427
3428#define LARX(name, len, loadop)                                      \
3429static void gen_##name(DisasContext *ctx)                            \
3430{                                                                    \
3431    TCGv t0;                                                         \
3432    TCGv gpr = cpu_gpr[rD(ctx->opcode)];                             \
3433    gen_set_access_type(ctx, ACCESS_RES);                            \
3434    t0 = tcg_temp_local_new();                                       \
3435    gen_addr_reg_index(ctx, t0);                                     \
3436    if ((len) > 1) {                                                 \
3437        gen_check_align(ctx, t0, (len)-1);                           \
3438    }                                                                \
3439    gen_qemu_##loadop(ctx, gpr, t0);                                 \
3440    tcg_gen_mov_tl(cpu_reserve, t0);                                 \
3441    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \
3442    tcg_temp_free(t0);                                               \
3443}
3444
3445/* lwarx */
3446LARX(lbarx, 1, ld8u);
3447LARX(lharx, 2, ld16u);
3448LARX(lwarx, 4, ld32u);
3449
3450
3451#if defined(CONFIG_USER_ONLY)
3452static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3453                                  int reg, int size)
3454{
3455    TCGv t0 = tcg_temp_new();
3456    uint32_t save_exception = ctx->exception;
3457
3458    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3459    tcg_gen_movi_tl(t0, (size << 5) | reg);
3460    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3461    tcg_temp_free(t0);
3462    gen_update_nip(ctx, ctx->nip-4);
3463    ctx->exception = POWERPC_EXCP_BRANCH;
3464    gen_exception(ctx, POWERPC_EXCP_STCX);
3465    ctx->exception = save_exception;
3466}
3467#else
3468static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3469                                  int reg, int size)
3470{
3471    TCGLabel *l1;
3472
3473    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3474    l1 = gen_new_label();
3475    tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
3476    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3477#if defined(TARGET_PPC64)
3478    if (size == 8) {
3479        gen_qemu_st64(ctx, cpu_gpr[reg], EA);
3480    } else
3481#endif
3482    if (size == 4) {
3483        gen_qemu_st32(ctx, cpu_gpr[reg], EA);
3484    } else if (size == 2) {
3485        gen_qemu_st16(ctx, cpu_gpr[reg], EA);
3486#if defined(TARGET_PPC64)
3487    } else if (size == 16) {
3488        TCGv gpr1, gpr2 , EA8;
3489        if (unlikely(ctx->le_mode)) {
3490            gpr1 = cpu_gpr[reg+1];
3491            gpr2 = cpu_gpr[reg];
3492        } else {
3493            gpr1 = cpu_gpr[reg];
3494            gpr2 = cpu_gpr[reg+1];
3495        }
3496        gen_qemu_st64(ctx, gpr1, EA);
3497        EA8 = tcg_temp_local_new();
3498        gen_addr_add(ctx, EA8, EA, 8);
3499        gen_qemu_st64(ctx, gpr2, EA8);
3500        tcg_temp_free(EA8);
3501#endif
3502    } else {
3503        gen_qemu_st8(ctx, cpu_gpr[reg], EA);
3504    }
3505    gen_set_label(l1);
3506    tcg_gen_movi_tl(cpu_reserve, -1);
3507}
3508#endif
3509
3510#define STCX(name, len)                                   \
3511static void gen_##name(DisasContext *ctx)                 \
3512{                                                         \
3513    TCGv t0;                                              \
3514    if (unlikely((len == 16) && (rD(ctx->opcode) & 1))) { \
3515        gen_inval_exception(ctx,                          \
3516                            POWERPC_EXCP_INVAL_INVAL);    \
3517        return;                                           \
3518    }                                                     \
3519    gen_set_access_type(ctx, ACCESS_RES);                 \
3520    t0 = tcg_temp_local_new();                            \
3521    gen_addr_reg_index(ctx, t0);                          \
3522    if (len > 1) {                                        \
3523        gen_check_align(ctx, t0, (len)-1);                \
3524    }                                                     \
3525    gen_conditional_store(ctx, t0, rS(ctx->opcode), len); \
3526    tcg_temp_free(t0);                                    \
3527}
3528
3529STCX(stbcx_, 1);
3530STCX(sthcx_, 2);
3531STCX(stwcx_, 4);
3532
3533#if defined(TARGET_PPC64)
3534/* ldarx */
3535LARX(ldarx, 8, ld64);
3536
3537/* lqarx */
3538static void gen_lqarx(DisasContext *ctx)
3539{
3540    TCGv EA;
3541    int rd = rD(ctx->opcode);
3542    TCGv gpr1, gpr2;
3543
3544    if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
3545                 (rd == rB(ctx->opcode)))) {
3546        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3547        return;
3548    }
3549
3550    gen_set_access_type(ctx, ACCESS_RES);
3551    EA = tcg_temp_local_new();
3552    gen_addr_reg_index(ctx, EA);
3553    gen_check_align(ctx, EA, 15);
3554    if (unlikely(ctx->le_mode)) {
3555        gpr1 = cpu_gpr[rd+1];
3556        gpr2 = cpu_gpr[rd];
3557    } else {
3558        gpr1 = cpu_gpr[rd];
3559        gpr2 = cpu_gpr[rd+1];
3560    }
3561    gen_qemu_ld64(ctx, gpr1, EA);
3562    tcg_gen_mov_tl(cpu_reserve, EA);
3563
3564    gen_addr_add(ctx, EA, EA, 8);
3565    gen_qemu_ld64(ctx, gpr2, EA);
3566
3567    tcg_gen_st_tl(gpr1, cpu_env, offsetof(CPUPPCState, reserve_val));
3568    tcg_gen_st_tl(gpr2, cpu_env, offsetof(CPUPPCState, reserve_val2));
3569
3570    tcg_temp_free(EA);
3571}
3572
3573/* stdcx. */
3574STCX(stdcx_, 8);
3575STCX(stqcx_, 16);
3576#endif /* defined(TARGET_PPC64) */
3577
3578/* sync */
3579static void gen_sync(DisasContext *ctx)
3580{
3581    uint32_t l = (ctx->opcode >> 21) & 3;
3582
3583    /*
3584     * We may need to check for a pending TLB flush.
3585     *
3586     * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
3587     *
3588     * Additionally, this can only happen in kernel mode however so
3589     * check MSR_PR as well.
3590     */
3591    if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
3592        gen_check_tlb_flush(ctx);
3593    }
3594}
3595
3596/* wait */
3597static void gen_wait(DisasContext *ctx)
3598{
3599    TCGv_i32 t0 = tcg_const_i32(1);
3600    tcg_gen_st_i32(t0, cpu_env,
3601                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3602    tcg_temp_free_i32(t0);
3603    /* Stop translation, as the CPU is supposed to sleep from now */
3604    gen_exception_err(ctx, EXCP_HLT, 1);
3605}
3606
3607#if defined(TARGET_PPC64)
3608static void gen_doze(DisasContext *ctx)
3609{
3610#if defined(CONFIG_USER_ONLY)
3611    GEN_PRIV;
3612#else
3613    TCGv_i32 t;
3614
3615    CHK_HV;
3616    t = tcg_const_i32(PPC_PM_DOZE);
3617    gen_helper_pminsn(cpu_env, t);
3618    tcg_temp_free_i32(t);
3619    gen_stop_exception(ctx);
3620#endif /* defined(CONFIG_USER_ONLY) */
3621}
3622
3623static void gen_nap(DisasContext *ctx)
3624{
3625#if defined(CONFIG_USER_ONLY)
3626    GEN_PRIV;
3627#else
3628    TCGv_i32 t;
3629
3630    CHK_HV;
3631    t = tcg_const_i32(PPC_PM_NAP);
3632    gen_helper_pminsn(cpu_env, t);
3633    tcg_temp_free_i32(t);
3634    gen_stop_exception(ctx);
3635#endif /* defined(CONFIG_USER_ONLY) */
3636}
3637
3638static void gen_sleep(DisasContext *ctx)
3639{
3640#if defined(CONFIG_USER_ONLY)
3641    GEN_PRIV;
3642#else
3643    TCGv_i32 t;
3644
3645    CHK_HV;
3646    t = tcg_const_i32(PPC_PM_SLEEP);
3647    gen_helper_pminsn(cpu_env, t);
3648    tcg_temp_free_i32(t);
3649    gen_stop_exception(ctx);
3650#endif /* defined(CONFIG_USER_ONLY) */
3651}
3652
3653static void gen_rvwinkle(DisasContext *ctx)
3654{
3655#if defined(CONFIG_USER_ONLY)
3656    GEN_PRIV;
3657#else
3658    TCGv_i32 t;
3659
3660    CHK_HV;
3661    t = tcg_const_i32(PPC_PM_RVWINKLE);
3662    gen_helper_pminsn(cpu_env, t);
3663    tcg_temp_free_i32(t);
3664    gen_stop_exception(ctx);
3665#endif /* defined(CONFIG_USER_ONLY) */
3666}
3667#endif /* #if defined(TARGET_PPC64) */
3668
3669/***                         Floating-point load                           ***/
3670#define GEN_LDF(name, ldop, opc, type)                                        \
3671static void glue(gen_, name)(DisasContext *ctx)                                       \
3672{                                                                             \
3673    TCGv EA;                                                                  \
3674    if (unlikely(!ctx->fpu_enabled)) {                                        \
3675        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3676        return;                                                               \
3677    }                                                                         \
3678    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3679    EA = tcg_temp_new();                                                      \
3680    gen_addr_imm_index(ctx, EA, 0);                                           \
3681    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3682    tcg_temp_free(EA);                                                        \
3683}
3684
3685#define GEN_LDUF(name, ldop, opc, type)                                       \
3686static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3687{                                                                             \
3688    TCGv EA;                                                                  \
3689    if (unlikely(!ctx->fpu_enabled)) {                                        \
3690        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3691        return;                                                               \
3692    }                                                                         \
3693    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3694        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3695        return;                                                               \
3696    }                                                                         \
3697    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3698    EA = tcg_temp_new();                                                      \
3699    gen_addr_imm_index(ctx, EA, 0);                                           \
3700    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3701    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3702    tcg_temp_free(EA);                                                        \
3703}
3704
3705#define GEN_LDUXF(name, ldop, opc, type)                                      \
3706static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3707{                                                                             \
3708    TCGv EA;                                                                  \
3709    if (unlikely(!ctx->fpu_enabled)) {                                        \
3710        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3711        return;                                                               \
3712    }                                                                         \
3713    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3714        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3715        return;                                                               \
3716    }                                                                         \
3717    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3718    EA = tcg_temp_new();                                                      \
3719    gen_addr_reg_index(ctx, EA);                                              \
3720    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3721    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3722    tcg_temp_free(EA);                                                        \
3723}
3724
3725#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3726static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3727{                                                                             \
3728    TCGv EA;                                                                  \
3729    if (unlikely(!ctx->fpu_enabled)) {                                        \
3730        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3731        return;                                                               \
3732    }                                                                         \
3733    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3734    EA = tcg_temp_new();                                                      \
3735    gen_addr_reg_index(ctx, EA);                                              \
3736    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3737    tcg_temp_free(EA);                                                        \
3738}
3739
3740#define GEN_LDFS(name, ldop, op, type)                                        \
3741GEN_LDF(name, ldop, op | 0x20, type);                                         \
3742GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3743GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3744GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3745
3746static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3747{
3748    TCGv t0 = tcg_temp_new();
3749    TCGv_i32 t1 = tcg_temp_new_i32();
3750    gen_qemu_ld32u(ctx, t0, arg2);
3751    tcg_gen_trunc_tl_i32(t1, t0);
3752    tcg_temp_free(t0);
3753    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3754    tcg_temp_free_i32(t1);
3755}
3756
3757 /* lfd lfdu lfdux lfdx */
3758GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3759 /* lfs lfsu lfsux lfsx */
3760GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3761
3762/* lfdp */
3763static void gen_lfdp(DisasContext *ctx)
3764{
3765    TCGv EA;
3766    if (unlikely(!ctx->fpu_enabled)) {
3767        gen_exception(ctx, POWERPC_EXCP_FPU);
3768        return;
3769    }
3770    gen_set_access_type(ctx, ACCESS_FLOAT);
3771    EA = tcg_temp_new();
3772    gen_addr_imm_index(ctx, EA, 0);
3773    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3774       64-bit byteswap already. */
3775    if (unlikely(ctx->le_mode)) {
3776        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3777        tcg_gen_addi_tl(EA, EA, 8);
3778        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3779    } else {
3780        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3781        tcg_gen_addi_tl(EA, EA, 8);
3782        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3783    }
3784    tcg_temp_free(EA);
3785}
3786
3787/* lfdpx */
3788static void gen_lfdpx(DisasContext *ctx)
3789{
3790    TCGv EA;
3791    if (unlikely(!ctx->fpu_enabled)) {
3792        gen_exception(ctx, POWERPC_EXCP_FPU);
3793        return;
3794    }
3795    gen_set_access_type(ctx, ACCESS_FLOAT);
3796    EA = tcg_temp_new();
3797    gen_addr_reg_index(ctx, EA);
3798    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3799       64-bit byteswap already. */
3800    if (unlikely(ctx->le_mode)) {
3801        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3802        tcg_gen_addi_tl(EA, EA, 8);
3803        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3804    } else {
3805        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3806        tcg_gen_addi_tl(EA, EA, 8);
3807        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3808    }
3809    tcg_temp_free(EA);
3810}
3811
3812/* lfiwax */
3813static void gen_lfiwax(DisasContext *ctx)
3814{
3815    TCGv EA;
3816    TCGv t0;
3817    if (unlikely(!ctx->fpu_enabled)) {
3818        gen_exception(ctx, POWERPC_EXCP_FPU);
3819        return;
3820    }
3821    gen_set_access_type(ctx, ACCESS_FLOAT);
3822    EA = tcg_temp_new();
3823    t0 = tcg_temp_new();
3824    gen_addr_reg_index(ctx, EA);
3825    gen_qemu_ld32s(ctx, t0, EA);
3826    tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
3827    tcg_temp_free(EA);
3828    tcg_temp_free(t0);
3829}
3830
3831/* lfiwzx */
3832static void gen_lfiwzx(DisasContext *ctx)
3833{
3834    TCGv EA;
3835    if (unlikely(!ctx->fpu_enabled)) {
3836        gen_exception(ctx, POWERPC_EXCP_FPU);
3837        return;
3838    }
3839    gen_set_access_type(ctx, ACCESS_FLOAT);
3840    EA = tcg_temp_new();
3841    gen_addr_reg_index(ctx, EA);
3842    gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3843    tcg_temp_free(EA);
3844}
3845/***                         Floating-point store                          ***/
3846#define GEN_STF(name, stop, opc, type)                                        \
3847static void glue(gen_, name)(DisasContext *ctx)                                       \
3848{                                                                             \
3849    TCGv EA;                                                                  \
3850    if (unlikely(!ctx->fpu_enabled)) {                                        \
3851        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3852        return;                                                               \
3853    }                                                                         \
3854    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3855    EA = tcg_temp_new();                                                      \
3856    gen_addr_imm_index(ctx, EA, 0);                                           \
3857    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3858    tcg_temp_free(EA);                                                        \
3859}
3860
3861#define GEN_STUF(name, stop, opc, type)                                       \
3862static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3863{                                                                             \
3864    TCGv EA;                                                                  \
3865    if (unlikely(!ctx->fpu_enabled)) {                                        \
3866        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3867        return;                                                               \
3868    }                                                                         \
3869    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3870        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3871        return;                                                               \
3872    }                                                                         \
3873    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3874    EA = tcg_temp_new();                                                      \
3875    gen_addr_imm_index(ctx, EA, 0);                                           \
3876    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3877    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3878    tcg_temp_free(EA);                                                        \
3879}
3880
3881#define GEN_STUXF(name, stop, opc, type)                                      \
3882static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3883{                                                                             \
3884    TCGv EA;                                                                  \
3885    if (unlikely(!ctx->fpu_enabled)) {                                        \
3886        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3887        return;                                                               \
3888    }                                                                         \
3889    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3890        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3891        return;                                                               \
3892    }                                                                         \
3893    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3894    EA = tcg_temp_new();                                                      \
3895    gen_addr_reg_index(ctx, EA);                                              \
3896    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3897    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3898    tcg_temp_free(EA);                                                        \
3899}
3900
3901#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3902static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3903{                                                                             \
3904    TCGv EA;                                                                  \
3905    if (unlikely(!ctx->fpu_enabled)) {                                        \
3906        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3907        return;                                                               \
3908    }                                                                         \
3909    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3910    EA = tcg_temp_new();                                                      \
3911    gen_addr_reg_index(ctx, EA);                                              \
3912    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3913    tcg_temp_free(EA);                                                        \
3914}
3915
3916#define GEN_STFS(name, stop, op, type)                                        \
3917GEN_STF(name, stop, op | 0x20, type);                                         \
3918GEN_STUF(name, stop, op | 0x21, type);                                        \
3919GEN_STUXF(name, stop, op | 0x01, type);                                       \
3920GEN_STXF(name, stop, 0x17, op | 0x00, type)
3921
3922static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3923{
3924    TCGv_i32 t0 = tcg_temp_new_i32();
3925    TCGv t1 = tcg_temp_new();
3926    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3927    tcg_gen_extu_i32_tl(t1, t0);
3928    tcg_temp_free_i32(t0);
3929    gen_qemu_st32(ctx, t1, arg2);
3930    tcg_temp_free(t1);
3931}
3932
3933/* stfd stfdu stfdux stfdx */
3934GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3935/* stfs stfsu stfsux stfsx */
3936GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3937
3938/* stfdp */
3939static void gen_stfdp(DisasContext *ctx)
3940{
3941    TCGv EA;
3942    if (unlikely(!ctx->fpu_enabled)) {
3943        gen_exception(ctx, POWERPC_EXCP_FPU);
3944        return;
3945    }
3946    gen_set_access_type(ctx, ACCESS_FLOAT);
3947    EA = tcg_temp_new();
3948    gen_addr_imm_index(ctx, EA, 0);
3949    /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3950       64-bit byteswap already. */
3951    if (unlikely(ctx->le_mode)) {
3952        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3953        tcg_gen_addi_tl(EA, EA, 8);
3954        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3955    } else {
3956        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3957        tcg_gen_addi_tl(EA, EA, 8);
3958        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3959    }
3960    tcg_temp_free(EA);
3961}
3962
3963/* stfdpx */
3964static void gen_stfdpx(DisasContext *ctx)
3965{
3966    TCGv EA;
3967    if (unlikely(!ctx->fpu_enabled)) {
3968        gen_exception(ctx, POWERPC_EXCP_FPU);
3969        return;
3970    }
3971    gen_set_access_type(ctx, ACCESS_FLOAT);
3972    EA = tcg_temp_new();
3973    gen_addr_reg_index(ctx, EA);
3974    /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3975       64-bit byteswap already. */
3976    if (unlikely(ctx->le_mode)) {
3977        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3978        tcg_gen_addi_tl(EA, EA, 8);
3979        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3980    } else {
3981        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3982        tcg_gen_addi_tl(EA, EA, 8);
3983        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3984    }
3985    tcg_temp_free(EA);
3986}
3987
3988/* Optional: */
3989static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3990{
3991    TCGv t0 = tcg_temp_new();
3992    tcg_gen_trunc_i64_tl(t0, arg1),
3993    gen_qemu_st32(ctx, t0, arg2);
3994    tcg_temp_free(t0);
3995}
3996/* stfiwx */
3997GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3998
3999static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
4000{
4001#if defined(TARGET_PPC64)
4002    if (ctx->has_cfar)
4003        tcg_gen_movi_tl(cpu_cfar, nip);
4004#endif
4005}
4006
4007static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4008{
4009    if (unlikely(ctx->singlestep_enabled)) {
4010        return false;
4011    }
4012
4013#ifndef CONFIG_USER_ONLY
4014    return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4015#else
4016    return true;
4017#endif
4018}
4019
4020/***                                Branch                                 ***/
4021static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4022{
4023    if (NARROW_MODE(ctx)) {
4024        dest = (uint32_t) dest;
4025    }
4026    if (use_goto_tb(ctx, dest)) {
4027        tcg_gen_goto_tb(n);
4028        tcg_gen_movi_tl(cpu_nip, dest & ~3);
4029        tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4030    } else {
4031        tcg_gen_movi_tl(cpu_nip, dest & ~3);
4032        if (unlikely(ctx->singlestep_enabled)) {
4033            if ((ctx->singlestep_enabled &
4034                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
4035                (ctx->exception == POWERPC_EXCP_BRANCH ||
4036                 ctx->exception == POWERPC_EXCP_TRACE)) {
4037                target_ulong tmp = ctx->nip;
4038                ctx->nip = dest;
4039                gen_exception(ctx, POWERPC_EXCP_TRACE);
4040                ctx->nip = tmp;
4041            }
4042            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
4043                gen_debug_exception(ctx);
4044            }
4045        }
4046        tcg_gen_exit_tb(0);
4047    }
4048}
4049
4050static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
4051{
4052    if (NARROW_MODE(ctx)) {
4053        nip = (uint32_t)nip;
4054    }
4055    tcg_gen_movi_tl(cpu_lr, nip);
4056}
4057
4058/* b ba bl bla */
4059static void gen_b(DisasContext *ctx)
4060{
4061    target_ulong li, target;
4062
4063    ctx->exception = POWERPC_EXCP_BRANCH;
4064    /* sign extend LI */
4065    li = LI(ctx->opcode);
4066    li = (li ^ 0x02000000) - 0x02000000;
4067    if (likely(AA(ctx->opcode) == 0)) {
4068        target = ctx->nip + li - 4;
4069    } else {
4070        target = li;
4071    }
4072    if (LK(ctx->opcode)) {
4073        gen_setlr(ctx, ctx->nip);
4074    }
4075    gen_update_cfar(ctx, ctx->nip);
4076    gen_goto_tb(ctx, 0, target);
4077}
4078
4079#define BCOND_IM  0
4080#define BCOND_LR  1
4081#define BCOND_CTR 2
4082#define BCOND_TAR 3
4083
4084static inline void gen_bcond(DisasContext *ctx, int type)
4085{
4086    uint32_t bo = BO(ctx->opcode);
4087    TCGLabel *l1;
4088    TCGv target;
4089
4090    ctx->exception = POWERPC_EXCP_BRANCH;
4091    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
4092        target = tcg_temp_local_new();
4093        if (type == BCOND_CTR)
4094            tcg_gen_mov_tl(target, cpu_ctr);
4095        else if (type == BCOND_TAR)
4096            gen_load_spr(target, SPR_TAR);
4097        else
4098            tcg_gen_mov_tl(target, cpu_lr);
4099    } else {
4100        TCGV_UNUSED(target);
4101    }
4102    if (LK(ctx->opcode))
4103        gen_setlr(ctx, ctx->nip);
4104    l1 = gen_new_label();
4105    if ((bo & 0x4) == 0) {
4106        /* Decrement and test CTR */
4107        TCGv temp = tcg_temp_new();
4108        if (unlikely(type == BCOND_CTR)) {
4109            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4110            return;
4111        }
4112        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
4113        if (NARROW_MODE(ctx)) {
4114            tcg_gen_ext32u_tl(temp, cpu_ctr);
4115        } else {
4116            tcg_gen_mov_tl(temp, cpu_ctr);
4117        }
4118        if (bo & 0x2) {
4119            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4120        } else {
4121            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
4122        }
4123        tcg_temp_free(temp);
4124    }
4125    if ((bo & 0x10) == 0) {
4126        /* Test CR */
4127        uint32_t bi = BI(ctx->opcode);
4128        uint32_t mask = 0x08 >> (bi & 0x03);
4129        TCGv_i32 temp = tcg_temp_new_i32();
4130
4131        if (bo & 0x8) {
4132            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4133            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
4134        } else {
4135            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4136            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
4137        }
4138        tcg_temp_free_i32(temp);
4139    }
4140    gen_update_cfar(ctx, ctx->nip);
4141    if (type == BCOND_IM) {
4142        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
4143        if (likely(AA(ctx->opcode) == 0)) {
4144            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
4145        } else {
4146            gen_goto_tb(ctx, 0, li);
4147        }
4148        gen_set_label(l1);
4149        gen_goto_tb(ctx, 1, ctx->nip);
4150    } else {
4151        if (NARROW_MODE(ctx)) {
4152            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
4153        } else {
4154            tcg_gen_andi_tl(cpu_nip, target, ~3);
4155        }
4156        tcg_gen_exit_tb(0);
4157        gen_set_label(l1);
4158        gen_update_nip(ctx, ctx->nip);
4159        tcg_gen_exit_tb(0);
4160    }
4161    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
4162        tcg_temp_free(target);
4163    }
4164}
4165
4166static void gen_bc(DisasContext *ctx)
4167{
4168    gen_bcond(ctx, BCOND_IM);
4169}
4170
4171static void gen_bcctr(DisasContext *ctx)
4172{
4173    gen_bcond(ctx, BCOND_CTR);
4174}
4175
4176static void gen_bclr(DisasContext *ctx)
4177{
4178    gen_bcond(ctx, BCOND_LR);
4179}
4180
4181static void gen_bctar(DisasContext *ctx)
4182{
4183    gen_bcond(ctx, BCOND_TAR);
4184}
4185
4186/***                      Condition register logical                       ***/
4187#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
4188static void glue(gen_, name)(DisasContext *ctx)                                       \
4189{                                                                             \
4190    uint8_t bitmask;                                                          \
4191    int sh;                                                                   \
4192    TCGv_i32 t0, t1;                                                          \
4193    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
4194    t0 = tcg_temp_new_i32();                                                  \
4195    if (sh > 0)                                                               \
4196        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
4197    else if (sh < 0)                                                          \
4198        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
4199    else                                                                      \
4200        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
4201    t1 = tcg_temp_new_i32();                                                  \
4202    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
4203    if (sh > 0)                                                               \
4204        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
4205    else if (sh < 0)                                                          \
4206        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
4207    else                                                                      \
4208        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
4209    tcg_op(t0, t0, t1);                                                       \
4210    bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03);                             \
4211    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
4212    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
4213    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
4214    tcg_temp_free_i32(t0);                                                    \
4215    tcg_temp_free_i32(t1);                                                    \
4216}
4217
4218/* crand */
4219GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
4220/* crandc */
4221GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
4222/* creqv */
4223GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
4224/* crnand */
4225GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
4226/* crnor */
4227GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
4228/* cror */
4229GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
4230/* crorc */
4231GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
4232/* crxor */
4233GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
4234
4235/* mcrf */
4236static void gen_mcrf(DisasContext *ctx)
4237{
4238    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
4239}
4240
4241/***                           System linkage                              ***/
4242
4243/* rfi (supervisor only) */
4244static void gen_rfi(DisasContext *ctx)
4245{
4246#if defined(CONFIG_USER_ONLY)
4247    GEN_PRIV;
4248#else
4249    /* FIXME: This instruction doesn't exist anymore on 64-bit server
4250     * processors compliant with arch 2.x, we should remove it there,
4251     * but we need to fix OpenBIOS not to use it on 970 first
4252     */
4253    /* Restore CPU state */
4254    CHK_SV;
4255    gen_update_cfar(ctx, ctx->nip);
4256    gen_helper_rfi(cpu_env);
4257    gen_sync_exception(ctx);
4258#endif
4259}
4260
4261#if defined(TARGET_PPC64)
4262static void gen_rfid(DisasContext *ctx)
4263{
4264#if defined(CONFIG_USER_ONLY)
4265    GEN_PRIV;
4266#else
4267    /* Restore CPU state */
4268    CHK_SV;
4269    gen_update_cfar(ctx, ctx->nip);
4270    gen_helper_rfid(cpu_env);
4271    gen_sync_exception(ctx);
4272#endif
4273}
4274
4275static void gen_hrfid(DisasContext *ctx)
4276{
4277#if defined(CONFIG_USER_ONLY)
4278    GEN_PRIV;
4279#else
4280    /* Restore CPU state */
4281    CHK_HV;
4282    gen_helper_hrfid(cpu_env);
4283    gen_sync_exception(ctx);
4284#endif
4285}
4286#endif
4287
4288/* sc */
4289#if defined(CONFIG_USER_ONLY)
4290#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
4291#else
4292#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
4293#endif
4294static void gen_sc(DisasContext *ctx)
4295{
4296    uint32_t lev;
4297
4298    lev = (ctx->opcode >> 5) & 0x7F;
4299    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
4300}
4301
4302/***                                Trap                                   ***/
4303
4304/* tw */
4305static void gen_tw(DisasContext *ctx)
4306{
4307    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
4308    /* Update the nip since this might generate a trap exception */
4309    gen_update_nip(ctx, ctx->nip);
4310    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4311                  t0);
4312    tcg_temp_free_i32(t0);
4313}
4314
4315/* twi */
4316static void gen_twi(DisasContext *ctx)
4317{
4318    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4319    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
4320    /* Update the nip since this might generate a trap exception */
4321    gen_update_nip(ctx, ctx->nip);
4322    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4323    tcg_temp_free(t0);
4324    tcg_temp_free_i32(t1);
4325}
4326
4327#if defined(TARGET_PPC64)
4328/* td */
4329static void gen_td(DisasContext *ctx)
4330{
4331    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
4332    /* Update the nip since this might generate a trap exception */
4333    gen_update_nip(ctx, ctx->nip);
4334    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4335                  t0);
4336    tcg_temp_free_i32(t0);
4337}
4338
4339/* tdi */
4340static void gen_tdi(DisasContext *ctx)
4341{
4342    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4343    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
4344    /* Update the nip since this might generate a trap exception */
4345    gen_update_nip(ctx, ctx->nip);
4346    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
4347    tcg_temp_free(t0);
4348    tcg_temp_free_i32(t1);
4349}
4350#endif
4351
4352/***                          Processor control                            ***/
4353
4354static void gen_read_xer(TCGv dst)
4355{
4356    TCGv t0 = tcg_temp_new();
4357    TCGv t1 = tcg_temp_new();
4358    TCGv t2 = tcg_temp_new();
4359    tcg_gen_mov_tl(dst, cpu_xer);
4360    tcg_gen_shli_tl(t0, cpu_so, XER_SO);
4361    tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
4362    tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
4363    tcg_gen_or_tl(t0, t0, t1);
4364    tcg_gen_or_tl(dst, dst, t2);
4365    tcg_gen_or_tl(dst, dst, t0);
4366    tcg_temp_free(t0);
4367    tcg_temp_free(t1);
4368    tcg_temp_free(t2);
4369}
4370
4371static void gen_write_xer(TCGv src)
4372{
4373    tcg_gen_andi_tl(cpu_xer, src,
4374                    ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
4375    tcg_gen_shri_tl(cpu_so, src, XER_SO);
4376    tcg_gen_shri_tl(cpu_ov, src, XER_OV);
4377    tcg_gen_shri_tl(cpu_ca, src, XER_CA);
4378    tcg_gen_andi_tl(cpu_so, cpu_so, 1);
4379    tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
4380    tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
4381}
4382
4383/* mcrxr */
4384static void gen_mcrxr(DisasContext *ctx)
4385{
4386    TCGv_i32 t0 = tcg_temp_new_i32();
4387    TCGv_i32 t1 = tcg_temp_new_i32();
4388    TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4389
4390    tcg_gen_trunc_tl_i32(t0, cpu_so);
4391    tcg_gen_trunc_tl_i32(t1, cpu_ov);
4392    tcg_gen_trunc_tl_i32(dst, cpu_ca);
4393    tcg_gen_shli_i32(t0, t0, 3);
4394    tcg_gen_shli_i32(t1, t1, 2);
4395    tcg_gen_shli_i32(dst, dst, 1);
4396    tcg_gen_or_i32(dst, dst, t0);
4397    tcg_gen_or_i32(dst, dst, t1);
4398    tcg_temp_free_i32(t0);
4399    tcg_temp_free_i32(t1);
4400
4401    tcg_gen_movi_tl(cpu_so, 0);
4402    tcg_gen_movi_tl(cpu_ov, 0);
4403    tcg_gen_movi_tl(cpu_ca, 0);
4404}
4405
4406/* mfcr mfocrf */
4407static void gen_mfcr(DisasContext *ctx)
4408{
4409    uint32_t crm, crn;
4410
4411    if (likely(ctx->opcode & 0x00100000)) {
4412        crm = CRM(ctx->opcode);
4413        if (likely(crm && ((crm & (crm - 1)) == 0))) {
4414            crn = ctz32 (crm);
4415            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
4416            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
4417                            cpu_gpr[rD(ctx->opcode)], crn * 4);
4418        }
4419    } else {
4420        TCGv_i32 t0 = tcg_temp_new_i32();
4421        tcg_gen_mov_i32(t0, cpu_crf[0]);
4422        tcg_gen_shli_i32(t0, t0, 4);
4423        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
4424        tcg_gen_shli_i32(t0, t0, 4);
4425        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
4426        tcg_gen_shli_i32(t0, t0, 4);
4427        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
4428        tcg_gen_shli_i32(t0, t0, 4);
4429        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
4430        tcg_gen_shli_i32(t0, t0, 4);
4431        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
4432        tcg_gen_shli_i32(t0, t0, 4);
4433        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
4434        tcg_gen_shli_i32(t0, t0, 4);
4435        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
4436        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
4437        tcg_temp_free_i32(t0);
4438    }
4439}
4440
4441/* mfmsr */
4442static void gen_mfmsr(DisasContext *ctx)
4443{
4444    CHK_SV;
4445    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
4446}
4447
4448static void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
4449{
4450#if 0
4451    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
4452    printf("ERROR: try to access SPR %d !\n", sprn);
4453#endif
4454}
4455#define SPR_NOACCESS (&spr_noaccess)
4456
4457/* mfspr */
4458static inline void gen_op_mfspr(DisasContext *ctx)
4459{
4460    void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
4461    uint32_t sprn = SPR(ctx->opcode);
4462
4463#if defined(CONFIG_USER_ONLY)
4464    read_cb = ctx->spr_cb[sprn].uea_read;
4465#else
4466    if (ctx->pr) {
4467        read_cb = ctx->spr_cb[sprn].uea_read;
4468    } else if (ctx->hv) {
4469        read_cb = ctx->spr_cb[sprn].hea_read;
4470    } else {
4471        read_cb = ctx->spr_cb[sprn].oea_read;
4472    }
4473#endif
4474    if (likely(read_cb != NULL)) {
4475        if (likely(read_cb != SPR_NOACCESS)) {
4476            (*read_cb)(ctx, rD(ctx->opcode), sprn);
4477        } else {
4478            /* Privilege exception */
4479            /* This is a hack to avoid warnings when running Linux:
4480             * this OS breaks the PowerPC virtualisation model,
4481             * allowing userland application to read the PVR
4482             */
4483            if (sprn != SPR_PVR) {
4484                fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at "
4485                        TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4486                if (qemu_log_separate()) {
4487                    qemu_log("Trying to read privileged spr %d (0x%03x) at "
4488                             TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4489                }
4490            }
4491            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4492        }
4493    } else {
4494        /* ISA 2.07 defines these as no-ops */
4495        if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4496            (sprn >= 808 && sprn <= 811)) {
4497            /* This is a nop */
4498            return;
4499        }
4500        /* Not defined */
4501        fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at "
4502                TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4503        if (qemu_log_separate()) {
4504            qemu_log("Trying to read invalid spr %d (0x%03x) at "
4505                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4506        }
4507
4508        /* The behaviour depends on MSR:PR and SPR# bit 0x10,
4509         * it can generate a priv, a hv emu or a no-op
4510         */
4511        if (sprn & 0x10) {
4512            if (ctx->pr) {
4513                gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4514            }
4515        } else {
4516            if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) {
4517                gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4518            }
4519        }
4520    }
4521}
4522
4523static void gen_mfspr(DisasContext *ctx)
4524{
4525    gen_op_mfspr(ctx);
4526}
4527
4528/* mftb */
4529static void gen_mftb(DisasContext *ctx)
4530{
4531    gen_op_mfspr(ctx);
4532}
4533
4534/* mtcrf mtocrf*/
4535static void gen_mtcrf(DisasContext *ctx)
4536{
4537    uint32_t crm, crn;
4538
4539    crm = CRM(ctx->opcode);
4540    if (likely((ctx->opcode & 0x00100000))) {
4541        if (crm && ((crm & (crm - 1)) == 0)) {
4542            TCGv_i32 temp = tcg_temp_new_i32();
4543            crn = ctz32 (crm);
4544            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4545            tcg_gen_shri_i32(temp, temp, crn * 4);
4546            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
4547            tcg_temp_free_i32(temp);
4548        }
4549    } else {
4550        TCGv_i32 temp = tcg_temp_new_i32();
4551        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4552        for (crn = 0 ; crn < 8 ; crn++) {
4553            if (crm & (1 << crn)) {
4554                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4555                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4556            }
4557        }
4558        tcg_temp_free_i32(temp);
4559    }
4560}
4561
4562/* mtmsr */
4563#if defined(TARGET_PPC64)
4564static void gen_mtmsrd(DisasContext *ctx)
4565{
4566    CHK_SV;
4567
4568#if !defined(CONFIG_USER_ONLY)
4569    if (ctx->opcode & 0x00010000) {
4570        /* Special form that does not need any synchronisation */
4571        TCGv t0 = tcg_temp_new();
4572        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4573        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
4574        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4575        tcg_temp_free(t0);
4576    } else {
4577        /* XXX: we need to update nip before the store
4578         *      if we enter power saving mode, we will exit the loop
4579         *      directly from ppc_store_msr
4580         */
4581        gen_update_nip(ctx, ctx->nip);
4582        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
4583        /* Must stop the translation as machine state (may have) changed */
4584        /* Note that mtmsr is not always defined as context-synchronizing */
4585        gen_stop_exception(ctx);
4586    }
4587#endif /* !defined(CONFIG_USER_ONLY) */
4588}
4589#endif /* defined(TARGET_PPC64) */
4590
4591static void gen_mtmsr(DisasContext *ctx)
4592{
4593    CHK_SV;
4594
4595#if !defined(CONFIG_USER_ONLY)
4596   if (ctx->opcode & 0x00010000) {
4597        /* Special form that does not need any synchronisation */
4598        TCGv t0 = tcg_temp_new();
4599        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4600        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
4601        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4602        tcg_temp_free(t0);
4603    } else {
4604        TCGv msr = tcg_temp_new();
4605
4606        /* XXX: we need to update nip before the store
4607         *      if we enter power saving mode, we will exit the loop
4608         *      directly from ppc_store_msr
4609         */
4610        gen_update_nip(ctx, ctx->nip);
4611#if defined(TARGET_PPC64)
4612        tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
4613#else
4614        tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
4615#endif
4616        gen_helper_store_msr(cpu_env, msr);
4617        tcg_temp_free(msr);
4618        /* Must stop the translation as machine state (may have) changed */
4619        /* Note that mtmsr is not always defined as context-synchronizing */
4620        gen_stop_exception(ctx);
4621    }
4622#endif
4623}
4624
4625/* mtspr */
4626static void gen_mtspr(DisasContext *ctx)
4627{
4628    void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
4629    uint32_t sprn = SPR(ctx->opcode);
4630
4631#if defined(CONFIG_USER_ONLY)
4632    write_cb = ctx->spr_cb[sprn].uea_write;
4633#else
4634    if (ctx->pr) {
4635        write_cb = ctx->spr_cb[sprn].uea_write;
4636    } else if (ctx->hv) {
4637        write_cb = ctx->spr_cb[sprn].hea_write;
4638    } else {
4639        write_cb = ctx->spr_cb[sprn].oea_write;
4640    }
4641#endif
4642    if (likely(write_cb != NULL)) {
4643        if (likely(write_cb != SPR_NOACCESS)) {
4644            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4645        } else {
4646            /* Privilege exception */
4647            fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at "
4648                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4649            if (qemu_log_separate()) {
4650                qemu_log("Trying to write privileged spr %d (0x%03x) at "
4651                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4652            }
4653            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4654        }
4655    } else {
4656        /* ISA 2.07 defines these as no-ops */
4657        if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4658            (sprn >= 808 && sprn <= 811)) {
4659            /* This is a nop */
4660            return;
4661        }
4662
4663        /* Not defined */
4664        if (qemu_log_separate()) {
4665            qemu_log("Trying to write invalid spr %d (0x%03x) at "
4666                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4667        }
4668        fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
4669                TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4670
4671
4672        /* The behaviour depends on MSR:PR and SPR# bit 0x10,
4673         * it can generate a priv, a hv emu or a no-op
4674         */
4675        if (sprn & 0x10) {
4676            if (ctx->pr) {
4677                gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4678            }
4679        } else {
4680            if (ctx->pr || sprn == 0) {
4681                gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4682            }
4683        }
4684    }
4685}
4686
4687/***                         Cache management                              ***/
4688
4689/* dcbf */
4690static void gen_dcbf(DisasContext *ctx)
4691{
4692    /* XXX: specification says this is treated as a load by the MMU */
4693    TCGv t0;
4694    gen_set_access_type(ctx, ACCESS_CACHE);
4695    t0 = tcg_temp_new();
4696    gen_addr_reg_index(ctx, t0);
4697    gen_qemu_ld8u(ctx, t0, t0);
4698    tcg_temp_free(t0);
4699}
4700
4701/* dcbi (Supervisor only) */
4702static void gen_dcbi(DisasContext *ctx)
4703{
4704#if defined(CONFIG_USER_ONLY)
4705    GEN_PRIV;
4706#else
4707    TCGv EA, val;
4708
4709    CHK_SV;
4710    EA = tcg_temp_new();
4711    gen_set_access_type(ctx, ACCESS_CACHE);
4712    gen_addr_reg_index(ctx, EA);
4713    val = tcg_temp_new();
4714    /* XXX: specification says this should be treated as a store by the MMU */
4715    gen_qemu_ld8u(ctx, val, EA);
4716    gen_qemu_st8(ctx, val, EA);
4717    tcg_temp_free(val);
4718    tcg_temp_free(EA);
4719#endif /* defined(CONFIG_USER_ONLY) */
4720}
4721
4722/* dcdst */
4723static void gen_dcbst(DisasContext *ctx)
4724{
4725    /* XXX: specification say this is treated as a load by the MMU */
4726    TCGv t0;
4727    gen_set_access_type(ctx, ACCESS_CACHE);
4728    t0 = tcg_temp_new();
4729    gen_addr_reg_index(ctx, t0);
4730    gen_qemu_ld8u(ctx, t0, t0);
4731    tcg_temp_free(t0);
4732}
4733
4734/* dcbt */
4735static void gen_dcbt(DisasContext *ctx)
4736{
4737    /* interpreted as no-op */
4738    /* XXX: specification say this is treated as a load by the MMU
4739     *      but does not generate any exception
4740     */
4741}
4742
4743/* dcbtst */
4744static void gen_dcbtst(DisasContext *ctx)
4745{
4746    /* interpreted as no-op */
4747    /* XXX: specification say this is treated as a load by the MMU
4748     *      but does not generate any exception
4749     */
4750}
4751
4752/* dcbtls */
4753static void gen_dcbtls(DisasContext *ctx)
4754{
4755    /* Always fails locking the cache */
4756    TCGv t0 = tcg_temp_new();
4757    gen_load_spr(t0, SPR_Exxx_L1CSR0);
4758    tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
4759    gen_store_spr(SPR_Exxx_L1CSR0, t0);
4760    tcg_temp_free(t0);
4761}
4762
4763/* dcbz */
4764static void gen_dcbz(DisasContext *ctx)
4765{
4766    TCGv tcgv_addr;
4767    TCGv_i32 tcgv_is_dcbzl;
4768    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4769
4770    gen_set_access_type(ctx, ACCESS_CACHE);
4771    /* NIP cannot be restored if the memory exception comes from an helper */
4772    gen_update_nip(ctx, ctx->nip - 4);
4773    tcgv_addr = tcg_temp_new();
4774    tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
4775
4776    gen_addr_reg_index(ctx, tcgv_addr);
4777    gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
4778
4779    tcg_temp_free(tcgv_addr);
4780    tcg_temp_free_i32(tcgv_is_dcbzl);
4781}
4782
4783/* dst / dstt */
4784static void gen_dst(DisasContext *ctx)
4785{
4786    if (rA(ctx->opcode) == 0) {
4787        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4788    } else {
4789        /* interpreted as no-op */
4790    }
4791}
4792
4793/* dstst /dststt */
4794static void gen_dstst(DisasContext *ctx)
4795{
4796    if (rA(ctx->opcode) == 0) {
4797        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4798    } else {
4799        /* interpreted as no-op */
4800    }
4801
4802}
4803
4804/* dss / dssall */
4805static void gen_dss(DisasContext *ctx)
4806{
4807    /* interpreted as no-op */
4808}
4809
4810/* icbi */
4811static void gen_icbi(DisasContext *ctx)
4812{
4813    TCGv t0;
4814    gen_set_access_type(ctx, ACCESS_CACHE);
4815    /* NIP cannot be restored if the memory exception comes from an helper */
4816    gen_update_nip(ctx, ctx->nip - 4);
4817    t0 = tcg_temp_new();
4818    gen_addr_reg_index(ctx, t0);
4819    gen_helper_icbi(cpu_env, t0);
4820    tcg_temp_free(t0);
4821}
4822
4823/* Optional: */
4824/* dcba */
4825static void gen_dcba(DisasContext *ctx)
4826{
4827    /* interpreted as no-op */
4828    /* XXX: specification say this is treated as a store by the MMU
4829     *      but does not generate any exception
4830     */
4831}
4832
4833/***                    Segment register manipulation                      ***/
4834/* Supervisor only: */
4835
4836/* mfsr */
4837static void gen_mfsr(DisasContext *ctx)
4838{
4839#if defined(CONFIG_USER_ONLY)
4840    GEN_PRIV;
4841#else
4842    TCGv t0;
4843
4844    CHK_SV;
4845    t0 = tcg_const_tl(SR(ctx->opcode));
4846    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4847    tcg_temp_free(t0);
4848#endif /* defined(CONFIG_USER_ONLY) */
4849}
4850
4851/* mfsrin */
4852static void gen_mfsrin(DisasContext *ctx)
4853{
4854#if defined(CONFIG_USER_ONLY)
4855    GEN_PRIV;
4856#else
4857    TCGv t0;
4858
4859    CHK_SV;
4860    t0 = tcg_temp_new();
4861    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4862    tcg_gen_andi_tl(t0, t0, 0xF);
4863    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4864    tcg_temp_free(t0);
4865#endif /* defined(CONFIG_USER_ONLY) */
4866}
4867
4868/* mtsr */
4869static void gen_mtsr(DisasContext *ctx)
4870{
4871#if defined(CONFIG_USER_ONLY)
4872    GEN_PRIV;
4873#else
4874    TCGv t0;
4875
4876    CHK_SV;
4877    t0 = tcg_const_tl(SR(ctx->opcode));
4878    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4879    tcg_temp_free(t0);
4880#endif /* defined(CONFIG_USER_ONLY) */
4881}
4882
4883/* mtsrin */
4884static void gen_mtsrin(DisasContext *ctx)
4885{
4886#if defined(CONFIG_USER_ONLY)
4887    GEN_PRIV;
4888#else
4889    TCGv t0;
4890    CHK_SV;
4891
4892    t0 = tcg_temp_new();
4893    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4894    tcg_gen_andi_tl(t0, t0, 0xF);
4895    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4896    tcg_temp_free(t0);
4897#endif /* defined(CONFIG_USER_ONLY) */
4898}
4899
4900#if defined(TARGET_PPC64)
4901/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4902
4903/* mfsr */
4904static void gen_mfsr_64b(DisasContext *ctx)
4905{
4906#if defined(CONFIG_USER_ONLY)
4907    GEN_PRIV;
4908#else
4909    TCGv t0;
4910
4911    CHK_SV;
4912    t0 = tcg_const_tl(SR(ctx->opcode));
4913    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4914    tcg_temp_free(t0);
4915#endif /* defined(CONFIG_USER_ONLY) */
4916}
4917
4918/* mfsrin */
4919static void gen_mfsrin_64b(DisasContext *ctx)
4920{
4921#if defined(CONFIG_USER_ONLY)
4922    GEN_PRIV;
4923#else
4924    TCGv t0;
4925
4926    CHK_SV;
4927    t0 = tcg_temp_new();
4928    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4929    tcg_gen_andi_tl(t0, t0, 0xF);
4930    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4931    tcg_temp_free(t0);
4932#endif /* defined(CONFIG_USER_ONLY) */
4933}
4934
4935/* mtsr */
4936static void gen_mtsr_64b(DisasContext *ctx)
4937{
4938#if defined(CONFIG_USER_ONLY)
4939    GEN_PRIV;
4940#else
4941    TCGv t0;
4942
4943    CHK_SV;
4944    t0 = tcg_const_tl(SR(ctx->opcode));
4945    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4946    tcg_temp_free(t0);
4947#endif /* defined(CONFIG_USER_ONLY) */
4948}
4949
4950/* mtsrin */
4951static void gen_mtsrin_64b(DisasContext *ctx)
4952{
4953#if defined(CONFIG_USER_ONLY)
4954    GEN_PRIV;
4955#else
4956    TCGv t0;
4957
4958    CHK_SV;
4959    t0 = tcg_temp_new();
4960    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4961    tcg_gen_andi_tl(t0, t0, 0xF);
4962    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4963    tcg_temp_free(t0);
4964#endif /* defined(CONFIG_USER_ONLY) */
4965}
4966
4967/* slbmte */
4968static void gen_slbmte(DisasContext *ctx)
4969{
4970#if defined(CONFIG_USER_ONLY)
4971    GEN_PRIV;
4972#else
4973    CHK_SV;
4974
4975    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
4976                         cpu_gpr[rS(ctx->opcode)]);
4977#endif /* defined(CONFIG_USER_ONLY) */
4978}
4979
4980static void gen_slbmfee(DisasContext *ctx)
4981{
4982#if defined(CONFIG_USER_ONLY)
4983    GEN_PRIV;
4984#else
4985    CHK_SV;
4986
4987    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4988                             cpu_gpr[rB(ctx->opcode)]);
4989#endif /* defined(CONFIG_USER_ONLY) */
4990}
4991
4992static void gen_slbmfev(DisasContext *ctx)
4993{
4994#if defined(CONFIG_USER_ONLY)
4995    GEN_PRIV;
4996#else
4997    CHK_SV;
4998
4999    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
5000                             cpu_gpr[rB(ctx->opcode)]);
5001#endif /* defined(CONFIG_USER_ONLY) */
5002}
5003
5004static void gen_slbfee_(DisasContext *ctx)
5005{
5006#if defined(CONFIG_USER_ONLY)
5007    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5008#else
5009    TCGLabel *l1, *l2;
5010
5011    if (unlikely(ctx->pr)) {
5012        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5013        return;
5014    }
5015    gen_helper_find_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
5016                             cpu_gpr[rB(ctx->opcode)]);
5017    l1 = gen_new_label();
5018    l2 = gen_new_label();
5019    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5020    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1);
5021    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
5022    tcg_gen_br(l2);
5023    gen_set_label(l1);
5024    tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0);
5025    gen_set_label(l2);
5026#endif
5027}
5028#endif /* defined(TARGET_PPC64) */
5029
5030/***                      Lookaside buffer management                      ***/
5031/* Optional & supervisor only: */
5032
5033/* tlbia */
5034static void gen_tlbia(DisasContext *ctx)
5035{
5036#if defined(CONFIG_USER_ONLY)
5037    GEN_PRIV;
5038#else
5039    CHK_HV;
5040
5041    gen_helper_tlbia(cpu_env);
5042#endif  /* defined(CONFIG_USER_ONLY) */
5043}
5044
5045/* tlbiel */
5046static void gen_tlbiel(DisasContext *ctx)
5047{
5048#if defined(CONFIG_USER_ONLY)
5049    GEN_PRIV;
5050#else
5051    CHK_SV;
5052
5053    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5054#endif /* defined(CONFIG_USER_ONLY) */
5055}
5056
5057/* tlbie */
5058static void gen_tlbie(DisasContext *ctx)
5059{
5060#if defined(CONFIG_USER_ONLY)
5061    GEN_PRIV;
5062#else
5063    CHK_HV;
5064
5065    if (NARROW_MODE(ctx)) {
5066        TCGv t0 = tcg_temp_new();
5067        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
5068        gen_helper_tlbie(cpu_env, t0);
5069        tcg_temp_free(t0);
5070    } else {
5071        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5072    }
5073#endif /* defined(CONFIG_USER_ONLY) */
5074}
5075
5076/* tlbsync */
5077static void gen_tlbsync(DisasContext *ctx)
5078{
5079#if defined(CONFIG_USER_ONLY)
5080    GEN_PRIV;
5081#else
5082    CHK_HV;
5083
5084    /* tlbsync is a nop for server, ptesync handles delayed tlb flush,
5085     * embedded however needs to deal with tlbsync. We don't try to be
5086     * fancy and swallow the overhead of checking for both.
5087     */
5088    gen_check_tlb_flush(ctx);
5089#endif /* defined(CONFIG_USER_ONLY) */
5090}
5091
5092#if defined(TARGET_PPC64)
5093/* slbia */
5094static void gen_slbia(DisasContext *ctx)
5095{
5096#if defined(CONFIG_USER_ONLY)
5097    GEN_PRIV;
5098#else
5099    CHK_SV;
5100
5101    gen_helper_slbia(cpu_env);
5102#endif /* defined(CONFIG_USER_ONLY) */
5103}
5104
5105/* slbie */
5106static void gen_slbie(DisasContext *ctx)
5107{
5108#if defined(CONFIG_USER_ONLY)
5109    GEN_PRIV;
5110#else
5111    CHK_SV;
5112
5113    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5114#endif /* defined(CONFIG_USER_ONLY) */
5115}
5116#endif  /* defined(TARGET_PPC64) */
5117
5118/***                              External control                         ***/
5119/* Optional: */
5120
5121/* eciwx */
5122static void gen_eciwx(DisasContext *ctx)
5123{
5124    TCGv t0;
5125    /* Should check EAR[E] ! */
5126    gen_set_access_type(ctx, ACCESS_EXT);
5127    t0 = tcg_temp_new();
5128    gen_addr_reg_index(ctx, t0);
5129    gen_check_align(ctx, t0, 0x03);
5130    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
5131    tcg_temp_free(t0);
5132}
5133
5134/* ecowx */
5135static void gen_ecowx(DisasContext *ctx)
5136{
5137    TCGv t0;
5138    /* Should check EAR[E] ! */
5139    gen_set_access_type(ctx, ACCESS_EXT);
5140    t0 = tcg_temp_new();
5141    gen_addr_reg_index(ctx, t0);
5142    gen_check_align(ctx, t0, 0x03);
5143    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
5144    tcg_temp_free(t0);
5145}
5146
5147/* PowerPC 601 specific instructions */
5148
5149/* abs - abs. */
5150static void gen_abs(DisasContext *ctx)
5151{
5152    TCGLabel *l1 = gen_new_label();
5153    TCGLabel *l2 = gen_new_label();
5154    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
5155    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5156    tcg_gen_br(l2);
5157    gen_set_label(l1);
5158    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5159    gen_set_label(l2);
5160    if (unlikely(Rc(ctx->opcode) != 0))
5161        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5162}
5163
5164/* abso - abso. */
5165static void gen_abso(DisasContext *ctx)
5166{
5167    TCGLabel *l1 = gen_new_label();
5168    TCGLabel *l2 = gen_new_label();
5169    TCGLabel *l3 = gen_new_label();
5170    /* Start with XER OV disabled, the most likely case */
5171    tcg_gen_movi_tl(cpu_ov, 0);
5172    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
5173    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
5174    tcg_gen_movi_tl(cpu_ov, 1);
5175    tcg_gen_movi_tl(cpu_so, 1);
5176    tcg_gen_br(l2);
5177    gen_set_label(l1);
5178    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5179    tcg_gen_br(l3);
5180    gen_set_label(l2);
5181    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5182    gen_set_label(l3);
5183    if (unlikely(Rc(ctx->opcode) != 0))
5184        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5185}
5186
5187/* clcs */
5188static void gen_clcs(DisasContext *ctx)
5189{
5190    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
5191    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5192    tcg_temp_free_i32(t0);
5193    /* Rc=1 sets CR0 to an undefined state */
5194}
5195
5196/* div - div. */
5197static void gen_div(DisasContext *ctx)
5198{
5199    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5200                   cpu_gpr[rB(ctx->opcode)]);
5201    if (unlikely(Rc(ctx->opcode) != 0))
5202        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5203}
5204
5205/* divo - divo. */
5206static void gen_divo(DisasContext *ctx)
5207{
5208    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5209                    cpu_gpr[rB(ctx->opcode)]);
5210    if (unlikely(Rc(ctx->opcode) != 0))
5211        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5212}
5213
5214/* divs - divs. */
5215static void gen_divs(DisasContext *ctx)
5216{
5217    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5218                    cpu_gpr[rB(ctx->opcode)]);
5219    if (unlikely(Rc(ctx->opcode) != 0))
5220        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5221}
5222
5223/* divso - divso. */
5224static void gen_divso(DisasContext *ctx)
5225{
5226    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
5227                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5228    if (unlikely(Rc(ctx->opcode) != 0))
5229        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5230}
5231
5232/* doz - doz. */
5233static void gen_doz(DisasContext *ctx)
5234{
5235    TCGLabel *l1 = gen_new_label();
5236    TCGLabel *l2 = gen_new_label();
5237    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5238    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5239    tcg_gen_br(l2);
5240    gen_set_label(l1);
5241    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5242    gen_set_label(l2);
5243    if (unlikely(Rc(ctx->opcode) != 0))
5244        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5245}
5246
5247/* dozo - dozo. */
5248static void gen_dozo(DisasContext *ctx)
5249{
5250    TCGLabel *l1 = gen_new_label();
5251    TCGLabel *l2 = gen_new_label();
5252    TCGv t0 = tcg_temp_new();
5253    TCGv t1 = tcg_temp_new();
5254    TCGv t2 = tcg_temp_new();
5255    /* Start with XER OV disabled, the most likely case */
5256    tcg_gen_movi_tl(cpu_ov, 0);
5257    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5258    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5259    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5260    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
5261    tcg_gen_andc_tl(t1, t1, t2);
5262    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
5263    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5264    tcg_gen_movi_tl(cpu_ov, 1);
5265    tcg_gen_movi_tl(cpu_so, 1);
5266    tcg_gen_br(l2);
5267    gen_set_label(l1);
5268    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5269    gen_set_label(l2);
5270    tcg_temp_free(t0);
5271    tcg_temp_free(t1);
5272    tcg_temp_free(t2);
5273    if (unlikely(Rc(ctx->opcode) != 0))
5274        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5275}
5276
5277/* dozi */
5278static void gen_dozi(DisasContext *ctx)
5279{
5280    target_long simm = SIMM(ctx->opcode);
5281    TCGLabel *l1 = gen_new_label();
5282    TCGLabel *l2 = gen_new_label();
5283    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
5284    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
5285    tcg_gen_br(l2);
5286    gen_set_label(l1);
5287    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5288    gen_set_label(l2);
5289    if (unlikely(Rc(ctx->opcode) != 0))
5290        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5291}
5292
5293/* lscbx - lscbx. */
5294static void gen_lscbx(DisasContext *ctx)
5295{
5296    TCGv t0 = tcg_temp_new();
5297    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
5298    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
5299    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
5300
5301    gen_addr_reg_index(ctx, t0);
5302    /* NIP cannot be restored if the memory exception comes from an helper */
5303    gen_update_nip(ctx, ctx->nip - 4);
5304    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
5305    tcg_temp_free_i32(t1);
5306    tcg_temp_free_i32(t2);
5307    tcg_temp_free_i32(t3);
5308    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
5309    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
5310    if (unlikely(Rc(ctx->opcode) != 0))
5311        gen_set_Rc0(ctx, t0);
5312    tcg_temp_free(t0);
5313}
5314
5315/* maskg - maskg. */
5316static void gen_maskg(DisasContext *ctx)
5317{
5318    TCGLabel *l1 = gen_new_label();
5319    TCGv t0 = tcg_temp_new();
5320    TCGv t1 = tcg_temp_new();
5321    TCGv t2 = tcg_temp_new();
5322    TCGv t3 = tcg_temp_new();
5323    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
5324    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5325    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
5326    tcg_gen_addi_tl(t2, t0, 1);
5327    tcg_gen_shr_tl(t2, t3, t2);
5328    tcg_gen_shr_tl(t3, t3, t1);
5329    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
5330    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5331    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5332    gen_set_label(l1);
5333    tcg_temp_free(t0);
5334    tcg_temp_free(t1);
5335    tcg_temp_free(t2);
5336    tcg_temp_free(t3);
5337    if (unlikely(Rc(ctx->opcode) != 0))
5338        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5339}
5340
5341/* maskir - maskir. */
5342static void gen_maskir(DisasContext *ctx)
5343{
5344    TCGv t0 = tcg_temp_new();
5345    TCGv t1 = tcg_temp_new();
5346    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5347    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5348    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5349    tcg_temp_free(t0);
5350    tcg_temp_free(t1);
5351    if (unlikely(Rc(ctx->opcode) != 0))
5352        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5353}
5354
5355/* mul - mul. */
5356static void gen_mul(DisasContext *ctx)
5357{
5358    TCGv_i64 t0 = tcg_temp_new_i64();
5359    TCGv_i64 t1 = tcg_temp_new_i64();
5360    TCGv t2 = tcg_temp_new();
5361    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5362    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5363    tcg_gen_mul_i64(t0, t0, t1);
5364    tcg_gen_trunc_i64_tl(t2, t0);
5365    gen_store_spr(SPR_MQ, t2);
5366    tcg_gen_shri_i64(t1, t0, 32);
5367    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5368    tcg_temp_free_i64(t0);
5369    tcg_temp_free_i64(t1);
5370    tcg_temp_free(t2);
5371    if (unlikely(Rc(ctx->opcode) != 0))
5372        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5373}
5374
5375/* mulo - mulo. */
5376static void gen_mulo(DisasContext *ctx)
5377{
5378    TCGLabel *l1 = gen_new_label();
5379    TCGv_i64 t0 = tcg_temp_new_i64();
5380    TCGv_i64 t1 = tcg_temp_new_i64();
5381    TCGv t2 = tcg_temp_new();
5382    /* Start with XER OV disabled, the most likely case */
5383    tcg_gen_movi_tl(cpu_ov, 0);
5384    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5385    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5386    tcg_gen_mul_i64(t0, t0, t1);
5387    tcg_gen_trunc_i64_tl(t2, t0);
5388    gen_store_spr(SPR_MQ, t2);
5389    tcg_gen_shri_i64(t1, t0, 32);
5390    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5391    tcg_gen_ext32s_i64(t1, t0);
5392    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
5393    tcg_gen_movi_tl(cpu_ov, 1);
5394    tcg_gen_movi_tl(cpu_so, 1);
5395    gen_set_label(l1);
5396    tcg_temp_free_i64(t0);
5397    tcg_temp_free_i64(t1);
5398    tcg_temp_free(t2);
5399    if (unlikely(Rc(ctx->opcode) != 0))
5400        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5401}
5402
5403/* nabs - nabs. */
5404static void gen_nabs(DisasContext *ctx)
5405{
5406    TCGLabel *l1 = gen_new_label();
5407    TCGLabel *l2 = gen_new_label();
5408    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5409    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5410    tcg_gen_br(l2);
5411    gen_set_label(l1);
5412    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5413    gen_set_label(l2);
5414    if (unlikely(Rc(ctx->opcode) != 0))
5415        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5416}
5417
5418/* nabso - nabso. */
5419static void gen_nabso(DisasContext *ctx)
5420{
5421    TCGLabel *l1 = gen_new_label();
5422    TCGLabel *l2 = gen_new_label();
5423    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5424    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5425    tcg_gen_br(l2);
5426    gen_set_label(l1);
5427    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5428    gen_set_label(l2);
5429    /* nabs never overflows */
5430    tcg_gen_movi_tl(cpu_ov, 0);
5431    if (unlikely(Rc(ctx->opcode) != 0))
5432        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5433}
5434
5435/* rlmi - rlmi. */
5436static void gen_rlmi(DisasContext *ctx)
5437{
5438    uint32_t mb = MB(ctx->opcode);
5439    uint32_t me = ME(ctx->opcode);
5440    TCGv t0 = tcg_temp_new();
5441    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5442    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5443    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
5444    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
5445    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
5446    tcg_temp_free(t0);
5447    if (unlikely(Rc(ctx->opcode) != 0))
5448        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5449}
5450
5451/* rrib - rrib. */
5452static void gen_rrib(DisasContext *ctx)
5453{
5454    TCGv t0 = tcg_temp_new();
5455    TCGv t1 = tcg_temp_new();
5456    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5457    tcg_gen_movi_tl(t1, 0x80000000);
5458    tcg_gen_shr_tl(t1, t1, t0);
5459    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5460    tcg_gen_and_tl(t0, t0, t1);
5461    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
5462    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5463    tcg_temp_free(t0);
5464    tcg_temp_free(t1);
5465    if (unlikely(Rc(ctx->opcode) != 0))
5466        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5467}
5468
5469/* sle - sle. */
5470static void gen_sle(DisasContext *ctx)
5471{
5472    TCGv t0 = tcg_temp_new();
5473    TCGv t1 = tcg_temp_new();
5474    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5475    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5476    tcg_gen_subfi_tl(t1, 32, t1);
5477    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5478    tcg_gen_or_tl(t1, t0, t1);
5479    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5480    gen_store_spr(SPR_MQ, t1);
5481    tcg_temp_free(t0);
5482    tcg_temp_free(t1);
5483    if (unlikely(Rc(ctx->opcode) != 0))
5484        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5485}
5486
5487/* sleq - sleq. */
5488static void gen_sleq(DisasContext *ctx)
5489{
5490    TCGv t0 = tcg_temp_new();
5491    TCGv t1 = tcg_temp_new();
5492    TCGv t2 = tcg_temp_new();
5493    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5494    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
5495    tcg_gen_shl_tl(t2, t2, t0);
5496    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5497    gen_load_spr(t1, SPR_MQ);
5498    gen_store_spr(SPR_MQ, t0);
5499    tcg_gen_and_tl(t0, t0, t2);
5500    tcg_gen_andc_tl(t1, t1, t2);
5501    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5502    tcg_temp_free(t0);
5503    tcg_temp_free(t1);
5504    tcg_temp_free(t2);
5505    if (unlikely(Rc(ctx->opcode) != 0))
5506        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5507}
5508
5509/* sliq - sliq. */
5510static void gen_sliq(DisasContext *ctx)
5511{
5512    int sh = SH(ctx->opcode);
5513    TCGv t0 = tcg_temp_new();
5514    TCGv t1 = tcg_temp_new();
5515    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5516    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5517    tcg_gen_or_tl(t1, t0, t1);
5518    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5519    gen_store_spr(SPR_MQ, t1);
5520    tcg_temp_free(t0);
5521    tcg_temp_free(t1);
5522    if (unlikely(Rc(ctx->opcode) != 0))
5523        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5524}
5525
5526/* slliq - slliq. */
5527static void gen_slliq(DisasContext *ctx)
5528{
5529    int sh = SH(ctx->opcode);
5530    TCGv t0 = tcg_temp_new();
5531    TCGv t1 = tcg_temp_new();
5532    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5533    gen_load_spr(t1, SPR_MQ);
5534    gen_store_spr(SPR_MQ, t0);
5535    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
5536    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
5537    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5538    tcg_temp_free(t0);
5539    tcg_temp_free(t1);
5540    if (unlikely(Rc(ctx->opcode) != 0))
5541        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5542}
5543
5544/* sllq - sllq. */
5545static void gen_sllq(DisasContext *ctx)
5546{
5547    TCGLabel *l1 = gen_new_label();
5548    TCGLabel *l2 = gen_new_label();
5549    TCGv t0 = tcg_temp_local_new();
5550    TCGv t1 = tcg_temp_local_new();
5551    TCGv t2 = tcg_temp_local_new();
5552    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5553    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5554    tcg_gen_shl_tl(t1, t1, t2);
5555    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5556    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5557    gen_load_spr(t0, SPR_MQ);
5558    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5559    tcg_gen_br(l2);
5560    gen_set_label(l1);
5561    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5562    gen_load_spr(t2, SPR_MQ);
5563    tcg_gen_andc_tl(t1, t2, t1);
5564    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5565    gen_set_label(l2);
5566    tcg_temp_free(t0);
5567    tcg_temp_free(t1);
5568    tcg_temp_free(t2);
5569    if (unlikely(Rc(ctx->opcode) != 0))
5570        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5571}
5572
5573/* slq - slq. */
5574static void gen_slq(DisasContext *ctx)
5575{
5576    TCGLabel *l1 = gen_new_label();
5577    TCGv t0 = tcg_temp_new();
5578    TCGv t1 = tcg_temp_new();
5579    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5580    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5581    tcg_gen_subfi_tl(t1, 32, t1);
5582    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5583    tcg_gen_or_tl(t1, t0, t1);
5584    gen_store_spr(SPR_MQ, t1);
5585    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5586    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5587    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5588    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5589    gen_set_label(l1);
5590    tcg_temp_free(t0);
5591    tcg_temp_free(t1);
5592    if (unlikely(Rc(ctx->opcode) != 0))
5593        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5594}
5595
5596/* sraiq - sraiq. */
5597static void gen_sraiq(DisasContext *ctx)
5598{
5599    int sh = SH(ctx->opcode);
5600    TCGLabel *l1 = gen_new_label();
5601    TCGv t0 = tcg_temp_new();
5602    TCGv t1 = tcg_temp_new();
5603    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5604    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5605    tcg_gen_or_tl(t0, t0, t1);
5606    gen_store_spr(SPR_MQ, t0);
5607    tcg_gen_movi_tl(cpu_ca, 0);
5608    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5609    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
5610    tcg_gen_movi_tl(cpu_ca, 1);
5611    gen_set_label(l1);
5612    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
5613    tcg_temp_free(t0);
5614    tcg_temp_free(t1);
5615    if (unlikely(Rc(ctx->opcode) != 0))
5616        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5617}
5618
5619/* sraq - sraq. */
5620static void gen_sraq(DisasContext *ctx)
5621{
5622    TCGLabel *l1 = gen_new_label();
5623    TCGLabel *l2 = gen_new_label();
5624    TCGv t0 = tcg_temp_new();
5625    TCGv t1 = tcg_temp_local_new();
5626    TCGv t2 = tcg_temp_local_new();
5627    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5628    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5629    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
5630    tcg_gen_subfi_tl(t2, 32, t2);
5631    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
5632    tcg_gen_or_tl(t0, t0, t2);
5633    gen_store_spr(SPR_MQ, t0);
5634    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5635    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
5636    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
5637    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
5638    gen_set_label(l1);
5639    tcg_temp_free(t0);
5640    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
5641    tcg_gen_movi_tl(cpu_ca, 0);
5642    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5643    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
5644    tcg_gen_movi_tl(cpu_ca, 1);
5645    gen_set_label(l2);
5646    tcg_temp_free(t1);
5647    tcg_temp_free(t2);
5648    if (unlikely(Rc(ctx->opcode) != 0))
5649        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5650}
5651
5652/* sre - sre. */
5653static void gen_sre(DisasContext *ctx)
5654{
5655    TCGv t0 = tcg_temp_new();
5656    TCGv t1 = tcg_temp_new();
5657    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5658    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5659    tcg_gen_subfi_tl(t1, 32, t1);
5660    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5661    tcg_gen_or_tl(t1, t0, t1);
5662    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5663    gen_store_spr(SPR_MQ, t1);
5664    tcg_temp_free(t0);
5665    tcg_temp_free(t1);
5666    if (unlikely(Rc(ctx->opcode) != 0))
5667        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5668}
5669
5670/* srea - srea. */
5671static void gen_srea(DisasContext *ctx)
5672{
5673    TCGv t0 = tcg_temp_new();
5674    TCGv t1 = tcg_temp_new();
5675    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5676    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5677    gen_store_spr(SPR_MQ, t0);
5678    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
5679    tcg_temp_free(t0);
5680    tcg_temp_free(t1);
5681    if (unlikely(Rc(ctx->opcode) != 0))
5682        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5683}
5684
5685/* sreq */
5686static void gen_sreq(DisasContext *ctx)
5687{
5688    TCGv t0 = tcg_temp_new();
5689    TCGv t1 = tcg_temp_new();
5690    TCGv t2 = tcg_temp_new();
5691    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5692    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5693    tcg_gen_shr_tl(t1, t1, t0);
5694    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5695    gen_load_spr(t2, SPR_MQ);
5696    gen_store_spr(SPR_MQ, t0);
5697    tcg_gen_and_tl(t0, t0, t1);
5698    tcg_gen_andc_tl(t2, t2, t1);
5699    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5700    tcg_temp_free(t0);
5701    tcg_temp_free(t1);
5702    tcg_temp_free(t2);
5703    if (unlikely(Rc(ctx->opcode) != 0))
5704        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5705}
5706
5707/* sriq */
5708static void gen_sriq(DisasContext *ctx)
5709{
5710    int sh = SH(ctx->opcode);
5711    TCGv t0 = tcg_temp_new();
5712    TCGv t1 = tcg_temp_new();
5713    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5714    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5715    tcg_gen_or_tl(t1, t0, t1);
5716    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5717    gen_store_spr(SPR_MQ, t1);
5718    tcg_temp_free(t0);
5719    tcg_temp_free(t1);
5720    if (unlikely(Rc(ctx->opcode) != 0))
5721        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5722}
5723
5724/* srliq */
5725static void gen_srliq(DisasContext *ctx)
5726{
5727    int sh = SH(ctx->opcode);
5728    TCGv t0 = tcg_temp_new();
5729    TCGv t1 = tcg_temp_new();
5730    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5731    gen_load_spr(t1, SPR_MQ);
5732    gen_store_spr(SPR_MQ, t0);
5733    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
5734    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5735    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5736    tcg_temp_free(t0);
5737    tcg_temp_free(t1);
5738    if (unlikely(Rc(ctx->opcode) != 0))
5739        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5740}
5741
5742/* srlq */
5743static void gen_srlq(DisasContext *ctx)
5744{
5745    TCGLabel *l1 = gen_new_label();
5746    TCGLabel *l2 = gen_new_label();
5747    TCGv t0 = tcg_temp_local_new();
5748    TCGv t1 = tcg_temp_local_new();
5749    TCGv t2 = tcg_temp_local_new();
5750    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5751    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5752    tcg_gen_shr_tl(t2, t1, t2);
5753    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5754    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5755    gen_load_spr(t0, SPR_MQ);
5756    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5757    tcg_gen_br(l2);
5758    gen_set_label(l1);
5759    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5760    tcg_gen_and_tl(t0, t0, t2);
5761    gen_load_spr(t1, SPR_MQ);
5762    tcg_gen_andc_tl(t1, t1, t2);
5763    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5764    gen_set_label(l2);
5765    tcg_temp_free(t0);
5766    tcg_temp_free(t1);
5767    tcg_temp_free(t2);
5768    if (unlikely(Rc(ctx->opcode) != 0))
5769        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5770}
5771
5772/* srq */
5773static void gen_srq(DisasContext *ctx)
5774{
5775    TCGLabel *l1 = gen_new_label();
5776    TCGv t0 = tcg_temp_new();
5777    TCGv t1 = tcg_temp_new();
5778    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5779    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5780    tcg_gen_subfi_tl(t1, 32, t1);
5781    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5782    tcg_gen_or_tl(t1, t0, t1);
5783    gen_store_spr(SPR_MQ, t1);
5784    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5785    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5786    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5787    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5788    gen_set_label(l1);
5789    tcg_temp_free(t0);
5790    tcg_temp_free(t1);
5791    if (unlikely(Rc(ctx->opcode) != 0))
5792        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5793}
5794
5795/* PowerPC 602 specific instructions */
5796
5797/* dsa  */
5798static void gen_dsa(DisasContext *ctx)
5799{
5800    /* XXX: TODO */
5801    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5802}
5803
5804/* esa */
5805static void gen_esa(DisasContext *ctx)
5806{
5807    /* XXX: TODO */
5808    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5809}
5810
5811/* mfrom */
5812static void gen_mfrom(DisasContext *ctx)
5813{
5814#if defined(CONFIG_USER_ONLY)
5815    GEN_PRIV;
5816#else
5817    CHK_SV;
5818    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5819#endif /* defined(CONFIG_USER_ONLY) */
5820}
5821
5822/* 602 - 603 - G2 TLB management */
5823
5824/* tlbld */
5825static void gen_tlbld_6xx(DisasContext *ctx)
5826{
5827#if defined(CONFIG_USER_ONLY)
5828    GEN_PRIV;
5829#else
5830    CHK_SV;
5831    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5832#endif /* defined(CONFIG_USER_ONLY) */
5833}
5834
5835/* tlbli */
5836static void gen_tlbli_6xx(DisasContext *ctx)
5837{
5838#if defined(CONFIG_USER_ONLY)
5839    GEN_PRIV;
5840#else
5841    CHK_SV;
5842    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5843#endif /* defined(CONFIG_USER_ONLY) */
5844}
5845
5846/* 74xx TLB management */
5847
5848/* tlbld */
5849static void gen_tlbld_74xx(DisasContext *ctx)
5850{
5851#if defined(CONFIG_USER_ONLY)
5852    GEN_PRIV;
5853#else
5854    CHK_SV;
5855    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5856#endif /* defined(CONFIG_USER_ONLY) */
5857}
5858
5859/* tlbli */
5860static void gen_tlbli_74xx(DisasContext *ctx)
5861{
5862#if defined(CONFIG_USER_ONLY)
5863    GEN_PRIV;
5864#else
5865    CHK_SV;
5866    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5867#endif /* defined(CONFIG_USER_ONLY) */
5868}
5869
5870/* POWER instructions not in PowerPC 601 */
5871
5872/* clf */
5873static void gen_clf(DisasContext *ctx)
5874{
5875    /* Cache line flush: implemented as no-op */
5876}
5877
5878/* cli */
5879static void gen_cli(DisasContext *ctx)
5880{
5881#if defined(CONFIG_USER_ONLY)
5882    GEN_PRIV;
5883#else
5884    /* Cache line invalidate: privileged and treated as no-op */
5885    CHK_SV;
5886#endif /* defined(CONFIG_USER_ONLY) */
5887}
5888
5889/* dclst */
5890static void gen_dclst(DisasContext *ctx)
5891{
5892    /* Data cache line store: treated as no-op */
5893}
5894
5895static void gen_mfsri(DisasContext *ctx)
5896{
5897#if defined(CONFIG_USER_ONLY)
5898    GEN_PRIV;
5899#else
5900    int ra = rA(ctx->opcode);
5901    int rd = rD(ctx->opcode);
5902    TCGv t0;
5903
5904    CHK_SV;
5905    t0 = tcg_temp_new();
5906    gen_addr_reg_index(ctx, t0);
5907    tcg_gen_shri_tl(t0, t0, 28);
5908    tcg_gen_andi_tl(t0, t0, 0xF);
5909    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5910    tcg_temp_free(t0);
5911    if (ra != 0 && ra != rd)
5912        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5913#endif /* defined(CONFIG_USER_ONLY) */
5914}
5915
5916static void gen_rac(DisasContext *ctx)
5917{
5918#if defined(CONFIG_USER_ONLY)
5919    GEN_PRIV;
5920#else
5921    TCGv t0;
5922
5923    CHK_SV;
5924    t0 = tcg_temp_new();
5925    gen_addr_reg_index(ctx, t0);
5926    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5927    tcg_temp_free(t0);
5928#endif /* defined(CONFIG_USER_ONLY) */
5929}
5930
5931static void gen_rfsvc(DisasContext *ctx)
5932{
5933#if defined(CONFIG_USER_ONLY)
5934    GEN_PRIV;
5935#else
5936    CHK_SV;
5937
5938    gen_helper_rfsvc(cpu_env);
5939    gen_sync_exception(ctx);
5940#endif /* defined(CONFIG_USER_ONLY) */
5941}
5942
5943/* svc is not implemented for now */
5944
5945/* POWER2 specific instructions */
5946/* Quad manipulation (load/store two floats at a time) */
5947
5948/* lfq */
5949static void gen_lfq(DisasContext *ctx)
5950{
5951    int rd = rD(ctx->opcode);
5952    TCGv t0;
5953    gen_set_access_type(ctx, ACCESS_FLOAT);
5954    t0 = tcg_temp_new();
5955    gen_addr_imm_index(ctx, t0, 0);
5956    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5957    gen_addr_add(ctx, t0, t0, 8);
5958    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5959    tcg_temp_free(t0);
5960}
5961
5962/* lfqu */
5963static void gen_lfqu(DisasContext *ctx)
5964{
5965    int ra = rA(ctx->opcode);
5966    int rd = rD(ctx->opcode);
5967    TCGv t0, t1;
5968    gen_set_access_type(ctx, ACCESS_FLOAT);
5969    t0 = tcg_temp_new();
5970    t1 = tcg_temp_new();
5971    gen_addr_imm_index(ctx, t0, 0);
5972    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5973    gen_addr_add(ctx, t1, t0, 8);
5974    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5975    if (ra != 0)
5976        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5977    tcg_temp_free(t0);
5978    tcg_temp_free(t1);
5979}
5980
5981/* lfqux */
5982static void gen_lfqux(DisasContext *ctx)
5983{
5984    int ra = rA(ctx->opcode);
5985    int rd = rD(ctx->opcode);
5986    gen_set_access_type(ctx, ACCESS_FLOAT);
5987    TCGv t0, t1;
5988    t0 = tcg_temp_new();
5989    gen_addr_reg_index(ctx, t0);
5990    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5991    t1 = tcg_temp_new();
5992    gen_addr_add(ctx, t1, t0, 8);
5993    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5994    tcg_temp_free(t1);
5995    if (ra != 0)
5996        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5997    tcg_temp_free(t0);
5998}
5999
6000/* lfqx */
6001static void gen_lfqx(DisasContext *ctx)
6002{
6003    int rd = rD(ctx->opcode);
6004    TCGv t0;
6005    gen_set_access_type(ctx, ACCESS_FLOAT);
6006    t0 = tcg_temp_new();
6007    gen_addr_reg_index(ctx, t0);
6008    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
6009    gen_addr_add(ctx, t0, t0, 8);
6010    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
6011    tcg_temp_free(t0);
6012}
6013
6014/* stfq */
6015static void gen_stfq(DisasContext *ctx)
6016{
6017    int rd = rD(ctx->opcode);
6018    TCGv t0;
6019    gen_set_access_type(ctx, ACCESS_FLOAT);
6020    t0 = tcg_temp_new();
6021    gen_addr_imm_index(ctx, t0, 0);
6022    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
6023    gen_addr_add(ctx, t0, t0, 8);
6024    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
6025    tcg_temp_free(t0);
6026}
6027
6028/* stfqu */
6029static void gen_stfqu(DisasContext *ctx)
6030{
6031    int ra = rA(ctx->opcode);
6032    int rd = rD(ctx->opcode);
6033    TCGv t0, t1;
6034    gen_set_access_type(ctx, ACCESS_FLOAT);
6035    t0 = tcg_temp_new();
6036    gen_addr_imm_index(ctx, t0, 0);
6037    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
6038    t1 = tcg_temp_new();
6039    gen_addr_add(ctx, t1, t0, 8);
6040    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
6041    tcg_temp_free(t1);
6042    if (ra != 0)
6043        tcg_gen_mov_tl(cpu_gpr[ra], t0);
6044    tcg_temp_free(t0);
6045}
6046
6047/* stfqux */
6048static void gen_stfqux(DisasContext *ctx)
6049{
6050    int ra = rA(ctx->opcode);
6051    int rd = rD(ctx->opcode);
6052    TCGv t0, t1;
6053    gen_set_access_type(ctx, ACCESS_FLOAT);
6054    t0 = tcg_temp_new();
6055    gen_addr_reg_index(ctx, t0);
6056    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
6057    t1 = tcg_temp_new();
6058    gen_addr_add(ctx, t1, t0, 8);
6059    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
6060    tcg_temp_free(t1);
6061    if (ra != 0)
6062        tcg_gen_mov_tl(cpu_gpr[ra], t0);
6063    tcg_temp_free(t0);
6064}
6065
6066/* stfqx */
6067static void gen_stfqx(DisasContext *ctx)
6068{
6069    int rd = rD(ctx->opcode);
6070    TCGv t0;
6071    gen_set_access_type(ctx, ACCESS_FLOAT);
6072    t0 = tcg_temp_new();
6073    gen_addr_reg_index(ctx, t0);
6074    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
6075    gen_addr_add(ctx, t0, t0, 8);
6076    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
6077    tcg_temp_free(t0);
6078}
6079
6080/* BookE specific instructions */
6081
6082/* XXX: not implemented on 440 ? */
6083static void gen_mfapidi(DisasContext *ctx)
6084{
6085    /* XXX: TODO */
6086    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6087}
6088
6089/* XXX: not implemented on 440 ? */
6090static void gen_tlbiva(DisasContext *ctx)
6091{
6092#if defined(CONFIG_USER_ONLY)
6093    GEN_PRIV;
6094#else
6095    TCGv t0;
6096
6097    CHK_SV;
6098    t0 = tcg_temp_new();
6099    gen_addr_reg_index(ctx, t0);
6100    gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
6101    tcg_temp_free(t0);
6102#endif /* defined(CONFIG_USER_ONLY) */
6103}
6104
6105/* All 405 MAC instructions are translated here */
6106static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
6107                                        int ra, int rb, int rt, int Rc)
6108{
6109    TCGv t0, t1;
6110
6111    t0 = tcg_temp_local_new();
6112    t1 = tcg_temp_local_new();
6113
6114    switch (opc3 & 0x0D) {
6115    case 0x05:
6116        /* macchw    - macchw.    - macchwo   - macchwo.   */
6117        /* macchws   - macchws.   - macchwso  - macchwso.  */
6118        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
6119        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
6120        /* mulchw - mulchw. */
6121        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
6122        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
6123        tcg_gen_ext16s_tl(t1, t1);
6124        break;
6125    case 0x04:
6126        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
6127        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
6128        /* mulchwu - mulchwu. */
6129        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
6130        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
6131        tcg_gen_ext16u_tl(t1, t1);
6132        break;
6133    case 0x01:
6134        /* machhw    - machhw.    - machhwo   - machhwo.   */
6135        /* machhws   - machhws.   - machhwso  - machhwso.  */
6136        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
6137        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
6138        /* mulhhw - mulhhw. */
6139        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
6140        tcg_gen_ext16s_tl(t0, t0);
6141        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
6142        tcg_gen_ext16s_tl(t1, t1);
6143        break;
6144    case 0x00:
6145        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
6146        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
6147        /* mulhhwu - mulhhwu. */
6148        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
6149        tcg_gen_ext16u_tl(t0, t0);
6150        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
6151        tcg_gen_ext16u_tl(t1, t1);
6152        break;
6153    case 0x0D:
6154        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
6155        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
6156        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
6157        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
6158        /* mullhw - mullhw. */
6159        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
6160        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
6161        break;
6162    case 0x0C:
6163        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
6164        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
6165        /* mullhwu - mullhwu. */
6166        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
6167        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
6168        break;
6169    }
6170    if (opc2 & 0x04) {
6171        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
6172        tcg_gen_mul_tl(t1, t0, t1);
6173        if (opc2 & 0x02) {
6174            /* nmultiply-and-accumulate (0x0E) */
6175            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
6176        } else {
6177            /* multiply-and-accumulate (0x0C) */
6178            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
6179        }
6180
6181        if (opc3 & 0x12) {
6182            /* Check overflow and/or saturate */
6183            TCGLabel *l1 = gen_new_label();
6184
6185            if (opc3 & 0x10) {
6186                /* Start with XER OV disabled, the most likely case */
6187                tcg_gen_movi_tl(cpu_ov, 0);
6188            }
6189            if (opc3 & 0x01) {
6190                /* Signed */
6191                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
6192                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
6193                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
6194                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
6195                if (opc3 & 0x02) {
6196                    /* Saturate */
6197                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
6198                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
6199                }
6200            } else {
6201                /* Unsigned */
6202                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6203                if (opc3 & 0x02) {
6204                    /* Saturate */
6205                    tcg_gen_movi_tl(t0, UINT32_MAX);
6206                }
6207            }
6208            if (opc3 & 0x10) {
6209                /* Check overflow */
6210                tcg_gen_movi_tl(cpu_ov, 1);
6211                tcg_gen_movi_tl(cpu_so, 1);
6212            }
6213            gen_set_label(l1);
6214            tcg_gen_mov_tl(cpu_gpr[rt], t0);
6215        }
6216    } else {
6217        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
6218    }
6219    tcg_temp_free(t0);
6220    tcg_temp_free(t1);
6221    if (unlikely(Rc) != 0) {
6222        /* Update Rc0 */
6223        gen_set_Rc0(ctx, cpu_gpr[rt]);
6224    }
6225}
6226
6227#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
6228static void glue(gen_, name)(DisasContext *ctx)                               \
6229{                                                                             \
6230    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
6231                         rD(ctx->opcode), Rc(ctx->opcode));                   \
6232}
6233
6234/* macchw    - macchw.    */
6235GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
6236/* macchwo   - macchwo.   */
6237GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
6238/* macchws   - macchws.   */
6239GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
6240/* macchwso  - macchwso.  */
6241GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
6242/* macchwsu  - macchwsu.  */
6243GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
6244/* macchwsuo - macchwsuo. */
6245GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
6246/* macchwu   - macchwu.   */
6247GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
6248/* macchwuo  - macchwuo.  */
6249GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
6250/* machhw    - machhw.    */
6251GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
6252/* machhwo   - machhwo.   */
6253GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
6254/* machhws   - machhws.   */
6255GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
6256/* machhwso  - machhwso.  */
6257GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
6258/* machhwsu  - machhwsu.  */
6259GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
6260/* machhwsuo - machhwsuo. */
6261GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
6262/* machhwu   - machhwu.   */
6263GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
6264/* machhwuo  - machhwuo.  */
6265GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
6266/* maclhw    - maclhw.    */
6267GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
6268/* maclhwo   - maclhwo.   */
6269GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
6270/* maclhws   - maclhws.   */
6271GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
6272/* maclhwso  - maclhwso.  */
6273GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
6274/* maclhwu   - maclhwu.   */
6275GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
6276/* maclhwuo  - maclhwuo.  */
6277GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
6278/* maclhwsu  - maclhwsu.  */
6279GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
6280/* maclhwsuo - maclhwsuo. */
6281GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
6282/* nmacchw   - nmacchw.   */
6283GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
6284/* nmacchwo  - nmacchwo.  */
6285GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
6286/* nmacchws  - nmacchws.  */
6287GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
6288/* nmacchwso - nmacchwso. */
6289GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
6290/* nmachhw   - nmachhw.   */
6291GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
6292/* nmachhwo  - nmachhwo.  */
6293GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
6294/* nmachhws  - nmachhws.  */
6295GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
6296/* nmachhwso - nmachhwso. */
6297GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
6298/* nmaclhw   - nmaclhw.   */
6299GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
6300/* nmaclhwo  - nmaclhwo.  */
6301GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
6302/* nmaclhws  - nmaclhws.  */
6303GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
6304/* nmaclhwso - nmaclhwso. */
6305GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
6306
6307/* mulchw  - mulchw.  */
6308GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
6309/* mulchwu - mulchwu. */
6310GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
6311/* mulhhw  - mulhhw.  */
6312GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
6313/* mulhhwu - mulhhwu. */
6314GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
6315/* mullhw  - mullhw.  */
6316GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
6317/* mullhwu - mullhwu. */
6318GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
6319
6320/* mfdcr */
6321static void gen_mfdcr(DisasContext *ctx)
6322{
6323#if defined(CONFIG_USER_ONLY)
6324    GEN_PRIV;
6325#else
6326    TCGv dcrn;
6327
6328    CHK_SV;
6329    /* NIP cannot be restored if the memory exception comes from an helper */
6330    gen_update_nip(ctx, ctx->nip - 4);
6331    dcrn = tcg_const_tl(SPR(ctx->opcode));
6332    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
6333    tcg_temp_free(dcrn);
6334#endif /* defined(CONFIG_USER_ONLY) */
6335}
6336
6337/* mtdcr */
6338static void gen_mtdcr(DisasContext *ctx)
6339{
6340#if defined(CONFIG_USER_ONLY)
6341    GEN_PRIV;
6342#else
6343    TCGv dcrn;
6344
6345    CHK_SV;
6346    /* NIP cannot be restored if the memory exception comes from an helper */
6347    gen_update_nip(ctx, ctx->nip - 4);
6348    dcrn = tcg_const_tl(SPR(ctx->opcode));
6349    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
6350    tcg_temp_free(dcrn);
6351#endif /* defined(CONFIG_USER_ONLY) */
6352}
6353
6354/* mfdcrx */
6355/* XXX: not implemented on 440 ? */
6356static void gen_mfdcrx(DisasContext *ctx)
6357{
6358#if defined(CONFIG_USER_ONLY)
6359    GEN_PRIV;
6360#else
6361    CHK_SV;
6362    /* NIP cannot be restored if the memory exception comes from an helper */
6363    gen_update_nip(ctx, ctx->nip - 4);
6364    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6365                        cpu_gpr[rA(ctx->opcode)]);
6366    /* Note: Rc update flag set leads to undefined state of Rc0 */
6367#endif /* defined(CONFIG_USER_ONLY) */
6368}
6369
6370/* mtdcrx */
6371/* XXX: not implemented on 440 ? */
6372static void gen_mtdcrx(DisasContext *ctx)
6373{
6374#if defined(CONFIG_USER_ONLY)
6375    GEN_PRIV;
6376#else
6377    CHK_SV;
6378    /* NIP cannot be restored if the memory exception comes from an helper */
6379    gen_update_nip(ctx, ctx->nip - 4);
6380    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
6381                         cpu_gpr[rS(ctx->opcode)]);
6382    /* Note: Rc update flag set leads to undefined state of Rc0 */
6383#endif /* defined(CONFIG_USER_ONLY) */
6384}
6385
6386/* mfdcrux (PPC 460) : user-mode access to DCR */
6387static void gen_mfdcrux(DisasContext *ctx)
6388{
6389    /* NIP cannot be restored if the memory exception comes from an helper */
6390    gen_update_nip(ctx, ctx->nip - 4);
6391    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6392                        cpu_gpr[rA(ctx->opcode)]);
6393    /* Note: Rc update flag set leads to undefined state of Rc0 */
6394}
6395
6396/* mtdcrux (PPC 460) : user-mode access to DCR */
6397static void gen_mtdcrux(DisasContext *ctx)
6398{
6399    /* NIP cannot be restored if the memory exception comes from an helper */
6400    gen_update_nip(ctx, ctx->nip - 4);
6401    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
6402                         cpu_gpr[rS(ctx->opcode)]);
6403    /* Note: Rc update flag set leads to undefined state of Rc0 */
6404}
6405
6406/* dccci */
6407static void gen_dccci(DisasContext *ctx)
6408{
6409    CHK_SV;
6410    /* interpreted as no-op */
6411}
6412
6413/* dcread */
6414static void gen_dcread(DisasContext *ctx)
6415{
6416#if defined(CONFIG_USER_ONLY)
6417    GEN_PRIV;
6418#else
6419    TCGv EA, val;
6420
6421    CHK_SV;
6422    gen_set_access_type(ctx, ACCESS_CACHE);
6423    EA = tcg_temp_new();
6424    gen_addr_reg_index(ctx, EA);
6425    val = tcg_temp_new();
6426    gen_qemu_ld32u(ctx, val, EA);
6427    tcg_temp_free(val);
6428    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
6429    tcg_temp_free(EA);
6430#endif /* defined(CONFIG_USER_ONLY) */
6431}
6432
6433/* icbt */
6434static void gen_icbt_40x(DisasContext *ctx)
6435{
6436    /* interpreted as no-op */
6437    /* XXX: specification say this is treated as a load by the MMU
6438     *      but does not generate any exception
6439     */
6440}
6441
6442/* iccci */
6443static void gen_iccci(DisasContext *ctx)
6444{
6445    CHK_SV;
6446    /* interpreted as no-op */
6447}
6448
6449/* icread */
6450static void gen_icread(DisasContext *ctx)
6451{
6452    CHK_SV;
6453    /* interpreted as no-op */
6454}
6455
6456/* rfci (supervisor only) */
6457static void gen_rfci_40x(DisasContext *ctx)
6458{
6459#if defined(CONFIG_USER_ONLY)
6460    GEN_PRIV;
6461#else
6462    CHK_SV;
6463    /* Restore CPU state */
6464    gen_helper_40x_rfci(cpu_env);
6465    gen_sync_exception(ctx);
6466#endif /* defined(CONFIG_USER_ONLY) */
6467}
6468
6469static void gen_rfci(DisasContext *ctx)
6470{
6471#if defined(CONFIG_USER_ONLY)
6472    GEN_PRIV;
6473#else
6474    CHK_SV;
6475    /* Restore CPU state */
6476    gen_helper_rfci(cpu_env);
6477    gen_sync_exception(ctx);
6478#endif /* defined(CONFIG_USER_ONLY) */
6479}
6480
6481/* BookE specific */
6482
6483/* XXX: not implemented on 440 ? */
6484static void gen_rfdi(DisasContext *ctx)
6485{
6486#if defined(CONFIG_USER_ONLY)
6487    GEN_PRIV;
6488#else
6489    CHK_SV;
6490    /* Restore CPU state */
6491    gen_helper_rfdi(cpu_env);
6492    gen_sync_exception(ctx);
6493#endif /* defined(CONFIG_USER_ONLY) */
6494}
6495
6496/* XXX: not implemented on 440 ? */
6497static void gen_rfmci(DisasContext *ctx)
6498{
6499#if defined(CONFIG_USER_ONLY)
6500    GEN_PRIV;
6501#else
6502    CHK_SV;
6503    /* Restore CPU state */
6504    gen_helper_rfmci(cpu_env);
6505    gen_sync_exception(ctx);
6506#endif /* defined(CONFIG_USER_ONLY) */
6507}
6508
6509/* TLB management - PowerPC 405 implementation */
6510
6511/* tlbre */
6512static void gen_tlbre_40x(DisasContext *ctx)
6513{
6514#if defined(CONFIG_USER_ONLY)
6515    GEN_PRIV;
6516#else
6517    CHK_SV;
6518    switch (rB(ctx->opcode)) {
6519    case 0:
6520        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
6521                                cpu_gpr[rA(ctx->opcode)]);
6522        break;
6523    case 1:
6524        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
6525                                cpu_gpr[rA(ctx->opcode)]);
6526        break;
6527    default:
6528        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6529        break;
6530    }
6531#endif /* defined(CONFIG_USER_ONLY) */
6532}
6533
6534/* tlbsx - tlbsx. */
6535static void gen_tlbsx_40x(DisasContext *ctx)
6536{
6537#if defined(CONFIG_USER_ONLY)
6538    GEN_PRIV;
6539#else
6540    TCGv t0;
6541
6542    CHK_SV;
6543    t0 = tcg_temp_new();
6544    gen_addr_reg_index(ctx, t0);
6545    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6546    tcg_temp_free(t0);
6547    if (Rc(ctx->opcode)) {
6548        TCGLabel *l1 = gen_new_label();
6549        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6550        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6551        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6552        gen_set_label(l1);
6553    }
6554#endif /* defined(CONFIG_USER_ONLY) */
6555}
6556
6557/* tlbwe */
6558static void gen_tlbwe_40x(DisasContext *ctx)
6559{
6560#if defined(CONFIG_USER_ONLY)
6561    GEN_PRIV;
6562#else
6563    CHK_SV;
6564
6565    switch (rB(ctx->opcode)) {
6566    case 0:
6567        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6568                                cpu_gpr[rS(ctx->opcode)]);
6569        break;
6570    case 1:
6571        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6572                                cpu_gpr[rS(ctx->opcode)]);
6573        break;
6574    default:
6575        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6576        break;
6577    }
6578#endif /* defined(CONFIG_USER_ONLY) */
6579}
6580
6581/* TLB management - PowerPC 440 implementation */
6582
6583/* tlbre */
6584static void gen_tlbre_440(DisasContext *ctx)
6585{
6586#if defined(CONFIG_USER_ONLY)
6587    GEN_PRIV;
6588#else
6589    CHK_SV;
6590
6591    switch (rB(ctx->opcode)) {
6592    case 0:
6593    case 1:
6594    case 2:
6595        {
6596            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6597            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6598                                 t0, cpu_gpr[rA(ctx->opcode)]);
6599            tcg_temp_free_i32(t0);
6600        }
6601        break;
6602    default:
6603        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6604        break;
6605    }
6606#endif /* defined(CONFIG_USER_ONLY) */
6607}
6608
6609/* tlbsx - tlbsx. */
6610static void gen_tlbsx_440(DisasContext *ctx)
6611{
6612#if defined(CONFIG_USER_ONLY)
6613    GEN_PRIV;
6614#else
6615    TCGv t0;
6616
6617    CHK_SV;
6618    t0 = tcg_temp_new();
6619    gen_addr_reg_index(ctx, t0);
6620    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6621    tcg_temp_free(t0);
6622    if (Rc(ctx->opcode)) {
6623        TCGLabel *l1 = gen_new_label();
6624        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6625        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6626        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6627        gen_set_label(l1);
6628    }
6629#endif /* defined(CONFIG_USER_ONLY) */
6630}
6631
6632/* tlbwe */
6633static void gen_tlbwe_440(DisasContext *ctx)
6634{
6635#if defined(CONFIG_USER_ONLY)
6636    GEN_PRIV;
6637#else
6638    CHK_SV;
6639    switch (rB(ctx->opcode)) {
6640    case 0:
6641    case 1:
6642    case 2:
6643        {
6644            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6645            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6646                                 cpu_gpr[rS(ctx->opcode)]);
6647            tcg_temp_free_i32(t0);
6648        }
6649        break;
6650    default:
6651        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6652        break;
6653    }
6654#endif /* defined(CONFIG_USER_ONLY) */
6655}
6656
6657/* TLB management - PowerPC BookE 2.06 implementation */
6658
6659/* tlbre */
6660static void gen_tlbre_booke206(DisasContext *ctx)
6661{
6662 #if defined(CONFIG_USER_ONLY)
6663    GEN_PRIV;
6664#else
6665   CHK_SV;
6666    gen_helper_booke206_tlbre(cpu_env);
6667#endif /* defined(CONFIG_USER_ONLY) */
6668}
6669
6670/* tlbsx - tlbsx. */
6671static void gen_tlbsx_booke206(DisasContext *ctx)
6672{
6673#if defined(CONFIG_USER_ONLY)
6674    GEN_PRIV;
6675#else
6676    TCGv t0;
6677
6678    CHK_SV;
6679    if (rA(ctx->opcode)) {
6680        t0 = tcg_temp_new();
6681        tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6682    } else {
6683        t0 = tcg_const_tl(0);
6684    }
6685
6686    tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6687    gen_helper_booke206_tlbsx(cpu_env, t0);
6688    tcg_temp_free(t0);
6689#endif /* defined(CONFIG_USER_ONLY) */
6690}
6691
6692/* tlbwe */
6693static void gen_tlbwe_booke206(DisasContext *ctx)
6694{
6695#if defined(CONFIG_USER_ONLY)
6696    GEN_PRIV;
6697#else
6698    CHK_SV;
6699    gen_update_nip(ctx, ctx->nip - 4);
6700    gen_helper_booke206_tlbwe(cpu_env);
6701#endif /* defined(CONFIG_USER_ONLY) */
6702}
6703
6704static void gen_tlbivax_booke206(DisasContext *ctx)
6705{
6706#if defined(CONFIG_USER_ONLY)
6707    GEN_PRIV;
6708#else
6709    TCGv t0;
6710
6711    CHK_SV;
6712    t0 = tcg_temp_new();
6713    gen_addr_reg_index(ctx, t0);
6714    gen_helper_booke206_tlbivax(cpu_env, t0);
6715    tcg_temp_free(t0);
6716#endif /* defined(CONFIG_USER_ONLY) */
6717}
6718
6719static void gen_tlbilx_booke206(DisasContext *ctx)
6720{
6721#if defined(CONFIG_USER_ONLY)
6722    GEN_PRIV;
6723#else
6724    TCGv t0;
6725
6726    CHK_SV;
6727    t0 = tcg_temp_new();
6728    gen_addr_reg_index(ctx, t0);
6729
6730    switch((ctx->opcode >> 21) & 0x3) {
6731    case 0:
6732        gen_helper_booke206_tlbilx0(cpu_env, t0);
6733        break;
6734    case 1:
6735        gen_helper_booke206_tlbilx1(cpu_env, t0);
6736        break;
6737    case 3:
6738        gen_helper_booke206_tlbilx3(cpu_env, t0);
6739        break;
6740    default:
6741        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6742        break;
6743    }
6744
6745    tcg_temp_free(t0);
6746#endif /* defined(CONFIG_USER_ONLY) */
6747}
6748
6749
6750/* wrtee */
6751static void gen_wrtee(DisasContext *ctx)
6752{
6753#if defined(CONFIG_USER_ONLY)
6754    GEN_PRIV;
6755#else
6756    TCGv t0;
6757
6758    CHK_SV;
6759    t0 = tcg_temp_new();
6760    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6761    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6762    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6763    tcg_temp_free(t0);
6764    /* Stop translation to have a chance to raise an exception
6765     * if we just set msr_ee to 1
6766     */
6767    gen_stop_exception(ctx);
6768#endif /* defined(CONFIG_USER_ONLY) */
6769}
6770
6771/* wrteei */
6772static void gen_wrteei(DisasContext *ctx)
6773{
6774#if defined(CONFIG_USER_ONLY)
6775    GEN_PRIV;
6776#else
6777    CHK_SV;
6778    if (ctx->opcode & 0x00008000) {
6779        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6780        /* Stop translation to have a chance to raise an exception */
6781        gen_stop_exception(ctx);
6782    } else {
6783        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6784    }
6785#endif /* defined(CONFIG_USER_ONLY) */
6786}
6787
6788/* PowerPC 440 specific instructions */
6789
6790/* dlmzb */
6791static void gen_dlmzb(DisasContext *ctx)
6792{
6793    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6794    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6795                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6796    tcg_temp_free_i32(t0);
6797}
6798
6799/* mbar replaces eieio on 440 */
6800static void gen_mbar(DisasContext *ctx)
6801{
6802    /* interpreted as no-op */
6803}
6804
6805/* msync replaces sync on 440 */
6806static void gen_msync_4xx(DisasContext *ctx)
6807{
6808    /* interpreted as no-op */
6809}
6810
6811/* icbt */
6812static void gen_icbt_440(DisasContext *ctx)
6813{
6814    /* interpreted as no-op */
6815    /* XXX: specification say this is treated as a load by the MMU
6816     *      but does not generate any exception
6817     */
6818}
6819
6820/* Embedded.Processor Control */
6821
6822static void gen_msgclr(DisasContext *ctx)
6823{
6824#if defined(CONFIG_USER_ONLY)
6825    GEN_PRIV;
6826#else
6827    CHK_SV;
6828    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
6829#endif /* defined(CONFIG_USER_ONLY) */
6830}
6831
6832static void gen_msgsnd(DisasContext *ctx)
6833{
6834#if defined(CONFIG_USER_ONLY)
6835    GEN_PRIV;
6836#else
6837    CHK_SV;
6838    gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
6839#endif /* defined(CONFIG_USER_ONLY) */
6840}
6841
6842/***                      Altivec vector extension                         ***/
6843/* Altivec registers moves */
6844
6845static inline TCGv_ptr gen_avr_ptr(int reg)
6846{
6847    TCGv_ptr r = tcg_temp_new_ptr();
6848    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6849    return r;
6850}
6851
6852#define GEN_VR_LDX(name, opc2, opc3)                                          \
6853static void glue(gen_, name)(DisasContext *ctx)                                       \
6854{                                                                             \
6855    TCGv EA;                                                                  \
6856    if (unlikely(!ctx->altivec_enabled)) {                                    \
6857        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6858        return;                                                               \
6859    }                                                                         \
6860    gen_set_access_type(ctx, ACCESS_INT);                                     \
6861    EA = tcg_temp_new();                                                      \
6862    gen_addr_reg_index(ctx, EA);                                              \
6863    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6864    /* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
6865       64-bit byteswap already. */                                            \
6866    if (ctx->le_mode) {                                                       \
6867        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6868        tcg_gen_addi_tl(EA, EA, 8);                                           \
6869        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6870    } else {                                                                  \
6871        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6872        tcg_gen_addi_tl(EA, EA, 8);                                           \
6873        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6874    }                                                                         \
6875    tcg_temp_free(EA);                                                        \
6876}
6877
6878#define GEN_VR_STX(name, opc2, opc3)                                          \
6879static void gen_st##name(DisasContext *ctx)                                   \
6880{                                                                             \
6881    TCGv EA;                                                                  \
6882    if (unlikely(!ctx->altivec_enabled)) {                                    \
6883        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6884        return;                                                               \
6885    }                                                                         \
6886    gen_set_access_type(ctx, ACCESS_INT);                                     \
6887    EA = tcg_temp_new();                                                      \
6888    gen_addr_reg_index(ctx, EA);                                              \
6889    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6890    /* We only need to swap high and low halves. gen_qemu_st64 does necessary \
6891       64-bit byteswap already. */                                            \
6892    if (ctx->le_mode) {                                                       \
6893        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6894        tcg_gen_addi_tl(EA, EA, 8);                                           \
6895        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6896    } else {                                                                  \
6897        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6898        tcg_gen_addi_tl(EA, EA, 8);                                           \
6899        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6900    }                                                                         \
6901    tcg_temp_free(EA);                                                        \
6902}
6903
6904#define GEN_VR_LVE(name, opc2, opc3, size)                              \
6905static void gen_lve##name(DisasContext *ctx)                            \
6906    {                                                                   \
6907        TCGv EA;                                                        \
6908        TCGv_ptr rs;                                                    \
6909        if (unlikely(!ctx->altivec_enabled)) {                          \
6910            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6911            return;                                                     \
6912        }                                                               \
6913        gen_set_access_type(ctx, ACCESS_INT);                           \
6914        EA = tcg_temp_new();                                            \
6915        gen_addr_reg_index(ctx, EA);                                    \
6916        if (size > 1) {                                                 \
6917            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
6918        }                                                               \
6919        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6920        gen_helper_lve##name(cpu_env, rs, EA);                          \
6921        tcg_temp_free(EA);                                              \
6922        tcg_temp_free_ptr(rs);                                          \
6923    }
6924
6925#define GEN_VR_STVE(name, opc2, opc3, size)                             \
6926static void gen_stve##name(DisasContext *ctx)                           \
6927    {                                                                   \
6928        TCGv EA;                                                        \
6929        TCGv_ptr rs;                                                    \
6930        if (unlikely(!ctx->altivec_enabled)) {                          \
6931            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6932            return;                                                     \
6933        }                                                               \
6934        gen_set_access_type(ctx, ACCESS_INT);                           \
6935        EA = tcg_temp_new();                                            \
6936        gen_addr_reg_index(ctx, EA);                                    \
6937        if (size > 1) {                                                 \
6938            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
6939        }                                                               \
6940        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6941        gen_helper_stve##name(cpu_env, rs, EA);                         \
6942        tcg_temp_free(EA);                                              \
6943        tcg_temp_free_ptr(rs);                                          \
6944    }
6945
6946GEN_VR_LDX(lvx, 0x07, 0x03);
6947/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6948GEN_VR_LDX(lvxl, 0x07, 0x0B);
6949
6950GEN_VR_LVE(bx, 0x07, 0x00, 1);
6951GEN_VR_LVE(hx, 0x07, 0x01, 2);
6952GEN_VR_LVE(wx, 0x07, 0x02, 4);
6953
6954GEN_VR_STX(svx, 0x07, 0x07);
6955/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6956GEN_VR_STX(svxl, 0x07, 0x0F);
6957
6958GEN_VR_STVE(bx, 0x07, 0x04, 1);
6959GEN_VR_STVE(hx, 0x07, 0x05, 2);
6960GEN_VR_STVE(wx, 0x07, 0x06, 4);
6961
6962static void gen_lvsl(DisasContext *ctx)
6963{
6964    TCGv_ptr rd;
6965    TCGv EA;
6966    if (unlikely(!ctx->altivec_enabled)) {
6967        gen_exception(ctx, POWERPC_EXCP_VPU);
6968        return;
6969    }
6970    EA = tcg_temp_new();
6971    gen_addr_reg_index(ctx, EA);
6972    rd = gen_avr_ptr(rD(ctx->opcode));
6973    gen_helper_lvsl(rd, EA);
6974    tcg_temp_free(EA);
6975    tcg_temp_free_ptr(rd);
6976}
6977
6978static void gen_lvsr(DisasContext *ctx)
6979{
6980    TCGv_ptr rd;
6981    TCGv EA;
6982    if (unlikely(!ctx->altivec_enabled)) {
6983        gen_exception(ctx, POWERPC_EXCP_VPU);
6984        return;
6985    }
6986    EA = tcg_temp_new();
6987    gen_addr_reg_index(ctx, EA);
6988    rd = gen_avr_ptr(rD(ctx->opcode));
6989    gen_helper_lvsr(rd, EA);
6990    tcg_temp_free(EA);
6991    tcg_temp_free_ptr(rd);
6992}
6993
6994static void gen_mfvscr(DisasContext *ctx)
6995{
6996    TCGv_i32 t;
6997    if (unlikely(!ctx->altivec_enabled)) {
6998        gen_exception(ctx, POWERPC_EXCP_VPU);
6999        return;
7000    }
7001    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
7002    t = tcg_temp_new_i32();
7003    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
7004    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
7005    tcg_temp_free_i32(t);
7006}
7007
7008static void gen_mtvscr(DisasContext *ctx)
7009{
7010    TCGv_ptr p;
7011    if (unlikely(!ctx->altivec_enabled)) {
7012        gen_exception(ctx, POWERPC_EXCP_VPU);
7013        return;
7014    }
7015    p = gen_avr_ptr(rB(ctx->opcode));
7016    gen_helper_mtvscr(cpu_env, p);
7017    tcg_temp_free_ptr(p);
7018}
7019
7020/* Logical operations */
7021#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
7022static void glue(gen_, name)(DisasContext *ctx)                                 \
7023{                                                                       \
7024    if (unlikely(!ctx->altivec_enabled)) {                              \
7025        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
7026        return;                                                         \
7027    }                                                                   \
7028    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
7029    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
7030}
7031
7032GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
7033GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
7034GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
7035GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
7036GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
7037GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
7038GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
7039GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
7040
7041#define GEN_VXFORM(name, opc2, opc3)                                    \
7042static void glue(gen_, name)(DisasContext *ctx)                                 \
7043{                                                                       \
7044    TCGv_ptr ra, rb, rd;                                                \
7045    if (unlikely(!ctx->altivec_enabled)) {                              \
7046        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
7047        return;                                                         \
7048    }                                                                   \
7049    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
7050    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
7051    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
7052    gen_helper_##name (rd, ra, rb);                                     \
7053    tcg_temp_free_ptr(ra);                                              \
7054    tcg_temp_free_ptr(rb);                                              \
7055    tcg_temp_free_ptr(rd);                                              \
7056}
7057
7058#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
7059static void glue(gen_, name)(DisasContext *ctx)                         \
7060{                                                                       \
7061    TCGv_ptr ra, rb, rd;                                                \
7062    if (unlikely(!ctx->altivec_enabled)) {                              \
7063        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
7064        return;                                                         \
7065    }                                                                   \
7066    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
7067    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
7068    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
7069    gen_helper_##name(cpu_env, rd, ra, rb);                             \
7070    tcg_temp_free_ptr(ra);                                              \
7071    tcg_temp_free_ptr(rb);                                              \
7072    tcg_temp_free_ptr(rd);                                              \
7073}
7074
7075#define GEN_VXFORM3(name, opc2, opc3)                                   \
7076static void glue(gen_, name)(DisasContext *ctx)                         \
7077{                                                                       \
7078    TCGv_ptr ra, rb, rc, rd;                                            \
7079    if (unlikely(!ctx->altivec_enabled)) {                              \
7080        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
7081        return;                                                         \
7082    }                                                                   \
7083    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
7084    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
7085    rc = gen_avr_ptr(rC(ctx->opcode));                                  \
7086    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
7087    gen_helper_##name(rd, ra, rb, rc);                                  \
7088    tcg_temp_free_ptr(ra);                                              \
7089    tcg_temp_free_ptr(rb);                                              \
7090    tcg_temp_free_ptr(rc);                                              \
7091    tcg_temp_free_ptr(rd);                                              \
7092}
7093
7094/*
7095 * Support for Altivec instruction pairs that use bit 31 (Rc) as
7096 * an opcode bit.  In general, these pairs come from different
7097 * versions of the ISA, so we must also support a pair of flags for
7098 * each instruction.
7099 */
7100#define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)          \
7101static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
7102{                                                                      \
7103    if ((Rc(ctx->opcode) == 0) &&                                      \
7104        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7105        gen_##name0(ctx);                                              \
7106    } else if ((Rc(ctx->opcode) == 1) &&                               \
7107        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7108        gen_##name1(ctx);                                              \
7109    } else {                                                           \
7110        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
7111    }                                                                  \
7112}
7113
7114GEN_VXFORM(vaddubm, 0, 0);
7115GEN_VXFORM(vadduhm, 0, 1);
7116GEN_VXFORM(vadduwm, 0, 2);
7117GEN_VXFORM(vaddudm, 0, 3);
7118GEN_VXFORM(vsububm, 0, 16);
7119GEN_VXFORM(vsubuhm, 0, 17);
7120GEN_VXFORM(vsubuwm, 0, 18);
7121GEN_VXFORM(vsubudm, 0, 19);
7122GEN_VXFORM(vmaxub, 1, 0);
7123GEN_VXFORM(vmaxuh, 1, 1);
7124GEN_VXFORM(vmaxuw, 1, 2);
7125GEN_VXFORM(vmaxud, 1, 3);
7126GEN_VXFORM(vmaxsb, 1, 4);
7127GEN_VXFORM(vmaxsh, 1, 5);
7128GEN_VXFORM(vmaxsw, 1, 6);
7129GEN_VXFORM(vmaxsd, 1, 7);
7130GEN_VXFORM(vminub, 1, 8);
7131GEN_VXFORM(vminuh, 1, 9);
7132GEN_VXFORM(vminuw, 1, 10);
7133GEN_VXFORM(vminud, 1, 11);
7134GEN_VXFORM(vminsb, 1, 12);
7135GEN_VXFORM(vminsh, 1, 13);
7136GEN_VXFORM(vminsw, 1, 14);
7137GEN_VXFORM(vminsd, 1, 15);
7138GEN_VXFORM(vavgub, 1, 16);
7139GEN_VXFORM(vavguh, 1, 17);
7140GEN_VXFORM(vavguw, 1, 18);
7141GEN_VXFORM(vavgsb, 1, 20);
7142GEN_VXFORM(vavgsh, 1, 21);
7143GEN_VXFORM(vavgsw, 1, 22);
7144GEN_VXFORM(vmrghb, 6, 0);
7145GEN_VXFORM(vmrghh, 6, 1);
7146GEN_VXFORM(vmrghw, 6, 2);
7147GEN_VXFORM(vmrglb, 6, 4);
7148GEN_VXFORM(vmrglh, 6, 5);
7149GEN_VXFORM(vmrglw, 6, 6);
7150
7151static void gen_vmrgew(DisasContext *ctx)
7152{
7153    TCGv_i64 tmp;
7154    int VT, VA, VB;
7155    if (unlikely(!ctx->altivec_enabled)) {
7156        gen_exception(ctx, POWERPC_EXCP_VPU);
7157        return;
7158    }
7159    VT = rD(ctx->opcode);
7160    VA = rA(ctx->opcode);
7161    VB = rB(ctx->opcode);
7162    tmp = tcg_temp_new_i64();
7163    tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32);
7164    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32);
7165    tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32);
7166    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32);
7167    tcg_temp_free_i64(tmp);
7168}
7169
7170static void gen_vmrgow(DisasContext *ctx)
7171{
7172    int VT, VA, VB;
7173    if (unlikely(!ctx->altivec_enabled)) {
7174        gen_exception(ctx, POWERPC_EXCP_VPU);
7175        return;
7176    }
7177    VT = rD(ctx->opcode);
7178    VA = rA(ctx->opcode);
7179    VB = rB(ctx->opcode);
7180
7181    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32);
7182    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32);
7183}
7184
7185GEN_VXFORM(vmuloub, 4, 0);
7186GEN_VXFORM(vmulouh, 4, 1);
7187GEN_VXFORM(vmulouw, 4, 2);
7188GEN_VXFORM(vmuluwm, 4, 2);
7189GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
7190                vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
7191GEN_VXFORM(vmulosb, 4, 4);
7192GEN_VXFORM(vmulosh, 4, 5);
7193GEN_VXFORM(vmulosw, 4, 6);
7194GEN_VXFORM(vmuleub, 4, 8);
7195GEN_VXFORM(vmuleuh, 4, 9);
7196GEN_VXFORM(vmuleuw, 4, 10);
7197GEN_VXFORM(vmulesb, 4, 12);
7198GEN_VXFORM(vmulesh, 4, 13);
7199GEN_VXFORM(vmulesw, 4, 14);
7200GEN_VXFORM(vslb, 2, 4);
7201GEN_VXFORM(vslh, 2, 5);
7202GEN_VXFORM(vslw, 2, 6);
7203GEN_VXFORM(vsld, 2, 23);
7204GEN_VXFORM(vsrb, 2, 8);
7205GEN_VXFORM(vsrh, 2, 9);
7206GEN_VXFORM(vsrw, 2, 10);
7207GEN_VXFORM(vsrd, 2, 27);
7208GEN_VXFORM(vsrab, 2, 12);
7209GEN_VXFORM(vsrah, 2, 13);
7210GEN_VXFORM(vsraw, 2, 14);
7211GEN_VXFORM(vsrad, 2, 15);
7212GEN_VXFORM(vslo, 6, 16);
7213GEN_VXFORM(vsro, 6, 17);
7214GEN_VXFORM(vaddcuw, 0, 6);
7215GEN_VXFORM(vsubcuw, 0, 22);
7216GEN_VXFORM_ENV(vaddubs, 0, 8);
7217GEN_VXFORM_ENV(vadduhs, 0, 9);
7218GEN_VXFORM_ENV(vadduws, 0, 10);
7219GEN_VXFORM_ENV(vaddsbs, 0, 12);
7220GEN_VXFORM_ENV(vaddshs, 0, 13);
7221GEN_VXFORM_ENV(vaddsws, 0, 14);
7222GEN_VXFORM_ENV(vsububs, 0, 24);
7223GEN_VXFORM_ENV(vsubuhs, 0, 25);
7224GEN_VXFORM_ENV(vsubuws, 0, 26);
7225GEN_VXFORM_ENV(vsubsbs, 0, 28);
7226GEN_VXFORM_ENV(vsubshs, 0, 29);
7227GEN_VXFORM_ENV(vsubsws, 0, 30);
7228GEN_VXFORM(vadduqm, 0, 4);
7229GEN_VXFORM(vaddcuq, 0, 5);
7230GEN_VXFORM3(vaddeuqm, 30, 0);
7231GEN_VXFORM3(vaddecuq, 30, 0);
7232GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7233            vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
7234GEN_VXFORM(vsubuqm, 0, 20);
7235GEN_VXFORM(vsubcuq, 0, 21);
7236GEN_VXFORM3(vsubeuqm, 31, 0);
7237GEN_VXFORM3(vsubecuq, 31, 0);
7238GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7239            vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
7240GEN_VXFORM(vrlb, 2, 0);
7241GEN_VXFORM(vrlh, 2, 1);
7242GEN_VXFORM(vrlw, 2, 2);
7243GEN_VXFORM(vrld, 2, 3);
7244GEN_VXFORM(vsl, 2, 7);
7245GEN_VXFORM(vsr, 2, 11);
7246GEN_VXFORM_ENV(vpkuhum, 7, 0);
7247GEN_VXFORM_ENV(vpkuwum, 7, 1);
7248GEN_VXFORM_ENV(vpkudum, 7, 17);
7249GEN_VXFORM_ENV(vpkuhus, 7, 2);
7250GEN_VXFORM_ENV(vpkuwus, 7, 3);
7251GEN_VXFORM_ENV(vpkudus, 7, 19);
7252GEN_VXFORM_ENV(vpkshus, 7, 4);
7253GEN_VXFORM_ENV(vpkswus, 7, 5);
7254GEN_VXFORM_ENV(vpksdus, 7, 21);
7255GEN_VXFORM_ENV(vpkshss, 7, 6);
7256GEN_VXFORM_ENV(vpkswss, 7, 7);
7257GEN_VXFORM_ENV(vpksdss, 7, 23);
7258GEN_VXFORM(vpkpx, 7, 12);
7259GEN_VXFORM_ENV(vsum4ubs, 4, 24);
7260GEN_VXFORM_ENV(vsum4sbs, 4, 28);
7261GEN_VXFORM_ENV(vsum4shs, 4, 25);
7262GEN_VXFORM_ENV(vsum2sws, 4, 26);
7263GEN_VXFORM_ENV(vsumsws, 4, 30);
7264GEN_VXFORM_ENV(vaddfp, 5, 0);
7265GEN_VXFORM_ENV(vsubfp, 5, 1);
7266GEN_VXFORM_ENV(vmaxfp, 5, 16);
7267GEN_VXFORM_ENV(vminfp, 5, 17);
7268
7269#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
7270static void glue(gen_, name)(DisasContext *ctx)                         \
7271    {                                                                   \
7272        TCGv_ptr ra, rb, rd;                                            \
7273        if (unlikely(!ctx->altivec_enabled)) {                          \
7274            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7275            return;                                                     \
7276        }                                                               \
7277        ra = gen_avr_ptr(rA(ctx->opcode));                              \
7278        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7279        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7280        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
7281        tcg_temp_free_ptr(ra);                                          \
7282        tcg_temp_free_ptr(rb);                                          \
7283        tcg_temp_free_ptr(rd);                                          \
7284    }
7285
7286#define GEN_VXRFORM(name, opc2, opc3)                                \
7287    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
7288    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
7289
7290/*
7291 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
7292 * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
7293 * come from different versions of the ISA, so we must also support a
7294 * pair of flags for each instruction.
7295 */
7296#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
7297static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
7298{                                                                      \
7299    if ((Rc(ctx->opcode) == 0) &&                                      \
7300        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7301        if (Rc21(ctx->opcode) == 0) {                                  \
7302            gen_##name0(ctx);                                          \
7303        } else {                                                       \
7304            gen_##name0##_(ctx);                                       \
7305        }                                                              \
7306    } else if ((Rc(ctx->opcode) == 1) &&                               \
7307        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7308        if (Rc21(ctx->opcode) == 0) {                                  \
7309            gen_##name1(ctx);                                          \
7310        } else {                                                       \
7311            gen_##name1##_(ctx);                                       \
7312        }                                                              \
7313    } else {                                                           \
7314        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
7315    }                                                                  \
7316}
7317
7318GEN_VXRFORM(vcmpequb, 3, 0)
7319GEN_VXRFORM(vcmpequh, 3, 1)
7320GEN_VXRFORM(vcmpequw, 3, 2)
7321GEN_VXRFORM(vcmpequd, 3, 3)
7322GEN_VXRFORM(vcmpgtsb, 3, 12)
7323GEN_VXRFORM(vcmpgtsh, 3, 13)
7324GEN_VXRFORM(vcmpgtsw, 3, 14)
7325GEN_VXRFORM(vcmpgtsd, 3, 15)
7326GEN_VXRFORM(vcmpgtub, 3, 8)
7327GEN_VXRFORM(vcmpgtuh, 3, 9)
7328GEN_VXRFORM(vcmpgtuw, 3, 10)
7329GEN_VXRFORM(vcmpgtud, 3, 11)
7330GEN_VXRFORM(vcmpeqfp, 3, 3)
7331GEN_VXRFORM(vcmpgefp, 3, 7)
7332GEN_VXRFORM(vcmpgtfp, 3, 11)
7333GEN_VXRFORM(vcmpbfp, 3, 15)
7334
7335GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
7336                 vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
7337GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
7338                 vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
7339GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
7340                 vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
7341
7342#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
7343static void glue(gen_, name)(DisasContext *ctx)                         \
7344    {                                                                   \
7345        TCGv_ptr rd;                                                    \
7346        TCGv_i32 simm;                                                  \
7347        if (unlikely(!ctx->altivec_enabled)) {                          \
7348            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7349            return;                                                     \
7350        }                                                               \
7351        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
7352        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7353        gen_helper_##name (rd, simm);                                   \
7354        tcg_temp_free_i32(simm);                                        \
7355        tcg_temp_free_ptr(rd);                                          \
7356    }
7357
7358GEN_VXFORM_SIMM(vspltisb, 6, 12);
7359GEN_VXFORM_SIMM(vspltish, 6, 13);
7360GEN_VXFORM_SIMM(vspltisw, 6, 14);
7361
7362#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
7363static void glue(gen_, name)(DisasContext *ctx)                                 \
7364    {                                                                   \
7365        TCGv_ptr rb, rd;                                                \
7366        if (unlikely(!ctx->altivec_enabled)) {                          \
7367            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7368            return;                                                     \
7369        }                                                               \
7370        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7371        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7372        gen_helper_##name (rd, rb);                                     \
7373        tcg_temp_free_ptr(rb);                                          \
7374        tcg_temp_free_ptr(rd);                                         \
7375    }
7376
7377#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
7378static void glue(gen_, name)(DisasContext *ctx)                         \
7379    {                                                                   \
7380        TCGv_ptr rb, rd;                                                \
7381                                                                        \
7382        if (unlikely(!ctx->altivec_enabled)) {                          \
7383            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7384            return;                                                     \
7385        }                                                               \
7386        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7387        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7388        gen_helper_##name(cpu_env, rd, rb);                             \
7389        tcg_temp_free_ptr(rb);                                          \
7390        tcg_temp_free_ptr(rd);                                          \
7391    }
7392
7393GEN_VXFORM_NOA(vupkhsb, 7, 8);
7394GEN_VXFORM_NOA(vupkhsh, 7, 9);
7395GEN_VXFORM_NOA(vupkhsw, 7, 25);
7396GEN_VXFORM_NOA(vupklsb, 7, 10);
7397GEN_VXFORM_NOA(vupklsh, 7, 11);
7398GEN_VXFORM_NOA(vupklsw, 7, 27);
7399GEN_VXFORM_NOA(vupkhpx, 7, 13);
7400GEN_VXFORM_NOA(vupklpx, 7, 15);
7401GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
7402GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
7403GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
7404GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
7405GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
7406GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
7407GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
7408GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
7409
7410#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
7411static void glue(gen_, name)(DisasContext *ctx)                                 \
7412    {                                                                   \
7413        TCGv_ptr rd;                                                    \
7414        TCGv_i32 simm;                                                  \
7415        if (unlikely(!ctx->altivec_enabled)) {                          \
7416            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7417            return;                                                     \
7418        }                                                               \
7419        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
7420        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7421        gen_helper_##name (rd, simm);                                   \
7422        tcg_temp_free_i32(simm);                                        \
7423        tcg_temp_free_ptr(rd);                                          \
7424    }
7425
7426#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
7427static void glue(gen_, name)(DisasContext *ctx)                                 \
7428    {                                                                   \
7429        TCGv_ptr rb, rd;                                                \
7430        TCGv_i32 uimm;                                                  \
7431        if (unlikely(!ctx->altivec_enabled)) {                          \
7432            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7433            return;                                                     \
7434        }                                                               \
7435        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
7436        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7437        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7438        gen_helper_##name (rd, rb, uimm);                               \
7439        tcg_temp_free_i32(uimm);                                        \
7440        tcg_temp_free_ptr(rb);                                          \
7441        tcg_temp_free_ptr(rd);                                          \
7442    }
7443
7444#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
7445static void glue(gen_, name)(DisasContext *ctx)                         \
7446    {                                                                   \
7447        TCGv_ptr rb, rd;                                                \
7448        TCGv_i32 uimm;                                                  \
7449                                                                        \
7450        if (unlikely(!ctx->altivec_enabled)) {                          \
7451            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7452            return;                                                     \
7453        }                                                               \
7454        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
7455        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7456        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7457        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
7458        tcg_temp_free_i32(uimm);                                        \
7459        tcg_temp_free_ptr(rb);                                          \
7460        tcg_temp_free_ptr(rd);                                          \
7461    }
7462
7463GEN_VXFORM_UIMM(vspltb, 6, 8);
7464GEN_VXFORM_UIMM(vsplth, 6, 9);
7465GEN_VXFORM_UIMM(vspltw, 6, 10);
7466GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
7467GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
7468GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
7469GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
7470
7471static void gen_vsldoi(DisasContext *ctx)
7472{
7473    TCGv_ptr ra, rb, rd;
7474    TCGv_i32 sh;
7475    if (unlikely(!ctx->altivec_enabled)) {
7476        gen_exception(ctx, POWERPC_EXCP_VPU);
7477        return;
7478    }
7479    ra = gen_avr_ptr(rA(ctx->opcode));
7480    rb = gen_avr_ptr(rB(ctx->opcode));
7481    rd = gen_avr_ptr(rD(ctx->opcode));
7482    sh = tcg_const_i32(VSH(ctx->opcode));
7483    gen_helper_vsldoi (rd, ra, rb, sh);
7484    tcg_temp_free_ptr(ra);
7485    tcg_temp_free_ptr(rb);
7486    tcg_temp_free_ptr(rd);
7487    tcg_temp_free_i32(sh);
7488}
7489
7490#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
7491static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
7492    {                                                                   \
7493        TCGv_ptr ra, rb, rc, rd;                                        \
7494        if (unlikely(!ctx->altivec_enabled)) {                          \
7495            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
7496            return;                                                     \
7497        }                                                               \
7498        ra = gen_avr_ptr(rA(ctx->opcode));                              \
7499        rb = gen_avr_ptr(rB(ctx->opcode));                              \
7500        rc = gen_avr_ptr(rC(ctx->opcode));                              \
7501        rd = gen_avr_ptr(rD(ctx->opcode));                              \
7502        if (Rc(ctx->opcode)) {                                          \
7503            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
7504        } else {                                                        \
7505            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
7506        }                                                               \
7507        tcg_temp_free_ptr(ra);                                          \
7508        tcg_temp_free_ptr(rb);                                          \
7509        tcg_temp_free_ptr(rc);                                          \
7510        tcg_temp_free_ptr(rd);                                          \
7511    }
7512
7513GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
7514
7515static void gen_vmladduhm(DisasContext *ctx)
7516{
7517    TCGv_ptr ra, rb, rc, rd;
7518    if (unlikely(!ctx->altivec_enabled)) {
7519        gen_exception(ctx, POWERPC_EXCP_VPU);
7520        return;
7521    }
7522    ra = gen_avr_ptr(rA(ctx->opcode));
7523    rb = gen_avr_ptr(rB(ctx->opcode));
7524    rc = gen_avr_ptr(rC(ctx->opcode));
7525    rd = gen_avr_ptr(rD(ctx->opcode));
7526    gen_helper_vmladduhm(rd, ra, rb, rc);
7527    tcg_temp_free_ptr(ra);
7528    tcg_temp_free_ptr(rb);
7529    tcg_temp_free_ptr(rc);
7530    tcg_temp_free_ptr(rd);
7531}
7532
7533GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
7534GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
7535GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
7536GEN_VAFORM_PAIRED(vsel, vperm, 21)
7537GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
7538
7539GEN_VXFORM_NOA(vclzb, 1, 28)
7540GEN_VXFORM_NOA(vclzh, 1, 29)
7541GEN_VXFORM_NOA(vclzw, 1, 30)
7542GEN_VXFORM_NOA(vclzd, 1, 31)
7543GEN_VXFORM_NOA(vpopcntb, 1, 28)
7544GEN_VXFORM_NOA(vpopcnth, 1, 29)
7545GEN_VXFORM_NOA(vpopcntw, 1, 30)
7546GEN_VXFORM_NOA(vpopcntd, 1, 31)
7547GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
7548                vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
7549GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
7550                vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
7551GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
7552                vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
7553GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
7554                vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
7555GEN_VXFORM(vbpermq, 6, 21);
7556GEN_VXFORM_NOA(vgbbd, 6, 20);
7557GEN_VXFORM(vpmsumb, 4, 16)
7558GEN_VXFORM(vpmsumh, 4, 17)
7559GEN_VXFORM(vpmsumw, 4, 18)
7560GEN_VXFORM(vpmsumd, 4, 19)
7561
7562#define GEN_BCD(op)                                 \
7563static void gen_##op(DisasContext *ctx)             \
7564{                                                   \
7565    TCGv_ptr ra, rb, rd;                            \
7566    TCGv_i32 ps;                                    \
7567                                                    \
7568    if (unlikely(!ctx->altivec_enabled)) {          \
7569        gen_exception(ctx, POWERPC_EXCP_VPU);       \
7570        return;                                     \
7571    }                                               \
7572                                                    \
7573    ra = gen_avr_ptr(rA(ctx->opcode));              \
7574    rb = gen_avr_ptr(rB(ctx->opcode));              \
7575    rd = gen_avr_ptr(rD(ctx->opcode));              \
7576                                                    \
7577    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
7578                                                    \
7579    gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
7580                                                    \
7581    tcg_temp_free_ptr(ra);                          \
7582    tcg_temp_free_ptr(rb);                          \
7583    tcg_temp_free_ptr(rd);                          \
7584    tcg_temp_free_i32(ps);                          \
7585}
7586
7587GEN_BCD(bcdadd)
7588GEN_BCD(bcdsub)
7589
7590GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
7591                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7592GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
7593                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7594GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
7595                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7596GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
7597                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7598
7599static void gen_vsbox(DisasContext *ctx)
7600{
7601    TCGv_ptr ra, rd;
7602    if (unlikely(!ctx->altivec_enabled)) {
7603        gen_exception(ctx, POWERPC_EXCP_VPU);
7604        return;
7605    }
7606    ra = gen_avr_ptr(rA(ctx->opcode));
7607    rd = gen_avr_ptr(rD(ctx->opcode));
7608    gen_helper_vsbox(rd, ra);
7609    tcg_temp_free_ptr(ra);
7610    tcg_temp_free_ptr(rd);
7611}
7612
7613GEN_VXFORM(vcipher, 4, 20)
7614GEN_VXFORM(vcipherlast, 4, 20)
7615GEN_VXFORM(vncipher, 4, 21)
7616GEN_VXFORM(vncipherlast, 4, 21)
7617
7618GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
7619                vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7620GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
7621                vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7622
7623#define VSHASIGMA(op)                         \
7624static void gen_##op(DisasContext *ctx)       \
7625{                                             \
7626    TCGv_ptr ra, rd;                          \
7627    TCGv_i32 st_six;                          \
7628    if (unlikely(!ctx->altivec_enabled)) {    \
7629        gen_exception(ctx, POWERPC_EXCP_VPU); \
7630        return;                               \
7631    }                                         \
7632    ra = gen_avr_ptr(rA(ctx->opcode));        \
7633    rd = gen_avr_ptr(rD(ctx->opcode));        \
7634    st_six = tcg_const_i32(rB(ctx->opcode));  \
7635    gen_helper_##op(rd, ra, st_six);          \
7636    tcg_temp_free_ptr(ra);                    \
7637    tcg_temp_free_ptr(rd);                    \
7638    tcg_temp_free_i32(st_six);                \
7639}
7640
7641VSHASIGMA(vshasigmaw)
7642VSHASIGMA(vshasigmad)
7643
7644GEN_VXFORM3(vpermxor, 22, 0xFF)
7645GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
7646                vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
7647
7648/***                           VSX extension                               ***/
7649
7650static inline TCGv_i64 cpu_vsrh(int n)
7651{
7652    if (n < 32) {
7653        return cpu_fpr[n];
7654    } else {
7655        return cpu_avrh[n-32];
7656    }
7657}
7658
7659static inline TCGv_i64 cpu_vsrl(int n)
7660{
7661    if (n < 32) {
7662        return cpu_vsr[n];
7663    } else {
7664        return cpu_avrl[n-32];
7665    }
7666}
7667
7668#define VSX_LOAD_SCALAR(name, operation)                      \
7669static void gen_##name(DisasContext *ctx)                     \
7670{                                                             \
7671    TCGv EA;                                                  \
7672    if (unlikely(!ctx->vsx_enabled)) {                        \
7673        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7674        return;                                               \
7675    }                                                         \
7676    gen_set_access_type(ctx, ACCESS_INT);                     \
7677    EA = tcg_temp_new();                                      \
7678    gen_addr_reg_index(ctx, EA);                              \
7679    gen_qemu_##operation(ctx, cpu_vsrh(xT(ctx->opcode)), EA); \
7680    /* NOTE: cpu_vsrl is undefined */                         \
7681    tcg_temp_free(EA);                                        \
7682}
7683
7684VSX_LOAD_SCALAR(lxsdx, ld64)
7685VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
7686VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
7687VSX_LOAD_SCALAR(lxsspx, ld32fs)
7688
7689static void gen_lxvd2x(DisasContext *ctx)
7690{
7691    TCGv EA;
7692    if (unlikely(!ctx->vsx_enabled)) {
7693        gen_exception(ctx, POWERPC_EXCP_VSXU);
7694        return;
7695    }
7696    gen_set_access_type(ctx, ACCESS_INT);
7697    EA = tcg_temp_new();
7698    gen_addr_reg_index(ctx, EA);
7699    gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7700    tcg_gen_addi_tl(EA, EA, 8);
7701    gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
7702    tcg_temp_free(EA);
7703}
7704
7705static void gen_lxvdsx(DisasContext *ctx)
7706{
7707    TCGv EA;
7708    if (unlikely(!ctx->vsx_enabled)) {
7709        gen_exception(ctx, POWERPC_EXCP_VSXU);
7710        return;
7711    }
7712    gen_set_access_type(ctx, ACCESS_INT);
7713    EA = tcg_temp_new();
7714    gen_addr_reg_index(ctx, EA);
7715    gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7716    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
7717    tcg_temp_free(EA);
7718}
7719
7720static void gen_lxvw4x(DisasContext *ctx)
7721{
7722    TCGv EA;
7723    TCGv_i64 tmp;
7724    TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
7725    TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
7726    if (unlikely(!ctx->vsx_enabled)) {
7727        gen_exception(ctx, POWERPC_EXCP_VSXU);
7728        return;
7729    }
7730    gen_set_access_type(ctx, ACCESS_INT);
7731    EA = tcg_temp_new();
7732    tmp = tcg_temp_new_i64();
7733
7734    gen_addr_reg_index(ctx, EA);
7735    gen_qemu_ld32u_i64(ctx, tmp, EA);
7736    tcg_gen_addi_tl(EA, EA, 4);
7737    gen_qemu_ld32u_i64(ctx, xth, EA);
7738    tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
7739
7740    tcg_gen_addi_tl(EA, EA, 4);
7741    gen_qemu_ld32u_i64(ctx, tmp, EA);
7742    tcg_gen_addi_tl(EA, EA, 4);
7743    gen_qemu_ld32u_i64(ctx, xtl, EA);
7744    tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
7745
7746    tcg_temp_free(EA);
7747    tcg_temp_free_i64(tmp);
7748}
7749
7750#define VSX_STORE_SCALAR(name, operation)                     \
7751static void gen_##name(DisasContext *ctx)                     \
7752{                                                             \
7753    TCGv EA;                                                  \
7754    if (unlikely(!ctx->vsx_enabled)) {                        \
7755        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7756        return;                                               \
7757    }                                                         \
7758    gen_set_access_type(ctx, ACCESS_INT);                     \
7759    EA = tcg_temp_new();                                      \
7760    gen_addr_reg_index(ctx, EA);                              \
7761    gen_qemu_##operation(ctx, cpu_vsrh(xS(ctx->opcode)), EA); \
7762    tcg_temp_free(EA);                                        \
7763}
7764
7765VSX_STORE_SCALAR(stxsdx, st64)
7766VSX_STORE_SCALAR(stxsiwx, st32_i64)
7767VSX_STORE_SCALAR(stxsspx, st32fs)
7768
7769static void gen_stxvd2x(DisasContext *ctx)
7770{
7771    TCGv EA;
7772    if (unlikely(!ctx->vsx_enabled)) {
7773        gen_exception(ctx, POWERPC_EXCP_VSXU);
7774        return;
7775    }
7776    gen_set_access_type(ctx, ACCESS_INT);
7777    EA = tcg_temp_new();
7778    gen_addr_reg_index(ctx, EA);
7779    gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7780    tcg_gen_addi_tl(EA, EA, 8);
7781    gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7782    tcg_temp_free(EA);
7783}
7784
7785static void gen_stxvw4x(DisasContext *ctx)
7786{
7787    TCGv_i64 tmp;
7788    TCGv EA;
7789    if (unlikely(!ctx->vsx_enabled)) {
7790        gen_exception(ctx, POWERPC_EXCP_VSXU);
7791        return;
7792    }
7793    gen_set_access_type(ctx, ACCESS_INT);
7794    EA = tcg_temp_new();
7795    gen_addr_reg_index(ctx, EA);
7796    tmp = tcg_temp_new_i64();
7797
7798    tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
7799    gen_qemu_st32_i64(ctx, tmp, EA);
7800    tcg_gen_addi_tl(EA, EA, 4);
7801    gen_qemu_st32_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7802
7803    tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
7804    tcg_gen_addi_tl(EA, EA, 4);
7805    gen_qemu_st32_i64(ctx, tmp, EA);
7806    tcg_gen_addi_tl(EA, EA, 4);
7807    gen_qemu_st32_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7808
7809    tcg_temp_free(EA);
7810    tcg_temp_free_i64(tmp);
7811}
7812
7813#define MV_VSRW(name, tcgop1, tcgop2, target, source)           \
7814static void gen_##name(DisasContext *ctx)                       \
7815{                                                               \
7816    if (xS(ctx->opcode) < 32) {                                 \
7817        if (unlikely(!ctx->fpu_enabled)) {                      \
7818            gen_exception(ctx, POWERPC_EXCP_FPU);               \
7819            return;                                             \
7820        }                                                       \
7821    } else {                                                    \
7822        if (unlikely(!ctx->altivec_enabled)) {                  \
7823            gen_exception(ctx, POWERPC_EXCP_VPU);               \
7824            return;                                             \
7825        }                                                       \
7826    }                                                           \
7827    TCGv_i64 tmp = tcg_temp_new_i64();                          \
7828    tcg_gen_##tcgop1(tmp, source);                              \
7829    tcg_gen_##tcgop2(target, tmp);                              \
7830    tcg_temp_free_i64(tmp);                                     \
7831}
7832
7833
7834MV_VSRW(mfvsrwz, ext32u_i64, trunc_i64_tl, cpu_gpr[rA(ctx->opcode)], \
7835        cpu_vsrh(xS(ctx->opcode)))
7836MV_VSRW(mtvsrwa, extu_tl_i64, ext32s_i64, cpu_vsrh(xT(ctx->opcode)), \
7837        cpu_gpr[rA(ctx->opcode)])
7838MV_VSRW(mtvsrwz, extu_tl_i64, ext32u_i64, cpu_vsrh(xT(ctx->opcode)), \
7839        cpu_gpr[rA(ctx->opcode)])
7840
7841#if defined(TARGET_PPC64)
7842#define MV_VSRD(name, target, source)                           \
7843static void gen_##name(DisasContext *ctx)                       \
7844{                                                               \
7845    if (xS(ctx->opcode) < 32) {                                 \
7846        if (unlikely(!ctx->fpu_enabled)) {                      \
7847            gen_exception(ctx, POWERPC_EXCP_FPU);               \
7848            return;                                             \
7849        }                                                       \
7850    } else {                                                    \
7851        if (unlikely(!ctx->altivec_enabled)) {                  \
7852            gen_exception(ctx, POWERPC_EXCP_VPU);               \
7853            return;                                             \
7854        }                                                       \
7855    }                                                           \
7856    tcg_gen_mov_i64(target, source);                            \
7857}
7858
7859MV_VSRD(mfvsrd, cpu_gpr[rA(ctx->opcode)], cpu_vsrh(xS(ctx->opcode)))
7860MV_VSRD(mtvsrd, cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)])
7861
7862#endif
7863
7864static void gen_xxpermdi(DisasContext *ctx)
7865{
7866    if (unlikely(!ctx->vsx_enabled)) {
7867        gen_exception(ctx, POWERPC_EXCP_VSXU);
7868        return;
7869    }
7870
7871    if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
7872                 (xT(ctx->opcode) == xB(ctx->opcode)))) {
7873        TCGv_i64 xh, xl;
7874
7875        xh = tcg_temp_new_i64();
7876        xl = tcg_temp_new_i64();
7877
7878        if ((DM(ctx->opcode) & 2) == 0) {
7879            tcg_gen_mov_i64(xh, cpu_vsrh(xA(ctx->opcode)));
7880        } else {
7881            tcg_gen_mov_i64(xh, cpu_vsrl(xA(ctx->opcode)));
7882        }
7883        if ((DM(ctx->opcode) & 1) == 0) {
7884            tcg_gen_mov_i64(xl, cpu_vsrh(xB(ctx->opcode)));
7885        } else {
7886            tcg_gen_mov_i64(xl, cpu_vsrl(xB(ctx->opcode)));
7887        }
7888
7889        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xh);
7890        tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xl);
7891
7892        tcg_temp_free_i64(xh);
7893        tcg_temp_free_i64(xl);
7894    } else {
7895        if ((DM(ctx->opcode) & 2) == 0) {
7896            tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
7897        } else {
7898            tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
7899        }
7900        if ((DM(ctx->opcode) & 1) == 0) {
7901            tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
7902        } else {
7903            tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
7904        }
7905    }
7906}
7907
7908#define OP_ABS 1
7909#define OP_NABS 2
7910#define OP_NEG 3
7911#define OP_CPSGN 4
7912#define SGN_MASK_DP  0x8000000000000000ull
7913#define SGN_MASK_SP 0x8000000080000000ull
7914
7915#define VSX_SCALAR_MOVE(name, op, sgn_mask)                       \
7916static void glue(gen_, name)(DisasContext * ctx)                  \
7917    {                                                             \
7918        TCGv_i64 xb, sgm;                                         \
7919        if (unlikely(!ctx->vsx_enabled)) {                        \
7920            gen_exception(ctx, POWERPC_EXCP_VSXU);                \
7921            return;                                               \
7922        }                                                         \
7923        xb = tcg_temp_new_i64();                                  \
7924        sgm = tcg_temp_new_i64();                                 \
7925        tcg_gen_mov_i64(xb, cpu_vsrh(xB(ctx->opcode)));           \
7926        tcg_gen_movi_i64(sgm, sgn_mask);                          \
7927        switch (op) {                                             \
7928            case OP_ABS: {                                        \
7929                tcg_gen_andc_i64(xb, xb, sgm);                    \
7930                break;                                            \
7931            }                                                     \
7932            case OP_NABS: {                                       \
7933                tcg_gen_or_i64(xb, xb, sgm);                      \
7934                break;                                            \
7935            }                                                     \
7936            case OP_NEG: {                                        \
7937                tcg_gen_xor_i64(xb, xb, sgm);                     \
7938                break;                                            \
7939            }                                                     \
7940            case OP_CPSGN: {                                      \
7941                TCGv_i64 xa = tcg_temp_new_i64();                 \
7942                tcg_gen_mov_i64(xa, cpu_vsrh(xA(ctx->opcode)));   \
7943                tcg_gen_and_i64(xa, xa, sgm);                     \
7944                tcg_gen_andc_i64(xb, xb, sgm);                    \
7945                tcg_gen_or_i64(xb, xb, xa);                       \
7946                tcg_temp_free_i64(xa);                            \
7947                break;                                            \
7948            }                                                     \
7949        }                                                         \
7950        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xb);           \
7951        tcg_temp_free_i64(xb);                                    \
7952        tcg_temp_free_i64(sgm);                                   \
7953    }
7954
7955VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
7956VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
7957VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
7958VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
7959
7960#define VSX_VECTOR_MOVE(name, op, sgn_mask)                      \
7961static void glue(gen_, name)(DisasContext * ctx)                 \
7962    {                                                            \
7963        TCGv_i64 xbh, xbl, sgm;                                  \
7964        if (unlikely(!ctx->vsx_enabled)) {                       \
7965            gen_exception(ctx, POWERPC_EXCP_VSXU);               \
7966            return;                                              \
7967        }                                                        \
7968        xbh = tcg_temp_new_i64();                                \
7969        xbl = tcg_temp_new_i64();                                \
7970        sgm = tcg_temp_new_i64();                                \
7971        tcg_gen_mov_i64(xbh, cpu_vsrh(xB(ctx->opcode)));         \
7972        tcg_gen_mov_i64(xbl, cpu_vsrl(xB(ctx->opcode)));         \
7973        tcg_gen_movi_i64(sgm, sgn_mask);                         \
7974        switch (op) {                                            \
7975            case OP_ABS: {                                       \
7976                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
7977                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
7978                break;                                           \
7979            }                                                    \
7980            case OP_NABS: {                                      \
7981                tcg_gen_or_i64(xbh, xbh, sgm);                   \
7982                tcg_gen_or_i64(xbl, xbl, sgm);                   \
7983                break;                                           \
7984            }                                                    \
7985            case OP_NEG: {                                       \
7986                tcg_gen_xor_i64(xbh, xbh, sgm);                  \
7987                tcg_gen_xor_i64(xbl, xbl, sgm);                  \
7988                break;                                           \
7989            }                                                    \
7990            case OP_CPSGN: {                                     \
7991                TCGv_i64 xah = tcg_temp_new_i64();               \
7992                TCGv_i64 xal = tcg_temp_new_i64();               \
7993                tcg_gen_mov_i64(xah, cpu_vsrh(xA(ctx->opcode))); \
7994                tcg_gen_mov_i64(xal, cpu_vsrl(xA(ctx->opcode))); \
7995                tcg_gen_and_i64(xah, xah, sgm);                  \
7996                tcg_gen_and_i64(xal, xal, sgm);                  \
7997                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
7998                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
7999                tcg_gen_or_i64(xbh, xbh, xah);                   \
8000                tcg_gen_or_i64(xbl, xbl, xal);                   \
8001                tcg_temp_free_i64(xah);                          \
8002                tcg_temp_free_i64(xal);                          \
8003                break;                                           \
8004            }                                                    \
8005        }                                                        \
8006        tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xbh);         \
8007        tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xbl);         \
8008        tcg_temp_free_i64(xbh);                                  \
8009        tcg_temp_free_i64(xbl);                                  \
8010        tcg_temp_free_i64(sgm);                                  \
8011    }
8012
8013VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
8014VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
8015VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
8016VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
8017VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
8018VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
8019VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
8020VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
8021
8022#define GEN_VSX_HELPER_2(name, op1, op2, inval, type)                         \
8023static void gen_##name(DisasContext * ctx)                                    \
8024{                                                                             \
8025    TCGv_i32 opc;                                                             \
8026    if (unlikely(!ctx->vsx_enabled)) {                                        \
8027        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
8028        return;                                                               \
8029    }                                                                         \
8030    /* NIP cannot be restored if the memory exception comes from an helper */ \
8031    gen_update_nip(ctx, ctx->nip - 4);                                        \
8032    opc = tcg_const_i32(ctx->opcode);                                         \
8033    gen_helper_##name(cpu_env, opc);                                          \
8034    tcg_temp_free_i32(opc);                                                   \
8035}
8036
8037#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
8038static void gen_##name(DisasContext * ctx)                    \
8039{                                                             \
8040    if (unlikely(!ctx->vsx_enabled)) {                        \
8041        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
8042        return;                                               \
8043    }                                                         \
8044    /* NIP cannot be restored if the exception comes */       \
8045    /* from a helper. */                                      \
8046    gen_update_nip(ctx, ctx->nip - 4);                        \
8047                                                              \
8048    gen_helper_##name(cpu_vsrh(xT(ctx->opcode)), cpu_env,     \
8049                      cpu_vsrh(xB(ctx->opcode)));             \
8050}
8051
8052GEN_VSX_HELPER_2(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
8053GEN_VSX_HELPER_2(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
8054GEN_VSX_HELPER_2(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
8055GEN_VSX_HELPER_2(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
8056GEN_VSX_HELPER_2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
8057GEN_VSX_HELPER_2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
8058GEN_VSX_HELPER_2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
8059GEN_VSX_HELPER_2(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
8060GEN_VSX_HELPER_2(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
8061GEN_VSX_HELPER_2(xsmaddadp, 0x04, 0x04, 0, PPC2_VSX)
8062GEN_VSX_HELPER_2(xsmaddmdp, 0x04, 0x05, 0, PPC2_VSX)
8063GEN_VSX_HELPER_2(xsmsubadp, 0x04, 0x06, 0, PPC2_VSX)
8064GEN_VSX_HELPER_2(xsmsubmdp, 0x04, 0x07, 0, PPC2_VSX)
8065GEN_VSX_HELPER_2(xsnmaddadp, 0x04, 0x14, 0, PPC2_VSX)
8066GEN_VSX_HELPER_2(xsnmaddmdp, 0x04, 0x15, 0, PPC2_VSX)
8067GEN_VSX_HELPER_2(xsnmsubadp, 0x04, 0x16, 0, PPC2_VSX)
8068GEN_VSX_HELPER_2(xsnmsubmdp, 0x04, 0x17, 0, PPC2_VSX)
8069GEN_VSX_HELPER_2(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
8070GEN_VSX_HELPER_2(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
8071GEN_VSX_HELPER_2(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
8072GEN_VSX_HELPER_2(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
8073GEN_VSX_HELPER_2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
8074GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207)
8075GEN_VSX_HELPER_2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
8076GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
8077GEN_VSX_HELPER_2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
8078GEN_VSX_HELPER_2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
8079GEN_VSX_HELPER_2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
8080GEN_VSX_HELPER_2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
8081GEN_VSX_HELPER_2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
8082GEN_VSX_HELPER_2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
8083GEN_VSX_HELPER_2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
8084GEN_VSX_HELPER_2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
8085GEN_VSX_HELPER_2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
8086GEN_VSX_HELPER_2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
8087GEN_VSX_HELPER_2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
8088GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207)
8089
8090GEN_VSX_HELPER_2(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
8091GEN_VSX_HELPER_2(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
8092GEN_VSX_HELPER_2(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
8093GEN_VSX_HELPER_2(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
8094GEN_VSX_HELPER_2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
8095GEN_VSX_HELPER_2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
8096GEN_VSX_HELPER_2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
8097GEN_VSX_HELPER_2(xsmaddasp, 0x04, 0x00, 0, PPC2_VSX207)
8098GEN_VSX_HELPER_2(xsmaddmsp, 0x04, 0x01, 0, PPC2_VSX207)
8099GEN_VSX_HELPER_2(xsmsubasp, 0x04, 0x02, 0, PPC2_VSX207)
8100GEN_VSX_HELPER_2(xsmsubmsp, 0x04, 0x03, 0, PPC2_VSX207)
8101GEN_VSX_HELPER_2(xsnmaddasp, 0x04, 0x10, 0, PPC2_VSX207)
8102GEN_VSX_HELPER_2(xsnmaddmsp, 0x04, 0x11, 0, PPC2_VSX207)
8103GEN_VSX_HELPER_2(xsnmsubasp, 0x04, 0x12, 0, PPC2_VSX207)
8104GEN_VSX_HELPER_2(xsnmsubmsp, 0x04, 0x13, 0, PPC2_VSX207)
8105GEN_VSX_HELPER_2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
8106GEN_VSX_HELPER_2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
8107
8108GEN_VSX_HELPER_2(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
8109GEN_VSX_HELPER_2(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
8110GEN_VSX_HELPER_2(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
8111GEN_VSX_HELPER_2(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
8112GEN_VSX_HELPER_2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
8113GEN_VSX_HELPER_2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
8114GEN_VSX_HELPER_2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
8115GEN_VSX_HELPER_2(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
8116GEN_VSX_HELPER_2(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
8117GEN_VSX_HELPER_2(xvmaddadp, 0x04, 0x0C, 0, PPC2_VSX)
8118GEN_VSX_HELPER_2(xvmaddmdp, 0x04, 0x0D, 0, PPC2_VSX)
8119GEN_VSX_HELPER_2(xvmsubadp, 0x04, 0x0E, 0, PPC2_VSX)
8120GEN_VSX_HELPER_2(xvmsubmdp, 0x04, 0x0F, 0, PPC2_VSX)
8121GEN_VSX_HELPER_2(xvnmaddadp, 0x04, 0x1C, 0, PPC2_VSX)
8122GEN_VSX_HELPER_2(xvnmaddmdp, 0x04, 0x1D, 0, PPC2_VSX)
8123GEN_VSX_HELPER_2(xvnmsubadp, 0x04, 0x1E, 0, PPC2_VSX)
8124GEN_VSX_HELPER_2(xvnmsubmdp, 0x04, 0x1F, 0, PPC2_VSX)
8125GEN_VSX_HELPER_2(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
8126GEN_VSX_HELPER_2(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
8127GEN_VSX_HELPER_2(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
8128GEN_VSX_HELPER_2(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
8129GEN_VSX_HELPER_2(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
8130GEN_VSX_HELPER_2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
8131GEN_VSX_HELPER_2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
8132GEN_VSX_HELPER_2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
8133GEN_VSX_HELPER_2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
8134GEN_VSX_HELPER_2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
8135GEN_VSX_HELPER_2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
8136GEN_VSX_HELPER_2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
8137GEN_VSX_HELPER_2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
8138GEN_VSX_HELPER_2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
8139GEN_VSX_HELPER_2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
8140GEN_VSX_HELPER_2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
8141GEN_VSX_HELPER_2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
8142GEN_VSX_HELPER_2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
8143GEN_VSX_HELPER_2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
8144
8145GEN_VSX_HELPER_2(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
8146GEN_VSX_HELPER_2(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
8147GEN_VSX_HELPER_2(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
8148GEN_VSX_HELPER_2(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
8149GEN_VSX_HELPER_2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
8150GEN_VSX_HELPER_2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
8151GEN_VSX_HELPER_2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
8152GEN_VSX_HELPER_2(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
8153GEN_VSX_HELPER_2(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
8154GEN_VSX_HELPER_2(xvmaddasp, 0x04, 0x08, 0, PPC2_VSX)
8155GEN_VSX_HELPER_2(xvmaddmsp, 0x04, 0x09, 0, PPC2_VSX)
8156GEN_VSX_HELPER_2(xvmsubasp, 0x04, 0x0A, 0, PPC2_VSX)
8157GEN_VSX_HELPER_2(xvmsubmsp, 0x04, 0x0B, 0, PPC2_VSX)
8158GEN_VSX_HELPER_2(xvnmaddasp, 0x04, 0x18, 0, PPC2_VSX)
8159GEN_VSX_HELPER_2(xvnmaddmsp, 0x04, 0x19, 0, PPC2_VSX)
8160GEN_VSX_HELPER_2(xvnmsubasp, 0x04, 0x1A, 0, PPC2_VSX)
8161GEN_VSX_HELPER_2(xvnmsubmsp, 0x04, 0x1B, 0, PPC2_VSX)
8162GEN_VSX_HELPER_2(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
8163GEN_VSX_HELPER_2(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
8164GEN_VSX_HELPER_2(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
8165GEN_VSX_HELPER_2(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
8166GEN_VSX_HELPER_2(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
8167GEN_VSX_HELPER_2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
8168GEN_VSX_HELPER_2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
8169GEN_VSX_HELPER_2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
8170GEN_VSX_HELPER_2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
8171GEN_VSX_HELPER_2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
8172GEN_VSX_HELPER_2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
8173GEN_VSX_HELPER_2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
8174GEN_VSX_HELPER_2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
8175GEN_VSX_HELPER_2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
8176GEN_VSX_HELPER_2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
8177GEN_VSX_HELPER_2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
8178GEN_VSX_HELPER_2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
8179GEN_VSX_HELPER_2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
8180GEN_VSX_HELPER_2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
8181
8182#define VSX_LOGICAL(name, tcg_op)                                    \
8183static void glue(gen_, name)(DisasContext * ctx)                     \
8184    {                                                                \
8185        if (unlikely(!ctx->vsx_enabled)) {                           \
8186            gen_exception(ctx, POWERPC_EXCP_VSXU);                   \
8187            return;                                                  \
8188        }                                                            \
8189        tcg_op(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)), \
8190            cpu_vsrh(xB(ctx->opcode)));                              \
8191        tcg_op(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)), \
8192            cpu_vsrl(xB(ctx->opcode)));                              \
8193    }
8194
8195VSX_LOGICAL(xxland, tcg_gen_and_i64)
8196VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
8197VSX_LOGICAL(xxlor, tcg_gen_or_i64)
8198VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
8199VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
8200VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
8201VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
8202VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
8203
8204#define VSX_XXMRG(name, high)                               \
8205static void glue(gen_, name)(DisasContext * ctx)            \
8206    {                                                       \
8207        TCGv_i64 a0, a1, b0, b1;                            \
8208        if (unlikely(!ctx->vsx_enabled)) {                  \
8209            gen_exception(ctx, POWERPC_EXCP_VSXU);          \
8210            return;                                         \
8211        }                                                   \
8212        a0 = tcg_temp_new_i64();                            \
8213        a1 = tcg_temp_new_i64();                            \
8214        b0 = tcg_temp_new_i64();                            \
8215        b1 = tcg_temp_new_i64();                            \
8216        if (high) {                                         \
8217            tcg_gen_mov_i64(a0, cpu_vsrh(xA(ctx->opcode))); \
8218            tcg_gen_mov_i64(a1, cpu_vsrh(xA(ctx->opcode))); \
8219            tcg_gen_mov_i64(b0, cpu_vsrh(xB(ctx->opcode))); \
8220            tcg_gen_mov_i64(b1, cpu_vsrh(xB(ctx->opcode))); \
8221        } else {                                            \
8222            tcg_gen_mov_i64(a0, cpu_vsrl(xA(ctx->opcode))); \
8223            tcg_gen_mov_i64(a1, cpu_vsrl(xA(ctx->opcode))); \
8224            tcg_gen_mov_i64(b0, cpu_vsrl(xB(ctx->opcode))); \
8225            tcg_gen_mov_i64(b1, cpu_vsrl(xB(ctx->opcode))); \
8226        }                                                   \
8227        tcg_gen_shri_i64(a0, a0, 32);                       \
8228        tcg_gen_shri_i64(b0, b0, 32);                       \
8229        tcg_gen_deposit_i64(cpu_vsrh(xT(ctx->opcode)),      \
8230                            b0, a0, 32, 32);                \
8231        tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)),      \
8232                            b1, a1, 32, 32);                \
8233        tcg_temp_free_i64(a0);                              \
8234        tcg_temp_free_i64(a1);                              \
8235        tcg_temp_free_i64(b0);                              \
8236        tcg_temp_free_i64(b1);                              \
8237    }
8238
8239VSX_XXMRG(xxmrghw, 1)
8240VSX_XXMRG(xxmrglw, 0)
8241
8242static void gen_xxsel(DisasContext * ctx)
8243{
8244    TCGv_i64 a, b, c;
8245    if (unlikely(!ctx->vsx_enabled)) {
8246        gen_exception(ctx, POWERPC_EXCP_VSXU);
8247        return;
8248    }
8249    a = tcg_temp_new_i64();
8250    b = tcg_temp_new_i64();
8251    c = tcg_temp_new_i64();
8252
8253    tcg_gen_mov_i64(a, cpu_vsrh(xA(ctx->opcode)));
8254    tcg_gen_mov_i64(b, cpu_vsrh(xB(ctx->opcode)));
8255    tcg_gen_mov_i64(c, cpu_vsrh(xC(ctx->opcode)));
8256
8257    tcg_gen_and_i64(b, b, c);
8258    tcg_gen_andc_i64(a, a, c);
8259    tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), a, b);
8260
8261    tcg_gen_mov_i64(a, cpu_vsrl(xA(ctx->opcode)));
8262    tcg_gen_mov_i64(b, cpu_vsrl(xB(ctx->opcode)));
8263    tcg_gen_mov_i64(c, cpu_vsrl(xC(ctx->opcode)));
8264
8265    tcg_gen_and_i64(b, b, c);
8266    tcg_gen_andc_i64(a, a, c);
8267    tcg_gen_or_i64(cpu_vsrl(xT(ctx->opcode)), a, b);
8268
8269    tcg_temp_free_i64(a);
8270    tcg_temp_free_i64(b);
8271    tcg_temp_free_i64(c);
8272}
8273
8274static void gen_xxspltw(DisasContext *ctx)
8275{
8276    TCGv_i64 b, b2;
8277    TCGv_i64 vsr = (UIM(ctx->opcode) & 2) ?
8278                   cpu_vsrl(xB(ctx->opcode)) :
8279                   cpu_vsrh(xB(ctx->opcode));
8280
8281    if (unlikely(!ctx->vsx_enabled)) {
8282        gen_exception(ctx, POWERPC_EXCP_VSXU);
8283        return;
8284    }
8285
8286    b = tcg_temp_new_i64();
8287    b2 = tcg_temp_new_i64();
8288
8289    if (UIM(ctx->opcode) & 1) {
8290        tcg_gen_ext32u_i64(b, vsr);
8291    } else {
8292        tcg_gen_shri_i64(b, vsr, 32);
8293    }
8294
8295    tcg_gen_shli_i64(b2, b, 32);
8296    tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), b, b2);
8297    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
8298
8299    tcg_temp_free_i64(b);
8300    tcg_temp_free_i64(b2);
8301}
8302
8303static void gen_xxsldwi(DisasContext *ctx)
8304{
8305    TCGv_i64 xth, xtl;
8306    if (unlikely(!ctx->vsx_enabled)) {
8307        gen_exception(ctx, POWERPC_EXCP_VSXU);
8308        return;
8309    }
8310    xth = tcg_temp_new_i64();
8311    xtl = tcg_temp_new_i64();
8312
8313    switch (SHW(ctx->opcode)) {
8314        case 0: {
8315            tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8316            tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8317            break;
8318        }
8319        case 1: {
8320            TCGv_i64 t0 = tcg_temp_new_i64();
8321            tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8322            tcg_gen_shli_i64(xth, xth, 32);
8323            tcg_gen_mov_i64(t0, cpu_vsrl(xA(ctx->opcode)));
8324            tcg_gen_shri_i64(t0, t0, 32);
8325            tcg_gen_or_i64(xth, xth, t0);
8326            tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8327            tcg_gen_shli_i64(xtl, xtl, 32);
8328            tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8329            tcg_gen_shri_i64(t0, t0, 32);
8330            tcg_gen_or_i64(xtl, xtl, t0);
8331            tcg_temp_free_i64(t0);
8332            break;
8333        }
8334        case 2: {
8335            tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8336            tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8337            break;
8338        }
8339        case 3: {
8340            TCGv_i64 t0 = tcg_temp_new_i64();
8341            tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8342            tcg_gen_shli_i64(xth, xth, 32);
8343            tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8344            tcg_gen_shri_i64(t0, t0, 32);
8345            tcg_gen_or_i64(xth, xth, t0);
8346            tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8347            tcg_gen_shli_i64(xtl, xtl, 32);
8348            tcg_gen_mov_i64(t0, cpu_vsrl(xB(ctx->opcode)));
8349            tcg_gen_shri_i64(t0, t0, 32);
8350            tcg_gen_or_i64(xtl, xtl, t0);
8351            tcg_temp_free_i64(t0);
8352            break;
8353        }
8354    }
8355
8356    tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xth);
8357    tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xtl);
8358
8359    tcg_temp_free_i64(xth);
8360    tcg_temp_free_i64(xtl);
8361}
8362
8363/*** Decimal Floating Point ***/
8364
8365static inline TCGv_ptr gen_fprp_ptr(int reg)
8366{
8367    TCGv_ptr r = tcg_temp_new_ptr();
8368    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
8369    return r;
8370}
8371
8372#define GEN_DFP_T_A_B_Rc(name)                   \
8373static void gen_##name(DisasContext *ctx)        \
8374{                                                \
8375    TCGv_ptr rd, ra, rb;                         \
8376    if (unlikely(!ctx->fpu_enabled)) {           \
8377        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8378        return;                                  \
8379    }                                            \
8380    gen_update_nip(ctx, ctx->nip - 4);           \
8381    rd = gen_fprp_ptr(rD(ctx->opcode));          \
8382    ra = gen_fprp_ptr(rA(ctx->opcode));          \
8383    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8384    gen_helper_##name(cpu_env, rd, ra, rb);      \
8385    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8386        gen_set_cr1_from_fpscr(ctx);             \
8387    }                                            \
8388    tcg_temp_free_ptr(rd);                       \
8389    tcg_temp_free_ptr(ra);                       \
8390    tcg_temp_free_ptr(rb);                       \
8391}
8392
8393#define GEN_DFP_BF_A_B(name)                      \
8394static void gen_##name(DisasContext *ctx)         \
8395{                                                 \
8396    TCGv_ptr ra, rb;                              \
8397    if (unlikely(!ctx->fpu_enabled)) {            \
8398        gen_exception(ctx, POWERPC_EXCP_FPU);     \
8399        return;                                   \
8400    }                                             \
8401    gen_update_nip(ctx, ctx->nip - 4);            \
8402    ra = gen_fprp_ptr(rA(ctx->opcode));           \
8403    rb = gen_fprp_ptr(rB(ctx->opcode));           \
8404    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8405                      cpu_env, ra, rb);           \
8406    tcg_temp_free_ptr(ra);                        \
8407    tcg_temp_free_ptr(rb);                        \
8408}
8409
8410#define GEN_DFP_BF_A_DCM(name)                    \
8411static void gen_##name(DisasContext *ctx)         \
8412{                                                 \
8413    TCGv_ptr ra;                                  \
8414    TCGv_i32 dcm;                                 \
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    ra = gen_fprp_ptr(rA(ctx->opcode));           \
8421    dcm = tcg_const_i32(DCM(ctx->opcode));        \
8422    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8423                      cpu_env, ra, dcm);          \
8424    tcg_temp_free_ptr(ra);                        \
8425    tcg_temp_free_i32(dcm);                       \
8426}
8427
8428#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2)    \
8429static void gen_##name(DisasContext *ctx)             \
8430{                                                     \
8431    TCGv_ptr rt, rb;                                  \
8432    TCGv_i32 u32_1, u32_2;                            \
8433    if (unlikely(!ctx->fpu_enabled)) {                \
8434        gen_exception(ctx, POWERPC_EXCP_FPU);         \
8435        return;                                       \
8436    }                                                 \
8437    gen_update_nip(ctx, ctx->nip - 4);                \
8438    rt = gen_fprp_ptr(rD(ctx->opcode));               \
8439    rb = gen_fprp_ptr(rB(ctx->opcode));               \
8440    u32_1 = tcg_const_i32(u32f1(ctx->opcode));        \
8441    u32_2 = tcg_const_i32(u32f2(ctx->opcode));        \
8442    gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
8443    if (unlikely(Rc(ctx->opcode) != 0)) {             \
8444        gen_set_cr1_from_fpscr(ctx);                  \
8445    }                                                 \
8446    tcg_temp_free_ptr(rt);                            \
8447    tcg_temp_free_ptr(rb);                            \
8448    tcg_temp_free_i32(u32_1);                         \
8449    tcg_temp_free_i32(u32_2);                         \
8450}
8451
8452#define GEN_DFP_T_A_B_I32_Rc(name, i32fld)       \
8453static void gen_##name(DisasContext *ctx)        \
8454{                                                \
8455    TCGv_ptr rt, ra, rb;                         \
8456    TCGv_i32 i32;                                \
8457    if (unlikely(!ctx->fpu_enabled)) {           \
8458        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8459        return;                                  \
8460    }                                            \
8461    gen_update_nip(ctx, ctx->nip - 4);           \
8462    rt = gen_fprp_ptr(rD(ctx->opcode));          \
8463    ra = gen_fprp_ptr(rA(ctx->opcode));          \
8464    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8465    i32 = tcg_const_i32(i32fld(ctx->opcode));    \
8466    gen_helper_##name(cpu_env, rt, ra, rb, i32); \
8467    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8468        gen_set_cr1_from_fpscr(ctx);             \
8469    }                                            \
8470    tcg_temp_free_ptr(rt);                       \
8471    tcg_temp_free_ptr(rb);                       \
8472    tcg_temp_free_ptr(ra);                       \
8473    tcg_temp_free_i32(i32);                      \
8474    }
8475
8476#define GEN_DFP_T_B_Rc(name)                     \
8477static void gen_##name(DisasContext *ctx)        \
8478{                                                \
8479    TCGv_ptr rt, rb;                             \
8480    if (unlikely(!ctx->fpu_enabled)) {           \
8481        gen_exception(ctx, POWERPC_EXCP_FPU);    \
8482        return;                                  \
8483    }                                            \
8484    gen_update_nip(ctx, ctx->nip - 4);           \
8485    rt = gen_fprp_ptr(rD(ctx->opcode));          \
8486    rb = gen_fprp_ptr(rB(ctx->opcode));          \
8487    gen_helper_##name(cpu_env, rt, rb);          \
8488    if (unlikely(Rc(ctx->opcode) != 0)) {        \
8489        gen_set_cr1_from_fpscr(ctx);             \
8490    }                                            \
8491    tcg_temp_free_ptr(rt);                       \
8492    tcg_temp_free_ptr(rb);                       \
8493    }
8494
8495#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \
8496static void gen_##name(DisasContext *ctx)          \
8497{                                                  \
8498    TCGv_ptr rt, rs;                               \
8499    TCGv_i32 i32;                                  \
8500    if (unlikely(!ctx->fpu_enabled)) {             \
8501        gen_exception(ctx, POWERPC_EXCP_FPU);      \
8502        return;                                    \
8503    }                                              \
8504    gen_update_nip(ctx, ctx->nip - 4);             \
8505    rt = gen_fprp_ptr(rD(ctx->opcode));            \
8506    rs = gen_fprp_ptr(fprfld(ctx->opcode));        \
8507    i32 = tcg_const_i32(i32fld(ctx->opcode));      \
8508    gen_helper_##name(cpu_env, rt, rs, i32);       \
8509    if (unlikely(Rc(ctx->opcode) != 0)) {          \
8510        gen_set_cr1_from_fpscr(ctx);               \
8511    }                                              \
8512    tcg_temp_free_ptr(rt);                         \
8513    tcg_temp_free_ptr(rs);                         \
8514    tcg_temp_free_i32(i32);                        \
8515}
8516
8517GEN_DFP_T_A_B_Rc(dadd)
8518GEN_DFP_T_A_B_Rc(daddq)
8519GEN_DFP_T_A_B_Rc(dsub)
8520GEN_DFP_T_A_B_Rc(dsubq)
8521GEN_DFP_T_A_B_Rc(dmul)
8522GEN_DFP_T_A_B_Rc(dmulq)
8523GEN_DFP_T_A_B_Rc(ddiv)
8524GEN_DFP_T_A_B_Rc(ddivq)
8525GEN_DFP_BF_A_B(dcmpu)
8526GEN_DFP_BF_A_B(dcmpuq)
8527GEN_DFP_BF_A_B(dcmpo)
8528GEN_DFP_BF_A_B(dcmpoq)
8529GEN_DFP_BF_A_DCM(dtstdc)
8530GEN_DFP_BF_A_DCM(dtstdcq)
8531GEN_DFP_BF_A_DCM(dtstdg)
8532GEN_DFP_BF_A_DCM(dtstdgq)
8533GEN_DFP_BF_A_B(dtstex)
8534GEN_DFP_BF_A_B(dtstexq)
8535GEN_DFP_BF_A_B(dtstsf)
8536GEN_DFP_BF_A_B(dtstsfq)
8537GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC)
8538GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC)
8539GEN_DFP_T_A_B_I32_Rc(dqua, RMC)
8540GEN_DFP_T_A_B_I32_Rc(dquaq, RMC)
8541GEN_DFP_T_A_B_I32_Rc(drrnd, RMC)
8542GEN_DFP_T_A_B_I32_Rc(drrndq, RMC)
8543GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC)
8544GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC)
8545GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC)
8546GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC)
8547GEN_DFP_T_B_Rc(dctdp)
8548GEN_DFP_T_B_Rc(dctqpq)
8549GEN_DFP_T_B_Rc(drsp)
8550GEN_DFP_T_B_Rc(drdpq)
8551GEN_DFP_T_B_Rc(dcffix)
8552GEN_DFP_T_B_Rc(dcffixq)
8553GEN_DFP_T_B_Rc(dctfix)
8554GEN_DFP_T_B_Rc(dctfixq)
8555GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
8556GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
8557GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
8558GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
8559GEN_DFP_T_B_Rc(dxex)
8560GEN_DFP_T_B_Rc(dxexq)
8561GEN_DFP_T_A_B_Rc(diex)
8562GEN_DFP_T_A_B_Rc(diexq)
8563GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
8564GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
8565GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
8566GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
8567
8568/***                           SPE extension                               ***/
8569/* Register moves */
8570
8571static inline void gen_evmra(DisasContext *ctx)
8572{
8573
8574    if (unlikely(!ctx->spe_enabled)) {
8575        gen_exception(ctx, POWERPC_EXCP_SPEU);
8576        return;
8577    }
8578
8579    TCGv_i64 tmp = tcg_temp_new_i64();
8580
8581    /* tmp := rA_lo + rA_hi << 32 */
8582    tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8583
8584    /* spe_acc := tmp */
8585    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
8586    tcg_temp_free_i64(tmp);
8587
8588    /* rD := rA */
8589    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8590    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8591}
8592
8593static inline void gen_load_gpr64(TCGv_i64 t, int reg)
8594{
8595    tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
8596}
8597
8598static inline void gen_store_gpr64(int reg, TCGv_i64 t)
8599{
8600    tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
8601}
8602
8603#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
8604static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
8605{                                                                             \
8606    if (Rc(ctx->opcode))                                                      \
8607        gen_##name1(ctx);                                                     \
8608    else                                                                      \
8609        gen_##name0(ctx);                                                     \
8610}
8611
8612/* Handler for undefined SPE opcodes */
8613static inline void gen_speundef(DisasContext *ctx)
8614{
8615    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
8616}
8617
8618/* SPE logic */
8619#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
8620static inline void gen_##name(DisasContext *ctx)                              \
8621{                                                                             \
8622    if (unlikely(!ctx->spe_enabled)) {                                        \
8623        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8624        return;                                                               \
8625    }                                                                         \
8626    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
8627           cpu_gpr[rB(ctx->opcode)]);                                         \
8628    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
8629           cpu_gprh[rB(ctx->opcode)]);                                        \
8630}
8631
8632GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
8633GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
8634GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
8635GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
8636GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
8637GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
8638GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
8639GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
8640
8641/* SPE logic immediate */
8642#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
8643static inline void gen_##name(DisasContext *ctx)                              \
8644{                                                                             \
8645    TCGv_i32 t0;                                                              \
8646    if (unlikely(!ctx->spe_enabled)) {                                        \
8647        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8648        return;                                                               \
8649    }                                                                         \
8650    t0 = tcg_temp_new_i32();                                                  \
8651                                                                              \
8652    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8653    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
8654    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8655                                                                              \
8656    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8657    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
8658    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8659                                                                              \
8660    tcg_temp_free_i32(t0);                                                    \
8661}
8662GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
8663GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
8664GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
8665GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
8666
8667/* SPE arithmetic */
8668#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
8669static inline void gen_##name(DisasContext *ctx)                              \
8670{                                                                             \
8671    TCGv_i32 t0;                                                              \
8672    if (unlikely(!ctx->spe_enabled)) {                                        \
8673        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8674        return;                                                               \
8675    }                                                                         \
8676    t0 = tcg_temp_new_i32();                                                  \
8677                                                                              \
8678    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8679    tcg_op(t0, t0);                                                           \
8680    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8681                                                                              \
8682    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8683    tcg_op(t0, t0);                                                           \
8684    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8685                                                                              \
8686    tcg_temp_free_i32(t0);                                                    \
8687}
8688
8689static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
8690{
8691    TCGLabel *l1 = gen_new_label();
8692    TCGLabel *l2 = gen_new_label();
8693
8694    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
8695    tcg_gen_neg_i32(ret, arg1);
8696    tcg_gen_br(l2);
8697    gen_set_label(l1);
8698    tcg_gen_mov_i32(ret, arg1);
8699    gen_set_label(l2);
8700}
8701GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
8702GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
8703GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
8704GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
8705static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
8706{
8707    tcg_gen_addi_i32(ret, arg1, 0x8000);
8708    tcg_gen_ext16u_i32(ret, ret);
8709}
8710GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
8711GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
8712GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
8713
8714#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
8715static inline void gen_##name(DisasContext *ctx)                              \
8716{                                                                             \
8717    TCGv_i32 t0, t1;                                                          \
8718    if (unlikely(!ctx->spe_enabled)) {                                        \
8719        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8720        return;                                                               \
8721    }                                                                         \
8722    t0 = tcg_temp_new_i32();                                                  \
8723    t1 = tcg_temp_new_i32();                                                  \
8724                                                                              \
8725    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
8726    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
8727    tcg_op(t0, t0, t1);                                                       \
8728    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8729                                                                              \
8730    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]);                      \
8731    tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]);                      \
8732    tcg_op(t0, t0, t1);                                                       \
8733    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8734                                                                              \
8735    tcg_temp_free_i32(t0);                                                    \
8736    tcg_temp_free_i32(t1);                                                    \
8737}
8738
8739static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8740{
8741    TCGLabel *l1 = gen_new_label();
8742    TCGLabel *l2 = gen_new_label();
8743    TCGv_i32 t0 = tcg_temp_local_new_i32();
8744
8745    /* No error here: 6 bits are used */
8746    tcg_gen_andi_i32(t0, arg2, 0x3F);
8747    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8748    tcg_gen_shr_i32(ret, arg1, t0);
8749    tcg_gen_br(l2);
8750    gen_set_label(l1);
8751    tcg_gen_movi_i32(ret, 0);
8752    gen_set_label(l2);
8753    tcg_temp_free_i32(t0);
8754}
8755GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
8756static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8757{
8758    TCGLabel *l1 = gen_new_label();
8759    TCGLabel *l2 = gen_new_label();
8760    TCGv_i32 t0 = tcg_temp_local_new_i32();
8761
8762    /* No error here: 6 bits are used */
8763    tcg_gen_andi_i32(t0, arg2, 0x3F);
8764    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8765    tcg_gen_sar_i32(ret, arg1, t0);
8766    tcg_gen_br(l2);
8767    gen_set_label(l1);
8768    tcg_gen_movi_i32(ret, 0);
8769    gen_set_label(l2);
8770    tcg_temp_free_i32(t0);
8771}
8772GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
8773static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8774{
8775    TCGLabel *l1 = gen_new_label();
8776    TCGLabel *l2 = gen_new_label();
8777    TCGv_i32 t0 = tcg_temp_local_new_i32();
8778
8779    /* No error here: 6 bits are used */
8780    tcg_gen_andi_i32(t0, arg2, 0x3F);
8781    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8782    tcg_gen_shl_i32(ret, arg1, t0);
8783    tcg_gen_br(l2);
8784    gen_set_label(l1);
8785    tcg_gen_movi_i32(ret, 0);
8786    gen_set_label(l2);
8787    tcg_temp_free_i32(t0);
8788}
8789GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
8790static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8791{
8792    TCGv_i32 t0 = tcg_temp_new_i32();
8793    tcg_gen_andi_i32(t0, arg2, 0x1F);
8794    tcg_gen_rotl_i32(ret, arg1, t0);
8795    tcg_temp_free_i32(t0);
8796}
8797GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
8798static inline void gen_evmergehi(DisasContext *ctx)
8799{
8800    if (unlikely(!ctx->spe_enabled)) {
8801        gen_exception(ctx, POWERPC_EXCP_SPEU);
8802        return;
8803    }
8804    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8805    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8806}
8807GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
8808static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
8809{
8810    tcg_gen_sub_i32(ret, arg2, arg1);
8811}
8812GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
8813
8814/* SPE arithmetic immediate */
8815#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
8816static inline void gen_##name(DisasContext *ctx)                              \
8817{                                                                             \
8818    TCGv_i32 t0;                                                              \
8819    if (unlikely(!ctx->spe_enabled)) {                                        \
8820        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8821        return;                                                               \
8822    }                                                                         \
8823    t0 = tcg_temp_new_i32();                                                  \
8824                                                                              \
8825    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8826    tcg_op(t0, t0, rA(ctx->opcode));                                          \
8827    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
8828                                                                              \
8829    tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]);                      \
8830    tcg_op(t0, t0, rA(ctx->opcode));                                          \
8831    tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0);                       \
8832                                                                              \
8833    tcg_temp_free_i32(t0);                                                    \
8834}
8835GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
8836GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
8837
8838/* SPE comparison */
8839#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
8840static inline void gen_##name(DisasContext *ctx)                              \
8841{                                                                             \
8842    if (unlikely(!ctx->spe_enabled)) {                                        \
8843        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8844        return;                                                               \
8845    }                                                                         \
8846    TCGLabel *l1 = gen_new_label();                                           \
8847    TCGLabel *l2 = gen_new_label();                                           \
8848    TCGLabel *l3 = gen_new_label();                                           \
8849    TCGLabel *l4 = gen_new_label();                                           \
8850                                                                              \
8851    tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);    \
8852    tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8853    tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);  \
8854    tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);  \
8855                                                                              \
8856    tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)],                     \
8857                       cpu_gpr[rB(ctx->opcode)], l1);                         \
8858    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
8859    tcg_gen_br(l2);                                                           \
8860    gen_set_label(l1);                                                        \
8861    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
8862                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
8863    gen_set_label(l2);                                                        \
8864    tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)],                    \
8865                       cpu_gprh[rB(ctx->opcode)], l3);                        \
8866    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
8867                     ~(CRF_CH | CRF_CH_AND_CL));                              \
8868    tcg_gen_br(l4);                                                           \
8869    gen_set_label(l3);                                                        \
8870    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
8871                    CRF_CH | CRF_CH_OR_CL);                                   \
8872    gen_set_label(l4);                                                        \
8873}
8874GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
8875GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
8876GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
8877GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
8878GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
8879
8880/* SPE misc */
8881static inline void gen_brinc(DisasContext *ctx)
8882{
8883    /* Note: brinc is usable even if SPE is disabled */
8884    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
8885                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8886}
8887static inline void gen_evmergelo(DisasContext *ctx)
8888{
8889    if (unlikely(!ctx->spe_enabled)) {
8890        gen_exception(ctx, POWERPC_EXCP_SPEU);
8891        return;
8892    }
8893    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8894    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8895}
8896static inline void gen_evmergehilo(DisasContext *ctx)
8897{
8898    if (unlikely(!ctx->spe_enabled)) {
8899        gen_exception(ctx, POWERPC_EXCP_SPEU);
8900        return;
8901    }
8902    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8903    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8904}
8905static inline void gen_evmergelohi(DisasContext *ctx)
8906{
8907    if (unlikely(!ctx->spe_enabled)) {
8908        gen_exception(ctx, POWERPC_EXCP_SPEU);
8909        return;
8910    }
8911    if (rD(ctx->opcode) == rA(ctx->opcode)) {
8912        TCGv tmp = tcg_temp_new();
8913        tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
8914        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8915        tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
8916        tcg_temp_free(tmp);
8917    } else {
8918        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8919        tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8920    }
8921}
8922static inline void gen_evsplati(DisasContext *ctx)
8923{
8924    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
8925
8926    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8927    tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
8928}
8929static inline void gen_evsplatfi(DisasContext *ctx)
8930{
8931    uint64_t imm = rA(ctx->opcode) << 27;
8932
8933    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8934    tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
8935}
8936
8937static inline void gen_evsel(DisasContext *ctx)
8938{
8939    TCGLabel *l1 = gen_new_label();
8940    TCGLabel *l2 = gen_new_label();
8941    TCGLabel *l3 = gen_new_label();
8942    TCGLabel *l4 = gen_new_label();
8943    TCGv_i32 t0 = tcg_temp_local_new_i32();
8944
8945    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
8946    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
8947    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
8948    tcg_gen_br(l2);
8949    gen_set_label(l1);
8950    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8951    gen_set_label(l2);
8952    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
8953    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
8954    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8955    tcg_gen_br(l4);
8956    gen_set_label(l3);
8957    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8958    gen_set_label(l4);
8959    tcg_temp_free_i32(t0);
8960}
8961
8962static void gen_evsel0(DisasContext *ctx)
8963{
8964    gen_evsel(ctx);
8965}
8966
8967static void gen_evsel1(DisasContext *ctx)
8968{
8969    gen_evsel(ctx);
8970}
8971
8972static void gen_evsel2(DisasContext *ctx)
8973{
8974    gen_evsel(ctx);
8975}
8976
8977static void gen_evsel3(DisasContext *ctx)
8978{
8979    gen_evsel(ctx);
8980}
8981
8982/* Multiply */
8983
8984static inline void gen_evmwumi(DisasContext *ctx)
8985{
8986    TCGv_i64 t0, t1;
8987
8988    if (unlikely(!ctx->spe_enabled)) {
8989        gen_exception(ctx, POWERPC_EXCP_SPEU);
8990        return;
8991    }
8992
8993    t0 = tcg_temp_new_i64();
8994    t1 = tcg_temp_new_i64();
8995
8996    /* t0 := rA; t1 := rB */
8997    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
8998    tcg_gen_ext32u_i64(t0, t0);
8999    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
9000    tcg_gen_ext32u_i64(t1, t1);
9001
9002    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
9003
9004    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
9005
9006    tcg_temp_free_i64(t0);
9007    tcg_temp_free_i64(t1);
9008}
9009
9010static inline void gen_evmwumia(DisasContext *ctx)
9011{
9012    TCGv_i64 tmp;
9013
9014    if (unlikely(!ctx->spe_enabled)) {
9015        gen_exception(ctx, POWERPC_EXCP_SPEU);
9016        return;
9017    }
9018
9019    gen_evmwumi(ctx);            /* rD := rA * rB */
9020
9021    tmp = tcg_temp_new_i64();
9022
9023    /* acc := rD */
9024    gen_load_gpr64(tmp, rD(ctx->opcode));
9025    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
9026    tcg_temp_free_i64(tmp);
9027}
9028
9029static inline void gen_evmwumiaa(DisasContext *ctx)
9030{
9031    TCGv_i64 acc;
9032    TCGv_i64 tmp;
9033
9034    if (unlikely(!ctx->spe_enabled)) {
9035        gen_exception(ctx, POWERPC_EXCP_SPEU);
9036        return;
9037    }
9038
9039    gen_evmwumi(ctx);           /* rD := rA * rB */
9040
9041    acc = tcg_temp_new_i64();
9042    tmp = tcg_temp_new_i64();
9043
9044    /* tmp := rD */
9045    gen_load_gpr64(tmp, rD(ctx->opcode));
9046
9047    /* Load acc */
9048    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9049
9050    /* acc := tmp + acc */
9051    tcg_gen_add_i64(acc, acc, tmp);
9052
9053    /* Store acc */
9054    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9055
9056    /* rD := acc */
9057    gen_store_gpr64(rD(ctx->opcode), acc);
9058
9059    tcg_temp_free_i64(acc);
9060    tcg_temp_free_i64(tmp);
9061}
9062
9063static inline void gen_evmwsmi(DisasContext *ctx)
9064{
9065    TCGv_i64 t0, t1;
9066
9067    if (unlikely(!ctx->spe_enabled)) {
9068        gen_exception(ctx, POWERPC_EXCP_SPEU);
9069        return;
9070    }
9071
9072    t0 = tcg_temp_new_i64();
9073    t1 = tcg_temp_new_i64();
9074
9075    /* t0 := rA; t1 := rB */
9076    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
9077    tcg_gen_ext32s_i64(t0, t0);
9078    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
9079    tcg_gen_ext32s_i64(t1, t1);
9080
9081    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */
9082
9083    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
9084
9085    tcg_temp_free_i64(t0);
9086    tcg_temp_free_i64(t1);
9087}
9088
9089static inline void gen_evmwsmia(DisasContext *ctx)
9090{
9091    TCGv_i64 tmp;
9092
9093    gen_evmwsmi(ctx);            /* rD := rA * rB */
9094
9095    tmp = tcg_temp_new_i64();
9096
9097    /* acc := rD */
9098    gen_load_gpr64(tmp, rD(ctx->opcode));
9099    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
9100
9101    tcg_temp_free_i64(tmp);
9102}
9103
9104static inline void gen_evmwsmiaa(DisasContext *ctx)
9105{
9106    TCGv_i64 acc = tcg_temp_new_i64();
9107    TCGv_i64 tmp = tcg_temp_new_i64();
9108
9109    gen_evmwsmi(ctx);           /* rD := rA * rB */
9110
9111    acc = tcg_temp_new_i64();
9112    tmp = tcg_temp_new_i64();
9113
9114    /* tmp := rD */
9115    gen_load_gpr64(tmp, rD(ctx->opcode));
9116
9117    /* Load acc */
9118    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9119
9120    /* acc := tmp + acc */
9121    tcg_gen_add_i64(acc, acc, tmp);
9122
9123    /* Store acc */
9124    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
9125
9126    /* rD := acc */
9127    gen_store_gpr64(rD(ctx->opcode), acc);
9128
9129    tcg_temp_free_i64(acc);
9130    tcg_temp_free_i64(tmp);
9131}
9132
9133GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9134GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9135GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9136GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9137GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9138GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9139GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9140GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
9141GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
9142GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9143GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9144GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9145GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9146GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9147GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9148GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9149GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9150GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9151GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9152GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
9153GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9154GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9155GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
9156GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
9157GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9158GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9159GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9160GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9161GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
9162
9163/* SPE load and stores */
9164static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
9165{
9166    target_ulong uimm = rB(ctx->opcode);
9167
9168    if (rA(ctx->opcode) == 0) {
9169        tcg_gen_movi_tl(EA, uimm << sh);
9170    } else {
9171        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
9172        if (NARROW_MODE(ctx)) {
9173            tcg_gen_ext32u_tl(EA, EA);
9174        }
9175    }
9176}
9177
9178static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
9179{
9180    TCGv_i64 t0 = tcg_temp_new_i64();
9181    gen_qemu_ld64(ctx, t0, addr);
9182    gen_store_gpr64(rD(ctx->opcode), t0);
9183    tcg_temp_free_i64(t0);
9184}
9185
9186static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
9187{
9188    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9189    gen_addr_add(ctx, addr, addr, 4);
9190    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9191}
9192
9193static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
9194{
9195    TCGv t0 = tcg_temp_new();
9196    gen_qemu_ld16u(ctx, t0, addr);
9197    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9198    gen_addr_add(ctx, addr, addr, 2);
9199    gen_qemu_ld16u(ctx, t0, addr);
9200    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9201    gen_addr_add(ctx, addr, addr, 2);
9202    gen_qemu_ld16u(ctx, t0, addr);
9203    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9204    gen_addr_add(ctx, addr, addr, 2);
9205    gen_qemu_ld16u(ctx, t0, addr);
9206    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
9207    tcg_temp_free(t0);
9208}
9209
9210static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
9211{
9212    TCGv t0 = tcg_temp_new();
9213    gen_qemu_ld16u(ctx, t0, addr);
9214    tcg_gen_shli_tl(t0, t0, 16);
9215    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9216    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9217    tcg_temp_free(t0);
9218}
9219
9220static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
9221{
9222    TCGv t0 = tcg_temp_new();
9223    gen_qemu_ld16u(ctx, t0, addr);
9224    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9225    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9226    tcg_temp_free(t0);
9227}
9228
9229static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
9230{
9231    TCGv t0 = tcg_temp_new();
9232    gen_qemu_ld16s(ctx, t0, addr);
9233    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9234    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9235    tcg_temp_free(t0);
9236}
9237
9238static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
9239{
9240    TCGv t0 = tcg_temp_new();
9241    gen_qemu_ld16u(ctx, t0, addr);
9242    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9243    gen_addr_add(ctx, addr, addr, 2);
9244    gen_qemu_ld16u(ctx, t0, addr);
9245    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
9246    tcg_temp_free(t0);
9247}
9248
9249static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
9250{
9251    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9252    gen_addr_add(ctx, addr, addr, 2);
9253    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9254}
9255
9256static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
9257{
9258    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9259    gen_addr_add(ctx, addr, addr, 2);
9260    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
9261}
9262
9263static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
9264{
9265    TCGv t0 = tcg_temp_new();
9266    gen_qemu_ld32u(ctx, t0, addr);
9267    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9268    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
9269    tcg_temp_free(t0);
9270}
9271
9272static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
9273{
9274    TCGv t0 = tcg_temp_new();
9275    gen_qemu_ld16u(ctx, t0, addr);
9276    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9277    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9278    gen_addr_add(ctx, addr, addr, 2);
9279    gen_qemu_ld16u(ctx, t0, addr);
9280    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
9281    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
9282    tcg_temp_free(t0);
9283}
9284
9285static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
9286{
9287    TCGv_i64 t0 = tcg_temp_new_i64();
9288    gen_load_gpr64(t0, rS(ctx->opcode));
9289    gen_qemu_st64(ctx, t0, addr);
9290    tcg_temp_free_i64(t0);
9291}
9292
9293static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
9294{
9295    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9296    gen_addr_add(ctx, addr, addr, 4);
9297    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9298}
9299
9300static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
9301{
9302    TCGv t0 = tcg_temp_new();
9303    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
9304    gen_qemu_st16(ctx, t0, addr);
9305    gen_addr_add(ctx, addr, addr, 2);
9306    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9307    gen_addr_add(ctx, addr, addr, 2);
9308    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
9309    gen_qemu_st16(ctx, t0, addr);
9310    tcg_temp_free(t0);
9311    gen_addr_add(ctx, addr, addr, 2);
9312    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9313}
9314
9315static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
9316{
9317    TCGv t0 = tcg_temp_new();
9318    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
9319    gen_qemu_st16(ctx, t0, addr);
9320    gen_addr_add(ctx, addr, addr, 2);
9321    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
9322    gen_qemu_st16(ctx, t0, addr);
9323    tcg_temp_free(t0);
9324}
9325
9326static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
9327{
9328    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9329    gen_addr_add(ctx, addr, addr, 2);
9330    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9331}
9332
9333static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
9334{
9335    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
9336}
9337
9338static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
9339{
9340    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
9341}
9342
9343#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
9344static void glue(gen_, name)(DisasContext *ctx)                                       \
9345{                                                                             \
9346    TCGv t0;                                                                  \
9347    if (unlikely(!ctx->spe_enabled)) {                                        \
9348        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9349        return;                                                               \
9350    }                                                                         \
9351    gen_set_access_type(ctx, ACCESS_INT);                                     \
9352    t0 = tcg_temp_new();                                                      \
9353    if (Rc(ctx->opcode)) {                                                    \
9354        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
9355    } else {                                                                  \
9356        gen_addr_reg_index(ctx, t0);                                          \
9357    }                                                                         \
9358    gen_op_##name(ctx, t0);                                                   \
9359    tcg_temp_free(t0);                                                        \
9360}
9361
9362GEN_SPEOP_LDST(evldd, 0x00, 3);
9363GEN_SPEOP_LDST(evldw, 0x01, 3);
9364GEN_SPEOP_LDST(evldh, 0x02, 3);
9365GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
9366GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
9367GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
9368GEN_SPEOP_LDST(evlwhe, 0x08, 2);
9369GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
9370GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
9371GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
9372GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
9373
9374GEN_SPEOP_LDST(evstdd, 0x10, 3);
9375GEN_SPEOP_LDST(evstdw, 0x11, 3);
9376GEN_SPEOP_LDST(evstdh, 0x12, 3);
9377GEN_SPEOP_LDST(evstwhe, 0x18, 2);
9378GEN_SPEOP_LDST(evstwho, 0x1A, 2);
9379GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
9380GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
9381
9382/* Multiply and add - TODO */
9383#if 0
9384GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
9385GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9386GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9387GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9388GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9389GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9390GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9391GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9392GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9393GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9394GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9395GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9396
9397GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9398GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9399GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9400GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9401GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9402GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9403GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9404GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9405GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9406GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9407GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9408GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9409
9410GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9411GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9412GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9413GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9414GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
9415
9416GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9417GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9418GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9419GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9420GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9421GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9422GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9423GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9424GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9425GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9426GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9427GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9428
9429GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9430GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9431GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9432GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9433
9434GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9435GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9436GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9437GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9438GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9439GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9440GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9441GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9442GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9443GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9444GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9445GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9446
9447GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9448GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9449GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9450GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9451GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9452#endif
9453
9454/***                      SPE floating-point extension                     ***/
9455#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
9456static inline void gen_##name(DisasContext *ctx)                              \
9457{                                                                             \
9458    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
9459    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
9460    gen_helper_##name(t0, cpu_env, t0);                                       \
9461    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
9462    tcg_temp_free_i32(t0);                                                    \
9463}
9464#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
9465static inline void gen_##name(DisasContext *ctx)                              \
9466{                                                                             \
9467    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9468    TCGv_i32 t1 = tcg_temp_new_i32();                                         \
9469    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
9470    gen_helper_##name(t1, cpu_env, t0);                                       \
9471    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);                        \
9472    tcg_temp_free_i64(t0);                                                    \
9473    tcg_temp_free_i32(t1);                                                    \
9474}
9475#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
9476static inline void gen_##name(DisasContext *ctx)                              \
9477{                                                                             \
9478    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9479    TCGv_i32 t1 = tcg_temp_new_i32();                                         \
9480    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9481    gen_helper_##name(t0, cpu_env, t1);                                       \
9482    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9483    tcg_temp_free_i64(t0);                                                    \
9484    tcg_temp_free_i32(t1);                                                    \
9485}
9486#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
9487static inline void gen_##name(DisasContext *ctx)                              \
9488{                                                                             \
9489    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
9490    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
9491    gen_helper_##name(t0, cpu_env, t0);                                       \
9492    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9493    tcg_temp_free_i64(t0);                                                    \
9494}
9495#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
9496static inline void gen_##name(DisasContext *ctx)                              \
9497{                                                                             \
9498    TCGv_i32 t0, t1;                                                          \
9499    if (unlikely(!ctx->spe_enabled)) {                                        \
9500        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9501        return;                                                               \
9502    }                                                                         \
9503    t0 = tcg_temp_new_i32();                                                  \
9504    t1 = tcg_temp_new_i32();                                                  \
9505    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
9506    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9507    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
9508    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);                        \
9509                                                                              \
9510    tcg_temp_free_i32(t0);                                                    \
9511    tcg_temp_free_i32(t1);                                                    \
9512}
9513#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
9514static inline void gen_##name(DisasContext *ctx)                              \
9515{                                                                             \
9516    TCGv_i64 t0, t1;                                                          \
9517    if (unlikely(!ctx->spe_enabled)) {                                        \
9518        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9519        return;                                                               \
9520    }                                                                         \
9521    t0 = tcg_temp_new_i64();                                                  \
9522    t1 = tcg_temp_new_i64();                                                  \
9523    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
9524    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
9525    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
9526    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
9527    tcg_temp_free_i64(t0);                                                    \
9528    tcg_temp_free_i64(t1);                                                    \
9529}
9530#define GEN_SPEFPUOP_COMP_32(name)                                            \
9531static inline void gen_##name(DisasContext *ctx)                              \
9532{                                                                             \
9533    TCGv_i32 t0, t1;                                                          \
9534    if (unlikely(!ctx->spe_enabled)) {                                        \
9535        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9536        return;                                                               \
9537    }                                                                         \
9538    t0 = tcg_temp_new_i32();                                                  \
9539    t1 = tcg_temp_new_i32();                                                  \
9540                                                                              \
9541    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
9542    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
9543    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
9544                                                                              \
9545    tcg_temp_free_i32(t0);                                                    \
9546    tcg_temp_free_i32(t1);                                                    \
9547}
9548#define GEN_SPEFPUOP_COMP_64(name)                                            \
9549static inline void gen_##name(DisasContext *ctx)                              \
9550{                                                                             \
9551    TCGv_i64 t0, t1;                                                          \
9552    if (unlikely(!ctx->spe_enabled)) {                                        \
9553        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
9554        return;                                                               \
9555    }                                                                         \
9556    t0 = tcg_temp_new_i64();                                                  \
9557    t1 = tcg_temp_new_i64();                                                  \
9558    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
9559    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
9560    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
9561    tcg_temp_free_i64(t0);                                                    \
9562    tcg_temp_free_i64(t1);                                                    \
9563}
9564
9565/* Single precision floating-point vectors operations */
9566/* Arithmetic */
9567GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
9568GEN_SPEFPUOP_ARITH2_64_64(evfssub);
9569GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
9570GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
9571static inline void gen_evfsabs(DisasContext *ctx)
9572{
9573    if (unlikely(!ctx->spe_enabled)) {
9574        gen_exception(ctx, POWERPC_EXCP_SPEU);
9575        return;
9576    }
9577    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9578                    ~0x80000000);
9579    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9580                    ~0x80000000);
9581}
9582static inline void gen_evfsnabs(DisasContext *ctx)
9583{
9584    if (unlikely(!ctx->spe_enabled)) {
9585        gen_exception(ctx, POWERPC_EXCP_SPEU);
9586        return;
9587    }
9588    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9589                   0x80000000);
9590    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9591                   0x80000000);
9592}
9593static inline void gen_evfsneg(DisasContext *ctx)
9594{
9595    if (unlikely(!ctx->spe_enabled)) {
9596        gen_exception(ctx, POWERPC_EXCP_SPEU);
9597        return;
9598    }
9599    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9600                    0x80000000);
9601    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9602                    0x80000000);
9603}
9604
9605/* Conversion */
9606GEN_SPEFPUOP_CONV_64_64(evfscfui);
9607GEN_SPEFPUOP_CONV_64_64(evfscfsi);
9608GEN_SPEFPUOP_CONV_64_64(evfscfuf);
9609GEN_SPEFPUOP_CONV_64_64(evfscfsf);
9610GEN_SPEFPUOP_CONV_64_64(evfsctui);
9611GEN_SPEFPUOP_CONV_64_64(evfsctsi);
9612GEN_SPEFPUOP_CONV_64_64(evfsctuf);
9613GEN_SPEFPUOP_CONV_64_64(evfsctsf);
9614GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
9615GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
9616
9617/* Comparison */
9618GEN_SPEFPUOP_COMP_64(evfscmpgt);
9619GEN_SPEFPUOP_COMP_64(evfscmplt);
9620GEN_SPEFPUOP_COMP_64(evfscmpeq);
9621GEN_SPEFPUOP_COMP_64(evfststgt);
9622GEN_SPEFPUOP_COMP_64(evfststlt);
9623GEN_SPEFPUOP_COMP_64(evfststeq);
9624
9625/* Opcodes definitions */
9626GEN_SPE(evfsadd,   evfssub,   0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9627GEN_SPE(evfsabs,   evfsnabs,  0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9628GEN_SPE(evfsneg,   speundef,  0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9629GEN_SPE(evfsmul,   evfsdiv,   0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9630GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9631GEN_SPE(evfscmpeq, speundef,  0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9632GEN_SPE(evfscfui,  evfscfsi,  0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9633GEN_SPE(evfscfuf,  evfscfsf,  0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9634GEN_SPE(evfsctui,  evfsctsi,  0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9635GEN_SPE(evfsctuf,  evfsctsf,  0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9636GEN_SPE(evfsctuiz, speundef,  0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9637GEN_SPE(evfsctsiz, speundef,  0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9638GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9639GEN_SPE(evfststeq, speundef,  0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9640
9641/* Single precision floating-point operations */
9642/* Arithmetic */
9643GEN_SPEFPUOP_ARITH2_32_32(efsadd);
9644GEN_SPEFPUOP_ARITH2_32_32(efssub);
9645GEN_SPEFPUOP_ARITH2_32_32(efsmul);
9646GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
9647static inline void gen_efsabs(DisasContext *ctx)
9648{
9649    if (unlikely(!ctx->spe_enabled)) {
9650        gen_exception(ctx, POWERPC_EXCP_SPEU);
9651        return;
9652    }
9653    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
9654}
9655static inline void gen_efsnabs(DisasContext *ctx)
9656{
9657    if (unlikely(!ctx->spe_enabled)) {
9658        gen_exception(ctx, POWERPC_EXCP_SPEU);
9659        return;
9660    }
9661    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
9662}
9663static inline void gen_efsneg(DisasContext *ctx)
9664{
9665    if (unlikely(!ctx->spe_enabled)) {
9666        gen_exception(ctx, POWERPC_EXCP_SPEU);
9667        return;
9668    }
9669    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
9670}
9671
9672/* Conversion */
9673GEN_SPEFPUOP_CONV_32_32(efscfui);
9674GEN_SPEFPUOP_CONV_32_32(efscfsi);
9675GEN_SPEFPUOP_CONV_32_32(efscfuf);
9676GEN_SPEFPUOP_CONV_32_32(efscfsf);
9677GEN_SPEFPUOP_CONV_32_32(efsctui);
9678GEN_SPEFPUOP_CONV_32_32(efsctsi);
9679GEN_SPEFPUOP_CONV_32_32(efsctuf);
9680GEN_SPEFPUOP_CONV_32_32(efsctsf);
9681GEN_SPEFPUOP_CONV_32_32(efsctuiz);
9682GEN_SPEFPUOP_CONV_32_32(efsctsiz);
9683GEN_SPEFPUOP_CONV_32_64(efscfd);
9684
9685/* Comparison */
9686GEN_SPEFPUOP_COMP_32(efscmpgt);
9687GEN_SPEFPUOP_COMP_32(efscmplt);
9688GEN_SPEFPUOP_COMP_32(efscmpeq);
9689GEN_SPEFPUOP_COMP_32(efststgt);
9690GEN_SPEFPUOP_COMP_32(efststlt);
9691GEN_SPEFPUOP_COMP_32(efststeq);
9692
9693/* Opcodes definitions */
9694GEN_SPE(efsadd,   efssub,   0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9695GEN_SPE(efsabs,   efsnabs,  0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9696GEN_SPE(efsneg,   speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9697GEN_SPE(efsmul,   efsdiv,   0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9698GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9699GEN_SPE(efscmpeq, efscfd,   0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
9700GEN_SPE(efscfui,  efscfsi,  0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9701GEN_SPE(efscfuf,  efscfsf,  0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9702GEN_SPE(efsctui,  efsctsi,  0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9703GEN_SPE(efsctuf,  efsctsf,  0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9704GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9705GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9706GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9707GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9708
9709/* Double precision floating-point operations */
9710/* Arithmetic */
9711GEN_SPEFPUOP_ARITH2_64_64(efdadd);
9712GEN_SPEFPUOP_ARITH2_64_64(efdsub);
9713GEN_SPEFPUOP_ARITH2_64_64(efdmul);
9714GEN_SPEFPUOP_ARITH2_64_64(efddiv);
9715static inline void gen_efdabs(DisasContext *ctx)
9716{
9717    if (unlikely(!ctx->spe_enabled)) {
9718        gen_exception(ctx, POWERPC_EXCP_SPEU);
9719        return;
9720    }
9721    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9722    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9723                    ~0x80000000);
9724}
9725static inline void gen_efdnabs(DisasContext *ctx)
9726{
9727    if (unlikely(!ctx->spe_enabled)) {
9728        gen_exception(ctx, POWERPC_EXCP_SPEU);
9729        return;
9730    }
9731    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9732    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9733                   0x80000000);
9734}
9735static inline void gen_efdneg(DisasContext *ctx)
9736{
9737    if (unlikely(!ctx->spe_enabled)) {
9738        gen_exception(ctx, POWERPC_EXCP_SPEU);
9739        return;
9740    }
9741    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9742    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9743                    0x80000000);
9744}
9745
9746/* Conversion */
9747GEN_SPEFPUOP_CONV_64_32(efdcfui);
9748GEN_SPEFPUOP_CONV_64_32(efdcfsi);
9749GEN_SPEFPUOP_CONV_64_32(efdcfuf);
9750GEN_SPEFPUOP_CONV_64_32(efdcfsf);
9751GEN_SPEFPUOP_CONV_32_64(efdctui);
9752GEN_SPEFPUOP_CONV_32_64(efdctsi);
9753GEN_SPEFPUOP_CONV_32_64(efdctuf);
9754GEN_SPEFPUOP_CONV_32_64(efdctsf);
9755GEN_SPEFPUOP_CONV_32_64(efdctuiz);
9756GEN_SPEFPUOP_CONV_32_64(efdctsiz);
9757GEN_SPEFPUOP_CONV_64_32(efdcfs);
9758GEN_SPEFPUOP_CONV_64_64(efdcfuid);
9759GEN_SPEFPUOP_CONV_64_64(efdcfsid);
9760GEN_SPEFPUOP_CONV_64_64(efdctuidz);
9761GEN_SPEFPUOP_CONV_64_64(efdctsidz);
9762
9763/* Comparison */
9764GEN_SPEFPUOP_COMP_64(efdcmpgt);
9765GEN_SPEFPUOP_COMP_64(efdcmplt);
9766GEN_SPEFPUOP_COMP_64(efdcmpeq);
9767GEN_SPEFPUOP_COMP_64(efdtstgt);
9768GEN_SPEFPUOP_COMP_64(efdtstlt);
9769GEN_SPEFPUOP_COMP_64(efdtsteq);
9770
9771/* Opcodes definitions */
9772GEN_SPE(efdadd,    efdsub,    0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9773GEN_SPE(efdcfuid,  efdcfsid,  0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9774GEN_SPE(efdabs,    efdnabs,   0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
9775GEN_SPE(efdneg,    speundef,  0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9776GEN_SPE(efdmul,    efddiv,    0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9777GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9778GEN_SPE(efdcmpgt,  efdcmplt,  0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9779GEN_SPE(efdcmpeq,  efdcfs,    0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
9780GEN_SPE(efdcfui,   efdcfsi,   0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9781GEN_SPE(efdcfuf,   efdcfsf,   0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9782GEN_SPE(efdctui,   efdctsi,   0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9783GEN_SPE(efdctuf,   efdctsf,   0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9784GEN_SPE(efdctuiz,  speundef,  0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9785GEN_SPE(efdctsiz,  speundef,  0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9786GEN_SPE(efdtstgt,  efdtstlt,  0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9787GEN_SPE(efdtsteq,  speundef,  0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9788
9789static void gen_tbegin(DisasContext *ctx)
9790{
9791    if (unlikely(!ctx->tm_enabled)) {
9792        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9793        return;
9794    }
9795    gen_helper_tbegin(cpu_env);
9796}
9797
9798#define GEN_TM_NOOP(name)                                      \
9799static inline void gen_##name(DisasContext *ctx)               \
9800{                                                              \
9801    if (unlikely(!ctx->tm_enabled)) {                          \
9802        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
9803        return;                                                \
9804    }                                                          \
9805    /* Because tbegin always fails in QEMU, these user         \
9806     * space instructions all have a simple implementation:    \
9807     *                                                         \
9808     *     CR[0] = 0b0 || MSR[TS] || 0b0                       \
9809     *           = 0b0 || 0b00    || 0b0                       \
9810     */                                                        \
9811    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
9812}
9813
9814GEN_TM_NOOP(tend);
9815GEN_TM_NOOP(tabort);
9816GEN_TM_NOOP(tabortwc);
9817GEN_TM_NOOP(tabortwci);
9818GEN_TM_NOOP(tabortdc);
9819GEN_TM_NOOP(tabortdci);
9820GEN_TM_NOOP(tsr);
9821
9822static void gen_tcheck(DisasContext *ctx)
9823{
9824    if (unlikely(!ctx->tm_enabled)) {
9825        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9826        return;
9827    }
9828    /* Because tbegin always fails, the tcheck implementation
9829     * is simple:
9830     *
9831     * CR[CRF] = TDOOMED || MSR[TS] || 0b0
9832     *         = 0b1 || 0b00 || 0b0
9833     */
9834    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
9835}
9836
9837#if defined(CONFIG_USER_ONLY)
9838#define GEN_TM_PRIV_NOOP(name)                                 \
9839static inline void gen_##name(DisasContext *ctx)               \
9840{                                                              \
9841    gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);           \
9842}
9843
9844#else
9845
9846#define GEN_TM_PRIV_NOOP(name)                                 \
9847static inline void gen_##name(DisasContext *ctx)               \
9848{                                                              \
9849    CHK_SV;                                                    \
9850    if (unlikely(!ctx->tm_enabled)) {                          \
9851        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
9852        return;                                                \
9853    }                                                          \
9854    /* Because tbegin always fails, the implementation is      \
9855     * simple:                                                 \
9856     *                                                         \
9857     *   CR[0] = 0b0 || MSR[TS] || 0b0                         \
9858     *         = 0b0 || 0b00 | 0b0                             \
9859     */                                                        \
9860    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
9861}
9862
9863#endif
9864
9865GEN_TM_PRIV_NOOP(treclaim);
9866GEN_TM_PRIV_NOOP(trechkpt);
9867
9868static opcode_t opcodes[] = {
9869GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
9870GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
9871GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
9872GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
9873GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
9874GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
9875GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
9876GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9877GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9878GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9879GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9880GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
9881GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
9882GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
9883GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
9884GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9885#if defined(TARGET_PPC64)
9886GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
9887#endif
9888GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
9889GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
9890GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9891GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9892GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9893GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
9894GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
9895GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
9896GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9897GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9898GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9899GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9900GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
9901GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
9902GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
9903#if defined(TARGET_PPC64)
9904GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
9905GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
9906GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
9907GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
9908#endif
9909GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9910GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9911GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9912GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
9913GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
9914GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
9915GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
9916#if defined(TARGET_PPC64)
9917GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
9918GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
9919GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
9920GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
9921GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
9922#endif
9923GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
9924GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9925GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9926GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
9927GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
9928GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
9929GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
9930GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
9931GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
9932GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
9933GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x00000001, PPC_NONE, PPC2_VSX207),
9934GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x00000001, PPC_NONE, PPC2_VSX207),
9935GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
9936GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
9937GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
9938GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
9939GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
9940GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
9941#if defined(TARGET_PPC64)
9942GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
9943GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
9944GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
9945#endif
9946GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9947GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9948GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
9949GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
9950GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
9951GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
9952GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
9953GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
9954GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9955GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9956GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
9957GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9958GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9959GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
9960#if defined(TARGET_PPC64)
9961GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
9962GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
9963GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
9964GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
9965#endif
9966GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
9967GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
9968GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9969GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9970GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
9971GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
9972GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0, PPC_NONE, PPC2_BCTAR_ISA207),
9973GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
9974GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
9975#if defined(TARGET_PPC64)
9976GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
9977GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
9978GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
9979GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
9980GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
9981GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
9982#endif
9983GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
9984GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
9985GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9986#if defined(TARGET_PPC64)
9987GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
9988GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
9989#endif
9990GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
9991GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
9992GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
9993GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
9994GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
9995GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
9996#if defined(TARGET_PPC64)
9997GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
9998#endif
9999GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
10000GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
10001GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
10002GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
10003GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
10004GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
10005GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
10006GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
10007GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
10008GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
10009GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
10010GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
10011GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
10012GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
10013GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
10014GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
10015GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
10016GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
10017#if defined(TARGET_PPC64)
10018GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
10019GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
10020             PPC_SEGMENT_64B),
10021GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
10022GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
10023             PPC_SEGMENT_64B),
10024GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
10025GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
10026GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
10027GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
10028#endif
10029GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
10030/* XXX Those instructions will need to be handled differently for
10031 * different ISA versions */
10032GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
10033GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
10034GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
10035#if defined(TARGET_PPC64)
10036GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI),
10037GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
10038#endif
10039GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
10040GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
10041GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
10042GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
10043GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
10044GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
10045GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
10046GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
10047GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
10048GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
10049GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
10050GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
10051GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
10052GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
10053GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
10054GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
10055GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
10056GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
10057GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
10058GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
10059GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
10060GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
10061GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
10062GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
10063GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
10064GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
10065GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
10066GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
10067GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
10068GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
10069GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
10070GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
10071GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
10072GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
10073GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
10074GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
10075GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
10076GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
10077GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
10078GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
10079GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
10080GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
10081GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
10082GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
10083GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
10084GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
10085GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
10086GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
10087GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
10088GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10089GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10090GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
10091GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
10092GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10093GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10094GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
10095GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
10096GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
10097GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
10098GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
10099GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
10100GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
10101GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
10102GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
10103GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
10104GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
10105GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
10106GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
10107GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
10108GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
10109GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
10110GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
10111GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
10112GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
10113GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
10114GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
10115GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
10116GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
10117GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
10118GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
10119GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
10120               PPC_NONE, PPC2_BOOKE206),
10121GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
10122               PPC_NONE, PPC2_BOOKE206),
10123GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
10124               PPC_NONE, PPC2_BOOKE206),
10125GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
10126               PPC_NONE, PPC2_BOOKE206),
10127GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
10128               PPC_NONE, PPC2_BOOKE206),
10129GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
10130               PPC_NONE, PPC2_PRCNTL),
10131GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
10132               PPC_NONE, PPC2_PRCNTL),
10133GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
10134GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
10135GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
10136GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
10137              PPC_BOOKE, PPC2_BOOKE206),
10138GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
10139GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
10140               PPC_BOOKE, PPC2_BOOKE206),
10141GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
10142GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
10143GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
10144GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
10145GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
10146GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
10147GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
10148GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
10149GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
10150
10151#undef GEN_INT_ARITH_ADD
10152#undef GEN_INT_ARITH_ADD_CONST
10153#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
10154GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
10155#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
10156                                add_ca, compute_ca, compute_ov)               \
10157GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
10158GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
10159GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
10160GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
10161GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
10162GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
10163GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
10164GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
10165GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
10166GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
10167GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
10168
10169#undef GEN_INT_ARITH_DIVW
10170#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
10171GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
10172GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
10173GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
10174GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
10175GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
10176GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10177GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10178GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10179GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10180
10181#if defined(TARGET_PPC64)
10182#undef GEN_INT_ARITH_DIVD
10183#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
10184GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10185GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
10186GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
10187GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
10188GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
10189
10190GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10191GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10192GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10193GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10194
10195#undef GEN_INT_ARITH_MUL_HELPER
10196#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
10197GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10198GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
10199GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
10200GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
10201#endif
10202
10203#undef GEN_INT_ARITH_SUBF
10204#undef GEN_INT_ARITH_SUBF_CONST
10205#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
10206GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
10207#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
10208                                add_ca, compute_ca, compute_ov)               \
10209GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
10210GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
10211GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
10212GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
10213GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
10214GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
10215GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
10216GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
10217GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
10218GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
10219GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
10220
10221#undef GEN_LOGICAL1
10222#undef GEN_LOGICAL2
10223#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
10224GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
10225#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
10226GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
10227GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
10228GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
10229GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
10230GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
10231GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
10232GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
10233GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
10234GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
10235#if defined(TARGET_PPC64)
10236GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
10237#endif
10238
10239#if defined(TARGET_PPC64)
10240#undef GEN_PPC64_R2
10241#undef GEN_PPC64_R4
10242#define GEN_PPC64_R2(name, opc1, opc2)                                        \
10243GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10244GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
10245             PPC_64B)
10246#define GEN_PPC64_R4(name, opc1, opc2)                                        \
10247GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10248GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
10249             PPC_64B),                                                        \
10250GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
10251             PPC_64B),                                                        \
10252GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
10253             PPC_64B)
10254GEN_PPC64_R4(rldicl, 0x1E, 0x00),
10255GEN_PPC64_R4(rldicr, 0x1E, 0x02),
10256GEN_PPC64_R4(rldic, 0x1E, 0x04),
10257GEN_PPC64_R2(rldcl, 0x1E, 0x08),
10258GEN_PPC64_R2(rldcr, 0x1E, 0x09),
10259GEN_PPC64_R4(rldimi, 0x1E, 0x06),
10260#endif
10261
10262#undef _GEN_FLOAT_ACB
10263#undef GEN_FLOAT_ACB
10264#undef _GEN_FLOAT_AB
10265#undef GEN_FLOAT_AB
10266#undef _GEN_FLOAT_AC
10267#undef GEN_FLOAT_AC
10268#undef GEN_FLOAT_B
10269#undef GEN_FLOAT_BS
10270#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
10271GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
10272#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
10273_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type),                     \
10274_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
10275#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
10276GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10277#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
10278_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
10279_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10280#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
10281GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10282#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
10283_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
10284_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10285#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
10286GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
10287#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
10288GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
10289
10290GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
10291GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
10292GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
10293GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
10294GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
10295GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
10296_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
10297GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
10298GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
10299GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
10300GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
10301GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
10302GEN_HANDLER_E(ftdiv, 0x3F, 0x00, 0x04, 1, PPC_NONE, PPC2_FP_TST_ISA206),
10303GEN_HANDLER_E(ftsqrt, 0x3F, 0x00, 0x05, 1, PPC_NONE, PPC2_FP_TST_ISA206),
10304GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
10305GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10306GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
10307GEN_HANDLER_E(fctiwuz, 0x3F, 0x0F, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10308GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
10309GEN_HANDLER_E(fcfid, 0x3F, 0x0E, 0x1A, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10310GEN_HANDLER_E(fcfids, 0x3B, 0x0E, 0x1A, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10311GEN_HANDLER_E(fcfidu, 0x3F, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10312GEN_HANDLER_E(fcfidus, 0x3B, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10313GEN_HANDLER_E(fctid, 0x3F, 0x0E, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10314GEN_HANDLER_E(fctidu, 0x3F, 0x0E, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10315GEN_HANDLER_E(fctidz, 0x3F, 0x0F, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
10316GEN_HANDLER_E(fctiduz, 0x3F, 0x0F, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10317GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
10318GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
10319GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
10320GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
10321
10322#undef GEN_LD
10323#undef GEN_LDU
10324#undef GEN_LDUX
10325#undef GEN_LDX_E
10326#undef GEN_LDS
10327#define GEN_LD(name, ldop, opc, type)                                         \
10328GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10329#define GEN_LDU(name, ldop, opc, type)                                        \
10330GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10331#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
10332GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
10333#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk)                   \
10334GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
10335#define GEN_LDS(name, ldop, op, type)                                         \
10336GEN_LD(name, ldop, op | 0x20, type)                                           \
10337GEN_LDU(name, ldop, op | 0x21, type)                                          \
10338GEN_LDUX(name, ldop, 0x17, op | 0x01, type)                                   \
10339GEN_LDX(name, ldop, 0x17, op | 0x00, type)
10340
10341GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
10342GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
10343GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
10344GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
10345#if defined(TARGET_PPC64)
10346GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
10347GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
10348GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
10349GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
10350GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
10351
10352/* HV/P7 and later only */
10353GEN_LDX_HVRM(ldcix, ld64, 0x15, 0x1b, PPC_CILDST)
10354GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST)
10355GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
10356GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
10357#endif
10358GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
10359GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
10360
10361#undef GEN_ST
10362#undef GEN_STU
10363#undef GEN_STUX
10364#undef GEN_STX_E
10365#undef GEN_STS
10366#define GEN_ST(name, stop, opc, type)                                         \
10367GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10368#define GEN_STU(name, stop, opc, type)                                        \
10369GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
10370#define GEN_STUX(name, stop, opc2, opc3, type)                                \
10371GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
10372#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk)                   \
10373GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
10374#define GEN_STS(name, stop, op, type)                                         \
10375GEN_ST(name, stop, op | 0x20, type)                                           \
10376GEN_STU(name, stop, op | 0x21, type)                                          \
10377GEN_STUX(name, stop, 0x17, op | 0x01, type)                                   \
10378GEN_STX(name, stop, 0x17, op | 0x00, type)
10379
10380GEN_STS(stb, st8, 0x06, PPC_INTEGER)
10381GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
10382GEN_STS(stw, st32, 0x04, PPC_INTEGER)
10383#if defined(TARGET_PPC64)
10384GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
10385GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
10386GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
10387GEN_STX_HVRM(stdcix, st64, 0x15, 0x1f, PPC_CILDST)
10388GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
10389GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
10390GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
10391#endif
10392GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
10393GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
10394
10395#undef GEN_LDF
10396#undef GEN_LDUF
10397#undef GEN_LDUXF
10398#undef GEN_LDXF
10399#undef GEN_LDFS
10400#define GEN_LDF(name, ldop, opc, type)                                        \
10401GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10402#define GEN_LDUF(name, ldop, opc, type)                                       \
10403GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10404#define GEN_LDUXF(name, ldop, opc, type)                                      \
10405GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10406#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
10407GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10408#define GEN_LDFS(name, ldop, op, type)                                        \
10409GEN_LDF(name, ldop, op | 0x20, type)                                          \
10410GEN_LDUF(name, ldop, op | 0x21, type)                                         \
10411GEN_LDUXF(name, ldop, op | 0x01, type)                                        \
10412GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
10413
10414GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
10415GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
10416GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
10417GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x1, PPC_NONE, PPC2_FP_CVT_ISA206),
10418GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10419GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
10420
10421#undef GEN_STF
10422#undef GEN_STUF
10423#undef GEN_STUXF
10424#undef GEN_STXF
10425#undef GEN_STFS
10426#define GEN_STF(name, stop, opc, type)                                        \
10427GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10428#define GEN_STUF(name, stop, opc, type)                                       \
10429GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10430#define GEN_STUXF(name, stop, opc, type)                                      \
10431GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10432#define GEN_STXF(name, stop, opc2, opc3, type)                                \
10433GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10434#define GEN_STFS(name, stop, op, type)                                        \
10435GEN_STF(name, stop, op | 0x20, type)                                          \
10436GEN_STUF(name, stop, op | 0x21, type)                                         \
10437GEN_STUXF(name, stop, op | 0x01, type)                                        \
10438GEN_STXF(name, stop, 0x17, op | 0x00, type)
10439
10440GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
10441GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
10442GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
10443GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10444GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
10445
10446#undef GEN_CRLOGIC
10447#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
10448GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
10449GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
10450GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
10451GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
10452GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
10453GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
10454GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
10455GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
10456GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
10457
10458#undef GEN_MAC_HANDLER
10459#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
10460GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
10461GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
10462GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
10463GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
10464GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
10465GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
10466GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
10467GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
10468GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
10469GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
10470GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
10471GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
10472GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
10473GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
10474GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
10475GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
10476GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
10477GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
10478GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
10479GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
10480GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
10481GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
10482GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
10483GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
10484GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
10485GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
10486GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
10487GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
10488GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
10489GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
10490GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
10491GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
10492GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
10493GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
10494GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
10495GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
10496GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
10497GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
10498GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
10499GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
10500GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
10501GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
10502GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
10503
10504#undef GEN_VR_LDX
10505#undef GEN_VR_STX
10506#undef GEN_VR_LVE
10507#undef GEN_VR_STVE
10508#define GEN_VR_LDX(name, opc2, opc3)                                          \
10509GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10510#define GEN_VR_STX(name, opc2, opc3)                                          \
10511GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10512#define GEN_VR_LVE(name, opc2, opc3)                                    \
10513    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10514#define GEN_VR_STVE(name, opc2, opc3)                                   \
10515    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10516GEN_VR_LDX(lvx, 0x07, 0x03),
10517GEN_VR_LDX(lvxl, 0x07, 0x0B),
10518GEN_VR_LVE(bx, 0x07, 0x00),
10519GEN_VR_LVE(hx, 0x07, 0x01),
10520GEN_VR_LVE(wx, 0x07, 0x02),
10521GEN_VR_STX(svx, 0x07, 0x07),
10522GEN_VR_STX(svxl, 0x07, 0x0F),
10523GEN_VR_STVE(bx, 0x07, 0x04),
10524GEN_VR_STVE(hx, 0x07, 0x05),
10525GEN_VR_STVE(wx, 0x07, 0x06),
10526
10527#undef GEN_VX_LOGICAL
10528#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
10529GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10530
10531#undef GEN_VX_LOGICAL_207
10532#define GEN_VX_LOGICAL_207(name, tcg_op, opc2, opc3) \
10533GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10534
10535GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
10536GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
10537GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
10538GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
10539GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
10540GEN_VX_LOGICAL_207(veqv, tcg_gen_eqv_i64, 2, 26),
10541GEN_VX_LOGICAL_207(vnand, tcg_gen_nand_i64, 2, 22),
10542GEN_VX_LOGICAL_207(vorc, tcg_gen_orc_i64, 2, 21),
10543
10544#undef GEN_VXFORM
10545#define GEN_VXFORM(name, opc2, opc3)                                    \
10546GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10547
10548#undef GEN_VXFORM_207
10549#define GEN_VXFORM_207(name, opc2, opc3) \
10550GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10551
10552#undef GEN_VXFORM_DUAL
10553#define GEN_VXFORM_DUAL(name0, name1, opc2, opc3, type0, type1) \
10554GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, type0, type1)
10555
10556#undef GEN_VXRFORM_DUAL
10557#define GEN_VXRFORM_DUAL(name0, name1, opc2, opc3, tp0, tp1) \
10558GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, tp0, tp1), \
10559GEN_HANDLER_E(name0##_##name1, 0x4, opc2, (opc3 | 0x10), 0x00000000, tp0, tp1),
10560
10561GEN_VXFORM(vaddubm, 0, 0),
10562GEN_VXFORM(vadduhm, 0, 1),
10563GEN_VXFORM(vadduwm, 0, 2),
10564GEN_VXFORM_207(vaddudm, 0, 3),
10565GEN_VXFORM_DUAL(vsububm, bcdadd, 0, 16, PPC_ALTIVEC, PPC_NONE),
10566GEN_VXFORM_DUAL(vsubuhm, bcdsub, 0, 17, PPC_ALTIVEC, PPC_NONE),
10567GEN_VXFORM(vsubuwm, 0, 18),
10568GEN_VXFORM_207(vsubudm, 0, 19),
10569GEN_VXFORM(vmaxub, 1, 0),
10570GEN_VXFORM(vmaxuh, 1, 1),
10571GEN_VXFORM(vmaxuw, 1, 2),
10572GEN_VXFORM_207(vmaxud, 1, 3),
10573GEN_VXFORM(vmaxsb, 1, 4),
10574GEN_VXFORM(vmaxsh, 1, 5),
10575GEN_VXFORM(vmaxsw, 1, 6),
10576GEN_VXFORM_207(vmaxsd, 1, 7),
10577GEN_VXFORM(vminub, 1, 8),
10578GEN_VXFORM(vminuh, 1, 9),
10579GEN_VXFORM(vminuw, 1, 10),
10580GEN_VXFORM_207(vminud, 1, 11),
10581GEN_VXFORM(vminsb, 1, 12),
10582GEN_VXFORM(vminsh, 1, 13),
10583GEN_VXFORM(vminsw, 1, 14),
10584GEN_VXFORM_207(vminsd, 1, 15),
10585GEN_VXFORM(vavgub, 1, 16),
10586GEN_VXFORM(vavguh, 1, 17),
10587GEN_VXFORM(vavguw, 1, 18),
10588GEN_VXFORM(vavgsb, 1, 20),
10589GEN_VXFORM(vavgsh, 1, 21),
10590GEN_VXFORM(vavgsw, 1, 22),
10591GEN_VXFORM(vmrghb, 6, 0),
10592GEN_VXFORM(vmrghh, 6, 1),
10593GEN_VXFORM(vmrghw, 6, 2),
10594GEN_VXFORM(vmrglb, 6, 4),
10595GEN_VXFORM(vmrglh, 6, 5),
10596GEN_VXFORM(vmrglw, 6, 6),
10597GEN_VXFORM_207(vmrgew, 6, 30),
10598GEN_VXFORM_207(vmrgow, 6, 26),
10599GEN_VXFORM(vmuloub, 4, 0),
10600GEN_VXFORM(vmulouh, 4, 1),
10601GEN_VXFORM_DUAL(vmulouw, vmuluwm, 4, 2, PPC_ALTIVEC, PPC_NONE),
10602GEN_VXFORM(vmulosb, 4, 4),
10603GEN_VXFORM(vmulosh, 4, 5),
10604GEN_VXFORM_207(vmulosw, 4, 6),
10605GEN_VXFORM(vmuleub, 4, 8),
10606GEN_VXFORM(vmuleuh, 4, 9),
10607GEN_VXFORM_207(vmuleuw, 4, 10),
10608GEN_VXFORM(vmulesb, 4, 12),
10609GEN_VXFORM(vmulesh, 4, 13),
10610GEN_VXFORM_207(vmulesw, 4, 14),
10611GEN_VXFORM(vslb, 2, 4),
10612GEN_VXFORM(vslh, 2, 5),
10613GEN_VXFORM(vslw, 2, 6),
10614GEN_VXFORM_207(vsld, 2, 23),
10615GEN_VXFORM(vsrb, 2, 8),
10616GEN_VXFORM(vsrh, 2, 9),
10617GEN_VXFORM(vsrw, 2, 10),
10618GEN_VXFORM_207(vsrd, 2, 27),
10619GEN_VXFORM(vsrab, 2, 12),
10620GEN_VXFORM(vsrah, 2, 13),
10621GEN_VXFORM(vsraw, 2, 14),
10622GEN_VXFORM_207(vsrad, 2, 15),
10623GEN_VXFORM(vslo, 6, 16),
10624GEN_VXFORM(vsro, 6, 17),
10625GEN_VXFORM(vaddcuw, 0, 6),
10626GEN_VXFORM(vsubcuw, 0, 22),
10627GEN_VXFORM(vaddubs, 0, 8),
10628GEN_VXFORM(vadduhs, 0, 9),
10629GEN_VXFORM(vadduws, 0, 10),
10630GEN_VXFORM(vaddsbs, 0, 12),
10631GEN_VXFORM(vaddshs, 0, 13),
10632GEN_VXFORM(vaddsws, 0, 14),
10633GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
10634GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
10635GEN_VXFORM(vsubuws, 0, 26),
10636GEN_VXFORM(vsubsbs, 0, 28),
10637GEN_VXFORM(vsubshs, 0, 29),
10638GEN_VXFORM(vsubsws, 0, 30),
10639GEN_VXFORM_207(vadduqm, 0, 4),
10640GEN_VXFORM_207(vaddcuq, 0, 5),
10641GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
10642GEN_VXFORM_207(vsubuqm, 0, 20),
10643GEN_VXFORM_207(vsubcuq, 0, 21),
10644GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
10645GEN_VXFORM(vrlb, 2, 0),
10646GEN_VXFORM(vrlh, 2, 1),
10647GEN_VXFORM(vrlw, 2, 2),
10648GEN_VXFORM_207(vrld, 2, 3),
10649GEN_VXFORM(vsl, 2, 7),
10650GEN_VXFORM(vsr, 2, 11),
10651GEN_VXFORM(vpkuhum, 7, 0),
10652GEN_VXFORM(vpkuwum, 7, 1),
10653GEN_VXFORM_207(vpkudum, 7, 17),
10654GEN_VXFORM(vpkuhus, 7, 2),
10655GEN_VXFORM(vpkuwus, 7, 3),
10656GEN_VXFORM_207(vpkudus, 7, 19),
10657GEN_VXFORM(vpkshus, 7, 4),
10658GEN_VXFORM(vpkswus, 7, 5),
10659GEN_VXFORM_207(vpksdus, 7, 21),
10660GEN_VXFORM(vpkshss, 7, 6),
10661GEN_VXFORM(vpkswss, 7, 7),
10662GEN_VXFORM_207(vpksdss, 7, 23),
10663GEN_VXFORM(vpkpx, 7, 12),
10664GEN_VXFORM(vsum4ubs, 4, 24),
10665GEN_VXFORM(vsum4sbs, 4, 28),
10666GEN_VXFORM(vsum4shs, 4, 25),
10667GEN_VXFORM(vsum2sws, 4, 26),
10668GEN_VXFORM(vsumsws, 4, 30),
10669GEN_VXFORM(vaddfp, 5, 0),
10670GEN_VXFORM(vsubfp, 5, 1),
10671GEN_VXFORM(vmaxfp, 5, 16),
10672GEN_VXFORM(vminfp, 5, 17),
10673
10674#undef GEN_VXRFORM1
10675#undef GEN_VXRFORM
10676#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
10677    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
10678#define GEN_VXRFORM(name, opc2, opc3)                                \
10679    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
10680    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
10681GEN_VXRFORM(vcmpequb, 3, 0)
10682GEN_VXRFORM(vcmpequh, 3, 1)
10683GEN_VXRFORM(vcmpequw, 3, 2)
10684GEN_VXRFORM(vcmpgtsb, 3, 12)
10685GEN_VXRFORM(vcmpgtsh, 3, 13)
10686GEN_VXRFORM(vcmpgtsw, 3, 14)
10687GEN_VXRFORM(vcmpgtub, 3, 8)
10688GEN_VXRFORM(vcmpgtuh, 3, 9)
10689GEN_VXRFORM(vcmpgtuw, 3, 10)
10690GEN_VXRFORM_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
10691GEN_VXRFORM(vcmpgefp, 3, 7)
10692GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
10693GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
10694
10695#undef GEN_VXFORM_SIMM
10696#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
10697    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10698GEN_VXFORM_SIMM(vspltisb, 6, 12),
10699GEN_VXFORM_SIMM(vspltish, 6, 13),
10700GEN_VXFORM_SIMM(vspltisw, 6, 14),
10701
10702#undef GEN_VXFORM_NOA
10703#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
10704    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
10705GEN_VXFORM_NOA(vupkhsb, 7, 8),
10706GEN_VXFORM_NOA(vupkhsh, 7, 9),
10707GEN_VXFORM_207(vupkhsw, 7, 25),
10708GEN_VXFORM_NOA(vupklsb, 7, 10),
10709GEN_VXFORM_NOA(vupklsh, 7, 11),
10710GEN_VXFORM_207(vupklsw, 7, 27),
10711GEN_VXFORM_NOA(vupkhpx, 7, 13),
10712GEN_VXFORM_NOA(vupklpx, 7, 15),
10713GEN_VXFORM_NOA(vrefp, 5, 4),
10714GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
10715GEN_VXFORM_NOA(vexptefp, 5, 6),
10716GEN_VXFORM_NOA(vlogefp, 5, 7),
10717GEN_VXFORM_NOA(vrfim, 5, 11),
10718GEN_VXFORM_NOA(vrfin, 5, 8),
10719GEN_VXFORM_NOA(vrfip, 5, 10),
10720GEN_VXFORM_NOA(vrfiz, 5, 9),
10721
10722#undef GEN_VXFORM_UIMM
10723#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
10724    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10725GEN_VXFORM_UIMM(vspltb, 6, 8),
10726GEN_VXFORM_UIMM(vsplth, 6, 9),
10727GEN_VXFORM_UIMM(vspltw, 6, 10),
10728GEN_VXFORM_UIMM(vcfux, 5, 12),
10729GEN_VXFORM_UIMM(vcfsx, 5, 13),
10730GEN_VXFORM_UIMM(vctuxs, 5, 14),
10731GEN_VXFORM_UIMM(vctsxs, 5, 15),
10732
10733#undef GEN_VAFORM_PAIRED
10734#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
10735    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
10736GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
10737GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
10738GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
10739GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
10740GEN_VAFORM_PAIRED(vsel, vperm, 21),
10741GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
10742
10743GEN_VXFORM_DUAL(vclzb, vpopcntb, 1, 28, PPC_NONE, PPC2_ALTIVEC_207),
10744GEN_VXFORM_DUAL(vclzh, vpopcnth, 1, 29, PPC_NONE, PPC2_ALTIVEC_207),
10745GEN_VXFORM_DUAL(vclzw, vpopcntw, 1, 30, PPC_NONE, PPC2_ALTIVEC_207),
10746GEN_VXFORM_DUAL(vclzd, vpopcntd, 1, 31, PPC_NONE, PPC2_ALTIVEC_207),
10747
10748GEN_VXFORM_207(vbpermq, 6, 21),
10749GEN_VXFORM_207(vgbbd, 6, 20),
10750GEN_VXFORM_207(vpmsumb, 4, 16),
10751GEN_VXFORM_207(vpmsumh, 4, 17),
10752GEN_VXFORM_207(vpmsumw, 4, 18),
10753GEN_VXFORM_207(vpmsumd, 4, 19),
10754
10755GEN_VXFORM_207(vsbox, 4, 23),
10756
10757GEN_VXFORM_DUAL(vcipher, vcipherlast, 4, 20, PPC_NONE, PPC2_ALTIVEC_207),
10758GEN_VXFORM_DUAL(vncipher, vncipherlast, 4, 21, PPC_NONE, PPC2_ALTIVEC_207),
10759
10760GEN_VXFORM_207(vshasigmaw, 1, 26),
10761GEN_VXFORM_207(vshasigmad, 1, 27),
10762
10763GEN_VXFORM_DUAL(vsldoi, vpermxor, 22, 0xFF, PPC_ALTIVEC, PPC_NONE),
10764
10765GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
10766GEN_HANDLER_E(lxsiwax, 0x1F, 0x0C, 0x02, 0, PPC_NONE, PPC2_VSX207),
10767GEN_HANDLER_E(lxsiwzx, 0x1F, 0x0C, 0x00, 0, PPC_NONE, PPC2_VSX207),
10768GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
10769GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
10770GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
10771GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
10772
10773GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
10774GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
10775GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
10776GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
10777GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
10778
10779GEN_HANDLER_E(mfvsrwz, 0x1F, 0x13, 0x03, 0x0000F800, PPC_NONE, PPC2_VSX207),
10780GEN_HANDLER_E(mtvsrwa, 0x1F, 0x13, 0x06, 0x0000F800, PPC_NONE, PPC2_VSX207),
10781GEN_HANDLER_E(mtvsrwz, 0x1F, 0x13, 0x07, 0x0000F800, PPC_NONE, PPC2_VSX207),
10782#if defined(TARGET_PPC64)
10783GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
10784GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
10785#endif
10786
10787#undef GEN_XX2FORM
10788#define GEN_XX2FORM(name, opc2, opc3, fl2)                           \
10789GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10790GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
10791
10792#undef GEN_XX3FORM
10793#define GEN_XX3FORM(name, opc2, opc3, fl2)                           \
10794GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10795GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
10796GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
10797GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
10798
10799#undef GEN_XX2IFORM
10800#define GEN_XX2IFORM(name, opc2, opc3, fl2)                           \
10801GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 1, PPC_NONE, fl2), \
10802GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 1, PPC_NONE, fl2), \
10803GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 1, PPC_NONE, fl2), \
10804GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 1, PPC_NONE, fl2)
10805
10806#undef GEN_XX3_RC_FORM
10807#define GEN_XX3_RC_FORM(name, opc2, opc3, fl2)                          \
10808GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x00, 0, PPC_NONE, fl2), \
10809GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x00, 0, PPC_NONE, fl2), \
10810GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x00, 0, PPC_NONE, fl2), \
10811GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x00, 0, PPC_NONE, fl2), \
10812GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x10, 0, PPC_NONE, fl2), \
10813GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x10, 0, PPC_NONE, fl2), \
10814GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x10, 0, PPC_NONE, fl2), \
10815GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x10, 0, PPC_NONE, fl2)
10816
10817#undef GEN_XX3FORM_DM
10818#define GEN_XX3FORM_DM(name, opc2, opc3) \
10819GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10820GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10821GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10822GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10823GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10824GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10825GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10826GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10827GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10828GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10829GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10830GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10831GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10832GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10833GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10834GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x0C, 0, PPC_NONE, PPC2_VSX)
10835
10836GEN_XX2FORM(xsabsdp, 0x12, 0x15, PPC2_VSX),
10837GEN_XX2FORM(xsnabsdp, 0x12, 0x16, PPC2_VSX),
10838GEN_XX2FORM(xsnegdp, 0x12, 0x17, PPC2_VSX),
10839GEN_XX3FORM(xscpsgndp, 0x00, 0x16, PPC2_VSX),
10840
10841GEN_XX2FORM(xvabsdp, 0x12, 0x1D, PPC2_VSX),
10842GEN_XX2FORM(xvnabsdp, 0x12, 0x1E, PPC2_VSX),
10843GEN_XX2FORM(xvnegdp, 0x12, 0x1F, PPC2_VSX),
10844GEN_XX3FORM(xvcpsgndp, 0x00, 0x1E, PPC2_VSX),
10845GEN_XX2FORM(xvabssp, 0x12, 0x19, PPC2_VSX),
10846GEN_XX2FORM(xvnabssp, 0x12, 0x1A, PPC2_VSX),
10847GEN_XX2FORM(xvnegsp, 0x12, 0x1B, PPC2_VSX),
10848GEN_XX3FORM(xvcpsgnsp, 0x00, 0x1A, PPC2_VSX),
10849
10850GEN_XX3FORM(xsadddp, 0x00, 0x04, PPC2_VSX),
10851GEN_XX3FORM(xssubdp, 0x00, 0x05, PPC2_VSX),
10852GEN_XX3FORM(xsmuldp, 0x00, 0x06, PPC2_VSX),
10853GEN_XX3FORM(xsdivdp, 0x00, 0x07, PPC2_VSX),
10854GEN_XX2FORM(xsredp,  0x14, 0x05, PPC2_VSX),
10855GEN_XX2FORM(xssqrtdp,  0x16, 0x04, PPC2_VSX),
10856GEN_XX2FORM(xsrsqrtedp,  0x14, 0x04, PPC2_VSX),
10857GEN_XX3FORM(xstdivdp,  0x14, 0x07, PPC2_VSX),
10858GEN_XX2FORM(xstsqrtdp,  0x14, 0x06, PPC2_VSX),
10859GEN_XX3FORM(xsmaddadp, 0x04, 0x04, PPC2_VSX),
10860GEN_XX3FORM(xsmaddmdp, 0x04, 0x05, PPC2_VSX),
10861GEN_XX3FORM(xsmsubadp, 0x04, 0x06, PPC2_VSX),
10862GEN_XX3FORM(xsmsubmdp, 0x04, 0x07, PPC2_VSX),
10863GEN_XX3FORM(xsnmaddadp, 0x04, 0x14, PPC2_VSX),
10864GEN_XX3FORM(xsnmaddmdp, 0x04, 0x15, PPC2_VSX),
10865GEN_XX3FORM(xsnmsubadp, 0x04, 0x16, PPC2_VSX),
10866GEN_XX3FORM(xsnmsubmdp, 0x04, 0x17, PPC2_VSX),
10867GEN_XX2IFORM(xscmpodp,  0x0C, 0x05, PPC2_VSX),
10868GEN_XX2IFORM(xscmpudp,  0x0C, 0x04, PPC2_VSX),
10869GEN_XX3FORM(xsmaxdp, 0x00, 0x14, PPC2_VSX),
10870GEN_XX3FORM(xsmindp, 0x00, 0x15, PPC2_VSX),
10871GEN_XX2FORM(xscvdpsp, 0x12, 0x10, PPC2_VSX),
10872GEN_XX2FORM(xscvdpspn, 0x16, 0x10, PPC2_VSX207),
10873GEN_XX2FORM(xscvspdp, 0x12, 0x14, PPC2_VSX),
10874GEN_XX2FORM(xscvspdpn, 0x16, 0x14, PPC2_VSX207),
10875GEN_XX2FORM(xscvdpsxds, 0x10, 0x15, PPC2_VSX),
10876GEN_XX2FORM(xscvdpsxws, 0x10, 0x05, PPC2_VSX),
10877GEN_XX2FORM(xscvdpuxds, 0x10, 0x14, PPC2_VSX),
10878GEN_XX2FORM(xscvdpuxws, 0x10, 0x04, PPC2_VSX),
10879GEN_XX2FORM(xscvsxddp, 0x10, 0x17, PPC2_VSX),
10880GEN_XX2FORM(xscvuxddp, 0x10, 0x16, PPC2_VSX),
10881GEN_XX2FORM(xsrdpi, 0x12, 0x04, PPC2_VSX),
10882GEN_XX2FORM(xsrdpic, 0x16, 0x06, PPC2_VSX),
10883GEN_XX2FORM(xsrdpim, 0x12, 0x07, PPC2_VSX),
10884GEN_XX2FORM(xsrdpip, 0x12, 0x06, PPC2_VSX),
10885GEN_XX2FORM(xsrdpiz, 0x12, 0x05, PPC2_VSX),
10886
10887GEN_XX3FORM(xsaddsp, 0x00, 0x00, PPC2_VSX207),
10888GEN_XX3FORM(xssubsp, 0x00, 0x01, PPC2_VSX207),
10889GEN_XX3FORM(xsmulsp, 0x00, 0x02, PPC2_VSX207),
10890GEN_XX3FORM(xsdivsp, 0x00, 0x03, PPC2_VSX207),
10891GEN_XX2FORM(xsresp,  0x14, 0x01, PPC2_VSX207),
10892GEN_XX2FORM(xsrsp, 0x12, 0x11, PPC2_VSX207),
10893GEN_XX2FORM(xssqrtsp,  0x16, 0x00, PPC2_VSX207),
10894GEN_XX2FORM(xsrsqrtesp,  0x14, 0x00, PPC2_VSX207),
10895GEN_XX3FORM(xsmaddasp, 0x04, 0x00, PPC2_VSX207),
10896GEN_XX3FORM(xsmaddmsp, 0x04, 0x01, PPC2_VSX207),
10897GEN_XX3FORM(xsmsubasp, 0x04, 0x02, PPC2_VSX207),
10898GEN_XX3FORM(xsmsubmsp, 0x04, 0x03, PPC2_VSX207),
10899GEN_XX3FORM(xsnmaddasp, 0x04, 0x10, PPC2_VSX207),
10900GEN_XX3FORM(xsnmaddmsp, 0x04, 0x11, PPC2_VSX207),
10901GEN_XX3FORM(xsnmsubasp, 0x04, 0x12, PPC2_VSX207),
10902GEN_XX3FORM(xsnmsubmsp, 0x04, 0x13, PPC2_VSX207),
10903GEN_XX2FORM(xscvsxdsp, 0x10, 0x13, PPC2_VSX207),
10904GEN_XX2FORM(xscvuxdsp, 0x10, 0x12, PPC2_VSX207),
10905
10906GEN_XX3FORM(xvadddp, 0x00, 0x0C, PPC2_VSX),
10907GEN_XX3FORM(xvsubdp, 0x00, 0x0D, PPC2_VSX),
10908GEN_XX3FORM(xvmuldp, 0x00, 0x0E, PPC2_VSX),
10909GEN_XX3FORM(xvdivdp, 0x00, 0x0F, PPC2_VSX),
10910GEN_XX2FORM(xvredp,  0x14, 0x0D, PPC2_VSX),
10911GEN_XX2FORM(xvsqrtdp,  0x16, 0x0C, PPC2_VSX),
10912GEN_XX2FORM(xvrsqrtedp,  0x14, 0x0C, PPC2_VSX),
10913GEN_XX3FORM(xvtdivdp, 0x14, 0x0F, PPC2_VSX),
10914GEN_XX2FORM(xvtsqrtdp, 0x14, 0x0E, PPC2_VSX),
10915GEN_XX3FORM(xvmaddadp, 0x04, 0x0C, PPC2_VSX),
10916GEN_XX3FORM(xvmaddmdp, 0x04, 0x0D, PPC2_VSX),
10917GEN_XX3FORM(xvmsubadp, 0x04, 0x0E, PPC2_VSX),
10918GEN_XX3FORM(xvmsubmdp, 0x04, 0x0F, PPC2_VSX),
10919GEN_XX3FORM(xvnmaddadp, 0x04, 0x1C, PPC2_VSX),
10920GEN_XX3FORM(xvnmaddmdp, 0x04, 0x1D, PPC2_VSX),
10921GEN_XX3FORM(xvnmsubadp, 0x04, 0x1E, PPC2_VSX),
10922GEN_XX3FORM(xvnmsubmdp, 0x04, 0x1F, PPC2_VSX),
10923GEN_XX3FORM(xvmaxdp, 0x00, 0x1C, PPC2_VSX),
10924GEN_XX3FORM(xvmindp, 0x00, 0x1D, PPC2_VSX),
10925GEN_XX3_RC_FORM(xvcmpeqdp, 0x0C, 0x0C, PPC2_VSX),
10926GEN_XX3_RC_FORM(xvcmpgtdp, 0x0C, 0x0D, PPC2_VSX),
10927GEN_XX3_RC_FORM(xvcmpgedp, 0x0C, 0x0E, PPC2_VSX),
10928GEN_XX2FORM(xvcvdpsp, 0x12, 0x18, PPC2_VSX),
10929GEN_XX2FORM(xvcvdpsxds, 0x10, 0x1D, PPC2_VSX),
10930GEN_XX2FORM(xvcvdpsxws, 0x10, 0x0D, PPC2_VSX),
10931GEN_XX2FORM(xvcvdpuxds, 0x10, 0x1C, PPC2_VSX),
10932GEN_XX2FORM(xvcvdpuxws, 0x10, 0x0C, PPC2_VSX),
10933GEN_XX2FORM(xvcvsxddp, 0x10, 0x1F, PPC2_VSX),
10934GEN_XX2FORM(xvcvuxddp, 0x10, 0x1E, PPC2_VSX),
10935GEN_XX2FORM(xvcvsxwdp, 0x10, 0x0F, PPC2_VSX),
10936GEN_XX2FORM(xvcvuxwdp, 0x10, 0x0E, PPC2_VSX),
10937GEN_XX2FORM(xvrdpi, 0x12, 0x0C, PPC2_VSX),
10938GEN_XX2FORM(xvrdpic, 0x16, 0x0E, PPC2_VSX),
10939GEN_XX2FORM(xvrdpim, 0x12, 0x0F, PPC2_VSX),
10940GEN_XX2FORM(xvrdpip, 0x12, 0x0E, PPC2_VSX),
10941GEN_XX2FORM(xvrdpiz, 0x12, 0x0D, PPC2_VSX),
10942
10943GEN_XX3FORM(xvaddsp, 0x00, 0x08, PPC2_VSX),
10944GEN_XX3FORM(xvsubsp, 0x00, 0x09, PPC2_VSX),
10945GEN_XX3FORM(xvmulsp, 0x00, 0x0A, PPC2_VSX),
10946GEN_XX3FORM(xvdivsp, 0x00, 0x0B, PPC2_VSX),
10947GEN_XX2FORM(xvresp, 0x14, 0x09, PPC2_VSX),
10948GEN_XX2FORM(xvsqrtsp, 0x16, 0x08, PPC2_VSX),
10949GEN_XX2FORM(xvrsqrtesp, 0x14, 0x08, PPC2_VSX),
10950GEN_XX3FORM(xvtdivsp, 0x14, 0x0B, PPC2_VSX),
10951GEN_XX2FORM(xvtsqrtsp, 0x14, 0x0A, PPC2_VSX),
10952GEN_XX3FORM(xvmaddasp, 0x04, 0x08, PPC2_VSX),
10953GEN_XX3FORM(xvmaddmsp, 0x04, 0x09, PPC2_VSX),
10954GEN_XX3FORM(xvmsubasp, 0x04, 0x0A, PPC2_VSX),
10955GEN_XX3FORM(xvmsubmsp, 0x04, 0x0B, PPC2_VSX),
10956GEN_XX3FORM(xvnmaddasp, 0x04, 0x18, PPC2_VSX),
10957GEN_XX3FORM(xvnmaddmsp, 0x04, 0x19, PPC2_VSX),
10958GEN_XX3FORM(xvnmsubasp, 0x04, 0x1A, PPC2_VSX),
10959GEN_XX3FORM(xvnmsubmsp, 0x04, 0x1B, PPC2_VSX),
10960GEN_XX3FORM(xvmaxsp, 0x00, 0x18, PPC2_VSX),
10961GEN_XX3FORM(xvminsp, 0x00, 0x19, PPC2_VSX),
10962GEN_XX3_RC_FORM(xvcmpeqsp, 0x0C, 0x08, PPC2_VSX),
10963GEN_XX3_RC_FORM(xvcmpgtsp, 0x0C, 0x09, PPC2_VSX),
10964GEN_XX3_RC_FORM(xvcmpgesp, 0x0C, 0x0A, PPC2_VSX),
10965GEN_XX2FORM(xvcvspdp, 0x12, 0x1C, PPC2_VSX),
10966GEN_XX2FORM(xvcvspsxds, 0x10, 0x19, PPC2_VSX),
10967GEN_XX2FORM(xvcvspsxws, 0x10, 0x09, PPC2_VSX),
10968GEN_XX2FORM(xvcvspuxds, 0x10, 0x18, PPC2_VSX),
10969GEN_XX2FORM(xvcvspuxws, 0x10, 0x08, PPC2_VSX),
10970GEN_XX2FORM(xvcvsxdsp, 0x10, 0x1B, PPC2_VSX),
10971GEN_XX2FORM(xvcvuxdsp, 0x10, 0x1A, PPC2_VSX),
10972GEN_XX2FORM(xvcvsxwsp, 0x10, 0x0B, PPC2_VSX),
10973GEN_XX2FORM(xvcvuxwsp, 0x10, 0x0A, PPC2_VSX),
10974GEN_XX2FORM(xvrspi, 0x12, 0x08, PPC2_VSX),
10975GEN_XX2FORM(xvrspic, 0x16, 0x0A, PPC2_VSX),
10976GEN_XX2FORM(xvrspim, 0x12, 0x0B, PPC2_VSX),
10977GEN_XX2FORM(xvrspip, 0x12, 0x0A, PPC2_VSX),
10978GEN_XX2FORM(xvrspiz, 0x12, 0x09, PPC2_VSX),
10979
10980#undef VSX_LOGICAL
10981#define VSX_LOGICAL(name, opc2, opc3, fl2) \
10982GEN_XX3FORM(name, opc2, opc3, fl2)
10983
10984VSX_LOGICAL(xxland, 0x8, 0x10, PPC2_VSX),
10985VSX_LOGICAL(xxlandc, 0x8, 0x11, PPC2_VSX),
10986VSX_LOGICAL(xxlor, 0x8, 0x12, PPC2_VSX),
10987VSX_LOGICAL(xxlxor, 0x8, 0x13, PPC2_VSX),
10988VSX_LOGICAL(xxlnor, 0x8, 0x14, PPC2_VSX),
10989VSX_LOGICAL(xxleqv, 0x8, 0x17, PPC2_VSX207),
10990VSX_LOGICAL(xxlnand, 0x8, 0x16, PPC2_VSX207),
10991VSX_LOGICAL(xxlorc, 0x8, 0x15, PPC2_VSX207),
10992GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
10993GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
10994GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
10995GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
10996
10997#define GEN_XXSEL_ROW(opc3) \
10998GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x18, opc3, 0, PPC_NONE, PPC2_VSX), \
10999GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x19, opc3, 0, PPC_NONE, PPC2_VSX), \
11000GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1A, opc3, 0, PPC_NONE, PPC2_VSX), \
11001GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1B, opc3, 0, PPC_NONE, PPC2_VSX), \
11002GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1C, opc3, 0, PPC_NONE, PPC2_VSX), \
11003GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1D, opc3, 0, PPC_NONE, PPC2_VSX), \
11004GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1E, opc3, 0, PPC_NONE, PPC2_VSX), \
11005GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1F, opc3, 0, PPC_NONE, PPC2_VSX), \
11006
11007GEN_XXSEL_ROW(0x00)
11008GEN_XXSEL_ROW(0x01)
11009GEN_XXSEL_ROW(0x02)
11010GEN_XXSEL_ROW(0x03)
11011GEN_XXSEL_ROW(0x04)
11012GEN_XXSEL_ROW(0x05)
11013GEN_XXSEL_ROW(0x06)
11014GEN_XXSEL_ROW(0x07)
11015GEN_XXSEL_ROW(0x08)
11016GEN_XXSEL_ROW(0x09)
11017GEN_XXSEL_ROW(0x0A)
11018GEN_XXSEL_ROW(0x0B)
11019GEN_XXSEL_ROW(0x0C)
11020GEN_XXSEL_ROW(0x0D)
11021GEN_XXSEL_ROW(0x0E)
11022GEN_XXSEL_ROW(0x0F)
11023GEN_XXSEL_ROW(0x10)
11024GEN_XXSEL_ROW(0x11)
11025GEN_XXSEL_ROW(0x12)
11026GEN_XXSEL_ROW(0x13)
11027GEN_XXSEL_ROW(0x14)
11028GEN_XXSEL_ROW(0x15)
11029GEN_XXSEL_ROW(0x16)
11030GEN_XXSEL_ROW(0x17)
11031GEN_XXSEL_ROW(0x18)
11032GEN_XXSEL_ROW(0x19)
11033GEN_XXSEL_ROW(0x1A)
11034GEN_XXSEL_ROW(0x1B)
11035GEN_XXSEL_ROW(0x1C)
11036GEN_XXSEL_ROW(0x1D)
11037GEN_XXSEL_ROW(0x1E)
11038GEN_XXSEL_ROW(0x1F)
11039
11040GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
11041
11042#undef GEN_DFP_T_A_B_Rc
11043#undef GEN_DFP_BF_A_B
11044#undef GEN_DFP_BF_A_DCM
11045#undef GEN_DFP_T_B_U32_U32_Rc
11046#undef GEN_DFP_T_A_B_I32_Rc
11047#undef GEN_DFP_T_B_Rc
11048#undef GEN_DFP_T_FPR_I32_Rc
11049
11050#define _GEN_DFP_LONG(name, op1, op2, mask) \
11051GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP)
11052
11053#define _GEN_DFP_LONGx2(name, op1, op2, mask) \
11054GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
11055GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
11056
11057#define _GEN_DFP_LONGx4(name, op1, op2, mask) \
11058GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
11059GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
11060GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
11061GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
11062
11063#define _GEN_DFP_QUAD(name, op1, op2, mask) \
11064GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP)
11065
11066#define _GEN_DFP_QUADx2(name, op1, op2, mask) \
11067GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
11068GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
11069
11070#define _GEN_DFP_QUADx4(name, op1, op2, mask)                         \
11071GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
11072GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
11073GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
11074GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
11075
11076#define GEN_DFP_T_A_B_Rc(name, op1, op2) \
11077_GEN_DFP_LONG(name, op1, op2, 0x00000000)
11078
11079#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \
11080_GEN_DFP_QUAD(name, op1, op2, 0x00210800)
11081
11082#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \
11083_GEN_DFP_QUAD(name, op1, op2, 0x00200800)
11084
11085#define GEN_DFP_T_B_Rc(name, op1, op2) \
11086_GEN_DFP_LONG(name, op1, op2, 0x001F0000)
11087
11088#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \
11089_GEN_DFP_QUAD(name, op1, op2, 0x003F0800)
11090
11091#define GEN_DFP_Tp_B_Rc(name, op1, op2) \
11092_GEN_DFP_QUAD(name, op1, op2, 0x003F0000)
11093
11094#define GEN_DFP_T_Bp_Rc(name, op1, op2) \
11095_GEN_DFP_QUAD(name, op1, op2, 0x001F0800)
11096
11097#define GEN_DFP_BF_A_B(name, op1, op2) \
11098_GEN_DFP_LONG(name, op1, op2, 0x00000001)
11099
11100#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \
11101_GEN_DFP_QUAD(name, op1, op2, 0x00610801)
11102
11103#define GEN_DFP_BF_A_Bp(name, op1, op2) \
11104_GEN_DFP_QUAD(name, op1, op2, 0x00600801)
11105
11106#define GEN_DFP_BF_A_DCM(name, op1, op2) \
11107_GEN_DFP_LONGx2(name, op1, op2, 0x00600001)
11108
11109#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \
11110_GEN_DFP_QUADx2(name, op1, op2, 0x00610001)
11111
11112#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \
11113_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11114
11115#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \
11116_GEN_DFP_QUADx4(name, op1, op2, 0x02010800)
11117
11118#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \
11119_GEN_DFP_QUADx4(name, op1, op2, 0x02000800)
11120
11121#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \
11122_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11123
11124#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \
11125_GEN_DFP_QUADx4(name, op1, op2, 0x00200800)
11126
11127#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \
11128_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000)
11129
11130#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \
11131_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800)
11132
11133#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \
11134_GEN_DFP_LONG(name, op1, op2, 0x00070000)
11135
11136#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \
11137_GEN_DFP_QUAD(name, op1, op2, 0x00270800)
11138
11139#define GEN_DFP_S_T_B_Rc(name, op1, op2) \
11140_GEN_DFP_LONG(name, op1, op2, 0x000F0000)
11141
11142#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \
11143_GEN_DFP_QUAD(name, op1, op2, 0x002F0800)
11144
11145#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \
11146_GEN_DFP_LONGx2(name, op1, op2, 0x00000000)
11147
11148#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \
11149_GEN_DFP_QUADx2(name, op1, op2, 0x00210000)
11150
11151GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00),
11152GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00),
11153GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10),
11154GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10),
11155GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01),
11156GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01),
11157GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11),
11158GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11),
11159GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14),
11160GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14),
11161GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04),
11162GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04),
11163GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06),
11164GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06),
11165GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07),
11166GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07),
11167GEN_DFP_BF_A_B(dtstex, 0x02, 0x05),
11168GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05),
11169GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15),
11170GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15),
11171GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02),
11172GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02),
11173GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00),
11174GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00),
11175GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01),
11176GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01),
11177GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03),
11178GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03),
11179GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07),
11180GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07),
11181GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08),
11182GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08),
11183GEN_DFP_T_B_Rc(drsp, 0x02, 0x18),
11184GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18),
11185GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19),
11186GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19),
11187GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
11188GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
11189GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
11190GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
11191GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
11192GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
11193GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
11194GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
11195GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
11196GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
11197GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
11198GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
11199GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
11200GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
11201
11202#undef GEN_SPE
11203#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
11204    GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
11205GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11206GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11207GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11208GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11209GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11210GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11211GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11212GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
11213GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
11214GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11215GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11216GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11217GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11218GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11219GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11220GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
11221GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11222GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11223GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11224GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11225GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11226GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11227GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11228GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11229GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11230GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11231GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11232GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11233GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
11234
11235GEN_SPE(evfsadd,     evfssub,     0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11236GEN_SPE(evfsabs,     evfsnabs,    0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11237GEN_SPE(evfsneg,     speundef,    0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11238GEN_SPE(evfsmul,     evfsdiv,     0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11239GEN_SPE(evfscmpgt,   evfscmplt,   0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11240GEN_SPE(evfscmpeq,   speundef,    0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11241GEN_SPE(evfscfui,    evfscfsi,    0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11242GEN_SPE(evfscfuf,    evfscfsf,    0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11243GEN_SPE(evfsctui,    evfsctsi,    0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11244GEN_SPE(evfsctuf,    evfsctsf,    0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11245GEN_SPE(evfsctuiz,   speundef,    0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11246GEN_SPE(evfsctsiz,   speundef,    0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11247GEN_SPE(evfststgt,   evfststlt,   0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11248GEN_SPE(evfststeq,   speundef,    0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11249
11250GEN_SPE(efsadd,      efssub,      0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11251GEN_SPE(efsabs,      efsnabs,     0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11252GEN_SPE(efsneg,      speundef,    0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11253GEN_SPE(efsmul,      efsdiv,      0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11254GEN_SPE(efscmpgt,    efscmplt,    0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11255GEN_SPE(efscmpeq,    efscfd,      0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
11256GEN_SPE(efscfui,     efscfsi,     0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11257GEN_SPE(efscfuf,     efscfsf,     0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11258GEN_SPE(efsctui,     efsctsi,     0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11259GEN_SPE(efsctuf,     efsctsf,     0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11260GEN_SPE(efsctuiz,    speundef,    0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11261GEN_SPE(efsctsiz,    speundef,    0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11262GEN_SPE(efststgt,    efststlt,    0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11263GEN_SPE(efststeq,    speundef,    0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11264
11265GEN_SPE(efdadd,      efdsub,      0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11266GEN_SPE(efdcfuid,    efdcfsid,    0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11267GEN_SPE(efdabs,      efdnabs,     0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
11268GEN_SPE(efdneg,      speundef,    0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11269GEN_SPE(efdmul,      efddiv,      0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11270GEN_SPE(efdctuidz,   efdctsidz,   0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11271GEN_SPE(efdcmpgt,    efdcmplt,    0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11272GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
11273GEN_SPE(efdcfui,     efdcfsi,     0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11274GEN_SPE(efdcfuf,     efdcfsf,     0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11275GEN_SPE(efdctui,     efdctsi,     0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11276GEN_SPE(efdctuf,     efdctsf,     0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11277GEN_SPE(efdctuiz,    speundef,    0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11278GEN_SPE(efdctsiz,    speundef,    0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11279GEN_SPE(efdtstgt,    efdtstlt,    0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11280GEN_SPE(efdtsteq,    speundef,    0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11281
11282#undef GEN_SPEOP_LDST
11283#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
11284GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
11285GEN_SPEOP_LDST(evldd, 0x00, 3),
11286GEN_SPEOP_LDST(evldw, 0x01, 3),
11287GEN_SPEOP_LDST(evldh, 0x02, 3),
11288GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
11289GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
11290GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
11291GEN_SPEOP_LDST(evlwhe, 0x08, 2),
11292GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
11293GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
11294GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
11295GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
11296
11297GEN_SPEOP_LDST(evstdd, 0x10, 3),
11298GEN_SPEOP_LDST(evstdw, 0x11, 3),
11299GEN_SPEOP_LDST(evstdh, 0x12, 3),
11300GEN_SPEOP_LDST(evstwhe, 0x18, 2),
11301GEN_SPEOP_LDST(evstwho, 0x1A, 2),
11302GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
11303GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
11304
11305GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
11306               PPC_NONE, PPC2_TM),
11307GEN_HANDLER2_E(tend,   "tend",   0x1F, 0x0E, 0x15, 0x01FFF800, \
11308               PPC_NONE, PPC2_TM),
11309GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
11310               PPC_NONE, PPC2_TM),
11311GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
11312               PPC_NONE, PPC2_TM),
11313GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
11314               PPC_NONE, PPC2_TM),
11315GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
11316               PPC_NONE, PPC2_TM),
11317GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
11318               PPC_NONE, PPC2_TM),
11319GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
11320               PPC_NONE, PPC2_TM),
11321GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
11322               PPC_NONE, PPC2_TM),
11323GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
11324               PPC_NONE, PPC2_TM),
11325GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
11326               PPC_NONE, PPC2_TM),
11327};
11328
11329#include "helper_regs.h"
11330#include "translate_init.c"
11331
11332/*****************************************************************************/
11333/* Misc PowerPC helpers */
11334void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11335                        int flags)
11336{
11337#define RGPL  4
11338#define RFPL  4
11339
11340    PowerPCCPU *cpu = POWERPC_CPU(cs);
11341    CPUPPCState *env = &cpu->env;
11342    int i;
11343
11344    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
11345                TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n",
11346                env->nip, env->lr, env->ctr, cpu_read_xer(env),
11347                cs->cpu_index);
11348    cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx "  HF "
11349                TARGET_FMT_lx " iidx %d didx %d\n",
11350                env->msr, env->spr[SPR_HID0],
11351                env->hflags, env->immu_idx, env->dmmu_idx);
11352#if !defined(NO_TIMER_DUMP)
11353    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
11354#if !defined(CONFIG_USER_ONLY)
11355                " DECR %08" PRIu32
11356#endif
11357                "\n",
11358                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
11359#if !defined(CONFIG_USER_ONLY)
11360                , cpu_ppc_load_decr(env)
11361#endif
11362                );
11363#endif
11364    for (i = 0; i < 32; i++) {
11365        if ((i & (RGPL - 1)) == 0)
11366            cpu_fprintf(f, "GPR%02d", i);
11367        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
11368        if ((i & (RGPL - 1)) == (RGPL - 1))
11369            cpu_fprintf(f, "\n");
11370    }
11371    cpu_fprintf(f, "CR ");
11372    for (i = 0; i < 8; i++)
11373        cpu_fprintf(f, "%01x", env->crf[i]);
11374    cpu_fprintf(f, "  [");
11375    for (i = 0; i < 8; i++) {
11376        char a = '-';
11377        if (env->crf[i] & 0x08)
11378            a = 'L';
11379        else if (env->crf[i] & 0x04)
11380            a = 'G';
11381        else if (env->crf[i] & 0x02)
11382            a = 'E';
11383        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
11384    }
11385    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
11386                env->reserve_addr);
11387    for (i = 0; i < 32; i++) {
11388        if ((i & (RFPL - 1)) == 0)
11389            cpu_fprintf(f, "FPR%02d", i);
11390        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
11391        if ((i & (RFPL - 1)) == (RFPL - 1))
11392            cpu_fprintf(f, "\n");
11393    }
11394    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
11395#if !defined(CONFIG_USER_ONLY)
11396    cpu_fprintf(f, " SRR0 " TARGET_FMT_lx "  SRR1 " TARGET_FMT_lx
11397                   "    PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
11398                env->spr[SPR_SRR0], env->spr[SPR_SRR1],
11399                env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
11400
11401    cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
11402                   "  SPRG2 " TARGET_FMT_lx "  SPRG3 " TARGET_FMT_lx "\n",
11403                env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
11404                env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
11405
11406    cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
11407                   "  SPRG6 " TARGET_FMT_lx "  SPRG7 " TARGET_FMT_lx "\n",
11408                env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
11409                env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
11410
11411#if defined(TARGET_PPC64)
11412    if (env->excp_model == POWERPC_EXCP_POWER7 ||
11413        env->excp_model == POWERPC_EXCP_POWER8) {
11414        cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
11415                    env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
11416    }
11417#endif
11418    if (env->excp_model == POWERPC_EXCP_BOOKE) {
11419        cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
11420                       " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
11421                    env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
11422                    env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
11423
11424        cpu_fprintf(f, "  TCR " TARGET_FMT_lx "   TSR " TARGET_FMT_lx
11425                       "    ESR " TARGET_FMT_lx "   DEAR " TARGET_FMT_lx "\n",
11426                    env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
11427                    env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
11428
11429        cpu_fprintf(f, "  PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
11430                       "   IVPR " TARGET_FMT_lx "   EPCR " TARGET_FMT_lx "\n",
11431                    env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
11432                    env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
11433
11434        cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
11435                       "    EPR " TARGET_FMT_lx "\n",
11436                    env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
11437                    env->spr[SPR_BOOKE_EPR]);
11438
11439        /* FSL-specific */
11440        cpu_fprintf(f, " MCAR " TARGET_FMT_lx "  PID1 " TARGET_FMT_lx
11441                       "   PID2 " TARGET_FMT_lx "    SVR " TARGET_FMT_lx "\n",
11442                    env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
11443                    env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
11444
11445        /*
11446         * IVORs are left out as they are large and do not change often --
11447         * they can be read with "p $ivor0", "p $ivor1", etc.
11448         */
11449    }
11450
11451#if defined(TARGET_PPC64)
11452    if (env->flags & POWERPC_FLAG_CFAR) {
11453        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
11454    }
11455#endif
11456
11457    switch (env->mmu_model) {
11458    case POWERPC_MMU_32B:
11459    case POWERPC_MMU_601:
11460    case POWERPC_MMU_SOFT_6xx:
11461    case POWERPC_MMU_SOFT_74xx:
11462#if defined(TARGET_PPC64)
11463    case POWERPC_MMU_64B:
11464    case POWERPC_MMU_2_03:
11465    case POWERPC_MMU_2_06:
11466    case POWERPC_MMU_2_06a:
11467    case POWERPC_MMU_2_07:
11468    case POWERPC_MMU_2_07a:
11469#endif
11470        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "   DAR " TARGET_FMT_lx
11471                       "  DSISR " TARGET_FMT_lx "\n", env->spr[SPR_SDR1],
11472                    env->spr[SPR_DAR], env->spr[SPR_DSISR]);
11473        break;
11474    case POWERPC_MMU_BOOKE206:
11475        cpu_fprintf(f, " MAS0 " TARGET_FMT_lx "  MAS1 " TARGET_FMT_lx
11476                       "   MAS2 " TARGET_FMT_lx "   MAS3 " TARGET_FMT_lx "\n",
11477                    env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
11478                    env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
11479
11480        cpu_fprintf(f, " MAS4 " TARGET_FMT_lx "  MAS6 " TARGET_FMT_lx
11481                       "   MAS7 " TARGET_FMT_lx "    PID " TARGET_FMT_lx "\n",
11482                    env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
11483                    env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
11484
11485        cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
11486                       " TLB1CFG " TARGET_FMT_lx "\n",
11487                    env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
11488                    env->spr[SPR_BOOKE_TLB1CFG]);
11489        break;
11490    default:
11491        break;
11492    }
11493#endif
11494
11495#undef RGPL
11496#undef RFPL
11497}
11498
11499void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
11500                             fprintf_function cpu_fprintf, int flags)
11501{
11502#if defined(DO_PPC_STATISTICS)
11503    PowerPCCPU *cpu = POWERPC_CPU(cs);
11504    opc_handler_t **t1, **t2, **t3, *handler;
11505    int op1, op2, op3;
11506
11507    t1 = cpu->env.opcodes;
11508    for (op1 = 0; op1 < 64; op1++) {
11509        handler = t1[op1];
11510        if (is_indirect_opcode(handler)) {
11511            t2 = ind_table(handler);
11512            for (op2 = 0; op2 < 32; op2++) {
11513                handler = t2[op2];
11514                if (is_indirect_opcode(handler)) {
11515                    t3 = ind_table(handler);
11516                    for (op3 = 0; op3 < 32; op3++) {
11517                        handler = t3[op3];
11518                        if (handler->count == 0)
11519                            continue;
11520                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
11521                                    "%016" PRIx64 " %" PRId64 "\n",
11522                                    op1, op2, op3, op1, (op3 << 5) | op2,
11523                                    handler->oname,
11524                                    handler->count, handler->count);
11525                    }
11526                } else {
11527                    if (handler->count == 0)
11528                        continue;
11529                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
11530                                "%016" PRIx64 " %" PRId64 "\n",
11531                                op1, op2, op1, op2, handler->oname,
11532                                handler->count, handler->count);
11533                }
11534            }
11535        } else {
11536            if (handler->count == 0)
11537                continue;
11538            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
11539                        " %" PRId64 "\n",
11540                        op1, op1, handler->oname,
11541                        handler->count, handler->count);
11542        }
11543    }
11544#endif
11545}
11546
11547/*****************************************************************************/
11548void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
11549{
11550    PowerPCCPU *cpu = ppc_env_get_cpu(env);
11551    CPUState *cs = CPU(cpu);
11552    DisasContext ctx, *ctxp = &ctx;
11553    opc_handler_t **table, *handler;
11554    target_ulong pc_start;
11555    int num_insns;
11556    int max_insns;
11557
11558    pc_start = tb->pc;
11559    ctx.nip = pc_start;
11560    ctx.tb = tb;
11561    ctx.exception = POWERPC_EXCP_NONE;
11562    ctx.spr_cb = env->spr_cb;
11563    ctx.pr = msr_pr;
11564    ctx.mem_idx = env->dmmu_idx;
11565    ctx.dr = msr_dr;
11566#if !defined(CONFIG_USER_ONLY)
11567    ctx.hv = msr_hv || !env->has_hv_mode;
11568#endif
11569    ctx.insns_flags = env->insns_flags;
11570    ctx.insns_flags2 = env->insns_flags2;
11571    ctx.access_type = -1;
11572    ctx.le_mode = !!(env->hflags & (1 << MSR_LE));
11573    ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE;
11574#if defined(TARGET_PPC64)
11575    ctx.sf_mode = msr_is_64bit(env, env->msr);
11576    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
11577#endif
11578    if (env->mmu_model == POWERPC_MMU_32B ||
11579        env->mmu_model == POWERPC_MMU_601 ||
11580        (env->mmu_model & POWERPC_MMU_64B))
11581            ctx.lazy_tlb_flush = true;
11582
11583    ctx.fpu_enabled = !!msr_fp;
11584    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
11585        ctx.spe_enabled = !!msr_spe;
11586    else
11587        ctx.spe_enabled = false;
11588    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
11589        ctx.altivec_enabled = !!msr_vr;
11590    else
11591        ctx.altivec_enabled = false;
11592    if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
11593        ctx.vsx_enabled = !!msr_vsx;
11594    } else {
11595        ctx.vsx_enabled = false;
11596    }
11597#if defined(TARGET_PPC64)
11598    if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
11599        ctx.tm_enabled = !!msr_tm;
11600    } else {
11601        ctx.tm_enabled = false;
11602    }
11603#endif
11604    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
11605        ctx.singlestep_enabled = CPU_SINGLE_STEP;
11606    else
11607        ctx.singlestep_enabled = 0;
11608    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
11609        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
11610    if (unlikely(cs->singlestep_enabled)) {
11611        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
11612    }
11613#if defined (DO_SINGLE_STEP) && 0
11614    /* Single step trace mode */
11615    msr_se = 1;
11616#endif
11617    num_insns = 0;
11618    max_insns = tb->cflags & CF_COUNT_MASK;
11619    if (max_insns == 0) {
11620        max_insns = CF_COUNT_MASK;
11621    }
11622    if (max_insns > TCG_MAX_INSNS) {
11623        max_insns = TCG_MAX_INSNS;
11624    }
11625
11626    gen_tb_start(tb);
11627    tcg_clear_temp_count();
11628    /* Set env in case of segfault during code fetch */
11629    while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
11630        tcg_gen_insn_start(ctx.nip);
11631        num_insns++;
11632
11633        if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
11634            gen_debug_exception(ctxp);
11635            /* The address covered by the breakpoint must be included in
11636               [tb->pc, tb->pc + tb->size) in order to for it to be
11637               properly cleared -- thus we increment the PC here so that
11638               the logic setting tb->size below does the right thing.  */
11639            ctx.nip += 4;
11640            break;
11641        }
11642
11643        LOG_DISAS("----------------\n");
11644        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
11645                  ctx.nip, ctx.mem_idx, (int)msr_ir);
11646        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
11647            gen_io_start();
11648        if (unlikely(need_byteswap(&ctx))) {
11649            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
11650        } else {
11651            ctx.opcode = cpu_ldl_code(env, ctx.nip);
11652        }
11653        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
11654                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
11655                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
11656        ctx.nip += 4;
11657        table = env->opcodes;
11658        handler = table[opc1(ctx.opcode)];
11659        if (is_indirect_opcode(handler)) {
11660            table = ind_table(handler);
11661            handler = table[opc2(ctx.opcode)];
11662            if (is_indirect_opcode(handler)) {
11663                table = ind_table(handler);
11664                handler = table[opc3(ctx.opcode)];
11665            }
11666        }
11667        /* Is opcode *REALLY* valid ? */
11668        if (unlikely(handler->handler == &gen_invalid)) {
11669            qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
11670                          "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
11671                          opc1(ctx.opcode), opc2(ctx.opcode),
11672                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
11673        } else {
11674            uint32_t inval;
11675
11676            if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
11677                inval = handler->inval2;
11678            } else {
11679                inval = handler->inval1;
11680            }
11681
11682            if (unlikely((ctx.opcode & inval) != 0)) {
11683                qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
11684                              "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
11685                              ctx.opcode & inval, opc1(ctx.opcode),
11686                              opc2(ctx.opcode), opc3(ctx.opcode),
11687                              ctx.opcode, ctx.nip - 4);
11688                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
11689                break;
11690            }
11691        }
11692        (*(handler->handler))(&ctx);
11693#if defined(DO_PPC_STATISTICS)
11694        handler->count++;
11695#endif
11696        /* Check trace mode exceptions */
11697        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
11698                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
11699                     ctx.exception != POWERPC_SYSCALL &&
11700                     ctx.exception != POWERPC_EXCP_TRAP &&
11701                     ctx.exception != POWERPC_EXCP_BRANCH)) {
11702            gen_exception(ctxp, POWERPC_EXCP_TRACE);
11703        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
11704                            (cs->singlestep_enabled) ||
11705                            singlestep ||
11706                            num_insns >= max_insns)) {
11707            /* if we reach a page boundary or are single stepping, stop
11708             * generation
11709             */
11710            break;
11711        }
11712        if (tcg_check_temp_count()) {
11713            fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked temporaries\n",
11714                    opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
11715                    ctx.opcode);
11716            exit(1);
11717        }
11718    }
11719    if (tb->cflags & CF_LAST_IO)
11720        gen_io_end();
11721    if (ctx.exception == POWERPC_EXCP_NONE) {
11722        gen_goto_tb(&ctx, 0, ctx.nip);
11723    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
11724        if (unlikely(cs->singlestep_enabled)) {
11725            gen_debug_exception(ctxp);
11726        }
11727        /* Generate the return instruction */
11728        tcg_gen_exit_tb(0);
11729    }
11730    gen_tb_end(tb, num_insns);
11731
11732    tb->size = ctx.nip - pc_start;
11733    tb->icount = num_insns;
11734
11735#if defined(DEBUG_DISAS)
11736    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
11737        && qemu_log_in_addr_range(pc_start)) {
11738        int flags;
11739        flags = env->bfd_mach;
11740        flags |= ctx.le_mode << 16;
11741        qemu_log("IN: %s\n", lookup_symbol(pc_start));
11742        log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
11743        qemu_log("\n");
11744    }
11745#endif
11746}
11747
11748void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
11749                          target_ulong *data)
11750{
11751    env->nip = data[0];
11752}
11753