translate.c 356.6 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
    if (rA(ctx->opcode) == 0) {
2335 2336 2337
        if (NARROW_MODE(ctx)) {
            simm = (uint32_t)simm;
        }
2338
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2339
    } else if (likely(simm != 0)) {
2340
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2341
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2342 2343 2344
            tcg_gen_ext32u_tl(EA, EA);
        }
    } else {
2345
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2346
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2347 2348 2349
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        }
A
aurel32 已提交
2350
    }
2351 2352
}

B
Blue Swirl 已提交
2353
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2354
{
A
aurel32 已提交
2355
    if (rA(ctx->opcode) == 0) {
2356
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2357
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2358 2359 2360
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        }
A
aurel32 已提交
2361
    } else {
2362
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2363
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2364 2365 2366
            tcg_gen_ext32u_tl(EA, EA);
        }
    }
2367 2368
}

B
Blue Swirl 已提交
2369
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2370
{
A
aurel32 已提交
2371
    if (rA(ctx->opcode) == 0) {
2372
        tcg_gen_movi_tl(EA, 0);
2373 2374
    } else if (NARROW_MODE(ctx)) {
        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2375
    } else {
2376
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2377 2378 2379
    }
}

B
Blue Swirl 已提交
2380 2381
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2382 2383
{
    tcg_gen_addi_tl(ret, arg1, val);
2384
    if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2385 2386
        tcg_gen_ext32u_tl(ret, ret);
    }
2387 2388
}

B
Blue Swirl 已提交
2389
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399
{
    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);
2400
    gen_helper_raise_exception_err(cpu_env, t1, t2);
2401 2402 2403 2404 2405 2406
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2407
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2408
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2409 2410 2411 2412
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2413
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2414 2415 2416 2417
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2418
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2419 2420 2421
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2422
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2423
    }
A
aurel32 已提交
2424 2425
}

B
Blue Swirl 已提交
2426
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2427
{
A
aurel32 已提交
2428 2429
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2430
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2431 2432 2433 2434
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2435 2436
}

B
Blue Swirl 已提交
2437
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2438
{
A
aurel32 已提交
2439 2440
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2441
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2442
    }
A
aurel32 已提交
2443 2444
}

A
aurel32 已提交
2445
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2446
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2447
{
B
blueswir1 已提交
2448
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2449
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2450 2451
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2452
    } else
A
aurel32 已提交
2453
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2454
}
A
aurel32 已提交
2455
#endif
A
aurel32 已提交
2456

B
Blue Swirl 已提交
2457
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2458
{
A
aurel32 已提交
2459 2460
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2461
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2462
    }
A
aurel32 已提交
2463 2464
}

B
Blue Swirl 已提交
2465
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2466
{
A
aurel32 已提交
2467
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2468 2469
}

B
Blue Swirl 已提交
2470
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2471
{
A
aurel32 已提交
2472 2473 2474
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2475
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2476 2477 2478 2479 2480
        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 已提交
2481 2482
}

B
Blue Swirl 已提交
2483
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2484
{
A
aurel32 已提交
2485
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2486 2487 2488
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2489 2490 2491 2492 2493
        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 已提交
2494 2495
}

B
Blue Swirl 已提交
2496
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2497
{
A
aurel32 已提交
2498
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2499
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2500
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2501
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2502
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2503
    } else
A
aurel32 已提交
2504
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2505 2506
}

2507
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2508
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2509
{                                                                             \
A
aurel32 已提交
2510 2511 2512 2513 2514
    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 已提交
2515
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2516 2517
}

2518
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2519
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2520
{                                                                             \
A
aurel32 已提交
2521
    TCGv EA;                                                                  \
2522 2523
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2524
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2525
        return;                                                               \
2526
    }                                                                         \
A
aurel32 已提交
2527
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2528
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2529
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2530
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2531
    else                                                                      \
A
aurel32 已提交
2532 2533
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2534 2535
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2536 2537
}

2538
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2539
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2540
{                                                                             \
A
aurel32 已提交
2541
    TCGv EA;                                                                  \
2542 2543
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2544
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2545
        return;                                                               \
2546
    }                                                                         \
A
aurel32 已提交
2547
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2548
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2549 2550
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2551 2552
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2553 2554
}

2555
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
B
Blue Swirl 已提交
2556
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2557
{                                                                             \
A
aurel32 已提交
2558 2559 2560 2561 2562
    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 已提交
2563
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2564
}
2565 2566
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2567

2568 2569 2570 2571 2572
#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 已提交
2573 2574

/* lbz lbzu lbzux lbzx */
2575
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2576
/* lha lhau lhaux lhax */
2577
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2578
/* lhz lhzu lhzux lhzx */
2579
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2580
/* lwz lwzu lwzux lwzx */
2581
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2582 2583
#if defined(TARGET_PPC64)
/* lwaux */
2584
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2585
/* lwax */
2586
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2587
/* ldux */
2588
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2589
/* ldx */
2590
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2591 2592

static void gen_ld(DisasContext *ctx)
2593
{
A
aurel32 已提交
2594
    TCGv EA;
2595 2596 2597
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2598
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2599 2600 2601
            return;
        }
    }
A
aurel32 已提交
2602
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2603
    EA = tcg_temp_new();
A
aurel32 已提交
2604
    gen_addr_imm_index(ctx, EA, 0x03);
2605 2606
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2607
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2608 2609
    } else {
        /* ld - ldu */
A
aurel32 已提交
2610
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2611 2612
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2613 2614
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2615
}
B
Blue Swirl 已提交
2616

2617
/* lq */
B
Blue Swirl 已提交
2618
static void gen_lq(DisasContext *ctx)
2619 2620
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2621
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2622 2623
#else
    int ra, rd;
A
aurel32 已提交
2624
    TCGv EA;
2625 2626

    /* Restore CPU state */
A
aurel32 已提交
2627
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2628
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2629 2630 2631 2632 2633
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2634
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2635 2636
        return;
    }
A
aurel32 已提交
2637
    if (unlikely(ctx->le_mode)) {
2638
        /* Little-endian mode is not handled */
A
aurel32 已提交
2639
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2640 2641
        return;
    }
A
aurel32 已提交
2642
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2643
    EA = tcg_temp_new();
A
aurel32 已提交
2644 2645 2646 2647
    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 已提交
2648
    tcg_temp_free(EA);
2649 2650
#endif
}
2651
#endif
B
bellard 已提交
2652 2653

/***                              Integer store                            ***/
2654
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2655
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2656
{                                                                             \
A
aurel32 已提交
2657 2658 2659 2660 2661
    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 已提交
2662
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2663 2664
}

2665
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2666
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2667
{                                                                             \
A
aurel32 已提交
2668
    TCGv EA;                                                                  \
2669
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2670
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2671
        return;                                                               \
2672
    }                                                                         \
A
aurel32 已提交
2673
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2674
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2675
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2676
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2677
    else                                                                      \
A
aurel32 已提交
2678 2679
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2680 2681
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2682 2683
}

2684
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2685
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2686
{                                                                             \
A
aurel32 已提交
2687
    TCGv EA;                                                                  \
2688
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2689
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2690
        return;                                                               \
2691
    }                                                                         \
A
aurel32 已提交
2692
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2693
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2694 2695
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2696 2697
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2698 2699
}

2700 2701
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2702
{                                                                             \
A
aurel32 已提交
2703 2704 2705 2706 2707
    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 已提交
2708
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2709
}
2710 2711
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2712

2713 2714 2715 2716 2717
#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 已提交
2718 2719

/* stb stbu stbux stbx */
2720
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2721
/* sth sthu sthux sthx */
2722
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2723
/* stw stwu stwux stwx */
2724
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2725
#if defined(TARGET_PPC64)
2726 2727
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2728 2729

static void gen_std(DisasContext *ctx)
2730
{
2731
    int rs;
A
aurel32 已提交
2732
    TCGv EA;
2733 2734 2735 2736

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2737
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2738 2739
#else
        /* stq */
A
aurel32 已提交
2740
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2741
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2742 2743 2744
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2745
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2746 2747
            return;
        }
A
aurel32 已提交
2748
        if (unlikely(ctx->le_mode)) {
2749
            /* Little-endian mode is not handled */
A
aurel32 已提交
2750
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2751 2752
            return;
        }
A
aurel32 已提交
2753
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2754
        EA = tcg_temp_new();
A
aurel32 已提交
2755 2756 2757 2758
        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 已提交
2759
        tcg_temp_free(EA);
2760 2761 2762 2763 2764
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2765
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2766 2767 2768
                return;
            }
        }
A
aurel32 已提交
2769
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2770
        EA = tcg_temp_new();
A
aurel32 已提交
2771 2772
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2773
        if (Rc(ctx->opcode))
A
aurel32 已提交
2774 2775
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2776 2777 2778
    }
}
#endif
B
bellard 已提交
2779 2780
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2781
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2782
{
A
aurel32 已提交
2783 2784
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2785
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2786
    }
A
aurel32 已提交
2787
}
2788
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2789

B
bellard 已提交
2790
/* lwbrx */
2791
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2792
{
A
aurel32 已提交
2793 2794
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2795
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2796
    }
A
aurel32 已提交
2797
}
2798
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2799

2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811
#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 已提交
2812
/* sthbrx */
2813
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2814
{
A
aurel32 已提交
2815 2816 2817
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2818
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2819 2820 2821 2822 2823
        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 已提交
2824
}
2825
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2826

B
bellard 已提交
2827
/* stwbrx */
2828
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2829
{
A
aurel32 已提交
2830
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2831 2832 2833
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2834 2835 2836 2837 2838
        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 已提交
2839
}
2840
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2841

2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857
#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 已提交
2858
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2859

2860
/* lmw */
B
Blue Swirl 已提交
2861
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2862
{
A
aurel32 已提交
2863 2864 2865
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2866
    /* NIP cannot be restored if the memory exception comes from an helper */
2867
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2868 2869 2870
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2871
    gen_helper_lmw(cpu_env, t0, t1);
2872 2873
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2874 2875 2876
}

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

/***                    Integer load and store strings                     ***/
2893

B
bellard 已提交
2894
/* lswi */
2895
/* PowerPC32 specification says we must generate an exception if
2896 2897 2898 2899
 * 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 已提交
2900
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
2901
{
2902 2903
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2904 2905
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2906
    int ra = rA(ctx->opcode);
B
bellard 已提交
2907 2908 2909 2910 2911
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2912 2913 2914
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
2915
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2916
        return;
B
bellard 已提交
2917
    }
A
aurel32 已提交
2918
    gen_set_access_type(ctx, ACCESS_INT);
2919
    /* NIP cannot be restored if the memory exception comes from an helper */
2920
    gen_update_nip(ctx, ctx->nip - 4);
2921
    t0 = tcg_temp_new();
A
aurel32 已提交
2922
    gen_addr_register(ctx, t0);
2923 2924
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
2925
    gen_helper_lsw(cpu_env, t0, t1, t2);
2926 2927 2928
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2929 2930 2931
}

/* lswx */
B
Blue Swirl 已提交
2932
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
2933
{
A
aurel32 已提交
2934 2935 2936
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
2937
    /* NIP cannot be restored if the memory exception comes from an helper */
2938
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2939 2940 2941 2942 2943
    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));
2944
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
2945 2946 2947 2948
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
2949 2950 2951
}

/* stswi */
B
Blue Swirl 已提交
2952
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
2953
{
A
aurel32 已提交
2954 2955
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2956
    int nb = NB(ctx->opcode);
A
aurel32 已提交
2957
    gen_set_access_type(ctx, ACCESS_INT);
2958
    /* NIP cannot be restored if the memory exception comes from an helper */
2959
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2960 2961
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
2962 2963
    if (nb == 0)
        nb = 32;
2964
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
2965
    t2 = tcg_const_i32(rS(ctx->opcode));
2966
    gen_helper_stsw(cpu_env, t0, t1, t2);
2967 2968 2969
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2970 2971 2972
}

