translate.c 356.9 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
S
Scott Wood 已提交
5
 *  Copyright (C) 2011 Freescale Semiconductor, Inc.
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17
 *
 * 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
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
19
 */
B
bellard 已提交
20

B
bellard 已提交
21
#include "cpu.h"
22
#include "disas/disas.h"
B
bellard 已提交
23
#include "tcg-op.h"
24
#include "qemu/host-utils.h"
B
bellard 已提交
25

P
pbrook 已提交
26 27 28 29
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

30 31 32 33
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

34
/* Include definitions for instructions classes and implementations flags */
35
//#define PPC_DEBUG_DISAS
36
//#define DO_PPC_STATISTICS
B
bellard 已提交
37

38
#ifdef PPC_DEBUG_DISAS
39
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40 41 42
#else
#  define LOG_DISAS(...) do { } while (0)
#endif
43 44
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
45

A
aurel32 已提交
46
/* global register indexes */
P
pbrook 已提交
47
static TCGv_ptr 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
P
pbrook 已提交
59 60 61
static TCGv_i64 cpu_fpr[32];
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
static TCGv_i32 cpu_crf[8];
A
aurel32 已提交
62
static TCGv cpu_nip;
63
static TCGv cpu_msr;
A
aurel32 已提交
64 65
static TCGv cpu_ctr;
static TCGv cpu_lr;
D
David Gibson 已提交
66 67 68
#if defined(TARGET_PPC64)
static TCGv cpu_cfar;
#endif
69
static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
70
static TCGv cpu_reserve;
71
static TCGv cpu_fpscr;
A
aurel32 已提交
72
static TCGv_i32 cpu_access_type;
A
aurel32 已提交
73

74
#include "exec/gen-icount.h"
P
pbrook 已提交
75 76 77

void ppc_translate_init(void)
{
A
aurel32 已提交
78 79
    int i;
    char* p;
80
    size_t cpu_reg_names_size;
P
pbrook 已提交
81
    static int done_init = 0;
A
aurel32 已提交
82

P
pbrook 已提交
83 84
    if (done_init)
        return;
A
aurel32 已提交
85

P
pbrook 已提交
86 87
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

A
aurel32 已提交
88
    p = cpu_reg_names;
89
    cpu_reg_names_size = sizeof(cpu_reg_names);
A
aurel32 已提交
90 91

    for (i = 0; i < 8; i++) {
92
        snprintf(p, cpu_reg_names_size, "crf%d", i);
P
pbrook 已提交
93
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
94
                                            offsetof(CPUPPCState, crf[i]), p);
A
aurel32 已提交
95
        p += 5;
96
        cpu_reg_names_size -= 5;
A
aurel32 已提交
97 98
    }

A
aurel32 已提交
99
    for (i = 0; i < 32; i++) {
100
        snprintf(p, cpu_reg_names_size, "r%d", i);
P
pbrook 已提交
101
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
102
                                        offsetof(CPUPPCState, gpr[i]), p);
A
aurel32 已提交
103
        p += (i < 10) ? 3 : 4;
104
        cpu_reg_names_size -= (i < 10) ? 3 : 4;
A
aurel32 已提交
105
#if !defined(TARGET_PPC64)
106
        snprintf(p, cpu_reg_names_size, "r%dH", i);
P
pbrook 已提交
107
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
108
                                             offsetof(CPUPPCState, gprh[i]), p);
A
aurel32 已提交
109
        p += (i < 10) ? 4 : 5;
110
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
A
aurel32 已提交
111
#endif
112

113
        snprintf(p, cpu_reg_names_size, "fp%d", i);
P
pbrook 已提交
114
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
115
                                            offsetof(CPUPPCState, fpr[i]), p);
A
aurel32 已提交
116
        p += (i < 10) ? 4 : 5;
117
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
A
aurel32 已提交
118

119
        snprintf(p, cpu_reg_names_size, "avr%dH", i);
120
#ifdef HOST_WORDS_BIGENDIAN
121
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
122
                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
123
#else
P
pbrook 已提交
124
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
125
                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
126
#endif
127
        p += (i < 10) ? 6 : 7;
128
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
A
aurel32 已提交
129

130
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
131
#ifdef HOST_WORDS_BIGENDIAN
132
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
133
                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
134
#else
P
pbrook 已提交
135
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
136
                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
137
#endif
138
        p += (i < 10) ? 6 : 7;
139
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
A
aurel32 已提交
140
    }
A
aurel32 已提交
141

P
pbrook 已提交
142
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
143
                                 offsetof(CPUPPCState, nip), "nip");
A
aurel32 已提交
144

145
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
146
                                 offsetof(CPUPPCState, msr), "msr");
147

P
pbrook 已提交
148
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
149
                                 offsetof(CPUPPCState, ctr), "ctr");
A
aurel32 已提交
150

P
pbrook 已提交
151
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
152
                                offsetof(CPUPPCState, lr), "lr");
A
aurel32 已提交
153

D
David Gibson 已提交
154 155
#if defined(TARGET_PPC64)
    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
156
                                  offsetof(CPUPPCState, cfar), "cfar");
D
David Gibson 已提交
157 158
#endif

P
pbrook 已提交
159
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
160
                                 offsetof(CPUPPCState, xer), "xer");
161 162 163 164 165 166
    cpu_so = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, so), "SO");
    cpu_ov = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, ov), "OV");
    cpu_ca = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, ca), "CA");
A
aurel32 已提交
167

168
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
169
                                     offsetof(CPUPPCState, reserve_addr),
170
                                     "reserve_addr");
171

172 173
    cpu_fpscr = tcg_global_mem_new(TCG_AREG0,
                                   offsetof(CPUPPCState, fpscr), "fpscr");
174

A
aurel32 已提交
175
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
176
                                             offsetof(CPUPPCState, access_type), "access_type");
A
aurel32 已提交
177

A
aurel32 已提交
178
    /* register helpers */
P
pbrook 已提交
179
#define GEN_HELPER 2
A
aurel32 已提交
180 181
#include "helper.h"

P
pbrook 已提交
182 183 184
    done_init = 1;
}

B
bellard 已提交
185 186 187
/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
B
bellard 已提交
188
    target_ulong nip;
B
bellard 已提交
189
    uint32_t opcode;
190
    uint32_t exception;
B
bellard 已提交
191 192
    /* Routine used to access memory */
    int mem_idx;
A
aurel32 已提交
193
    int access_type;
B
bellard 已提交
194
    /* Translation flags */
A
aurel32 已提交
195
    int le_mode;
196 197
#if defined(TARGET_PPC64)
    int sf_mode;
D
David Gibson 已提交
198
    int has_cfar;
199
#endif
B
bellard 已提交
200
    int fpu_enabled;
201
    int altivec_enabled;
202
    int spe_enabled;
A
Anthony Liguori 已提交
203
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
204
    int singlestep_enabled;
B
bellard 已提交
205 206
} DisasContext;

207 208 209 210 211 212 213
/* True when active word size < size of target_long.  */
#ifdef TARGET_PPC64
# define NARROW_MODE(C)  (!(C)->sf_mode)
#else
# define NARROW_MODE(C)  0
#endif

A
Anthony Liguori 已提交
214
struct opc_handler_t {
215 216 217 218
    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
    uint32_t inval1;
    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
    uint32_t inval2;
219
    /* instruction type */
220
    uint64_t type;
221 222
    /* extended instruction type */
    uint64_t type2;
B
bellard 已提交
223 224
    /* handler */
    void (*handler)(DisasContext *ctx);
225
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
226
    const char *oname;
227 228
#endif
#if defined(DO_PPC_STATISTICS)
229 230
    uint64_t count;
#endif
231
};
B
bellard 已提交
232

B
Blue Swirl 已提交
233
static inline void gen_reset_fpstatus(void)
234
{
235
    gen_helper_reset_fpstatus(cpu_env);
236 237
}

B
Blue Swirl 已提交
238
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
239
{
240
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
241

242 243
    if (set_fprf != 0) {
        /* This case might be optimized later */
244
        tcg_gen_movi_i32(t0, 1);
245
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
P
pbrook 已提交
246
        if (unlikely(set_rc)) {
247
            tcg_gen_mov_i32(cpu_crf[1], t0);
P
pbrook 已提交
248
        }
249
        gen_helper_float_check_status(cpu_env);
250 251
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
252
        tcg_gen_movi_i32(t0, 0);
253
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
254
        tcg_gen_mov_i32(cpu_crf[1], t0);
255
    }
A
aurel32 已提交
256

257
    tcg_temp_free_i32(t0);
258 259
}

B
Blue Swirl 已提交
260
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
261
{
A
aurel32 已提交
262 263 264 265
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
266 267
}

B
Blue Swirl 已提交
268
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
269
{
270 271 272 273
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_nip, nip);
274 275
}

B
Blue Swirl 已提交
276
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
277 278 279 280 281 282 283
{
    TCGv_i32 t0, t1;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
    t1 = tcg_const_i32(error);
284
    gen_helper_raise_exception_err(cpu_env, t0, t1);
A
aurel32 已提交
285 286 287 288
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
289

B
Blue Swirl 已提交
290
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
A
aurel32 已提交
291 292 293 294 295 296
{
    TCGv_i32 t0;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
297
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
298 299 300
    tcg_temp_free_i32(t0);
    ctx->exception = (excp);
}
301

B
Blue Swirl 已提交
302
static inline void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
303 304
{
    TCGv_i32 t0;
B
blueswir1 已提交
305

306 307
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
B
blueswir1 已提交
308
        gen_update_nip(ctx, ctx->nip);
309
    }
A
aurel32 已提交
310
    t0 = tcg_const_i32(EXCP_DEBUG);
311
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
312 313
    tcg_temp_free_i32(t0);
}
314

B
Blue Swirl 已提交
315
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
316 317 318
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
319

320
/* Stop translation */
B
Blue Swirl 已提交
321
static inline void gen_stop_exception(DisasContext *ctx)
322
{
323
    gen_update_nip(ctx, ctx->nip);
324
    ctx->exception = POWERPC_EXCP_STOP;
325 326
}

327
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
328
static inline void gen_sync_exception(DisasContext *ctx)
329
{
330
    ctx->exception = POWERPC_EXCP_SYNC;
331 332
}

B
bellard 已提交
333
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
334 335 336 337
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)

#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2)             \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
B
bellard 已提交
338

339
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
340 341 342 343
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)

#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2)      \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
344

A
Anthony Liguori 已提交
345
typedef struct opcode_t {
B
bellard 已提交
346
    unsigned char opc1, opc2, opc3;
T
ths 已提交
347
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
348 349 350 351
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
A
Anthony Liguori 已提交
352
    opc_handler_t handler;
353
    const char *oname;
A
Anthony Liguori 已提交
354
} opcode_t;
B
bellard 已提交
355

356
/*****************************************************************************/
B
bellard 已提交
357 358
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
B
Blue Swirl 已提交
359
static inline uint32_t name(uint32_t opcode)                                  \
B
bellard 已提交
360 361 362 363 364
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
B
Blue Swirl 已提交
365
static inline int32_t name(uint32_t opcode)                                   \
B
bellard 已提交
366
{                                                                             \
367
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
}

/* 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 */
395
EXTRACT_HELPER(_SPR, 11, 10);
B
Blue Swirl 已提交
396
static inline uint32_t SPR(uint32_t opcode)
397 398 399 400 401
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
402 403 404 405 406 407
/***                              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);
408 409
/* 5 bits signed immediate value */
EXTRACT_HELPER(SIMM5, 16, 5);
410 411
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
B
bellard 已提交
412 413 414 415
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
A
aurel32 已提交
416 417
/* Vector shift count */
EXTRACT_HELPER(VSH, 6, 4);
B
bellard 已提交
418 419 420 421
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
422 423
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
424 425 426 427

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

B
bellard 已提交
430 431 432 433
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
B
Blue Swirl 已提交
434
static inline target_ulong LI(uint32_t opcode)
B
bellard 已提交
435 436 437 438
{
    return (opcode >> 0) & 0x03FFFFFC;
}

B
Blue Swirl 已提交
439
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
440 441 442 443 444 445 446 447 448 449 450 451
{
    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 */
B
Blue Swirl 已提交
452
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
453
{
454
    target_ulong ret;
B
bellard 已提交
455

456 457
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
458
        ret = UINT64_MAX << (63 - end);
459
    } else if (likely(end == 63)) {
460
        ret = UINT64_MAX >> start;
461 462 463
    }
#else
    if (likely(start == 0)) {
464
        ret = UINT32_MAX << (31  - end);
465
    } else if (likely(end == 31)) {
466
        ret = UINT32_MAX >> start;
467 468 469 470 471 472 473 474
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
475 476 477 478

    return ret;
}

479 480
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
481

482
#if defined(DO_PPC_STATISTICS)
483
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
484
{                                                                             \
B
bellard 已提交
485 486 487
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
488
    .pad  = { 0, },                                                           \
B
bellard 已提交
489
    .handler = {                                                              \
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
        .oname = stringify(name),                                             \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
507
        .type = _typ,                                                         \
508
        .type2 = _typ2,                                                       \
B
bellard 已提交
509
        .handler = &gen_##name,                                               \
510
        .oname = stringify(name),                                             \
B
bellard 已提交
511
    },                                                                        \
512
    .oname = stringify(name),                                                 \
B
bellard 已提交
513
}
514
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
515
{                                                                             \
516 517 518 519 520
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
521
        .inval1  = invl,                                                      \
522
        .type = _typ,                                                         \
523
        .type2 = _typ2,                                                       \
524 525 526 527 528
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
529
#else
530
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
531
{                                                                             \
532 533 534 535 536
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
553
        .type = _typ,                                                         \
554
        .type2 = _typ2,                                                       \
555
        .handler = &gen_##name,                                               \
556 557 558
    },                                                                        \
    .oname = stringify(name),                                                 \
}
559
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
560 561 562 563 564 565
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
566
        .inval1  = invl,                                                      \
567
        .type = _typ,                                                         \
568
        .type2 = _typ2,                                                       \
569 570 571 572 573
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
#endif
574

575
/* SPR load/store helpers */
B
Blue Swirl 已提交
576
static inline void gen_load_spr(TCGv t, int reg)
577
{
578
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
579
}
580

B
Blue Swirl 已提交
581
static inline void gen_store_spr(int reg, TCGv t)
582
{
583
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
584
}
585

586
/* Invalid instruction */
B
Blue Swirl 已提交
587
static void gen_invalid(DisasContext *ctx)
588
{
A
aurel32 已提交
589
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
590 591
}

A
Anthony Liguori 已提交
592
static opc_handler_t invalid_handler = {
593 594
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
595
    .type    = PPC_NONE,
596
    .type2   = PPC_NONE,
B
bellard 已提交
597 598 599
    .handler = gen_invalid,
};

600 601
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
602
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
603
{
604 605
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
606

607
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
608

609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
    tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_LT);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_GT);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_EQ);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
626 627
}

B
Blue Swirl 已提交
628
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
629
{
630
    TCGv t0 = tcg_const_tl(arg1);
631 632
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
633 634
}

B
Blue Swirl 已提交
635
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
636
{
637
    TCGv t0, t1;
638 639
    t0 = tcg_temp_new();
    t1 = tcg_temp_new();
640
    if (s) {
641 642
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
643
    } else {
644 645
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
646
    }
647 648 649
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
650 651
}

B
Blue Swirl 已提交
652
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
653
{
654
    TCGv t0 = tcg_const_tl(arg1);
655 656
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
657 658
}

B
Blue Swirl 已提交
659
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
660
{
661
    if (NARROW_MODE(ctx)) {
662
        gen_op_cmpi32(reg, 0, 1, 0);
663
    } else {
664
        gen_op_cmpi(reg, 0, 1, 0);
665
    }
666 667 668
}

/* cmp */
B
Blue Swirl 已提交
669
static void gen_cmp(DisasContext *ctx)
670
{
671
    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
672 673
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
674
    } else {
675 676
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
677
    }
678 679 680
}

/* cmpi */
B
Blue Swirl 已提交
681
static void gen_cmpi(DisasContext *ctx)
682
{
683
    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
684 685
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
686
    } else {
687 688
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
689
    }
690 691 692
}

/* cmpl */
B
Blue Swirl 已提交
693
static void gen_cmpl(DisasContext *ctx)
694
{
695
    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
696 697
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
698
    } else {
699 700
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
701
    }
702 703 704
}

/* cmpli */
B
Blue Swirl 已提交
705
static void gen_cmpli(DisasContext *ctx)
706
{
707
    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
708 709
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
710
    } else {
711 712
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
713
    }
714 715 716
}

/* isel (PowerPC 2.03 specification) */
B
Blue Swirl 已提交
717
static void gen_isel(DisasContext *ctx)
718 719 720 721
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
722
    TCGv_i32 t0;
723 724 725 726 727

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

    mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
728
    t0 = tcg_temp_new_i32();
729 730
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
731 732 733 734 735 736 737 738
    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);
P
pbrook 已提交
739
    tcg_temp_free_i32(t0);
740 741
}

B
bellard 已提交
742 743
/***                           Integer arithmetic                          ***/

B
Blue Swirl 已提交
744 745
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
746
{
747
    TCGv t0 = tcg_temp_new();
B
bellard 已提交
748

749
    tcg_gen_xor_tl(cpu_ov, arg0, arg1);
750
    tcg_gen_xor_tl(t0, arg1, arg2);
751 752 753 754 755 756
    if (sub) {
        tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
    } else {
        tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
    }
    tcg_temp_free(t0);
757
    if (NARROW_MODE(ctx)) {
758 759 760 761
        tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
    }
    tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
B
bellard 已提交
762 763
}

764
/* Common add function */
B
Blue Swirl 已提交
765
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
766 767
                                    TCGv arg2, bool add_ca, bool compute_ca,
                                    bool compute_ov, bool compute_rc0)
768
{
769
    TCGv t0 = ret;
770

771 772
    if (((compute_ca && add_ca) || compute_ov)
        && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
773
        t0 = tcg_temp_new();
774
    }
B
bellard 已提交
775

776
    if (compute_ca) {
777 778 779 780 781 782 783 784 785 786
        if (NARROW_MODE(ctx)) {
            TCGv t1 = tcg_temp_new();
            tcg_gen_ext32u_tl(t1, arg2);
            tcg_gen_ext32u_tl(t0, arg1);
            tcg_gen_add_tl(t0, t0, t1);
            tcg_temp_free(t1);
            if (add_ca) {
                tcg_gen_add_tl(t0, t0, cpu_ca);
            }
            tcg_gen_shri_tl(cpu_ca, t0, 32);
787
        } else {
788 789 790 791 792 793 794 795
            TCGv zero = tcg_const_tl(0);
            if (add_ca) {
                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
                tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
            } else {
                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
            }
            tcg_temp_free(zero);
796 797 798 799 800 801
        }
    } else {
        tcg_gen_add_tl(t0, arg1, arg2);
        if (add_ca) {
            tcg_gen_add_tl(t0, t0, cpu_ca);
        }
802
    }
B
bellard 已提交
803

804 805 806
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
    }
807
    if (unlikely(compute_rc0)) {
808
        gen_set_Rc0(ctx, t0);
809
    }
810

P
pbrook 已提交
811
    if (!TCGV_EQUAL(t0, ret)) {
812 813 814
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
815
}
816 817
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
818
static void glue(gen_, name)(DisasContext *ctx)                               \
819 820 821
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
822
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
823 824 825 826
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
827
static void glue(gen_, name)(DisasContext *ctx)                               \
828
{                                                                             \
829
    TCGv t0 = tcg_const_tl(const_val);                                        \
830 831
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
832
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
    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 */
B
Blue Swirl 已提交
852
static void gen_addi(DisasContext *ctx)
853
{
854 855 856 857 858 859
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
860 861
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm);
862
    }
863
}
864
/* addic  addic.*/
865
static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
866
{
867 868 869 870
    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                     c, 0, 1, 0, compute_rc0);
    tcg_temp_free(c);
871
}
B
Blue Swirl 已提交
872 873

static void gen_addic(DisasContext *ctx)
874
{
875
    gen_op_addic(ctx, 0);
876
}
B
Blue Swirl 已提交
877 878

static void gen_addic_(DisasContext *ctx)
879
{
880
    gen_op_addic(ctx, 1);
881
}
B
Blue Swirl 已提交
882

883
/* addis */
B
Blue Swirl 已提交
884
static void gen_addis(DisasContext *ctx)
885
{
886 887 888 889 890 891
    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 {
892 893
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm << 16);
894
    }
895
}
896

B
Blue Swirl 已提交
897 898
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
899
{
900 901
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
902 903
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
904

905 906 907
    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
908
    if (sign) {
909 910 911
        int l3 = gen_new_label();
        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
912
        gen_set_label(l3);
913
        tcg_gen_div_i32(t0, t0, t1);
914
    } else {
915
        tcg_gen_divu_i32(t0, t0, t1);
916 917
    }
    if (compute_ov) {
918
        tcg_gen_movi_tl(cpu_ov, 0);
919 920 921 922
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
923
        tcg_gen_sari_i32(t0, t0, 31);
924 925 926 927
    } else {
        tcg_gen_movi_i32(t0, 0);
    }
    if (compute_ov) {
928 929
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
930 931
    }
    gen_set_label(l2);
932
    tcg_gen_extu_i32_tl(ret, t0);
P
pbrook 已提交
933 934
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
935 936
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
937
}
938 939
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
940
static void glue(gen_, name)(DisasContext *ctx)                                       \
941 942 943 944 945 946 947 948 949 950 951
{                                                                             \
    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);
952
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
953 954
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
955
{
956 957
    int l1 = gen_new_label();
    int l2 = gen_new_label();
958 959 960

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
961
        int l3 = gen_new_label();
962 963 964 965 966 967 968 969
        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);
        tcg_gen_div_i64(ret, arg1, arg2);
    } else {
        tcg_gen_divu_i64(ret, arg1, arg2);
    }
    if (compute_ov) {
970
        tcg_gen_movi_tl(cpu_ov, 0);
971 972 973 974 975 976 977 978 979
    }
    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) {
980 981
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
982 983 984 985
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
986
}
987
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
988
static void glue(gen_, name)(DisasContext *ctx)                                       \
989
{                                                                             \
990 991 992
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
993 994 995 996 997 998 999
}
/* 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);
1000
#endif
1001 1002

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1003
static void gen_mulhw(DisasContext *ctx)
1004
{
1005 1006
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1007

1008 1009 1010 1011 1012 1013
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_muls2_i32(t0, t1, t0, t1);
    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1014 1015
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1016
}
B
Blue Swirl 已提交
1017

1018
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1019
static void gen_mulhwu(DisasContext *ctx)
1020
{
1021 1022
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1023

1024 1025 1026 1027 1028 1029
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mulu2_i32(t0, t1, t0, t1);
    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1030 1031
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1032
}
B
Blue Swirl 已提交
1033

1034
/* mullw  mullw. */
B
Blue Swirl 已提交
1035
static void gen_mullw(DisasContext *ctx)
1036
{
1037 1038
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1039
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1040 1041
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1042
}
B
Blue Swirl 已提交
1043

1044
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1045
static void gen_mullwo(DisasContext *ctx)
1046
{
1047 1048
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1049

1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_muls2_i32(t0, t1, t0, t1);
    tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);

    tcg_gen_sari_i32(t0, t0, 31);
    tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
    tcg_gen_extu_i32_tl(cpu_ov, t0);
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);

    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1062 1063
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1064
}
B
Blue Swirl 已提交
1065

1066
/* mulli */
B
Blue Swirl 已提交
1067
static void gen_mulli(DisasContext *ctx)
1068
{
1069 1070
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1071
}
1072

1073
#if defined(TARGET_PPC64)
1074
/* mulhd  mulhd. */
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
static void gen_mulhd(DisasContext *ctx)
{
    TCGv lo = tcg_temp_new();
    tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(lo);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
}

1086
/* mulhdu  mulhdu. */
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
static void gen_mulhdu(DisasContext *ctx)
{
    TCGv lo = tcg_temp_new();
    tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(lo);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
}
B
Blue Swirl 已提交
1097

1098
/* mulld  mulld. */
B
Blue Swirl 已提交
1099
static void gen_mulld(DisasContext *ctx)
1100
{
1101 1102 1103 1104
    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)]);
1105
}
1106

1107
/* mulldo  mulldo. */
1108 1109 1110 1111 1112 1113 1114 1115
static void gen_mulldo(DisasContext *ctx)
{
    gen_helper_mulldo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                      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)]);
    }
}
1116
#endif
1117 1118

/* Common subf function */
B
Blue Swirl 已提交
1119
static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1120 1121
                                     TCGv arg2, bool add_ca, bool compute_ca,
                                     bool compute_ov, bool compute_rc0)
