translate.c 249.2 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
B
bellard 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
B
bellard 已提交
20 21 22 23 24 25
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

B
bellard 已提交
26
#include "cpu.h"
B
bellard 已提交
27
#include "exec-all.h"
B
bellard 已提交
28
#include "disas.h"
A
aurel32 已提交
29
#include "helper.h"
B
bellard 已提交
30
#include "tcg-op.h"
31
#include "qemu-common.h"
B
bellard 已提交
32

33 34 35 36
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

37
/* Include definitions for instructions classes and implementations flags */
B
bellard 已提交
38
//#define DO_SINGLE_STEP
39
//#define PPC_DEBUG_DISAS
40
//#define DO_PPC_STATISTICS
41
//#define OPTIMIZE_FPRF_UPDATE
B
bellard 已提交
42

43 44
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
45

A
aurel32 已提交
46 47
/* global register indexes */
static TCGv cpu_env;
48
static char cpu_reg_names[10*3 + 22*4 /* GPR */
A
aurel32 已提交
49
#if !defined(TARGET_PPC64)
50
    + 10*4 + 22*5 /* SPE GPRh */
A
aurel32 已提交
51
#endif
A
aurel32 已提交
52
    + 10*4 + 22*5 /* FPR */
A
aurel32 已提交
53 54
    + 2*(10*6 + 22*7) /* AVRh, AVRl */
    + 8*5 /* CRF */];
A
aurel32 已提交
55 56 57 58
static TCGv cpu_gpr[32];
#if !defined(TARGET_PPC64)
static TCGv cpu_gprh[32];
#endif
A
aurel32 已提交
59
static TCGv cpu_fpr[32];
60
static TCGv cpu_avrh[32], cpu_avrl[32];
A
aurel32 已提交
61
static TCGv cpu_crf[8];
A
aurel32 已提交
62
static TCGv cpu_nip;
A
aurel32 已提交
63 64
static TCGv cpu_ctr;
static TCGv cpu_lr;
A
aurel32 已提交
65
static TCGv cpu_xer;
66
static TCGv cpu_fpscr;
A
aurel32 已提交
67 68 69 70 71 72 73 74

/* dyngen register indexes */
static TCGv cpu_T[3];
#if defined(TARGET_PPC64)
#define cpu_T64 cpu_T
#else
static TCGv cpu_T64[3];
#endif
A
aurel32 已提交
75
static TCGv cpu_FT[3];
76
static TCGv cpu_AVRh[3], cpu_AVRl[3];
P
pbrook 已提交
77 78 79 80 81

#include "gen-icount.h"

void ppc_translate_init(void)
{
A
aurel32 已提交
82 83
    int i;
    char* p;
P
pbrook 已提交
84
    static int done_init = 0;
A
aurel32 已提交
85

P
pbrook 已提交
86 87
    if (done_init)
        return;
A
aurel32 已提交
88

P
pbrook 已提交
89
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
A
aurel32 已提交
90 91 92 93 94 95 96 97 98 99 100 101
#if TARGET_LONG_BITS > HOST_LONG_BITS
    cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t0), "T0");
    cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t1), "T1");
    cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t2), "T2");
#else
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
    cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
#endif
A
aurel32 已提交
102 103
#if !defined(TARGET_PPC64)
    cpu_T64[0] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
104
                                    TCG_AREG0, offsetof(CPUState, t0_64),
A
aurel32 已提交
105 106
                                    "T0_64");
    cpu_T64[1] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
107
                                    TCG_AREG0, offsetof(CPUState, t1_64),
A
aurel32 已提交
108 109
                                    "T1_64");
    cpu_T64[2] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
110
                                    TCG_AREG0, offsetof(CPUState, t2_64),
A
aurel32 已提交
111 112
                                    "T2_64");
#endif
A
aurel32 已提交
113 114 115 116 117 118 119 120

    cpu_FT[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft0), "FT0");
    cpu_FT[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft1), "FT1");
    cpu_FT[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft2), "FT2");

121 122 123 124 125 126 127 128 129 130 131 132 133
    cpu_AVRh[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr0.u64[0]), "AVR0H");
    cpu_AVRl[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr0.u64[1]), "AVR0L");
    cpu_AVRh[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr1.u64[0]), "AVR1H");
    cpu_AVRl[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr1.u64[1]), "AVR1L");
    cpu_AVRh[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr2.u64[0]), "AVR2H");
    cpu_AVRl[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr2.u64[1]), "AVR2L");

A
aurel32 已提交
134
    p = cpu_reg_names;
A
aurel32 已提交
135 136 137 138 139 140 141 142

    for (i = 0; i < 8; i++) {
        sprintf(p, "crf%d", i);
        cpu_crf[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                        offsetof(CPUState, crf[i]), p);
        p += 5;
    }

A
aurel32 已提交
143 144 145 146 147 148 149 150 151 152 153
    for (i = 0; i < 32; i++) {
        sprintf(p, "r%d", i);
        cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                        offsetof(CPUState, gpr[i]), p);
        p += (i < 10) ? 3 : 4;
#if !defined(TARGET_PPC64)
        sprintf(p, "r%dH", i);
        cpu_gprh[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                         offsetof(CPUState, gprh[i]), p);
        p += (i < 10) ? 4 : 5;
#endif
154

A
aurel32 已提交
155 156 157
        sprintf(p, "fp%d", i);
        cpu_fpr[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                        offsetof(CPUState, fpr[i]), p);
A
aurel32 已提交
158
        p += (i < 10) ? 4 : 5;
A
aurel32 已提交
159

160 161 162 163
        sprintf(p, "avr%dH", i);
        cpu_avrh[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                         offsetof(CPUState, avr[i].u64[0]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
164

165 166 167 168
        sprintf(p, "avr%dL", i);
        cpu_avrl[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                         offsetof(CPUState, avr[i].u64[1]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
169
    }
A
aurel32 已提交
170

A
aurel32 已提交
171 172 173
    cpu_nip = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                 offsetof(CPUState, nip), "nip");

A
aurel32 已提交
174 175 176 177 178 179
    cpu_ctr = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                 offsetof(CPUState, ctr), "ctr");

    cpu_lr = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                offsetof(CPUState, lr), "lr");

A
aurel32 已提交
180 181 182
    cpu_xer = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                 offsetof(CPUState, xer), "xer");

183 184 185
    cpu_fpscr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                   offsetof(CPUState, fpscr), "fpscr");

A
aurel32 已提交
186 187 188 189 190
    /* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
#include "helper.h"

P
pbrook 已提交
191 192 193
    done_init = 1;
}

194 195 196 197
#if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr;
#endif
B
bellard 已提交
198 199 200 201

/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
B
bellard 已提交
202
    target_ulong nip;
B
bellard 已提交
203
    uint32_t opcode;
204
    uint32_t exception;
B
bellard 已提交
205 206 207
    /* Routine used to access memory */
    int mem_idx;
    /* Translation flags */
208
#if !defined(CONFIG_USER_ONLY)
B
bellard 已提交
209
    int supervisor;
210 211 212
#endif
#if defined(TARGET_PPC64)
    int sf_mode;
213
#endif
B
bellard 已提交
214
    int fpu_enabled;
215
    int altivec_enabled;
216
    int spe_enabled;
217
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
218
    int singlestep_enabled;
219
    int dcache_line_size;
B
bellard 已提交
220 221
} DisasContext;

222
struct opc_handler_t {
B
bellard 已提交
223 224
    /* invalid bits */
    uint32_t inval;
225
    /* instruction type */
226
    uint64_t type;
B
bellard 已提交
227 228
    /* handler */
    void (*handler)(DisasContext *ctx);
229
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
230
    const char *oname;
231 232
#endif
#if defined(DO_PPC_STATISTICS)
233 234
    uint64_t count;
#endif
235
};
B
bellard 已提交
236

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
static always_inline void gen_reset_fpstatus (void)
{
#ifdef CONFIG_SOFTFLOAT
    gen_op_reset_fpstatus();
#endif
}

static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
{
    if (set_fprf != 0) {
        /* This case might be optimized later */
#if defined(OPTIMIZE_FPRF_UPDATE)
        *gen_fprf_ptr++ = gen_opc_ptr;
#endif
        gen_op_compute_fprf(1);
        if (unlikely(set_rc))
A
aurel32 已提交
253
            tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
254 255 256 257
        gen_op_float_check_status();
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
        gen_op_compute_fprf(0);
A
aurel32 已提交
258
        tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        if (set_fprf)
            gen_op_float_check_status();
    }
}

static always_inline void gen_optimize_fprf (void)
{
#if defined(OPTIMIZE_FPRF_UPDATE)
    uint16_t **ptr;

    for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
        *ptr = INDEX_op_nop1;
    gen_fprf_ptr = gen_fprf_buf;
#endif
}

275
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
276 277 278
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
279
        tcg_gen_movi_tl(cpu_nip, nip);
280 281
    else
#endif
A
aurel32 已提交
282
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
283 284
}

285
#define GEN_EXCP(ctx, excp, error)                                            \
B
bellard 已提交
286
do {                                                                          \
287
    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
288
        gen_update_nip(ctx, (ctx)->nip);                                      \
289 290 291
    }                                                                         \
    gen_op_raise_exception_err((excp), (error));                              \
    ctx->exception = (excp);                                                  \
B
bellard 已提交
292 293
} while (0)

294 295 296
#define GEN_EXCP_INVAL(ctx)                                                   \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
297

298 299 300
#define GEN_EXCP_PRIVOPC(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
301

302 303 304 305 306 307 308 309 310
#define GEN_EXCP_PRIVREG(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)

#define GEN_EXCP_NO_FP(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)

#define GEN_EXCP_NO_AP(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
311

312 313 314
#define GEN_EXCP_NO_VR(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)

315
/* Stop translation */
316
static always_inline void GEN_STOP (DisasContext *ctx)
317
{
318
    gen_update_nip(ctx, ctx->nip);
319
    ctx->exception = POWERPC_EXCP_STOP;
320 321
}

322
/* No need to update nip here, as execution flow will change */
323
static always_inline void GEN_SYNC (DisasContext *ctx)
324
{
325
    ctx->exception = POWERPC_EXCP_SYNC;
326 327
}

B
bellard 已提交
328 329 330 331 332
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
static void gen_##name (DisasContext *ctx);                                   \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
static void gen_##name (DisasContext *ctx)

333 334 335 336 337
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
static void gen_##name (DisasContext *ctx);                                   \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type);                       \
static void gen_##name (DisasContext *ctx)

B
bellard 已提交
338 339
typedef struct opcode_t {
    unsigned char opc1, opc2, opc3;
T
ths 已提交
340
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
341 342 343 344
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
B
bellard 已提交
345
    opc_handler_t handler;
346
    const char *oname;
B
bellard 已提交
347 348
} opcode_t;

349
/*****************************************************************************/
B
bellard 已提交
350 351
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
352
static always_inline uint32_t name (uint32_t opcode)                          \
B
bellard 已提交
353 354 355 356 357
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
358
static always_inline int32_t name (uint32_t opcode)                           \
B
bellard 已提交
359
{                                                                             \
360
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
}

/* Opcode part 1 */
EXTRACT_HELPER(opc1, 26, 6);
/* Opcode part 2 */
EXTRACT_HELPER(opc2, 1, 5);
/* Opcode part 3 */
EXTRACT_HELPER(opc3, 6, 5);
/* Update Cr0 flags */
EXTRACT_HELPER(Rc, 0, 1);
/* Destination */
EXTRACT_HELPER(rD, 21, 5);
/* Source */
EXTRACT_HELPER(rS, 21, 5);
/* First operand */
EXTRACT_HELPER(rA, 16, 5);
/* Second operand */
EXTRACT_HELPER(rB, 11, 5);
/* Third operand */
EXTRACT_HELPER(rC, 6, 5);
/***                               Get CRn                                 ***/
EXTRACT_HELPER(crfD, 23, 3);
EXTRACT_HELPER(crfS, 18, 3);
EXTRACT_HELPER(crbD, 21, 5);
EXTRACT_HELPER(crbA, 16, 5);
EXTRACT_HELPER(crbB, 11, 5);
/* SPR / TBL */
388
EXTRACT_HELPER(_SPR, 11, 10);
389
static always_inline uint32_t SPR (uint32_t opcode)
390 391 392 393 394
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
395 396 397 398 399 400 401 402 403 404 405 406 407 408
/***                              Get constants                            ***/
EXTRACT_HELPER(IMM, 12, 8);
/* 16 bits signed immediate value */
EXTRACT_SHELPER(SIMM, 0, 16);
/* 16 bits unsigned immediate value */
EXTRACT_HELPER(UIMM, 0, 16);
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
409 410
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
411 412 413 414

EXTRACT_HELPER(CRM, 12, 8);
EXTRACT_HELPER(FM, 17, 8);
EXTRACT_HELPER(SR, 16, 4);
A
aurel32 已提交
415
EXTRACT_HELPER(FPIMM, 12, 4);
B
bellard 已提交
416

B
bellard 已提交
417 418 419 420
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
421
static always_inline target_ulong LI (uint32_t opcode)
B
bellard 已提交
422 423 424 425
{
    return (opcode >> 0) & 0x03FFFFFC;
}

426
static always_inline uint32_t BD (uint32_t opcode)
B
bellard 已提交
427 428 429 430 431 432 433 434 435 436 437 438
{
    return (opcode >> 0) & 0xFFFC;
}

EXTRACT_HELPER(BO, 21, 5);
EXTRACT_HELPER(BI, 16, 5);
/* Absolute/relative address */
EXTRACT_HELPER(AA, 1, 1);
/* Link */
EXTRACT_HELPER(LK, 0, 1);

/* Create a mask between <start> and <end> bits */
439
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
B
bellard 已提交
440
{
441
    target_ulong ret;
B
bellard 已提交
442

443 444
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
445
        ret = UINT64_MAX << (63 - end);
446
    } else if (likely(end == 63)) {
447
        ret = UINT64_MAX >> start;
448 449 450
    }
#else
    if (likely(start == 0)) {
451
        ret = UINT32_MAX << (31  - end);
452
    } else if (likely(end == 31)) {
453
        ret = UINT32_MAX >> start;
454 455 456 457 458 459 460 461
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
462 463 464 465

    return ret;
}

466 467 468
/*****************************************************************************/
/* PowerPC Instructions types definitions                                    */
enum {
469
    PPC_NONE           = 0x0000000000000000ULL,
470
    /* PowerPC base instructions set                                         */
471 472
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
    /*   integer operations instructions                                     */
473
#define PPC_INTEGER PPC_INSNS_BASE
474
    /*   flow control instructions                                           */
475
#define PPC_FLOW    PPC_INSNS_BASE
476
    /*   virtual memory instructions                                         */
477
#define PPC_MEM     PPC_INSNS_BASE
478
    /*   ld/st with reservation instructions                                 */
479
#define PPC_RES     PPC_INSNS_BASE
480
    /*   spr/msr access instructions                                         */
481
#define PPC_MISC    PPC_INSNS_BASE
482 483
    /* Deprecated instruction sets                                           */
    /*   Original POWER instruction set                                      */
484
    PPC_POWER          = 0x0000000000000002ULL,
485
    /*   POWER2 instruction set extension                                    */
486
    PPC_POWER2         = 0x0000000000000004ULL,
487
    /*   Power RTC support                                                   */
488
    PPC_POWER_RTC      = 0x0000000000000008ULL,
489
    /*   Power-to-PowerPC bridge (601)                                       */
490
    PPC_POWER_BR       = 0x0000000000000010ULL,
491
    /* 64 bits PowerPC instruction set                                       */
492
    PPC_64B            = 0x0000000000000020ULL,
493
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
494
    PPC_64BX           = 0x0000000000000040ULL,
495
    /*   64 bits hypervisor extensions                                       */
496
    PPC_64H            = 0x0000000000000080ULL,
497
    /*   New wait instruction (PowerPC 2.0x)                                 */
498
    PPC_WAIT           = 0x0000000000000100ULL,
499
    /*   Time base mftb instruction                                          */
500
    PPC_MFTB           = 0x0000000000000200ULL,
501 502 503

    /* Fixed-point unit extensions                                           */
    /*   PowerPC 602 specific                                                */
504
    PPC_602_SPEC       = 0x0000000000000400ULL,
505 506 507 508 509 510
    /*   isel instruction                                                    */
    PPC_ISEL           = 0x0000000000000800ULL,
    /*   popcntb instruction                                                 */
    PPC_POPCNTB        = 0x0000000000001000ULL,
    /*   string load / store                                                 */
    PPC_STRING         = 0x0000000000002000ULL,
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527

    /* Floating-point unit extensions                                        */
    /*   Optional floating point instructions                                */
    PPC_FLOAT          = 0x0000000000010000ULL,
    /* New floating-point extensions (PowerPC 2.0x)                          */
    PPC_FLOAT_EXT      = 0x0000000000020000ULL,
    PPC_FLOAT_FSQRT    = 0x0000000000040000ULL,
    PPC_FLOAT_FRES     = 0x0000000000080000ULL,
    PPC_FLOAT_FRSQRTE  = 0x0000000000100000ULL,
    PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
    PPC_FLOAT_FSEL     = 0x0000000000400000ULL,
    PPC_FLOAT_STFIWX   = 0x0000000000800000ULL,

    /* Vector/SIMD extensions                                                */
    /*   Altivec support                                                     */
    PPC_ALTIVEC        = 0x0000000001000000ULL,
    /*   PowerPC 2.03 SPE extension                                          */
528
    PPC_SPE            = 0x0000000002000000ULL,
529
    /*   PowerPC 2.03 SPE floating-point extension                           */
530
    PPC_SPEFPU         = 0x0000000004000000ULL,
531

532
    /* Optional memory control instructions                                  */
533 534 535 536 537 538 539 540 541
    PPC_MEM_TLBIA      = 0x0000000010000000ULL,
    PPC_MEM_TLBIE      = 0x0000000020000000ULL,
    PPC_MEM_TLBSYNC    = 0x0000000040000000ULL,
    /*   sync instruction                                                    */
    PPC_MEM_SYNC       = 0x0000000080000000ULL,
    /*   eieio instruction                                                   */
    PPC_MEM_EIEIO      = 0x0000000100000000ULL,

    /* Cache control instructions                                            */
542
    PPC_CACHE          = 0x0000000200000000ULL,
543
    /*   icbi instruction                                                    */
544
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
545
    /*   dcbz instruction with fixed cache line size                         */
546
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
547
    /*   dcbz instruction with tunable cache line size                       */
548
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
549
    /*   dcba instruction                                                    */
550 551 552
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
    /*   Freescale cache locking instructions                                */
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
553 554 555

    /* MMU related extensions                                                */
    /*   external control instructions                                       */
556
    PPC_EXTERN         = 0x0000010000000000ULL,
557
    /*   segment register access instructions                                */
558
    PPC_SEGMENT        = 0x0000020000000000ULL,
559
    /*   PowerPC 6xx TLB management instructions                             */
560
    PPC_6xx_TLB        = 0x0000040000000000ULL,
561
    /* PowerPC 74xx TLB management instructions                              */
562
    PPC_74xx_TLB       = 0x0000080000000000ULL,
563
    /*   PowerPC 40x TLB management instructions                             */
564
    PPC_40x_TLB        = 0x0000100000000000ULL,
565
    /*   segment register access instructions for PowerPC 64 "bridge"        */
566
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
567
    /*   SLB management                                                      */
568
    PPC_SLBI           = 0x0000400000000000ULL,
569

570
    /* Embedded PowerPC dedicated instructions                               */
571
    PPC_WRTEE          = 0x0001000000000000ULL,
572
    /* PowerPC 40x exception model                                           */
573
    PPC_40x_EXCP       = 0x0002000000000000ULL,
574
    /* PowerPC 405 Mac instructions                                          */
575
    PPC_405_MAC        = 0x0004000000000000ULL,
576
    /* PowerPC 440 specific instructions                                     */
577
    PPC_440_SPEC       = 0x0008000000000000ULL,
578
    /* BookE (embedded) PowerPC specification                                */
579 580 581 582 583 584 585
    PPC_BOOKE          = 0x0010000000000000ULL,
    /* mfapidi instruction                                                   */
    PPC_MFAPIDI        = 0x0020000000000000ULL,
    /* tlbiva instruction                                                    */
    PPC_TLBIVA         = 0x0040000000000000ULL,
    /* tlbivax instruction                                                   */
    PPC_TLBIVAX        = 0x0080000000000000ULL,
586
    /* PowerPC 4xx dedicated instructions                                    */
587
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
588
    /* PowerPC 40x ibct instructions                                         */
589
    PPC_40x_ICBT       = 0x0200000000000000ULL,
590
    /* rfmci is not implemented in all BookE PowerPC                         */
591 592 593 594 595 596 597
    PPC_RFMCI          = 0x0400000000000000ULL,
    /* rfdi instruction                                                      */
    PPC_RFDI           = 0x0800000000000000ULL,
    /* DCR accesses                                                          */
    PPC_DCR            = 0x1000000000000000ULL,
    /* DCR extended accesse                                                  */
    PPC_DCRX           = 0x2000000000000000ULL,
598
    /* user-mode DCR access, implemented in PowerPC 460                      */
599
    PPC_DCRUX          = 0x4000000000000000ULL,
600 601 602 603
};

/*****************************************************************************/
/* PowerPC instructions table                                                */
604 605 606 607 608
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#else
#define OPC_ALIGN 4
#endif
B
bellard 已提交
609
#if defined(__APPLE__)
610
#define OPCODES_SECTION                                                       \
611
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
612
#else
613
#define OPCODES_SECTION                                                       \
614
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
615 616
#endif

617
#if defined(DO_PPC_STATISTICS)
B
bellard 已提交
618
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
619
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
620 621 622
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
623
    .pad  = { 0, },                                                           \
B
bellard 已提交
624 625
    .handler = {                                                              \
        .inval   = invl,                                                      \
626
        .type = _typ,                                                         \
B
bellard 已提交
627
        .handler = &gen_##name,                                               \
628
        .oname = stringify(name),                                             \
B
bellard 已提交
629
    },                                                                        \
630
    .oname = stringify(name),                                                 \
B
bellard 已提交
631
}
632 633 634 635 636 637 638 639 640 641 642 643 644 645
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
646 647 648 649 650 651 652 653 654 655 656 657 658 659
#else
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
660 661 662 663 664 665 666 667 668 669 670 671 672
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
673
#endif
B
bellard 已提交
674 675

#define GEN_OPCODE_MARK(name)                                                 \
676
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
677 678 679
    .opc1 = 0xFF,                                                             \
    .opc2 = 0xFF,                                                             \
    .opc3 = 0xFF,                                                             \
680
    .pad  = { 0, },                                                           \
B
bellard 已提交
681 682
    .handler = {                                                              \
        .inval   = 0x00000000,                                                \
683
        .type = 0x00,                                                         \
B
bellard 已提交
684 685
        .handler = NULL,                                                      \
    },                                                                        \
686
    .oname = stringify(name),                                                 \
B
bellard 已提交
687 688 689 690 691 692
}

/* Start opcode list */
GEN_OPCODE_MARK(start);

/* Invalid instruction */
693 694
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
{
695
    GEN_EXCP_INVAL(ctx);
696 697
}

B
bellard 已提交
698 699
static opc_handler_t invalid_handler = {
    .inval   = 0xFFFFFFFF,
700
    .type    = PPC_NONE,
B
bellard 已提交
701 702 703
    .handler = gen_invalid,
};