/* stswx */
B
Blue Swirl 已提交
2973
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
2974
{
A
aurel32 已提交
2975 2976 2977
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
2978
    /* NIP cannot be restored if the memory exception comes from an helper */
2979
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2980 2981 2982
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
2983 2984
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
2985
    t2 = tcg_const_i32(rS(ctx->opcode));
2986
    gen_helper_stsw(cpu_env, t0, t1, t2);
2987 2988 2989
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2990 2991 2992 2993
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
2994
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
2995 2996 2997 2998
{
}

/* isync */
B
Blue Swirl 已提交
2999
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3000
{
A
aurel32 已提交
3001
    gen_stop_exception(ctx);
B
bellard 已提交
3002 3003
}

3004
/* lwarx */
B
Blue Swirl 已提交
3005
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3006
{
A
aurel32 已提交
3007
    TCGv t0;
3008
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3009 3010 3011
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3012
    gen_check_align(ctx, t0, 0x03);
3013
    gen_qemu_ld32u(ctx, gpr, t0);
3014
    tcg_gen_mov_tl(cpu_reserve, t0);
3015
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3016
    tcg_temp_free(t0);
B
bellard 已提交
3017 3018
}

3019 3020 3021 3022 3023 3024 3025
#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;

3026
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3027
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3028
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3029 3030 3031 3032 3033 3034 3035 3036
    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 已提交
3037
/* stwcx. */
B
Blue Swirl 已提交
3038
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3039
{
A
aurel32 已提交
3040 3041 3042 3043
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3044
    gen_check_align(ctx, t0, 0x03);
3045 3046 3047 3048 3049 3050
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
    {
        int l1;

3051
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3052 3053 3054 3055 3056 3057 3058 3059
        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
3060
    tcg_temp_free(t0);
B
bellard 已提交
3061 3062
}

J
j_mayer 已提交
3063 3064
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3065
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3066
{
A
aurel32 已提交
3067
    TCGv t0;
3068
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3069 3070 3071
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3072
    gen_check_align(ctx, t0, 0x07);
3073
    gen_qemu_ld64(ctx, gpr, t0);
3074
    tcg_gen_mov_tl(cpu_reserve, t0);
3075
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3076
    tcg_temp_free(t0);
J
j_mayer 已提交
3077 3078 3079
}

/* stdcx. */
B
Blue Swirl 已提交
3080
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3081
{
A
aurel32 已提交
3082 3083 3084 3085
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3086
    gen_check_align(ctx, t0, 0x07);
3087 3088 3089 3090 3091
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
#else
    {
        int l1;
3092
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3093 3094 3095 3096 3097 3098 3099 3100
        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
3101
    tcg_temp_free(t0);
J
j_mayer 已提交
3102 3103 3104
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3105
/* sync */
B
Blue Swirl 已提交
3106
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3107 3108 3109
{
}

3110
/* wait */
B
Blue Swirl 已提交
3111
static void gen_wait(DisasContext *ctx)
3112
{
3113
    TCGv_i32 t0 = tcg_temp_new_i32();
3114 3115
    tcg_gen_st_i32(t0, cpu_env,
                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3116
    tcg_temp_free_i32(t0);
3117
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3118
    gen_exception_err(ctx, EXCP_HLT, 1);
3119 3120
}

B
bellard 已提交
3121
/***                         Floating-point load                           ***/
3122
#define GEN_LDF(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
3123
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3124
{                                                                             \
3125
    TCGv EA;                                                                  \
3126
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3127
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3128 3129
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3130
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3131
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3132 3133
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3134
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3135 3136
}

3137
#define GEN_LDUF(name, ldop, opc, type)                                       \
B
Blue Swirl 已提交
3138
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3139
{                                                                             \
3140
    TCGv EA;                                                                  \
3141
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3142
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3143 3144
        return;                                                               \
    }                                                                         \
3145
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3146
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3147
        return;                                                               \
3148
    }                                                                         \
A
aurel32 已提交
3149
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3150
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3151 3152
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3153 3154
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3155 3156
}

3157
#define GEN_LDUXF(name, ldop, opc, type)                                      \
B
Blue Swirl 已提交
3158
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3159
{                                                                             \
3160
    TCGv EA;                                                                  \
3161
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3162
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3163 3164
        return;                                                               \
    }                                                                         \
3165
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3166
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3167
        return;                                                               \
3168
    }                                                                         \
A
aurel32 已提交
3169
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3170
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3171 3172
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3173 3174
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3175 3176
}

3177
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3178
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3179
{                                                                             \
3180
    TCGv EA;                                                                  \
3181
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3182
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3183 3184
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3185
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3186
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3187 3188
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3189
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3190 3191
}

3192 3193 3194 3195 3196 3197
#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 已提交
3198
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3199 3200 3201
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3202
    gen_qemu_ld32u(ctx, t0, arg2);
3203 3204
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
3205
    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3206 3207
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3208

3209 3210 3211 3212
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3213 3214

/***                         Floating-point store                          ***/
3215
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3216
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3217
{                                                                             \
3218
    TCGv EA;                                                                  \
3219
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3220
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3221 3222
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3223
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3224
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3225 3226
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3227
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3228 3229
}

3230
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3231
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3232
{                                                                             \
3233
    TCGv EA;                                                                  \
3234
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3235
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3236 3237
        return;                                                               \
    }                                                                         \
3238
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3239
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3240
        return;                                                               \
3241
    }                                                                         \
A
aurel32 已提交
3242
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3243
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3244 3245
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3246 3247
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3248 3249
}

3250
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3251
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3252
{                                                                             \
3253
    TCGv EA;                                                                  \
3254
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3255
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3256 3257
        return;                                                               \
    }                                                                         \
3258
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3259
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3260
        return;                                                               \
3261
    }                                                                         \
A
aurel32 已提交
3262
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3263
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3264 3265
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3266 3267
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3268 3269
}

3270
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3271
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3272
{                                                                             \
3273
    TCGv EA;                                                                  \
3274
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3275
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3276 3277
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3278
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3279
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3280 3281
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3282
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3283 3284
}

3285 3286 3287 3288 3289 3290
#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 已提交
3291
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3292 3293 3294
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
3295
    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3296 3297
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3298
    gen_qemu_st32(ctx, t1, arg2);
3299 3300
    tcg_temp_free(t1);
}
B
bellard 已提交
3301 3302

/* stfd stfdu stfdux stfdx */
3303
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3304
/* stfs stfsu stfsux stfsx */
3305
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3306 3307

/* Optional: */
B
Blue Swirl 已提交
3308
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3309 3310 3311
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3312
    gen_qemu_st32(ctx, t0, arg2);
3313 3314
    tcg_temp_free(t0);
}
B
bellard 已提交
3315
/* stfiwx */
3316
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3317

D
David Gibson 已提交
3318 3319 3320 3321 3322 3323 3324 3325
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 已提交
3326
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3327
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3328 3329 3330
{
    TranslationBlock *tb;
    tb = ctx->tb;
3331
    if (NARROW_MODE(ctx)) {
3332
        dest = (uint32_t) dest;
3333
    }
B
bellard 已提交
3334
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3335
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3336
        tcg_gen_goto_tb(n);
3337
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3338
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3339
    } else {
3340
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3341 3342
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3343
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3344 3345
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3346 3347
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3348
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3349 3350 3351
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3352
                gen_debug_exception(ctx);
3353 3354
            }
        }
B
bellard 已提交
3355
        tcg_gen_exit_tb(0);
3356
    }
B
bellard 已提交
3357 3358
}

B
Blue Swirl 已提交
3359
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3360
{
3361 3362 3363 3364
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_lr, nip);
3365 3366
}

B
bellard 已提交
3367
/* b ba bl bla */
B
Blue Swirl 已提交
3368
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3369
{
3370
    target_ulong li, target;
B
bellard 已提交
3371

3372
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3373
    /* sign extend LI */
3374 3375 3376
    li = LI(ctx->opcode);
    li = (li ^ 0x02000000) - 0x02000000;
    if (likely(AA(ctx->opcode) == 0)) {
B
bellard 已提交
3377
        target = ctx->nip + li - 4;
3378
    } else {
3379
        target = li;
3380 3381
    }
    if (LK(ctx->opcode)) {
3382
        gen_setlr(ctx, ctx->nip);
3383
    }
D
David Gibson 已提交
3384
    gen_update_cfar(ctx, ctx->nip);
3385
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3386 3387
}

3388 3389 3390 3391
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3392
static inline void gen_bcond(DisasContext *ctx, int type)
3393 3394
{
    uint32_t bo = BO(ctx->opcode);
3395
    int l1;
3396
    TCGv target;
3397

3398
    ctx->exception = POWERPC_EXCP_BRANCH;
3399
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3400
        target = tcg_temp_local_new();
3401 3402 3403 3404
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3405 3406
    } else {
        TCGV_UNUSED(target);
3407
    }
3408 3409
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3410 3411 3412
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3413
        TCGv temp = tcg_temp_new();
3414
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3415
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3416 3417 3418
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3419
        if (NARROW_MODE(ctx)) {
3420
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3421
        } else {
3422
            tcg_gen_mov_tl(temp, cpu_ctr);
3423
        }
3424 3425 3426 3427
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3428
        }
P
pbrook 已提交
3429
        tcg_temp_free(temp);
3430 3431 3432 3433 3434
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3435
        TCGv_i32 temp = tcg_temp_new_i32();
3436

3437
        if (bo & 0x8) {
3438 3439
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3440
        } else {
3441 3442
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3443
        }
P
pbrook 已提交
3444
        tcg_temp_free_i32(temp);
3445
    }
D
David Gibson 已提交
3446
    gen_update_cfar(ctx, ctx->nip);
3447
    if (type == BCOND_IM) {
3448 3449 3450 3451 3452 3453
        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 已提交
3454
        gen_set_label(l1);
3455
        gen_goto_tb(ctx, 1, ctx->nip);
3456
    } else {
3457
        if (NARROW_MODE(ctx)) {
3458
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3459
        } else {
3460
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3461
        }
3462 3463
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
3464
        gen_update_nip(ctx, ctx->nip);
B
bellard 已提交
3465
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3466
    }
3467 3468
}

B
Blue Swirl 已提交
3469
static void gen_bc(DisasContext *ctx)
3470
{
3471 3472 3473
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3474
static void gen_bcctr(DisasContext *ctx)
3475
{
3476 3477 3478
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3479
static void gen_bclr(DisasContext *ctx)
3480
{
3481 3482
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3483 3484

/***                      Condition register logical                       ***/
3485
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3486
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3487
{                                                                             \
3488 3489
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3490
    TCGv_i32 t0, t1;                                                          \
3491
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3492
    t0 = tcg_temp_new_i32();                                                  \
3493
    if (sh > 0)                                                               \
3494
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3495
    else if (sh < 0)                                                          \
3496
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3497
    else                                                                      \
3498
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3499
    t1 = tcg_temp_new_i32();                                                  \
3500 3501
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3502
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3503
    else if (sh < 0)                                                          \
3504
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3505
    else                                                                      \
3506 3507
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3508
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3509 3510 3511
    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 已提交
3512 3513
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3514 3515 3516
}

/* crand */
3517
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3518
/* crandc */
3519
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3520
/* creqv */
3521
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3522
/* crnand */
3523
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3524
/* crnor */
3525
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3526
/* cror */
3527
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3528
/* crorc */
3529
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3530
/* crxor */
3531
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3532

3533
/* mcrf */
B
Blue Swirl 已提交
3534
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3535
{
A
aurel32 已提交
3536
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3537 3538 3539
}

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

3541
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3542
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3543
{
3544
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3545
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3546 3547
#else
    /* Restore CPU state */
A
aurel32 已提交
3548
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3549
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3550
        return;
3551
    }
D
David Gibson 已提交
3552
    gen_update_cfar(ctx, ctx->nip);
3553
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3554
    gen_sync_exception(ctx);
3555
#endif
B
bellard 已提交
3556 3557
}

J
j_mayer 已提交
3558
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3559
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3560 3561
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3562
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3563 3564
#else
    /* Restore CPU state */
A
aurel32 已提交
3565
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3566
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3567 3568
        return;
    }
D
David Gibson 已提交
3569
    gen_update_cfar(ctx, ctx->nip);
3570
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3571
    gen_sync_exception(ctx);
J
j_mayer 已提交
3572 3573 3574
#endif
}