B
bellard 已提交
1122
{
1123
    TCGv t0 = ret;
B
bellard 已提交
1124

1125
    if (compute_ov && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
1126
        t0 = tcg_temp_new();
1127
    }
1128

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
    if (compute_ca) {
        /* dest = ~arg1 + arg2 [+ ca].  */
        if (NARROW_MODE(ctx)) {
            TCGv inv1 = tcg_temp_new();
            tcg_gen_not_tl(inv1, arg1);
            tcg_gen_ext32u_tl(t0, arg2);
            tcg_gen_ext32u_tl(inv1, inv1);
            if (add_ca) {
                tcg_gen_add_tl(t0, t0, cpu_ca);
            } else {
                tcg_gen_addi_tl(t0, t0, 1);
            }
            tcg_gen_add_tl(t0, t0, inv1);
            tcg_gen_shri_tl(cpu_ca, t0, 32);
        } else if (add_ca) {
R
Richard Henderson 已提交
1144 1145
            TCGv zero, inv1 = tcg_temp_new();
            tcg_gen_not_tl(inv1, arg1);
1146 1147
            zero = tcg_const_tl(0);
            tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
R
Richard Henderson 已提交
1148
            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
1149
            tcg_temp_free(zero);
R
Richard Henderson 已提交
1150
            tcg_temp_free(inv1);
1151
        } else {
1152
            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
1153 1154
            tcg_gen_sub_tl(t0, arg2, arg1);
        }
1155 1156 1157 1158 1159 1160
    } else if (add_ca) {
        /* Since we're ignoring carry-out, we can simplify the
           standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.  */
        tcg_gen_sub_tl(t0, arg2, arg1);
        tcg_gen_add_tl(t0, t0, cpu_ca);
        tcg_gen_subi_tl(t0, t0, 1);
B
bellard 已提交
1161
    } else {
1162
        tcg_gen_sub_tl(t0, arg2, arg1);
1163
    }
1164

1165 1166 1167
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }
1168
    if (unlikely(compute_rc0)) {
1169
        gen_set_Rc0(ctx, t0);
1170
    }
1171

P
pbrook 已提交
1172
    if (!TCGV_EQUAL(t0, ret)) {
1173 1174
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1175 1176
    }
}
1177 1178
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1179
static void glue(gen_, name)(DisasContext *ctx)                               \
1180 1181 1182
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1183
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1184 1185 1186 1187
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
1188
static void glue(gen_, name)(DisasContext *ctx)                               \
1189
{                                                                             \
1190
    TCGv t0 = tcg_const_tl(const_val);                                        \
1191 1192
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1193
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
    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
Blue Swirl 已提交
1211

1212
/* subfic */
B
Blue Swirl 已提交
1213
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1214
{
1215 1216 1217 1218
    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                      c, 0, 1, 0, 0);
    tcg_temp_free(c);
B
bellard 已提交
1219 1220
}

1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
/* neg neg. nego nego. */
static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
{
    TCGv zero = tcg_const_tl(0);
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                      zero, 0, 0, compute_ov, Rc(ctx->opcode));
    tcg_temp_free(zero);
}

static void gen_neg(DisasContext *ctx)
{
    gen_op_arith_neg(ctx, 0);
}

static void gen_nego(DisasContext *ctx)
{
    gen_op_arith_neg(ctx, 1);
}

B
bellard 已提交
1240
/***                            Integer logical                            ***/
1241
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1242
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1243
{                                                                             \
1244 1245
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1246
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1247
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1248 1249
}

1250
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1251
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1252
{                                                                             \
1253
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1254
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1255
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1256 1257 1258
}

/* and & and. */
1259
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1260
/* andc & andc. */
1261
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1262

1263
/* andi. */
B
Blue Swirl 已提交
1264
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1265
{
1266 1267
    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 已提交
1268
}
B
Blue Swirl 已提交
1269

1270
/* andis. */
B
Blue Swirl 已提交
1271
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1272
{
1273 1274
    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 已提交
1275
}
B
Blue Swirl 已提交
1276

1277
/* cntlzw */
B
Blue Swirl 已提交
1278
static void gen_cntlzw(DisasContext *ctx)
1279
{
P
pbrook 已提交
1280
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1281
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1282
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1283
}
B
bellard 已提交
1284
/* eqv & eqv. */
1285
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1286
/* extsb & extsb. */
1287
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1288
/* extsh & extsh. */
1289
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1290
/* nand & nand. */
1291
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1292
/* nor & nor. */
1293
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
Blue Swirl 已提交
1294

1295
/* or & or. */
B
Blue Swirl 已提交
1296
static void gen_or(DisasContext *ctx)
1297
{
1298 1299 1300 1301 1302 1303 1304
    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) {
1305 1306 1307 1308
        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]);
1309
        if (unlikely(Rc(ctx->opcode) != 0))
1310
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1311
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1312
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1313 1314
#if defined(TARGET_PPC64)
    } else {
1315 1316
        int prio = 0;

1317 1318 1319
        switch (rs) {
        case 1:
            /* Set process priority to low */
1320
            prio = 2;
1321 1322 1323
            break;
        case 6:
            /* Set process priority to medium-low */
1324
            prio = 3;
1325 1326 1327
            break;
        case 2:
            /* Set process priority to normal */
1328
            prio = 4;
1329
            break;
1330 1331
#if !defined(CONFIG_USER_ONLY)
        case 31:
A
aurel32 已提交
1332
            if (ctx->mem_idx > 0) {
1333
                /* Set process priority to very low */
1334
                prio = 1;
1335 1336 1337
            }
            break;
        case 5:
A
aurel32 已提交
1338
            if (ctx->mem_idx > 0) {
1339
                /* Set process priority to medium-hight */
1340
                prio = 5;
1341 1342 1343
            }
            break;
        case 3:
A
aurel32 已提交
1344
            if (ctx->mem_idx > 0) {
1345
                /* Set process priority to high */
1346
                prio = 6;
1347 1348 1349
            }
            break;
        case 7:
A
aurel32 已提交
1350
            if (ctx->mem_idx > 1) {
1351
                /* Set process priority to very high */
1352
                prio = 7;
1353 1354 1355
            }
            break;
#endif
1356 1357 1358 1359
        default:
            /* nop */
            break;
        }
1360
        if (prio) {
P
pbrook 已提交
1361
            TCGv t0 = tcg_temp_new();
1362
            gen_load_spr(t0, SPR_PPR);
1363 1364
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1365
            gen_store_spr(SPR_PPR, t0);
1366
            tcg_temp_free(t0);
1367
        }
1368
#endif
1369 1370
    }
}
B
bellard 已提交
1371
/* orc & orc. */
1372
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
Blue Swirl 已提交
1373

1374
/* xor & xor. */
B
Blue Swirl 已提交
1375
static void gen_xor(DisasContext *ctx)
1376 1377
{
    /* Optimisation for "set to zero" case */
1378
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1379
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1380 1381
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1382
    if (unlikely(Rc(ctx->opcode) != 0))
1383
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1384
}
B
Blue Swirl 已提交
1385

1386
/* ori */
B
Blue Swirl 已提交
1387
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1388
{
1389
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1390

1391 1392
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1393
        /* XXX: should handle special NOPs for POWER series */
1394
        return;
1395
    }
1396
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1397
}
B
Blue Swirl 已提交
1398

1399
/* oris */
B
Blue Swirl 已提交
1400
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1401
{
1402
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1403

1404 1405 1406
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1407
    }
1408
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1409
}
B
Blue Swirl 已提交
1410

1411
/* xori */
B
Blue Swirl 已提交
1412
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1413
{
1414
    target_ulong uimm = UIMM(ctx->opcode);
1415 1416 1417 1418 1419

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1420
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1421
}
B
Blue Swirl 已提交
1422

1423
/* xoris */
B
Blue Swirl 已提交
1424
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1425
{
1426
    target_ulong uimm = UIMM(ctx->opcode);
1427 1428 1429 1430 1431

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1432
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1433
}
B
Blue Swirl 已提交
1434

1435
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1436
static void gen_popcntb(DisasContext *ctx)
1437
{
1438 1439 1440 1441 1442 1443 1444 1445
    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
}

static void gen_popcntw(DisasContext *ctx)
{
    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
}

1446
#if defined(TARGET_PPC64)
1447 1448 1449 1450
/* popcntd: PowerPC 2.06 specification */
static void gen_popcntd(DisasContext *ctx)
{
    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1451
}
1452
#endif
1453 1454 1455

#if defined(TARGET_PPC64)
/* extsw & extsw. */
1456
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
B
Blue Swirl 已提交
1457

1458
/* cntlzd */
B
Blue Swirl 已提交
1459
static void gen_cntlzd(DisasContext *ctx)
1460
{
P
pbrook 已提交
1461
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1462 1463 1464
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1465 1466
#endif

B
bellard 已提交
1467
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1468

1469
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1470
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1471
{
1472
    uint32_t mb, me, sh;
B
bellard 已提交
1473 1474 1475

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1476
    sh = SH(ctx->opcode);
1477 1478 1479 1480
    if (likely(sh == 0 && mb == 0 && me == 31)) {
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        target_ulong mask;
P
pbrook 已提交
1481 1482
        TCGv t1;
        TCGv t0 = tcg_temp_new();
1483
#if defined(TARGET_PPC64)
P
pbrook 已提交
1484 1485 1486 1487 1488
        TCGv_i32 t2 = tcg_temp_new_i32();
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_rotli_i32(t2, t2, sh);
        tcg_gen_extu_i32_i64(t0, t2);
        tcg_temp_free_i32(t2);
1489 1490 1491
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1492
#if defined(TARGET_PPC64)
1493 1494
        mb += 32;
        me += 32;
1495
#endif
1496
        mask = MASK(mb, me);
P
pbrook 已提交
1497
        t1 = tcg_temp_new();
1498 1499 1500 1501 1502 1503
        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);
    }
1504
    if (unlikely(Rc(ctx->opcode) != 0))
1505
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1506
}
B
Blue Swirl 已提交
1507

1508
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1509
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1510 1511
{
    uint32_t mb, me, sh;
1512

B
bellard 已提交
1513 1514 1515
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1516 1517 1518 1519 1520

    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 {
P
pbrook 已提交
1521
            TCGv t0 = tcg_temp_new();
1522 1523 1524 1525
            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 已提交
1526
        }
1527
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
P
pbrook 已提交
1528
        TCGv t0 = tcg_temp_new();
1529 1530 1531 1532 1533
        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 {
P
pbrook 已提交
1534
        TCGv t0 = tcg_temp_new();
1535
#if defined(TARGET_PPC64)
P
pbrook 已提交
1536
        TCGv_i32 t1 = tcg_temp_new_i32();
1537 1538 1539
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_rotli_i32(t1, t1, sh);
        tcg_gen_extu_i32_i64(t0, t1);
P
pbrook 已提交
1540
        tcg_temp_free_i32(t1);
1541 1542 1543
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1544
#if defined(TARGET_PPC64)
1545 1546
        mb += 32;
        me += 32;
1547
#endif
1548 1549 1550
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
        tcg_temp_free(t0);
    }
1551
    if (unlikely(Rc(ctx->opcode) != 0))
1552
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1553
}
B
Blue Swirl 已提交
1554

1555
/* rlwnm & rlwnm. */
B
Blue Swirl 已提交
1556
static void gen_rlwnm(DisasContext *ctx)
B
bellard 已提交
1557 1558
{
    uint32_t mb, me;
1559 1560
    TCGv t0;
#if defined(TARGET_PPC64)
P
pbrook 已提交
1561
    TCGv_i32 t1, t2;
1562
#endif
B
bellard 已提交
1563 1564 1565

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1566
    t0 = tcg_temp_new();
1567
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1568
#if defined(TARGET_PPC64)
P
pbrook 已提交
1569 1570
    t1 = tcg_temp_new_i32();
    t2 = tcg_temp_new_i32();
1571 1572 1573 1574
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_trunc_i64_i32(t2, t0);
    tcg_gen_rotl_i32(t1, t1, t2);
    tcg_gen_extu_i32_i64(t0, t1);
P
pbrook 已提交
1575 1576
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
1577 1578 1579
#else
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
1580 1581 1582 1583 1584
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1585
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1586
    } else {
1587
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
B
bellard 已提交
1588
    }
1589
    tcg_temp_free(t0);
1590
    if (unlikely(Rc(ctx->opcode) != 0))
1591
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1592 1593
}

1594 1595
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1596
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1597 1598 1599
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
B
Blue Swirl 已提交
1600 1601
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1602 1603 1604 1605
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1606
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1607 1608 1609
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1610 1611
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1612 1613 1614
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1615 1616
                                                                              \
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1617 1618 1619
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1620 1621
                                                                              \
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1622 1623 1624
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1625

B
Blue Swirl 已提交
1626 1627
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
                              uint32_t sh)
J
j_mayer 已提交
1628
{
1629 1630 1631 1632 1633
    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 {
P
pbrook 已提交
1634
        TCGv t0 = tcg_temp_new();
1635
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1636
        if (likely(mb == 0 && me == 63)) {
1637
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1638 1639
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1640
        }
1641
        tcg_temp_free(t0);
J
j_mayer 已提交
1642 1643
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1644
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1645
}
1646
/* rldicl - rldicl. */
B
Blue Swirl 已提交
1647
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1648
{
J
j_mayer 已提交
1649
    uint32_t sh, mb;
1650

J
j_mayer 已提交
1651 1652
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1653
    gen_rldinm(ctx, mb, 63, sh);
1654
}
J
j_mayer 已提交
1655
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1656
/* rldicr - rldicr. */
B
Blue Swirl 已提交
1657
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1658
{
J
j_mayer 已提交
1659
    uint32_t sh, me;
1660

J
j_mayer 已提交
1661 1662
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1663
    gen_rldinm(ctx, 0, me, sh);
1664
}
J
j_mayer 已提交
1665
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1666
/* rldic - rldic. */
B
Blue Swirl 已提交
1667
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1668
{
J
j_mayer 已提交
1669
    uint32_t sh, mb;
1670

J
j_mayer 已提交
1671 1672
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1673 1674 1675 1676
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

B
Blue Swirl 已提交
1677
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
J
j_mayer 已提交
1678
{
1679
    TCGv t0;
1680 1681 1682

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1683
    t0 = tcg_temp_new();
1684
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1685
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1686
    if (unlikely(mb != 0 || me != 63)) {
1687 1688 1689 1690 1691
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    }
    tcg_temp_free(t0);
J
j_mayer 已提交
1692
    if (unlikely(Rc(ctx->opcode) != 0))
1693
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1694
}
J
j_mayer 已提交
1695

1696
/* rldcl - rldcl. */
B
Blue Swirl 已提交
1697
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1698
{
J
j_mayer 已提交
1699
    uint32_t mb;
1700

J
j_mayer 已提交
1701
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1702
    gen_rldnm(ctx, mb, 63);
1703
}
1704
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1705
/* rldcr - rldcr. */
B
Blue Swirl 已提交
1706
static inline void gen_rldcr(DisasContext *ctx, int men)
1707
{
J
j_mayer 已提交
1708
    uint32_t me;
1709

J
j_mayer 已提交
1710
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1711
    gen_rldnm(ctx, 0, me);
1712
}
1713
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1714
/* rldimi - rldimi. */
B
Blue Swirl 已提交
1715
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1716
{
1717
    uint32_t sh, mb, me;
1718

J
j_mayer 已提交
1719 1720
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1721
    me = 63 - sh;
1722 1723 1724 1725 1726 1727
    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;

P
pbrook 已提交
1728
        t0 = tcg_temp_new();
1729
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1730
        t1 = tcg_temp_new();
1731 1732 1733 1734 1735 1736
        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 已提交
1737 1738
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1739
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1740
}
1741
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1742 1743
#endif

B
bellard 已提交
1744
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1745

1746
/* slw & slw. */
B
Blue Swirl 已提交
1747
static void gen_slw(DisasContext *ctx)
1748
{
1749
    TCGv t0, t1;
1750

1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764
    t0 = tcg_temp_new();
    /* AND rS with a mask that is 0 when rB >= 0x20 */
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
    tcg_gen_sari_tl(t0, t0, 0x3f);
#else
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
    tcg_gen_sari_tl(t0, t0, 0x1f);
#endif
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t1);
1765
    tcg_temp_free(t0);
1766
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1767 1768 1769
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1770

1771
/* sraw & sraw. */
B
Blue Swirl 已提交
1772
static void gen_sraw(DisasContext *ctx)
1773
{
1774
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1775
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1776 1777 1778
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1779

1780
/* srawi & srawi. */
B
Blue Swirl 已提交
1781
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
1782
{
1783
    int sh = SH(ctx->opcode);
1784 1785 1786 1787
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
        tcg_gen_mov_tl(dst, src);
1788
        tcg_gen_movi_tl(cpu_ca, 0);
1789
    } else {
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801
        TCGv t0;
        tcg_gen_ext32s_tl(dst, src);
        tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
        t0 = tcg_temp_new();
        tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
        tcg_temp_free(t0);
        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
        tcg_gen_sari_tl(dst, dst, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
1802
    }
B
bellard 已提交
1803
}
B
Blue Swirl 已提交
1804

1805
/* srw & srw. */
B
Blue Swirl 已提交
1806
static void gen_srw(DisasContext *ctx)
1807
{
1808
    TCGv t0, t1;
1809

1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820
    t0 = tcg_temp_new();
    /* AND rS with a mask that is 0 when rB >= 0x20 */
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
    tcg_gen_sari_tl(t0, t0, 0x3f);
#else
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
    tcg_gen_sari_tl(t0, t0, 0x1f);
#endif
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    tcg_gen_ext32u_tl(t0, t0);
P
pbrook 已提交
1821
    t1 = tcg_temp_new();
1822 1823
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1824 1825
    tcg_temp_free(t1);
    tcg_temp_free(t0);
1826 1827 1828
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1829

1830 1831
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
1832
static void gen_sld(DisasContext *ctx)
1833
{
1834
    TCGv t0, t1;
1835

1836 1837 1838 1839 1840 1841 1842 1843 1844
    t0 = tcg_temp_new();
    /* AND rS with a mask that is 0 when rB >= 0x40 */
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
    tcg_gen_sari_tl(t0, t0, 0x3f);
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t1);
1845
    tcg_temp_free(t0);
1846 1847 1848
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1849

1850
/* srad & srad. */
B
Blue Swirl 已提交
1851
static void gen_srad(DisasContext *ctx)
1852
{
1853
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1854
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1855 1856 1857
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1858
/* sradi & sradi. */
B
Blue Swirl 已提交
1859
static inline void gen_sradi(DisasContext *ctx, int n)
1860
{
1861
    int sh = SH(ctx->opcode) + (n << 5);
1862 1863 1864 1865
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
        tcg_gen_mov_tl(dst, src);
1866
        tcg_gen_movi_tl(cpu_ca, 0);
1867
    } else {
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
        TCGv t0;
        tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
        t0 = tcg_temp_new();
        tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
        tcg_temp_free(t0);
        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
        tcg_gen_sari_tl(dst, src, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
1879 1880
    }
}
B
Blue Swirl 已提交
1881 1882

static void gen_sradi0(DisasContext *ctx)
1883 1884 1885
{
    gen_sradi(ctx, 0);
}
B
Blue Swirl 已提交
1886 1887

static void gen_sradi1(DisasContext *ctx)
1888 1889 1890
{
    gen_sradi(ctx, 1);
}
B
Blue Swirl 已提交
1891

1892
/* srd & srd. */
B
Blue Swirl 已提交
1893
static void gen_srd(DisasContext *ctx)
1894
{
1895
    TCGv t0, t1;
1896

1897 1898 1899 1900 1901 1902 1903 1904 1905
    t0 = tcg_temp_new();
    /* AND rS with a mask that is 0 when rB >= 0x40 */
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
    tcg_gen_sari_tl(t0, t0, 0x3f);
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t1);
1906
    tcg_temp_free(t0);
1907 1908 1909
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1910
#endif
B
bellard 已提交
1911 1912

/***                       Floating-Point arithmetic                       ***/
1913
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
B
Blue Swirl 已提交
1914
static void gen_f##name(DisasContext *ctx)                                    \
1915
{                                                                             \
1916
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
1917
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
1918 1919
        return;                                                               \
    }                                                                         \
1920 1921
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1922
    gen_reset_fpstatus();                                                     \
1923 1924
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
A
aurel32 已提交
1925
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
1926
    if (isfloat) {                                                            \
1927 1928
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
1929
    }                                                                         \
A
aurel32 已提交
1930 1931
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
                     Rc(ctx->opcode) != 0);                                   \
1932 1933
}

1934 1935 1936
#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);
1937

1938
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
1939
static void gen_f##name(DisasContext *ctx)                                    \
1940
{                                                                             \
1941
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
1942
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
1943 1944
        return;                                                               \
    }                                                                         \
1945 1946
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1947
    gen_reset_fpstatus();                                                     \
1948 1949
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
A
aurel32 已提交
1950
                     cpu_fpr[rB(ctx->opcode)]);                               \
1951
    if (isfloat) {                                                            \
1952 1953
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
1954
    }                                                                         \
A
aurel32 已提交
1955 1956
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
1957
}
1958 1959 1960
#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);
1961

1962
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
1963
static void gen_f##name(DisasContext *ctx)                                    \
1964
{                                                                             \
1965
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
1966
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
1967 1968
        return;                                                               \
    }                                                                         \
1969 1970
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1971
    gen_reset_fpstatus();                                                     \
1972 1973 1974
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
                     cpu_fpr[rC(ctx->opcode)]);                               \
1975
    if (isfloat) {                                                            \
1976 1977
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
1978
    }                                                                         \
A
aurel32 已提交
1979 1980
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
1981
}
1982 1983 1984
#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);
1985

1986
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
1987
static void gen_f##name(DisasContext *ctx)                                    \
1988
{                                                                             \
1989
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
1990
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
1991 1992
        return;                                                               \
    }                                                                         \
1993 1994
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1995
    gen_reset_fpstatus();                                                     \
1996 1997
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
1998 1999
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2000 2001
}

2002
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
B
Blue Swirl 已提交
2003
static void gen_f##name(DisasContext *ctx)                                    \
2004
{                                                                             \
2005
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2006
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2007 2008
        return;                                                               \
    }                                                                         \
2009 2010
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2011
    gen_reset_fpstatus();                                                     \
2012 2013
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
2014 2015
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2016 2017
}

2018
/* fadd - fadds */
2019
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2020
/* fdiv - fdivs */
2021
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2022
/* fmul - fmuls */
2023
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2024

2025
/* fre */
2026
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2027

2028
/* fres */
2029
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2030

2031
/* frsqrte */
2032 2033 2034
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2035
static void gen_frsqrtes(DisasContext *ctx)
2036
{
A
aurel32 已提交
2037
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2038
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2039 2040
        return;
    }
2041 2042
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2043
    gen_reset_fpstatus();
2044 2045 2046 2047
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
                       cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
                    cpu_fpr[rD(ctx->opcode)]);
A
aurel32 已提交
2048
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2049
}
B
bellard 已提交
2050

2051
/* fsel */
2052
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2053
/* fsub - fsubs */
2054
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2055
/* Optional: */
B
Blue Swirl 已提交
2056

2057
/* fsqrt */
B
Blue Swirl 已提交
2058
static void gen_fsqrt(DisasContext *ctx)
2059
{
2060
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2061
        gen_exception(ctx, POWERPC_EXCP_FPU);
2062 2063
        return;
    }
2064 2065
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2066
    gen_reset_fpstatus();
2067 2068
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
                     cpu_fpr[rB(ctx->opcode)]);
A
aurel32 已提交
2069
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2070
}
B
bellard 已提交
2071

B
Blue Swirl 已提交
2072
static void gen_fsqrts(DisasContext *ctx)
B
bellard 已提交
2073
{
2074
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2075
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2076 2077
        return;
    }
2078 2079
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2080
    gen_reset_fpstatus();
2081 2082 2083 2084
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
                     cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
                    cpu_fpr[rD(ctx->opcode)]);
A
aurel32 已提交
2085
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2086 2087 2088
}

/***                     Floating-Point multiply-and-add                   ***/
2089
/* fmadd - fmadds */
2090
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2091
/* fmsub - fmsubs */
2092
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2093
/* fnmadd - fnmadds */
2094
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2095
/* fnmsub - fnmsubs */
2096
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2097 2098 2099

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2100
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2101
/* fctiwz */
2102
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2103
/* frsp */
2104
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2105 2106
#if defined(TARGET_PPC64)
/* fcfid */
2107
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2108
/* fctid */
2109
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2110
/* fctidz */
2111
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2112
#endif
B
bellard 已提交
2113

2114
/* frin */
2115
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2116
/* friz */
2117
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2118
/* frip */
2119
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2120
/* frim */
2121
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2122

B
bellard 已提交
2123
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2124

2125
/* fcmpo */
B
Blue Swirl 已提交
2126
static void gen_fcmpo(DisasContext *ctx)
B
bellard 已提交
2127
{
A
aurel32 已提交
2128
    TCGv_i32 crf;
2129
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2130
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2131 2132
        return;
    }
2133 2134
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2135
    gen_reset_fpstatus();
A
aurel32 已提交
2136
    crf = tcg_const_i32(crfD(ctx->opcode));
2137 2138
    gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2139
    tcg_temp_free_i32(crf);
2140
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2141 2142 2143
}

/* fcmpu */
B
Blue Swirl 已提交
2144
static void gen_fcmpu(DisasContext *ctx)
B
bellard 已提交
2145
{
A
aurel32 已提交
2146
    TCGv_i32 crf;
2147
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2148
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2149 2150
        return;
    }
2151 2152
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2153
    gen_reset_fpstatus();
A
aurel32 已提交
2154
    crf = tcg_const_i32(crfD(ctx->opcode));
2155 2156
    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2157
    tcg_temp_free_i32(crf);
2158
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2159 2160
}

2161 2162
/***                         Floating-point move                           ***/
/* fabs */
2163 2164
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2165 2166

/* fmr  - fmr. */
2167
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2168
static void gen_fmr(DisasContext *ctx)
2169
{
2170
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2171
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2172 2173
        return;
    }