704 705
/***                           Integer comparison                          ***/

706
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
707 708 709
{
    int l1, l2, l3;

710 711
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
712 713 714 715 716 717
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
718 719
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
720
    } else {
721 722
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
723 724 725 726 727 728 729 730 731 732 733
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

734
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
735
{
736 737 738
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
739 740 741
}

#if defined(TARGET_PPC64)
742
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
743
{
744 745 746
    TCGv t0, t1;
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
    t1 = tcg_temp_local_new(TCG_TYPE_TL);
747
    if (s) {
748 749
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
750
    } else {
751 752
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
753
    }
754 755 756
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
757 758
}

759
static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
760
{
761 762 763
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
}
#endif

static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode))
        gen_op_cmpi32(reg, 0, 1, 0);
    else
#endif
        gen_op_cmpi(reg, 0, 1, 0);
}

/* cmp */
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
}

/* cmpi */
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
}

/* cmpl */
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
}

/* cmpli */
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
}

/* isel (PowerPC 2.03 specification) */
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
835
    TCGv t0;
836 837 838 839 840

    l1 = gen_new_label();
    l2 = gen_new_label();

    mask = 1 << (3 - (bi & 0x03));
841 842 843
    t0 = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
844 845 846 847 848 849 850 851 852 853
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
}

B
bellard 已提交
854 855
/***                           Integer arithmetic                          ***/

856 857 858 859
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
{
    int l1;
    TCGv t0;
B
bellard 已提交
860

861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
    tcg_gen_xor_tl(t0, arg0, arg1);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    tcg_gen_xor_tl(t0, arg1, arg2);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free(t0);
B
bellard 已提交
886 887
}

888 889 890
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
{
    int l1 = gen_new_label();
891 892

#if defined(TARGET_PPC64)
893 894 895 896
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_TL);
        t1 = tcg_temp_new(TCG_TYPE_TL);
897

898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_ext32u_tl(t1, arg2);
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
	} else {
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
    } else
#endif
    if (sub) {
        tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
    } else {
        tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
    }
    tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
    gen_set_label(l1);
914 915
}

916 917 918 919 920
/* Common add function */
static always_inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                           int add_ca, int compute_ca, int compute_ov)
{
    TCGv t0, t1;
921

922 923 924 925 926 927
    if ((!compute_ca && !compute_ov) ||
        (GET_TCGV(ret) != GET_TCGV(arg1) && GET_TCGV(ret) != GET_TCGV(arg2)))  {
        t0 = ret;
    } else {
        t0 = tcg_temp_local_new(TCG_TYPE_TL);
    }
B
bellard 已提交
928

929 930 931 932 933
    if (add_ca) {
        t1 = tcg_temp_local_new(TCG_TYPE_TL);
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
    }
B
bellard 已提交
934

935 936 937 938 939 940 941 942 943 944
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
B
bellard 已提交
945

946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
    tcg_gen_add_tl(t0, arg1, arg2);

    if (compute_ca) {
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
    }
    if (add_ca) {
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
    }

    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, t0);

    if (GET_TCGV(t0) != GET_TCGV(ret)) {
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
967
}
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     add_ca, compute_ca, compute_ov);                         \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER)                  \
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
                     add_ca, compute_ca, compute_ov);                         \
    tcg_temp_free(t0);                                                        \
}

/* add  add.  addo  addo. */
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
/* addc  addc.  addco  addco. */
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
/* adde  adde.  addeo  addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
/* addme  addme.  addmeo  addmeo.  */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
/* addze  addze.  addzeo  addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
/* addi */
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1005
{
1006 1007 1008 1009 1010 1011 1012 1013
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
    }
1014
}
1015 1016 1017
/* addic  addic.*/
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
                                        int compute_Rc0)
1018
{
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
    target_long simm = SIMM(ctx->opcode);

    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));

    if (likely(simm != 0)) {
        TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
        tcg_gen_addi_tl(t0, arg1, simm);
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    } else {
        tcg_gen_mov_tl(ret, arg1);
    }
    if (compute_Rc0) {
        gen_set_Rc0(ctx, ret);
    }
1036
}
1037
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1038
{
1039
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1040
}
1041
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1042
{
1043
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1044
}
1045 1046
/* addis */
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1047
{
1048 1049 1050 1051 1052 1053 1054 1055
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* lis case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
    }
1056
}
1057 1058 1059

static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                             int sign, int compute_ov)
1060
{
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
    int l1, l2, l3;
    TCGv t0, t1, t2;

#if defined(TARGET_PPC64)
    t0 = tcg_temp_local_new(TCG_TYPE_I32);
    t1 = t0;
    t2 = tcg_temp_local_new(TCG_TYPE_I32);
    tcg_gen_trunc_i64_i32(t1, arg1);
    tcg_gen_trunc_i64_i32(t2, arg2);
#else
    t0 = ret;
    t1 = arg1;
    t2 = arg2;
1074
#endif
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
    l1 = gen_new_label();
    l2 = gen_new_label();
    tcg_gen_brcondi_i32(TCG_COND_EQ, t2, 0, l1);
    if (sign) {
        l3 = gen_new_label();
        tcg_gen_brcondi_i32(TCG_COND_NE, t2, -1, l3);
        tcg_gen_brcondi_i32(TCG_COND_EQ, t1, INT32_MIN, l1);
        gen_set_label(l3);
    }
    if (sign) {
        tcg_gen_div_i32(t0, t1, t2);
    } else {
        tcg_gen_divu_i32(t0, t1, t2);
    }
    if (compute_ov) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
        tcg_gen_sari_i32(t0, t1, 31);
    } else {
        tcg_gen_movi_i32(t0, 0);
    }
    if (compute_ov) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
1103
#if defined(TARGET_PPC64)
1104 1105
    tcg_gen_extu_i32_i64(ret, t0);
    tcg_temp_free(t0);
1106
#endif
1107 1108
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1109
}
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     sign, compute_ov);                                       \
}
/* divwu  divwu.  divwuo  divwuo.   */
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
/* divw  divw.  divwo  divwo.   */
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1124
#if defined(TARGET_PPC64)
1125 1126
static always_inline void gen_op_divd (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                       int sign, int compute_ov)
1127
{
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
    int l1, l2, l3;

    l1 = gen_new_label();
    l2 = gen_new_label();

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
        l3 = gen_new_label();
        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
        gen_set_label(l3);
    }
    if (sign) {
        tcg_gen_div_i64(ret, arg1, arg2);
    } else {
        tcg_gen_divu_i64(ret, arg1, arg2);
    }
    if (compute_ov) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
        tcg_gen_sari_i64(ret, arg1, 63);
    } else {
        tcg_gen_movi_i64(ret, 0);
    }
    if (compute_ov) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1161
}
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
{                                                                             \
    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     sign, compute_ov);                                       \
}
/* divwu  divwu.  divwuo  divwuo.   */
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
/* divw  divw.  divwo  divwo.   */
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1175
#endif
1176 1177 1178

/* mulhw  mulhw. */
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
1179
{
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
    TCGv t0, t1;

    t0 = tcg_temp_new(TCG_TYPE_I64);
    t1 = tcg_temp_new(TCG_TYPE_I64);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1200
}
1201 1202
/* mulhwu  mulhwu.  */
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
1203
{
1204 1205 1206 1207
    TCGv t0, t1;

    t0 = tcg_temp_new(TCG_TYPE_I64);
    t1 = tcg_temp_new(TCG_TYPE_I64);
1208
#if defined(TARGET_PPC64)
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1224
}
1225 1226
/* mullw  mullw. */
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER)
1227
{
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
#if defined(TARGET_PPC64)
    TCGv t0, t1;
    t0 = tcg_temp_new(TCG_TYPE_TL);
    t1 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_tl(t0, t0, t1);
    tcg_temp_free(t0);
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1241
#endif
1242 1243
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1244
}
1245 1246
/* mullwo  mullwo. */
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER)
1247
{
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
    int l1;
    TCGv t0, t1;

    t0 = tcg_temp_local_new(TCG_TYPE_I64);
    t1 = tcg_temp_local_new(TCG_TYPE_I64);
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1262
#endif
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
    tcg_gen_mul_i64(t0, t0, t1);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
#else
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
#endif
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1276
}
1277 1278
/* mulli */
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1279
{
1280 1281
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1282 1283
}
#if defined(TARGET_PPC64)
1284 1285 1286 1287 1288 1289 1290
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
{                                                                             \
    tcg_gen_helper_1_2(helper_##name, cpu_gpr[rD(ctx->opcode)],               \
                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);   \
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1291
}
1292 1293 1294 1295 1296 1297
/* mulhd  mulhd. */
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
/* mulhdu  mulhdu. */
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
/* mulld  mulld. */
GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B)
1298
{
1299 1300 1301 1302
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1303
}
1304 1305
/* mulldo  mulldo. */
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1306
#endif
1307 1308 1309

/* neg neg. nego nego. */
static always_inline void gen_op_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
1310
{
1311 1312 1313 1314
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
1315
#if defined(TARGET_PPC64)
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
    if (ctx->sf_mode) {
        tcg_gen_brcondi_tl(TCG_COND_EQ, arg1, INT64_MIN, l1);
    } else {
        TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
	tcg_gen_ext32s_tl(t0, arg1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
    }
#else
        tcg_gen_brcondi_tl(TCG_COND_EQ, arg1, INT32_MIN, l1);
#endif
    tcg_gen_neg_tl(ret, arg1);
    if (ov_check) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(ret, arg1);
    if (ov_check) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
}
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER)
1341
{
1342
    gen_op_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1343
}
1344
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER)
B
bellard 已提交
1345
{
1346
    gen_op_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
B
bellard 已提交
1347
}
1348 1349 1350 1351

/* Common subf function */
static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                            int add_ca, int compute_ca, int compute_ov)
B
bellard 已提交
1352
{
1353
    TCGv t0, t1;
1354

1355 1356 1357
    if ((!compute_ca && !compute_ov) ||
        (GET_TCGV(ret) != GET_TCGV(arg1) && GET_TCGV(ret) != GET_TCGV(arg2)))  {
        t0 = ret;
J
j_mayer 已提交
1358
    } else {
1359
        t0 = tcg_temp_local_new(TCG_TYPE_TL);
1360
    }
1361

1362 1363 1364 1365
    if (add_ca) {
        t1 = tcg_temp_local_new(TCG_TYPE_TL);
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1366
    }
B
bellard 已提交
1367

1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }

    if (add_ca) {
        tcg_gen_not_tl(t0, arg1);
        tcg_gen_add_tl(t0, t0, arg2);
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
B
bellard 已提交
1386
    } else {
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
        tcg_gen_sub_tl(t0, arg2, arg1);
        if (compute_ca) {
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
        }
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }

    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, t0);

    if (GET_TCGV(t0) != GET_TCGV(ret)) {
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1402 1403
    }
}
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      add_ca, compute_ca, compute_ov);                        \
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER)                  \
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
                      add_ca, compute_ca, compute_ov);                        \
    tcg_temp_free(t0);                                                        \
}
/* subf  subf.  subfo  subfo. */
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
/* subfc  subfc.  subfco  subfco. */
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
/* subfe  subfe.  subfeo  subfo. */
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
/* subfme  subfme.  subfmeo  subfmeo.  */
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
/* subfze  subfze.  subfzeo  subfzeo.*/
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
B
bellard 已提交
1438 1439 1440
/* subfic */
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1441 1442 1443 1444 1445 1446 1447 1448 1449
    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
    tcg_temp_free(t1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
B
bellard 已提交
1450 1451 1452
}

/***                            Integer logical                            ***/
1453 1454
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)                          \
B
bellard 已提交
1455
{                                                                             \
1456 1457
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1458
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1459
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1460 1461
}

1462
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1463
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
B
bellard 已提交
1464
{                                                                             \
1465
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1466
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1467
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1468 1469 1470
}

/* and & and. */
1471
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1472
/* andc & andc. */
1473
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
bellard 已提交
1474
/* andi. */
1475
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1476
{
1477 1478
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1479 1480
}
/* andis. */
1481
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1482
{
1483 1484
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1485 1486
}
/* cntlzw */
1487 1488 1489 1490
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER)
{
    tcg_gen_helper_1_1(helper_cntlzw, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1491
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1492
}
B
bellard 已提交
1493
/* eqv & eqv. */
1494
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1495
/* extsb & extsb. */
1496
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1497
/* extsh & extsh. */
1498
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1499
/* nand & nand. */
1500
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1501
/* nor & nor. */
1502
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
bellard 已提交
1503
/* or & or. */
1504 1505
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
{
1506 1507 1508 1509 1510 1511 1512
    int rs, ra, rb;

    rs = rS(ctx->opcode);
    ra = rA(ctx->opcode);
    rb = rB(ctx->opcode);
    /* Optimisation for mr. ri case */
    if (rs != ra || rs != rb) {
1513 1514 1515 1516
        if (rs != rb)
            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
        else
            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1517
        if (unlikely(Rc(ctx->opcode) != 0))
1518
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1519
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1520
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1521 1522
#if defined(TARGET_PPC64)
    } else {
1523 1524
        int prio = 0;

1525 1526 1527
        switch (rs) {
        case 1:
            /* Set process priority to low */
1528
            prio = 2;
1529 1530 1531
            break;
        case 6:
            /* Set process priority to medium-low */
1532
            prio = 3;
1533 1534 1535
            break;
        case 2:
            /* Set process priority to normal */
1536
            prio = 4;
1537
            break;
1538 1539 1540 1541
#if !defined(CONFIG_USER_ONLY)
        case 31:
            if (ctx->supervisor > 0) {
                /* Set process priority to very low */
1542
                prio = 1;
1543 1544 1545 1546 1547
            }
            break;
        case 5:
            if (ctx->supervisor > 0) {
                /* Set process priority to medium-hight */
1548
                prio = 5;
1549 1550 1551 1552 1553
            }
            break;
        case 3:
            if (ctx->supervisor > 0) {
                /* Set process priority to high */
1554
                prio = 6;
1555 1556 1557 1558 1559
            }
            break;
        case 7:
            if (ctx->supervisor > 1) {
                /* Set process priority to very high */
1560
                prio = 7;
1561 1562 1563
            }
            break;
#endif
1564 1565 1566 1567
        default:
            /* nop */
            break;
        }
1568
        if (prio) {
1569 1570 1571 1572 1573 1574
            TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
            tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, spr[SPR_PPR]));
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
            tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, spr[SPR_PPR]));
            tcg_temp_free(t0);
1575
        }
1576
#endif
1577 1578
    }
}
B
bellard 已提交
1579
/* orc & orc. */
1580
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
bellard 已提交
1581
/* xor & xor. */
1582 1583 1584
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
{
    /* Optimisation for "set to zero" case */
1585
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1586
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1587 1588
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1589
    if (unlikely(Rc(ctx->opcode) != 0))
1590
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1591
}
B
bellard 已提交
1592 1593 1594
/* ori */
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1595
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1596

1597 1598
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1599
        /* XXX: should handle special NOPs for POWER series */
1600
        return;
1601
    }
1602
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1603 1604 1605 1606
}
/* oris */
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1607
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1608

1609 1610 1611
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1612
    }
1613
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1614 1615 1616 1617
}
/* xori */
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1618
    target_ulong uimm = UIMM(ctx->opcode);
1619 1620 1621 1622 1623

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1624
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1625 1626 1627 1628
}
/* xoris */
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1629
    target_ulong uimm = UIMM(ctx->opcode);
1630 1631 1632 1633 1634

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1635
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1636
}
1637
/* popcntb : PowerPC 2.03 specification */
1638
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1639 1640 1641
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
1642
        tcg_gen_helper_1_1(helper_popcntb_64, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1643 1644
    else
#endif
1645
        tcg_gen_helper_1_1(helper_popcntb, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1646 1647 1648 1649
}

#if defined(TARGET_PPC64)
/* extsw & extsw. */
1650
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1651
/* cntlzd */
1652 1653 1654 1655 1656 1657
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B)
{
    tcg_gen_helper_1_1(helper_cntlzd, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1658 1659
#endif

B
bellard 已提交
1660 1661 1662 1663
/***                             Integer rotate                            ***/
/* rlwimi & rlwimi. */
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1664
    uint32_t mb, me, sh;
B
bellard 已提交
1665 1666 1667

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1668
    sh = SH(ctx->opcode);
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
    if (likely(sh == 0 && mb == 0 && me == 31)) {
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        TCGv t0, t1;
        target_ulong mask;

        t0 = tcg_temp_new(TCG_TYPE_TL);
        t1 = tcg_temp_new(TCG_TYPE_TL);
        if (likely(sh == 0)) {
            tcg_gen_mov_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        } else {
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_shli_tl(t0, t1, sh);
            tcg_gen_shri_tl(t1, t1, 32 - sh);
            tcg_gen_or_tl(t0, t0, t1);
1684 1685
        }
#if defined(TARGET_PPC64)
1686 1687
        mb += 32;
        me += 32;
1688
#endif
1689 1690 1691 1692 1693 1694 1695
        mask = MASK(mb, me);
        tcg_gen_andi_tl(t0, t0, mask);
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
    }
1696
    if (unlikely(Rc(ctx->opcode) != 0))
1697
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1698 1699 1700 1701 1702
}
/* rlwinm & rlwinm. */
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me, sh;
1703

B
bellard 已提交
1704 1705 1706
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716

    if (likely(mb == 0 && me == (31 - sh))) {
        if (likely(sh == 0)) {
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
        } else {
            TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_shli_tl(t0, t0, sh);
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
            tcg_temp_free(t0);
B
bellard 已提交
1717
        }
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
        TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_shri_tl(t0, t0, mb);
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
        tcg_temp_free(t0);
    } else {
        TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
        if (likely(sh != 0)) {
            TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_shli_tl(t1, t0, sh);
            tcg_gen_shri_tl(t0, t0, 32 - sh);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_temp_free(t1);
        } else {
            tcg_gen_mov_tl(t0, cpu_gpr[rS(ctx->opcode)]);
B
bellard 已提交
1735
        }
1736
#if defined(TARGET_PPC64)
1737 1738
        mb += 32;
        me += 32;
1739
#endif
1740 1741 1742
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
        tcg_temp_free(t0);
    }
1743
    if (unlikely(Rc(ctx->opcode) != 0))
1744
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1745 1746 1747 1748 1749
}
/* rlwnm & rlwnm. */
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me;
A
aurel32 已提交
1750
    TCGv t0, t1, t2;
B
bellard 已提交
1751 1752 1753

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1754 1755 1756 1757 1758 1759
    t0 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
    t1 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
    t2 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_shl_tl(t2, t1, t0);
A
aurel32 已提交
1760
    tcg_gen_subfi_tl(t0, 32, t0);
1761 1762 1763 1764
    tcg_gen_shr_tl(t1, t1, t0);
    tcg_temp_free(t0);
    tcg_gen_or_tl(t2, t2, t1);
    tcg_temp_free(t1);
1765 1766 1767 1768 1769
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1770 1771 1772
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t2, MASK(mb, me));
    } else {
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t2);
B
bellard 已提交
1773
    }
1774
    tcg_temp_free(t2);
1775
    if (unlikely(Rc(ctx->opcode) != 0))
1776
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1777 1778
}

1779 1780
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1781
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1782 1783 1784
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
1785 1786
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1787 1788 1789 1790
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1791
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1792 1793 1794
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
1795 1796
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1797 1798 1799
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
1800 1801
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1802 1803 1804
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
1805 1806
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1807 1808 1809
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1810

1811 1812
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
                                      uint32_t me, uint32_t sh)
J
j_mayer 已提交
1813
{
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
    } else {
        TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
        if (likely(sh != 0)) {
            TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
            tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
            tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 64 - sh);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_temp_free(t1);
        } else {
            tcg_gen_mov_tl(t0, cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
1828
        }
1829 1830 1831 1832
        if (likely(mb == 0 && me == 63)) {
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1833
        }
1834
        tcg_temp_free(t0);
J
j_mayer 已提交
1835 1836
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1837
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1838
}
1839
/* rldicl - rldicl. */
1840
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1841
{
J
j_mayer 已提交
1842
    uint32_t sh, mb;
1843

J
j_mayer 已提交
1844 1845
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1846
    gen_rldinm(ctx, mb, 63, sh);
1847
}
J
j_mayer 已提交
1848
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1849
/* rldicr - rldicr. */
1850
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1851
{
J
j_mayer 已提交
1852
    uint32_t sh, me;
1853

J
j_mayer 已提交
1854 1855
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1856
    gen_rldinm(ctx, 0, me, sh);
1857
}
J
j_mayer 已提交
1858
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1859
/* rldic - rldic. */
1860
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1861
{
J
j_mayer 已提交
1862
    uint32_t sh, mb;
1863

J
j_mayer 已提交
1864 1865
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1866 1867 1868 1869
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

1870 1871
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
                                     uint32_t me)
J
j_mayer 已提交
1872
{
A
aurel32 已提交
1873
    TCGv t0, t1;
1874 1875 1876 1877 1878 1879 1880

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
    t0 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    t1 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t0);
A
aurel32 已提交
1881
    tcg_gen_subfi_tl(t0, 64, t0);
1882 1883 1884
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    tcg_gen_or_tl(t1, t1, t0);
    tcg_temp_free(t0);
J
j_mayer 已提交
1885
    if (unlikely(mb != 0 || me != 63)) {
1886 1887 1888 1889
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t1, MASK(mb, me));
    } else
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
    tcg_temp_free(t1);
J
j_mayer 已提交
1890
    if (unlikely(Rc(ctx->opcode) != 0))
1891
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1892
}
J
j_mayer 已提交
1893

1894
/* rldcl - rldcl. */
1895
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1896
{
J
j_mayer 已提交
1897
    uint32_t mb;
1898

J
j_mayer 已提交
1899
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1900
    gen_rldnm(ctx, mb, 63);
1901
}
1902
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1903
/* rldcr - rldcr. */
1904
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1905
{
J
j_mayer 已提交
1906
    uint32_t me;
1907

J
j_mayer 已提交
1908
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1909
    gen_rldnm(ctx, 0, me);
1910
}
1911
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1912
/* rldimi - rldimi. */
1913
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1914
{
1915
    uint32_t sh, mb, me;
1916

J
j_mayer 已提交
1917 1918
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1919
    me = 63 - sh;
1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
    if (unlikely(sh == 0 && mb == 0)) {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        TCGv t0, t1;
        target_ulong mask;

        t0 = tcg_temp_new(TCG_TYPE_TL);
        t1 = tcg_temp_new(TCG_TYPE_TL);
        if (likely(sh == 0)) {
            tcg_gen_mov_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        } else {
            tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
            tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 64 - sh);
            tcg_gen_or_tl(t0, t0, t1);
J
j_mayer 已提交
1934
        }
1935 1936 1937 1938 1939 1940
        mask = MASK(mb, me);
        tcg_gen_andi_tl(t0, t0, mask);
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
J
j_mayer 已提交
1941 1942
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1943
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1944
}
1945
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1946 1947
#endif