B
Blue Swirl 已提交
3575
static void gen_hrfid(DisasContext *ctx)
3576 3577
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3578
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3579 3580
#else
    /* Restore CPU state */
A
aurel32 已提交
3581
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3582
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3583 3584
        return;
    }
3585
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3586
    gen_sync_exception(ctx);
3587 3588 3589 3590
#endif
}
#endif

B
bellard 已提交
3591
/* sc */
3592 3593 3594 3595 3596
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3597
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3598
{
3599 3600 3601
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3602
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3603 3604 3605
}

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

3607
/* tw */
B
Blue Swirl 已提交
3608
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3609
{
3610
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3611 3612
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3613 3614
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3615
    tcg_temp_free_i32(t0);
B
bellard 已提交
3616 3617 3618
}

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

3630 3631
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3632
static void gen_td(DisasContext *ctx)
3633
{
3634
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3635 3636
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3637 3638
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3639
    tcg_temp_free_i32(t0);
3640 3641 3642
}

/* tdi */
B
Blue Swirl 已提交
3643
static void gen_tdi(DisasContext *ctx)
3644
{
3645 3646
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3647 3648
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3649
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3650 3651
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3652 3653 3654
}
#endif

B
bellard 已提交
3655
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3656

3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
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);
}

3686
/* mcrxr */
B
Blue Swirl 已提交
3687
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3688
{
3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705
    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 已提交
3706 3707
}

A
aurel32 已提交
3708
/* mfcr mfocrf */
B
Blue Swirl 已提交
3709
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3710
{
3711
    uint32_t crm, crn;
3712

3713 3714
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3715
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3716
            crn = ctz32 (crm);
3717
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3718 3719
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3720
        }
3721
    } else {
A
aurel32 已提交
3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739
        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);
3740
    }
B
bellard 已提交
3741 3742 3743
}

/* mfmsr */
B
Blue Swirl 已提交
3744
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3745
{
3746
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3747
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3748
#else
A
aurel32 已提交
3749
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3750
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3751
        return;
3752
    }
3753
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3754
#endif
B
bellard 已提交
3755 3756
}

3757
static void spr_noaccess(void *opaque, int gprn, int sprn)
3758
{
3759
#if 0
3760 3761
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3762
#endif
3763 3764 3765
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3766
/* mfspr */
B
Blue Swirl 已提交
3767
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3768
{
A
aurel32 已提交
3769
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3770 3771
    uint32_t sprn = SPR(ctx->opcode);

3772
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3773
    if (ctx->mem_idx == 2)
3774
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3775
    else if (ctx->mem_idx)
3776 3777
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3778
#endif
3779
        read_cb = ctx->spr_cb[sprn].uea_read;
3780 3781
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3782
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3783 3784
        } else {
            /* Privilege exception */
3785 3786 3787 3788 3789
            /* 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) {
3790
                qemu_log("Trying to read privileged spr %d %03x at "
3791 3792 3793
                         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);
3794
            }
A
aurel32 已提交
3795
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3796
        }
3797 3798
    } else {
        /* Not defined */
3799
        qemu_log("Trying to read invalid spr %d %03x at "
3800 3801
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3802
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3803
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3804 3805 3806
    }
}

B
Blue Swirl 已提交
3807
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3808
{
3809
    gen_op_mfspr(ctx);
3810
}
3811 3812

/* mftb */
B
Blue Swirl 已提交
3813
static void gen_mftb(DisasContext *ctx)
3814 3815
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3816 3817
}

A
aurel32 已提交
3818
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3819
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3820
{
3821
    uint32_t crm, crn;
3822

3823
    crm = CRM(ctx->opcode);
M
malc 已提交
3824 3825 3826
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3827
            crn = ctz32 (crm);
M
malc 已提交
3828
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3829 3830
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3831 3832
            tcg_temp_free_i32(temp);
        }
3833
    } else {
A
aurel32 已提交
3834 3835 3836 3837 3838 3839 3840 3841
        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 已提交
3842
        tcg_temp_free_i32(temp);
3843
    }
B
bellard 已提交
3844 3845 3846
}

/* mtmsr */
J
j_mayer 已提交
3847
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3848
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3849 3850
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3851
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3852
#else
A
aurel32 已提交
3853
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3854
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3855 3856
        return;
    }
3857 3858
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3859 3860 3861 3862 3863
        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);
3864
    } else {
3865 3866 3867 3868
        /* 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
         */
3869
        gen_update_nip(ctx, ctx->nip);
3870
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
3871 3872
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3873
        gen_stop_exception(ctx);
3874
    }
J
j_mayer 已提交
3875 3876 3877 3878
#endif
}
#endif

B
Blue Swirl 已提交
3879
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3880
{
3881
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3882
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3883
#else
A
aurel32 已提交
3884
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3885
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3886
        return;
3887
    }
3888 3889
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3890 3891 3892 3893 3894
        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);
3895
    } else {
3896 3897
        TCGv msr = tcg_temp_new();

3898 3899 3900 3901
        /* 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
         */
3902
        gen_update_nip(ctx, ctx->nip);
3903
#if defined(TARGET_PPC64)
3904 3905 3906
        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)]);
3907
#endif
3908
        gen_helper_store_msr(cpu_env, msr);
3909
        /* Must stop the translation as machine state (may have) changed */
3910
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3911
        gen_stop_exception(ctx);
3912
    }
3913
#endif
B
bellard 已提交
3914 3915 3916
}

/* mtspr */
B
Blue Swirl 已提交
3917
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
3918
{
A
aurel32 已提交
3919
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3920 3921
    uint32_t sprn = SPR(ctx->opcode);

3922
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3923
    if (ctx->mem_idx == 2)
3924
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3925
    else if (ctx->mem_idx)
3926 3927
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3928
#endif
3929
        write_cb = ctx->spr_cb[sprn].uea_write;
3930 3931
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3932
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3933 3934
        } else {
            /* Privilege exception */
3935
            qemu_log("Trying to write privileged spr %d %03x at "
3936 3937 3938
                     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 已提交
3939
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3940
        }
3941 3942
    } else {
        /* Not defined */
3943
        qemu_log("Trying to write invalid spr %d %03x at "
3944 3945
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3946
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3947
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3948 3949 3950 3951
    }
}

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

3953
/* dcbf */
B
Blue Swirl 已提交
3954
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
3955
{
J
j_mayer 已提交
3956
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
3957 3958 3959 3960 3961
    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);
3962
    tcg_temp_free(t0);
B
bellard 已提交
3963 3964 3965
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
3966
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
3967
{
3968
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3969
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3970
#else
A
aurel32 已提交
3971
    TCGv EA, val;
A
aurel32 已提交
3972
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3973
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3974
        return;
3975
    }
P
pbrook 已提交
3976
    EA = tcg_temp_new();
A
aurel32 已提交
3977 3978
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
3979
    val = tcg_temp_new();
3980
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
3981 3982
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
3983 3984
    tcg_temp_free(val);
    tcg_temp_free(EA);
3985
#endif
B
bellard 已提交
3986 3987 3988
}

/* dcdst */
B
Blue Swirl 已提交
3989
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
3990
{
3991
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
3992 3993 3994 3995 3996
    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);
3997
    tcg_temp_free(t0);
B
bellard 已提交
3998 3999 4000
}

/* dcbt */
B
Blue Swirl 已提交
4001
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4002
{
4003
    /* interpreted as no-op */
4004 4005 4006
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4007 4008 4009
}

/* dcbtst */
B
Blue Swirl 已提交
4010
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4011
{
4012
    /* interpreted as no-op */
4013 4014 4015
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4016 4017 4018
}

/* dcbz */
B
Blue Swirl 已提交
4019
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4020
{
A
Alexander Graf 已提交
4021 4022 4023
    TCGv tcgv_addr;
    TCGv_i32 tcgv_is_dcbzl;
    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4024

A
aurel32 已提交
4025
    gen_set_access_type(ctx, ACCESS_CACHE);
4026 4027
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
4028 4029 4030 4031 4032 4033 4034 4035
    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 已提交
4036 4037
}

4038
/* dst / dstt */
B
Blue Swirl 已提交
4039
static void gen_dst(DisasContext *ctx)
4040 4041 4042 4043 4044 4045 4046 4047 4048
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

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

}

/* dss / dssall */
B
Blue Swirl 已提交
4060
static void gen_dss(DisasContext *ctx)
4061 4062 4063 4064
{
    /* interpreted as no-op */
}

B
bellard 已提交
4065
/* icbi */
B
Blue Swirl 已提交
4066
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4067
{
A
aurel32 已提交
4068 4069
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4070 4071
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4072 4073
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4074
    gen_helper_icbi(cpu_env, t0);
4075
    tcg_temp_free(t0);
B
bellard 已提交
4076 4077 4078 4079
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4080
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4081
{
4082 4083 4084 4085
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4086 4087 4088 4089
}

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

4091
/* mfsr */
B
Blue Swirl 已提交
4092
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4093
{
4094
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4095
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4096
#else
4097
    TCGv t0;
A
aurel32 已提交
4098
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4099
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4100
        return;
4101
    }
4102
    t0 = tcg_const_tl(SR(ctx->opcode));
4103
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4104
    tcg_temp_free(t0);
4105
#endif
B
bellard 已提交
4106 4107 4108
}

/* mfsrin */
B
Blue Swirl 已提交
4109
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4110
{
4111
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4112
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4113
#else
4114
    TCGv t0;
A
aurel32 已提交
4115
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4116
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4117
        return;
4118
    }
4119 4120 4121
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4122
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4123
    tcg_temp_free(t0);
4124
#endif
B
bellard 已提交
4125 4126 4127
}

/* mtsr */
B
Blue Swirl 已提交
4128
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4129
{
4130
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4131
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4132
#else
4133
    TCGv t0;
A
aurel32 已提交
4134
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4135
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4136
        return;
4137
    }
4138
    t0 = tcg_const_tl(SR(ctx->opcode));
4139
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4140
    tcg_temp_free(t0);
4141
#endif
B
bellard 已提交
4142 4143 4144
}

/* mtsrin */
B
Blue Swirl 已提交
4145
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4146
{
4147
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4148
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4149
#else
4150
    TCGv t0;
A
aurel32 已提交
4151
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4152
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4153
        return;
4154
    }
4155 4156 4157
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4158
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4159
    tcg_temp_free(t0);
4160
#endif
B
bellard 已提交
4161 4162
}

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

4166
/* mfsr */
B
Blue Swirl 已提交
4167
static void gen_mfsr_64b(DisasContext *ctx)
4168 4169
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4170
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4171
#else
4172
    TCGv t0;
A
aurel32 已提交
4173
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4174
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4175 4176
        return;
    }
4177
    t0 = tcg_const_tl(SR(ctx->opcode));
4178
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4179
    tcg_temp_free(t0);
4180 4181 4182 4183
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4184
static void gen_mfsrin_64b(DisasContext *ctx)
4185 4186
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4187
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4188
#else
4189
    TCGv t0;
A
aurel32 已提交
4190
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4191
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4192 4193
        return;
    }
4194 4195 4196
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4197
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4198
    tcg_temp_free(t0);
4199 4200 4201 4202
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4203
static void gen_mtsr_64b(DisasContext *ctx)
4204 4205
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4206
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4207
#else
4208
    TCGv t0;
A
aurel32 已提交
4209
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4210
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4211 4212
        return;
    }