A
aurel32 已提交
2174 2175
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2176 2177 2178
}

/* fnabs */
2179 2180
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2181
/* fneg */
2182 2183
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2184

B
bellard 已提交
2185
/***                  Floating-Point status & ctrl register                ***/
B
Blue Swirl 已提交
2186

2187
/* mcrfs */
B
Blue Swirl 已提交
2188
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2189
{
2190
    TCGv tmp = tcg_temp_new();
2191 2192
    int bfa;

2193
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2194
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2195 2196
        return;
    }
2197
    bfa = 4 * (7 - crfS(ctx->opcode));
2198 2199 2200
    tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
    tcg_temp_free(tmp);
2201
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2202
    tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2203 2204 2205
}

/* mffs */
B
Blue Swirl 已提交
2206
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2207
{
2208
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2209
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2210 2211
        return;
    }
2212
    gen_reset_fpstatus();
2213
    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
A
aurel32 已提交
2214
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2215 2216 2217
}

/* mtfsb0 */
B
Blue Swirl 已提交
2218
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2219
{
B
bellard 已提交
2220
    uint8_t crb;
2221

2222
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2223
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2224 2225
        return;
    }
A
aurel32 已提交
2226
    crb = 31 - crbD(ctx->opcode);
2227
    gen_reset_fpstatus();
A
aurel32 已提交
2228
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2229 2230 2231 2232
        TCGv_i32 t0;
        /* NIP cannot be restored if the memory exception comes from an helper */
        gen_update_nip(ctx, ctx->nip - 4);
        t0 = tcg_const_i32(crb);
2233
        gen_helper_fpscr_clrbit(cpu_env, t0);
A
aurel32 已提交
2234 2235
        tcg_temp_free_i32(t0);
    }
2236
    if (unlikely(Rc(ctx->opcode) != 0)) {
2237 2238
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2239
    }
B
bellard 已提交
2240 2241 2242
}

/* mtfsb1 */
B
Blue Swirl 已提交
2243
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2244
{
B
bellard 已提交
2245
    uint8_t crb;
2246

2247
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2248
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2249 2250
        return;
    }
A
aurel32 已提交
2251
    crb = 31 - crbD(ctx->opcode);
2252 2253
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2254
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2255 2256 2257 2258
        TCGv_i32 t0;
        /* NIP cannot be restored if the memory exception comes from an helper */
        gen_update_nip(ctx, ctx->nip - 4);
        t0 = tcg_const_i32(crb);
2259
        gen_helper_fpscr_setbit(cpu_env, t0);
2260
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2261
    }
2262
    if (unlikely(Rc(ctx->opcode) != 0)) {
2263 2264
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2265 2266
    }
    /* We can raise a differed exception */
2267
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2268 2269 2270
}

/* mtfsf */
B
Blue Swirl 已提交
2271
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2272
{
2273
    TCGv_i32 t0;
B
blueswir1 已提交
2274
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2275

2276
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2277
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2278 2279
        return;
    }
2280 2281
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2282
    gen_reset_fpstatus();
B
blueswir1 已提交
2283 2284 2285 2286
    if (L)
        t0 = tcg_const_i32(0xff);
    else
        t0 = tcg_const_i32(FM(ctx->opcode));
2287
    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2288
    tcg_temp_free_i32(t0);
2289
    if (unlikely(Rc(ctx->opcode) != 0)) {
2290 2291
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2292 2293
    }
    /* We can raise a differed exception */
2294
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2295 2296 2297
}

/* mtfsfi */
B
Blue Swirl 已提交
2298
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2299
{
2300
    int bf, sh;
2301 2302
    TCGv_i64 t0;
    TCGv_i32 t1;
2303

2304
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2305
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2306 2307
        return;
    }
2308 2309
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2310 2311
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2312
    gen_reset_fpstatus();
2313
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2314
    t1 = tcg_const_i32(1 << sh);
2315
    gen_helper_store_fpscr(cpu_env, t0, t1);
2316 2317
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2318
    if (unlikely(Rc(ctx->opcode) != 0)) {
2319 2320
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2321 2322
    }
    /* We can raise a differed exception */
2323
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2324 2325
}

2326 2327
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2328 2329
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2330 2331 2332
{
    target_long simm = SIMM(ctx->opcode);

2333
    simm &= ~maskl;
A
aurel32 已提交
2334 2335 2336 2337 2338 2339
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2340
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2341
    } else if (likely(simm != 0)) {
2342
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
2354
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2355
    }
2356 2357
}

B
Blue Swirl 已提交
2358
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2359
{
A
aurel32 已提交
2360 2361 2362 2363 2364 2365
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        } else
#endif
2366
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2367
    } else {
2368
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2369 2370 2371 2372 2373 2374
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2375 2376
}

B
Blue Swirl 已提交
2377
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2378
{
A
aurel32 已提交
2379
    if (rA(ctx->opcode) == 0) {
2380
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
    }
}

B
Blue Swirl 已提交
2391 2392
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2393 2394 2395 2396 2397 2398 2399
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2400 2401
}

B
Blue Swirl 已提交
2402
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
{
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1, t2;
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    tcg_gen_andi_tl(t0, EA, mask);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
    t2 = tcg_const_i32(0);
2413
    gen_helper_raise_exception_err(cpu_env, t1, t2);
2414 2415 2416 2417 2418 2419
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2420
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2421
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2422 2423 2424 2425
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2426
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2427 2428 2429 2430
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2431
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2432 2433 2434
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2435
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2436
    }
A
aurel32 已提交
2437 2438
}

B
Blue Swirl 已提交
2439
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2440
{
A
aurel32 已提交
2441 2442
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2443
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2444 2445 2446 2447
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2448 2449
}

B
Blue Swirl 已提交
2450
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2451
{
A
aurel32 已提交
2452 2453
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2454
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2455
    }
A
aurel32 已提交
2456 2457
}

A
aurel32 已提交
2458
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2459
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2460
{
B
blueswir1 已提交
2461
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2462
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2463 2464
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2465
    } else
A
aurel32 已提交
2466
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2467
}
A
aurel32 已提交
2468
#endif
A
aurel32 已提交
2469

B
Blue Swirl 已提交
2470
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2471
{
A
aurel32 已提交
2472 2473
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2474
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2475
    }
A
aurel32 已提交
2476 2477
}

B
Blue Swirl 已提交
2478
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2479
{
A
aurel32 已提交
2480
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2481 2482
}

B
Blue Swirl 已提交
2483
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2484
{
A
aurel32 已提交
2485 2486 2487
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2488
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2489 2490 2491 2492 2493
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2494 2495
}

B
Blue Swirl 已提交
2496
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2497
{
A
aurel32 已提交
2498
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2499 2500 2501
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2502 2503 2504 2505 2506
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2507 2508
}

B
Blue Swirl 已提交
2509
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2510
{
A
aurel32 已提交
2511
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2512
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2513
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2514
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2515
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2516
    } else
A
aurel32 已提交
2517
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2518 2519
}

2520
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2521
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2522
{                                                                             \
A
aurel32 已提交
2523 2524 2525 2526 2527
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2528
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2529 2530
}

2531
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2532
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2533
{                                                                             \
A
aurel32 已提交
2534
    TCGv EA;                                                                  \
2535 2536
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2537
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2538
        return;                                                               \
2539
    }                                                                         \
A
aurel32 已提交
2540
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2541
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2542
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2543
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2544
    else                                                                      \
A
aurel32 已提交
2545 2546
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2547 2548
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2549 2550
}

2551
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2552
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2553
{                                                                             \
A
aurel32 已提交
2554
    TCGv EA;                                                                  \
2555 2556
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2557
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2558
        return;                                                               \
2559
    }                                                                         \
A
aurel32 已提交
2560
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2561
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2562 2563
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2564 2565
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2566 2567
}

2568
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
B
Blue Swirl 已提交
2569
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2570
{                                                                             \
A
aurel32 已提交
2571 2572 2573 2574 2575
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2576
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2577
}
2578 2579
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2580

2581 2582 2583 2584 2585
#define GEN_LDS(name, ldop, op, type)                                         \
GEN_LD(name, ldop, op | 0x20, type);                                          \
GEN_LDU(name, ldop, op | 0x21, type);                                         \
GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
B
bellard 已提交
2586 2587

/* lbz lbzu lbzux lbzx */
2588
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2589
/* lha lhau lhaux lhax */
2590
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2591
/* lhz lhzu lhzux lhzx */
2592
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2593
/* lwz lwzu lwzux lwzx */
2594
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2595 2596
#if defined(TARGET_PPC64)
/* lwaux */
2597
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2598
/* lwax */
2599
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2600
/* ldux */
2601
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2602
/* ldx */
2603
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2604 2605

static void gen_ld(DisasContext *ctx)
2606
{
A
aurel32 已提交
2607
    TCGv EA;
2608 2609 2610
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2611
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2612 2613 2614
            return;
        }
    }
A
aurel32 已提交
2615
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2616
    EA = tcg_temp_new();
A
aurel32 已提交
2617
    gen_addr_imm_index(ctx, EA, 0x03);
2618 2619
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2620
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2621 2622
    } else {
        /* ld - ldu */
A
aurel32 已提交
2623
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2624 2625
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2626 2627
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2628
}
B
Blue Swirl 已提交
2629

2630
/* lq */
B
Blue Swirl 已提交
2631
static void gen_lq(DisasContext *ctx)
2632 2633
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2634
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2635 2636
#else
    int ra, rd;
A
aurel32 已提交
2637
    TCGv EA;
2638 2639

    /* Restore CPU state */
A
aurel32 已提交
2640
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2641
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2642 2643 2644 2645 2646
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2647
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2648 2649
        return;
    }
A
aurel32 已提交
2650
    if (unlikely(ctx->le_mode)) {
2651
        /* Little-endian mode is not handled */
A
aurel32 已提交
2652
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2653 2654
        return;
    }
A
aurel32 已提交
2655
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2656
    EA = tcg_temp_new();
A
aurel32 已提交
2657 2658 2659 2660
    gen_addr_imm_index(ctx, EA, 0x0F);
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
    gen_addr_add(ctx, EA, EA, 8);
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
A
aurel32 已提交
2661
    tcg_temp_free(EA);
2662 2663
#endif
}
2664
#endif
B
bellard 已提交
2665 2666

/***                              Integer store                            ***/
2667
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2668
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2669
{                                                                             \
A
aurel32 已提交
2670 2671 2672 2673 2674
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2675
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2676 2677
}

2678
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2679
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2680
{                                                                             \
A
aurel32 已提交
2681
    TCGv EA;                                                                  \
2682
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2683
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2684
        return;                                                               \
2685
    }                                                                         \
A
aurel32 已提交
2686
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2687
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2688
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2689
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2690
    else                                                                      \
A
aurel32 已提交
2691 2692
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2693 2694
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2695 2696
}

2697
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2698
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2699
{                                                                             \
A
aurel32 已提交
2700
    TCGv EA;                                                                  \
2701
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2702
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2703
        return;                                                               \
2704
    }                                                                         \
A
aurel32 已提交
2705
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2706
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2707 2708
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2709 2710
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2711 2712
}

2713 2714
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2715
{                                                                             \
A
aurel32 已提交
2716 2717 2718 2719 2720
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2721
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2722
}
2723 2724
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2725

2726 2727 2728 2729 2730
#define GEN_STS(name, stop, op, type)                                         \
GEN_ST(name, stop, op | 0x20, type);                                          \
GEN_STU(name, stop, op | 0x21, type);                                         \
GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
GEN_STX(name, stop, 0x17, op | 0x00, type)
B
bellard 已提交
2731 2732

/* stb stbu stbux stbx */
2733
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2734
/* sth sthu sthux sthx */
2735
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2736
/* stw stwu stwux stwx */
2737
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2738
#if defined(TARGET_PPC64)
2739 2740
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2741 2742

static void gen_std(DisasContext *ctx)
2743
{
2744
    int rs;
A
aurel32 已提交
2745
    TCGv EA;
2746 2747 2748 2749

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2750
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2751 2752
#else
        /* stq */
A
aurel32 已提交
2753
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2754
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2755 2756 2757
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2758
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2759 2760
            return;
        }
A
aurel32 已提交
2761
        if (unlikely(ctx->le_mode)) {
2762
            /* Little-endian mode is not handled */
A
aurel32 已提交
2763
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2764 2765
            return;
        }
A
aurel32 已提交
2766
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2767
        EA = tcg_temp_new();
A
aurel32 已提交
2768 2769 2770 2771
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
        gen_addr_add(ctx, EA, EA, 8);
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
A
aurel32 已提交
2772
        tcg_temp_free(EA);
2773 2774 2775 2776 2777
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2778
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2779 2780 2781
                return;
            }
        }
A
aurel32 已提交
2782
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2783
        EA = tcg_temp_new();
A
aurel32 已提交
2784 2785
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2786
        if (Rc(ctx->opcode))
A
aurel32 已提交
2787 2788
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2789 2790 2791
    }
}
#endif
B
bellard 已提交
2792 2793
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2794
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2795
{
A
aurel32 已提交
2796 2797
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2798
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2799
    }
A
aurel32 已提交
2800
}
2801
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2802

B
bellard 已提交
2803
/* lwbrx */
2804
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2805
{
A
aurel32 已提交
2806 2807
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2808
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2809
    }
A
aurel32 已提交
2810
}
2811
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2812

2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824
#if defined(TARGET_PPC64)
/* ldbrx */
static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
        tcg_gen_bswap64_tl(arg1, arg1);
    }
}
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
#endif  /* TARGET_PPC64 */

B
bellard 已提交
2825
/* sthbrx */
2826
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2827
{
A
aurel32 已提交
2828 2829 2830
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2831
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2832 2833 2834 2835 2836
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2837
}
2838
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2839

B
bellard 已提交
2840
/* stwbrx */
2841
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2842
{
A
aurel32 已提交
2843
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2844 2845 2846
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2847 2848 2849 2850 2851
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2852
}
2853
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2854

2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870
#if defined(TARGET_PPC64)
/* stdbrx */
static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_bswap64_tl(t0, arg1);
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
    }
}
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
#endif  /* TARGET_PPC64 */

B
bellard 已提交
2871
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2872

2873
/* lmw */
B
Blue Swirl 已提交
2874
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2875
{
A
aurel32 已提交
2876 2877 2878
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2879
    /* NIP cannot be restored if the memory exception comes from an helper */
2880
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2881 2882 2883
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2884
    gen_helper_lmw(cpu_env, t0, t1);
2885 2886
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2887 2888 2889
}

/* stmw */
B
Blue Swirl 已提交
2890
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
2891
{
A
aurel32 已提交
2892 2893 2894
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2895
    /* NIP cannot be restored if the memory exception comes from an helper */
2896
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2897 2898 2899
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2900
    gen_helper_stmw(cpu_env, t0, t1);
2901 2902
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2903 2904 2905
}

/***                    Integer load and store strings                     ***/
2906

B
bellard 已提交
2907
/* lswi */
2908
/* PowerPC32 specification says we must generate an exception if
2909 2910 2911 2912
 * 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...
 */
B
Blue Swirl 已提交
2913
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
2914
{
2915 2916
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2917 2918
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2919
    int ra = rA(ctx->opcode);
B
bellard 已提交
2920 2921 2922 2923 2924
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2925 2926 2927
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
2928
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2929
        return;
B
bellard 已提交
2930
    }
A
aurel32 已提交
2931
    gen_set_access_type(ctx, ACCESS_INT);
2932
    /* NIP cannot be restored if the memory exception comes from an helper */
2933
    gen_update_nip(ctx, ctx->nip - 4);
2934
    t0 = tcg_temp_new();
A
aurel32 已提交
2935
    gen_addr_register(ctx, t0);
2936 2937
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
2938
    gen_helper_lsw(cpu_env, t0, t1, t2);
2939 2940 2941
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2942 2943 2944
}

/* lswx */
B
Blue Swirl 已提交
2945
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
2946
{
A
aurel32 已提交
2947 2948 2949
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
2950
    /* NIP cannot be restored if the memory exception comes from an helper */
2951
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2952 2953 2954 2955 2956
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_const_i32(rD(ctx->opcode));
    t2 = tcg_const_i32(rA(ctx->opcode));
    t3 = tcg_const_i32(rB(ctx->opcode));
2957
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
2958 2959 2960 2961
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
2962 2963 2964
}

/* stswi */
B
Blue Swirl 已提交
2965
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
2966
{
A
aurel32 已提交
2967 2968
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2969
    int nb = NB(ctx->opcode);
A
aurel32 已提交
2970
    gen_set_access_type(ctx, ACCESS_INT);
2971
    /* NIP cannot be restored if the memory exception comes from an helper */
2972
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2973 2974
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
2975 2976
    if (nb == 0)
        nb = 32;
2977
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
2978
    t2 = tcg_const_i32(rS(ctx->opcode));
2979
    gen_helper_stsw(cpu_env, t0, t1, t2);
2980 2981 2982
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2983 2984 2985
}

/* stswx */
B
Blue Swirl 已提交
2986
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
2987
{
A
aurel32 已提交
2988 2989 2990
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
2991
    /* NIP cannot be restored if the memory exception comes from an helper */
2992
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2993 2994 2995
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
2996 2997
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
2998
    t2 = tcg_const_i32(rS(ctx->opcode));
2999
    gen_helper_stsw(cpu_env, t0, t1, t2);
3000 3001 3002
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3003 3004 3005 3006
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3007
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3008 3009 3010 3011
{
}

/* isync */
B
Blue Swirl 已提交
3012
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3013
{
A
aurel32 已提交
3014
    gen_stop_exception(ctx);
B
bellard 已提交
3015 3016
}

3017
/* lwarx */
B
Blue Swirl 已提交
3018
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3019
{
A
aurel32 已提交
3020
    TCGv t0;
3021
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3022 3023 3024
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3025
    gen_check_align(ctx, t0, 0x03);
3026
    gen_qemu_ld32u(ctx, gpr, t0);
3027
    tcg_gen_mov_tl(cpu_reserve, t0);
3028
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3029
    tcg_temp_free(t0);
B
bellard 已提交
3030 3031
}

3032 3033 3034 3035 3036 3037 3038
#if defined(CONFIG_USER_ONLY)
static void gen_conditional_store (DisasContext *ctx, TCGv EA,
                                   int reg, int size)
{
    TCGv t0 = tcg_temp_new();
    uint32_t save_exception = ctx->exception;

3039
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3040
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3041
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3042 3043 3044 3045 3046 3047 3048 3049
    tcg_temp_free(t0);
    gen_update_nip(ctx, ctx->nip-4);
    ctx->exception = POWERPC_EXCP_BRANCH;
    gen_exception(ctx, POWERPC_EXCP_STCX);
    ctx->exception = save_exception;
}
#endif

B
bellard 已提交
3050
/* stwcx. */
B
Blue Swirl 已提交
3051
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3052
{
A
aurel32 已提交
3053 3054 3055 3056
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3057
    gen_check_align(ctx, t0, 0x03);
3058 3059 3060 3061 3062 3063
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
    {
        int l1;

3064
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3065 3066 3067 3068 3069 3070 3071 3072
        l1 = gen_new_label();
        tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
        gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
        gen_set_label(l1);
        tcg_gen_movi_tl(cpu_reserve, -1);
    }
#endif
3073
    tcg_temp_free(t0);
B
bellard 已提交
3074 3075
}

J
j_mayer 已提交
3076 3077
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3078
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3079
{
A
aurel32 已提交
3080
    TCGv t0;
3081
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3082 3083 3084
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3085
    gen_check_align(ctx, t0, 0x07);
3086
    gen_qemu_ld64(ctx, gpr, t0);
3087
    tcg_gen_mov_tl(cpu_reserve, t0);
3088
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3089
    tcg_temp_free(t0);
J
j_mayer 已提交
3090 3091 3092
}

/* stdcx. */
B
Blue Swirl 已提交
3093
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3094
{
A
aurel32 已提交
3095 3096 3097 3098
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3099
    gen_check_align(ctx, t0, 0x07);
3100 3101 3102 3103 3104
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
#else
    {
        int l1;
3105
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3106 3107 3108 3109 3110 3111 3112 3113
        l1 = gen_new_label();
        tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
        gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
        gen_set_label(l1);
        tcg_gen_movi_tl(cpu_reserve, -1);
    }
#endif
3114
    tcg_temp_free(t0);
J
j_mayer 已提交
3115 3116 3117
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3118
/* sync */
B
Blue Swirl 已提交
3119
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3120 3121 3122
{
}

3123
/* wait */
B
Blue Swirl 已提交
3124
static void gen_wait(DisasContext *ctx)
3125
{
3126
    TCGv_i32 t0 = tcg_temp_new_i32();
3127 3128
    tcg_gen_st_i32(t0, cpu_env,
                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3129
    tcg_temp_free_i32(t0);
3130
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3131
    gen_exception_err(ctx, EXCP_HLT, 1);
3132 3133
}

B
bellard 已提交
3134
/***                         Floating-point load                           ***/
3135
#define GEN_LDF(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
3136
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3137
{                                                                             \
3138
    TCGv EA;                                                                  \
3139
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3140
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3141 3142
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3143
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3144
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3145 3146
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3147
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3148 3149
}

3150
#define GEN_LDUF(name, ldop, opc, type)                                       \
B
Blue Swirl 已提交
3151
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3152
{                                                                             \
3153
    TCGv EA;                                                                  \
3154
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3155
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3156 3157
        return;                                                               \
    }                                                                         \
3158
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3159
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3160
        return;                                                               \
3161
    }                                                                         \
A
aurel32 已提交
3162
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3163
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3164 3165
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3166 3167
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3168 3169
}

3170
#define GEN_LDUXF(name, ldop, opc, type)                                      \
B
Blue Swirl 已提交
3171
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3172
{                                                                             \
3173
    TCGv EA;                                                                  \
3174
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3175
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3176 3177
        return;                                                               \
    }                                                                         \
3178
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3179
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3180
        return;                                                               \
3181
    }                                                                         \
A
aurel32 已提交
3182
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3183
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3184 3185
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3186 3187
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3188 3189
}

3190
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3191
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3192
{                                                                             \
3193
    TCGv EA;                                                                  \
3194
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3195
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3196 3197
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3198
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3199
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3200 3201
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3202
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3203 3204
}

3205 3206 3207 3208 3209 3210
#define GEN_LDFS(name, ldop, op, type)                                        \
GEN_LDF(name, ldop, op | 0x20, type);                                         \
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)

B
Blue Swirl 已提交
3211
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3212 3213 3214
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3215
    gen_qemu_ld32u(ctx, t0, arg2);
3216 3217
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
3218
    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3219 3220
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3221

3222 3223 3224 3225
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3226 3227

/***                         Floating-point store                          ***/
3228
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3229
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3230
{                                                                             \
3231
    TCGv EA;                                                                  \
3232
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3233
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3234 3235
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3236
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3237
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3238 3239
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3240
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3241 3242
}

3243
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3244
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3245
{                                                                             \
3246
    TCGv EA;                                                                  \
3247
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3248
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3249 3250
        return;                                                               \
    }                                                                         \
3251
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3252
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3253
        return;                                                               \
3254
    }                                                                         \
A
aurel32 已提交
3255
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3256
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3257 3258
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3259 3260
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3261 3262
}

3263
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3264
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3265
{                                                                             \
3266
    TCGv EA;                                                                  \
3267
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3268
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3269 3270
        return;                                                               \
    }                                                                         \
3271
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3272
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3273
        return;                                                               \
3274
    }                                                                         \
A
aurel32 已提交
3275
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3276
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3277 3278
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3279 3280
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3281 3282
}

3283
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3284
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3285
{                                                                             \
3286
    TCGv EA;                                                                  \
3287
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3288
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3289 3290
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3291
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3292
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3293 3294
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3295
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3296 3297
}

3298 3299 3300 3301 3302 3303
#define GEN_STFS(name, stop, op, type)                                        \
GEN_STF(name, stop, op | 0x20, type);                                         \
GEN_STUF(name, stop, op | 0x21, type);                                        \
GEN_STUXF(name, stop, op | 0x01, type);                                       \
GEN_STXF(name, stop, 0x17, op | 0x00, type)

B
Blue Swirl 已提交
3304
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3305 3306 3307
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
3308
    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3309 3310
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3311
    gen_qemu_st32(ctx, t1, arg2);
3312 3313
    tcg_temp_free(t1);
}
B
bellard 已提交
3314 3315

/* stfd stfdu stfdux stfdx */
3316
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3317
/* stfs stfsu stfsux stfsx */
3318
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3319 3320

/* Optional: */
B
Blue Swirl 已提交
3321
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3322 3323 3324
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3325
    gen_qemu_st32(ctx, t0, arg2);
3326 3327
    tcg_temp_free(t0);
}
B
bellard 已提交
3328
/* stfiwx */
3329
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3330

D
David Gibson 已提交
3331 3332 3333 3334 3335 3336 3337 3338
static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
{
#if defined(TARGET_PPC64)
    if (ctx->has_cfar)
        tcg_gen_movi_tl(cpu_cfar, nip);
#endif
}

B
bellard 已提交
3339
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3340
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3341 3342 3343
{
    TranslationBlock *tb;
    tb = ctx->tb;
3344
    if (NARROW_MODE(ctx)) {
3345
        dest = (uint32_t) dest;
3346
    }
B
bellard 已提交
3347
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3348
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3349
        tcg_gen_goto_tb(n);
3350
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3351
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3352
    } else {
3353
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3354 3355
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3356
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3357 3358
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3359 3360
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3361
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3362 3363 3364
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3365
                gen_debug_exception(ctx);
3366 3367
            }
        }