B
bellard 已提交
1948 1949
/***                             Integer shift                             ***/
/* slw & slw. */
1950 1951
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER)
{
1952
    TCGv t0;
1953 1954 1955 1956
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

1957
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
A
aurel32 已提交
1958 1959
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1960 1961 1962
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
1963
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1964 1965
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
1966
    tcg_temp_free(t0);
1967 1968 1969
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
bellard 已提交
1970
/* sraw & sraw. */
1971 1972 1973 1974 1975 1976 1977
GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER)
{
    tcg_gen_helper_1_2(helper_sraw, cpu_gpr[rA(ctx->opcode)],
                       cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
bellard 已提交
1978 1979 1980
/* srawi & srawi. */
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
{
1981 1982 1983
    int sh = SH(ctx->opcode);
    if (sh != 0) {
        int l1, l2;
1984
        TCGv t0;
1985 1986
        l1 = gen_new_label();
        l2 = gen_new_label();
1987 1988 1989 1990 1991
        t0 = tcg_temp_local_new(TCG_TYPE_TL);
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1992
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1993 1994
        tcg_gen_br(l2);
        gen_set_label(l1);
1995
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1996
        gen_set_label(l2);
1997 1998 1999
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
        tcg_temp_free(t0);
2000 2001
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2002
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2003
    }
2004
    if (unlikely(Rc(ctx->opcode) != 0))
2005
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
2006 2007
}
/* srw & srw. */
2008 2009
GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER)
{
2010
    TCGv t0, t1;
2011 2012 2013
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();
2014

2015
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
A
aurel32 已提交
2016 2017
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
2018 2019 2020
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
2021 2022 2023 2024
    t1 = tcg_temp_new(TCG_TYPE_TL);
    tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t1, t0);
    tcg_temp_free(t1);
2025
    gen_set_label(l2);
2026
    tcg_temp_free(t0);
2027 2028 2029
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2030 2031
#if defined(TARGET_PPC64)
/* sld & sld. */
2032 2033
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B)
{
2034
    TCGv t0;
2035 2036 2037 2038
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

2039
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
A
aurel32 已提交
2040 2041
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2042 2043 2044
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
2045
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2046
    gen_set_label(l2);
2047
    tcg_temp_free(t0);
2048 2049 2050
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2051
/* srad & srad. */
2052 2053 2054 2055 2056 2057 2058
GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B)
{
    tcg_gen_helper_1_2(helper_srad, cpu_gpr[rA(ctx->opcode)],
                       cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2059
/* sradi & sradi. */
2060
static always_inline void gen_sradi (DisasContext *ctx, int n)
2061
{
2062
    int sh = SH(ctx->opcode) + (n << 5);
2063
    if (sh != 0) {
2064
        int l1, l2;
2065
        TCGv t0;
2066 2067 2068
        l1 = gen_new_label();
        l2 = gen_new_label();
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
2069 2070 2071
        t0 = tcg_temp_new(TCG_TYPE_TL);
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2072
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
2073 2074
        tcg_gen_br(l2);
        gen_set_label(l1);
2075
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2076 2077 2078 2079
        gen_set_label(l2);
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2080
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2081 2082
    }
    if (unlikely(Rc(ctx->opcode) != 0))
2083
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2084
}
2085
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
2086 2087 2088
{
    gen_sradi(ctx, 0);
}
2089
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
2090 2091 2092 2093
{
    gen_sradi(ctx, 1);
}
/* srd & srd. */
2094 2095
GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B)
{
2096
    TCGv t0;
2097 2098 2099 2100
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

2101
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
A
aurel32 已提交
2102 2103
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2104 2105 2106
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
2107
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2108
    gen_set_label(l2);
2109
    tcg_temp_free(t0);
2110 2111 2112
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2113
#endif
B
bellard 已提交
2114 2115

/***                       Floating-Point arithmetic                       ***/
2116
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2117
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2118
{                                                                             \
2119
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2120
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2121 2122
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2123 2124 2125
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[2], cpu_fpr[rB(ctx->opcode)]);                     \
2126
    gen_reset_fpstatus();                                                     \
2127 2128 2129 2130
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2131
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2132
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2133 2134
}

2135 2136 2137
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2138

2139 2140
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2141
{                                                                             \
2142
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2143
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2144 2145
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2146 2147
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);                     \
2148
    gen_reset_fpstatus();                                                     \
2149 2150 2151 2152
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2153
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2154
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2155
}
2156 2157 2158
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2159

2160 2161
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2162
{                                                                             \
2163
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2164
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2165 2166
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2167 2168
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]);                     \
2169
    gen_reset_fpstatus();                                                     \
2170 2171 2172 2173
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2174
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2175
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2176
}
2177 2178 2179
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2180

2181
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2182
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
2183
{                                                                             \
2184
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2185
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2186 2187
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2188
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
2189
    gen_reset_fpstatus();                                                     \
2190
    gen_op_f##name();                                                         \
A
aurel32 已提交
2191
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2192
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2193 2194
}

2195
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2196
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
2197
{                                                                             \
2198
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2199
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2200 2201
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2202
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
2203
    gen_reset_fpstatus();                                                     \
2204
    gen_op_f##name();                                                         \
A
aurel32 已提交
2205
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2206
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2207 2208
}

2209
/* fadd - fadds */
2210
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2211
/* fdiv - fdivs */
2212
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2213
/* fmul - fmuls */
2214
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2215

2216
/* fre */
2217
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2218

2219
/* fres */
2220
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2221

2222
/* frsqrte */
2223 2224 2225 2226 2227 2228 2229 2230
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
static always_inline void gen_op_frsqrtes (void)
{
    gen_op_frsqrte();
    gen_op_frsp();
}
2231
GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
B
bellard 已提交
2232

2233
/* fsel */
2234
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2235
/* fsub - fsubs */
2236
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2237 2238
/* Optional: */
/* fsqrt */
2239
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2240
{
2241
    if (unlikely(!ctx->fpu_enabled)) {
2242
        GEN_EXCP_NO_FP(ctx);
2243 2244
        return;
    }
A
aurel32 已提交
2245
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2246
    gen_reset_fpstatus();
2247
    gen_op_fsqrt();
A
aurel32 已提交
2248
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2249
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
2250
}
B
bellard 已提交
2251

2252
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
2253
{
2254
    if (unlikely(!ctx->fpu_enabled)) {
2255
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2256 2257
        return;
    }
A
aurel32 已提交
2258
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2259
    gen_reset_fpstatus();
2260 2261
    gen_op_fsqrt();
    gen_op_frsp();
A
aurel32 已提交
2262
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2263
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2264 2265 2266
}

/***                     Floating-Point multiply-and-add                   ***/
2267
/* fmadd - fmadds */
2268
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2269
/* fmsub - fmsubs */
2270
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2271
/* fnmadd - fnmadds */
2272
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2273
/* fnmsub - fnmsubs */
2274
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2275 2276 2277

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2278
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2279
/* fctiwz */
2280
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2281
/* frsp */
2282
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2283 2284
#if defined(TARGET_PPC64)
/* fcfid */
2285
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2286
/* fctid */
2287
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2288
/* fctidz */
2289
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2290
#endif
B
bellard 已提交
2291

2292
/* frin */
2293
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2294
/* friz */
2295
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2296
/* frip */
2297
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2298
/* frim */
2299
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2300

B
bellard 已提交
2301 2302
/***                         Floating-Point compare                        ***/
/* fcmpo */
2303
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2304
{
2305
    if (unlikely(!ctx->fpu_enabled)) {
2306
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2307 2308
        return;
    }
A
aurel32 已提交
2309 2310
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
2311
    gen_reset_fpstatus();
2312
    tcg_gen_helper_1_0(helper_fcmpo, cpu_crf[crfD(ctx->opcode)]);
2313
    gen_op_float_check_status();
B
bellard 已提交
2314 2315 2316
}

/* fcmpu */
2317
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2318
{
2319
    if (unlikely(!ctx->fpu_enabled)) {
2320
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2321 2322
        return;
    }
A
aurel32 已提交
2323 2324
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
2325
    gen_reset_fpstatus();
2326
    tcg_gen_helper_1_0(helper_fcmpu, cpu_crf[crfD(ctx->opcode)]);
2327
    gen_op_float_check_status();
B
bellard 已提交
2328 2329
}

2330 2331
/***                         Floating-point move                           ***/
/* fabs */
2332 2333
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2334 2335

/* fmr  - fmr. */
2336
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2337 2338
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
2339
    if (unlikely(!ctx->fpu_enabled)) {
2340
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2341 2342
        return;
    }
A
aurel32 已提交
2343 2344
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2345
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
2346 2347 2348
}

/* fnabs */
2349 2350
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2351
/* fneg */
2352 2353
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2354

B
bellard 已提交
2355 2356 2357 2358
/***                  Floating-Point status & ctrl register                ***/
/* mcrfs */
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
{
2359 2360
    int bfa;

2361
    if (unlikely(!ctx->fpu_enabled)) {
2362
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2363 2364
        return;
    }
2365 2366
    gen_optimize_fprf();
    bfa = 4 * (7 - crfS(ctx->opcode));
2367 2368
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2369
    gen_op_fpscr_resetbit(~(0xF << bfa));
B
bellard 已提交
2370 2371 2372 2373 2374
}

/* mffs */
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
{
2375
    if (unlikely(!ctx->fpu_enabled)) {
2376
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2377 2378
        return;
    }
2379 2380 2381
    gen_optimize_fprf();
    gen_reset_fpstatus();
    gen_op_load_fpscr_FT0();
A
aurel32 已提交
2382
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2383
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2384 2385 2386 2387 2388
}

/* mtfsb0 */
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
{
B
bellard 已提交
2389
    uint8_t crb;
2390

2391
    if (unlikely(!ctx->fpu_enabled)) {
2392
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2393 2394
        return;
    }
2395 2396 2397 2398 2399 2400
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    if (likely(crb != 30 && crb != 29))
        gen_op_fpscr_resetbit(~(1 << crb));
    if (unlikely(Rc(ctx->opcode) != 0)) {
2401
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2402
    }
B
bellard 已提交
2403 2404 2405 2406 2407
}

/* mtfsb1 */
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
{
B
bellard 已提交
2408
    uint8_t crb;
2409

2410
    if (unlikely(!ctx->fpu_enabled)) {
2411
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2412 2413
        return;
    }
2414 2415 2416 2417 2418 2419 2420
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
        gen_op_fpscr_setbit(crb);
    if (unlikely(Rc(ctx->opcode) != 0)) {
2421
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2422 2423 2424
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2425 2426 2427 2428 2429
}

/* mtfsf */
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
{
2430
    if (unlikely(!ctx->fpu_enabled)) {
2431
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2432 2433
        return;
    }
2434
    gen_optimize_fprf();
A
aurel32 已提交
2435
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2436
    gen_reset_fpstatus();
2437
    gen_op_store_fpscr(FM(ctx->opcode));
2438
    if (unlikely(Rc(ctx->opcode) != 0)) {
2439
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2440 2441 2442
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2443 2444 2445 2446 2447
}

/* mtfsfi */
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
{
2448 2449
    int bf, sh;

2450
    if (unlikely(!ctx->fpu_enabled)) {
2451
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2452 2453
        return;
    }
2454 2455 2456
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
    gen_optimize_fprf();
2457
    tcg_gen_movi_i64(cpu_FT[0], FPIMM(ctx->opcode) << (4 * sh));
2458 2459 2460
    gen_reset_fpstatus();
    gen_op_store_fpscr(1 << sh);
    if (unlikely(Rc(ctx->opcode) != 0)) {
2461
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2462 2463 2464
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2465 2466
}

2467 2468
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2469 2470
static always_inline void gen_addr_imm_index (TCGv EA,
                                              DisasContext *ctx,
2471
                                              target_long maskl)
2472 2473 2474
{
    target_long simm = SIMM(ctx->opcode);

2475
    simm &= ~maskl;
2476 2477 2478 2479 2480 2481
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, simm);
    else if (likely(simm != 0))
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2482 2483
}

2484 2485
static always_inline void gen_addr_reg_index (TCGv EA,
                                              DisasContext *ctx)
2486
{
2487 2488 2489 2490
    if (rA(ctx->opcode) == 0)
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
    else
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2491 2492
}

2493 2494
static always_inline void gen_addr_register (TCGv EA,
                                             DisasContext *ctx)
2495
{
2496 2497 2498 2499
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, 0);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2500 2501
}

2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
#if defined(TARGET_PPC64)
#define _GEN_MEM_FUNCS(name, mode)                                            \
    &gen_op_##name##_##mode,                                                  \
    &gen_op_##name##_le_##mode,                                               \
    &gen_op_##name##_64_##mode,                                               \
    &gen_op_##name##_le_64_##mode
#else
#define _GEN_MEM_FUNCS(name, mode)                                            \
    &gen_op_##name##_##mode,                                                  \
    &gen_op_##name##_le_##mode
#endif
2513
#if defined(CONFIG_USER_ONLY)
2514
#if defined(TARGET_PPC64)
2515
#define NB_MEM_FUNCS 4
2516
#else
2517
#define NB_MEM_FUNCS 2
2518
#endif
2519 2520
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, raw)
2521
#else
2522
#if defined(TARGET_PPC64)
2523
#define NB_MEM_FUNCS 12
2524
#else
2525
#define NB_MEM_FUNCS 6
2526
#endif
2527 2528 2529 2530 2531 2532 2533 2534
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, user),                                               \
    _GEN_MEM_FUNCS(name, kernel),                                             \
    _GEN_MEM_FUNCS(name, hypv)
#endif

/***                             Integer load                              ***/
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
2535
#define OP_LD_TABLE(width)                                                    \
2536 2537
static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = {                           \
    GEN_MEM_FUNCS(l##width),                                                  \
2538 2539
};
#define OP_ST_TABLE(width)                                                    \
2540 2541
static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = {                          \
    GEN_MEM_FUNCS(st##width),                                                 \
2542
};
2543

A
aurel32 已提交
2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582

#if defined(TARGET_PPC64)
#define GEN_QEMU_LD_PPC64(width)                                                 \
static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\
{                                                                                \
    if (likely(flags & 2))                                                       \
        tcg_gen_qemu_ld##width(t0, t1, flags >> 2);                              \
    else {                                                                       \
        TCGv addr = tcg_temp_new(TCG_TYPE_TL);                                   \
        tcg_gen_ext32u_tl(addr, t1);                                             \
        tcg_gen_qemu_ld##width(t0, addr, flags >> 2);                            \
        tcg_temp_free(addr);                                                     \
    }                                                                            \
}
GEN_QEMU_LD_PPC64(8u)
GEN_QEMU_LD_PPC64(8s)
GEN_QEMU_LD_PPC64(16u)
GEN_QEMU_LD_PPC64(16s)
GEN_QEMU_LD_PPC64(32u)
GEN_QEMU_LD_PPC64(32s)
GEN_QEMU_LD_PPC64(64)

#define GEN_QEMU_ST_PPC64(width)                                                 \
static always_inline void gen_qemu_st##width##_ppc64(TCGv t0, TCGv t1, int flags)\
{                                                                                \
    if (likely(flags & 2))                                                       \
        tcg_gen_qemu_st##width(t0, t1, flags >> 2);                              \
    else {                                                                       \
        TCGv addr = tcg_temp_new(TCG_TYPE_TL);                                   \
        tcg_gen_ext32u_tl(addr, t1);                                             \
        tcg_gen_qemu_st##width(t0, addr, flags >> 2);                            \
        tcg_temp_free(addr);                                                     \
    }                                                                            \
}
GEN_QEMU_ST_PPC64(8)
GEN_QEMU_ST_PPC64(16)
GEN_QEMU_ST_PPC64(32)
GEN_QEMU_ST_PPC64(64)

2583
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2584
{
2585
    gen_qemu_ld8u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2586 2587
}

2588
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2589
{
2590
    gen_qemu_ld8s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2591 2592
}

2593
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2594 2595
{
    if (unlikely(flags & 1)) {
2596 2597 2598 2599 2600 2601 2602
        TCGv t0;
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap16_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2603
    } else
2604
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2605 2606
}

2607
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2608 2609
{
    if (unlikely(flags & 1)) {
2610 2611 2612 2613 2614 2615 2616 2617
        TCGv t0;
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap16_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_gen_ext16s_tl(arg0, arg0);
        tcg_temp_free(t0);
A
aurel32 已提交
2618
    } else
2619
        gen_qemu_ld16s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2620 2621
}

2622
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2623 2624
{
    if (unlikely(flags & 1)) {
2625 2626 2627 2628 2629 2630 2631
        TCGv t0;
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2632
    } else
2633
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2634 2635
}

2636
static always_inline void gen_qemu_ld32s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2637 2638
{
    if (unlikely(flags & 1)) {
2639 2640 2641 2642 2643 2644 2645
        TCGv t0;
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_ext_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2646
    } else
2647
        gen_qemu_ld32s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2648 2649
}

2650
static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2651
{
2652
    gen_qemu_ld64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2653
    if (unlikely(flags & 1))
2654
        tcg_gen_bswap_i64(arg0, arg0);
A
aurel32 已提交
2655 2656
}

2657
static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2658
{
2659
    gen_qemu_st8_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2660 2661
}

2662
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2663 2664
{
    if (unlikely(flags & 1)) {
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_ext16u_i32(t0, t0);
        tcg_gen_bswap16_i32(t0, t0);
        t1 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_extu_i32_tl(t1, t0);
        tcg_temp_free(t0);
        gen_qemu_st16_ppc64(t1, arg1, flags);
        tcg_temp_free(t1);
A
aurel32 已提交
2675
    } else
2676
        gen_qemu_st16_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2677 2678
}

2679
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2680 2681
{
    if (unlikely(flags & 1)) {
2682 2683 2684 2685 2686 2687 2688 2689 2690
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        t1 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_extu_i32_tl(t1, t0);
        tcg_temp_free(t0);
        gen_qemu_st32_ppc64(t1, arg1, flags);
        tcg_temp_free(t1);
A
aurel32 已提交
2691
    } else
2692
        gen_qemu_st32_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2693 2694
}

2695
static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2696 2697
{
    if (unlikely(flags & 1)) {
2698 2699 2700 2701
        TCGv t0 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_bswap_i64(t0, arg0);
        gen_qemu_st64_ppc64(t0, arg1, flags);
        tcg_temp_free(t0);
A
aurel32 已提交
2702
    } else
2703
        gen_qemu_st64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2704 2705 2706 2707 2708
}


#else /* defined(TARGET_PPC64) */
#define GEN_QEMU_LD_PPC32(width)                                                 \
2709
static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2710
{                                                                                \
2711
    tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2712 2713 2714 2715 2716 2717 2718 2719 2720 2721
}
GEN_QEMU_LD_PPC32(8u)
GEN_QEMU_LD_PPC32(8s)
GEN_QEMU_LD_PPC32(16u)
GEN_QEMU_LD_PPC32(16s)
GEN_QEMU_LD_PPC32(32u)
GEN_QEMU_LD_PPC32(32s)
GEN_QEMU_LD_PPC32(64)

#define GEN_QEMU_ST_PPC32(width)                                                 \
2722
static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2723
{                                                                                \
2724
    tcg_gen_qemu_st##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2725 2726 2727 2728 2729 2730
}
GEN_QEMU_ST_PPC32(8)
GEN_QEMU_ST_PPC32(16)
GEN_QEMU_ST_PPC32(32)
GEN_QEMU_ST_PPC32(64)

2731
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2732
{
2733
    gen_qemu_ld8u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2734 2735
}

2736
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2737
{
2738
    gen_qemu_ld8s_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2739 2740
}

2741
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2742
{
2743
    gen_qemu_ld16u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2744
    if (unlikely(flags & 1))
2745
        tcg_gen_bswap16_i32(arg0, arg0);
A
aurel32 已提交
2746 2747
}

2748
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2749 2750
{
    if (unlikely(flags & 1)) {
2751 2752 2753
        gen_qemu_ld16u_ppc32(arg0, arg1, flags);
        tcg_gen_bswap16_i32(arg0, arg0);
        tcg_gen_ext16s_i32(arg0, arg0);
A
aurel32 已提交
2754
    } else
2755
        gen_qemu_ld16s_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2756 2757
}

2758
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2759
{
2760
    gen_qemu_ld32u_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2761
    if (unlikely(flags & 1))
2762
        tcg_gen_bswap_i32(arg0, arg0);
A
aurel32 已提交
2763 2764
}

2765
static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2766
{
2767
    gen_qemu_ld64_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2768
    if (unlikely(flags & 1))
2769
        tcg_gen_bswap_i64(arg0, arg0);
A
aurel32 已提交
2770 2771
}

2772
static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2773
{
2774
    gen_qemu_st8_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2775 2776
}

2777
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2778 2779 2780
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);
2781
        tcg_gen_ext16u_i32(temp, arg0);
A
aurel32 已提交
2782
        tcg_gen_bswap16_i32(temp, temp);
2783
        gen_qemu_st16_ppc32(temp, arg1, flags >> 1);
A
aurel32 已提交
2784
        tcg_temp_free(temp);
A
aurel32 已提交
2785
    } else
2786
        gen_qemu_st16_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2787 2788
}

2789
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2790 2791 2792
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);
2793 2794
        tcg_gen_bswap_i32(temp, arg0);
        gen_qemu_st32_ppc32(temp, arg1, flags >> 1);
A
aurel32 已提交
2795
        tcg_temp_free(temp);
A
aurel32 已提交
2796
    } else
2797
        gen_qemu_st32_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2798 2799
}

2800
static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2801 2802 2803
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I64);
2804 2805
        tcg_gen_bswap_i64(temp, arg0);
        gen_qemu_st64_ppc32(temp, arg1, flags >> 1);
A
aurel32 已提交
2806
        tcg_temp_free(temp);
A
aurel32 已提交
2807
    } else
2808
        gen_qemu_st64_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2809 2810 2811 2812
}

#endif

2813 2814
#define GEN_LD(width, opc, type)                                              \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2815
{                                                                             \
A
aurel32 已提交
2816 2817 2818 2819
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_imm_index(EA, ctx, 0);                                           \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2820 2821
}

2822 2823
#define GEN_LDU(width, opc, type)                                             \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2824
{                                                                             \
A
aurel32 已提交
2825
    TCGv EA;                                                                  \
2826 2827
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2828
        GEN_EXCP_INVAL(ctx);                                                  \
2829
        return;                                                               \
2830
    }                                                                         \
A
aurel32 已提交
2831
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
J
j_mayer 已提交
2832
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2833
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2834
    else                                                                      \
A
aurel32 已提交
2835 2836 2837 2838
        gen_addr_imm_index(EA, ctx, 0);                                       \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2839 2840
}

2841 2842
#define GEN_LDUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2843
{                                                                             \
A
aurel32 已提交
2844
    TCGv EA;                                                                  \
2845 2846
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2847
        GEN_EXCP_INVAL(ctx);                                                  \
2848
        return;                                                               \
2849
    }                                                                         \
A
aurel32 已提交
2850 2851 2852 2853 2854
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2855 2856
}

2857 2858
#define GEN_LDX(width, opc2, opc3, type)                                      \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2859
{                                                                             \
A
aurel32 已提交
2860 2861 2862 2863
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2864 2865
}

2866 2867 2868 2869 2870
#define GEN_LDS(width, op, type)                                              \
GEN_LD(width, op | 0x20, type);                                               \
GEN_LDU(width, op | 0x21, type);                                              \
GEN_LDUX(width, 0x17, op | 0x01, type);                                       \
GEN_LDX(width, 0x17, op | 0x00, type)
B
bellard 已提交
2871 2872