4213
    t0 = tcg_const_tl(SR(ctx->opcode));
4214
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4215
    tcg_temp_free(t0);
4216 4217 4218 4219
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4220
static void gen_mtsrin_64b(DisasContext *ctx)
4221 4222
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4223
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4224
#else
4225
    TCGv t0;
A
aurel32 已提交
4226
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4227
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4228 4229
        return;
    }
4230 4231 4232
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4233
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4234
    tcg_temp_free(t0);
4235 4236
#endif
}
B
blueswir1 已提交
4237 4238

/* slbmte */
B
Blue Swirl 已提交
4239
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4240 4241 4242 4243 4244 4245 4246 4247
{
#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;
    }
4248 4249
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
B
blueswir1 已提交
4250 4251 4252
#endif
}

4253 4254 4255 4256 4257 4258 4259 4260 4261
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;
    }
4262
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275
                             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;
    }
4276
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4277 4278 4279
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4280 4281
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4282
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4283
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4284

4285
/* tlbia */
B
Blue Swirl 已提交
4286
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4287
{
4288
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4289
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4290
#else
A
aurel32 已提交
4291
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4292
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4293
        return;
4294
    }
4295
    gen_helper_tlbia(cpu_env);
4296
#endif
B
bellard 已提交
4297 4298
}

B
blueswir1 已提交
4299
/* tlbiel */
B
Blue Swirl 已提交
4300
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4301 4302 4303 4304 4305 4306 4307 4308
{
#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;
    }
4309
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
B
blueswir1 已提交
4310 4311 4312
#endif
}

B
bellard 已提交
4313
/* tlbie */
B
Blue Swirl 已提交
4314
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4315
{
4316
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4317
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4318
#else
A
aurel32 已提交
4319
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4320
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4321
        return;
4322
    }
4323
    if (NARROW_MODE(ctx)) {
4324 4325
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4326
        gen_helper_tlbie(cpu_env, t0);
4327
        tcg_temp_free(t0);
4328
    } else {
4329
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4330
    }
4331
#endif
B
bellard 已提交
4332 4333 4334
}

/* tlbsync */
B
Blue Swirl 已提交
4335
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4336
{
4337
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4338
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4339
#else
A
aurel32 已提交
4340
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4341
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4342
        return;
4343 4344 4345 4346
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4347
    gen_stop_exception(ctx);
4348
#endif
B
bellard 已提交
4349 4350
}

J
j_mayer 已提交
4351 4352
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4353
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4354 4355
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4356
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4357
#else
A
aurel32 已提交
4358
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4359
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4360 4361
        return;
    }
4362
    gen_helper_slbia(cpu_env);
J
j_mayer 已提交
4363 4364 4365 4366
#endif
}

/* slbie */
B
Blue Swirl 已提交
4367
static void gen_slbie(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_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4377 4378 4379 4380
#endif
}
#endif

B
bellard 已提交
4381 4382
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4383

4384
/* eciwx */
B
Blue Swirl 已提交
4385
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4386
{
A
aurel32 已提交
4387
    TCGv t0;
4388
    /* Should check EAR[E] ! */
A
aurel32 已提交
4389 4390 4391
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4392
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4393
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4394
    tcg_temp_free(t0);
4395 4396 4397
}

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

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

4412
/* abs - abs. */
B
Blue Swirl 已提交
4413
static void gen_abs(DisasContext *ctx)
4414
{
4415 4416 4417 4418 4419 4420 4421 4422
    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);
4423
    if (unlikely(Rc(ctx->opcode) != 0))
4424
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4425 4426 4427
}

/* abso - abso. */
B
Blue Swirl 已提交
4428
static void gen_abso(DisasContext *ctx)
4429
{
4430 4431 4432 4433
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
4434
    tcg_gen_movi_tl(cpu_ov, 0);
4435 4436
    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);
4437 4438
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4439 4440 4441 4442 4443 4444 4445
    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);
4446
    if (unlikely(Rc(ctx->opcode) != 0))
4447
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4448 4449 4450
}

/* clcs */
B
Blue Swirl 已提交
4451
static void gen_clcs(DisasContext *ctx)
4452
{
4453
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4454
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4455
    tcg_temp_free_i32(t0);
4456
    /* Rc=1 sets CR0 to an undefined state */
4457 4458 4459
}

/* div - div. */
B
Blue Swirl 已提交
4460
static void gen_div(DisasContext *ctx)
4461
{
4462 4463
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4464
    if (unlikely(Rc(ctx->opcode) != 0))
4465
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4466 4467 4468
}

/* divo - divo. */
B
Blue Swirl 已提交
4469
static void gen_divo(DisasContext *ctx)
4470
{
4471 4472
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4473
    if (unlikely(Rc(ctx->opcode) != 0))
4474
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4475 4476 4477
}

/* divs - divs. */
B
Blue Swirl 已提交
4478
static void gen_divs(DisasContext *ctx)
4479
{
4480 4481
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4482
    if (unlikely(Rc(ctx->opcode) != 0))
4483
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4484 4485 4486
}

/* divso - divso. */
B
Blue Swirl 已提交
4487
static void gen_divso(DisasContext *ctx)
4488
{
4489 4490
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4491
    if (unlikely(Rc(ctx->opcode) != 0))
4492
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4493 4494 4495
}

/* doz - doz. */
B
Blue Swirl 已提交
4496
static void gen_doz(DisasContext *ctx)
4497
{
4498 4499 4500 4501 4502 4503 4504 4505
    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);
4506
    if (unlikely(Rc(ctx->opcode) != 0))
4507
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4508 4509 4510
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4511
static void gen_dozo(DisasContext *ctx)
4512
{
4513 4514 4515 4516 4517 4518
    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 */
4519
    tcg_gen_movi_tl(cpu_ov, 0);
4520 4521 4522 4523 4524 4525 4526
    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);
4527 4528
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4529 4530 4531 4532 4533 4534 4535
    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);
4536
    if (unlikely(Rc(ctx->opcode) != 0))
4537
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4538 4539 4540
}

/* dozi */
B
Blue Swirl 已提交
4541
static void gen_dozi(DisasContext *ctx)
4542
{
4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553
    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)]);
4554 4555 4556
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4557
static void gen_lscbx(DisasContext *ctx)
4558
{
4559 4560 4561 4562
    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));
4563

A
aurel32 已提交
4564
    gen_addr_reg_index(ctx, t0);
4565
    /* NIP cannot be restored if the memory exception comes from an helper */
4566
    gen_update_nip(ctx, ctx->nip - 4);
4567
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4568 4569 4570
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4571
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4572
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4573
    if (unlikely(Rc(ctx->opcode) != 0))
4574 4575
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4576 4577 4578
}

/* maskg - maskg. */
B
Blue Swirl 已提交
4579
static void gen_maskg(DisasContext *ctx)
4580
{
4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599
    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);
4600
    if (unlikely(Rc(ctx->opcode) != 0))
4601
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4602 4603 4604
}

/* maskir - maskir. */
B
Blue Swirl 已提交
4605
static void gen_maskir(DisasContext *ctx)
4606
{
4607 4608 4609 4610 4611 4612 4613
    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);
4614
    if (unlikely(Rc(ctx->opcode) != 0))
4615
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4616 4617 4618
}

/* mul - mul. */
B
Blue Swirl 已提交
4619
static void gen_mul(DisasContext *ctx)
4620
{
4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633
    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);
4634
    if (unlikely(Rc(ctx->opcode) != 0))
4635
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4636 4637 4638
}

/* mulo - mulo. */
B
Blue Swirl 已提交
4639
static void gen_mulo(DisasContext *ctx)
4640
{
4641 4642 4643 4644 4645
    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 */
4646
    tcg_gen_movi_tl(cpu_ov, 0);
4647 4648 4649 4650 4651 4652 4653 4654 4655
    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);
4656 4657
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4658 4659 4660 4661
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4662
    if (unlikely(Rc(ctx->opcode) != 0))
4663
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4664 4665 4666
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4667
static void gen_nabs(DisasContext *ctx)
4668
{
4669 4670 4671 4672 4673 4674 4675 4676
    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);
4677
    if (unlikely(Rc(ctx->opcode) != 0))
4678
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4679 4680 4681
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4682
static void gen_nabso(DisasContext *ctx)
4683
{
4684 4685 4686 4687 4688 4689 4690 4691 4692
    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 */
4693
    tcg_gen_movi_tl(cpu_ov, 0);
4694
    if (unlikely(Rc(ctx->opcode) != 0))
4695
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4696 4697 4698
}

/* rlmi - rlmi. */
B
Blue Swirl 已提交
4699
static void gen_rlmi(DisasContext *ctx)
4700
{
4701 4702 4703 4704 4705 4706 4707 4708 4709
    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);
4710
    if (unlikely(Rc(ctx->opcode) != 0))
4711
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4712 4713 4714
}

/* rrib - rrib. */
B
Blue Swirl 已提交
4715
static void gen_rrib(DisasContext *ctx)
4716
{
4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727
    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);
4728
    if (unlikely(Rc(ctx->opcode) != 0))
4729
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4730 4731 4732
}

/* sle - sle. */
B
Blue Swirl 已提交
4733
static void gen_sle(DisasContext *ctx)
4734
{
4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745
    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);
4746
    if (unlikely(Rc(ctx->opcode) != 0))
4747
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4748 4749 4750
}

/* sleq - sleq. */
B
Blue Swirl 已提交
4751
static void gen_sleq(DisasContext *ctx)
4752
{
4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767
    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);
4768
    if (unlikely(Rc(ctx->opcode) != 0))
4769
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4770 4771 4772
}

/* sliq - sliq. */
B
Blue Swirl 已提交
4773
static void gen_sliq(DisasContext *ctx)
4774
{
4775 4776 4777 4778 4779 4780 4781 4782 4783 4784
    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);
4785
    if (unlikely(Rc(ctx->opcode) != 0))
4786
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4787 4788 4789
}

/* slliq - slliq. */
B
Blue Swirl 已提交
4790
static void gen_slliq(DisasContext *ctx)
4791
{
4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802
    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);
4803
    if (unlikely(Rc(ctx->opcode) != 0))
4804
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4805 4806 4807
}

/* sllq - sllq. */
B
Blue Swirl 已提交
4808
static void gen_sllq(DisasContext *ctx)
4809
{
4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831
    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);
4832
    if (unlikely(Rc(ctx->opcode) != 0))
4833
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4834 4835 4836
}

/* slq - slq. */
B
Blue Swirl 已提交
4837
static void gen_slq(DisasContext *ctx)
4838
{
4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854
    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);
4855
    if (unlikely(Rc(ctx->opcode) != 0))
4856
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4857 4858
}

4859
/* sraiq - sraiq. */
B
Blue Swirl 已提交
4860
static void gen_sraiq(DisasContext *ctx)
4861
{
4862 4863 4864 4865 4866 4867 4868 4869
    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);
4870
    tcg_gen_movi_tl(cpu_ca, 0);
4871 4872
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4873
    tcg_gen_movi_tl(cpu_ca, 1);
4874 4875 4876 4877
    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);
4878
    if (unlikely(Rc(ctx->opcode) != 0))
4879
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4880 4881 4882
}

/* sraq - sraq. */
B
Blue Swirl 已提交
4883
static void gen_sraq(DisasContext *ctx)
4884
{
4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903
    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);
4904
    tcg_gen_movi_tl(cpu_ca, 0);
4905 4906
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4907
    tcg_gen_movi_tl(cpu_ca, 1);
4908 4909 4910
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4911
    if (unlikely(Rc(ctx->opcode) != 0))
4912
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4913 4914 4915
}

/* sre - sre. */
B
Blue Swirl 已提交
4916
static void gen_sre(DisasContext *ctx)
4917
{
4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928
    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);
4929
    if (unlikely(Rc(ctx->opcode) != 0))
4930
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4931 4932 4933
}