B
bellard 已提交
3368
        tcg_gen_exit_tb(0);
3369
    }
B
bellard 已提交
3370 3371
}

B
Blue Swirl 已提交
3372
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3373
{
3374 3375 3376 3377
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_lr, nip);
3378 3379
}

B
bellard 已提交
3380
/* b ba bl bla */
B
Blue Swirl 已提交
3381
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3382
{
3383
    target_ulong li, target;
B
bellard 已提交
3384

3385
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3386
    /* sign extend LI */
3387 3388 3389
    li = LI(ctx->opcode);
    li = (li ^ 0x02000000) - 0x02000000;
    if (likely(AA(ctx->opcode) == 0)) {
B
bellard 已提交
3390
        target = ctx->nip + li - 4;
3391
    } else {
3392
        target = li;
3393 3394
    }
    if (LK(ctx->opcode)) {
3395
        gen_setlr(ctx, ctx->nip);
3396
    }
D
David Gibson 已提交
3397
    gen_update_cfar(ctx, ctx->nip);
3398
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3399 3400
}

3401 3402 3403 3404
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3405
static inline void gen_bcond(DisasContext *ctx, int type)
3406 3407
{
    uint32_t bo = BO(ctx->opcode);
3408
    int l1;
3409
    TCGv target;
3410

3411
    ctx->exception = POWERPC_EXCP_BRANCH;
3412
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3413
        target = tcg_temp_local_new();
3414 3415 3416 3417
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3418 3419
    } else {
        TCGV_UNUSED(target);
3420
    }
3421 3422
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3423 3424 3425
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3426
        TCGv temp = tcg_temp_new();
3427
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3428
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3429 3430 3431
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3432
        if (NARROW_MODE(ctx)) {
3433
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3434
        } else {
3435
            tcg_gen_mov_tl(temp, cpu_ctr);
3436
        }
3437 3438 3439 3440
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3441
        }
P
pbrook 已提交
3442
        tcg_temp_free(temp);
3443 3444 3445 3446 3447
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3448
        TCGv_i32 temp = tcg_temp_new_i32();
3449

3450
        if (bo & 0x8) {
3451 3452
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3453
        } else {
3454 3455
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3456
        }
P
pbrook 已提交
3457
        tcg_temp_free_i32(temp);
3458
    }
D
David Gibson 已提交
3459
    gen_update_cfar(ctx, ctx->nip);
3460
    if (type == BCOND_IM) {
3461 3462 3463 3464 3465 3466
        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 已提交
3467
        gen_set_label(l1);
3468
        gen_goto_tb(ctx, 1, ctx->nip);
3469
    } else {
3470
        if (NARROW_MODE(ctx)) {
3471
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3472
        } else {
3473
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3474
        }
3475 3476
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
3477
        gen_update_nip(ctx, ctx->nip);
B
bellard 已提交
3478
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3479
    }
3480 3481
}

B
Blue Swirl 已提交
3482
static void gen_bc(DisasContext *ctx)
3483
{
3484 3485 3486
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3487
static void gen_bcctr(DisasContext *ctx)
3488
{
3489 3490 3491
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3492
static void gen_bclr(DisasContext *ctx)
3493
{
3494 3495
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3496 3497

/***                      Condition register logical                       ***/
3498
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3499
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3500
{                                                                             \
3501 3502
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3503
    TCGv_i32 t0, t1;                                                          \
3504
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3505
    t0 = tcg_temp_new_i32();                                                  \
3506
    if (sh > 0)                                                               \
3507
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3508
    else if (sh < 0)                                                          \
3509
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3510
    else                                                                      \
3511
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3512
    t1 = tcg_temp_new_i32();                                                  \
3513 3514
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3515
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3516
    else if (sh < 0)                                                          \
3517
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3518
    else                                                                      \
3519 3520
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3521
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3522 3523 3524
    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);                  \
P
pbrook 已提交
3525 3526
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3527 3528 3529
}

/* crand */
3530
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3531
/* crandc */
3532
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3533
/* creqv */
3534
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3535
/* crnand */
3536
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3537
/* crnor */
3538
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3539
/* cror */
3540
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3541
/* crorc */
3542
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3543
/* crxor */
3544
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3545

3546
/* mcrf */
B
Blue Swirl 已提交
3547
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3548
{
A
aurel32 已提交
3549
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3550 3551 3552
}

/***                           System linkage                              ***/
B
Blue Swirl 已提交
3553

3554
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3555
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3556
{
3557
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3558
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3559 3560
#else
    /* Restore CPU state */
A
aurel32 已提交
3561
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3562
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3563
        return;
3564
    }
D
David Gibson 已提交
3565
    gen_update_cfar(ctx, ctx->nip);
3566
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3567
    gen_sync_exception(ctx);
3568
#endif
B
bellard 已提交
3569 3570
}

J
j_mayer 已提交
3571
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3572
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3573 3574
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3575
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3576 3577
#else
    /* Restore CPU state */
A
aurel32 已提交
3578
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3579
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3580 3581
        return;
    }
D
David Gibson 已提交
3582
    gen_update_cfar(ctx, ctx->nip);
3583
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3584
    gen_sync_exception(ctx);
J
j_mayer 已提交
3585 3586 3587
#endif
}

B
Blue Swirl 已提交
3588
static void gen_hrfid(DisasContext *ctx)
3589 3590
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3591
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3592 3593
#else
    /* Restore CPU state */
A
aurel32 已提交
3594
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3595
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3596 3597
        return;
    }
3598
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3599
    gen_sync_exception(ctx);
3600 3601 3602 3603
#endif
}
#endif

B
bellard 已提交
3604
/* sc */
3605 3606 3607 3608 3609
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3610
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3611
{
3612 3613 3614
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3615
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3616 3617 3618
}

/***                                Trap                                   ***/
B
Blue Swirl 已提交
3619

3620
/* tw */
B
Blue Swirl 已提交
3621
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3622
{
3623
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3624 3625
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3626 3627
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3628
    tcg_temp_free_i32(t0);
B
bellard 已提交
3629 3630 3631
}

/* twi */
B
Blue Swirl 已提交
3632
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3633
{
3634 3635
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3636 3637
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3638
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3639 3640
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3641 3642
}

3643 3644
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3645
static void gen_td(DisasContext *ctx)
3646
{
3647
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3648 3649
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3650 3651
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3652
    tcg_temp_free_i32(t0);
3653 3654 3655
}

/* tdi */
B
Blue Swirl 已提交
3656
static void gen_tdi(DisasContext *ctx)
3657
{
3658 3659
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3660 3661
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3662
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3663 3664
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3665 3666 3667
}
#endif

B
bellard 已提交
3668
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3669

3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698
static void gen_read_xer(TCGv dst)
{
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    tcg_gen_mov_tl(dst, cpu_xer);
    tcg_gen_shli_tl(t0, cpu_so, XER_SO);
    tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
    tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
    tcg_gen_or_tl(t0, t0, t1);
    tcg_gen_or_tl(dst, dst, t2);
    tcg_gen_or_tl(dst, dst, t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
}

static void gen_write_xer(TCGv src)
{
    tcg_gen_andi_tl(cpu_xer, src,
                    ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
    tcg_gen_shri_tl(cpu_so, src, XER_SO);
    tcg_gen_shri_tl(cpu_ov, src, XER_OV);
    tcg_gen_shri_tl(cpu_ca, src, XER_CA);
    tcg_gen_andi_tl(cpu_so, cpu_so, 1);
    tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
    tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
}

3699
/* mcrxr */
B
Blue Swirl 已提交
3700
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3701
{
3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
    TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];

    tcg_gen_trunc_tl_i32(t0, cpu_so);
    tcg_gen_trunc_tl_i32(t1, cpu_ov);
    tcg_gen_trunc_tl_i32(dst, cpu_ca);
    tcg_gen_shri_i32(t0, t0, 2);
    tcg_gen_shri_i32(t1, t1, 1);
    tcg_gen_or_i32(dst, dst, t0);
    tcg_gen_or_i32(dst, dst, t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);

    tcg_gen_movi_tl(cpu_so, 0);
    tcg_gen_movi_tl(cpu_ov, 0);
    tcg_gen_movi_tl(cpu_ca, 0);
B
bellard 已提交
3719 3720
}

A
aurel32 已提交
3721
/* mfcr mfocrf */
B
Blue Swirl 已提交
3722
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3723
{
3724
    uint32_t crm, crn;
3725

3726 3727
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3728
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3729
            crn = ctz32 (crm);
3730
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3731 3732
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3733
        }
3734
    } else {
A
aurel32 已提交
3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752
        TCGv_i32 t0 = tcg_temp_new_i32();
        tcg_gen_mov_i32(t0, cpu_crf[0]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
        tcg_gen_shli_i32(t0, t0, 4);
        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
        tcg_temp_free_i32(t0);
3753
    }
B
bellard 已提交
3754 3755 3756
}

/* mfmsr */
B
Blue Swirl 已提交
3757
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3758
{
3759
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3760
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3761
#else
A
aurel32 已提交
3762
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3763
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3764
        return;
3765
    }
3766
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3767
#endif
B
bellard 已提交
3768 3769
}

3770
static void spr_noaccess(void *opaque, int gprn, int sprn)
3771
{
3772
#if 0
3773 3774
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3775
#endif
3776 3777 3778
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3779
/* mfspr */
B
Blue Swirl 已提交
3780
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3781
{
A
aurel32 已提交
3782
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3783 3784
    uint32_t sprn = SPR(ctx->opcode);

3785
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3786
    if (ctx->mem_idx == 2)
3787
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3788
    else if (ctx->mem_idx)
3789 3790
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3791
#endif
3792
        read_cb = ctx->spr_cb[sprn].uea_read;
3793 3794
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3795
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3796 3797
        } else {
            /* Privilege exception */
3798 3799 3800 3801 3802
            /* 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) {
3803
                qemu_log("Trying to read privileged spr %d %03x at "
3804 3805 3806
                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
                printf("Trying to read privileged spr %d %03x at "
                       TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3807
            }
A
aurel32 已提交
3808
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3809
        }
3810 3811
    } else {
        /* Not defined */
3812
        qemu_log("Trying to read invalid spr %d %03x at "
3813 3814
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3815
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3816
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3817 3818 3819
    }
}

B
Blue Swirl 已提交
3820
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3821
{
3822
    gen_op_mfspr(ctx);
3823
}
3824 3825

/* mftb */
B
Blue Swirl 已提交
3826
static void gen_mftb(DisasContext *ctx)
3827 3828
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3829 3830
}

A
aurel32 已提交
3831
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3832
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3833
{
3834
    uint32_t crm, crn;
3835

3836
    crm = CRM(ctx->opcode);
M
malc 已提交
3837 3838 3839
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3840
            crn = ctz32 (crm);
M
malc 已提交
3841
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3842 3843
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3844 3845
            tcg_temp_free_i32(temp);
        }
3846
    } else {
A
aurel32 已提交
3847 3848 3849 3850 3851 3852 3853 3854
        TCGv_i32 temp = tcg_temp_new_i32();
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
        for (crn = 0 ; crn < 8 ; crn++) {
            if (crm & (1 << crn)) {
                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
            }
        }
P
pbrook 已提交
3855
        tcg_temp_free_i32(temp);
3856
    }
B
bellard 已提交
3857 3858 3859
}

/* mtmsr */
J
j_mayer 已提交
3860
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3861
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3862 3863
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3864
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3865
#else
A
aurel32 已提交
3866
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3867
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3868 3869
        return;
    }
3870 3871
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3872 3873 3874 3875 3876
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
3877
    } else {
3878 3879 3880 3881
        /* 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
         */
3882
        gen_update_nip(ctx, ctx->nip);
3883
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
3884 3885
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3886
        gen_stop_exception(ctx);
3887
    }
J
j_mayer 已提交
3888 3889 3890 3891
#endif
}
#endif

B
Blue Swirl 已提交
3892
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3893
{
3894
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3895
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3896
#else
A
aurel32 已提交
3897
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3898
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3899
        return;
3900
    }
3901 3902
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3903 3904 3905 3906 3907
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
3908
    } else {
3909 3910
        TCGv msr = tcg_temp_new();

3911 3912 3913 3914
        /* 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
         */
3915
        gen_update_nip(ctx, ctx->nip);
3916
#if defined(TARGET_PPC64)
3917 3918 3919
        tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
#else
        tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
3920
#endif
3921
        gen_helper_store_msr(cpu_env, msr);
3922
        /* Must stop the translation as machine state (may have) changed */
3923
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3924
        gen_stop_exception(ctx);
3925
    }
3926
#endif
B
bellard 已提交
3927 3928 3929
}

/* mtspr */
B
Blue Swirl 已提交
3930
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
3931
{
A
aurel32 已提交
3932
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3933 3934
    uint32_t sprn = SPR(ctx->opcode);

3935
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3936
    if (ctx->mem_idx == 2)
3937
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3938
    else if (ctx->mem_idx)
3939 3940
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3941
#endif
3942
        write_cb = ctx->spr_cb[sprn].uea_write;
3943 3944
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3945
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3946 3947
        } else {
            /* Privilege exception */
3948
            qemu_log("Trying to write privileged spr %d %03x at "
3949 3950 3951
                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
            printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
                   "\n", sprn, sprn, ctx->nip);
A
aurel32 已提交
3952
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3953
        }
3954 3955
    } else {
        /* Not defined */
3956
        qemu_log("Trying to write invalid spr %d %03x at "
3957 3958
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3959
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3960
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3961 3962 3963 3964
    }
}

/***                         Cache management                              ***/
B
Blue Swirl 已提交
3965

3966
/* dcbf */
B
Blue Swirl 已提交
3967
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
3968
{
J
j_mayer 已提交
3969
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
3970 3971 3972 3973 3974
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld8u(ctx, t0, t0);
3975
    tcg_temp_free(t0);
B
bellard 已提交
3976 3977 3978
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
3979
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
3980
{
3981
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3982
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3983
#else
A
aurel32 已提交
3984
    TCGv EA, val;
A
aurel32 已提交
3985
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3986
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3987
        return;
3988
    }
P
pbrook 已提交
3989
    EA = tcg_temp_new();
A
aurel32 已提交
3990 3991
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
3992
    val = tcg_temp_new();
3993
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
3994 3995
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
3996 3997
    tcg_temp_free(val);
    tcg_temp_free(EA);
3998
#endif
B
bellard 已提交
3999 4000 4001
}

/* dcdst */
B
Blue Swirl 已提交
4002
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4003
{
4004
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4005 4006 4007 4008 4009
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld8u(ctx, t0, t0);
4010
    tcg_temp_free(t0);
B
bellard 已提交
4011 4012 4013
}

/* dcbt */
B
Blue Swirl 已提交
4014
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4015
{
4016
    /* interpreted as no-op */
4017 4018 4019
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4020 4021 4022
}

/* dcbtst */
B
Blue Swirl 已提交
4023
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4024
{
4025
    /* interpreted as no-op */
4026 4027 4028
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4029 4030 4031
}

/* dcbz */
B
Blue Swirl 已提交
4032
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4033
{
A
Alexander Graf 已提交
4034 4035 4036
    TCGv tcgv_addr;
    TCGv_i32 tcgv_is_dcbzl;
    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4037

A
aurel32 已提交
4038
    gen_set_access_type(ctx, ACCESS_CACHE);
4039 4040
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
4041 4042 4043 4044 4045 4046 4047 4048
    tcgv_addr = tcg_temp_new();
    tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);

    gen_addr_reg_index(ctx, tcgv_addr);
    gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);

    tcg_temp_free(tcgv_addr);
    tcg_temp_free_i32(tcgv_is_dcbzl);
B
bellard 已提交
4049 4050
}

4051
/* dst / dstt */
B
Blue Swirl 已提交
4052
static void gen_dst(DisasContext *ctx)
4053 4054 4055 4056 4057 4058 4059 4060 4061
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4062
static void gen_dstst(DisasContext *ctx)
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4073
static void gen_dss(DisasContext *ctx)
4074 4075 4076 4077
{
    /* interpreted as no-op */
}

B
bellard 已提交
4078
/* icbi */
B
Blue Swirl 已提交
4079
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4080
{
A
aurel32 已提交
4081 4082
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4083 4084
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4085 4086
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4087
    gen_helper_icbi(cpu_env, t0);
4088
    tcg_temp_free(t0);
B
bellard 已提交
4089 4090 4091 4092
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4093
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4094
{
4095 4096 4097 4098
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4099 4100 4101 4102
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
B
Blue Swirl 已提交
4103

4104
/* mfsr */
B
Blue Swirl 已提交
4105
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4106
{
4107
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4108
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4109
#else
4110
    TCGv t0;
A
aurel32 已提交
4111
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4112
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4113
        return;
4114
    }
4115
    t0 = tcg_const_tl(SR(ctx->opcode));
4116
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4117
    tcg_temp_free(t0);
4118
#endif
B
bellard 已提交
4119 4120 4121
}

/* mfsrin */
B
Blue Swirl 已提交
4122
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4123
{
4124
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4125
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4126
#else
4127
    TCGv t0;
A
aurel32 已提交
4128
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4129
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4130
        return;
4131
    }
4132 4133 4134
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4135
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4136
    tcg_temp_free(t0);
4137
#endif
B
bellard 已提交
4138 4139 4140
}

/* mtsr */
B
Blue Swirl 已提交
4141
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4142
{
4143
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4144
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4145
#else
4146
    TCGv t0;
A
aurel32 已提交
4147
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4148
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4149
        return;
4150
    }
4151
    t0 = tcg_const_tl(SR(ctx->opcode));
4152
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4153
    tcg_temp_free(t0);
4154
#endif
B
bellard 已提交
4155 4156 4157
}

/* mtsrin */
B
Blue Swirl 已提交
4158
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4159
{
4160
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4161
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4162
#else
4163
    TCGv t0;
A
aurel32 已提交
4164
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4165
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4166
        return;
4167
    }
4168 4169 4170
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4171
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4172
    tcg_temp_free(t0);
4173
#endif
B
bellard 已提交
4174 4175
}

4176 4177
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
B
Blue Swirl 已提交
4178

4179
/* mfsr */
B
Blue Swirl 已提交
4180
static void gen_mfsr_64b(DisasContext *ctx)
4181 4182
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4183
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4184
#else
4185
    TCGv t0;
A
aurel32 已提交
4186
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4187
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4188 4189
        return;
    }
4190
    t0 = tcg_const_tl(SR(ctx->opcode));
4191
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4192
    tcg_temp_free(t0);
4193 4194 4195 4196
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4197
static void gen_mfsrin_64b(DisasContext *ctx)
4198 4199
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4200
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4201
#else
4202
    TCGv t0;
A
aurel32 已提交
4203
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4204
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4205 4206
        return;
    }
4207 4208 4209
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4210
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4211
    tcg_temp_free(t0);
4212 4213 4214 4215
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4216
static void gen_mtsr_64b(DisasContext *ctx)
4217 4218
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4219
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4220
#else
4221
    TCGv t0;
A
aurel32 已提交
4222
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4223
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4224 4225
        return;
    }
4226
    t0 = tcg_const_tl(SR(ctx->opcode));
4227
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4228
    tcg_temp_free(t0);
4229 4230 4231 4232
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4233
static void gen_mtsrin_64b(DisasContext *ctx)
4234 4235
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4236
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4237
#else
4238
    TCGv t0;
A
aurel32 已提交
4239
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4240
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4241 4242
        return;
    }
4243 4244 4245
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4246
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4247
    tcg_temp_free(t0);
4248 4249
#endif
}
B
blueswir1 已提交
4250 4251

/* slbmte */
B
Blue Swirl 已提交
4252
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4253 4254 4255 4256 4257 4258 4259 4260
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
4261 4262
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
B
blueswir1 已提交
4263 4264 4265
#endif
}

4266 4267 4268 4269 4270 4271 4272 4273 4274
static void gen_slbmfee(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
4275
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}

static void gen_slbmfev(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
4289
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4290 4291 4292
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4293 4294
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4295
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4296
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4297

4298
/* tlbia */
B
Blue Swirl 已提交
4299
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4300
{
4301
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4302
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4303
#else
A
aurel32 已提交
4304
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4305
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4306
        return;
4307
    }
4308
    gen_helper_tlbia(cpu_env);
4309
#endif
B
bellard 已提交
4310 4311
}

B
blueswir1 已提交
4312
/* tlbiel */
B
Blue Swirl 已提交
4313
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4314 4315 4316 4317 4318 4319 4320 4321
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }
4322
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
B
blueswir1 已提交
4323 4324 4325
#endif
}

B
bellard 已提交
4326
/* tlbie */
B
Blue Swirl 已提交
4327
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4328
{
4329
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4330
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4331
#else
A
aurel32 已提交
4332
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4333
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4334
        return;
4335
    }
4336
#if defined(TARGET_PPC64)
4337 4338 4339
    if (!ctx->sf_mode) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4340
        gen_helper_tlbie(cpu_env, t0);
4341 4342
        tcg_temp_free(t0);
    } else
4343
#endif
4344
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4345
#endif
B
bellard 已提交
4346 4347 4348
}

/* tlbsync */
B
Blue Swirl 已提交
4349
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4350
{
4351
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4352
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4353
#else
A
aurel32 已提交
4354
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4355
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4356
        return;
4357 4358 4359 4360
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4361
    gen_stop_exception(ctx);
4362
#endif
B
bellard 已提交
4363 4364
}

J
j_mayer 已提交
4365 4366
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4367
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4368 4369
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4370
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4371
#else
A
aurel32 已提交
4372
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4373
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4374 4375
        return;
    }
4376
    gen_helper_slbia(cpu_env);
J
j_mayer 已提交
4377 4378 4379 4380
#endif
}

/* slbie */
B
Blue Swirl 已提交
4381
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4382 4383
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4384
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4385
#else
A
aurel32 已提交
4386
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4387
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4388 4389
        return;
    }
4390
    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4391 4392 4393 4394
#endif
}
#endif

B
bellard 已提交
4395 4396
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4397

4398
/* eciwx */
B
Blue Swirl 已提交
4399
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4400
{
A
aurel32 已提交
4401
    TCGv t0;
4402
    /* Should check EAR[E] ! */
A
aurel32 已提交
4403 4404 4405
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4406
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4407
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4408
    tcg_temp_free(t0);
4409 4410 4411
}

/* ecowx */
B
Blue Swirl 已提交
4412
static void gen_ecowx(DisasContext *ctx)
4413
{
A
aurel32 已提交
4414
    TCGv t0;
4415
    /* Should check EAR[E] ! */
A
aurel32 已提交
4416 4417 4418
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4419
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4420
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4421
    tcg_temp_free(t0);
4422 4423 4424
}

/* PowerPC 601 specific instructions */
B
Blue Swirl 已提交
4425

4426
/* abs - abs. */
B
Blue Swirl 已提交
4427
static void gen_abs(DisasContext *ctx)
4428
{
4429 4430 4431 4432 4433 4434 4435 4436
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_neg_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[rA(ctx->opcode)]);
    gen_set_label(l2);
4437
    if (unlikely(Rc(ctx->opcode) != 0))
4438
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4439 4440 4441
}

/* abso - abso. */
B
Blue Swirl 已提交
4442
static void gen_abso(DisasContext *ctx)
4443
{
4444 4445 4446 4447
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
4448
    tcg_gen_movi_tl(cpu_ov, 0);
4449 4450
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4451 4452
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4453 4454 4455 4456 4457 4458 4459
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l3);
4460
    if (unlikely(Rc(ctx->opcode) != 0))
4461
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4462 4463 4464
}

/* clcs */
B
Blue Swirl 已提交
4465
static void gen_clcs(DisasContext *ctx)
4466
{
4467
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4468
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4469
    tcg_temp_free_i32(t0);
4470
    /* Rc=1 sets CR0 to an undefined state */
4471 4472 4473
}

/* div - div. */
B
Blue Swirl 已提交
4474
static void gen_div(DisasContext *ctx)
4475
{
4476 4477
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4478
    if (unlikely(Rc(ctx->opcode) != 0))
4479
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4480 4481 4482
}

/* divo - divo. */
B
Blue Swirl 已提交
4483
static void gen_divo(DisasContext *ctx)
4484
{
4485 4486
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4487
    if (unlikely(Rc(ctx->opcode) != 0))
4488
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4489 4490 4491
}

/* divs - divs. */
B
Blue Swirl 已提交
4492
static void gen_divs(DisasContext *ctx)
4493
{
4494 4495
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4496
    if (unlikely(Rc(ctx->opcode) != 0))
4497
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4498 4499 4500
}

/* divso - divso. */
B
Blue Swirl 已提交
4501
static void gen_divso(DisasContext *ctx)
4502
{
4503 4504
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4505
    if (unlikely(Rc(ctx->opcode) != 0))
4506
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4507 4508 4509
}