/* lbz lbzu lbzux lbzx */
A
aurel32 已提交
2873
GEN_LDS(8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2874
/* lha lhau lhaux lhax */
A
aurel32 已提交
2875
GEN_LDS(16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2876
/* lhz lhzu lhzux lhzx */
A
aurel32 已提交
2877
GEN_LDS(16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2878
/* lwz lwzu lwzux lwzx */
A
aurel32 已提交
2879
GEN_LDS(32u, 0x00, PPC_INTEGER);
2880 2881
#if defined(TARGET_PPC64)
/* lwaux */
A
aurel32 已提交
2882
GEN_LDUX(32s, 0x15, 0x0B, PPC_64B);
2883
/* lwax */
A
aurel32 已提交
2884
GEN_LDX(32s, 0x15, 0x0A, PPC_64B);
2885
/* ldux */
A
aurel32 已提交
2886
GEN_LDUX(64, 0x15, 0x01, PPC_64B);
2887
/* ldx */
A
aurel32 已提交
2888
GEN_LDX(64, 0x15, 0x00, PPC_64B);
2889 2890
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
A
aurel32 已提交
2891
    TCGv EA;
2892 2893 2894
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2895
            GEN_EXCP_INVAL(ctx);
2896 2897 2898
            return;
        }
    }
A
aurel32 已提交
2899 2900
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_imm_index(EA, ctx, 0x03);
2901 2902
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2903
        gen_qemu_ld32s(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
2904 2905
    } else {
        /* ld - ldu */
A
aurel32 已提交
2906
        gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
2907 2908
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2909 2910
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2911
}
2912 2913 2914 2915 2916 2917 2918
/* lq */
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    int ra, rd;
A
aurel32 已提交
2919
    TCGv EA;
2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936

    /* Restore CPU state */
    if (unlikely(ctx->supervisor == 0)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
        GEN_EXCP_INVAL(ctx);
        return;
    }
    if (unlikely(ctx->mem_idx & 1)) {
        /* Little-endian mode is not handled */
        GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
        return;
    }
A
aurel32 已提交
2937 2938 2939 2940 2941 2942
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_imm_index(EA, ctx, 0x0F);
    gen_qemu_ld64(cpu_gpr[rd], EA, ctx->mem_idx);
    tcg_gen_addi_tl(EA, EA, 8);
    gen_qemu_ld64(cpu_gpr[rd+1], EA, ctx->mem_idx);
    tcg_temp_free(EA);
2943 2944
#endif
}
2945
#endif
B
bellard 已提交
2946 2947

/***                              Integer store                            ***/
2948 2949
#define GEN_ST(width, opc, type)                                              \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2950
{                                                                             \
A
aurel32 已提交
2951 2952 2953 2954
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_imm_index(EA, ctx, 0);                                           \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);       \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2955 2956
}

2957 2958
#define GEN_STU(width, opc, type)                                             \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2959
{                                                                             \
A
aurel32 已提交
2960
    TCGv EA;                                                                  \
2961
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2962
        GEN_EXCP_INVAL(ctx);                                                  \
2963
        return;                                                               \
2964
    }                                                                         \
A
aurel32 已提交
2965
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
J
j_mayer 已提交
2966
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2967
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2968
    else                                                                      \
A
aurel32 已提交
2969 2970 2971 2972
        gen_addr_imm_index(EA, ctx, 0);                                       \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2973 2974
}

2975 2976
#define GEN_STUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
B
bellard 已提交
2977
{                                                                             \
A
aurel32 已提交
2978
    TCGv EA;                                                                  \
2979
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2980
        GEN_EXCP_INVAL(ctx);                                                  \
2981
        return;                                                               \
2982
    }                                                                         \
A
aurel32 已提交
2983 2984 2985 2986 2987
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2988 2989
}

2990 2991
#define GEN_STX(width, opc2, opc3, type)                                      \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2992
{                                                                             \
A
aurel32 已提交
2993 2994 2995 2996
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2997 2998
}

2999 3000 3001 3002 3003
#define GEN_STS(width, op, type)                                              \
GEN_ST(width, op | 0x20, type);                                               \
GEN_STU(width, op | 0x21, type);                                              \
GEN_STUX(width, 0x17, op | 0x01, type);                                       \
GEN_STX(width, 0x17, op | 0x00, type)
B
bellard 已提交
3004 3005

/* stb stbu stbux stbx */
A
aurel32 已提交
3006
GEN_STS(8, 0x06, PPC_INTEGER);
B
bellard 已提交
3007
/* sth sthu sthux sthx */
A
aurel32 已提交
3008
GEN_STS(16, 0x0C, PPC_INTEGER);
B
bellard 已提交
3009
/* stw stwu stwux stwx */
A
aurel32 已提交
3010
GEN_STS(32, 0x04, PPC_INTEGER);
3011
#if defined(TARGET_PPC64)
A
aurel32 已提交
3012 3013
GEN_STUX(64, 0x15, 0x05, PPC_64B);
GEN_STX(64, 0x15, 0x04, PPC_64B);
3014
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
3015
{
3016
    int rs;
A
aurel32 已提交
3017
    TCGv EA;
3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
        GEN_EXCP_PRIVOPC(ctx);
#else
        /* stq */
        if (unlikely(ctx->supervisor == 0)) {
            GEN_EXCP_PRIVOPC(ctx);
            return;
        }
        if (unlikely(rs & 1)) {
3030
            GEN_EXCP_INVAL(ctx);
3031 3032
            return;
        }
3033 3034 3035 3036 3037
        if (unlikely(ctx->mem_idx & 1)) {
            /* Little-endian mode is not handled */
            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
            return;
        }
A
aurel32 已提交
3038 3039 3040 3041 3042 3043
        EA = tcg_temp_new(TCG_TYPE_TL);
        gen_addr_imm_index(EA, ctx, 0x03);
        gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(cpu_gpr[rs+1], EA, ctx->mem_idx);
        tcg_temp_free(EA);
3044 3045 3046 3047 3048 3049 3050 3051 3052
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
                GEN_EXCP_INVAL(ctx);
                return;
            }
        }
A
aurel32 已提交
3053 3054 3055
        EA = tcg_temp_new(TCG_TYPE_TL);
        gen_addr_imm_index(EA, ctx, 0x03);
        gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
3056
        if (Rc(ctx->opcode))
A
aurel32 已提交
3057 3058
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
3059 3060 3061
    }
}
#endif
B
bellard 已提交
3062 3063
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
A
aurel32 已提交
3064 3065 3066 3067 3068 3069 3070 3071 3072 3073
void always_inline gen_qemu_ld16ur(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    gen_qemu_ld16u(temp, t1, flags);
    tcg_gen_bswap16_i32(temp, temp);
    tcg_gen_extu_i32_tl(t0, temp);
    tcg_temp_free(temp);
}
GEN_LDX(16ur, 0x16, 0x18, PPC_INTEGER);

B
bellard 已提交
3074
/* lwbrx */
A
aurel32 已提交
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084
void always_inline gen_qemu_ld32ur(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    gen_qemu_ld32u(temp, t1, flags);
    tcg_gen_bswap_i32(temp, temp);
    tcg_gen_extu_i32_tl(t0, temp);
    tcg_temp_free(temp);
}
GEN_LDX(32ur, 0x16, 0x10, PPC_INTEGER);

B
bellard 已提交
3085
/* sthbrx */
A
aurel32 已提交
3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096
void always_inline gen_qemu_st16r(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_ext16u_i32(temp, temp);
    tcg_gen_bswap16_i32(temp, temp);
    gen_qemu_st16(temp, t1, flags);
    tcg_temp_free(temp);
}
GEN_STX(16r, 0x16, 0x1C, PPC_INTEGER);

B
bellard 已提交
3097
/* stwbrx */
A
aurel32 已提交
3098 3099 3100 3101 3102 3103 3104 3105 3106
void always_inline gen_qemu_st32r(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_bswap_i32(temp, temp);
    gen_qemu_st32(temp, t1, flags);
    tcg_temp_free(temp);
}
GEN_STX(32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
3107 3108

/***                    Integer load and store multiple                    ***/
3109
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
3110 3111
static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lmw),
3112
};
3113 3114
static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stmw),
3115
};
3116

B
bellard 已提交
3117 3118 3119
/* lmw */
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
3120
    /* NIP cannot be restored if the memory exception comes from an helper */
3121
    gen_update_nip(ctx, ctx->nip - 4);
3122
    gen_addr_imm_index(cpu_T[0], ctx, 0);
3123
    op_ldstm(lmw, rD(ctx->opcode));
B
bellard 已提交
3124 3125 3126 3127 3128
}

/* stmw */
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
3129
    /* NIP cannot be restored if the memory exception comes from an helper */
3130
    gen_update_nip(ctx, ctx->nip - 4);
3131
    gen_addr_imm_index(cpu_T[0], ctx, 0);
3132
    op_ldstm(stmw, rS(ctx->opcode));
B
bellard 已提交
3133 3134 3135
}

/***                    Integer load and store strings                     ***/
3136 3137
#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
3138 3139 3140 3141 3142 3143 3144 3145 3146
/* string load & stores are by definition endian-safe */
#define gen_op_lswi_le_raw       gen_op_lswi_raw
#define gen_op_lswi_le_user      gen_op_lswi_user
#define gen_op_lswi_le_kernel    gen_op_lswi_kernel
#define gen_op_lswi_le_hypv      gen_op_lswi_hypv
#define gen_op_lswi_le_64_raw    gen_op_lswi_raw
#define gen_op_lswi_le_64_user   gen_op_lswi_user
#define gen_op_lswi_le_64_kernel gen_op_lswi_kernel
#define gen_op_lswi_le_64_hypv   gen_op_lswi_hypv
3147 3148
static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswi),
3149
};
3150 3151 3152 3153 3154 3155 3156 3157
#define gen_op_lswx_le_raw       gen_op_lswx_raw
#define gen_op_lswx_le_user      gen_op_lswx_user
#define gen_op_lswx_le_kernel    gen_op_lswx_kernel
#define gen_op_lswx_le_hypv      gen_op_lswx_hypv
#define gen_op_lswx_le_64_raw    gen_op_lswx_raw
#define gen_op_lswx_le_64_user   gen_op_lswx_user
#define gen_op_lswx_le_64_kernel gen_op_lswx_kernel
#define gen_op_lswx_le_64_hypv   gen_op_lswx_hypv
3158 3159
static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswx),
3160
};
3161 3162 3163 3164 3165 3166 3167 3168
#define gen_op_stsw_le_raw       gen_op_stsw_raw
#define gen_op_stsw_le_user      gen_op_stsw_user
#define gen_op_stsw_le_kernel    gen_op_stsw_kernel
#define gen_op_stsw_le_hypv      gen_op_stsw_hypv
#define gen_op_stsw_le_64_raw    gen_op_stsw_raw
#define gen_op_stsw_le_64_user   gen_op_stsw_user
#define gen_op_stsw_le_64_kernel gen_op_stsw_kernel
#define gen_op_stsw_le_64_hypv   gen_op_stsw_hypv
3169 3170
static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stsw),
3171 3172
};

B
bellard 已提交
3173
/* lswi */
3174
/* PowerPC32 specification says we must generate an exception if
3175 3176 3177 3178
 * rA is in the range of registers to be loaded.
 * In an other hand, IBM says this is valid, but rA won't be loaded.
 * For now, I'll follow the spec...
 */
3179
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
B
bellard 已提交
3180 3181 3182
{
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3183
    int ra = rA(ctx->opcode);
B
bellard 已提交
3184 3185 3186 3187 3188
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3189 3190 3191
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
3192 3193
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
3194
        return;
B
bellard 已提交
3195
    }
3196
    /* NIP cannot be restored if the memory exception comes from an helper */
3197
    gen_update_nip(ctx, ctx->nip - 4);
3198
    gen_addr_register(cpu_T[0], ctx);
3199
    tcg_gen_movi_tl(cpu_T[1], nb);
3200
    op_ldsts(lswi, start);
B
bellard 已提交
3201 3202 3203
}

/* lswx */
3204
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
B
bellard 已提交
3205
{
3206 3207 3208
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

3209
    /* NIP cannot be restored if the memory exception comes from an helper */
3210
    gen_update_nip(ctx, ctx->nip - 4);
3211
    gen_addr_reg_index(cpu_T[0], ctx);
3212 3213
    if (ra == 0) {
        ra = rb;
B
bellard 已提交
3214
    }
A
aurel32 已提交
3215
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
3216
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
B
bellard 已提交
3217 3218 3219
}

/* stswi */
3220
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
B
bellard 已提交
3221
{
B
bellard 已提交
3222 3223
    int nb = NB(ctx->opcode);

3224
    /* NIP cannot be restored if the memory exception comes from an helper */
3225
    gen_update_nip(ctx, ctx->nip - 4);
3226
    gen_addr_register(cpu_T[0], ctx);
B
bellard 已提交
3227 3228
    if (nb == 0)
        nb = 32;
3229
    tcg_gen_movi_tl(cpu_T[1], nb);
3230
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
3231 3232 3233
}

/* stswx */
3234
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
B
bellard 已提交
3235
{
3236
    /* NIP cannot be restored if the memory exception comes from an helper */
3237
    gen_update_nip(ctx, ctx->nip - 4);
3238
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3239
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
3240
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
3241 3242 3243 3244
}

/***                        Memory synchronisation                         ***/
/* eieio */
3245
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
B
bellard 已提交
3246 3247 3248 3249
{
}

/* isync */
3250
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
B
bellard 已提交
3251
{
3252
    GEN_STOP(ctx);
B
bellard 已提交
3253 3254
}

3255 3256
#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
3257 3258
static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lwarx),
3259
};
3260 3261
static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stwcx),
B
bellard 已提交
3262
};
3263

3264
/* lwarx */
3265
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
B
bellard 已提交
3266
{
3267 3268
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3269
    gen_addr_reg_index(cpu_T[0], ctx);
B
bellard 已提交
3270
    op_lwarx();
A
aurel32 已提交
3271
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
B
bellard 已提交
3272 3273 3274
}

/* stwcx. */
3275
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
B
bellard 已提交
3276
{
3277 3278
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3279
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3280
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
3281
    op_stwcx();
B
bellard 已提交
3282 3283
}

J
j_mayer 已提交
3284 3285 3286
#if defined(TARGET_PPC64)
#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
3287 3288
static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ldarx),
J
j_mayer 已提交
3289
};
3290 3291
static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stdcx),
J
j_mayer 已提交
3292 3293 3294
};

/* ldarx */
3295
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
J
j_mayer 已提交
3296
{
3297 3298
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3299
    gen_addr_reg_index(cpu_T[0], ctx);
J
j_mayer 已提交
3300
    op_ldarx();
A
aurel32 已提交
3301
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
J
j_mayer 已提交
3302 3303 3304
}

/* stdcx. */
3305
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
J
j_mayer 已提交
3306
{
3307 3308
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3309
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3310
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
3311 3312 3313 3314
    op_stdcx();
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3315
/* sync */
3316
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
B
bellard 已提交
3317 3318 3319
{
}

3320 3321 3322 3323
/* wait */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
{
    /* Stop translation, as the CPU is supposed to sleep from now */
3324 3325
    gen_op_wait();
    GEN_EXCP(ctx, EXCP_HLT, 1);
3326 3327
}

B
bellard 已提交
3328
/***                         Floating-point load                           ***/
3329 3330
#define GEN_LDF(width, opc, type)                                             \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
3331
{                                                                             \
3332
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3333
        GEN_EXCP_NO_FP(ctx);                                                  \
3334 3335
        return;                                                               \
    }                                                                         \
3336
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
3337
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3338
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
3339 3340
}

3341 3342
#define GEN_LDUF(width, opc, type)                                            \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
3343
{                                                                             \
3344
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3345
        GEN_EXCP_NO_FP(ctx);                                                  \
3346 3347
        return;                                                               \
    }                                                                         \
3348
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3349
        GEN_EXCP_INVAL(ctx);                                                  \
3350
        return;                                                               \
3351
    }                                                                         \
3352
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
3353
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3354
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
3355
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3356 3357
}

3358 3359
#define GEN_LDUXF(width, opc, type)                                           \
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
B
bellard 已提交
3360
{                                                                             \
3361
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3362
        GEN_EXCP_NO_FP(ctx);                                                  \
3363 3364
        return;                                                               \
    }                                                                         \
3365
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3366
        GEN_EXCP_INVAL(ctx);                                                  \
3367
        return;                                                               \
3368
    }                                                                         \
3369
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
3370
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3371
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
3372
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3373 3374
}

3375 3376
#define GEN_LDXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
3377
{                                                                             \
3378
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3379
        GEN_EXCP_NO_FP(ctx);                                                  \
3380 3381
        return;                                                               \
    }                                                                         \
3382
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
3383
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3384
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
3385 3386
}

3387
#define GEN_LDFS(width, op, type)                                             \
3388
OP_LD_TABLE(width);                                                           \
3389 3390 3391 3392
GEN_LDF(width, op | 0x20, type);                                              \
GEN_LDUF(width, op | 0x21, type);                                             \
GEN_LDUXF(width, op | 0x01, type);                                            \
GEN_LDXF(width, 0x17, op | 0x00, type)
B
bellard 已提交
3393 3394

/* lfd lfdu lfdux lfdx */
3395
GEN_LDFS(fd, 0x12, PPC_FLOAT);
B
bellard 已提交
3396
/* lfs lfsu lfsux lfsx */
3397
GEN_LDFS(fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3398 3399

/***                         Floating-point store                          ***/
3400 3401
#define GEN_STF(width, opc, type)                                             \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
3402
{                                                                             \
3403
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3404
        GEN_EXCP_NO_FP(ctx);                                                  \
3405 3406
        return;                                                               \
    }                                                                         \
3407
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
A
aurel32 已提交
3408
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3409
    op_ldst(st##width);                                                       \
B
bellard 已提交
3410 3411
}

3412 3413
#define GEN_STUF(width, opc, type)                                            \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
3414
{                                                                             \
3415
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3416
        GEN_EXCP_NO_FP(ctx);                                                  \
3417 3418
        return;                                                               \
    }                                                                         \
3419
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3420
        GEN_EXCP_INVAL(ctx);                                                  \
3421
        return;                                                               \
3422
    }                                                                         \
3423
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
A
aurel32 已提交
3424
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3425
    op_ldst(st##width);                                                       \
A
aurel32 已提交
3426
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3427 3428
}

3429 3430
#define GEN_STUXF(width, opc, type)                                           \
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
B
bellard 已提交
3431
{                                                                             \
3432
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3433
        GEN_EXCP_NO_FP(ctx);                                                  \
3434 3435
        return;                                                               \
    }                                                                         \
3436
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3437
        GEN_EXCP_INVAL(ctx);                                                  \
3438
        return;                                                               \
3439
    }                                                                         \
3440
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
3441
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3442
    op_ldst(st##width);                                                       \
A
aurel32 已提交
3443
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3444 3445
}

3446 3447
#define GEN_STXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
3448
{                                                                             \
3449
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3450
        GEN_EXCP_NO_FP(ctx);                                                  \
3451 3452
        return;                                                               \
    }                                                                         \
3453
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
3454
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3455
    op_ldst(st##width);                                                       \
B
bellard 已提交
3456 3457
}

3458
#define GEN_STFS(width, op, type)                                             \
3459
OP_ST_TABLE(width);                                                           \
3460 3461 3462 3463
GEN_STF(width, op | 0x20, type);                                              \
GEN_STUF(width, op | 0x21, type);                                             \
GEN_STUXF(width, op | 0x01, type);                                            \
GEN_STXF(width, 0x17, op | 0x00, type)
B
bellard 已提交
3464 3465

/* stfd stfdu stfdux stfdx */
3466
GEN_STFS(fd, 0x16, PPC_FLOAT);
B
bellard 已提交
3467
/* stfs stfsu stfsux stfsx */
3468
GEN_STFS(fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3469 3470 3471

/* Optional: */
/* stfiwx */
J
j_mayer 已提交
3472 3473
OP_ST_TABLE(fiw);
GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3474 3475

/***                                Branch                                 ***/
3476 3477
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
                                       target_ulong dest)
3478 3479 3480
{
    TranslationBlock *tb;
    tb = ctx->tb;
3481 3482 3483 3484
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3485
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3486
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3487
        tcg_gen_goto_tb(n);
3488
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
B
bellard 已提交
3489
        tcg_gen_exit_tb((long)tb + n);
3490
    } else {
3491
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
                 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
                GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
                gen_update_nip(ctx, dest);
                gen_op_debug();
            }
        }
B
bellard 已提交
3506
        tcg_gen_exit_tb(0);
3507
    }
B
bellard 已提交
3508 3509
}

3510
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3511 3512
{
#if defined(TARGET_PPC64)
3513 3514
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3515 3516
    else
#endif
3517
        tcg_gen_movi_tl(cpu_lr, nip);
3518 3519
}

B
bellard 已提交
3520 3521 3522
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
3523
    target_ulong li, target;
B
bellard 已提交
3524

3525
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3526
    /* sign extend LI */
3527
#if defined(TARGET_PPC64)
3528 3529 3530
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3531
#endif
3532
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3533
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3534
        target = ctx->nip + li - 4;
B
bellard 已提交
3535
    else
3536
        target = li;
3537 3538
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3539
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3540 3541
}

3542 3543 3544 3545
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

3546
static always_inline void gen_bcond (DisasContext *ctx, int type)
3547 3548
{
    uint32_t bo = BO(ctx->opcode);
3549 3550
    int l1 = gen_new_label();
    TCGv target;
3551

3552
    ctx->exception = POWERPC_EXCP_BRANCH;
3553 3554 3555 3556 3557 3558
    if (type == BCOND_LR || type == BCOND_CTR) {
        target = tcg_temp_local_new(TCG_TYPE_TL);
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3559
    }
3560 3561
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3562 3563 3564 3565 3566 3567 3568 3569 3570
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
        TCGv temp = tcg_temp_new(TCG_TYPE_TL);
        if (unlikely(type == BCOND_CTR)) {
            GEN_EXCP_INVAL(ctx);
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3571
#if defined(TARGET_PPC64)
3572 3573 3574
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3575
#endif
3576 3577 3578 3579 3580
            tcg_gen_mov_tl(temp, cpu_ctr);
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3581
        }
3582 3583 3584 3585 3586 3587 3588
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);

3589
        if (bo & 0x8) {
3590 3591
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3592
        } else {
3593 3594
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3595 3596
        }
    }
3597
    if (type == BCOND_IM) {
3598 3599 3600 3601 3602 3603 3604

        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
        } else {
            gen_goto_tb(ctx, 0, li);
        }
B
bellard 已提交
3605
        gen_set_label(l1);
3606
        gen_goto_tb(ctx, 1, ctx->nip);
3607
    } else {
3608
#if defined(TARGET_PPC64)
3609 3610 3611 3612 3613 3614 3615 3616 3617 3618
        if (!(ctx->sf_mode))
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
        else
#endif
            tcg_gen_andi_tl(cpu_nip, target, ~3);
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
#if defined(TARGET_PPC64)
        if (!(ctx->sf_mode))
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3619 3620
        else
#endif
3621
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3622
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3623
    }
3624 3625 3626
}

GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3627
{
3628 3629 3630 3631
    gen_bcond(ctx, BCOND_IM);
}

GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3632
{
3633 3634 3635 3636
    gen_bcond(ctx, BCOND_CTR);
}

GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3637
{
3638 3639
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3640 3641

/***                      Condition register logical                       ***/
3642 3643
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                   \
B
bellard 已提交
3644
{                                                                             \
3645 3646
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
3647
    TCGv t0, t1;                                                              \
3648
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3649
    t0 = tcg_temp_new(TCG_TYPE_I32);                                          \
3650
    if (sh > 0)                                                               \
3651
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3652
    else if (sh < 0)                                                          \
3653
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3654
    else                                                                      \
3655 3656
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
    t1 = tcg_temp_new(TCG_TYPE_I32);                                          \
3657 3658
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3659
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3660
    else if (sh < 0)                                                          \
3661
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3662
    else                                                                      \
3663 3664
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3665
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3666 3667 3668 3669 3670
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
    tcg_temp_free(t0);                                                        \
    tcg_temp_free(t1);                                                        \
B
bellard 已提交
3671 3672 3673
}

/* crand */
3674
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3675
/* crandc */
3676
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3677
/* creqv */
3678
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3679
/* crnand */
3680
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3681
/* crnor */
3682
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3683
/* cror */
3684
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3685
/* crorc */
3686
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3687
/* crxor */
3688
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
bellard 已提交
3689 3690 3691
/* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{
A
aurel32 已提交
3692
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3693 3694 3695 3696
}

/***                           System linkage                              ***/
/* rfi (supervisor only) */
3697
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
B
bellard 已提交
3698
{
3699
#if defined(CONFIG_USER_ONLY)
3700
    GEN_EXCP_PRIVOPC(ctx);
3701 3702
#else
    /* Restore CPU state */
3703
    if (unlikely(!ctx->supervisor)) {
3704
        GEN_EXCP_PRIVOPC(ctx);
3705
        return;
3706
    }
3707
    gen_op_rfi();
3708
    GEN_SYNC(ctx);
3709
#endif
B
bellard 已提交
3710 3711
}

J
j_mayer 已提交
3712
#if defined(TARGET_PPC64)
3713
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
J
j_mayer 已提交
3714 3715
{
#if defined(CONFIG_USER_ONLY)
3716
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3717 3718 3719
#else
    /* Restore CPU state */
    if (unlikely(!ctx->supervisor)) {
3720
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3721 3722
        return;
    }
3723
    gen_op_rfid();
3724
    GEN_SYNC(ctx);
J
j_mayer 已提交
3725 3726 3727
#endif
}

J
j_mayer 已提交
3728
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    /* Restore CPU state */
    if (unlikely(ctx->supervisor <= 1)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    gen_op_hrfid();
    GEN_SYNC(ctx);
#endif
}
#endif

B
bellard 已提交
3744
/* sc */
3745 3746 3747 3748 3749
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
3750
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
B
bellard 已提交
3751
{
3752 3753 3754
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
3755
    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3756 3757 3758 3759
}

/***                                Trap                                   ***/
/* tw */
3760
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
B
bellard 已提交
3761
{
A
aurel32 已提交
3762 3763
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3764
    /* Update the nip since this might generate a trap exception */
3765
    gen_update_nip(ctx, ctx->nip);
3766
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3767 3768 3769 3770 3771
}

/* twi */
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
A
aurel32 已提交
3772
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3773
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3774 3775
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3776
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3777 3778
}

3779 3780 3781 3782
#if defined(TARGET_PPC64)
/* td */
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
{
A
aurel32 已提交
3783 3784
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3785 3786 3787 3788 3789 3790 3791 3792
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
    gen_op_td(TO(ctx->opcode));
}

/* tdi */
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
A
aurel32 已提交
3793
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3794
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3795 3796 3797 3798 3799 3800
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
    gen_op_td(TO(ctx->opcode));
}
#endif

B
bellard 已提交
3801 3802 3803 3804
/***                          Processor control                            ***/
/* mcrxr */
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{
A
aurel32 已提交
3805 3806
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3807
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3808 3809 3810
}

/* mfcr */
3811
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
B
bellard 已提交
3812
{
3813
    uint32_t crm, crn;
3814

3815 3816 3817 3818
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
        if (likely((crm ^ (crm - 1)) == 0)) {
            crn = ffs(crm);
3819
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3820
        }
3821
    } else {
3822
        tcg_gen_helper_1_0(helper_load_cr, cpu_gpr[rD(ctx->opcode)]);
3823
    }
B
bellard 已提交
3824 3825 3826 3827 3828
}

/* mfmsr */
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
{
3829
#if defined(CONFIG_USER_ONLY)
3830
    GEN_EXCP_PRIVREG(ctx);
3831
#else
3832
    if (unlikely(!ctx->supervisor)) {
3833
        GEN_EXCP_PRIVREG(ctx);
3834
        return;
3835
    }
A
aurel32 已提交
3836
    gen_op_load_msr();
A
aurel32 已提交
3837
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3838
#endif
B
bellard 已提交
3839 3840
}

J
j_mayer 已提交
3841
#if 1
3842
#define SPR_NOACCESS ((void *)(-1UL))
3843 3844 3845 3846 3847 3848 3849 3850 3851
#else
static void spr_noaccess (void *opaque, int sprn)
{
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
}
#define SPR_NOACCESS (&spr_noaccess)
#endif

B
bellard 已提交
3852
/* mfspr */
3853
static always_inline void gen_op_mfspr (DisasContext *ctx)
B
bellard 已提交
3854
{
3855
    void (*read_cb)(void *opaque, int sprn);
B
bellard 已提交
3856 3857
    uint32_t sprn = SPR(ctx->opcode);

3858
#if !defined(CONFIG_USER_ONLY)
3859 3860
    if (ctx->supervisor == 2)
        read_cb = ctx->spr_cb[sprn].hea_read;
3861
    else if (ctx->supervisor)
3862 3863
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3864
#endif
3865
        read_cb = ctx->spr_cb[sprn].uea_read;
3866 3867
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
3868
            (*read_cb)(ctx, sprn);
A
aurel32 已提交
3869
            tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3870 3871
        } else {
            /* Privilege exception */
3872 3873 3874 3875 3876 3877
            /* This is a hack to avoid warnings when running Linux:
             * this OS breaks the PowerPC virtualisation model,
             * allowing userland application to read the PVR
             */
            if (sprn != SPR_PVR) {
                if (loglevel != 0) {
3878
                    fprintf(logfile, "Trying to read privileged spr %d %03x at "
J
j_mayer 已提交
3879
                            ADDRX "\n", sprn, sprn, ctx->nip);
3880
                }
J
j_mayer 已提交
3881 3882
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
                       sprn, sprn, ctx->nip);
3883
            }
3884
            GEN_EXCP_PRIVREG(ctx);
B
bellard 已提交
3885
        }
3886 3887
    } else {
        /* Not defined */
J
j_mayer 已提交
3888
        if (loglevel != 0) {
J
j_mayer 已提交
3889 3890
            fprintf(logfile, "Trying to read invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3891
        }
J
j_mayer 已提交
3892 3893
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3894 3895
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3896 3897 3898
    }
}

3899
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
B
bellard 已提交
3900
{
3901
    gen_op_mfspr(ctx);
3902
}
3903 3904

/* mftb */
3905
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3906 3907
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3908 3909 3910
}

/* mtcrf */
3911
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
B
bellard 已提交
3912
{
3913
    uint32_t crm, crn;
3914

3915 3916 3917
    crm = CRM(ctx->opcode);
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
        crn = ffs(crm);
3918 3919
        tcg_gen_shri_i32(cpu_crf[7 - crn], cpu_gpr[rS(ctx->opcode)], crn * 4);
        tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3920
    } else {
3921 3922 3923
        TCGv t0 = tcg_const_tl(crm);
        tcg_gen_helper_0_2(helper_store_cr, cpu_gpr[rS(ctx->opcode)], t0);
        tcg_temp_free(t0);
3924
    }
B
bellard 已提交
3925 3926 3927
}

/* mtmsr */
J
j_mayer 已提交
3928
#if defined(TARGET_PPC64)
3929
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
J
j_mayer 已提交
3930 3931
{
#if defined(CONFIG_USER_ONLY)
3932
    GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3933 3934
#else
    if (unlikely(!ctx->supervisor)) {
3935
        GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3936 3937
        return;
    }
A
aurel32 已提交
3938
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3939 3940 3941 3942
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3943 3944 3945 3946
        /* XXX: we need to update nip before the store
         *      if we enter power saving mode, we will exit the loop
         *      directly from ppc_store_msr
         */
3947
        gen_update_nip(ctx, ctx->nip);
A
aurel32 已提交
3948
        gen_op_store_msr();
3949 3950
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
3951
        ctx->exception = POWERPC_EXCP_STOP;
3952
    }
J
j_mayer 已提交
3953 3954 3955 3956
#endif
}
#endif

B
bellard 已提交
3957 3958
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
3959
#if defined(CONFIG_USER_ONLY)
3960
    GEN_EXCP_PRIVREG(ctx);
3961
#else
3962
    if (unlikely(!ctx->supervisor)) {
3963
        GEN_EXCP_PRIVREG(ctx);
3964
        return;
3965
    }
A
aurel32 已提交
3966
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3967 3968 3969 3970
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3971 3972 3973 3974
        /* XXX: we need to update nip before the store
         *      if we enter power saving mode, we will exit the loop
         *      directly from ppc_store_msr
         */
3975
        gen_update_nip(ctx, ctx->nip);
3976
#if defined(TARGET_PPC64)
3977
        if (!ctx->sf_mode)
A
aurel32 已提交
3978
            gen_op_store_msr_32();
3979
        else
3980
#endif
A
aurel32 已提交
3981
            gen_op_store_msr();
3982 3983
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsrd is not always defined as context-synchronizing */
3984
        ctx->exception = POWERPC_EXCP_STOP;
3985
    }
3986
#endif
B
bellard 已提交
3987 3988 3989 3990 3991
}

/* mtspr */
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
{
3992
    void (*write_cb)(void *opaque, int sprn);
B
bellard 已提交
3993 3994
    uint32_t sprn = SPR(ctx->opcode);

3995
#if !defined(CONFIG_USER_ONLY)
3996 3997
    if (ctx->supervisor == 2)
        write_cb = ctx->spr_cb[sprn].hea_write;
3998
    else if (ctx->supervisor)
3999 4000
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
4001
#endif
4002
        write_cb = ctx->spr_cb[sprn].uea_write;
4003 4004
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4005
            tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4006 4007 4008
            (*write_cb)(ctx, sprn);
        } else {
            /* Privilege exception */
J
j_mayer 已提交
4009
            if (loglevel != 0) {
J
j_mayer 已提交
4010 4011
                fprintf(logfile, "Trying to write privileged spr %d %03x at "
                        ADDRX "\n", sprn, sprn, ctx->nip);
4012
            }
J
j_mayer 已提交
4013 4014
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
                   sprn, sprn, ctx->nip);
4015
            GEN_EXCP_PRIVREG(ctx);
4016
        }
4017 4018
    } else {
        /* Not defined */
J
j_mayer 已提交
4019
        if (loglevel != 0) {
J
j_mayer 已提交
4020 4021
            fprintf(logfile, "Trying to write invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
4022
        }
J
j_mayer 已提交
4023 4024
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
4025 4026
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4027 4028 4029 4030 4031
    }
}

/***                         Cache management                              ***/
/* dcbf */
4032
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
B
bellard 已提交
4033
{
J
j_mayer 已提交
4034
    /* XXX: specification says this is treated as a load by the MMU */
4035 4036 4037 4038
    TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(t0, ctx);
    gen_qemu_ld8u(t0, t0, ctx->mem_idx);
    tcg_temp_free(t0);
B
bellard 已提交
4039 4040 4041
}

/* dcbi (Supervisor only) */
4042
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
B
bellard 已提交
4043
{
4044
#if defined(CONFIG_USER_ONLY)
4045
    GEN_EXCP_PRIVOPC(ctx);
4046
#else
A
aurel32 已提交
4047
    TCGv EA, val;
4048
    if (unlikely(!ctx->supervisor)) {
4049
        GEN_EXCP_PRIVOPC(ctx);
4050
        return;
4051
    }
A
aurel32 已提交
4052 4053
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(EA, ctx);
A
aurel32 已提交
4054
    val = tcg_temp_new(TCG_TYPE_TL);
4055
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4056 4057 4058 4059
    gen_qemu_ld8u(val, EA, ctx->mem_idx);
    gen_qemu_st8(val, EA, ctx->mem_idx);
    tcg_temp_free(val);
    tcg_temp_free(EA);
4060
#endif
B
bellard 已提交
4061 4062 4063
}

/* dcdst */
4064
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
B
bellard 已提交
4065
{
4066
    /* XXX: specification say this is treated as a load by the MMU */
4067 4068 4069 4070
    TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(t0, ctx);
    gen_qemu_ld8u(t0, t0, ctx->mem_idx);
    tcg_temp_free(t0);
B
bellard 已提交
4071 4072 4073
}

/* dcbt */
4074
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
B
bellard 已提交
4075
{
4076
    /* interpreted as no-op */
4077 4078 4079
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4080 4081 4082
}

/* dcbtst */
4083
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
B
bellard 已提交
4084
{
4085
    /* interpreted as no-op */
4086 4087 4088
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4089 4090 4091
}

/* dcbz */
4092
#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
4093 4094
static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
    /* 32 bytes cache line size */
4095
    {
4096 4097 4098 4099 4100 4101 4102 4103 4104
#define gen_op_dcbz_l32_le_raw        gen_op_dcbz_l32_raw
#define gen_op_dcbz_l32_le_user       gen_op_dcbz_l32_user
#define gen_op_dcbz_l32_le_kernel     gen_op_dcbz_l32_kernel
#define gen_op_dcbz_l32_le_hypv       gen_op_dcbz_l32_hypv
#define gen_op_dcbz_l32_le_64_raw     gen_op_dcbz_l32_64_raw
#define gen_op_dcbz_l32_le_64_user    gen_op_dcbz_l32_64_user
#define gen_op_dcbz_l32_le_64_kernel  gen_op_dcbz_l32_64_kernel
#define gen_op_dcbz_l32_le_64_hypv    gen_op_dcbz_l32_64_hypv
        GEN_MEM_FUNCS(dcbz_l32),
4105
    },
4106
    /* 64 bytes cache line size */
4107
    {
4108 4109 4110 4111 4112 4113 4114 4115 4116
#define gen_op_dcbz_l64_le_raw        gen_op_dcbz_l64_raw
#define gen_op_dcbz_l64_le_user       gen_op_dcbz_l64_user
#define gen_op_dcbz_l64_le_kernel     gen_op_dcbz_l64_kernel
#define gen_op_dcbz_l64_le_hypv       gen_op_dcbz_l64_hypv
#define gen_op_dcbz_l64_le_64_raw     gen_op_dcbz_l64_64_raw
#define gen_op_dcbz_l64_le_64_user    gen_op_dcbz_l64_64_user
#define gen_op_dcbz_l64_le_64_kernel  gen_op_dcbz_l64_64_kernel
#define gen_op_dcbz_l64_le_64_hypv    gen_op_dcbz_l64_64_hypv
        GEN_MEM_FUNCS(dcbz_l64),
4117
    },
4118
    /* 128 bytes cache line size */
4119
    {
4120 4121 4122 4123 4124 4125 4126 4127 4128
#define gen_op_dcbz_l128_le_raw       gen_op_dcbz_l128_raw
#define gen_op_dcbz_l128_le_user      gen_op_dcbz_l128_user
#define gen_op_dcbz_l128_le_kernel    gen_op_dcbz_l128_kernel
#define gen_op_dcbz_l128_le_hypv      gen_op_dcbz_l128_hypv
#define gen_op_dcbz_l128_le_64_raw    gen_op_dcbz_l128_64_raw
#define gen_op_dcbz_l128_le_64_user   gen_op_dcbz_l128_64_user
#define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
#define gen_op_dcbz_l128_le_64_hypv   gen_op_dcbz_l128_64_hypv
        GEN_MEM_FUNCS(dcbz_l128),
4129
    },
4130
    /* tunable cache line size */
4131
    {
4132 4133 4134 4135 4136 4137 4138 4139 4140
#define gen_op_dcbz_le_raw            gen_op_dcbz_raw
#define gen_op_dcbz_le_user           gen_op_dcbz_user
#define gen_op_dcbz_le_kernel         gen_op_dcbz_kernel
#define gen_op_dcbz_le_hypv           gen_op_dcbz_hypv
#define gen_op_dcbz_le_64_raw         gen_op_dcbz_64_raw
#define gen_op_dcbz_le_64_user        gen_op_dcbz_64_user
#define gen_op_dcbz_le_64_kernel      gen_op_dcbz_64_kernel
#define gen_op_dcbz_le_64_hypv        gen_op_dcbz_64_hypv
        GEN_MEM_FUNCS(dcbz),
4141
    },
4142
};
4143

4144 4145
static always_inline void handler_dcbz (DisasContext *ctx,
                                        int dcache_line_size)
4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166
{
    int n;

    switch (dcache_line_size) {
    case 32:
        n = 0;
        break;
    case 64:
        n = 1;
        break;
    case 128:
        n = 2;
        break;
    default:
        n = 3;
        break;
    }
    op_dcbz(n);
}

GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
B
bellard 已提交
4167
{
4168
    gen_addr_reg_index(cpu_T[0], ctx);
4169 4170 4171 4172
    handler_dcbz(ctx, ctx->dcache_line_size);
    gen_op_check_reservation();
}

4173
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
4174
{
4175
    gen_addr_reg_index(cpu_T[0], ctx);
4176 4177 4178 4179
    if (ctx->opcode & 0x00200000)
        handler_dcbz(ctx, ctx->dcache_line_size);
    else
        handler_dcbz(ctx, -1);
B
bellard 已提交
4180
    gen_op_check_reservation();
B
bellard 已提交
4181 4182 4183
}

/* icbi */
4184
#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
#define gen_op_icbi_le_raw       gen_op_icbi_raw
#define gen_op_icbi_le_user      gen_op_icbi_user
#define gen_op_icbi_le_kernel    gen_op_icbi_kernel
#define gen_op_icbi_le_hypv      gen_op_icbi_hypv
#define gen_op_icbi_le_64_raw    gen_op_icbi_64_raw
#define gen_op_icbi_le_64_user   gen_op_icbi_64_user
#define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
#define gen_op_icbi_le_64_hypv   gen_op_icbi_64_hypv
static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(icbi),
4195
};
4196

4197
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
B
bellard 已提交
4198
{
4199 4200
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
4201
    gen_addr_reg_index(cpu_T[0], ctx);
4202
    op_icbi();
B
bellard 已提交
4203 4204 4205 4206
}

/* Optional: */
/* dcba */
4207
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
B
bellard 已提交
4208
{
4209 4210 4211 4212
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4213 4214 4215 4216 4217 4218 4219
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
/* mfsr */
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
{
4220
#if defined(CONFIG_USER_ONLY)
4221
    GEN_EXCP_PRIVREG(ctx);
4222
#else
4223
    if (unlikely(!ctx->supervisor)) {
4224
        GEN_EXCP_PRIVREG(ctx);
4225
        return;
4226
    }
4227
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4228
    gen_op_load_sr();
A
aurel32 已提交
4229
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4230
#endif
B
bellard 已提交
4231 4232 4233
}

/* mfsrin */
4234
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
4235
{
4236
#if defined(CONFIG_USER_ONLY)
4237
    GEN_EXCP_PRIVREG(ctx);
4238
#else
4239
    if (unlikely(!ctx->supervisor)) {
4240
        GEN_EXCP_PRIVREG(ctx);
4241
        return;
4242
    }
A
aurel32 已提交
4243
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4244 4245
    gen_op_srli_T1(28);
    gen_op_load_sr();
A
aurel32 已提交
4246
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4247
#endif
B
bellard 已提交
4248 4249 4250
}

/* mtsr */
B
bellard 已提交
4251
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
B
bellard 已提交
4252
{
4253
#if defined(CONFIG_USER_ONLY)
4254
    GEN_EXCP_PRIVREG(ctx);
4255
#else
4256
    if (unlikely(!ctx->supervisor)) {
4257
        GEN_EXCP_PRIVREG(ctx);
4258
        return;
4259
    }
A
aurel32 已提交
4260
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4261
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4262
    gen_op_store_sr();
4263
#endif
B
bellard 已提交
4264 4265 4266
}

/* mtsrin */
4267
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
4268
{
4269
#if defined(CONFIG_USER_ONLY)
4270
    GEN_EXCP_PRIVREG(ctx);
4271
#else
4272
    if (unlikely(!ctx->supervisor)) {
4273
        GEN_EXCP_PRIVREG(ctx);
4274
        return;
4275
    }
A
aurel32 已提交
4276 4277
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4278 4279
    gen_op_srli_T1(28);
    gen_op_store_sr();
4280
#endif
B
bellard 已提交
4281 4282
}

4283 4284 4285
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
/* mfsr */
4286
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4287 4288 4289 4290 4291 4292 4293 4294
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
4295
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4296
    gen_op_load_slb();
A
aurel32 已提交
4297
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4298 4299 4300 4301
#endif
}

/* mfsrin */
4302 4303
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B)
4304 4305 4306 4307 4308 4309 4310 4311
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4312
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4313 4314
    gen_op_srli_T1(28);
    gen_op_load_slb();
A
aurel32 已提交
4315
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4316 4317 4318 4319
#endif
}

/* mtsr */
4320
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4321 4322 4323 4324 4325 4326 4327 4328
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4329
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4330
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4331 4332 4333 4334 4335
    gen_op_store_slb();
#endif
}

/* mtsrin */
4336 4337
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B)
4338 4339 4340 4341 4342 4343 4344 4345
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4346 4347
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4348 4349 4350 4351 4352 4353
    gen_op_srli_T1(28);
    gen_op_store_slb();
#endif
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4354 4355 4356
/***                      Lookaside buffer management                      ***/
/* Optional & supervisor only: */
/* tlbia */
4357
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
B
bellard 已提交
4358
{
4359
#if defined(CONFIG_USER_ONLY)
4360
    GEN_EXCP_PRIVOPC(ctx);
4361
#else
4362
    if (unlikely(!ctx->supervisor)) {
4363
        GEN_EXCP_PRIVOPC(ctx);
4364
        return;
4365 4366 4367
    }
    gen_op_tlbia();
#endif
B
bellard 已提交
4368 4369 4370
}

/* tlbie */
4371
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
B
bellard 已提交
4372
{
4373
#if defined(CONFIG_USER_ONLY)
4374
    GEN_EXCP_PRIVOPC(ctx);
4375
#else
4376
    if (unlikely(!ctx->supervisor)) {
4377
        GEN_EXCP_PRIVOPC(ctx);
4378
        return;
4379
    }
A
aurel32 已提交
4380
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4381 4382 4383 4384 4385 4386
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
4387
#endif
B
bellard 已提交
4388 4389 4390
}

/* tlbsync */
4391
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
B
bellard 已提交
4392
{
4393
#if defined(CONFIG_USER_ONLY)
4394
    GEN_EXCP_PRIVOPC(ctx);
4395
#else
4396
    if (unlikely(!ctx->supervisor)) {
4397
        GEN_EXCP_PRIVOPC(ctx);
4398
        return;
4399 4400 4401 4402
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
4403
    GEN_STOP(ctx);
4404
#endif
B
bellard 已提交
4405 4406
}

J
j_mayer 已提交
4407 4408 4409 4410 4411
#if defined(TARGET_PPC64)
/* slbia */
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
4412
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4413 4414
#else
    if (unlikely(!ctx->supervisor)) {
4415
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4416 4417 4418 4419 4420 4421 4422 4423 4424 4425
        return;
    }
    gen_op_slbia();
#endif
}