/* srea - srea. */
B
Blue Swirl 已提交
4934
static void gen_srea(DisasContext *ctx)
4935
{
4936 4937 4938 4939 4940 4941 4942 4943
    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);
4944
    if (unlikely(Rc(ctx->opcode) != 0))
4945
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4946 4947 4948
}

/* sreq */
B
Blue Swirl 已提交
4949
static void gen_sreq(DisasContext *ctx)
4950
{
4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965
    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);
4966
    if (unlikely(Rc(ctx->opcode) != 0))
4967
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4968 4969 4970
}

/* sriq */
B
Blue Swirl 已提交
4971
static void gen_sriq(DisasContext *ctx)
4972
{
4973 4974 4975 4976 4977 4978 4979 4980 4981 4982
    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);
4983
    if (unlikely(Rc(ctx->opcode) != 0))
4984
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4985 4986 4987
}

/* srliq */
B
Blue Swirl 已提交
4988
static void gen_srliq(DisasContext *ctx)
4989
{
4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000
    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);
5001
    if (unlikely(Rc(ctx->opcode) != 0))
5002
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5003 5004 5005
}

/* srlq */
B
Blue Swirl 已提交
5006
static void gen_srlq(DisasContext *ctx)
5007
{
5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030
    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);
5031
    if (unlikely(Rc(ctx->opcode) != 0))
5032
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5033 5034 5035
}

/* srq */
B
Blue Swirl 已提交
5036
static void gen_srq(DisasContext *ctx)
5037
{
5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053
    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);
5054
    if (unlikely(Rc(ctx->opcode) != 0))
5055
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5056 5057 5058
}

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

5060
/* dsa  */
B
Blue Swirl 已提交
5061
static void gen_dsa(DisasContext *ctx)
5062 5063
{
    /* XXX: TODO */
A
aurel32 已提交
5064
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5065 5066 5067
}

/* esa */
B
Blue Swirl 已提交
5068
static void gen_esa(DisasContext *ctx)
5069 5070
{
    /* XXX: TODO */
A
aurel32 已提交
5071
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5072 5073 5074
}

/* mfrom */
B
Blue Swirl 已提交
5075
static void gen_mfrom(DisasContext *ctx)
5076 5077
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5078
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5079
#else
A
aurel32 已提交
5080
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5081
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5082 5083
        return;
    }
5084
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5085 5086 5087 5088
#endif
}

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

5090
/* tlbld */
B
Blue Swirl 已提交
5091
static void gen_tlbld_6xx(DisasContext *ctx)
5092 5093
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5094
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5095
#else
A
aurel32 已提交
5096
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5097
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5098 5099
        return;
    }
5100
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5101 5102 5103 5104
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5105
static void gen_tlbli_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_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5115 5116 5117
#endif
}

5118
/* 74xx TLB management */
B
Blue Swirl 已提交
5119

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

/* tlbli */
B
Blue Swirl 已提交
5135
static void gen_tlbli_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_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5145 5146 5147
#endif
}

5148
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5149

5150
/* clf */
B
Blue Swirl 已提交
5151
static void gen_clf(DisasContext *ctx)
5152 5153 5154 5155 5156
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5157
static void gen_cli(DisasContext *ctx)
5158
{
B
blueswir1 已提交
5159
    /* Cache line invalidate: privileged and treated as no-op */
5160
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5161
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5162
#else
A
aurel32 已提交
5163
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5164
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5165 5166 5167 5168 5169 5170
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5171
static void gen_dclst(DisasContext *ctx)
5172 5173 5174 5175
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5176
static void gen_mfsri(DisasContext *ctx)
5177 5178
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5179
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5180
#else
5181 5182 5183
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5184
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5185
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5186 5187
        return;
    }
5188
    t0 = tcg_temp_new();
A
aurel32 已提交
5189
    gen_addr_reg_index(ctx, t0);
5190 5191
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
5192
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5193
    tcg_temp_free(t0);
5194
    if (ra != 0 && ra != rd)
5195
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5196 5197 5198
#endif
}

B
Blue Swirl 已提交
5199
static void gen_rac(DisasContext *ctx)
5200 5201
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5202
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5203
#else
5204
    TCGv t0;
A
aurel32 已提交
5205
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5206
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5207 5208
        return;
    }
5209
    t0 = tcg_temp_new();
A
aurel32 已提交
5210
    gen_addr_reg_index(ctx, t0);
5211
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5212
    tcg_temp_free(t0);
5213 5214 5215
#endif
}

B
Blue Swirl 已提交
5216
static void gen_rfsvc(DisasContext *ctx)
5217 5218
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5219
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5220
#else
A
aurel32 已提交
5221
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5222
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5223 5224
        return;
    }
5225
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5226
    gen_sync_exception(ctx);
5227 5228 5229 5230 5231 5232 5233 5234 5235
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5236
static void gen_lfq(DisasContext *ctx)
5237
{
5238
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5239 5240 5241 5242 5243 5244 5245
    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);
5246
    tcg_temp_free(t0);
5247 5248 5249
}

/* lfqu */
B
Blue Swirl 已提交
5250
static void gen_lfqu(DisasContext *ctx)
5251 5252
{
    int ra = rA(ctx->opcode);
5253
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5254 5255 5256 5257 5258 5259 5260 5261
    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);
5262
    if (ra != 0)
5263 5264 5265
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5266 5267 5268
}

/* lfqux */
B
Blue Swirl 已提交
5269
static void gen_lfqux(DisasContext *ctx)
5270 5271
{
    int ra = rA(ctx->opcode);
5272
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5273 5274 5275 5276 5277 5278 5279 5280 5281
    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);
5282
    if (ra != 0)
5283 5284
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5285 5286 5287
}

/* lfqx */
B
Blue Swirl 已提交
5288
static void gen_lfqx(DisasContext *ctx)
5289
{
5290
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5291 5292 5293 5294 5295 5296 5297
    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);
5298
    tcg_temp_free(t0);
5299 5300 5301
}

/* stfq */
B
Blue Swirl 已提交
5302
static void gen_stfq(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_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);
5312
    tcg_temp_free(t0);
5313 5314 5315
}

/* stfqu */
B
Blue Swirl 已提交
5316
static void gen_stfqu(DisasContext *ctx)
5317 5318
{
    int ra = rA(ctx->opcode);
5319
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5320 5321 5322 5323 5324 5325 5326 5327 5328
    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);
5329
    if (ra != 0)
5330 5331
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5332 5333 5334
}

/* stfqux */
B
Blue Swirl 已提交
5335
static void gen_stfqux(DisasContext *ctx)
5336 5337
{
    int ra = rA(ctx->opcode);
5338
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5339 5340 5341 5342 5343 5344 5345 5346 5347
    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);
5348
    if (ra != 0)
5349 5350
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5351 5352 5353
}

/* stfqx */
B
Blue Swirl 已提交
5354
static void gen_stfqx(DisasContext *ctx)
5355
{
5356
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5357 5358 5359 5360 5361 5362 5363
    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);
5364
    tcg_temp_free(t0);
5365 5366 5367
}

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

5369
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5370
static void gen_mfapidi(DisasContext *ctx)
5371 5372
{
    /* XXX: TODO */
A
aurel32 已提交
5373
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5374 5375
}

5376
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5377
static void gen_tlbiva(DisasContext *ctx)
5378 5379
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5380
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5381
#else
5382
    TCGv t0;
A
aurel32 已提交
5383
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5384
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5385 5386
        return;
    }
5387
    t0 = tcg_temp_new();
A
aurel32 已提交
5388
    gen_addr_reg_index(ctx, t0);
5389
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5390
    tcg_temp_free(t0);
5391 5392 5393 5394
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5395 5396
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5397
{
5398 5399
    TCGv t0, t1;

P
pbrook 已提交
5400 5401
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5402

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

5516
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5517
static void glue(gen_, name)(DisasContext *ctx)                               \
5518 5519 5520 5521 5522 5523
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

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

/* mulchw  - mulchw.  */
5597
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5598
/* mulchwu - mulchwu. */
5599
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5600
/* mulhhw  - mulhhw.  */
5601
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5602
/* mulhhwu - mulhhwu. */
5603
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5604
/* mullhw  - mullhw.  */
5605
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5606
/* mullhwu - mullhwu. */
5607
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5608 5609

/* mfdcr */
B
Blue Swirl 已提交
5610
static void gen_mfdcr(DisasContext *ctx)
5611 5612
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5613
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5614
#else
5615
    TCGv dcrn;
A
aurel32 已提交
5616
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5617
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5618 5619
        return;
    }
5620 5621 5622
    /* 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));
5623
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5624
    tcg_temp_free(dcrn);
5625 5626 5627 5628
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5629
static void gen_mtdcr(DisasContext *ctx)
5630 5631
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5632
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5633
#else
5634
    TCGv dcrn;
A
aurel32 已提交
5635
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5636
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5637 5638
        return;
    }
5639 5640 5641
    /* 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));
5642
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5643
    tcg_temp_free(dcrn);
5644 5645 5646 5647
#endif
}

/* mfdcrx */
5648
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5649
static void gen_mfdcrx(DisasContext *ctx)
5650 5651
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5652
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5653
#else
A
aurel32 已提交
5654
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5655
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5656 5657
        return;
    }
5658 5659
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5660 5661
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5662
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5663 5664 5665 5666
#endif
}

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

5685
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5686
static void gen_mfdcrux(DisasContext *ctx)
5687
{
5688 5689
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5690 5691
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5692 5693 5694 5695
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

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

5705
/* dccci */
B
Blue Swirl 已提交
5706
static void gen_dccci(DisasContext *ctx)
5707 5708
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5709
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5710
#else
A
aurel32 已提交
5711
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5712
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5713 5714 5715 5716 5717 5718 5719
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5720
static void gen_dcread(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
    TCGv EA, val;
A
aurel32 已提交
5726
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5727
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5728 5729
        return;
    }
A
aurel32 已提交
5730
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5731
    EA = tcg_temp_new();
A
aurel32 已提交
5732
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5733
    val = tcg_temp_new();
A
aurel32 已提交
5734
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5735 5736 5737
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5738 5739 5740 5741
#endif
}

/* icbt */
B
Blue Swirl 已提交
5742
static void gen_icbt_40x(DisasContext *ctx)
5743 5744 5745 5746 5747 5748 5749 5750
{
    /* 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 已提交
5751
static void gen_iccci(DisasContext *ctx)
5752 5753
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5754
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5755
#else
A
aurel32 已提交
5756
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5757
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5758 5759 5760 5761 5762 5763 5764
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5765
static void gen_icread(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
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5778
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5779
static void gen_rfci_40x(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
        return;
    }
    /* Restore CPU state */
5789
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
5790
    gen_sync_exception(ctx);
5791 5792 5793
#endif
}

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

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

5811
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5812
static void gen_rfdi(DisasContext *ctx)
5813 5814
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5815
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5816
#else
A
aurel32 已提交
5817
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5818
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5819 5820 5821
        return;
    }
    /* Restore CPU state */
5822
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
5823
    gen_sync_exception(ctx);
5824 5825 5826
#endif
}

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

5843
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5844

5845
/* tlbre */
B
Blue Swirl 已提交
5846
static void gen_tlbre_40x(DisasContext *ctx)
5847 5848
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5849
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5850
#else
A
aurel32 已提交
5851
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5852
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5853 5854 5855 5856
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5857 5858
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5859 5860
        break;
    case 1:
5861 5862
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5863 5864
        break;
    default:
A
aurel32 已提交
5865
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5866
        break;
5867
    }
5868 5869 5870
#endif
}

5871
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5872
static void gen_tlbsx_40x(DisasContext *ctx)
5873 5874
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5875
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5876
#else
5877
    TCGv t0;
A
aurel32 已提交
5878
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5879
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5880 5881
        return;
    }
5882
    t0 = tcg_temp_new();
A
aurel32 已提交
5883
    gen_addr_reg_index(ctx, t0);