/* doz - doz. */
B
Blue Swirl 已提交
4510
static void gen_doz(DisasContext *ctx)
4511
{
4512 4513 4514 4515 4516 4517 4518 4519
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
4520
    if (unlikely(Rc(ctx->opcode) != 0))
4521
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4522 4523 4524
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4525
static void gen_dozo(DisasContext *ctx)
4526
{
4527 4528 4529 4530 4531 4532
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    /* Start with XER OV disabled, the most likely case */
4533
    tcg_gen_movi_tl(cpu_ov, 0);
4534 4535 4536 4537 4538 4539 4540
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_andc_tl(t1, t1, t2);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4541 4542
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4543 4544 4545 4546 4547 4548 4549
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4550
    if (unlikely(Rc(ctx->opcode) != 0))
4551
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4552 4553 4554
}

/* dozi */
B
Blue Swirl 已提交
4555
static void gen_dozi(DisasContext *ctx)
4556
{
4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567
    target_long simm = SIMM(ctx->opcode);
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4568 4569 4570
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4571
static void gen_lscbx(DisasContext *ctx)
4572
{
4573 4574 4575 4576
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
4577

A
aurel32 已提交
4578
    gen_addr_reg_index(ctx, t0);
4579
    /* NIP cannot be restored if the memory exception comes from an helper */
4580
    gen_update_nip(ctx, ctx->nip - 4);
4581
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4582 4583 4584
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4585
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4586
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4587
    if (unlikely(Rc(ctx->opcode) != 0))
4588 4589
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4590 4591 4592
}

/* maskg - maskg. */
B
Blue Swirl 已提交
4593
static void gen_maskg(DisasContext *ctx)
4594
{
4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    TCGv t3 = tcg_temp_new();
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
    tcg_gen_addi_tl(t2, t0, 1);
    tcg_gen_shr_tl(t2, t3, t2);
    tcg_gen_shr_tl(t3, t3, t1);
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
    tcg_temp_free(t3);
4614
    if (unlikely(Rc(ctx->opcode) != 0))
4615
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4616 4617 4618
}

/* maskir - maskir. */
B
Blue Swirl 已提交
4619
static void gen_maskir(DisasContext *ctx)
4620
{
4621 4622 4623 4624 4625 4626 4627
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4628
    if (unlikely(Rc(ctx->opcode) != 0))
4629
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4630 4631 4632
}

/* mul - mul. */
B
Blue Swirl 已提交
4633
static void gen_mul(DisasContext *ctx)
4634
{
4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();
    TCGv t2 = tcg_temp_new();
    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_trunc_i64_tl(t2, t0);
    gen_store_spr(SPR_MQ, t2);
    tcg_gen_shri_i64(t1, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4648
    if (unlikely(Rc(ctx->opcode) != 0))
4649
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4650 4651 4652
}

/* mulo - mulo. */
B
Blue Swirl 已提交
4653
static void gen_mulo(DisasContext *ctx)
4654
{
4655 4656 4657 4658 4659
    int l1 = gen_new_label();
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();
    TCGv t2 = tcg_temp_new();
    /* Start with XER OV disabled, the most likely case */
4660
    tcg_gen_movi_tl(cpu_ov, 0);
4661 4662 4663 4664 4665 4666 4667 4668 4669
    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_trunc_i64_tl(t2, t0);
    gen_store_spr(SPR_MQ, t2);
    tcg_gen_shri_i64(t1, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4670 4671
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4672 4673 4674 4675
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4676
    if (unlikely(Rc(ctx->opcode) != 0))
4677
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4678 4679 4680
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4681
static void gen_nabs(DisasContext *ctx)
4682
{
4683 4684 4685 4686 4687 4688 4689 4690
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
4691
    if (unlikely(Rc(ctx->opcode) != 0))
4692
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4693 4694 4695
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4696
static void gen_nabso(DisasContext *ctx)
4697
{
4698 4699 4700 4701 4702 4703 4704 4705 4706
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
    /* nabs never overflows */
4707
    tcg_gen_movi_tl(cpu_ov, 0);
4708
    if (unlikely(Rc(ctx->opcode) != 0))
4709
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4710 4711 4712
}

/* rlmi - rlmi. */
B
Blue Swirl 已提交
4713
static void gen_rlmi(DisasContext *ctx)
4714
{
4715 4716 4717 4718 4719 4720 4721 4722 4723
    uint32_t mb = MB(ctx->opcode);
    uint32_t me = ME(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
    tcg_temp_free(t0);
4724
    if (unlikely(Rc(ctx->opcode) != 0))
4725
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4726 4727 4728
}

/* rrib - rrib. */
B
Blue Swirl 已提交
4729
static void gen_rrib(DisasContext *ctx)
4730
{
4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0x80000000);
    tcg_gen_shr_tl(t1, t1, t0);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    tcg_gen_and_tl(t0, t0, t1);
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4742
    if (unlikely(Rc(ctx->opcode) != 0))
4743
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4744 4745 4746
}

/* sle - sle. */
B
Blue Swirl 已提交
4747
static void gen_sle(DisasContext *ctx)
4748
{
4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    gen_store_spr(SPR_MQ, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4760
    if (unlikely(Rc(ctx->opcode) != 0))
4761
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4762 4763 4764
}

/* sleq - sleq. */
B
Blue Swirl 已提交
4765
static void gen_sleq(DisasContext *ctx)
4766
{
4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
    tcg_gen_shl_tl(t2, t2, t0);
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    gen_load_spr(t1, SPR_MQ);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_and_tl(t0, t0, t2);
    tcg_gen_andc_tl(t1, t1, t2);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4782
    if (unlikely(Rc(ctx->opcode) != 0))
4783
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4784 4785 4786
}

/* sliq - sliq. */
B
Blue Swirl 已提交
4787
static void gen_sliq(DisasContext *ctx)
4788
{
4789 4790 4791 4792 4793 4794 4795 4796 4797 4798
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
    tcg_gen_or_tl(t1, t0, t1);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    gen_store_spr(SPR_MQ, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4799
    if (unlikely(Rc(ctx->opcode) != 0))
4800
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4801 4802 4803
}

/* slliq - slliq. */
B
Blue Swirl 已提交
4804
static void gen_slliq(DisasContext *ctx)
4805
{
4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    gen_load_spr(t1, SPR_MQ);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4817
    if (unlikely(Rc(ctx->opcode) != 0))
4818
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4819 4820 4821
}

/* sllq - sllq. */
B
Blue Swirl 已提交
4822
static void gen_sllq(DisasContext *ctx)
4823
{
4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
    tcg_gen_shl_tl(t1, t1, t2);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    gen_load_spr(t0, SPR_MQ);
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    gen_load_spr(t2, SPR_MQ);
    tcg_gen_andc_tl(t1, t2, t1);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4846
    if (unlikely(Rc(ctx->opcode) != 0))
4847
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4848 4849 4850
}

/* slq - slq. */
B
Blue Swirl 已提交
4851
static void gen_slq(DisasContext *ctx)
4852
{
4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    gen_store_spr(SPR_MQ, t1);
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4869
    if (unlikely(Rc(ctx->opcode) != 0))
4870
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4871 4872
}

4873
/* sraiq - sraiq. */
B
Blue Swirl 已提交
4874
static void gen_sraiq(DisasContext *ctx)
4875
{
4876 4877 4878 4879 4880 4881 4882 4883
    int sh = SH(ctx->opcode);
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
    tcg_gen_or_tl(t0, t0, t1);
    gen_store_spr(SPR_MQ, t0);
4884
    tcg_gen_movi_tl(cpu_ca, 0);
4885 4886
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4887
    tcg_gen_movi_tl(cpu_ca, 1);
4888 4889 4890 4891
    gen_set_label(l1);
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4892
    if (unlikely(Rc(ctx->opcode) != 0))
4893
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4894 4895 4896
}

/* sraq - sraq. */
B
Blue Swirl 已提交
4897
static void gen_sraq(DisasContext *ctx)
4898
{
4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_subfi_tl(t2, 32, t2);
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_or_tl(t0, t0, t2);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4918
    tcg_gen_movi_tl(cpu_ca, 0);
4919 4920
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4921
    tcg_gen_movi_tl(cpu_ca, 1);
4922 4923 4924
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4925
    if (unlikely(Rc(ctx->opcode) != 0))
4926
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4927 4928 4929
}

/* sre - sre. */
B
Blue Swirl 已提交
4930
static void gen_sre(DisasContext *ctx)
4931
{
4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    gen_store_spr(SPR_MQ, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4943
    if (unlikely(Rc(ctx->opcode) != 0))
4944
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4945 4946 4947
}

/* srea - srea. */
B
Blue Swirl 已提交
4948
static void gen_srea(DisasContext *ctx)
4949
{
4950 4951 4952 4953 4954 4955 4956 4957
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4958
    if (unlikely(Rc(ctx->opcode) != 0))
4959
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4960 4961 4962
}

/* sreq */
B
Blue Swirl 已提交
4963
static void gen_sreq(DisasContext *ctx)
4964
{
4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
    tcg_gen_shr_tl(t1, t1, t0);
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
    gen_load_spr(t2, SPR_MQ);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_and_tl(t0, t0, t1);
    tcg_gen_andc_tl(t2, t2, t1);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4980
    if (unlikely(Rc(ctx->opcode) != 0))
4981
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4982 4983 4984
}

/* sriq */
B
Blue Swirl 已提交
4985
static void gen_sriq(DisasContext *ctx)
4986
{
4987 4988 4989 4990 4991 4992 4993 4994 4995 4996
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
    tcg_gen_or_tl(t1, t0, t1);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    gen_store_spr(SPR_MQ, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4997
    if (unlikely(Rc(ctx->opcode) != 0))
4998
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4999 5000 5001
}

/* srliq */
B
Blue Swirl 已提交
5002
static void gen_srliq(DisasContext *ctx)
5003
{
5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    gen_load_spr(t1, SPR_MQ);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5015
    if (unlikely(Rc(ctx->opcode) != 0))
5016
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5017 5018 5019
}

/* srlq */
B
Blue Swirl 已提交
5020
static void gen_srlq(DisasContext *ctx)
5021
{
5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
    tcg_gen_shr_tl(t2, t1, t2);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    gen_load_spr(t0, SPR_MQ);
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_and_tl(t0, t0, t2);
    gen_load_spr(t1, SPR_MQ);
    tcg_gen_andc_tl(t1, t1, t2);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
5045
    if (unlikely(Rc(ctx->opcode) != 0))
5046
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5047 5048 5049
}

/* srq */
B
Blue Swirl 已提交
5050
static void gen_srq(DisasContext *ctx)
5051
{
5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    gen_store_spr(SPR_MQ, t1);
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5068
    if (unlikely(Rc(ctx->opcode) != 0))
5069
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5070 5071 5072
}

/* PowerPC 602 specific instructions */
B
Blue Swirl 已提交
5073

5074
/* dsa  */
B
Blue Swirl 已提交
5075
static void gen_dsa(DisasContext *ctx)
5076 5077
{
    /* XXX: TODO */
A
aurel32 已提交
5078
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5079 5080 5081
}

/* esa */
B
Blue Swirl 已提交
5082
static void gen_esa(DisasContext *ctx)
5083 5084
{
    /* XXX: TODO */
A
aurel32 已提交
5085
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5086 5087 5088
}

/* mfrom */
B
Blue Swirl 已提交
5089
static void gen_mfrom(DisasContext *ctx)
5090 5091
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5092
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5093
#else
A
aurel32 已提交
5094
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5095
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5096 5097
        return;
    }
5098
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5099 5100 5101 5102
#endif
}

/* 602 - 603 - G2 TLB management */
B
Blue Swirl 已提交
5103

5104
/* tlbld */
B
Blue Swirl 已提交
5105
static void gen_tlbld_6xx(DisasContext *ctx)
5106 5107
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5108
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5109
#else
A
aurel32 已提交
5110
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5111
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5112 5113
        return;
    }
5114
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5115 5116 5117 5118
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5119
static void gen_tlbli_6xx(DisasContext *ctx)
5120 5121
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5122
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5123
#else
A
aurel32 已提交
5124
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5125
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5126 5127
        return;
    }
5128
    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5129 5130 5131
#endif
}

5132
/* 74xx TLB management */
B
Blue Swirl 已提交
5133

5134
/* tlbld */
B
Blue Swirl 已提交
5135
static void gen_tlbld_74xx(DisasContext *ctx)
5136 5137
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5138
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5139
#else
A
aurel32 已提交
5140
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5141
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5142 5143
        return;
    }
5144
    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5145 5146 5147 5148
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5149
static void gen_tlbli_74xx(DisasContext *ctx)
5150 5151
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5152
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5153
#else
A
aurel32 已提交
5154
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5155
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5156 5157
        return;
    }
5158
    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5159 5160 5161
#endif
}

5162
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5163

5164
/* clf */
B
Blue Swirl 已提交
5165
static void gen_clf(DisasContext *ctx)
5166 5167 5168 5169 5170
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5171
static void gen_cli(DisasContext *ctx)
5172
{
B
blueswir1 已提交
5173
    /* Cache line invalidate: privileged and treated as no-op */
5174
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5175
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5176
#else
A
aurel32 已提交
5177
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5178
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5179 5180 5181 5182 5183 5184
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5185
static void gen_dclst(DisasContext *ctx)
5186 5187 5188 5189
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5190
static void gen_mfsri(DisasContext *ctx)
5191 5192
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5193
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5194
#else
5195 5196 5197
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5198
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5199
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5200 5201
        return;
    }
5202
    t0 = tcg_temp_new();
A
aurel32 已提交
5203
    gen_addr_reg_index(ctx, t0);
5204 5205
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
5206
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5207
    tcg_temp_free(t0);
5208
    if (ra != 0 && ra != rd)
5209
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5210 5211 5212
#endif
}

B
Blue Swirl 已提交
5213
static void gen_rac(DisasContext *ctx)
5214 5215
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5216
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5217
#else
5218
    TCGv t0;
A
aurel32 已提交
5219
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5220
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5221 5222
        return;
    }
5223
    t0 = tcg_temp_new();
A
aurel32 已提交
5224
    gen_addr_reg_index(ctx, t0);
5225
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5226
    tcg_temp_free(t0);
5227 5228 5229
#endif
}

B
Blue Swirl 已提交
5230
static void gen_rfsvc(DisasContext *ctx)
5231 5232
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5233
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5234
#else
A
aurel32 已提交
5235
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5236
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5237 5238
        return;
    }
5239
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5240
    gen_sync_exception(ctx);
5241 5242 5243 5244 5245 5246 5247 5248 5249
#endif
}

/* svc is not implemented for now */

/* POWER2 specific instructions */
/* Quad manipulation (load/store two floats at a time) */

/* lfq */
B
Blue Swirl 已提交
5250
static void gen_lfq(DisasContext *ctx)
5251
{
5252
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5253 5254 5255 5256 5257 5258 5259
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5260
    tcg_temp_free(t0);
5261 5262 5263
}

/* lfqu */
B
Blue Swirl 已提交
5264
static void gen_lfqu(DisasContext *ctx)
5265 5266
{
    int ra = rA(ctx->opcode);
5267
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5268 5269 5270 5271 5272 5273 5274 5275
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    t1 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5276
    if (ra != 0)
5277 5278 5279
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5280 5281 5282
}

/* lfqux */
B
Blue Swirl 已提交
5283
static void gen_lfqux(DisasContext *ctx)
5284 5285
{
    int ra = rA(ctx->opcode);
5286
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5287 5288 5289 5290 5291 5292 5293 5294 5295
    gen_set_access_type(ctx, ACCESS_FLOAT);
    TCGv t0, t1;
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5296
    if (ra != 0)
5297 5298
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5299 5300 5301
}

/* lfqx */
B
Blue Swirl 已提交
5302
static void gen_lfqx(DisasContext *ctx)
5303
{
5304
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5305 5306 5307 5308 5309 5310 5311
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5312
    tcg_temp_free(t0);
5313 5314 5315
}

/* stfq */
B
Blue Swirl 已提交
5316
static void gen_stfq(DisasContext *ctx)
5317
{
5318
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5319 5320 5321 5322 5323 5324 5325
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5326
    tcg_temp_free(t0);
5327 5328 5329
}

/* stfqu */
B
Blue Swirl 已提交
5330
static void gen_stfqu(DisasContext *ctx)
5331 5332
{
    int ra = rA(ctx->opcode);
5333
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5334 5335 5336 5337 5338 5339 5340 5341 5342
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5343
    if (ra != 0)
5344 5345
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5346 5347 5348
}

/* stfqux */
B
Blue Swirl 已提交
5349
static void gen_stfqux(DisasContext *ctx)
5350 5351
{
    int ra = rA(ctx->opcode);
5352
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5353 5354 5355 5356 5357 5358 5359 5360 5361
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5362
    if (ra != 0)
5363 5364
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5365 5366 5367
}

/* stfqx */
B
Blue Swirl 已提交
5368
static void gen_stfqx(DisasContext *ctx)
5369
{
5370
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5371 5372 5373 5374 5375 5376 5377
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5378
    tcg_temp_free(t0);
5379 5380 5381
}

/* BookE specific instructions */
B
Blue Swirl 已提交
5382

5383
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5384
static void gen_mfapidi(DisasContext *ctx)
5385 5386
{
    /* XXX: TODO */
A
aurel32 已提交
5387
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5388 5389
}

5390
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5391
static void gen_tlbiva(DisasContext *ctx)
5392 5393
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5394
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5395
#else
5396
    TCGv t0;
A
aurel32 已提交
5397
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5398
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5399 5400
        return;
    }
5401
    t0 = tcg_temp_new();
A
aurel32 已提交
5402
    gen_addr_reg_index(ctx, t0);
5403
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5404
    tcg_temp_free(t0);
5405 5406 5407 5408
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5409 5410
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5411
{
5412 5413
    TCGv t0, t1;

P
pbrook 已提交
5414 5415
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5416

5417 5418 5419 5420 5421 5422 5423
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5424 5425 5426
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5427 5428 5429 5430 5431
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5432 5433 5434
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5435 5436 5437 5438 5439 5440 5441
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5442 5443 5444 5445
        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);
5446 5447 5448 5449 5450
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5451 5452 5453 5454
        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);
5455 5456 5457 5458 5459 5460 5461
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5462 5463
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5464 5465 5466 5467 5468
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5469 5470
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5471 5472 5473
        break;
    }
    if (opc2 & 0x04) {
5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489
        /* (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 */
5490
                tcg_gen_movi_tl(cpu_ov, 0);
5491 5492 5493 5494 5495 5496 5497
            }
            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);
A
aurel32 已提交
5498
                if (opc3 & 0x02) {
5499 5500 5501 5502 5503 5504 5505
                    /* 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);
A
aurel32 已提交
5506
                if (opc3 & 0x02) {
5507 5508 5509 5510 5511 5512
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
5513 5514
                tcg_gen_movi_tl(cpu_ov, 1);
                tcg_gen_movi_tl(cpu_so, 1);
5515 5516 5517 5518 5519 5520
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5521
    }
5522 5523
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5524 5525
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5526
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5527 5528 5529
    }
}

5530
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5531
static void glue(gen_, name)(DisasContext *ctx)                               \
5532 5533 5534 5535 5536 5537
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5538
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5539
/* macchwo   - macchwo.   */
5540
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5541
/* macchws   - macchws.   */
5542
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5543
/* macchwso  - macchwso.  */
5544
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5545
/* macchwsu  - macchwsu.  */
5546
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5547
/* macchwsuo - macchwsuo. */
5548
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5549
/* macchwu   - macchwu.   */
5550
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5551
/* macchwuo  - macchwuo.  */
5552
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5553
/* machhw    - machhw.    */
5554
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5555
/* machhwo   - machhwo.   */
5556
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5557
/* machhws   - machhws.   */
5558
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5559
/* machhwso  - machhwso.  */
5560
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5561
/* machhwsu  - machhwsu.  */
5562
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5563
/* machhwsuo - machhwsuo. */
5564
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5565
/* machhwu   - machhwu.   */
5566
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5567
/* machhwuo  - machhwuo.  */
5568
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5569
/* maclhw    - maclhw.    */
5570
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5571
/* maclhwo   - maclhwo.   */
5572
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5573
/* maclhws   - maclhws.   */
5574
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5575
/* maclhwso  - maclhwso.  */
5576
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5577
/* maclhwu   - maclhwu.   */
5578
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5579
/* maclhwuo  - maclhwuo.  */
5580
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5581
/* maclhwsu  - maclhwsu.  */
5582
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5583
/* maclhwsuo - maclhwsuo. */
5584
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5585
/* nmacchw   - nmacchw.   */
5586
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5587
/* nmacchwo  - nmacchwo.  */
5588
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5589
/* nmacchws  - nmacchws.  */
5590
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5591
/* nmacchwso - nmacchwso. */
5592
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5593
/* nmachhw   - nmachhw.   */
5594
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5595
/* nmachhwo  - nmachhwo.  */
5596
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5597
/* nmachhws  - nmachhws.  */
5598
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5599
/* nmachhwso - nmachhwso. */
5600
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5601
/* nmaclhw   - nmaclhw.   */
5602
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5603
/* nmaclhwo  - nmaclhwo.  */
5604
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5605
/* nmaclhws  - nmaclhws.  */
5606
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5607
/* nmaclhwso - nmaclhwso. */
5608
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5609 5610

/* mulchw  - mulchw.  */
5611
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5612
/* mulchwu - mulchwu. */
5613
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5614
/* mulhhw  - mulhhw.  */
5615
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5616
/* mulhhwu - mulhhwu. */
5617
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5618
/* mullhw  - mullhw.  */
5619
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5620
/* mullhwu - mullhwu. */
5621
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5622 5623

/* mfdcr */
B
Blue Swirl 已提交
5624
static void gen_mfdcr(DisasContext *ctx)
5625 5626
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5627
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5628
#else
5629
    TCGv dcrn;
A
aurel32 已提交
5630
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5631
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5632 5633
        return;
    }
5634 5635 5636
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5637
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5638
    tcg_temp_free(dcrn);
5639 5640 5641 5642
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5643
static void gen_mtdcr(DisasContext *ctx)
5644 5645
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5646
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5647
#else
5648
    TCGv dcrn;
A
aurel32 已提交
5649
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5650
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5651 5652
        return;
    }
5653 5654 5655
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5656
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5657
    tcg_temp_free(dcrn);
5658 5659 5660 5661
#endif
}

/* mfdcrx */
5662
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5663
static void gen_mfdcrx(DisasContext *ctx)
5664 5665
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5666
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5667
#else
A
aurel32 已提交
5668
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5669
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5670 5671
        return;
    }
5672 5673
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5674 5675
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5676
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5677 5678 5679 5680
#endif
}

/* mtdcrx */
5681
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5682
static void gen_mtdcrx(DisasContext *ctx)
5683 5684
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5685
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5686
#else
A
aurel32 已提交
5687
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5688
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5689 5690
        return;
    }
5691 5692
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5693 5694
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
5695
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5696 5697 5698
#endif
}

5699
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5700
static void gen_mfdcrux(DisasContext *ctx)
5701
{
5702 5703
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5704 5705
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5706 5707 5708 5709
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5710
static void gen_mtdcrux(DisasContext *ctx)
5711
{
5712 5713
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5714
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5715
                         cpu_gpr[rS(ctx->opcode)]);
5716 5717 5718
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5719
/* dccci */
B
Blue Swirl 已提交
5720
static void gen_dccci(DisasContext *ctx)
5721 5722
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5723
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5724
#else
A
aurel32 已提交
5725
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5726
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5727 5728 5729 5730 5731 5732 5733
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5734
static void gen_dcread(DisasContext *ctx)
5735 5736
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5737
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5738
#else
A
aurel32 已提交
5739
    TCGv EA, val;
A
aurel32 已提交
5740
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5741
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5742 5743
        return;
    }
A
aurel32 已提交
5744
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5745
    EA = tcg_temp_new();
A
aurel32 已提交
5746
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5747
    val = tcg_temp_new();
A
aurel32 已提交
5748
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5749 5750 5751
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5752 5753 5754 5755
#endif
}

/* icbt */
B
Blue Swirl 已提交
5756
static void gen_icbt_40x(DisasContext *ctx)
5757 5758 5759 5760 5761 5762 5763 5764
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
}

/* iccci */
B
Blue Swirl 已提交
5765
static void gen_iccci(DisasContext *ctx)
5766 5767
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5768
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5769
#else
A
aurel32 已提交
5770
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5771
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5772 5773 5774 5775 5776 5777 5778
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5779
static void gen_icread(DisasContext *ctx)
5780 5781
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5782
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5783
#else
A
aurel32 已提交
5784
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5785
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5786 5787 5788 5789 5790 5791
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5792
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5793
static void gen_rfci_40x(DisasContext *ctx)
5794 5795
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5796
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5797
#else
A
aurel32 已提交
5798
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5799
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5800 5801 5802
        return;
    }
    /* Restore CPU state */
5803
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
5804
    gen_sync_exception(ctx);
5805 5806 5807
#endif
}

B
Blue Swirl 已提交
5808
static void gen_rfci(DisasContext *ctx)
5809 5810
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5811
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5812
#else
A
aurel32 已提交
5813
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5814
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5815 5816 5817
        return;
    }
    /* Restore CPU state */
5818
    gen_helper_rfci(cpu_env);
A
aurel32 已提交
5819
    gen_sync_exception(ctx);
5820 5821 5822 5823
#endif
}

/* BookE specific */
B
Blue Swirl 已提交
5824

5825
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5826
static void gen_rfdi(DisasContext *ctx)
5827 5828
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5829
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5830
#else
A
aurel32 已提交
5831
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5832
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5833 5834 5835
        return;
    }
    /* Restore CPU state */
5836
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
5837
    gen_sync_exception(ctx);
5838 5839 5840
#endif
}