/* slbie */
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
4426
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4427 4428
#else
    if (unlikely(!ctx->supervisor)) {
4429
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4430 4431
        return;
    }
A
aurel32 已提交
4432
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4433 4434 4435 4436 4437
    gen_op_slbie();
#endif
}
#endif

B
bellard 已提交
4438 4439
/***                              External control                         ***/
/* Optional: */
4440 4441
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
4442 4443
static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(eciwx),
4444
};
4445 4446
static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ecowx),
4447
};
4448

4449
/* eciwx */
B
bellard 已提交
4450 4451
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
4452
    /* Should check EAR[E] & alignment ! */
4453
    gen_addr_reg_index(cpu_T[0], ctx);
4454
    op_eciwx();
A
aurel32 已提交
4455
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4456 4457 4458 4459 4460 4461
}

/* ecowx */
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
{
    /* Should check EAR[E] & alignment ! */
4462
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
4463
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4464 4465 4466 4467 4468 4469 4470
    op_ecowx();
}

/* PowerPC 601 specific instructions */
/* abs - abs. */
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
4471
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4472
    gen_op_POWER_abs();
A
aurel32 已提交
4473
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4474
    if (unlikely(Rc(ctx->opcode) != 0))
4475
        gen_set_Rc0(ctx, cpu_T[0]);
4476 4477 4478 4479 4480
}

/* abso - abso. */
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
4481
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4482
    gen_op_POWER_abso();
A
aurel32 已提交
4483
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4484
    if (unlikely(Rc(ctx->opcode) != 0))
4485
        gen_set_Rc0(ctx, cpu_T[0]);
4486 4487 4488
}

/* clcs */
4489
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4490
{
A
aurel32 已提交
4491
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4492
    gen_op_POWER_clcs();
4493
    /* Rc=1 sets CR0 to an undefined state */
A
aurel32 已提交
4494
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4495 4496 4497 4498 4499
}

/* div - div. */
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4500 4501
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4502
    gen_op_POWER_div();
A
aurel32 已提交
4503
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4504
    if (unlikely(Rc(ctx->opcode) != 0))
4505
        gen_set_Rc0(ctx, cpu_T[0]);
4506 4507 4508 4509 4510
}

/* divo - divo. */
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4511 4512
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4513
    gen_op_POWER_divo();
A
aurel32 已提交
4514
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4515
    if (unlikely(Rc(ctx->opcode) != 0))
4516
        gen_set_Rc0(ctx, cpu_T[0]);
4517 4518 4519 4520 4521
}

/* divs - divs. */
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4522 4523
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4524
    gen_op_POWER_divs();
A
aurel32 已提交
4525
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4526
    if (unlikely(Rc(ctx->opcode) != 0))
4527
        gen_set_Rc0(ctx, cpu_T[0]);
4528 4529 4530 4531 4532
}

/* divso - divso. */
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4533 4534
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4535
    gen_op_POWER_divso();
A
aurel32 已提交
4536
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4537
    if (unlikely(Rc(ctx->opcode) != 0))
4538
        gen_set_Rc0(ctx, cpu_T[0]);
4539 4540 4541 4542 4543
}

/* doz - doz. */
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4544 4545
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4546
    gen_op_POWER_doz();
A
aurel32 已提交
4547
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4548
    if (unlikely(Rc(ctx->opcode) != 0))
4549
        gen_set_Rc0(ctx, cpu_T[0]);
4550 4551 4552 4553 4554
}

/* dozo - dozo. */
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4555 4556
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4557
    gen_op_POWER_dozo();
A
aurel32 已提交
4558
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4559
    if (unlikely(Rc(ctx->opcode) != 0))
4560
        gen_set_Rc0(ctx, cpu_T[0]);
4561 4562 4563 4564 4565
}

/* dozi */
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4566
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4567
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
4568
    gen_op_POWER_doz();
A
aurel32 已提交
4569
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4570 4571
}

4572 4573 4574
/* As lscbx load from memory byte after byte, it's always endian safe.
 * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
 */
4575
#define op_POWER_lscbx(start, ra, rb)                                         \
4576
(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590
#define gen_op_POWER_lscbx_64_raw       gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_64_user      gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_64_kernel    gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_64_hypv      gen_op_POWER_lscbx_hypv
#define gen_op_POWER_lscbx_le_raw       gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_le_user      gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_le_kernel    gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_le_hypv      gen_op_POWER_lscbx_hypv
#define gen_op_POWER_lscbx_le_64_raw    gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_le_64_user   gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_le_64_hypv   gen_op_POWER_lscbx_hypv
static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER_lscbx),
4591 4592 4593 4594 4595 4596 4597 4598
};

/* lscbx - lscbx. */
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
{
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

4599
    gen_addr_reg_index(cpu_T[0], ctx);
4600 4601 4602 4603
    if (ra == 0) {
        ra = rb;
    }
    /* NIP cannot be restored if the memory exception comes from an helper */
4604
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4605 4606 4607
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
    tcg_gen_shri_tl(cpu_T[2], cpu_xer, XER_CMP);
    tcg_gen_andi_tl(cpu_T[2], cpu_T[2], 0xFF);
4608
    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
A
aurel32 已提交
4609 4610
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
    tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
4611
    if (unlikely(Rc(ctx->opcode) != 0))
4612
        gen_set_Rc0(ctx, cpu_T[0]);
4613 4614 4615 4616 4617
}

/* maskg - maskg. */
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4618 4619
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4620
    gen_op_POWER_maskg();
A
aurel32 已提交
4621
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4622
    if (unlikely(Rc(ctx->opcode) != 0))
4623
        gen_set_Rc0(ctx, cpu_T[0]);
4624 4625 4626 4627 4628
}

/* maskir - maskir. */
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4629 4630 4631
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4632
    gen_op_POWER_maskir();
A
aurel32 已提交
4633
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4634
    if (unlikely(Rc(ctx->opcode) != 0))
4635
        gen_set_Rc0(ctx, cpu_T[0]);
4636 4637 4638 4639 4640
}

/* mul - mul. */
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4641 4642
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4643
    gen_op_POWER_mul();
A
aurel32 已提交
4644
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4645
    if (unlikely(Rc(ctx->opcode) != 0))
4646
        gen_set_Rc0(ctx, cpu_T[0]);
4647 4648 4649 4650 4651
}

/* mulo - mulo. */
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4652 4653
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4654
    gen_op_POWER_mulo();
A
aurel32 已提交
4655
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4656
    if (unlikely(Rc(ctx->opcode) != 0))
4657
        gen_set_Rc0(ctx, cpu_T[0]);
4658 4659 4660 4661 4662
}

/* nabs - nabs. */
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4663
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4664
    gen_op_POWER_nabs();
A
aurel32 已提交
4665
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4666
    if (unlikely(Rc(ctx->opcode) != 0))
4667
        gen_set_Rc0(ctx, cpu_T[0]);
4668 4669 4670 4671 4672
}

/* nabso - nabso. */
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4673
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4674
    gen_op_POWER_nabso();
A
aurel32 已提交
4675
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4676
    if (unlikely(Rc(ctx->opcode) != 0))
4677
        gen_set_Rc0(ctx, cpu_T[0]);
4678 4679 4680 4681 4682 4683 4684 4685 4686
}

/* rlmi - rlmi. */
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
    uint32_t mb, me;

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
A
aurel32 已提交
4687 4688 4689
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4690
    gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
A
aurel32 已提交
4691
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4692
    if (unlikely(Rc(ctx->opcode) != 0))
4693
        gen_set_Rc0(ctx, cpu_T[0]);
4694 4695 4696 4697 4698
}

/* rrib - rrib. */
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4699 4700 4701
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4702
    gen_op_POWER_rrib();
A
aurel32 已提交
4703
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4704
    if (unlikely(Rc(ctx->opcode) != 0))
4705
        gen_set_Rc0(ctx, cpu_T[0]);
4706 4707 4708 4709 4710
}

/* sle - sle. */
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4711 4712
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4713
    gen_op_POWER_sle();
A
aurel32 已提交
4714
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4715
    if (unlikely(Rc(ctx->opcode) != 0))
4716
        gen_set_Rc0(ctx, cpu_T[0]);
4717 4718 4719 4720 4721
}

/* sleq - sleq. */
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4722 4723
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4724
    gen_op_POWER_sleq();
A
aurel32 已提交
4725
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4726
    if (unlikely(Rc(ctx->opcode) != 0))
4727
        gen_set_Rc0(ctx, cpu_T[0]);
4728 4729 4730 4731 4732
}

/* sliq - sliq. */
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4733
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4734
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4735
    gen_op_POWER_sle();
A
aurel32 已提交
4736
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4737
    if (unlikely(Rc(ctx->opcode) != 0))
4738
        gen_set_Rc0(ctx, cpu_T[0]);
4739 4740 4741 4742 4743
}

/* slliq - slliq. */
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4744
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4745
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4746
    gen_op_POWER_sleq();
A
aurel32 已提交
4747
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4748
    if (unlikely(Rc(ctx->opcode) != 0))
4749
        gen_set_Rc0(ctx, cpu_T[0]);
4750 4751 4752 4753 4754
}

/* sllq - sllq. */
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4755 4756
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4757
    gen_op_POWER_sllq();
A
aurel32 已提交
4758
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4759
    if (unlikely(Rc(ctx->opcode) != 0))
4760
        gen_set_Rc0(ctx, cpu_T[0]);
4761 4762 4763 4764 4765
}

/* slq - slq. */
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4766 4767
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4768
    gen_op_POWER_slq();
A
aurel32 已提交
4769
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4770
    if (unlikely(Rc(ctx->opcode) != 0))
4771
        gen_set_Rc0(ctx, cpu_T[0]);
4772 4773
}

4774
/* sraiq - sraiq. */
4775 4776
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4777
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4778
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4779
    gen_op_POWER_sraq();
A
aurel32 已提交
4780
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4781
    if (unlikely(Rc(ctx->opcode) != 0))
4782
        gen_set_Rc0(ctx, cpu_T[0]);
4783 4784 4785 4786 4787
}

/* sraq - sraq. */
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4788 4789
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4790
    gen_op_POWER_sraq();
A
aurel32 已提交
4791
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4792
    if (unlikely(Rc(ctx->opcode) != 0))
4793
        gen_set_Rc0(ctx, cpu_T[0]);
4794 4795 4796 4797 4798
}

/* sre - sre. */
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4799 4800
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4801
    gen_op_POWER_sre();
A
aurel32 已提交
4802
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4803
    if (unlikely(Rc(ctx->opcode) != 0))
4804
        gen_set_Rc0(ctx, cpu_T[0]);
4805 4806 4807 4808 4809
}

/* srea - srea. */
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4810 4811
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4812
    gen_op_POWER_srea();
A
aurel32 已提交
4813
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4814
    if (unlikely(Rc(ctx->opcode) != 0))
4815
        gen_set_Rc0(ctx, cpu_T[0]);
4816 4817 4818 4819 4820
}

/* sreq */
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4821 4822
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4823
    gen_op_POWER_sreq();
A
aurel32 已提交
4824
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4825
    if (unlikely(Rc(ctx->opcode) != 0))
4826
        gen_set_Rc0(ctx, cpu_T[0]);
4827 4828 4829 4830 4831
}

/* sriq */
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4832
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4833
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4834
    gen_op_POWER_srq();
A
aurel32 已提交
4835
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4836
    if (unlikely(Rc(ctx->opcode) != 0))
4837
        gen_set_Rc0(ctx, cpu_T[0]);
4838 4839 4840 4841 4842
}

/* srliq */
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4843 4844
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4845
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4846
    gen_op_POWER_srlq();
A
aurel32 已提交
4847
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4848
    if (unlikely(Rc(ctx->opcode) != 0))
4849
        gen_set_Rc0(ctx, cpu_T[0]);
4850 4851 4852 4853 4854
}

/* srlq */
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4855 4856
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4857
    gen_op_POWER_srlq();
A
aurel32 已提交
4858
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4859
    if (unlikely(Rc(ctx->opcode) != 0))
4860
        gen_set_Rc0(ctx, cpu_T[0]);
4861 4862 4863 4864 4865
}

/* srq */
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4866 4867
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4868
    gen_op_POWER_srq();
A
aurel32 已提交
4869
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4870
    if (unlikely(Rc(ctx->opcode) != 0))
4871
        gen_set_Rc0(ctx, cpu_T[0]);
4872 4873 4874 4875 4876 4877 4878
}

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4879
    GEN_EXCP_INVAL(ctx);
4880 4881 4882 4883 4884 4885
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4886
    GEN_EXCP_INVAL(ctx);
4887 4888 4889 4890 4891 4892
}

/* mfrom */
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
{
#if defined(CONFIG_USER_ONLY)
4893
    GEN_EXCP_PRIVOPC(ctx);
4894 4895
#else
    if (unlikely(!ctx->supervisor)) {
4896
        GEN_EXCP_PRIVOPC(ctx);
4897 4898
        return;
    }
A
aurel32 已提交
4899
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4900
    gen_op_602_mfrom();
A
aurel32 已提交
4901
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4902 4903 4904 4905 4906
#endif
}

/* 602 - 603 - G2 TLB management */
/* tlbld */
4907
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4908 4909
{
#if defined(CONFIG_USER_ONLY)
4910
    GEN_EXCP_PRIVOPC(ctx);
4911 4912
#else
    if (unlikely(!ctx->supervisor)) {
4913
        GEN_EXCP_PRIVOPC(ctx);
4914 4915
        return;
    }
A
aurel32 已提交
4916
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4917 4918 4919 4920 4921
    gen_op_6xx_tlbld();
#endif
}

/* tlbli */
4922
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4923 4924
{
#if defined(CONFIG_USER_ONLY)
4925
    GEN_EXCP_PRIVOPC(ctx);
4926 4927
#else
    if (unlikely(!ctx->supervisor)) {
4928
        GEN_EXCP_PRIVOPC(ctx);
4929 4930
        return;
    }
A
aurel32 已提交
4931
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4932 4933 4934 4935
    gen_op_6xx_tlbli();
#endif
}

4936 4937
/* 74xx TLB management */
/* tlbld */
4938
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4939 4940 4941 4942 4943 4944 4945 4946
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4947
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4948 4949 4950 4951 4952
    gen_op_74xx_tlbld();
#endif
}

/* tlbli */
4953
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4954 4955 4956 4957 4958 4959 4960 4961
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4962
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4963 4964 4965 4966
    gen_op_74xx_tlbli();
#endif
}

4967 4968 4969 4970 4971 4972 4973 4974 4975 4976
/* POWER instructions not in PowerPC 601 */
/* clf */
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
{
B
blueswir1 已提交
4977
    /* Cache line invalidate: privileged and treated as no-op */
4978
#if defined(CONFIG_USER_ONLY)
4979
    GEN_EXCP_PRIVOPC(ctx);
4980 4981
#else
    if (unlikely(!ctx->supervisor)) {
4982
        GEN_EXCP_PRIVOPC(ctx);
4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996
        return;
    }
#endif
}

/* dclst */
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
{
    /* Data cache line store: treated as no-op */
}

GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4997
    GEN_EXCP_PRIVOPC(ctx);
4998 4999
#else
    if (unlikely(!ctx->supervisor)) {
5000
        GEN_EXCP_PRIVOPC(ctx);
5001 5002 5003 5004 5005
        return;
    }
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);

5006
    gen_addr_reg_index(cpu_T[0], ctx);
5007
    gen_op_POWER_mfsri();
A
aurel32 已提交
5008
    tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
5009
    if (ra != 0 && ra != rd)
A
aurel32 已提交
5010
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
5011 5012 5013 5014 5015 5016
#endif
}

GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
5017
    GEN_EXCP_PRIVOPC(ctx);
5018 5019
#else
    if (unlikely(!ctx->supervisor)) {
5020
        GEN_EXCP_PRIVOPC(ctx);
5021 5022
        return;
    }
5023
    gen_addr_reg_index(cpu_T[0], ctx);
5024
    gen_op_POWER_rac();
A
aurel32 已提交
5025
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5026 5027 5028 5029 5030 5031
#endif
}

GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
5032
    GEN_EXCP_PRIVOPC(ctx);
5033 5034
#else
    if (unlikely(!ctx->supervisor)) {
5035
        GEN_EXCP_PRIVOPC(ctx);
5036 5037 5038
        return;
    }
    gen_op_POWER_rfsvc();
5039
    GEN_SYNC(ctx);
5040 5041 5042 5043 5044 5045 5046
#endif
}

/* svc is not implemented for now */

/* POWER2 specific instructions */
/* Quad manipulation (load/store two floats at a time) */
5047
/* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
5048 5049
#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
#define gen_op_POWER2_lfq_64_raw        gen_op_POWER2_lfq_raw
#define gen_op_POWER2_lfq_64_user       gen_op_POWER2_lfq_user
#define gen_op_POWER2_lfq_64_kernel     gen_op_POWER2_lfq_kernel
#define gen_op_POWER2_lfq_64_hypv       gen_op_POWER2_lfq_hypv
#define gen_op_POWER2_lfq_le_64_raw     gen_op_POWER2_lfq_le_raw
#define gen_op_POWER2_lfq_le_64_user    gen_op_POWER2_lfq_le_user
#define gen_op_POWER2_lfq_le_64_kernel  gen_op_POWER2_lfq_le_kernel
#define gen_op_POWER2_lfq_le_64_hypv    gen_op_POWER2_lfq_le_hypv
#define gen_op_POWER2_stfq_64_raw       gen_op_POWER2_stfq_raw
#define gen_op_POWER2_stfq_64_user      gen_op_POWER2_stfq_user
#define gen_op_POWER2_stfq_64_kernel    gen_op_POWER2_stfq_kernel
#define gen_op_POWER2_stfq_64_hypv      gen_op_POWER2_stfq_hypv
#define gen_op_POWER2_stfq_le_64_raw    gen_op_POWER2_stfq_le_raw
#define gen_op_POWER2_stfq_le_64_user   gen_op_POWER2_stfq_le_user
#define gen_op_POWER2_stfq_le_64_kernel gen_op_POWER2_stfq_le_kernel
#define gen_op_POWER2_stfq_le_64_hypv   gen_op_POWER2_stfq_le_hypv
static GenOpFunc *gen_op_POWER2_lfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_lfq),
5068
};
5069 5070
static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_stfq),
5071 5072 5073 5074 5075 5076
};

/* lfq */
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5077
    gen_update_nip(ctx, ctx->nip - 4);
5078
    gen_addr_imm_index(cpu_T[0], ctx, 0);
5079
    op_POWER2_lfq();
A
aurel32 已提交
5080 5081
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
5082 5083 5084 5085 5086 5087 5088 5089
}

/* lfqu */
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
5090
    gen_update_nip(ctx, ctx->nip - 4);
5091
    gen_addr_imm_index(cpu_T[0], ctx, 0);
5092
    op_POWER2_lfq();
A
aurel32 已提交
5093 5094
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
5095
    if (ra != 0)
A
aurel32 已提交
5096
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5097 5098 5099 5100 5101 5102 5103 5104
}

/* lfqux */
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
5105
    gen_update_nip(ctx, ctx->nip - 4);
5106
    gen_addr_reg_index(cpu_T[0], ctx);
5107
    op_POWER2_lfq();
A
aurel32 已提交
5108 5109
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
5110
    if (ra != 0)
A
aurel32 已提交
5111
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5112 5113 5114 5115 5116 5117
}

/* lfqx */
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5118
    gen_update_nip(ctx, ctx->nip - 4);
5119
    gen_addr_reg_index(cpu_T[0], ctx);
5120
    op_POWER2_lfq();
A
aurel32 已提交
5121 5122
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
5123 5124 5125 5126 5127 5128
}

/* stfq */
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5129
    gen_update_nip(ctx, ctx->nip - 4);
5130
    gen_addr_imm_index(cpu_T[0], ctx, 0);
A
aurel32 已提交
5131 5132
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
5133 5134 5135 5136 5137 5138 5139 5140 5141
    op_POWER2_stfq();
}

/* stfqu */
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
5142
    gen_update_nip(ctx, ctx->nip - 4);
5143
    gen_addr_imm_index(cpu_T[0], ctx, 0);
A
aurel32 已提交
5144 5145
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
5146 5147
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
5148
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5149 5150 5151 5152 5153 5154 5155 5156
}

/* stfqux */
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
5157
    gen_update_nip(ctx, ctx->nip - 4);
5158
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
5159 5160
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
5161 5162
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
5163
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5164 5165 5166 5167 5168 5169
}

/* stfqx */
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5170
    gen_update_nip(ctx, ctx->nip - 4);
5171
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
5172 5173
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
5174 5175 5176 5177
    op_POWER2_stfq();
}

/* BookE specific instructions */
5178
/* XXX: not implemented on 440 ? */
5179
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
5180 5181
{
    /* XXX: TODO */
5182
    GEN_EXCP_INVAL(ctx);
5183 5184
}

5185
/* XXX: not implemented on 440 ? */
5186
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
5187 5188
{
#if defined(CONFIG_USER_ONLY)
5189
    GEN_EXCP_PRIVOPC(ctx);
5190 5191
#else
    if (unlikely(!ctx->supervisor)) {
5192
        GEN_EXCP_PRIVOPC(ctx);
5193 5194
        return;
    }
5195
    gen_addr_reg_index(cpu_T[0], ctx);
5196
    /* Use the same micro-ops as for tlbie */
5197 5198 5199 5200 5201 5202
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
5203 5204 5205 5206
#endif
}

/* All 405 MAC instructions are translated here */
5207 5208 5209
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
                                                int opc2, int opc3,
                                                int ra, int rb, int rt, int Rc)