5884
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5885 5886 5887
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
5888
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5889 5890 5891 5892
        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);
    }
5893
#endif
B
bellard 已提交
5894 5895
}

5896
/* tlbwe */
B
Blue Swirl 已提交
5897
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5898
{
5899
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5900
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5901
#else
A
aurel32 已提交
5902
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5903
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5904 5905 5906 5907
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5908 5909
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
5910 5911
        break;
    case 1:
5912 5913
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
5914 5915
        break;
    default:
A
aurel32 已提交
5916
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5917
        break;
5918
    }
5919 5920 5921
#endif
}

5922
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5923

5924
/* tlbre */
B
Blue Swirl 已提交
5925
static void gen_tlbre_440(DisasContext *ctx)
5926 5927
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5928
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5929
#else
A
aurel32 已提交
5930
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5931
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5932 5933 5934 5935 5936 5937
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5938 5939
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5940 5941
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
5942 5943
            tcg_temp_free_i32(t0);
        }
5944 5945
        break;
    default:
A
aurel32 已提交
5946
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5947 5948 5949 5950 5951 5952
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5953
static void gen_tlbsx_440(DisasContext *ctx)
5954 5955
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5956
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5957
#else
5958
    TCGv t0;
A
aurel32 已提交
5959
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5960
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5961 5962
        return;
    }
5963
    t0 = tcg_temp_new();
A
aurel32 已提交
5964
    gen_addr_reg_index(ctx, t0);
5965
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5966 5967 5968
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
5969
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5970 5971 5972 5973
        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);
    }
5974 5975 5976 5977
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
5978
static void gen_tlbwe_440(DisasContext *ctx)
5979 5980
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5981
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5982
#else
A
aurel32 已提交
5983
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5984
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5985 5986 5987 5988 5989 5990
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5991 5992
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5993 5994
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
5995 5996
            tcg_temp_free_i32(t0);
        }
5997 5998
        break;
    default:
A
aurel32 已提交
5999
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6000 6001 6002 6003 6004
        break;
    }
#endif
}

A
Alexander Graf 已提交
6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017
/* 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;
    }

6018
    gen_helper_booke206_tlbre(cpu_env);
A
Alexander Graf 已提交
6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041
#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)]);
6042
    gen_helper_booke206_tlbsx(cpu_env, t0);
A
Alexander Graf 已提交
6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055
#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;
    }
6056
    gen_update_nip(ctx, ctx->nip - 4);
6057
    gen_helper_booke206_tlbwe(cpu_env);
A
Alexander Graf 已提交
6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074
#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);

6075
    gen_helper_booke206_tlbivax(cpu_env, t0);
A
Alexander Graf 已提交
6076 6077 6078
#endif
}

A
Alexander Graf 已提交
6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094
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:
6095
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6096 6097
        break;
    case 1:
6098
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6099 6100
        break;
    case 3:
6101
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6102 6103 6104 6105 6106 6107 6108 6109 6110 6111
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6112

6113
/* wrtee */
B
Blue Swirl 已提交
6114
static void gen_wrtee(DisasContext *ctx)
6115 6116
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6117
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6118
#else
6119
    TCGv t0;
A
aurel32 已提交
6120
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6121
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6122 6123
        return;
    }
6124 6125 6126 6127 6128
    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 已提交
6129 6130 6131
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6132
    gen_stop_exception(ctx);
6133 6134 6135 6136
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6137
static void gen_wrteei(DisasContext *ctx)
6138 6139
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6140
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6141
#else
A
aurel32 已提交
6142
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6143
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6144 6145
        return;
    }
6146
    if (ctx->opcode & 0x00008000) {
6147 6148
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6149
        gen_stop_exception(ctx);
6150
    } else {
A
aurel32 已提交
6151
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6152
    }
6153 6154 6155
#endif
}

J
j_mayer 已提交
6156
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6157

6158
/* dlmzb */
B
Blue Swirl 已提交
6159
static void gen_dlmzb(DisasContext *ctx)
6160
{
6161
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6162 6163
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6164
    tcg_temp_free_i32(t0);
6165 6166 6167
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6168
static void gen_mbar(DisasContext *ctx)
6169 6170 6171 6172 6173
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6174
static void gen_msync_4xx(DisasContext *ctx)
6175 6176 6177 6178 6179
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6180
static void gen_icbt_440(DisasContext *ctx)
6181 6182 6183 6184 6185
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6186 6187
}

A
Alexander Graf 已提交
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199
/* 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;
    }

6200
    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
A
Alexander Graf 已提交
6201 6202 6203
#endif
}

A
Alexander Graf 已提交
6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217
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
}

6218 6219 6220
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6221
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6222
{
A
aurel32 已提交
6223
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6224 6225 6226 6227
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6228
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6229
static void glue(gen_, name)(DisasContext *ctx)                                       \
6230
{                                                                             \
6231
    TCGv EA;                                                                  \
6232
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6233
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6234 6235
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6236
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6237
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6238
    gen_addr_reg_index(ctx, EA);                                              \
6239
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6240 6241
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6242
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6243
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6244
    } else {                                                                  \
A
aurel32 已提交
6245
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6246
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6247
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6248 6249
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6250 6251 6252
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6253
static void gen_st##name(DisasContext *ctx)                                   \
6254
{                                                                             \
6255
    TCGv EA;                                                                  \
6256
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6257
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6258 6259
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6260
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6261
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6262
    gen_addr_reg_index(ctx, EA);                                              \
6263
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6264 6265
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6266
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6267
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6268
    } else {                                                                  \
A
aurel32 已提交
6269
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6270
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6271
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6272 6273
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6274 6275
}

A
aurel32 已提交
6276
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6277
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288
    {                                                                   \
        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));                              \
6289
        gen_helper_lve##name(cpu_env, rs, EA);                          \
A
aurel32 已提交
6290 6291 6292 6293 6294
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6295
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306
    {                                                                   \
        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));                              \
6307
        gen_helper_stve##name(cpu_env, rs, EA);                         \
A
aurel32 已提交
6308 6309 6310 6311
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6312
GEN_VR_LDX(lvx, 0x07, 0x03);
6313
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6314
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6315

A
aurel32 已提交
6316 6317 6318 6319
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6320
GEN_VR_STX(svx, 0x07, 0x07);
6321
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6322
GEN_VR_STX(svxl, 0x07, 0x0F);
6323

A
aurel32 已提交
6324 6325 6326 6327
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6328
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343
{
    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 已提交
6344
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359
{
    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 已提交
6360
static void gen_mfvscr(DisasContext *ctx)
6361 6362 6363 6364 6365 6366 6367 6368
{
    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();
6369
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6370
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6371
    tcg_temp_free_i32(t);
6372 6373
}

B
Blue Swirl 已提交
6374
static void gen_mtvscr(DisasContext *ctx)
6375
{
A
aurel32 已提交
6376
    TCGv_ptr p;
6377 6378 6379 6380
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6381
    p = gen_avr_ptr(rD(ctx->opcode));
6382
    gen_helper_mtvscr(cpu_env, p);
A
aurel32 已提交
6383
    tcg_temp_free_ptr(p);
6384 6385
}

6386 6387
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6388
static void glue(gen_, name)(DisasContext *ctx)                                 \
6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403
{                                                                       \
    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);

6404
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6405
static void glue(gen_, name)(DisasContext *ctx)                                 \
6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420
{                                                                       \
    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);                                              \
}

6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431
#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));                                  \
6432
    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6433 6434 6435 6436 6437
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6438 6439 6440 6441 6442 6443
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);
6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455
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 已提交
6456 6457 6458 6459 6460 6461
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 已提交
6462 6463 6464 6465 6466 6467
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 已提交
6468 6469 6470 6471 6472 6473 6474 6475
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 已提交
6476 6477 6478
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6479 6480 6481 6482 6483 6484
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 已提交
6485 6486
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6487 6488
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500
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 已提交
6501 6502 6503
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6504 6505
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6506 6507 6508 6509 6510 6511 6512 6513
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 已提交
6514
GEN_VXFORM(vpkpx, 7, 12);
6515 6516 6517 6518 6519 6520 6521 6522 6523
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 已提交
6524

6525
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6526
static void glue(gen_, name)(DisasContext *ctx)                         \
6527 6528 6529 6530 6531 6532 6533 6534 6535
    {                                                                   \
        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));                              \
6536
        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
6537 6538 6539 6540 6541 6542 6543 6544 6545
        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)))

6546 6547 6548 6549 6550 6551 6552 6553 6554
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)
6555 6556 6557 6558
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6559

A
aurel32 已提交
6560
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6561
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579
    {                                                                   \
        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);

6580
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6581
static void glue(gen_, name)(DisasContext *ctx)                                 \
6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594
    {                                                                   \
        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);                                         \
    }

6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610
#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 已提交
6611 6612 6613 6614
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 已提交
6615 6616
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
6617 6618 6619 6620 6621 6622 6623 6624
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 已提交
6625

6626
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6627
static void glue(gen_, name)(DisasContext *ctx)                                 \
6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641
    {                                                                   \
        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);                                          \
    }

6642
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6643
static void glue(gen_, name)(DisasContext *ctx)                                 \
6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659
    {                                                                   \
        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);                                          \
    }

6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678
#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 已提交
6679 6680 6681
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
6682 6683 6684 6685
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 已提交
6686

B
Blue Swirl 已提交
6687
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6688 6689
{
    TCGv_ptr ra, rb, rd;
6690
    TCGv_i32 sh;
A
aurel32 已提交
6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702
    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);
6703
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6704 6705
}

6706
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6707
static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718
    {                                                                   \
        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)) {                                          \
6719
            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
6720
        } else {                                                        \
6721
            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
6722 6723 6724 6725 6726 6727 6728
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6729 6730
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6731
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748
{
    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 已提交
6749
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6750
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6751
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6752
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6753
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6754

6755 6756
/***                           SPE extension                               ***/
/* Register moves */
6757

6758 6759 6760 6761 6762

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6763
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6764 6765 6766 6767 6768 6769 6770 6771 6772 6773
        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,
6774
                   offsetof(CPUPPCState, spe_acc));
6775 6776 6777 6778 6779 6780 6781
#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 */
6782
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
6783 6784 6785 6786 6787 6788 6789 6790
    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 已提交
6791 6792
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6793 6794 6795
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6796
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6797
#endif
A
aurel32 已提交
6798
}
6799

B
Blue Swirl 已提交
6800 6801
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6802 6803 6804
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6805
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6806 6807 6808
    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 已提交
6809
    tcg_temp_free_i64(tmp);
6810
#endif
A
aurel32 已提交
6811
}
6812

6813
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
6814
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6815 6816 6817 6818 6819 6820 6821 6822
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6823
static inline void gen_speundef(DisasContext *ctx)
6824
{
A
aurel32 已提交
6825
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6826 6827
}

6828 6829 6830
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6831
static inline void gen_##name(DisasContext *ctx)                              \
6832 6833
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6834
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6835 6836
        return;                                                               \
    }                                                                         \
6837 6838 6839 6840 6841
    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 已提交
6842
static inline void gen_##name(DisasContext *ctx)                              \
6843 6844
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6845
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6846 6847 6848 6849 6850 6851
        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)]);                                        \
6852
}
6853 6854 6855 6856 6857 6858 6859 6860 6861 6862
#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);
6863

6864 6865 6866
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6867
static inline void gen_##name(DisasContext *ctx)                              \
6868 6869
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6870
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6871 6872
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6873 6874 6875
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6876 6877 6878 6879
    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 已提交
6880
    tcg_temp_free_i64(t2);                                                    \
6881 6882
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6883 6884
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6885
}
6886 6887
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6888
static inline void gen_##name(DisasContext *ctx)                              \
6889 6890
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6891
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6892 6893
        return;                                                               \
    }                                                                         \
6894 6895 6896 6897
    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));                                                 \
6898
}
6899 6900 6901 6902 6903
#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);
6904