5841
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5842
static void gen_rfmci(DisasContext *ctx)
5843 5844
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5845
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5846
#else
A
aurel32 已提交
5847
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5848
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5849 5850 5851
        return;
    }
    /* Restore CPU state */
5852
    gen_helper_rfmci(cpu_env);
A
aurel32 已提交
5853
    gen_sync_exception(ctx);
5854 5855
#endif
}
5856

5857
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5858

5859
/* tlbre */
B
Blue Swirl 已提交
5860
static void gen_tlbre_40x(DisasContext *ctx)
5861 5862
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5863
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5864
#else
A
aurel32 已提交
5865
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5866
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5867 5868 5869 5870
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5871 5872
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5873 5874
        break;
    case 1:
5875 5876
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5877 5878
        break;
    default:
A
aurel32 已提交
5879
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5880
        break;
5881
    }
5882 5883 5884
#endif
}

5885
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5886
static void gen_tlbsx_40x(DisasContext *ctx)
5887 5888
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5889
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5890
#else
5891
    TCGv t0;
A
aurel32 已提交
5892
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5893
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5894 5895
        return;
    }
5896
    t0 = tcg_temp_new();
A
aurel32 已提交
5897
    gen_addr_reg_index(ctx, t0);
5898
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5899 5900 5901
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
5902
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5903 5904 5905 5906
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
        gen_set_label(l1);
    }
5907
#endif
B
bellard 已提交
5908 5909
}

5910
/* tlbwe */
B
Blue Swirl 已提交
5911
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5912
{
5913
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5914
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5915
#else
A
aurel32 已提交
5916
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5917
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5918 5919 5920 5921
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5922 5923
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
5924 5925
        break;
    case 1:
5926 5927
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
5928 5929
        break;
    default:
A
aurel32 已提交
5930
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5931
        break;
5932
    }
5933 5934 5935
#endif
}

5936
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5937

5938
/* tlbre */
B
Blue Swirl 已提交
5939
static void gen_tlbre_440(DisasContext *ctx)
5940 5941
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5942
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5943
#else
A
aurel32 已提交
5944
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5945
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5946 5947 5948 5949 5950 5951
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5952 5953
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5954 5955
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
5956 5957
            tcg_temp_free_i32(t0);
        }
5958 5959
        break;
    default:
A
aurel32 已提交
5960
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5961 5962 5963 5964 5965 5966
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5967
static void gen_tlbsx_440(DisasContext *ctx)
5968 5969
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5970
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5971
#else
5972
    TCGv t0;
A
aurel32 已提交
5973
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5974
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5975 5976
        return;
    }
5977
    t0 = tcg_temp_new();
A
aurel32 已提交
5978
    gen_addr_reg_index(ctx, t0);
5979
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5980 5981 5982
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
5983
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5984 5985 5986 5987
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
        gen_set_label(l1);
    }
5988 5989 5990 5991
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
5992
static void gen_tlbwe_440(DisasContext *ctx)
5993 5994
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5995
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5996
#else
A
aurel32 已提交
5997
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5998
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5999 6000 6001 6002 6003 6004
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6005 6006
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6007 6008
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
6009 6010
            tcg_temp_free_i32(t0);
        }
6011 6012
        break;
    default:
A
aurel32 已提交
6013
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6014 6015 6016 6017 6018
        break;
    }
#endif
}

A
Alexander Graf 已提交
6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031
/* TLB management - PowerPC BookE 2.06 implementation */

/* tlbre */
static void gen_tlbre_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

6032
    gen_helper_booke206_tlbre(cpu_env);
A
Alexander Graf 已提交
6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055
#endif
}

/* tlbsx - tlbsx. */
static void gen_tlbsx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    if (rA(ctx->opcode)) {
        t0 = tcg_temp_new();
        tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
    } else {
        t0 = tcg_const_tl(0);
    }

    tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6056
    gen_helper_booke206_tlbsx(cpu_env, t0);
A
Alexander Graf 已提交
6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069
#endif
}

/* tlbwe */
static void gen_tlbwe_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }
6070
    gen_update_nip(ctx, ctx->nip - 4);
6071
    gen_helper_booke206_tlbwe(cpu_env);
A
Alexander Graf 已提交
6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088
#endif
}

static void gen_tlbivax_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);

6089
    gen_helper_booke206_tlbivax(cpu_env, t0);
A
Alexander Graf 已提交
6090 6091 6092
#endif
}

A
Alexander Graf 已提交
6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108
static void gen_tlbilx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);

    switch((ctx->opcode >> 21) & 0x3) {
    case 0:
6109
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6110 6111
        break;
    case 1:
6112
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6113 6114
        break;
    case 3:
6115
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6116 6117 6118 6119 6120 6121 6122 6123 6124 6125
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6126

6127
/* wrtee */
B
Blue Swirl 已提交
6128
static void gen_wrtee(DisasContext *ctx)
6129 6130
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6131
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6132
#else
6133
    TCGv t0;
A
aurel32 已提交
6134
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6135
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6136 6137
        return;
    }
6138 6139 6140 6141 6142
    t0 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
    tcg_temp_free(t0);
J
j_mayer 已提交
6143 6144 6145
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6146
    gen_stop_exception(ctx);
6147 6148 6149 6150
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6151
static void gen_wrteei(DisasContext *ctx)
6152 6153
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6154
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6155
#else
A
aurel32 已提交
6156
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6157
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6158 6159
        return;
    }
6160
    if (ctx->opcode & 0x00008000) {
6161 6162
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6163
        gen_stop_exception(ctx);
6164
    } else {
A
aurel32 已提交
6165
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6166
    }
6167 6168 6169
#endif
}

J
j_mayer 已提交
6170
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6171

6172
/* dlmzb */
B
Blue Swirl 已提交
6173
static void gen_dlmzb(DisasContext *ctx)
6174
{
6175
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6176 6177
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6178
    tcg_temp_free_i32(t0);
6179 6180 6181
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6182
static void gen_mbar(DisasContext *ctx)
6183 6184 6185 6186 6187
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6188
static void gen_msync_4xx(DisasContext *ctx)
6189 6190 6191 6192 6193
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6194
static void gen_icbt_440(DisasContext *ctx)
6195 6196 6197 6198 6199
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6200 6201
}

A
Alexander Graf 已提交
6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213
/* Embedded.Processor Control */

static void gen_msgclr(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(ctx->mem_idx == 0)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

6214
    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
A
Alexander Graf 已提交
6215 6216 6217
#endif
}

A
Alexander Graf 已提交
6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231
static void gen_msgsnd(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(ctx->mem_idx == 0)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
#endif
}

6232 6233 6234
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6235
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6236
{
A
aurel32 已提交
6237
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6238 6239 6240 6241
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6242
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6243
static void glue(gen_, name)(DisasContext *ctx)                                       \
6244
{                                                                             \
6245
    TCGv EA;                                                                  \
6246
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6247
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6248 6249
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6250
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6251
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6252
    gen_addr_reg_index(ctx, EA);                                              \
6253
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6254 6255
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6256
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6257
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6258
    } else {                                                                  \
A
aurel32 已提交
6259
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6260
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6261
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6262 6263
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6264 6265 6266
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6267
static void gen_st##name(DisasContext *ctx)                                   \
6268
{                                                                             \
6269
    TCGv EA;                                                                  \
6270
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6271
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6272 6273
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6274
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6275
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6276
    gen_addr_reg_index(ctx, EA);                                              \
6277
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6278 6279
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6280
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6281
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6282
    } else {                                                                  \
A
aurel32 已提交
6283
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6284
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6285
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6286 6287
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6288 6289
}

A
aurel32 已提交
6290
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6291
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302
    {                                                                   \
        TCGv EA;                                                        \
        TCGv_ptr rs;                                                    \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        gen_set_access_type(ctx, ACCESS_INT);                           \
        EA = tcg_temp_new();                                            \
        gen_addr_reg_index(ctx, EA);                                    \
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6303
        gen_helper_lve##name(cpu_env, rs, EA);                          \
A
aurel32 已提交
6304 6305 6306 6307 6308
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6309
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320
    {                                                                   \
        TCGv EA;                                                        \
        TCGv_ptr rs;                                                    \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        gen_set_access_type(ctx, ACCESS_INT);                           \
        EA = tcg_temp_new();                                            \
        gen_addr_reg_index(ctx, EA);                                    \
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6321
        gen_helper_stve##name(cpu_env, rs, EA);                         \
A
aurel32 已提交
6322 6323 6324 6325
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6326
GEN_VR_LDX(lvx, 0x07, 0x03);
6327
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6328
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6329

A
aurel32 已提交
6330 6331 6332 6333
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6334
GEN_VR_STX(svx, 0x07, 0x07);
6335
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6336
GEN_VR_STX(svxl, 0x07, 0x0F);
6337

A
aurel32 已提交
6338 6339 6340 6341
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6342
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357
{
    TCGv_ptr rd;
    TCGv EA;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_lvsl(rd, EA);
    tcg_temp_free(EA);
    tcg_temp_free_ptr(rd);
}

B
Blue Swirl 已提交
6358
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373
{
    TCGv_ptr rd;
    TCGv EA;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_lvsr(rd, EA);
    tcg_temp_free(EA);
    tcg_temp_free_ptr(rd);
}

B
Blue Swirl 已提交
6374
static void gen_mfvscr(DisasContext *ctx)
6375 6376 6377 6378 6379 6380 6381 6382
{
    TCGv_i32 t;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
    t = tcg_temp_new_i32();
6383
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6384
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6385
    tcg_temp_free_i32(t);
6386 6387
}

B
Blue Swirl 已提交
6388
static void gen_mtvscr(DisasContext *ctx)
6389
{
A
aurel32 已提交
6390
    TCGv_ptr p;
6391 6392 6393 6394
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6395
    p = gen_avr_ptr(rD(ctx->opcode));
6396
    gen_helper_mtvscr(cpu_env, p);
A
aurel32 已提交
6397
    tcg_temp_free_ptr(p);
6398 6399
}

6400 6401
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6402
static void glue(gen_, name)(DisasContext *ctx)                                 \
6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417
{                                                                       \
    if (unlikely(!ctx->altivec_enabled)) {                              \
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
        return;                                                         \
    }                                                                   \
    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
}

GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);

6418
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6419
static void glue(gen_, name)(DisasContext *ctx)                                 \
6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434
{                                                                       \
    TCGv_ptr ra, rb, rd;                                                \
    if (unlikely(!ctx->altivec_enabled)) {                              \
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
        return;                                                         \
    }                                                                   \
    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
    gen_helper_##name (rd, ra, rb);                                     \
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445
#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
static void glue(gen_, name)(DisasContext *ctx)                         \
{                                                                       \
    TCGv_ptr ra, rb, rd;                                                \
    if (unlikely(!ctx->altivec_enabled)) {                              \
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
        return;                                                         \
    }                                                                   \
    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
6446
    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6447 6448 6449 6450 6451
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6452 6453 6454 6455 6456 6457
GEN_VXFORM(vaddubm, 0, 0);
GEN_VXFORM(vadduhm, 0, 1);
GEN_VXFORM(vadduwm, 0, 2);
GEN_VXFORM(vsububm, 0, 16);
GEN_VXFORM(vsubuhm, 0, 17);
GEN_VXFORM(vsubuwm, 0, 18);
6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469
GEN_VXFORM(vmaxub, 1, 0);
GEN_VXFORM(vmaxuh, 1, 1);
GEN_VXFORM(vmaxuw, 1, 2);
GEN_VXFORM(vmaxsb, 1, 4);
GEN_VXFORM(vmaxsh, 1, 5);
GEN_VXFORM(vmaxsw, 1, 6);
GEN_VXFORM(vminub, 1, 8);
GEN_VXFORM(vminuh, 1, 9);
GEN_VXFORM(vminuw, 1, 10);
GEN_VXFORM(vminsb, 1, 12);
GEN_VXFORM(vminsh, 1, 13);
GEN_VXFORM(vminsw, 1, 14);
A
aurel32 已提交
6470 6471 6472 6473 6474 6475
GEN_VXFORM(vavgub, 1, 16);
GEN_VXFORM(vavguh, 1, 17);
GEN_VXFORM(vavguw, 1, 18);
GEN_VXFORM(vavgsb, 1, 20);
GEN_VXFORM(vavgsh, 1, 21);
GEN_VXFORM(vavgsw, 1, 22);
A
aurel32 已提交
6476 6477 6478 6479 6480 6481
GEN_VXFORM(vmrghb, 6, 0);
GEN_VXFORM(vmrghh, 6, 1);
GEN_VXFORM(vmrghw, 6, 2);
GEN_VXFORM(vmrglb, 6, 4);
GEN_VXFORM(vmrglh, 6, 5);
GEN_VXFORM(vmrglw, 6, 6);
A
aurel32 已提交
6482 6483 6484 6485 6486 6487 6488 6489
GEN_VXFORM(vmuloub, 4, 0);
GEN_VXFORM(vmulouh, 4, 1);
GEN_VXFORM(vmulosb, 4, 4);
GEN_VXFORM(vmulosh, 4, 5);
GEN_VXFORM(vmuleub, 4, 8);
GEN_VXFORM(vmuleuh, 4, 9);
GEN_VXFORM(vmulesb, 4, 12);
GEN_VXFORM(vmulesh, 4, 13);
A
aurel32 已提交
6490 6491 6492
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6493 6494 6495 6496 6497 6498
GEN_VXFORM(vsrb, 2, 8);
GEN_VXFORM(vsrh, 2, 9);
GEN_VXFORM(vsrw, 2, 10);
GEN_VXFORM(vsrab, 2, 12);
GEN_VXFORM(vsrah, 2, 13);
GEN_VXFORM(vsraw, 2, 14);
A
aurel32 已提交
6499 6500
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6501 6502
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514
GEN_VXFORM_ENV(vaddubs, 0, 8);
GEN_VXFORM_ENV(vadduhs, 0, 9);
GEN_VXFORM_ENV(vadduws, 0, 10);
GEN_VXFORM_ENV(vaddsbs, 0, 12);
GEN_VXFORM_ENV(vaddshs, 0, 13);
GEN_VXFORM_ENV(vaddsws, 0, 14);
GEN_VXFORM_ENV(vsububs, 0, 24);
GEN_VXFORM_ENV(vsubuhs, 0, 25);
GEN_VXFORM_ENV(vsubuws, 0, 26);
GEN_VXFORM_ENV(vsubsbs, 0, 28);
GEN_VXFORM_ENV(vsubshs, 0, 29);
GEN_VXFORM_ENV(vsubsws, 0, 30);
A
aurel32 已提交
6515 6516 6517
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6518 6519
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6520 6521 6522 6523 6524 6525 6526 6527
GEN_VXFORM_ENV(vpkuhum, 7, 0);
GEN_VXFORM_ENV(vpkuwum, 7, 1);
GEN_VXFORM_ENV(vpkuhus, 7, 2);
GEN_VXFORM_ENV(vpkuwus, 7, 3);
GEN_VXFORM_ENV(vpkshus, 7, 4);
GEN_VXFORM_ENV(vpkswus, 7, 5);
GEN_VXFORM_ENV(vpkshss, 7, 6);
GEN_VXFORM_ENV(vpkswss, 7, 7);
A
aurel32 已提交
6528
GEN_VXFORM(vpkpx, 7, 12);
6529 6530 6531 6532 6533 6534 6535 6536 6537
GEN_VXFORM_ENV(vsum4ubs, 4, 24);
GEN_VXFORM_ENV(vsum4sbs, 4, 28);
GEN_VXFORM_ENV(vsum4shs, 4, 25);
GEN_VXFORM_ENV(vsum2sws, 4, 26);
GEN_VXFORM_ENV(vsumsws, 4, 30);
GEN_VXFORM_ENV(vaddfp, 5, 0);
GEN_VXFORM_ENV(vsubfp, 5, 1);
GEN_VXFORM_ENV(vmaxfp, 5, 16);
GEN_VXFORM_ENV(vminfp, 5, 17);
A
aurel32 已提交
6538

6539
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6540
static void glue(gen_, name)(DisasContext *ctx)                         \
6541 6542 6543 6544 6545 6546 6547 6548 6549
    {                                                                   \
        TCGv_ptr ra, rb, rd;                                            \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6550
        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
6551 6552 6553 6554 6555 6556 6557 6558 6559
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

#define GEN_VXRFORM(name, opc2, opc3)                                \
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))

6560 6561 6562 6563 6564 6565 6566 6567 6568
GEN_VXRFORM(vcmpequb, 3, 0)
GEN_VXRFORM(vcmpequh, 3, 1)
GEN_VXRFORM(vcmpequw, 3, 2)
GEN_VXRFORM(vcmpgtsb, 3, 12)
GEN_VXRFORM(vcmpgtsh, 3, 13)
GEN_VXRFORM(vcmpgtsw, 3, 14)
GEN_VXRFORM(vcmpgtub, 3, 8)
GEN_VXRFORM(vcmpgtuh, 3, 9)
GEN_VXRFORM(vcmpgtuw, 3, 10)
6569 6570 6571 6572
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6573

A
aurel32 已提交
6574
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6575
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593
    {                                                                   \
        TCGv_ptr rd;                                                    \
        TCGv_i32 simm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, simm);                                   \
        tcg_temp_free_i32(simm);                                        \
        tcg_temp_free_ptr(rd);                                          \
    }

GEN_VXFORM_SIMM(vspltisb, 6, 12);
GEN_VXFORM_SIMM(vspltish, 6, 13);
GEN_VXFORM_SIMM(vspltisw, 6, 14);

6594
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6595
static void glue(gen_, name)(DisasContext *ctx)                                 \
6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, rb);                                     \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                         \
    }

6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624
#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
static void glue(gen_, name)(DisasContext *ctx)                         \
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
                                                                        \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name(cpu_env, rd, rb);                             \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6625 6626 6627 6628
GEN_VXFORM_NOA(vupkhsb, 7, 8);
GEN_VXFORM_NOA(vupkhsh, 7, 9);
GEN_VXFORM_NOA(vupklsb, 7, 10);
GEN_VXFORM_NOA(vupklsh, 7, 11);
A
aurel32 已提交
6629 6630
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
6631 6632 6633 6634 6635 6636 6637 6638
GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
GEN_VXFORM_NOA_ENV(vrfim, 5, 8);
GEN_VXFORM_NOA_ENV(vrfin, 5, 9);
GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
GEN_VXFORM_NOA_ENV(vrfiz, 5, 11);
A
aurel32 已提交
6639

6640
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6641
static void glue(gen_, name)(DisasContext *ctx)                                 \
6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655
    {                                                                   \
        TCGv_ptr rd;                                                    \
        TCGv_i32 simm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, simm);                                   \
        tcg_temp_free_i32(simm);                                        \
        tcg_temp_free_ptr(rd);                                          \
    }

6656
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6657
static void glue(gen_, name)(DisasContext *ctx)                                 \
6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
        TCGv_i32 uimm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, rb, uimm);                               \
        tcg_temp_free_i32(uimm);                                        \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692
#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
static void glue(gen_, name)(DisasContext *ctx)                         \
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
        TCGv_i32 uimm;                                                  \
                                                                        \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
        tcg_temp_free_i32(uimm);                                        \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6693 6694 6695
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
6696 6697 6698 6699
GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
A
aurel32 已提交
6700

B
Blue Swirl 已提交
6701
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6702 6703
{
    TCGv_ptr ra, rb, rd;
6704
    TCGv_i32 sh;
A
aurel32 已提交
6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    ra = gen_avr_ptr(rA(ctx->opcode));
    rb = gen_avr_ptr(rB(ctx->opcode));
    rd = gen_avr_ptr(rD(ctx->opcode));
    sh = tcg_const_i32(VSH(ctx->opcode));
    gen_helper_vsldoi (rd, ra, rb, sh);
    tcg_temp_free_ptr(ra);
    tcg_temp_free_ptr(rb);
    tcg_temp_free_ptr(rd);
6717
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6718 6719
}

6720
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6721
static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732
    {                                                                   \
        TCGv_ptr ra, rb, rc, rd;                                        \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rc = gen_avr_ptr(rC(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        if (Rc(ctx->opcode)) {                                          \
6733
            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
6734
        } else {                                                        \
6735
            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
6736 6737 6738 6739 6740 6741 6742
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6743 6744
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6745
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762
{
    TCGv_ptr ra, rb, rc, rd;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    ra = gen_avr_ptr(rA(ctx->opcode));
    rb = gen_avr_ptr(rB(ctx->opcode));
    rc = gen_avr_ptr(rC(ctx->opcode));
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_vmladduhm(rd, ra, rb, rc);
    tcg_temp_free_ptr(ra);
    tcg_temp_free_ptr(rb);
    tcg_temp_free_ptr(rc);
    tcg_temp_free_ptr(rd);
}

A
aurel32 已提交
6763
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6764
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6765
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6766
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6767
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6768

6769 6770
/***                           SPE extension                               ***/
/* Register moves */
6771

6772 6773 6774 6775 6776

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6777
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6778 6779 6780 6781 6782 6783 6784 6785 6786 6787
        return;
    }

#if defined(TARGET_PPC64)
    /* rD := rA */
    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);

    /* spe_acc := rA */
    tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
                   cpu_env,
6788
                   offsetof(CPUPPCState, spe_acc));
6789 6790 6791 6792 6793 6794 6795
#else
    TCGv_i64 tmp = tcg_temp_new_i64();

    /* tmp := rA_lo + rA_hi << 32 */
    tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);

    /* spe_acc := tmp */
6796
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
6797 6798 6799 6800 6801 6802 6803 6804
    tcg_temp_free_i64(tmp);

    /* rD := rA */
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}

B
Blue Swirl 已提交
6805 6806
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6807 6808 6809
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6810
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6811
#endif
A
aurel32 已提交
6812
}
6813

B
Blue Swirl 已提交
6814 6815
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6816 6817 6818
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6819
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6820 6821 6822
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
P
pbrook 已提交
6823
    tcg_temp_free_i64(tmp);
6824
#endif
A
aurel32 已提交
6825
}
6826

6827
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
6828
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6829 6830 6831 6832 6833 6834 6835 6836
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6837
static inline void gen_speundef(DisasContext *ctx)
6838
{
A
aurel32 已提交
6839
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6840 6841
}

6842 6843 6844
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6845
static inline void gen_##name(DisasContext *ctx)                              \
6846 6847
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6848
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6849 6850
        return;                                                               \
    }                                                                         \
6851 6852 6853 6854 6855
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
}
#else
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6856
static inline void gen_##name(DisasContext *ctx)                              \
6857 6858
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6859
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6860 6861 6862 6863 6864 6865
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
           cpu_gprh[rB(ctx->opcode)]);                                        \
6866
}
6867 6868 6869 6870 6871 6872 6873 6874 6875 6876
#endif

GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6877

6878 6879 6880
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6881
static inline void gen_##name(DisasContext *ctx)                              \
6882 6883
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6884
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6885 6886
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6887 6888 6889
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6890 6891 6892 6893
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6894
    tcg_temp_free_i64(t2);                                                    \
6895 6896
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6897 6898
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6899
}
6900 6901
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6902
static inline void gen_##name(DisasContext *ctx)                              \
6903 6904
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6905
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6906 6907
        return;                                                               \
    }                                                                         \
6908 6909 6910 6911
    tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],               \
            rB(ctx->opcode));                                                 \
    tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],             \
            rB(ctx->opcode));                                                 \
6912
}
6913 6914 6915 6916 6917
#endif
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6918

6919 6920 6921
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6922
static inline void gen_##name(DisasContext *ctx)                              \
6923 6924
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6925
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6926 6927
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6928 6929 6930
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6931 6932 6933 6934
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_op(t0, t0);                                                           \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6935
    tcg_temp_free_i64(t2);                                                    \
6936 6937
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6938 6939
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6940
}
6941
#else
P
pbrook 已提交
6942
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6943
static inline void gen_##name(DisasContext *ctx)                              \
6944 6945
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6946
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6947 6948 6949 6950 6951 6952
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
}
#endif
6953

B
Blue Swirl 已提交
6954
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6955 6956 6957
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6958

6959 6960 6961 6962
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
    tcg_gen_neg_i32(ret, arg1);
    tcg_gen_br(l2);
    gen_set_label(l1);
P
pbrook 已提交
6963
    tcg_gen_mov_i32(ret, arg1);
6964 6965 6966 6967 6968 6969
    gen_set_label(l2);
}
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
B
Blue Swirl 已提交
6970
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6971
{
6972 6973 6974 6975
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6976 6977
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6978

6979 6980
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6981
static inline void gen_##name(DisasContext *ctx)                              \
6982 6983
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6984
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6985 6986
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6987 6988 6989
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6990
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6991 6992 6993 6994 6995 6996 6997
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_op(t0, t0, t2);                                                       \
    tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t3);                                            \
    tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t2, t3);                                            \
P
pbrook 已提交
6998
    tcg_temp_free_i64(t3);                                                    \
6999
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
7000
    tcg_temp_free_i32(t2);                                                    \
7001
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7002 7003
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7004
}
7005 7006
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7007
static inline void gen_##name(DisasContext *ctx)                              \
7008 7009
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7010
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7011 7012
        return;                                                               \
    }                                                                         \
7013 7014 7015 7016
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
           cpu_gprh[rB(ctx->opcode)]);                                        \
7017
}
7018
#endif
7019