5210
{
5211 5212 5213 5214 5215
    TCGv t0, t1;

    t0 = tcg_temp_local_new(TCG_TYPE_TL);
    t1 = tcg_temp_local_new(TCG_TYPE_TL);

5216 5217 5218 5219 5220 5221 5222
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5223 5224 5225
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5226 5227 5228 5229 5230
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5231 5232 5233
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5234 5235 5236 5237 5238 5239 5240
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5241 5242 5243 5244
        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
        tcg_gen_ext16s_tl(t0, t0);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5245 5246 5247 5248 5249
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5250 5251 5252 5253
        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
        tcg_gen_ext16u_tl(t0, t0);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5254 5255 5256 5257 5258 5259 5260
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5261 5262
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5263 5264 5265 5266 5267
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5268 5269
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5270 5271 5272
        break;
    }
    if (opc2 & 0x04) {
5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
        tcg_gen_mul_tl(t1, t0, t1);
        if (opc2 & 0x02) {
            /* nmultiply-and-accumulate (0x0E) */
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
        } else {
            /* multiply-and-accumulate (0x0C) */
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
        }

        if (opc3 & 0x12) {
            /* Check overflow and/or saturate */
            int l1 = gen_new_label();

            if (opc3 & 0x10) {
                /* Start with XER OV disabled, the most likely case */
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
            }
            if (opc3 & 0x01) {
                /* Signed */
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
		if (opc3 & 0x02) {
                    /* Saturate */
                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
                }
            } else {
                /* Unsigned */
                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
		if (opc3 & 0x02) {
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5319
    }
5320 5321
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5322 5323
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5324
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5325 5326 5327
    }
}

5328 5329
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5330 5331 5332 5333 5334 5335
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5336
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5337
/* macchwo   - macchwo.   */
5338
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5339
/* macchws   - macchws.   */
5340
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5341
/* macchwso  - macchwso.  */
5342
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5343
/* macchwsu  - macchwsu.  */
5344
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5345
/* macchwsuo - macchwsuo. */
5346
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5347
/* macchwu   - macchwu.   */
5348
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5349
/* macchwuo  - macchwuo.  */
5350
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5351
/* machhw    - machhw.    */
5352
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5353
/* machhwo   - machhwo.   */
5354
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5355
/* machhws   - machhws.   */
5356
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5357
/* machhwso  - machhwso.  */
5358
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5359
/* machhwsu  - machhwsu.  */
5360
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5361
/* machhwsuo - machhwsuo. */
5362
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5363
/* machhwu   - machhwu.   */
5364
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5365
/* machhwuo  - machhwuo.  */
5366
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5367
/* maclhw    - maclhw.    */
5368
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5369
/* maclhwo   - maclhwo.   */
5370
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5371
/* maclhws   - maclhws.   */
5372
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5373
/* maclhwso  - maclhwso.  */
5374
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5375
/* maclhwu   - maclhwu.   */
5376
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5377
/* maclhwuo  - maclhwuo.  */
5378
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5379
/* maclhwsu  - maclhwsu.  */
5380
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5381
/* maclhwsuo - maclhwsuo. */
5382
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5383
/* nmacchw   - nmacchw.   */
5384
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5385
/* nmacchwo  - nmacchwo.  */
5386
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5387
/* nmacchws  - nmacchws.  */
5388
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5389
/* nmacchwso - nmacchwso. */
5390
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5391
/* nmachhw   - nmachhw.   */
5392
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5393
/* nmachhwo  - nmachhwo.  */
5394
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5395
/* nmachhws  - nmachhws.  */
5396
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5397
/* nmachhwso - nmachhwso. */
5398
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5399
/* nmaclhw   - nmaclhw.   */
5400
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5401
/* nmaclhwo  - nmaclhwo.  */
5402
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5403
/* nmaclhws  - nmaclhws.  */
5404
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5405
/* nmaclhwso - nmaclhwso. */
5406
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5407 5408

/* mulchw  - mulchw.  */
5409
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5410
/* mulchwu - mulchwu. */
5411
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5412
/* mulhhw  - mulhhw.  */
5413
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5414
/* mulhhwu - mulhhwu. */
5415
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5416
/* mullhw  - mullhw.  */
5417
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5418
/* mullhwu - mullhwu. */
5419
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5420 5421

/* mfdcr */
5422
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
5423 5424
{
#if defined(CONFIG_USER_ONLY)
5425
    GEN_EXCP_PRIVREG(ctx);
5426 5427 5428 5429
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
5430
        GEN_EXCP_PRIVREG(ctx);
5431 5432
        return;
    }
5433
    tcg_gen_movi_tl(cpu_T[0], dcrn);
5434
    gen_op_load_dcr();
A
aurel32 已提交
5435
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5436 5437 5438 5439
#endif
}

/* mtdcr */
5440
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
5441 5442
{
#if defined(CONFIG_USER_ONLY)
5443
    GEN_EXCP_PRIVREG(ctx);
5444 5445 5446 5447
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
5448
        GEN_EXCP_PRIVREG(ctx);
5449 5450
        return;
    }
5451
    tcg_gen_movi_tl(cpu_T[0], dcrn);
A
aurel32 已提交
5452
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5453 5454 5455 5456 5457
    gen_op_store_dcr();
#endif
}

/* mfdcrx */
5458
/* XXX: not implemented on 440 ? */
5459
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
5460 5461
{
#if defined(CONFIG_USER_ONLY)
5462
    GEN_EXCP_PRIVREG(ctx);
5463 5464
#else
    if (unlikely(!ctx->supervisor)) {
5465
        GEN_EXCP_PRIVREG(ctx);
5466 5467
        return;
    }
A
aurel32 已提交
5468
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5469
    gen_op_load_dcr();
A
aurel32 已提交
5470
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5471
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5472 5473 5474 5475
#endif
}

/* mtdcrx */
5476
/* XXX: not implemented on 440 ? */
5477
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
5478 5479
{
#if defined(CONFIG_USER_ONLY)
5480
    GEN_EXCP_PRIVREG(ctx);
5481 5482
#else
    if (unlikely(!ctx->supervisor)) {
5483
        GEN_EXCP_PRIVREG(ctx);
5484 5485
        return;
    }
A
aurel32 已提交
5486 5487
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5488
    gen_op_store_dcr();
5489
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5490 5491 5492
#endif
}

5493 5494 5495
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
A
aurel32 已提交
5496
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5497
    gen_op_load_dcr();
A
aurel32 已提交
5498
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5499 5500 5501 5502 5503 5504
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
{
A
aurel32 已提交
5505 5506
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5507 5508 5509 5510
    gen_op_store_dcr();
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5511 5512 5513 5514
/* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5515
    GEN_EXCP_PRIVOPC(ctx);
5516 5517
#else
    if (unlikely(!ctx->supervisor)) {
5518
        GEN_EXCP_PRIVOPC(ctx);
5519 5520 5521 5522 5523 5524 5525 5526 5527 5528
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5529
    GEN_EXCP_PRIVOPC(ctx);
5530
#else
A
aurel32 已提交
5531
    TCGv EA, val;
5532
    if (unlikely(!ctx->supervisor)) {
5533
        GEN_EXCP_PRIVOPC(ctx);
5534 5535
        return;
    }
A
aurel32 已提交
5536 5537 5538 5539 5540 5541 5542
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(EA, ctx);
    val = tcg_temp_new(TCG_TYPE_TL);
    gen_qemu_ld32u(val, EA, ctx->mem_idx);
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5543 5544 5545 5546
#endif
}

/* icbt */
5547
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
}

/* iccci */
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5559
    GEN_EXCP_PRIVOPC(ctx);
5560 5561
#else
    if (unlikely(!ctx->supervisor)) {
5562
        GEN_EXCP_PRIVOPC(ctx);
5563 5564 5565 5566 5567 5568 5569 5570 5571 5572
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5573
    GEN_EXCP_PRIVOPC(ctx);
5574 5575
#else
    if (unlikely(!ctx->supervisor)) {
5576
        GEN_EXCP_PRIVOPC(ctx);
5577 5578 5579 5580 5581 5582 5583
        return;
    }
    /* interpreted as no-op */
#endif
}

/* rfci (supervisor only) */
5584
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5585 5586
{
#if defined(CONFIG_USER_ONLY)
5587
    GEN_EXCP_PRIVOPC(ctx);
5588 5589
#else
    if (unlikely(!ctx->supervisor)) {
5590
        GEN_EXCP_PRIVOPC(ctx);
5591 5592 5593 5594
        return;
    }
    /* Restore CPU state */
    gen_op_40x_rfci();
5595
    GEN_SYNC(ctx);
5596 5597 5598 5599 5600 5601
#endif
}

GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
{
#if defined(CONFIG_USER_ONLY)
5602
    GEN_EXCP_PRIVOPC(ctx);
5603 5604
#else
    if (unlikely(!ctx->supervisor)) {
5605
        GEN_EXCP_PRIVOPC(ctx);
5606 5607 5608 5609
        return;
    }
    /* Restore CPU state */
    gen_op_rfci();
5610
    GEN_SYNC(ctx);
5611 5612 5613 5614
#endif
}

/* BookE specific */
5615
/* XXX: not implemented on 440 ? */
5616
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5617 5618
{
#if defined(CONFIG_USER_ONLY)
5619
    GEN_EXCP_PRIVOPC(ctx);
5620 5621
#else
    if (unlikely(!ctx->supervisor)) {
5622
        GEN_EXCP_PRIVOPC(ctx);
5623 5624 5625
        return;
    }
    /* Restore CPU state */
5626
    gen_op_rfdi();
5627
    GEN_SYNC(ctx);
5628 5629 5630
#endif
}

5631
/* XXX: not implemented on 440 ? */
5632
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5633 5634
{
#if defined(CONFIG_USER_ONLY)
5635
    GEN_EXCP_PRIVOPC(ctx);
5636 5637
#else
    if (unlikely(!ctx->supervisor)) {
5638
        GEN_EXCP_PRIVOPC(ctx);
5639 5640 5641 5642
        return;
    }
    /* Restore CPU state */
    gen_op_rfmci();
5643
    GEN_SYNC(ctx);
5644 5645
#endif
}
5646

5647
/* TLB management - PowerPC 405 implementation */
5648
/* tlbre */
5649
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5650 5651
{
#if defined(CONFIG_USER_ONLY)
5652
    GEN_EXCP_PRIVOPC(ctx);
5653 5654
#else
    if (unlikely(!ctx->supervisor)) {
5655
        GEN_EXCP_PRIVOPC(ctx);
5656 5657 5658 5659
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5660
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5661
        gen_op_4xx_tlbre_hi();
A
aurel32 已提交
5662
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5663 5664
        break;
    case 1:
A
aurel32 已提交
5665
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5666
        gen_op_4xx_tlbre_lo();
A
aurel32 已提交
5667
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5668 5669
        break;
    default:
5670
        GEN_EXCP_INVAL(ctx);
5671
        break;
5672
    }
5673 5674 5675
#endif
}

5676
/* tlbsx - tlbsx. */
5677
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5678 5679
{
#if defined(CONFIG_USER_ONLY)
5680
    GEN_EXCP_PRIVOPC(ctx);
5681 5682
#else
    if (unlikely(!ctx->supervisor)) {
5683
        GEN_EXCP_PRIVOPC(ctx);
5684 5685
        return;
    }
5686
    gen_addr_reg_index(cpu_T[0], ctx);
5687
    gen_op_4xx_tlbsx();
5688
    if (Rc(ctx->opcode))
5689
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5690
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5691
#endif
B
bellard 已提交
5692 5693
}

5694
/* tlbwe */
5695
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
B
bellard 已提交
5696
{
5697
#if defined(CONFIG_USER_ONLY)
5698
    GEN_EXCP_PRIVOPC(ctx);
5699 5700
#else
    if (unlikely(!ctx->supervisor)) {
5701
        GEN_EXCP_PRIVOPC(ctx);
5702 5703 5704 5705
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5706 5707
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5708 5709 5710
        gen_op_4xx_tlbwe_hi();
        break;
    case 1:
A
aurel32 已提交
5711 5712
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5713 5714 5715
        gen_op_4xx_tlbwe_lo();
        break;
    default:
5716
        GEN_EXCP_INVAL(ctx);
5717
        break;
5718
    }
5719 5720 5721
#endif
}

5722
/* TLB management - PowerPC 440 implementation */
5723
/* tlbre */
5724
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5725 5726
{
#if defined(CONFIG_USER_ONLY)
5727
    GEN_EXCP_PRIVOPC(ctx);
5728 5729
#else
    if (unlikely(!ctx->supervisor)) {
5730
        GEN_EXCP_PRIVOPC(ctx);
5731 5732 5733 5734 5735 5736
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5737
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5738
        gen_op_440_tlbre(rB(ctx->opcode));
A
aurel32 已提交
5739
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5740 5741
        break;
    default:
5742
        GEN_EXCP_INVAL(ctx);
5743 5744 5745 5746 5747 5748
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
5749
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5750 5751
{
#if defined(CONFIG_USER_ONLY)
5752
    GEN_EXCP_PRIVOPC(ctx);
5753 5754
#else
    if (unlikely(!ctx->supervisor)) {
5755
        GEN_EXCP_PRIVOPC(ctx);
5756 5757
        return;
    }
5758
    gen_addr_reg_index(cpu_T[0], ctx);
5759
    gen_op_440_tlbsx();
5760
    if (Rc(ctx->opcode))
5761
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5762
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5763 5764 5765 5766
#endif
}

/* tlbwe */
5767
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5768 5769
{
#if defined(CONFIG_USER_ONLY)
5770
    GEN_EXCP_PRIVOPC(ctx);
5771 5772
#else
    if (unlikely(!ctx->supervisor)) {
5773
        GEN_EXCP_PRIVOPC(ctx);
5774 5775 5776 5777 5778 5779
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5780 5781
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5782
        gen_op_440_tlbwe(rB(ctx->opcode));
5783 5784
        break;
    default:
5785
        GEN_EXCP_INVAL(ctx);
5786 5787 5788 5789 5790
        break;
    }
#endif
}

5791
/* wrtee */
5792
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5793 5794
{
#if defined(CONFIG_USER_ONLY)
5795
    GEN_EXCP_PRIVOPC(ctx);
5796 5797
#else
    if (unlikely(!ctx->supervisor)) {
5798
        GEN_EXCP_PRIVOPC(ctx);
5799 5800
        return;
    }
A
aurel32 已提交
5801
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
5802
    gen_op_wrte();
J
j_mayer 已提交
5803 5804 5805
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5806
    GEN_STOP(ctx);
5807 5808 5809 5810
#endif
}

/* wrteei */
5811
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5812 5813
{
#if defined(CONFIG_USER_ONLY)
5814
    GEN_EXCP_PRIVOPC(ctx);
5815 5816
#else
    if (unlikely(!ctx->supervisor)) {
5817
        GEN_EXCP_PRIVOPC(ctx);
5818 5819
        return;
    }
5820
    tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
5821
    gen_op_wrte();
J
j_mayer 已提交
5822 5823 5824
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5825
    GEN_STOP(ctx);
5826 5827 5828
#endif
}

J
j_mayer 已提交
5829
/* PowerPC 440 specific instructions */
5830 5831 5832
/* dlmzb */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
{
A
aurel32 已提交
5833 5834
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5835
    gen_op_440_dlmzb();
A
aurel32 已提交
5836
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
A
aurel32 已提交
5837 5838
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
    tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
5839 5840
    if (Rc(ctx->opcode)) {
        gen_op_440_dlmzb_update_Rc();
A
aurel32 已提交
5841
        tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf);
5842 5843 5844 5845 5846 5847 5848 5849 5850 5851
    }
}

/* mbar replaces eieio on 440 */
GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
5852
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5853 5854 5855 5856 5857
{
    /* interpreted as no-op */
}

/* icbt */
5858
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5859 5860 5861 5862 5863
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
5864 5865
}

5866 5867 5868
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

5869 5870 5871 5872 5873 5874 5875 5876 5877
static always_inline void gen_load_avr(int t, int reg) {
    tcg_gen_mov_i64(cpu_AVRh[t], cpu_avrh[reg]);
    tcg_gen_mov_i64(cpu_AVRl[t], cpu_avrl[reg]);
}

static always_inline void gen_store_avr(int reg, int t) {
    tcg_gen_mov_i64(cpu_avrh[reg], cpu_AVRh[t]);
    tcg_gen_mov_i64(cpu_avrl[reg], cpu_AVRl[t]);
}
5878 5879 5880

#define op_vr_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_VR_LD_TABLE(name)                                                  \
5881 5882
static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = {                         \
    GEN_MEM_FUNCS(vr_l##name),                                                \
5883 5884
};
#define OP_VR_ST_TABLE(name)                                                  \
5885 5886
static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(vr_st##name),                                               \
5887 5888 5889 5890 5891 5892 5893 5894 5895
};

#define GEN_VR_LDX(name, opc2, opc3)                                          \
GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)               \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
5896
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5897
    op_vr_ldst(vr_l##name);                                                   \
5898
    gen_store_avr(rD(ctx->opcode), 0);                                        \
5899 5900 5901 5902 5903 5904 5905 5906 5907
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
5908
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5909
    gen_load_avr(0, rS(ctx->opcode));                                         \
5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924
    op_vr_ldst(vr_st##name);                                                  \
}

OP_VR_LD_TABLE(vx);
GEN_VR_LDX(vx, 0x07, 0x03);
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
#define gen_op_vr_lvxl gen_op_vr_lvx
GEN_VR_LDX(vxl, 0x07, 0x0B);

OP_VR_ST_TABLE(vx);
GEN_VR_STX(vx, 0x07, 0x07);
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
#define gen_op_vr_stvxl gen_op_vr_stvx
GEN_VR_STX(vxl, 0x07, 0x0F);

5925 5926
/***                           SPE extension                               ***/
/* Register moves */
5927

A
aurel32 已提交
5928 5929 5930 5931
static always_inline void gen_load_gpr64(TCGv t, int reg) {
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
5932
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
5933
#endif
A
aurel32 已提交
5934
}
5935

A
aurel32 已提交
5936 5937 5938 5939 5940
static always_inline void gen_store_gpr64(int reg, TCGv t) {
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
5941
    TCGv tmp = tcg_temp_new(TCG_TYPE_I64);
A
aurel32 已提交
5942 5943 5944
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
    tcg_temp_free(tmp);
5945
#endif
A
aurel32 已提交
5946
}
5947

5948 5949 5950 5951 5952 5953 5954 5955 5956 5957
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
5958
static always_inline void gen_speundef (DisasContext *ctx)
5959
{
5960
    GEN_EXCP_INVAL(ctx);
5961 5962 5963
}

/* SPE load and stores */
5964
static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
5965 5966 5967
{
    target_long simm = rB(ctx->opcode);

5968 5969 5970 5971 5972 5973
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, simm << sh);
    else if (likely(simm != 0))
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm << sh);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
5974 5975 5976 5977
}

#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_SPE_LD_TABLE(name)                                                 \
5978 5979
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(spe_l##name),                                               \
5980 5981
};
#define OP_SPE_ST_TABLE(name)                                                 \
5982 5983
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = {                       \
    GEN_MEM_FUNCS(spe_st##name),                                              \
5984
};
5985 5986

#define GEN_SPE_LD(name, sh)                                                  \
5987
static always_inline void gen_evl##name (DisasContext *ctx)                   \
5988 5989
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5990
        GEN_EXCP_NO_AP(ctx);                                                  \
5991 5992
        return;                                                               \
    }                                                                         \
5993
    gen_addr_spe_imm_index(cpu_T[0], ctx, sh);                                \
5994
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
5995
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
5996 5997 5998
}

#define GEN_SPE_LDX(name)                                                     \
5999
static always_inline void gen_evl##name##x (DisasContext *ctx)                \
6000 6001
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6002
        GEN_EXCP_NO_AP(ctx);                                                  \
6003 6004
        return;                                                               \
    }                                                                         \
6005
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
6006
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
6007
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
6008 6009 6010 6011 6012 6013 6014 6015
}

#define GEN_SPEOP_LD(name, sh)                                                \
OP_SPE_LD_TABLE(name);                                                        \
GEN_SPE_LD(name, sh);                                                         \
GEN_SPE_LDX(name)

#define GEN_SPE_ST(name, sh)                                                  \
6016
static always_inline void gen_evst##name (DisasContext *ctx)                  \
6017 6018
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6019
        GEN_EXCP_NO_AP(ctx);                                                  \
6020 6021
        return;                                                               \
    }                                                                         \
6022
    gen_addr_spe_imm_index(cpu_T[0], ctx, sh);                                \
A
aurel32 已提交
6023
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
6024 6025 6026 6027
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPE_STX(name)                                                     \
6028
static always_inline void gen_evst##name##x (DisasContext *ctx)               \
6029 6030
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6031
        GEN_EXCP_NO_AP(ctx);                                                  \
6032 6033
        return;                                                               \
    }                                                                         \
6034
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
6035
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPEOP_ST(name, sh)                                                \
OP_SPE_ST_TABLE(name);                                                        \
GEN_SPE_ST(name, sh);                                                         \
GEN_SPE_STX(name)

#define GEN_SPEOP_LDST(name, sh)                                              \
GEN_SPEOP_LD(name, sh);                                                       \
GEN_SPEOP_ST(name, sh)

/* SPE arithmetic and logic */
#define GEN_SPEOP_ARITH2(name)                                                \
6050
static always_inline void gen_##name (DisasContext *ctx)                      \
6051 6052
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6053
        GEN_EXCP_NO_AP(ctx);                                                  \
6054 6055
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6056 6057
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6058
    gen_op_##name();                                                          \
A
aurel32 已提交
6059
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6060 6061
}

6062
#define GEN_SPEOP_TCG_ARITH2(name, tcg_op)                                    \
6063 6064 6065 6066 6067 6068 6069 6070 6071 6072
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    TCGv t0 = tcg_temp_new(TCG_TYPE_I64);                                     \
    TCGv t1 = tcg_temp_new(TCG_TYPE_I64);                                     \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
6073
    tcg_op(t0, t0, t1);                                                       \
6074 6075 6076 6077 6078
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free(t0);                                                        \
    tcg_temp_free(t1);                                                        \
}

6079
#define GEN_SPEOP_ARITH1(name)                                                \
6080
static always_inline void gen_##name (DisasContext *ctx)                      \
6081 6082
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6083
        GEN_EXCP_NO_AP(ctx);                                                  \
6084 6085
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6086
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6087
    gen_op_##name();                                                          \
A
aurel32 已提交
6088
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6089 6090 6091
}

#define GEN_SPEOP_COMP(name)                                                  \
6092
static always_inline void gen_##name (DisasContext *ctx)                      \
6093 6094
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6095
        GEN_EXCP_NO_AP(ctx);                                                  \
6096 6097
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6098 6099
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6100
    gen_op_##name();                                                          \
A
aurel32 已提交
6101
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);              \
6102 6103 6104
}

/* Logical */
6105 6106 6107 6108 6109 6110 6111 6112
GEN_SPEOP_TCG_ARITH2(evand, tcg_gen_and_i64);
GEN_SPEOP_TCG_ARITH2(evandc, tcg_gen_andc_i64);
GEN_SPEOP_TCG_ARITH2(evxor, tcg_gen_xor_i64);
GEN_SPEOP_TCG_ARITH2(evor, tcg_gen_or_i64);
GEN_SPEOP_TCG_ARITH2(evnor, tcg_gen_nor_i64);
GEN_SPEOP_TCG_ARITH2(eveqv, tcg_gen_eqv_i64);
GEN_SPEOP_TCG_ARITH2(evorc, tcg_gen_orc_i64);
GEN_SPEOP_TCG_ARITH2(evnand, tcg_gen_nand_i64);
6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131
GEN_SPEOP_ARITH2(evsrwu);
GEN_SPEOP_ARITH2(evsrws);
GEN_SPEOP_ARITH2(evslw);
GEN_SPEOP_ARITH2(evrlw);
GEN_SPEOP_ARITH2(evmergehi);
GEN_SPEOP_ARITH2(evmergelo);
GEN_SPEOP_ARITH2(evmergehilo);
GEN_SPEOP_ARITH2(evmergelohi);

/* Arithmetic */
GEN_SPEOP_ARITH2(evaddw);
GEN_SPEOP_ARITH2(evsubfw);
GEN_SPEOP_ARITH1(evabs);
GEN_SPEOP_ARITH1(evneg);
GEN_SPEOP_ARITH1(evextsb);
GEN_SPEOP_ARITH1(evextsh);
GEN_SPEOP_ARITH1(evrndw);
GEN_SPEOP_ARITH1(evcntlzw);
GEN_SPEOP_ARITH1(evcntlsw);
6132
static always_inline void gen_brinc (DisasContext *ctx)
6133 6134
{
    /* Note: brinc is usable even if SPE is disabled */
A
aurel32 已提交
6135 6136
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
6137
    gen_op_brinc();
A
aurel32 已提交
6138
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
6139 6140 6141
}

#define GEN_SPEOP_ARITH_IMM2(name)                                            \
6142
static always_inline void gen_##name##i (DisasContext *ctx)                   \
6143 6144
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6145
        GEN_EXCP_NO_AP(ctx);                                                  \