6905 6906 6907
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6908
static inline void gen_##name(DisasContext *ctx)                              \
6909 6910
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6911
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6912 6913
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6914 6915 6916
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6917 6918 6919 6920
    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 已提交
6921
    tcg_temp_free_i64(t2);                                                    \
6922 6923
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6924 6925
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6926
}
6927
#else
P
pbrook 已提交
6928
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6929
static inline void gen_##name(DisasContext *ctx)                              \
6930 6931
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6932
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6933 6934 6935 6936 6937 6938
        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
6939

B
Blue Swirl 已提交
6940
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6941 6942 6943
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6944

6945 6946 6947 6948
    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 已提交
6949
    tcg_gen_mov_i32(ret, arg1);
6950 6951 6952 6953 6954 6955
    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 已提交
6956
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6957
{
6958 6959 6960 6961
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6962 6963
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6964

6965 6966
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6967
static inline void gen_##name(DisasContext *ctx)                              \
6968 6969
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6970
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6971 6972
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6973 6974 6975
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6976
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6977 6978 6979 6980 6981 6982 6983
    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 已提交
6984
    tcg_temp_free_i64(t3);                                                    \
6985
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6986
    tcg_temp_free_i32(t2);                                                    \
6987
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6988 6989
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6990
}
6991 6992
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6993
static inline void gen_##name(DisasContext *ctx)                              \
6994 6995
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6996
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6997 6998
        return;                                                               \
    }                                                                         \
6999 7000 7001 7002
    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)]);                                        \
7003
}
7004
#endif
7005

B
Blue Swirl 已提交
7006
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7007
{
P
pbrook 已提交
7008
    TCGv_i32 t0;
7009
    int l1, l2;
7010

7011 7012
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7013
    t0 = tcg_temp_local_new_i32();
7014 7015 7016 7017 7018 7019 7020
    /* 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);
7021
    gen_set_label(l2);
P
pbrook 已提交
7022
    tcg_temp_free_i32(t0);
7023 7024
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7025
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7026
{
P
pbrook 已提交
7027
    TCGv_i32 t0;
7028 7029 7030 7031
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7032
    t0 = tcg_temp_local_new_i32();
7033 7034 7035 7036 7037 7038 7039
    /* 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);
7040
    gen_set_label(l2);
P
pbrook 已提交
7041
    tcg_temp_free_i32(t0);
7042 7043
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7044
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7045
{
P
pbrook 已提交
7046
    TCGv_i32 t0;
7047 7048 7049 7050
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7051
    t0 = tcg_temp_local_new_i32();
7052 7053 7054 7055 7056 7057 7058
    /* 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);
7059
    gen_set_label(l2);
P
pbrook 已提交
7060
    tcg_temp_free_i32(t0);
7061 7062
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7063
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7064
{
P
pbrook 已提交
7065
    TCGv_i32 t0 = tcg_temp_new_i32();
7066 7067
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7068
    tcg_temp_free_i32(t0);
7069 7070
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7071
static inline void gen_evmergehi(DisasContext *ctx)
7072 7073
{
    if (unlikely(!ctx->spe_enabled)) {
7074
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7075 7076 7077
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7078 7079
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090
    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 已提交
7091
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7092
{
7093 7094 7095
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7096

7097 7098 7099
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7100
static inline void gen_##name(DisasContext *ctx)                              \
7101 7102
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7103
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7104 7105
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7106 7107 7108
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7109 7110 7111 7112
    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 已提交
7113
    tcg_temp_free_i64(t2);                                                    \
7114 7115
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7116 7117
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7118 7119 7120
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7121
static inline void gen_##name(DisasContext *ctx)                              \
7122 7123
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7124
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138
        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 已提交
7139
static inline void gen_##name(DisasContext *ctx)                              \
7140 7141
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7142
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7143 7144 7145 7146 7147 7148
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7149 7150 7151
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7152 7153 7154
    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 已提交
7155
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7156 7157 7158 7159 7160 7161 7162 7163 7164
    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 已提交
7165
    tcg_temp_free_i64(t2);                                                    \
7166 7167 7168 7169 7170 7171 7172 7173
    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 已提交
7174 7175
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7176 7177 7178
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7179
static inline void gen_##name(DisasContext *ctx)                              \
7180 7181
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7182
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215
        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 已提交
7216
static inline void gen_brinc(DisasContext *ctx)
7217 7218
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7219 7220
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7221
}
B
Blue Swirl 已提交
7222
static inline void gen_evmergelo(DisasContext *ctx)
7223 7224
{
    if (unlikely(!ctx->spe_enabled)) {
7225
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7226 7227 7228
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7229 7230
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7231
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7232 7233 7234 7235 7236 7237
    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)]);
7238
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7239 7240
#endif
}
B
Blue Swirl 已提交
7241
static inline void gen_evmergehilo(DisasContext *ctx)
7242 7243
{
    if (unlikely(!ctx->spe_enabled)) {
7244
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7245 7246 7247
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7248 7249
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7250
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7251 7252 7253 7254 7255 7256 7257 7258 7259
    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 已提交
7260
static inline void gen_evmergelohi(DisasContext *ctx)
7261 7262
{
    if (unlikely(!ctx->spe_enabled)) {
7263
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7264 7265 7266
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7267 7268
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7269 7270 7271 7272 7273 7274
    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
7275 7276 7277 7278 7279 7280 7281 7282 7283 7284
    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)]);
    }
7285 7286
#endif
}
B
Blue Swirl 已提交
7287
static inline void gen_evsplati(DisasContext *ctx)
7288
{
7289
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7290

7291
#if defined(TARGET_PPC64)
7292
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7293 7294 7295 7296 7297
#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 已提交
7298
static inline void gen_evsplatfi(DisasContext *ctx)
7299
{
7300
    uint64_t imm = rA(ctx->opcode) << 27;
7301

7302
#if defined(TARGET_PPC64)
7303
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7304 7305 7306 7307
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7308 7309
}

B
Blue Swirl 已提交
7310
static inline void gen_evsel(DisasContext *ctx)
7311 7312 7313 7314 7315
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7316
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7317
#if defined(TARGET_PPC64)
P
pbrook 已提交
7318 7319
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338
#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)
7339
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7340 7341 7342 7343 7344 7345
#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)
7346
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7347 7348 7349 7350
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7351
    tcg_temp_free_i32(t0);
7352 7353 7354 7355 7356 7357
#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 已提交
7358 7359

static void gen_evsel0(DisasContext *ctx)
7360 7361 7362
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7363 7364

static void gen_evsel1(DisasContext *ctx)
7365 7366 7367
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7368 7369

static void gen_evsel2(DisasContext *ctx)
7370 7371 7372
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7373 7374

static void gen_evsel3(DisasContext *ctx)
7375 7376 7377
{
    gen_evsel(ctx);
}
7378

7379 7380 7381 7382 7383 7384 7385
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7386
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414
        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)) {
7415
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7416 7417 7418 7419 7420 7421 7422 7423 7424
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7425
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7426 7427 7428 7429 7430 7431 7432 7433 7434
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7435
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447
        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 */
7448
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7449 7450 7451 7452 7453

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

    /* Store acc */
7454
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467

    /* 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)) {
7468
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501
        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));
7502
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520

    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 */
7521
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7522 7523 7524 7525 7526

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

    /* Store acc */
7527
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7528 7529 7530 7531 7532 7533 7534 7535

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564
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); ////
7565

7566
/* SPE load and stores */
B
Blue Swirl 已提交
7567
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7568 7569 7570
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7571
    if (rA(ctx->opcode) == 0) {
7572
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7573
    } else {
7574
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7575
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
7576 7577 7578
            tcg_gen_ext32u_tl(EA, EA);
        }
    }
7579
}
7580

B
Blue Swirl 已提交
7581
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7582 7583
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7584
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7585 7586
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7587
    gen_qemu_ld64(ctx, t0, addr);
7588 7589 7590 7591 7592
    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
7593
}
7594

B
Blue Swirl 已提交
7595
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7596
{
7597
#if defined(TARGET_PPC64)
7598
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7599
    gen_qemu_ld32u(ctx, t0, addr);
7600
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7601 7602
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7603 7604 7605
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7606 7607 7608
    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);
7609
#endif
7610
}
7611

B
Blue Swirl 已提交
7612
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7613 7614 7615
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7616
    gen_qemu_ld16u(ctx, t0, addr);
7617
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7618 7619
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7620 7621
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7622 7623
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7624 7625
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7626 7627
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7628
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7629
#else
A
aurel32 已提交
7630
    gen_qemu_ld16u(ctx, t0, addr);
7631
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7632 7633
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7634
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7635 7636
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7637
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7638 7639
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7640
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7641
#endif
7642
    tcg_temp_free(t0);
7643 7644
}

B
Blue Swirl 已提交
7645
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7646 7647
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7648
    gen_qemu_ld16u(ctx, t0, addr);
7649 7650 7651 7652 7653 7654 7655 7656 7657 7658
#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);
7659 7660
}

B
Blue Swirl 已提交
7661
static inline void gen_op_evlhhousplat(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
#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);
7673 7674
}

B
Blue Swirl 已提交
7675
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7676 7677
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7678
    gen_qemu_ld16s(ctx, t0, addr);
7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689
#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 已提交
7690
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7691 7692 7693
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7694
    gen_qemu_ld16u(ctx, t0, addr);
7695
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7696 7697
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7698 7699 7700
    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 已提交
7701
    gen_qemu_ld16u(ctx, t0, addr);
7702
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7703 7704
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7705 7706 7707 7708 7709
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7710
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7711 7712 7713
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7714 7715 7716
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7717 7718 7719 7720
    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 已提交
7721 7722 7723
    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);
7724 7725 7726
#endif
}

B
Blue Swirl 已提交
7727
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7728 7729 7730
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7731
    gen_qemu_ld16s(ctx, t0, addr);
7732
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7733 7734
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7735 7736 7737 7738
    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 已提交
7739 7740 7741
    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);
7742 7743 7744
#endif
}

B
Blue Swirl 已提交
7745
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7746 7747
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7748
    gen_qemu_ld32u(ctx, t0, addr);
7749
#if defined(TARGET_PPC64)
7750 7751 7752 7753 7754 7755 7756 7757 7758
    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 已提交
7759
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7760 7761 7762
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7763
    gen_qemu_ld16u(ctx, t0, addr);
7764 7765 7766
    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 已提交
7767 7768
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7769 7770 7771 7772
    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 已提交
7773
    gen_qemu_ld16u(ctx, t0, addr);
7774 7775
    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 已提交
7776 7777
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7778 7779
    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);
7780
#endif
7781 7782 7783
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7784
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7785 7786
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7787
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7788
#else
7789 7790
    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 已提交
7791
    gen_qemu_st64(ctx, t0, addr);
7792 7793 7794 7795
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7796
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7797
{
7798
#if defined(TARGET_PPC64)
7799 7800
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7801
    gen_qemu_st32(ctx, t0, addr);
7802 7803
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7804
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7805
#endif
A
aurel32 已提交
7806 7807
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7808 7809
}

B
Blue Swirl 已提交
7810
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7811 7812 7813 7814 7815 7816 7817
{
    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 已提交
7818 7819
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7820 7821
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7822
    gen_qemu_st16(ctx, t0, addr);
7823
#else
A
aurel32 已提交
7824
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7825
#endif
A
aurel32 已提交
7826
    gen_addr_add(ctx, addr, addr, 2);
7827
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7828
    gen_qemu_st16(ctx, t0, addr);
7829
    tcg_temp_free(t0);
A
aurel32 已提交
7830 7831
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7832 7833
}

B
Blue Swirl 已提交
7834
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7835 7836 7837 7838 7839 7840 7841
{
    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 已提交
7842 7843
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7844
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7845
    gen_qemu_st16(ctx, t0, addr);
7846 7847 7848
    tcg_temp_free(t0);
}

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

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