B
Blue Swirl 已提交
7020
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7021
{
P
pbrook 已提交
7022
    TCGv_i32 t0;
7023
    int l1, l2;
7024

7025 7026
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7027
    t0 = tcg_temp_local_new_i32();
7028 7029 7030 7031 7032 7033 7034
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shr_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
7035
    gen_set_label(l2);
P
pbrook 已提交
7036
    tcg_temp_free_i32(t0);
7037 7038
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7039
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7040
{
P
pbrook 已提交
7041
    TCGv_i32 t0;
7042 7043 7044 7045
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7046
    t0 = tcg_temp_local_new_i32();
7047 7048 7049 7050 7051 7052 7053
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_sar_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
7054
    gen_set_label(l2);
P
pbrook 已提交
7055
    tcg_temp_free_i32(t0);
7056 7057
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7058
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7059
{
P
pbrook 已提交
7060
    TCGv_i32 t0;
7061 7062 7063 7064
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7065
    t0 = tcg_temp_local_new_i32();
7066 7067 7068 7069 7070 7071 7072
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shl_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
7073
    gen_set_label(l2);
P
pbrook 已提交
7074
    tcg_temp_free_i32(t0);
7075 7076
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7077
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7078
{
P
pbrook 已提交
7079
    TCGv_i32 t0 = tcg_temp_new_i32();
7080 7081
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7082
    tcg_temp_free_i32(t0);
7083 7084
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7085
static inline void gen_evmergehi(DisasContext *ctx)
7086 7087
{
    if (unlikely(!ctx->spe_enabled)) {
7088
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7089 7090 7091
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7092 7093
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
B
Blue Swirl 已提交
7105
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7106
{
7107 7108 7109
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7110

7111 7112 7113
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7114
static inline void gen_##name(DisasContext *ctx)                              \
7115 7116
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7117
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7118 7119
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7120 7121 7122
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7123 7124 7125 7126
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
A
aurel32 已提交
7127
    tcg_temp_free_i64(t2);                                                    \
7128 7129
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7130 7131
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7132 7133 7134
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7135
static inline void gen_##name(DisasContext *ctx)                              \
7136 7137
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7138
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
           rA(ctx->opcode));                                                  \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
           rA(ctx->opcode));                                                  \
}
#endif
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);

/* SPE comparison */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7153
static inline void gen_##name(DisasContext *ctx)                              \
7154 7155
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7156
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7157 7158 7159 7160 7161 7162
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7163 7164 7165
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7166 7167 7168
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
P
pbrook 已提交
7169
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7170 7171 7172 7173 7174 7175 7176 7177 7178
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
7179
    tcg_temp_free_i64(t2);                                                    \
7180 7181 7182 7183 7184 7185 7186 7187
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
P
pbrook 已提交
7188 7189
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7190 7191 7192
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7193
static inline void gen_##name(DisasContext *ctx)                              \
7194 7195
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7196
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
                                                                              \
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
}
#endif
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);

/* SPE misc */
B
Blue Swirl 已提交
7230
static inline void gen_brinc(DisasContext *ctx)
7231 7232
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7233 7234
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7235
}
B
Blue Swirl 已提交
7236
static inline void gen_evmergelo(DisasContext *ctx)
7237 7238
{
    if (unlikely(!ctx->spe_enabled)) {
7239
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7240 7241 7242
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7243 7244
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7245
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7246 7247 7248 7249 7250 7251
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7252
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7253 7254
#endif
}
B
Blue Swirl 已提交
7255
static inline void gen_evmergehilo(DisasContext *ctx)
7256 7257
{
    if (unlikely(!ctx->spe_enabled)) {
7258
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7259 7260 7261
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7262 7263
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7264
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7265 7266 7267 7268 7269 7270 7271 7272 7273
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
B
Blue Swirl 已提交
7274
static inline void gen_evmergelohi(DisasContext *ctx)
7275 7276
{
    if (unlikely(!ctx->spe_enabled)) {
7277
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7278 7279 7280
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7281 7282
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7283 7284 7285 7286 7287 7288
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
7289 7290 7291 7292 7293 7294 7295 7296 7297 7298
    if (rD(ctx->opcode) == rA(ctx->opcode)) {
        TCGv_i32 tmp = tcg_temp_new_i32();
        tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
        tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
        tcg_temp_free_i32(tmp);
    } else {
        tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
        tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    }
7299 7300
#endif
}
B
Blue Swirl 已提交
7301
static inline void gen_evsplati(DisasContext *ctx)
7302
{
7303
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7304

7305
#if defined(TARGET_PPC64)
7306
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7307 7308 7309 7310 7311
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
}
B
Blue Swirl 已提交
7312
static inline void gen_evsplatfi(DisasContext *ctx)
7313
{
7314
    uint64_t imm = rA(ctx->opcode) << 27;
7315

7316
#if defined(TARGET_PPC64)
7317
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7318 7319 7320 7321
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7322 7323
}

B
Blue Swirl 已提交
7324
static inline void gen_evsel(DisasContext *ctx)
7325 7326 7327 7328 7329
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7330
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7331
#if defined(TARGET_PPC64)
P
pbrook 已提交
7332 7333
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352
#endif
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l2);
    gen_set_label(l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
#endif
    gen_set_label(l2);
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
#if defined(TARGET_PPC64)
7353
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7354 7355 7356 7357 7358 7359
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l4);
    gen_set_label(l3);
#if defined(TARGET_PPC64)
7360
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7361 7362 7363 7364
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7365
    tcg_temp_free_i32(t0);
7366 7367 7368 7369 7370 7371
#if defined(TARGET_PPC64)
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
#endif
}
B
Blue Swirl 已提交
7372 7373

static void gen_evsel0(DisasContext *ctx)
7374 7375 7376
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7377 7378

static void gen_evsel1(DisasContext *ctx)
7379 7380 7381
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7382 7383

static void gen_evsel2(DisasContext *ctx)
7384 7385 7386
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7387 7388

static void gen_evsel3(DisasContext *ctx)
7389 7390 7391
{
    gen_evsel(ctx);
}
7392

7393 7394 7395 7396 7397 7398 7399
/* Multiply */

static inline void gen_evmwumi(DisasContext *ctx)
{
    TCGv_i64 t0, t1;

    if (unlikely(!ctx->spe_enabled)) {
7400
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428
        return;
    }

    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();

    /* t0 := rA; t1 := rB */
#if defined(TARGET_PPC64)
    tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#endif

    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */

    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
}

static inline void gen_evmwumia(DisasContext *ctx)
{
    TCGv_i64 tmp;

    if (unlikely(!ctx->spe_enabled)) {
7429
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7430 7431 7432 7433 7434 7435 7436 7437 7438
        return;
    }

    gen_evmwumi(ctx);            /* rD := rA * rB */

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7439
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7440 7441 7442 7443 7444 7445 7446 7447 7448
    tcg_temp_free_i64(tmp);
}

static inline void gen_evmwumiaa(DisasContext *ctx)
{
    TCGv_i64 acc;
    TCGv_i64 tmp;

    if (unlikely(!ctx->spe_enabled)) {
7449
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461
        return;
    }

    gen_evmwumi(ctx);           /* rD := rA * rB */

    acc = tcg_temp_new_i64();
    tmp = tcg_temp_new_i64();

    /* tmp := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));

    /* Load acc */
7462
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7463 7464 7465 7466 7467

    /* acc := tmp + acc */
    tcg_gen_add_i64(acc, acc, tmp);

    /* Store acc */
7468
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481

    /* rD := acc */
    gen_store_gpr64(rD(ctx->opcode), acc);

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

static inline void gen_evmwsmi(DisasContext *ctx)
{
    TCGv_i64 t0, t1;

    if (unlikely(!ctx->spe_enabled)) {
7482
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515
        return;
    }

    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();

    /* t0 := rA; t1 := rB */
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(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)]);
#endif

    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */

    gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
}

static inline void gen_evmwsmia(DisasContext *ctx)
{
    TCGv_i64 tmp;

    gen_evmwsmi(ctx);            /* rD := rA * rB */

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7516
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534

    tcg_temp_free_i64(tmp);
}

static inline void gen_evmwsmiaa(DisasContext *ctx)
{
    TCGv_i64 acc = tcg_temp_new_i64();
    TCGv_i64 tmp = tcg_temp_new_i64();

    gen_evmwsmi(ctx);           /* rD := rA * rB */

    acc = tcg_temp_new_i64();
    tmp = tcg_temp_new_i64();

    /* tmp := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));

    /* Load acc */
7535
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7536 7537 7538 7539 7540

    /* acc := tmp + acc */
    tcg_gen_add_i64(acc, acc, tmp);

    /* Store acc */
7541
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7542 7543 7544 7545 7546 7547 7548 7549

    /* rD := acc */
    gen_store_gpr64(rD(ctx->opcode), acc);

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578
GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
7579

7580
/* SPE load and stores */
B
Blue Swirl 已提交
7581
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7582 7583 7584
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7585
    if (rA(ctx->opcode) == 0) {
7586
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7587
    } else {
7588
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7589 7590 7591 7592 7593 7594
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7595
}
7596

B
Blue Swirl 已提交
7597
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7598 7599
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7600
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7601 7602
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7603
    gen_qemu_ld64(ctx, t0, addr);
7604 7605 7606 7607 7608
    tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_temp_free_i64(t0);
#endif
7609
}
7610

B
Blue Swirl 已提交
7611
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7612
{
7613
#if defined(TARGET_PPC64)
7614
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7615
    gen_qemu_ld32u(ctx, t0, addr);
7616
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7617 7618
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7619 7620 7621
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7622 7623 7624
    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7625
#endif
7626
}
7627

B
Blue Swirl 已提交
7628
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7629 7630 7631
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7632
    gen_qemu_ld16u(ctx, t0, addr);
7633
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7634 7635
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7636 7637
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7638 7639
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7640 7641
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7642 7643
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7644
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7645
#else
A
aurel32 已提交
7646
    gen_qemu_ld16u(ctx, t0, addr);
7647
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7648 7649
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7650
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7651 7652
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7653
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7654 7655
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7656
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7657
#endif
7658
    tcg_temp_free(t0);
7659 7660
}

B
Blue Swirl 已提交
7661
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7662 7663
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7664
    gen_qemu_ld16u(ctx, t0, addr);
7665 7666 7667 7668 7669 7670 7671 7672 7673 7674
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
7675 7676
}

B
Blue Swirl 已提交
7677
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7678 7679
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7680
    gen_qemu_ld16u(ctx, t0, addr);
7681 7682 7683 7684 7685 7686 7687 7688
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
7689 7690
}

B
Blue Swirl 已提交
7691
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7692 7693
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7694
    gen_qemu_ld16s(ctx, t0, addr);
7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_ext32u_tl(t0, t0);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7706
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7707 7708 7709
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7710
    gen_qemu_ld16u(ctx, t0, addr);
7711
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7712 7713
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7714 7715 7716
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
A
aurel32 已提交
7717
    gen_qemu_ld16u(ctx, t0, addr);
7718
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7719 7720
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7721 7722 7723 7724 7725
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7726
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7727 7728 7729
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7730 7731 7732
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7733 7734 7735 7736
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7737 7738 7739
    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7740 7741 7742
#endif
}

B
Blue Swirl 已提交
7743
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7744 7745 7746
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7747
    gen_qemu_ld16s(ctx, t0, addr);
7748
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7749 7750
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7751 7752 7753 7754
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7755 7756 7757
    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7758 7759 7760
#endif
}

B
Blue Swirl 已提交
7761
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7762 7763
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7764
    gen_qemu_ld32u(ctx, t0, addr);
7765
#if defined(TARGET_PPC64)
7766 7767 7768 7769 7770 7771 7772 7773 7774
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7775
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7776 7777 7778
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7779
    gen_qemu_ld16u(ctx, t0, addr);
7780 7781 7782
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7783 7784
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7785 7786 7787 7788
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
A
aurel32 已提交
7789
    gen_qemu_ld16u(ctx, t0, addr);
7790 7791
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7792 7793
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7794 7795
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7796
#endif
7797 7798 7799
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7800
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7801 7802
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7803
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7804
#else
7805 7806
    TCGv_i64 t0 = tcg_temp_new_i64();
    tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
A
aurel32 已提交
7807
    gen_qemu_st64(ctx, t0, addr);
7808 7809 7810 7811
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7812
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7813
{
7814
#if defined(TARGET_PPC64)
7815 7816
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7817
    gen_qemu_st32(ctx, t0, addr);
7818 7819
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7820
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7821
#endif
A
aurel32 已提交
7822 7823
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7824 7825
}

B
Blue Swirl 已提交
7826
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7827 7828 7829 7830 7831 7832 7833
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
#else
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
#endif
A
aurel32 已提交
7834 7835
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7836 7837
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7838
    gen_qemu_st16(ctx, t0, addr);
7839
#else
A
aurel32 已提交
7840
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7841
#endif
A
aurel32 已提交
7842
    gen_addr_add(ctx, addr, addr, 2);
7843
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7844
    gen_qemu_st16(ctx, t0, addr);
7845
    tcg_temp_free(t0);
A
aurel32 已提交
7846 7847
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7848 7849
}

B
Blue Swirl 已提交
7850
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7851 7852 7853 7854 7855 7856 7857
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
#else
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
#endif
A
aurel32 已提交
7858 7859
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7860
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7861
    gen_qemu_st16(ctx, t0, addr);
7862 7863 7864
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7865
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7866 7867 7868 7869
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7870
    gen_qemu_st16(ctx, t0, addr);
7871 7872
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7873
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7874
#endif
A
aurel32 已提交
7875 7876
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7877 7878
}

B
Blue Swirl 已提交
7879
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7880 7881 7882 7883
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7884
    gen_qemu_st32(ctx, t0, addr);
7885 7886
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7887
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7888 7889 7890
#endif
}

B
Blue Swirl 已提交
7891
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7892
{
A
aurel32 已提交
7893
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7894 7895 7896
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7897
static void glue(gen_, name)(DisasContext *ctx)                                       \
7898 7899 7900
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7901
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7902 7903
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7904
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7905 7906
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7907
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7908
    } else {                                                                  \
A
aurel32 已提交
7909
        gen_addr_reg_index(ctx, t0);                                          \
7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933
    }                                                                         \
    gen_op_##name(ctx, t0);                                                   \
    tcg_temp_free(t0);                                                        \
}

GEN_SPEOP_LDST(evldd, 0x00, 3);
GEN_SPEOP_LDST(evldw, 0x01, 3);
GEN_SPEOP_LDST(evldh, 0x02, 3);
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);

GEN_SPEOP_LDST(evstdd, 0x10, 3);
GEN_SPEOP_LDST(evstdw, 0x11, 3);
GEN_SPEOP_LDST(evstdh, 0x12, 3);
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
7934 7935 7936

/* Multiply and add - TODO */
#if 0
7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);

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

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

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

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

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

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

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
8008 8009
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8010
static inline void gen_##name(DisasContext *ctx)                              \
8011
{                                                                             \
A
aurel32 已提交
8012 8013 8014 8015
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8016
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8017 8018 8019 8020 8021 8022 8023
    t1 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t1, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
    tcg_temp_free(t1);                                                        \
8024
}
A
aurel32 已提交
8025
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8026
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8027 8028 8029 8030
{                                                                             \
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
8031
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8032 8033 8034 8035 8036 8037 8038 8039 8040
    t1 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t1, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
    tcg_temp_free(t1);                                                        \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
B
Blue Swirl 已提交
8041
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8042 8043 8044
{                                                                             \
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8045
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8046 8047 8048
    tcg_temp_free_i32(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8049
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8050
{                                                                             \
8051 8052
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
A
aurel32 已提交
8053 8054
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8055
static inline void gen_##name(DisasContext *ctx)                              \
8056
{                                                                             \
A
aurel32 已提交
8057 8058
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
8059
    if (unlikely(!ctx->spe_enabled)) {                                        \
8060
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8061 8062
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8063 8064 8065 8066
    t0 = tcg_temp_new_i32();                                                  \
    t1 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
8067
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8068 8069 8070 8071 8072 8073 8074 8075
    tcg_temp_free_i32(t1);                                                    \
    t2 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t2, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
    tcg_temp_free(t2);                                                        \
8076
}
A
aurel32 已提交
8077
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8078
static inline void gen_##name(DisasContext *ctx)                              \
8079 8080
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8081
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8082 8083
        return;                                                               \
    }                                                                         \
8084 8085
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8086
}
A
aurel32 已提交
8087
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8088
static inline void gen_##name(DisasContext *ctx)                              \
8089
{                                                                             \
A
aurel32 已提交
8090
    TCGv_i32 t0, t1;                                                          \
8091
    if (unlikely(!ctx->spe_enabled)) {                                        \
8092
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8093 8094
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8095 8096 8097 8098
    t0 = tcg_temp_new_i32();                                                  \
    t1 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
8099
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8100 8101 8102 8103
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8104
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8105 8106
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8107
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8108 8109
        return;                                                               \
    }                                                                         \
8110
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8111 8112 8113 8114
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#else
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8115
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8116
{                                                                             \
8117 8118
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
8119
}
A
aurel32 已提交
8120
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8121
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8122 8123 8124
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8125
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8126 8127 8128
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
B
Blue Swirl 已提交
8129
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8130 8131
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
8132
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8133 8134 8135 8136
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8137
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8138 8139 8140
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8141
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8142 8143 8144 8145
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8146
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8147 8148
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8149
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8150 8151
        return;                                                               \
    }                                                                         \
8152
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
A
aurel32 已提交
8153 8154 8155
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8156
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8157 8158 8159
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8160
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8161 8162 8163 8164 8165 8166
        return;                                                               \
    }                                                                         \
    t0 = tcg_temp_new_i64();                                                  \
    t1 = tcg_temp_new_i64();                                                  \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
8167
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8168 8169 8170 8171 8172
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8173
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8174 8175
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8176
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8177 8178
        return;                                                               \
    }                                                                         \
8179
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8180 8181 8182
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8183
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8184 8185 8186
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8187
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8188 8189 8190 8191 8192 8193
        return;                                                               \
    }                                                                         \
    t0 = tcg_temp_new_i64();                                                  \
    t1 = tcg_temp_new_i64();                                                  \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
8194
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8195 8196 8197 8198
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#endif
8199

8200 8201
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8202 8203 8204 8205
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
B
Blue Swirl 已提交
8206
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8207 8208
{
    if (unlikely(!ctx->spe_enabled)) {
8209
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8210 8211 8212
        return;
    }
#if defined(TARGET_PPC64)
8213
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8214
#else
8215 8216
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
A
aurel32 已提交
8217 8218
#endif
}
B
Blue Swirl 已提交
8219
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8220 8221
{
    if (unlikely(!ctx->spe_enabled)) {
8222
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8223 8224 8225
        return;
    }
#if defined(TARGET_PPC64)
8226
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8227
#else
8228 8229
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8230 8231
#endif
}
B
Blue Swirl 已提交
8232
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8233 8234
{
    if (unlikely(!ctx->spe_enabled)) {
8235
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8236 8237 8238
        return;
    }
#if defined(TARGET_PPC64)
8239
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8240
#else
8241 8242
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8243 8244 8245
#endif
}

8246
/* Conversion */
A
aurel32 已提交
8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257
GEN_SPEFPUOP_CONV_64_64(evfscfui);
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
GEN_SPEFPUOP_CONV_64_64(evfsctui);
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);

8258
/* Comparison */
A
aurel32 已提交
8259 8260 8261 8262 8263 8264
GEN_SPEFPUOP_COMP_64(evfscmpgt);
GEN_SPEFPUOP_COMP_64(evfscmplt);
GEN_SPEFPUOP_COMP_64(evfscmpeq);
GEN_SPEFPUOP_COMP_64(evfststgt);
GEN_SPEFPUOP_COMP_64(evfststlt);
GEN_SPEFPUOP_COMP_64(evfststeq);
8265 8266

/* Opcodes definitions */
8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280
GEN_SPE(evfsadd,   evfssub,   0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfsabs,   evfsnabs,  0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsneg,   speundef,  0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfsmul,   evfsdiv,   0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpeq, speundef,  0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfscfui,  evfscfsi,  0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfuf,  evfscfsf,  0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctui,  evfsctsi,  0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuf,  evfsctsf,  0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuiz, speundef,  0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfsctsiz, speundef,  0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfststeq, speundef,  0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8281 8282 8283

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8284 8285 8286 8287
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
GEN_SPEFPUOP_ARITH2_32_32(efssub);
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
B
Blue Swirl 已提交
8288
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8289 8290
{
    if (unlikely(!ctx->spe_enabled)) {
8291
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8292 8293
        return;
    }
8294
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8295
}
B
Blue Swirl 已提交
8296
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8297 8298
{
    if (unlikely(!ctx->spe_enabled)) {
8299
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8300 8301
        return;
    }
8302
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8303
}
B
Blue Swirl 已提交
8304
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8305 8306
{
    if (unlikely(!ctx->spe_enabled)) {
8307
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8308 8309
        return;
    }
8310
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8311 8312
}

8313
/* Conversion */
A
aurel32 已提交
8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325
GEN_SPEFPUOP_CONV_32_32(efscfui);
GEN_SPEFPUOP_CONV_32_32(efscfsi);
GEN_SPEFPUOP_CONV_32_32(efscfuf);
GEN_SPEFPUOP_CONV_32_32(efscfsf);
GEN_SPEFPUOP_CONV_32_32(efsctui);
GEN_SPEFPUOP_CONV_32_32(efsctsi);
GEN_SPEFPUOP_CONV_32_32(efsctuf);
GEN_SPEFPUOP_CONV_32_32(efsctsf);
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
GEN_SPEFPUOP_CONV_32_64(efscfd);

8326
/* Comparison */
A
aurel32 已提交
8327 8328 8329 8330 8331 8332
GEN_SPEFPUOP_COMP_32(efscmpgt);
GEN_SPEFPUOP_COMP_32(efscmplt);
GEN_SPEFPUOP_COMP_32(efscmpeq);
GEN_SPEFPUOP_COMP_32(efststgt);
GEN_SPEFPUOP_COMP_32(efststlt);
GEN_SPEFPUOP_COMP_32(efststeq);
8333 8334

/* Opcodes definitions */
8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348
GEN_SPE(efsadd,   efssub,   0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efsabs,   efsnabs,  0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsneg,   speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efsmul,   efsdiv,   0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpeq, efscfd,   0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfui,  efscfsi,  0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfuf,  efscfsf,  0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctui,  efsctsi,  0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuf,  efsctsf,  0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8349 8350 8351

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8352 8353 8354 8355
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
B
Blue Swirl 已提交
8356
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8357 8358
{
    if (unlikely(!ctx->spe_enabled)) {
8359
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8360 8361 8362
        return;
    }
#if defined(TARGET_PPC64)
8363
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8364
#else
8365 8366
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
A
aurel32 已提交
8367 8368
#endif
}
B
Blue Swirl 已提交
8369
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8370 8371
{
    if (unlikely(!ctx->spe_enabled)) {
8372
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8373 8374 8375
        return;
    }
#if defined(TARGET_PPC64)
8376
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8377
#else
8378 8379
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8380 8381
#endif
}
B
Blue Swirl 已提交
8382
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8383 8384
{
    if (unlikely(!ctx->spe_enabled)) {
8385
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8386 8387 8388
        return;
    }
#if defined(TARGET_PPC64)
8389
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8390
#else
8391 8392
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8393 8394 8395
#endif
}

8396
/* Conversion */
A
aurel32 已提交
8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411
GEN_SPEFPUOP_CONV_64_32(efdcfui);
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
GEN_SPEFPUOP_CONV_32_64(efdctui);
GEN_SPEFPUOP_CONV_32_64(efdctsi);
GEN_SPEFPUOP_CONV_32_64(efdctuf);
GEN_SPEFPUOP_CONV_32_64(efdctsf);
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
GEN_SPEFPUOP_CONV_64_32(efdcfs);
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
8412 8413

/* Comparison */
A
aurel32 已提交
8414 8415 8416 8417 8418 8419
GEN_SPEFPUOP_COMP_64(efdcmpgt);
GEN_SPEFPUOP_COMP_64(efdcmplt);
GEN_SPEFPUOP_COMP_64(efdcmpeq);
GEN_SPEFPUOP_COMP_64(efdtstgt);
GEN_SPEFPUOP_COMP_64(efdtstlt);
GEN_SPEFPUOP_COMP_64(efdtsteq);
8420 8421

/* Opcodes definitions */
8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437
GEN_SPE(efdadd,    efdsub,    0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuid,  efdcfsid,  0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdabs,    efdnabs,   0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdneg,    speundef,  0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdmul,    efddiv,    0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpgt,  efdcmplt,  0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpeq,  efdcfs,    0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfui,   efdcfsi,   0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuf,   efdcfsf,   0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctui,   efdctsi,   0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuf,   efdctsf,   0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuiz,  speundef,  0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdctsiz,  speundef,  0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdtstgt,  efdtstlt,  0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtsteq,  speundef,  0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8438

A
Anthony Liguori 已提交
8439
static opcode_t opcodes[] = {
8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
#if defined(TARGET_PPC64)
GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
8471
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8472
#if defined(TARGET_PPC64)
8473
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
#if defined(TARGET_PPC64)
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
#if defined(TARGET_PPC64)
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
8515
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8516 8517
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8518
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
#if defined(TARGET_PPC64)
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
#endif
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
#if defined(TARGET_PPC64)
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
#if defined(TARGET_PPC64)
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
#endif
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
A
Alexander Graf 已提交
8556
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
#if defined(TARGET_PPC64)
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B),
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B),
8573 8574 8575
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655
#endif
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
#if defined(TARGET_PPC64)
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
#endif
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
A
Alexander Graf 已提交
8656
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8657 8658 8659 8660 8661 8662 8663 8664
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
A
Alexander Graf 已提交
8665 8666 8667 8668 8669 8670 8671 8672
GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8673 8674
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8675 8676
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8677 8678
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8679
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8680
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8681
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8682 8683
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8684
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8685 8686
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),

#undef GEN_INT_ARITH_ADD
#undef GEN_INT_ARITH_ADD_CONST
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
#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),
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)