6146 6147
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6148
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6149 6150
    gen_op_splatwi_T1_64(rA(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
6151
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6152 6153 6154
}

#define GEN_SPEOP_LOGIC_IMM2(name)                                            \
6155
static always_inline void gen_##name##i (DisasContext *ctx)                   \
6156 6157
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6158
        GEN_EXCP_NO_AP(ctx);                                                  \
6159 6160
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6161
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6162 6163
    gen_op_splatwi_T1_64(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
6164
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177
}

GEN_SPEOP_ARITH_IMM2(evaddw);
#define gen_evaddiw gen_evaddwi
GEN_SPEOP_ARITH_IMM2(evsubfw);
#define gen_evsubifw gen_evsubfwi
GEN_SPEOP_LOGIC_IMM2(evslw);
GEN_SPEOP_LOGIC_IMM2(evsrwu);
#define gen_evsrwis gen_evsrwsi
GEN_SPEOP_LOGIC_IMM2(evsrws);
#define gen_evsrwiu gen_evsrwui
GEN_SPEOP_LOGIC_IMM2(evrlw);

6178
static always_inline void gen_evsplati (DisasContext *ctx)
6179 6180 6181 6182
{
    int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
6183
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6184 6185
}

6186
static always_inline void gen_evsplatfi (DisasContext *ctx)
6187 6188 6189 6190
{
    uint32_t imm = rA(ctx->opcode) << 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
6191
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226
}

/* Comparison */
GEN_SPEOP_COMP(evcmpgtu);
GEN_SPEOP_COMP(evcmpgts);
GEN_SPEOP_COMP(evcmpltu);
GEN_SPEOP_COMP(evcmplts);
GEN_SPEOP_COMP(evcmpeq);

GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////

6227
static always_inline void gen_evsel (DisasContext *ctx)
6228 6229
{
    if (unlikely(!ctx->spe_enabled)) {
6230
        GEN_EXCP_NO_AP(ctx);
6231 6232
        return;
    }
A
aurel32 已提交
6233
    tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
A
aurel32 已提交
6234 6235
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
6236
    gen_op_evsel();
A
aurel32 已提交
6237
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6238 6239
}

6240
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6241 6242 6243
{
    gen_evsel(ctx);
}
6244
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6245 6246 6247
{
    gen_evsel(ctx);
}
6248
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6249 6250 6251
{
    gen_evsel(ctx);
}
6252
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266
{
    gen_evsel(ctx);
}

/* Load and stores */
GEN_SPEOP_LDST(dd, 3);
GEN_SPEOP_LDST(dw, 3);
GEN_SPEOP_LDST(dh, 3);
GEN_SPEOP_LDST(whe, 2);
GEN_SPEOP_LD(whou, 2);
GEN_SPEOP_LD(whos, 2);
GEN_SPEOP_ST(who, 2);

#define _GEN_OP_SPE_STWWE(suffix)                                             \
6267
static always_inline void gen_op_spe_stwwe_##suffix (void)                    \
6268 6269 6270 6271 6272
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_##suffix();                                              \
}
#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
6273
static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
6274 6275 6276 6277 6278 6279 6280 6281
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_le_##suffix();                                           \
}
#if defined(TARGET_PPC64)
#define GEN_OP_SPE_STWWE(suffix)                                              \
_GEN_OP_SPE_STWWE(suffix);                                                    \
_GEN_OP_SPE_STWWE_LE(suffix);                                                 \
6282
static always_inline void gen_op_spe_stwwe_64_##suffix (void)                 \
6283 6284 6285 6286
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_64_##suffix();                                           \
}                                                                             \
6287
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_le_64_##suffix();                                        \
}
#else
#define GEN_OP_SPE_STWWE(suffix)                                              \
_GEN_OP_SPE_STWWE(suffix);                                                    \
_GEN_OP_SPE_STWWE_LE(suffix)
#endif
#if defined(CONFIG_USER_ONLY)
GEN_OP_SPE_STWWE(raw);
#else /* defined(CONFIG_USER_ONLY) */
GEN_OP_SPE_STWWE(user);
6301 6302
GEN_OP_SPE_STWWE(kernel);
GEN_OP_SPE_STWWE(hypv);
6303 6304 6305 6306 6307
#endif /* defined(CONFIG_USER_ONLY) */
GEN_SPEOP_ST(wwe, 2);
GEN_SPEOP_ST(wwo, 2);

#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
6308
static always_inline void gen_op_spe_l##name##_##suffix (void)                \
6309 6310 6311 6312 6313 6314
{                                                                             \
    gen_op_##op##_##suffix();                                                 \
    gen_op_splatw_T1_64();                                                    \
}

#define GEN_OP_SPE_LHE(suffix)                                                \
6315
static always_inline void gen_op_spe_lhe_##suffix (void)                      \
6316 6317 6318 6319 6320 6321
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_sli16_T1_64();                                                     \
}

#define GEN_OP_SPE_LHX(suffix)                                                \
6322
static always_inline void gen_op_spe_lhx_##suffix (void)                      \
6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_extsh_T1_64();                                                     \
}

#if defined(CONFIG_USER_ONLY)
GEN_OP_SPE_LHE(raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
GEN_OP_SPE_LHE(le_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
GEN_OP_SPE_LHX(raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
GEN_OP_SPE_LHX(le_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
GEN_OP_SPE_LHE(le_64_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
GEN_OP_SPE_LHX(64_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
GEN_OP_SPE_LHX(le_64_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
#endif
#else
GEN_OP_SPE_LHE(user);
6353 6354
GEN_OP_SPE_LHE(kernel);
GEN_OP_SPE_LHE(hypv);
6355
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
6356 6357
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
6358
GEN_OP_SPE_LHE(le_user);
6359 6360
GEN_OP_SPE_LHE(le_kernel);
GEN_OP_SPE_LHE(le_hypv);
6361
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
6362 6363
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
6364
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
6365 6366
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
6367
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
6368 6369
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
6370
GEN_OP_SPE_LHX(user);
6371 6372
GEN_OP_SPE_LHX(kernel);
GEN_OP_SPE_LHX(hypv);
6373
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
6374 6375
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
6376
GEN_OP_SPE_LHX(le_user);
6377 6378
GEN_OP_SPE_LHX(le_kernel);
GEN_OP_SPE_LHX(le_hypv);
6379
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
6380 6381
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
6382 6383
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_user);
6384 6385
GEN_OP_SPE_LHE(64_kernel);
GEN_OP_SPE_LHE(64_hypv);
6386
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
6387 6388
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
6389
GEN_OP_SPE_LHE(le_64_user);
6390 6391
GEN_OP_SPE_LHE(le_64_kernel);
GEN_OP_SPE_LHE(le_64_hypv);
6392
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
6393 6394
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
6395
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
6396 6397
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
6398
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
6399 6400
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
6401
GEN_OP_SPE_LHX(64_user);
6402 6403
GEN_OP_SPE_LHX(64_kernel);
GEN_OP_SPE_LHX(64_hypv);
6404
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
6405 6406
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
6407
GEN_OP_SPE_LHX(le_64_user);
6408 6409
GEN_OP_SPE_LHX(le_64_kernel);
GEN_OP_SPE_LHX(le_64_hypv);
6410
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
6411 6412
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517
#endif
#endif
GEN_SPEOP_LD(hhesplat, 1);
GEN_SPEOP_LD(hhousplat, 1);
GEN_SPEOP_LD(hhossplat, 1);
GEN_SPEOP_LD(wwsplat, 2);
GEN_SPEOP_LD(whsplat, 2);

GEN_SPE(evlddx,         evldd,         0x00, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evldwx,         evldw,         0x01, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evldhx,         evldh,         0x02, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhesplatx,   evlhhesplat,   0x04, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhousplatx,  evlhhousplat,  0x06, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhossplatx,  evlhhossplat,  0x07, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhex,        evlwhe,        0x08, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhoux,       evlwhou,       0x0A, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhosx,       evlwhos,       0x0B, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwwsplatx,    evlwwsplat,    0x0C, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhsplatx,    evlwhsplat,    0x0E, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstddx,        evstdd,        0x10, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstdwx,        evstdw,        0x11, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstdhx,        evstdh,        0x12, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwhex,       evstwhe,       0x18, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwhox,       evstwho,       0x1A, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwwex,       evstwwe,       0x1C, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwwox,       evstwwo,       0x1E, 0x0C, 0x00000000, PPC_SPE); //

/* Multiply and add - TODO */
#if 0
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);

GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);

GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);

GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);

GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);

GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);

GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
#endif

/***                      SPE floating-point extension                     ***/
#define GEN_SPEFPUOP_CONV(name)                                               \
6518
static always_inline void gen_##name (DisasContext *ctx)                      \
6519
{                                                                             \
A
aurel32 已提交
6520
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6521
    gen_op_##name();                                                          \
A
aurel32 已提交
6522
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598
}

/* Single precision floating-point vectors operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(evfsadd);
GEN_SPEOP_ARITH2(evfssub);
GEN_SPEOP_ARITH2(evfsmul);
GEN_SPEOP_ARITH2(evfsdiv);
GEN_SPEOP_ARITH1(evfsabs);
GEN_SPEOP_ARITH1(evfsnabs);
GEN_SPEOP_ARITH1(evfsneg);
/* Conversion */
GEN_SPEFPUOP_CONV(evfscfui);
GEN_SPEFPUOP_CONV(evfscfsi);
GEN_SPEFPUOP_CONV(evfscfuf);
GEN_SPEFPUOP_CONV(evfscfsf);
GEN_SPEFPUOP_CONV(evfsctui);
GEN_SPEFPUOP_CONV(evfsctsi);
GEN_SPEFPUOP_CONV(evfsctuf);
GEN_SPEFPUOP_CONV(evfsctsf);
GEN_SPEFPUOP_CONV(evfsctuiz);
GEN_SPEFPUOP_CONV(evfsctsiz);
/* Comparison */
GEN_SPEOP_COMP(evfscmpgt);
GEN_SPEOP_COMP(evfscmplt);
GEN_SPEOP_COMP(evfscmpeq);
GEN_SPEOP_COMP(evfststgt);
GEN_SPEOP_COMP(evfststlt);
GEN_SPEOP_COMP(evfststeq);

/* Opcodes definitions */
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //

/* Single precision floating-point operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(efsadd);
GEN_SPEOP_ARITH2(efssub);
GEN_SPEOP_ARITH2(efsmul);
GEN_SPEOP_ARITH2(efsdiv);
GEN_SPEOP_ARITH1(efsabs);
GEN_SPEOP_ARITH1(efsnabs);
GEN_SPEOP_ARITH1(efsneg);
/* Conversion */
GEN_SPEFPUOP_CONV(efscfui);
GEN_SPEFPUOP_CONV(efscfsi);
GEN_SPEFPUOP_CONV(efscfuf);
GEN_SPEFPUOP_CONV(efscfsf);
GEN_SPEFPUOP_CONV(efsctui);
GEN_SPEFPUOP_CONV(efsctsi);
GEN_SPEFPUOP_CONV(efsctuf);
GEN_SPEFPUOP_CONV(efsctsf);
GEN_SPEFPUOP_CONV(efsctuiz);
GEN_SPEFPUOP_CONV(efsctsiz);
GEN_SPEFPUOP_CONV(efscfd);
/* Comparison */
GEN_SPEOP_COMP(efscmpgt);
GEN_SPEOP_COMP(efscmplt);
GEN_SPEOP_COMP(efscmpeq);
GEN_SPEOP_COMP(efststgt);
GEN_SPEOP_COMP(efststlt);
GEN_SPEOP_COMP(efststeq);

/* Opcodes definitions */
6599
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6600 6601 6602 6603 6604 6605 6606 6607 6608
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6609 6610
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //

/* Double precision floating-point operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(efdadd);
GEN_SPEOP_ARITH2(efdsub);
GEN_SPEOP_ARITH2(efdmul);
GEN_SPEOP_ARITH2(efddiv);
GEN_SPEOP_ARITH1(efdabs);
GEN_SPEOP_ARITH1(efdnabs);
GEN_SPEOP_ARITH1(efdneg);
/* Conversion */

GEN_SPEFPUOP_CONV(efdcfui);
GEN_SPEFPUOP_CONV(efdcfsi);
GEN_SPEFPUOP_CONV(efdcfuf);
GEN_SPEFPUOP_CONV(efdcfsf);
GEN_SPEFPUOP_CONV(efdctui);
GEN_SPEFPUOP_CONV(efdctsi);
GEN_SPEFPUOP_CONV(efdctuf);
GEN_SPEFPUOP_CONV(efdctsf);
GEN_SPEFPUOP_CONV(efdctuiz);
GEN_SPEFPUOP_CONV(efdctsiz);
GEN_SPEFPUOP_CONV(efdcfs);
GEN_SPEFPUOP_CONV(efdcfuid);
GEN_SPEFPUOP_CONV(efdcfsid);
GEN_SPEFPUOP_CONV(efdctuidz);
GEN_SPEFPUOP_CONV(efdctsidz);
/* Comparison */
GEN_SPEOP_COMP(efdcmpgt);
GEN_SPEOP_COMP(efdcmplt);
GEN_SPEOP_COMP(efdcmpeq);
GEN_SPEOP_COMP(efdtstgt);
GEN_SPEOP_COMP(efdtstlt);
GEN_SPEOP_COMP(efdtsteq);

/* Opcodes definitions */
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //

B
bellard 已提交
6666 6667 6668
/* End opcode list */
GEN_OPCODE_MARK(end);

6669
#include "translate_init.c"
6670
#include "helper_regs.h"
B
bellard 已提交
6671

6672
/*****************************************************************************/
6673
/* Misc PowerPC helpers */
6674 6675 6676
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
6677
{
6678 6679 6680
#define RGPL  4
#define RFPL  4

B
bellard 已提交
6681 6682
    int i;

J
j_mayer 已提交
6683
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
A
aurel32 已提交
6684
                env->nip, env->lr, env->ctr, env->xer);
6685 6686
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6687
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
6688
    cpu_fprintf(f, "TB %08x %08x "
6689 6690 6691 6692
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
6693
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6694 6695 6696 6697
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
6698
#endif
6699
    for (i = 0; i < 32; i++) {
6700 6701
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
6702
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6703
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
6704
            cpu_fprintf(f, "\n");
6705
    }
6706
    cpu_fprintf(f, "CR ");
6707
    for (i = 0; i < 8; i++)
B
bellard 已提交
6708 6709
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
6710 6711 6712 6713 6714 6715 6716 6717
    for (i = 0; i < 8; i++) {
        char a = '-';
        if (env->crf[i] & 0x08)
            a = 'L';
        else if (env->crf[i] & 0x04)
            a = 'G';
        else if (env->crf[i] & 0x02)
            a = 'E';
B
bellard 已提交
6718
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6719
    }
6720
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
6721 6722 6723
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
6724
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6725
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
6726
            cpu_fprintf(f, "\n");
B
bellard 已提交
6727
    }
6728
#if !defined(CONFIG_USER_ONLY)
6729
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6730
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6731
#endif
B
bellard 已提交
6732

6733 6734
#undef RGPL
#undef RFPL
B
bellard 已提交
6735 6736
}

6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783
void cpu_dump_statistics (CPUState *env, FILE*f,
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
    opc_handler_t **t1, **t2, **t3, *handler;
    int op1, op2, op3;

    t1 = env->opcodes;
    for (op1 = 0; op1 < 64; op1++) {
        handler = t1[op1];
        if (is_indirect_opcode(handler)) {
            t2 = ind_table(handler);
            for (op2 = 0; op2 < 32; op2++) {
                handler = t2[op2];
                if (is_indirect_opcode(handler)) {
                    t3 = ind_table(handler);
                    for (op3 = 0; op3 < 32; op3++) {
                        handler = t3[op3];
                        if (handler->count == 0)
                            continue;
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
                                    "%016llx %lld\n",
                                    op1, op2, op3, op1, (op3 << 5) | op2,
                                    handler->oname,
                                    handler->count, handler->count);
                    }
                } else {
                    if (handler->count == 0)
                        continue;
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
                                "%016llx %lld\n",
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

6784
/*****************************************************************************/
6785 6786 6787
static always_inline void gen_intermediate_code_internal (CPUState *env,
                                                          TranslationBlock *tb,
                                                          int search_pc)
B
bellard 已提交
6788
{
6789
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
6790
    opc_handler_t **table, *handler;
B
bellard 已提交
6791
    target_ulong pc_start;
B
bellard 已提交
6792
    uint16_t *gen_opc_end;
6793
    int supervisor, little_endian;
B
bellard 已提交
6794
    int j, lj = -1;
P
pbrook 已提交
6795 6796
    int num_insns;
    int max_insns;
B
bellard 已提交
6797 6798 6799

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6800 6801 6802
#if defined(OPTIMIZE_FPRF_UPDATE)
    gen_fprf_ptr = gen_fprf_buf;
#endif
B
bellard 已提交
6803
    ctx.nip = pc_start;
B
bellard 已提交
6804
    ctx.tb = tb;
6805
    ctx.exception = POWERPC_EXCP_NONE;
6806
    ctx.spr_cb = env->spr_cb;
6807 6808
    supervisor = env->mmu_idx;
#if !defined(CONFIG_USER_ONLY)
6809
    ctx.supervisor = supervisor;
6810
#endif
6811
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6812 6813
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
6814
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6815
#else
6816
    ctx.mem_idx = (supervisor << 1) | little_endian;
6817
#endif
6818
    ctx.dcache_line_size = env->dcache_line_size;
B
bellard 已提交
6819
    ctx.fpu_enabled = msr_fp;
6820
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6821 6822 6823
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
6824 6825 6826 6827
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
6828
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6829
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
6830
    else
6831
        ctx.singlestep_enabled = 0;
6832
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6833 6834 6835
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6836
#if defined (DO_SINGLE_STEP) && 0
6837 6838 6839
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
6840 6841 6842 6843 6844 6845
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
6846
    /* Set env in case of segfault during code fetch */
6847
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6848 6849
        if (unlikely(env->nb_breakpoints > 0)) {
            for (j = 0; j < env->nb_breakpoints; j++) {
6850
                if (env->breakpoints[j] == ctx.nip) {
6851
                    gen_update_nip(&ctx, ctx.nip);
6852 6853 6854 6855 6856
                    gen_op_debug();
                    break;
                }
            }
        }
6857
        if (unlikely(search_pc)) {
B
bellard 已提交
6858 6859 6860 6861 6862
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
6863
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
6864
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
6865
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
6866 6867
            }
        }
6868 6869
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
6870
            fprintf(logfile, "----------------\n");
6871
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6872
                    ctx.nip, supervisor, (int)msr_ir);
6873 6874
        }
#endif
P
pbrook 已提交
6875 6876
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
6877 6878 6879 6880
        if (unlikely(little_endian)) {
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
6881
        }
6882 6883
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
6884
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6885
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6886
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
6887 6888
        }
#endif
B
bellard 已提交
6889
        ctx.nip += 4;
6890
        table = env->opcodes;
P
pbrook 已提交
6891
        num_insns++;
B
bellard 已提交
6892 6893 6894 6895 6896 6897 6898 6899 6900 6901
        handler = table[opc1(ctx.opcode)];
        if (is_indirect_opcode(handler)) {
            table = ind_table(handler);
            handler = table[opc2(ctx.opcode)];
            if (is_indirect_opcode(handler)) {
                table = ind_table(handler);
                handler = table[opc3(ctx.opcode)];
            }
        }
        /* Is opcode *REALLY* valid ? */
6902
        if (unlikely(handler->handler == &gen_invalid)) {
J
j_mayer 已提交
6903
            if (loglevel != 0) {
6904
                fprintf(logfile, "invalid/unsupported opcode: "
6905
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6906
                        opc1(ctx.opcode), opc2(ctx.opcode),
6907
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6908 6909
            } else {
                printf("invalid/unsupported opcode: "
6910
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
6911
                       opc1(ctx.opcode), opc2(ctx.opcode),
6912
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6913
            }
6914 6915
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
J
j_mayer 已提交
6916
                if (loglevel != 0) {
B
bellard 已提交
6917
                    fprintf(logfile, "invalid bits: %08x for opcode: "
6918
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
B
bellard 已提交
6919 6920
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6921
                            ctx.opcode, ctx.nip - 4);
6922 6923
                } else {
                    printf("invalid bits: %08x for opcode: "
6924
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
6925 6926
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6927
                           ctx.opcode, ctx.nip - 4);
6928
                }
6929
                GEN_EXCP_INVAL(ctxp);
B
bellard 已提交
6930
                break;
B
bellard 已提交
6931 6932
            }
        }
B
bellard 已提交
6933
        (*(handler->handler))(&ctx);
6934 6935 6936
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
6937
        /* Check trace mode exceptions */
6938 6939 6940 6941 6942
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
                     ctx.exception != POWERPC_SYSCALL &&
                     ctx.exception != POWERPC_EXCP_TRAP &&
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
6943
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6944
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
6945 6946
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
6947 6948 6949
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
6950
            break;
6951
        }
6952 6953 6954 6955
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
6956 6957
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
6958
    if (ctx.exception == POWERPC_EXCP_NONE) {
6959
        gen_goto_tb(&ctx, 0, ctx.nip);
6960
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6961 6962 6963 6964
        if (unlikely(env->singlestep_enabled)) {
            gen_update_nip(&ctx, ctx.nip);
            gen_op_debug();
        }
6965
        /* Generate the return instruction */
B
bellard 已提交
6966
        tcg_gen_exit_tb(0);
6967
    }
P
pbrook 已提交
6968
    gen_icount_end(tb, num_insns);
B
bellard 已提交
6969
    *gen_opc_ptr = INDEX_op_end;
6970
    if (unlikely(search_pc)) {
6971 6972 6973 6974 6975
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
6976
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
6977
        tb->icount = num_insns;
6978
    }
6979
#if defined(DEBUG_DISAS)
6980
    if (loglevel & CPU_LOG_TB_CPU) {
6981
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
B
bellard 已提交
6982
        cpu_dump_state(env, logfile, fprintf, 0);
6983 6984
    }
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6985
        int flags;
6986
        flags = env->bfd_mach;
6987
        flags |= little_endian << 16;
B
bellard 已提交
6988
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6989
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
B
bellard 已提交
6990
        fprintf(logfile, "\n");
6991
    }
B
bellard 已提交
6992 6993 6994
#endif
}

6995
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6996
{
6997
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
6998 6999
}

7000
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
7001
{
7002
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
7003
}
A
aurel32 已提交
7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
    int type, c;
    /* for PPC, we need to look at the micro operation to get the
     * access type */
    env->nip = gen_opc_pc[pc_pos];
    c = gen_opc_buf[pc_pos];
    switch(c) {
#if defined(CONFIG_USER_ONLY)
#define CASE3(op)\
    case INDEX_op_ ## op ## _raw
#else
#define CASE3(op)\
    case INDEX_op_ ## op ## _user:\
    case INDEX_op_ ## op ## _kernel:\
    case INDEX_op_ ## op ## _hypv
#endif

    CASE3(stfd):
    CASE3(stfs):
    CASE3(lfd):
    CASE3(lfs):
        type = ACCESS_FLOAT;
        break;
    CASE3(lwarx):
        type = ACCESS_RES;
        break;
    CASE3(stwcx):
        type = ACCESS_RES;
        break;
    CASE3(eciwx):
    CASE3(ecowx):
        type = ACCESS_EXT;
        break;
    default:
        type = ACCESS_INT;
        break;
    }
    env->access_type = type;
}