B
Blue Swirl 已提交
7875
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7876
{
A
aurel32 已提交
7877
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7878 7879 7880
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7881
static void glue(gen_, name)(DisasContext *ctx)                                       \
7882 7883 7884
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7885
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7886 7887
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7888
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7889 7890
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7891
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7892
    } else {                                                                  \
A
aurel32 已提交
7893
        gen_addr_reg_index(ctx, t0);                                          \
7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917
    }                                                                         \
    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);
7918 7919 7920

/* Multiply and add - TODO */
#if 0
7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 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
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);
7989 7990 7991
#endif

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

8184 8185
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8186 8187 8188 8189
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 已提交
8190
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8191 8192
{
    if (unlikely(!ctx->spe_enabled)) {
8193
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8194 8195 8196
        return;
    }
#if defined(TARGET_PPC64)
8197
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8198
#else
8199 8200
    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 已提交
8201 8202
#endif
}
B
Blue Swirl 已提交
8203
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8204 8205
{
    if (unlikely(!ctx->spe_enabled)) {
8206
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8207 8208 8209
        return;
    }
#if defined(TARGET_PPC64)
8210
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8211
#else
8212 8213
    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 已提交
8214 8215
#endif
}
B
Blue Swirl 已提交
8216
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8217 8218
{
    if (unlikely(!ctx->spe_enabled)) {
8219
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8220 8221 8222
        return;
    }
#if defined(TARGET_PPC64)
8223
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8224
#else
8225 8226
    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 已提交
8227 8228 8229
#endif
}

8230
/* Conversion */
A
aurel32 已提交
8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241
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);

8242
/* Comparison */
A
aurel32 已提交
8243 8244 8245 8246 8247 8248
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);
8249 8250

/* Opcodes definitions */
8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264
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); //
8265 8266 8267

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8268 8269 8270 8271
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 已提交
8272
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8273 8274
{
    if (unlikely(!ctx->spe_enabled)) {
8275
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8276 8277
        return;
    }
8278
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8279
}
B
Blue Swirl 已提交
8280
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8281 8282
{
    if (unlikely(!ctx->spe_enabled)) {
8283
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8284 8285
        return;
    }
8286
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8287
}
B
Blue Swirl 已提交
8288
static inline void gen_efsneg(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_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8295 8296
}

8297
/* Conversion */
A
aurel32 已提交
8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309
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);

8310
/* Comparison */
A
aurel32 已提交
8311 8312 8313 8314 8315 8316
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);
8317 8318

/* Opcodes definitions */
8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332
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); //
8333 8334 8335

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8336 8337 8338 8339
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 已提交
8340
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8341 8342
{
    if (unlikely(!ctx->spe_enabled)) {
8343
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8344 8345 8346
        return;
    }
#if defined(TARGET_PPC64)
8347
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8348
#else
8349 8350
    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 已提交
8351 8352
#endif
}
B
Blue Swirl 已提交
8353
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8354 8355
{
    if (unlikely(!ctx->spe_enabled)) {
8356
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8357 8358 8359
        return;
    }
#if defined(TARGET_PPC64)
8360
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8361
#else
8362 8363
    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 已提交
8364 8365
#endif
}
B
Blue Swirl 已提交
8366
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8367 8368
{
    if (unlikely(!ctx->spe_enabled)) {
8369
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8370 8371 8372
        return;
    }
#if defined(TARGET_PPC64)
8373
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8374
#else
8375 8376
    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 已提交
8377 8378 8379
#endif
}

8380
/* Conversion */
A
aurel32 已提交
8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395
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);
8396 8397

/* Comparison */
A
aurel32 已提交
8398 8399 8400 8401 8402 8403
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);
8404 8405

/* Opcodes definitions */
8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421
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); //
8422

A
Anthony Liguori 已提交
8423
static opcode_t opcodes[] = {
8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454
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),
8455
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8456
#if defined(TARGET_PPC64)
8457
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 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
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),
8499
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8500 8501
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8502
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539
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 已提交
8540
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556
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),
8557 8558 8559
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),
8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 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
#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 已提交
8640
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8641 8642 8643 8644 8645 8646 8647 8648
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 已提交
8649 8650 8651 8652 8653 8654 8655 8656
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 已提交
8657 8658
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8659 8660
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8661 8662
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8663
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8664
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8665
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8666 8667
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8668
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8669 8670
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 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
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
8843
#undef GEN_LDX_E
8844 8845 8846 8847 8848 8849 8850
#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),
8851 8852
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867
#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)
8868
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
8869 8870 8871 8872 8873 8874 8875
#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
8876
#undef GEN_STX_E
8877 8878 8879 8880 8881 8882 8883
#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),
8884 8885
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897
#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)
8898
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 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
#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),
9167
GEN_VXFORM_NOA(vexptefp, 5, 6),
9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195
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
9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 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
#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),
9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298

#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),
};

9299
#include "helper_regs.h"
A
Andreas Färber 已提交
9300
#include "translate_init.c"
B
bellard 已提交
9301

9302
/*****************************************************************************/
9303
/* Misc PowerPC helpers */
9304
void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
9305
                     int flags)
B
bellard 已提交
9306
{
9307 9308 9309
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9310 9311
    int i;

9312 9313
    cpu_synchronize_state(env);

9314
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9315
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9316
                env->nip, env->lr, env->ctr, cpu_read_xer(env));
9317 9318 9319
    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);
9320
#if !defined(NO_TIMER_DUMP)
9321
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9322
#if !defined(CONFIG_USER_ONLY)
9323
                " DECR %08" PRIu32
9324 9325
#endif
                "\n",
J
j_mayer 已提交
9326
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9327 9328 9329 9330
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9331
#endif
9332
    for (i = 0; i < 32; i++) {
9333 9334
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9335
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9336
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9337
            cpu_fprintf(f, "\n");
9338
    }
9339
    cpu_fprintf(f, "CR ");
9340
    for (i = 0; i < 8; i++)
B
bellard 已提交
9341 9342
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9343 9344 9345 9346 9347 9348 9349 9350
    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 已提交
9351
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9352
    }
9353 9354
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9355 9356 9357
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9358
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9359
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9360
            cpu_fprintf(f, "\n");
B
bellard 已提交
9361
    }
9362
    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
9363
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 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
    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 已提交
9412 9413 9414 9415 9416 9417
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9418 9419 9420 9421 9422 9423 9424 9425 9426 9427
    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 已提交
9428
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446
        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;
    }
9447
#endif
B
bellard 已提交
9448

9449 9450
#undef RGPL
#undef RFPL
B
bellard 已提交
9451 9452
}

9453
void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
9454 9455 9456
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9457
    opc_handler_t **t1, **t2, **t3, *handler;
9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473
    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 已提交
9474
                                    "%016" PRIx64 " %" PRId64 "\n",
9475 9476 9477 9478 9479 9480 9481 9482
                                    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 已提交
9483
                                "%016" PRIx64 " %" PRId64 "\n",
9484 9485 9486 9487 9488 9489 9490
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9491 9492
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9493 9494 9495 9496 9497 9498 9499
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9500
/*****************************************************************************/
9501
static inline void gen_intermediate_code_internal(CPUPPCState *env,
B
Blue Swirl 已提交
9502 9503
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9504
{
9505
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9506
    opc_handler_t **table, *handler;
B
bellard 已提交
9507
    target_ulong pc_start;
B
bellard 已提交
9508
    uint16_t *gen_opc_end;
9509
    CPUBreakpoint *bp;
B
bellard 已提交
9510
    int j, lj = -1;
P
pbrook 已提交
9511 9512
    int num_insns;
    int max_insns;
B
bellard 已提交
9513 9514

    pc_start = tb->pc;
9515
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9516
    ctx.nip = pc_start;
B
bellard 已提交
9517
    ctx.tb = tb;
9518
    ctx.exception = POWERPC_EXCP_NONE;
9519
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9520 9521 9522
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9523
#if defined(TARGET_PPC64)
A
Alexander Graf 已提交
9524
    ctx.sf_mode = msr_is_64bit(env, env->msr);
D
David Gibson 已提交
9525
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9526
#endif
B
bellard 已提交
9527
    ctx.fpu_enabled = msr_fp;
9528
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9529 9530 9531
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9532 9533 9534 9535
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9536
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9537
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9538
    else
9539
        ctx.singlestep_enabled = 0;
9540
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9541 9542 9543
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9544
#if defined (DO_SINGLE_STEP) && 0
9545 9546 9547
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9548 9549 9550 9551 9552
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

9553
    gen_tb_start();
9554
    /* Set env in case of segfault during code fetch */
9555 9556
    while (ctx.exception == POWERPC_EXCP_NONE
            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9557 9558
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9559
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9560
                    gen_debug_exception(ctxp);
9561 9562 9563 9564
                    break;
                }
            }
        }
9565
        if (unlikely(search_pc)) {
9566
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
B
bellard 已提交
9567 9568 9569
            if (lj < j) {
                lj++;
                while (lj < j)
9570
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
9571
            }
9572
            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
9573
            tcg_ctx.gen_opc_instr_start[lj] = 1;
9574
            tcg_ctx.gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9575
        }
9576
        LOG_DISAS("----------------\n");
9577
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9578
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9579 9580
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9581
        if (unlikely(ctx.le_mode)) {
9582
            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
9583
        } else {
9584
            ctx.opcode = cpu_ldl_code(env, ctx.nip);
9585
        }
9586
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9587
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9588
                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
9589
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9590
            tcg_gen_debug_insn_start(ctx.nip);
9591
        }
B
bellard 已提交
9592
        ctx.nip += 4;
9593
        table = env->opcodes;
P
pbrook 已提交
9594
        num_insns++;
B
bellard 已提交
9595 9596 9597 9598 9599 9600 9601 9602 9603 9604
        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 ? */
9605
        if (unlikely(handler->handler == &gen_invalid)) {
9606 9607
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9608 9609 9610
                         "%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 已提交
9611
            }
9612
        } else {
9613 9614 9615 9616 9617 9618 9619 9620 9621
            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)) {
9622 9623
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9624
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9625
                             ctx.opcode & inval, opc1(ctx.opcode),
9626 9627
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9628
                }
A
aurel32 已提交
9629
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9630
                break;
B
bellard 已提交
9631 9632
            }
        }
B
bellard 已提交
9633
        (*(handler->handler))(&ctx);
9634 9635 9636
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9637
        /* Check trace mode exceptions */
9638 9639 9640 9641 9642
        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 已提交
9643
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9644
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9645
                            (env->singlestep_enabled) ||
9646
                            singlestep ||
P
pbrook 已提交
9647
                            num_insns >= max_insns)) {
9648 9649 9650
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9651
            break;
9652
        }
9653
    }
P
pbrook 已提交
9654 9655
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9656
    if (ctx.exception == POWERPC_EXCP_NONE) {
9657
        gen_goto_tb(&ctx, 0, ctx.nip);
9658
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9659
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9660
            gen_debug_exception(ctxp);
9661
        }
9662
        /* Generate the return instruction */
B
bellard 已提交
9663
        tcg_gen_exit_tb(0);
9664
    }
9665
    gen_tb_end(tb, num_insns);
9666
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
9667
    if (unlikely(search_pc)) {
9668
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9669 9670
        lj++;
        while (lj <= j)
9671
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
9672
    } else {
B
bellard 已提交
9673
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9674
        tb->icount = num_insns;
9675
    }
9676
#if defined(DEBUG_DISAS)
9677
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9678
        int flags;
9679
        flags = env->bfd_mach;
A
aurel32 已提交
9680
        flags |= ctx.le_mode << 16;
9681
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
9682
        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
9683
        qemu_log("\n");
9684
    }
B
bellard 已提交
9685 9686 9687
#endif
}

9688
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9689
{
9690
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9691 9692
}

9693
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9694
{
9695
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9696
}
A
aurel32 已提交
9697

9698
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9699
{
9700
    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
9701
}