#undef GEN_INT_ARITH_DIVW
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),

#if defined(TARGET_PPC64)
#undef GEN_INT_ARITH_DIVD
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),

#undef GEN_INT_ARITH_MUL_HELPER
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
#endif

#undef GEN_INT_ARITH_SUBF
#undef GEN_INT_ARITH_SUBF_CONST
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
#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),
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)

#undef GEN_LOGICAL1
#undef GEN_LOGICAL2
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
#if defined(TARGET_PPC64)
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
#endif

#if defined(TARGET_PPC64)
#undef GEN_PPC64_R2
#undef GEN_PPC64_R4
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
             PPC_64B),                                                        \
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B),                                                        \
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
             PPC_64B)
GEN_PPC64_R4(rldicl, 0x1E, 0x00),
GEN_PPC64_R4(rldicr, 0x1E, 0x02),
GEN_PPC64_R4(rldic, 0x1E, 0x04),
GEN_PPC64_R2(rldcl, 0x1E, 0x08),
GEN_PPC64_R2(rldcr, 0x1E, 0x09),
GEN_PPC64_R4(rldimi, 0x1E, 0x06),
#endif

#undef _GEN_FLOAT_ACB
#undef GEN_FLOAT_ACB
#undef _GEN_FLOAT_AB
#undef GEN_FLOAT_AB
#undef _GEN_FLOAT_AC
#undef GEN_FLOAT_AC
#undef GEN_FLOAT_B
#undef GEN_FLOAT_BS
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
#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)
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
#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)
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
#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)
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)

GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
#if defined(TARGET_PPC64)
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
#endif
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),

#undef GEN_LD
#undef GEN_LDU
#undef GEN_LDUX
8859
#undef GEN_LDX_E
8860 8861 8862 8863 8864 8865 8866
#undef GEN_LDS
#define GEN_LD(name, ldop, opc, type)                                         \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_LDU(name, ldop, opc, type)                                        \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8867 8868
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883
#define GEN_LDS(name, ldop, op, type)                                         \
GEN_LD(name, ldop, op | 0x20, type)                                           \
GEN_LDU(name, ldop, op | 0x21, type)                                          \
GEN_LDUX(name, ldop, 0x17, op | 0x01, type)                                   \
GEN_LDX(name, ldop, 0x17, op | 0x00, type)

GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
#if defined(TARGET_PPC64)
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
8884
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
8885 8886 8887 8888 8889 8890 8891
#endif
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)

#undef GEN_ST
#undef GEN_STU
#undef GEN_STUX
8892
#undef GEN_STX_E
8893 8894 8895 8896 8897 8898 8899
#undef GEN_STS
#define GEN_ST(name, stop, opc, type)                                         \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_STU(name, stop, opc, type)                                        \
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8900 8901
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913
#define GEN_STS(name, stop, op, type)                                         \
GEN_ST(name, stop, op | 0x20, type)                                           \
GEN_STU(name, stop, op | 0x21, type)                                          \
GEN_STUX(name, stop, 0x17, op | 0x01, type)                                   \
GEN_STX(name, stop, 0x17, op | 0x00, type)

GEN_STS(stb, st8, 0x06, PPC_INTEGER)
GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
GEN_STS(stw, st32, 0x04, PPC_INTEGER)
#if defined(TARGET_PPC64)
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
8914
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182
#endif
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)

#undef GEN_LDF
#undef GEN_LDUF
#undef GEN_LDUXF
#undef GEN_LDXF
#undef GEN_LDFS
#define GEN_LDF(name, ldop, opc, type)                                        \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_LDUF(name, ldop, opc, type)                                       \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_LDUXF(name, ldop, opc, type)                                      \
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
#define GEN_LDFS(name, ldop, op, type)                                        \
GEN_LDF(name, ldop, op | 0x20, type)                                          \
GEN_LDUF(name, ldop, op | 0x21, type)                                         \
GEN_LDUXF(name, ldop, op | 0x01, type)                                        \
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)

GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)

#undef GEN_STF
#undef GEN_STUF
#undef GEN_STUXF
#undef GEN_STXF
#undef GEN_STFS
#define GEN_STF(name, stop, opc, type)                                        \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_STUF(name, stop, opc, type)                                       \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_STUXF(name, stop, opc, type)                                      \
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
#define GEN_STFS(name, stop, op, type)                                        \
GEN_STF(name, stop, op | 0x20, type)                                          \
GEN_STUF(name, stop, op | 0x21, type)                                         \
GEN_STUXF(name, stop, op | 0x01, type)                                        \
GEN_STXF(name, stop, 0x17, op | 0x00, type)

GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)

#undef GEN_CRLOGIC
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),

#undef GEN_MAC_HANDLER
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),

#undef GEN_VR_LDX
#undef GEN_VR_STX
#undef GEN_VR_LVE
#undef GEN_VR_STVE
#define GEN_VR_LDX(name, opc2, opc3)                                          \
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
#define GEN_VR_STX(name, opc2, opc3)                                          \
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
#define GEN_VR_LVE(name, opc2, opc3)                                    \
    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
#define GEN_VR_STVE(name, opc2, opc3)                                   \
    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
GEN_VR_LDX(lvx, 0x07, 0x03),
GEN_VR_LDX(lvxl, 0x07, 0x0B),
GEN_VR_LVE(bx, 0x07, 0x00),
GEN_VR_LVE(hx, 0x07, 0x01),
GEN_VR_LVE(wx, 0x07, 0x02),
GEN_VR_STX(svx, 0x07, 0x07),
GEN_VR_STX(svxl, 0x07, 0x0F),
GEN_VR_STVE(bx, 0x07, 0x04),
GEN_VR_STVE(hx, 0x07, 0x05),
GEN_VR_STVE(wx, 0x07, 0x06),

#undef GEN_VX_LOGICAL
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),

#undef GEN_VXFORM
#define GEN_VXFORM(name, opc2, opc3)                                    \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
GEN_VXFORM(vaddubm, 0, 0),
GEN_VXFORM(vadduhm, 0, 1),
GEN_VXFORM(vadduwm, 0, 2),
GEN_VXFORM(vsububm, 0, 16),
GEN_VXFORM(vsubuhm, 0, 17),
GEN_VXFORM(vsubuwm, 0, 18),
GEN_VXFORM(vmaxub, 1, 0),
GEN_VXFORM(vmaxuh, 1, 1),
GEN_VXFORM(vmaxuw, 1, 2),
GEN_VXFORM(vmaxsb, 1, 4),
GEN_VXFORM(vmaxsh, 1, 5),
GEN_VXFORM(vmaxsw, 1, 6),
GEN_VXFORM(vminub, 1, 8),
GEN_VXFORM(vminuh, 1, 9),
GEN_VXFORM(vminuw, 1, 10),
GEN_VXFORM(vminsb, 1, 12),
GEN_VXFORM(vminsh, 1, 13),
GEN_VXFORM(vminsw, 1, 14),
GEN_VXFORM(vavgub, 1, 16),
GEN_VXFORM(vavguh, 1, 17),
GEN_VXFORM(vavguw, 1, 18),
GEN_VXFORM(vavgsb, 1, 20),
GEN_VXFORM(vavgsh, 1, 21),
GEN_VXFORM(vavgsw, 1, 22),
GEN_VXFORM(vmrghb, 6, 0),
GEN_VXFORM(vmrghh, 6, 1),
GEN_VXFORM(vmrghw, 6, 2),
GEN_VXFORM(vmrglb, 6, 4),
GEN_VXFORM(vmrglh, 6, 5),
GEN_VXFORM(vmrglw, 6, 6),
GEN_VXFORM(vmuloub, 4, 0),
GEN_VXFORM(vmulouh, 4, 1),
GEN_VXFORM(vmulosb, 4, 4),
GEN_VXFORM(vmulosh, 4, 5),
GEN_VXFORM(vmuleub, 4, 8),
GEN_VXFORM(vmuleuh, 4, 9),
GEN_VXFORM(vmulesb, 4, 12),
GEN_VXFORM(vmulesh, 4, 13),
GEN_VXFORM(vslb, 2, 4),
GEN_VXFORM(vslh, 2, 5),
GEN_VXFORM(vslw, 2, 6),
GEN_VXFORM(vsrb, 2, 8),
GEN_VXFORM(vsrh, 2, 9),
GEN_VXFORM(vsrw, 2, 10),
GEN_VXFORM(vsrab, 2, 12),
GEN_VXFORM(vsrah, 2, 13),
GEN_VXFORM(vsraw, 2, 14),
GEN_VXFORM(vslo, 6, 16),
GEN_VXFORM(vsro, 6, 17),
GEN_VXFORM(vaddcuw, 0, 6),
GEN_VXFORM(vsubcuw, 0, 22),
GEN_VXFORM(vaddubs, 0, 8),
GEN_VXFORM(vadduhs, 0, 9),
GEN_VXFORM(vadduws, 0, 10),
GEN_VXFORM(vaddsbs, 0, 12),
GEN_VXFORM(vaddshs, 0, 13),
GEN_VXFORM(vaddsws, 0, 14),
GEN_VXFORM(vsububs, 0, 24),
GEN_VXFORM(vsubuhs, 0, 25),
GEN_VXFORM(vsubuws, 0, 26),
GEN_VXFORM(vsubsbs, 0, 28),
GEN_VXFORM(vsubshs, 0, 29),
GEN_VXFORM(vsubsws, 0, 30),
GEN_VXFORM(vrlb, 2, 0),
GEN_VXFORM(vrlh, 2, 1),
GEN_VXFORM(vrlw, 2, 2),
GEN_VXFORM(vsl, 2, 7),
GEN_VXFORM(vsr, 2, 11),
GEN_VXFORM(vpkuhum, 7, 0),
GEN_VXFORM(vpkuwum, 7, 1),
GEN_VXFORM(vpkuhus, 7, 2),
GEN_VXFORM(vpkuwus, 7, 3),
GEN_VXFORM(vpkshus, 7, 4),
GEN_VXFORM(vpkswus, 7, 5),
GEN_VXFORM(vpkshss, 7, 6),
GEN_VXFORM(vpkswss, 7, 7),
GEN_VXFORM(vpkpx, 7, 12),
GEN_VXFORM(vsum4ubs, 4, 24),
GEN_VXFORM(vsum4sbs, 4, 28),
GEN_VXFORM(vsum4shs, 4, 25),
GEN_VXFORM(vsum2sws, 4, 26),
GEN_VXFORM(vsumsws, 4, 30),
GEN_VXFORM(vaddfp, 5, 0),
GEN_VXFORM(vsubfp, 5, 1),
GEN_VXFORM(vmaxfp, 5, 16),
GEN_VXFORM(vminfp, 5, 17),

#undef GEN_VXRFORM1
#undef GEN_VXRFORM
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
#define GEN_VXRFORM(name, opc2, opc3)                                \
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
GEN_VXRFORM(vcmpequb, 3, 0)
GEN_VXRFORM(vcmpequh, 3, 1)
GEN_VXRFORM(vcmpequw, 3, 2)
GEN_VXRFORM(vcmpgtsb, 3, 12)
GEN_VXRFORM(vcmpgtsh, 3, 13)
GEN_VXRFORM(vcmpgtsw, 3, 14)
GEN_VXRFORM(vcmpgtub, 3, 8)
GEN_VXRFORM(vcmpgtuh, 3, 9)
GEN_VXRFORM(vcmpgtuw, 3, 10)
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)

#undef GEN_VXFORM_SIMM
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
GEN_VXFORM_SIMM(vspltisb, 6, 12),
GEN_VXFORM_SIMM(vspltish, 6, 13),
GEN_VXFORM_SIMM(vspltisw, 6, 14),

#undef GEN_VXFORM_NOA
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
GEN_VXFORM_NOA(vupkhsb, 7, 8),
GEN_VXFORM_NOA(vupkhsh, 7, 9),
GEN_VXFORM_NOA(vupklsb, 7, 10),
GEN_VXFORM_NOA(vupklsh, 7, 11),
GEN_VXFORM_NOA(vupkhpx, 7, 13),
GEN_VXFORM_NOA(vupklpx, 7, 15),
GEN_VXFORM_NOA(vrefp, 5, 4),
GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
9183
GEN_VXFORM_NOA(vexptefp, 5, 6),
9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211
GEN_VXFORM_NOA(vlogefp, 5, 7),
GEN_VXFORM_NOA(vrfim, 5, 8),
GEN_VXFORM_NOA(vrfin, 5, 9),
GEN_VXFORM_NOA(vrfip, 5, 10),
GEN_VXFORM_NOA(vrfiz, 5, 11),

#undef GEN_VXFORM_UIMM
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
GEN_VXFORM_UIMM(vspltb, 6, 8),
GEN_VXFORM_UIMM(vsplth, 6, 9),
GEN_VXFORM_UIMM(vspltw, 6, 10),
GEN_VXFORM_UIMM(vcfux, 5, 12),
GEN_VXFORM_UIMM(vcfsx, 5, 13),
GEN_VXFORM_UIMM(vctuxs, 5, 14),
GEN_VXFORM_UIMM(vctsxs, 5, 15),

#undef GEN_VAFORM_PAIRED
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
GEN_VAFORM_PAIRED(vsel, vperm, 21),
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),

#undef GEN_SPE
9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
    GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),

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

GEN_SPE(efsadd,      efssub,      0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
GEN_SPE(efsabs,      efsnabs,     0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
GEN_SPE(efsneg,      speundef,    0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
GEN_SPE(efsmul,      efsdiv,      0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
GEN_SPE(efscmpgt,    efscmplt,    0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
GEN_SPE(efscmpeq,    efscfd,      0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
GEN_SPE(efscfui,     efscfsi,     0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
GEN_SPE(efscfuf,     efscfsf,     0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
GEN_SPE(efsctui,     efsctsi,     0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
GEN_SPE(efsctuf,     efsctsf,     0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
GEN_SPE(efsctuiz,    speundef,    0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
GEN_SPE(efsctsiz,    speundef,    0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
GEN_SPE(efststgt,    efststlt,    0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
GEN_SPE(efststeq,    speundef,    0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),

GEN_SPE(efdadd,      efdsub,      0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuid,    efdcfsid,    0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdabs,      efdnabs,     0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
GEN_SPE(efdneg,      speundef,    0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdmul,      efddiv,      0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuidz,   efdctsidz,   0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpgt,    efdcmplt,    0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfui,     efdcfsi,     0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuf,     efdcfsf,     0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctui,     efdctsi,     0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuf,     efdctsf,     0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuiz,    speundef,    0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdctsiz,    speundef,    0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdtstgt,    efdtstlt,    0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdtsteq,    speundef,    0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314

#undef GEN_SPEOP_LDST
#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
GEN_SPEOP_LDST(evldd, 0x00, 3),
GEN_SPEOP_LDST(evldw, 0x01, 3),
GEN_SPEOP_LDST(evldh, 0x02, 3),
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
GEN_SPEOP_LDST(evlwhe, 0x08, 2),
GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),

GEN_SPEOP_LDST(evstdd, 0x10, 3),
GEN_SPEOP_LDST(evstdw, 0x11, 3),
GEN_SPEOP_LDST(evstdh, 0x12, 3),
GEN_SPEOP_LDST(evstwhe, 0x18, 2),
GEN_SPEOP_LDST(evstwho, 0x1A, 2),
GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
};

9315
#include "helper_regs.h"
A
Andreas Färber 已提交
9316
#include "translate_init.c"
B
bellard 已提交
9317

9318
/*****************************************************************************/
9319
/* Misc PowerPC helpers */
9320
void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
9321
                     int flags)
B
bellard 已提交
9322
{
9323 9324 9325
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9326 9327
    int i;

9328 9329
    cpu_synchronize_state(env);

9330
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9331
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9332
                env->nip, env->lr, env->ctr, cpu_read_xer(env));
9333 9334 9335
    cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx "  HF "
                TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
                env->hflags, env->mmu_idx);
9336
#if !defined(NO_TIMER_DUMP)
9337
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9338
#if !defined(CONFIG_USER_ONLY)
9339
                " DECR %08" PRIu32
9340 9341
#endif
                "\n",
J
j_mayer 已提交
9342
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9343 9344 9345 9346
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9347
#endif
9348
    for (i = 0; i < 32; i++) {
9349 9350
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9351
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9352
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9353
            cpu_fprintf(f, "\n");
9354
    }
9355
    cpu_fprintf(f, "CR ");
9356
    for (i = 0; i < 8; i++)
B
bellard 已提交
9357 9358
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9359 9360 9361 9362 9363 9364 9365 9366
    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 已提交
9367
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9368
    }
9369 9370
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9371 9372 9373
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9374
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9375
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9376
            cpu_fprintf(f, "\n");
B
bellard 已提交
9377
    }
9378
    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
9379
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427
    cpu_fprintf(f, " SRR0 " TARGET_FMT_lx "  SRR1 " TARGET_FMT_lx
                   "    PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
                env->spr[SPR_SRR0], env->spr[SPR_SRR1],
                env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);

    cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
                   "  SPRG2 " TARGET_FMT_lx "  SPRG3 " TARGET_FMT_lx "\n",
                env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
                env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);

    cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
                   "  SPRG6 " TARGET_FMT_lx "  SPRG7 " TARGET_FMT_lx "\n",
                env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
                env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);

    if (env->excp_model == POWERPC_EXCP_BOOKE) {
        cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
                       " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
                    env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);

        cpu_fprintf(f, "  TCR " TARGET_FMT_lx "   TSR " TARGET_FMT_lx
                       "    ESR " TARGET_FMT_lx "   DEAR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
                    env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);

        cpu_fprintf(f, "  PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
                       "   IVPR " TARGET_FMT_lx "   EPCR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
                    env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);

        cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
                       "    EPR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
                    env->spr[SPR_BOOKE_EPR]);

        /* FSL-specific */
        cpu_fprintf(f, " MCAR " TARGET_FMT_lx "  PID1 " TARGET_FMT_lx
                       "   PID2 " TARGET_FMT_lx "    SVR " TARGET_FMT_lx "\n",
                    env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
                    env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);

        /*
         * IVORs are left out as they are large and do not change often --
         * they can be read with "p $ivor0", "p $ivor1", etc.
         */
    }

D
David Gibson 已提交
9428 9429 9430 9431 9432 9433
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9434 9435 9436 9437 9438 9439 9440 9441 9442 9443
    switch (env->mmu_model) {
    case POWERPC_MMU_32B:
    case POWERPC_MMU_601:
    case POWERPC_MMU_SOFT_6xx:
    case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
    case POWERPC_MMU_64B:
#endif
        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
        break;
A
Alexander Graf 已提交
9444
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462
        cpu_fprintf(f, " MAS0 " TARGET_FMT_lx "  MAS1 " TARGET_FMT_lx
                       "   MAS2 " TARGET_FMT_lx "   MAS3 " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
                    env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);

        cpu_fprintf(f, " MAS4 " TARGET_FMT_lx "  MAS6 " TARGET_FMT_lx
                       "   MAS7 " TARGET_FMT_lx "    PID " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
                    env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);

        cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
                       " TLB1CFG " TARGET_FMT_lx "\n",
                    env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
                    env->spr[SPR_BOOKE_TLB1CFG]);
        break;
    default:
        break;
    }
9463
#endif
B
bellard 已提交
9464

9465 9466
#undef RGPL
#undef RFPL
B
bellard 已提交
9467 9468
}

9469
void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
9470 9471 9472
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9473
    opc_handler_t **t1, **t2, **t3, *handler;
9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489
    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: "
B
Blue Swirl 已提交
9490
                                    "%016" PRIx64 " %" PRId64 "\n",
9491 9492 9493 9494 9495 9496 9497 9498
                                    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: "
B
Blue Swirl 已提交
9499
                                "%016" PRIx64 " %" PRId64 "\n",
9500 9501 9502 9503 9504 9505 9506
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9507 9508
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9509 9510 9511 9512 9513 9514 9515
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9516
/*****************************************************************************/
9517
static inline void gen_intermediate_code_internal(CPUPPCState *env,
B
Blue Swirl 已提交
9518 9519
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9520
{
9521
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9522
    opc_handler_t **table, *handler;
B
bellard 已提交
9523
    target_ulong pc_start;
B
bellard 已提交
9524
    uint16_t *gen_opc_end;
9525
    CPUBreakpoint *bp;
B
bellard 已提交
9526
    int j, lj = -1;
P
pbrook 已提交
9527 9528
    int num_insns;
    int max_insns;
B
bellard 已提交
9529 9530

    pc_start = tb->pc;
9531
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9532
    ctx.nip = pc_start;
B
bellard 已提交
9533
    ctx.tb = tb;
9534
    ctx.exception = POWERPC_EXCP_NONE;
9535
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9536 9537 9538
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9539
#if defined(TARGET_PPC64)
A
Alexander Graf 已提交
9540
    ctx.sf_mode = msr_is_64bit(env, env->msr);
D
David Gibson 已提交
9541
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9542
#endif
B
bellard 已提交
9543
    ctx.fpu_enabled = msr_fp;
9544
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9545 9546 9547
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9548 9549 9550 9551
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9552
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9553
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9554
    else
9555
        ctx.singlestep_enabled = 0;
9556
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9557 9558 9559
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9560
#if defined (DO_SINGLE_STEP) && 0
9561 9562 9563
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9564 9565 9566 9567 9568
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

9569
    gen_tb_start();
9570
    /* Set env in case of segfault during code fetch */
9571 9572
    while (ctx.exception == POWERPC_EXCP_NONE
            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9573 9574
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9575
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9576
                    gen_debug_exception(ctxp);
9577 9578 9579 9580
                    break;
                }
            }
        }
9581
        if (unlikely(search_pc)) {
9582
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
B
bellard 已提交
9583 9584 9585
            if (lj < j) {
                lj++;
                while (lj < j)
9586
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
9587
            }
9588
            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
9589
            tcg_ctx.gen_opc_instr_start[lj] = 1;
9590
            tcg_ctx.gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9591
        }
9592
        LOG_DISAS("----------------\n");
9593
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9594
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9595 9596
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9597
        if (unlikely(ctx.le_mode)) {
9598
            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
9599
        } else {
9600
            ctx.opcode = cpu_ldl_code(env, ctx.nip);
9601
        }
9602
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9603
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9604
                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
9605
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9606
            tcg_gen_debug_insn_start(ctx.nip);
9607
        }
B
bellard 已提交
9608
        ctx.nip += 4;
9609
        table = env->opcodes;
P
pbrook 已提交
9610
        num_insns++;
B
bellard 已提交
9611 9612 9613 9614 9615 9616 9617 9618 9619 9620
        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 ? */
9621
        if (unlikely(handler->handler == &gen_invalid)) {
9622 9623
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9624 9625 9626
                         "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
                         opc1(ctx.opcode), opc2(ctx.opcode),
                         opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
9627
            }
9628
        } else {
9629 9630 9631 9632 9633 9634 9635 9636 9637
            uint32_t inval;

            if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
                inval = handler->inval2;
            } else {
                inval = handler->inval1;
            }

            if (unlikely((ctx.opcode & inval) != 0)) {
9638 9639
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9640
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9641
                             ctx.opcode & inval, opc1(ctx.opcode),
9642 9643
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9644
                }
A
aurel32 已提交
9645
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9646
                break;
B
bellard 已提交
9647 9648
            }
        }
B
bellard 已提交
9649
        (*(handler->handler))(&ctx);
9650 9651 9652
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9653
        /* Check trace mode exceptions */
9654 9655 9656 9657 9658
        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)) {
A
aurel32 已提交
9659
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9660
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9661
                            (env->singlestep_enabled) ||
9662
                            singlestep ||
P
pbrook 已提交
9663
                            num_insns >= max_insns)) {
9664 9665 9666
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9667
            break;
9668
        }
9669
    }
P
pbrook 已提交
9670 9671
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9672
    if (ctx.exception == POWERPC_EXCP_NONE) {
9673
        gen_goto_tb(&ctx, 0, ctx.nip);
9674
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9675
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9676
            gen_debug_exception(ctxp);
9677
        }
9678
        /* Generate the return instruction */
B
bellard 已提交
9679
        tcg_gen_exit_tb(0);
9680
    }
9681
    gen_tb_end(tb, num_insns);
9682
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
9683
    if (unlikely(search_pc)) {
9684
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9685 9686
        lj++;
        while (lj <= j)
9687
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
9688
    } else {
B
bellard 已提交
9689
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9690
        tb->icount = num_insns;
9691
    }
9692
#if defined(DEBUG_DISAS)
9693
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9694
        int flags;
9695
        flags = env->bfd_mach;
A
aurel32 已提交
9696
        flags |= ctx.le_mode << 16;
9697
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
9698
        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
9699
        qemu_log("\n");
9700
    }
B
bellard 已提交
9701 9702 9703
#endif
}

9704
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9705
{
9706
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9707 9708
}

9709
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9710
{
9711
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9712
}
A
aurel32 已提交
9713

9714
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9715
{
9716
    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
9717
}