translate.c 359.9 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
S
Scott Wood 已提交
5
 *  Copyright (C) 2011 Freescale Semiconductor, Inc.
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
19
 */
B
bellard 已提交
20

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
Blue Swirl 已提交
226
static inline void gen_reset_fpstatus(void)
227
{
228
    gen_helper_reset_fpstatus(cpu_env);
229 230
}

B
Blue Swirl 已提交
231
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
232
{
233
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
234

235 236
    if (set_fprf != 0) {
        /* This case might be optimized later */
237
        tcg_gen_movi_i32(t0, 1);
238
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
P
pbrook 已提交
239
        if (unlikely(set_rc)) {
240
            tcg_gen_mov_i32(cpu_crf[1], t0);
P
pbrook 已提交
241
        }
242
        gen_helper_float_check_status(cpu_env);
243 244
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
245
        tcg_gen_movi_i32(t0, 0);
246
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
247
        tcg_gen_mov_i32(cpu_crf[1], t0);
248
    }
A
aurel32 已提交
249

250
    tcg_temp_free_i32(t0);
251 252
}

B
Blue Swirl 已提交
253
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
254
{
A
aurel32 已提交
255 256 257 258
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
259 260
}

B
Blue Swirl 已提交
261
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
262 263 264
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
265
        tcg_gen_movi_tl(cpu_nip, nip);
266 267
    else
#endif
A
aurel32 已提交
268
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
269 270
}

B
Blue Swirl 已提交
271
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
272 273 274 275 276 277 278
{
    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);
279
    gen_helper_raise_exception_err(cpu_env, t0, t1);
A
aurel32 已提交
280 281 282 283
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
284

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

B
Blue Swirl 已提交
297
static inline void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
298 299
{
    TCGv_i32 t0;
B
blueswir1 已提交
300

301 302
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
B
blueswir1 已提交
303
        gen_update_nip(ctx, ctx->nip);
304
    }
A
aurel32 已提交
305
    t0 = tcg_const_i32(EXCP_DEBUG);
306
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
307 308
    tcg_temp_free_i32(t0);
}
309

B
Blue Swirl 已提交
310
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
311 312 313
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
314

315
/* Stop translation */
B
Blue Swirl 已提交
316
static inline void gen_stop_exception(DisasContext *ctx)
317
{
318
    gen_update_nip(ctx, ctx->nip);
319
    ctx->exception = POWERPC_EXCP_STOP;
320 321
}

322
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
323
static inline void gen_sync_exception(DisasContext *ctx)
324
{
325
    ctx->exception = POWERPC_EXCP_SYNC;
326 327
}

B
bellard 已提交
328
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
329 330 331 332
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 已提交
333

334
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
335 336 337 338
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)
339

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

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

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

/* 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 */
390
EXTRACT_HELPER(_SPR, 11, 10);
B
Blue Swirl 已提交
391
static inline uint32_t SPR(uint32_t opcode)
392 393 394 395 396
{
    uint32_t sprn = _SPR(opcode);

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

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

B
bellard 已提交
425 426 427 428
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
B
Blue Swirl 已提交
429
static inline target_ulong LI(uint32_t opcode)
B
bellard 已提交
430 431 432 433
{
    return (opcode >> 0) & 0x03FFFFFC;
}

B
Blue Swirl 已提交
434
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
435 436 437 438 439 440 441 442 443 444 445 446
{
    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 已提交
447
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
448
{
449
    target_ulong ret;
B
bellard 已提交
450

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

    return ret;
}

474 475
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
476

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

570
/* SPR load/store helpers */
B
Blue Swirl 已提交
571
static inline void gen_load_spr(TCGv t, int reg)
572
{
573
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
574
}
575

B
Blue Swirl 已提交
576
static inline void gen_store_spr(int reg, TCGv t)
577
{
578
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
579
}
580

581
/* Invalid instruction */
B
Blue Swirl 已提交
582
static void gen_invalid(DisasContext *ctx)
583
{
A
aurel32 已提交
584
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
585 586
}

A
Anthony Liguori 已提交
587
static opc_handler_t invalid_handler = {
588 589
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
590
    .type    = PPC_NONE,
591
    .type2   = PPC_NONE,
B
bellard 已提交
592 593 594
    .handler = gen_invalid,
};

595 596
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
597
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
598 599 600
{
    int l1, l2, l3;

601
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
602 603 604 605 606

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
607 608
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
609
    } else {
610 611
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
612 613 614 615 616 617 618 619 620 621 622
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

B
Blue Swirl 已提交
623
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
624
{
625 626 627
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
628 629 630
}

#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
631
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
632
{
633
    TCGv t0, t1;
P
pbrook 已提交
634 635
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
636
    if (s) {
637 638
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
639
    } else {
640 641
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
642
    }
643 644 645
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
646 647
}

B
Blue Swirl 已提交
648
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
649
{
650 651 652
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
653 654 655
}
#endif

B
Blue Swirl 已提交
656
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
657 658 659 660 661 662 663 664 665 666
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode))
        gen_op_cmpi32(reg, 0, 1, 0);
    else
#endif
        gen_op_cmpi(reg, 0, 1, 0);
}

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

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

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

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

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

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

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

B
bellard 已提交
744 745
/***                           Integer arithmetic                          ***/

B
Blue Swirl 已提交
746 747
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
748 749 750
{
    int l1;
    TCGv t0;
B
bellard 已提交
751

752 753
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
754
    tcg_gen_movi_tl(cpu_ov, 0);
P
pbrook 已提交
755
    t0 = tcg_temp_local_new();
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
    tcg_gen_xor_tl(t0, arg0, arg1);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    tcg_gen_xor_tl(t0, arg1, arg2);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
774 775
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
776 777
    gen_set_label(l1);
    tcg_temp_free(t0);
B
bellard 已提交
778 779
}

B
Blue Swirl 已提交
780 781
static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
                                           TCGv arg2, int sub)
782 783
{
    int l1 = gen_new_label();
784 785

#if defined(TARGET_PPC64)
786 787
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
P
pbrook 已提交
788 789
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
790

791 792 793 794
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_ext32u_tl(t1, arg2);
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
A
aurel32 已提交
795
        } else {
796 797
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
798
        tcg_gen_movi_tl(cpu_ca, 1);
799 800 801
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
802 803
    } else
#endif
804 805 806 807 808 809
    {
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
        } else {
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
        }
810
        tcg_gen_movi_tl(cpu_ca, 1);
811
        gen_set_label(l1);
812
    }
813 814
}

815
/* Common add function */
B
Blue Swirl 已提交
816 817 818
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    TCGv arg2, int add_ca, int compute_ca,
                                    int compute_ov)
819 820
{
    TCGv t0, t1;
821

822
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
823
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
824 825
        t0 = ret;
    } else {
P
pbrook 已提交
826
        t0 = tcg_temp_local_new();
827
    }
B
bellard 已提交
828

829
    if (add_ca) {
P
pbrook 已提交
830
        t1 = tcg_temp_local_new();
831
        tcg_gen_mov_tl(t1, cpu_ca);
832 833
    } else {
        TCGV_UNUSED(t1);
834
    }
B
bellard 已提交
835

836
    if (compute_ca) {
837
        /* Start with XER CA disabled, the most likely case */
838 839 840
        tcg_gen_movi_tl(cpu_ca, 0);
    }
    if (compute_ov) {
841
        /* Start with XER OV disabled, the most likely case */
842
        tcg_gen_movi_tl(cpu_ov, 0);
843
    }
B
bellard 已提交
844

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
    tcg_gen_add_tl(t0, arg1, arg2);

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

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

P
pbrook 已提交
862
    if (!TCGV_EQUAL(t0, ret)) {
863 864 865
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
866
}
867 868
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
B
Blue Swirl 已提交
869
static void glue(gen_, name)(DisasContext *ctx)                                       \
870 871 872 873 874 875 876 877
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     add_ca, compute_ca, compute_ov);                         \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
B
Blue Swirl 已提交
878
static void glue(gen_, name)(DisasContext *ctx)                                       \
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
                     add_ca, compute_ca, compute_ov);                         \
    tcg_temp_free(t0);                                                        \
}

/* add  add.  addo  addo. */
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
/* addc  addc.  addco  addco. */
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
/* adde  adde.  addeo  addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
/* addme  addme.  addmeo  addmeo.  */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
/* addze  addze.  addzeo  addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
/* addi */
B
Blue Swirl 已提交
903
static void gen_addi(DisasContext *ctx)
904
{
905 906 907 908 909 910 911 912
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
    }
913
}
914
/* addic  addic.*/
B
Blue Swirl 已提交
915 916
static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
                                int compute_Rc0)
917
{
918 919
    target_long simm = SIMM(ctx->opcode);

920 921
    /* Start with XER CA disabled, the most likely case */
    tcg_gen_movi_tl(cpu_ca, 0);
922 923

    if (likely(simm != 0)) {
P
pbrook 已提交
924
        TCGv t0 = tcg_temp_local_new();
925 926 927 928 929 930 931 932 933 934
        tcg_gen_addi_tl(t0, arg1, simm);
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    } else {
        tcg_gen_mov_tl(ret, arg1);
    }
    if (compute_Rc0) {
        gen_set_Rc0(ctx, ret);
    }
935
}
B
Blue Swirl 已提交
936 937

static void gen_addic(DisasContext *ctx)
938
{
939
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
940
}
B
Blue Swirl 已提交
941 942

static void gen_addic_(DisasContext *ctx)
943
{
944
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
945
}
B
Blue Swirl 已提交
946

947
/* addis */
B
Blue Swirl 已提交
948
static void gen_addis(DisasContext *ctx)
949
{
950 951 952 953 954 955 956 957
    target_long simm = SIMM(ctx->opcode);

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

B
Blue Swirl 已提交
960 961
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
962
{
963 964
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
965 966
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
967

968 969 970
    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
971
    if (sign) {
972 973 974
        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);
975
        gen_set_label(l3);
976
        tcg_gen_div_i32(t0, t0, t1);
977
    } else {
978
        tcg_gen_divu_i32(t0, t0, t1);
979 980
    }
    if (compute_ov) {
981
        tcg_gen_movi_tl(cpu_ov, 0);
982 983 984 985
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
986
        tcg_gen_sari_i32(t0, t0, 31);
987 988 989 990
    } else {
        tcg_gen_movi_i32(t0, 0);
    }
    if (compute_ov) {
991 992
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
993 994
    }
    gen_set_label(l2);
995
    tcg_gen_extu_i32_tl(ret, t0);
P
pbrook 已提交
996 997
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
998 999
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1000
}
1001 1002
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
1003
static void glue(gen_, name)(DisasContext *ctx)                                       \
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
{                                                                             \
    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);
1015
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
1016 1017
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
1018
{
1019 1020
    int l1 = gen_new_label();
    int l2 = gen_new_label();
1021 1022 1023

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
1024
        int l3 = gen_new_label();
1025 1026 1027 1028 1029 1030 1031 1032
        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) {
1033
        tcg_gen_movi_tl(cpu_ov, 0);
1034 1035 1036 1037 1038 1039 1040 1041 1042
    }
    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) {
1043 1044
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
1045 1046 1047 1048
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1049
}
1050
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
1051
static void glue(gen_, name)(DisasContext *ctx)                                       \
1052
{                                                                             \
1053 1054 1055
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1056 1057 1058 1059 1060 1061 1062
}
/* 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);
1063
#endif
1064 1065

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1066
static void gen_mulhw(DisasContext *ctx)
1067
{
1068 1069
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1070

1071 1072 1073 1074 1075 1076
    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);
1077 1078
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1079
}
B
Blue Swirl 已提交
1080

1081
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1082
static void gen_mulhwu(DisasContext *ctx)
1083
{
1084 1085
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1086

1087 1088 1089 1090 1091 1092
    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);
1093 1094
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1095
}
B
Blue Swirl 已提交
1096

1097
/* mullw  mullw. */
B
Blue Swirl 已提交
1098
static void gen_mullw(DisasContext *ctx)
1099
{
1100 1101
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1102
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1103 1104
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1105
}
B
Blue Swirl 已提交
1106

1107
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1108
static void gen_mullwo(DisasContext *ctx)
1109
{
1110
    int l1;
P
pbrook 已提交
1111
    TCGv_i64 t0, t1;
1112

P
pbrook 已提交
1113 1114
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1115 1116
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
1117
    tcg_gen_movi_tl(cpu_ov, 0);
1118 1119 1120 1121 1122 1123
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1124
#endif
1125 1126 1127 1128 1129 1130 1131 1132 1133
    tcg_gen_mul_i64(t0, t0, t1);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
#else
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
#endif
1134 1135
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
1136
    gen_set_label(l1);
P
pbrook 已提交
1137 1138
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1139 1140
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1141
}
B
Blue Swirl 已提交
1142

1143
/* mulli */
B
Blue Swirl 已提交
1144
static void gen_mulli(DisasContext *ctx)
1145
{
1146 1147
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1148
}
1149

1150
#if defined(TARGET_PPC64)
1151
/* mulhd  mulhd. */
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
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)]);
    }
}

1163
/* mulhdu  mulhdu. */
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
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 已提交
1174

1175
/* mulld  mulld. */
B
Blue Swirl 已提交
1176
static void gen_mulld(DisasContext *ctx)
1177
{
1178 1179 1180 1181
    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)]);
1182
}
1183

1184
/* mulldo  mulldo. */
1185 1186 1187 1188 1189 1190 1191 1192
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)]);
    }
}
1193
#endif
1194 1195

/* neg neg. nego nego. */
B
Blue Swirl 已提交
1196 1197
static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    int ov_check)
1198
{
A
aurel32 已提交
1199 1200
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1201
    TCGv t0 = tcg_temp_local_new();
1202
#if defined(TARGET_PPC64)
1203
    if (ctx->sf_mode) {
A
aurel32 已提交
1204
        tcg_gen_mov_tl(t0, arg1);
A
aurel32 已提交
1205 1206 1207 1208 1209
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
    } else
#endif
    {
        tcg_gen_ext32s_tl(t0, arg1);
1210 1211 1212 1213
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
    }
    tcg_gen_neg_tl(ret, arg1);
    if (ov_check) {
1214
        tcg_gen_movi_tl(cpu_ov, 0);
1215 1216 1217
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
A
aurel32 已提交
1218
    tcg_gen_mov_tl(ret, t0);
1219
    if (ov_check) {
1220 1221
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
1222 1223
    }
    gen_set_label(l2);
A
aurel32 已提交
1224
    tcg_temp_free(t0);
1225 1226 1227
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
}
B
Blue Swirl 已提交
1228 1229

static void gen_neg(DisasContext *ctx)
1230
{
A
aurel32 已提交
1231
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1232
}
B
Blue Swirl 已提交
1233 1234

static void gen_nego(DisasContext *ctx)
B
bellard 已提交
1235
{
A
aurel32 已提交
1236
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
B
bellard 已提交
1237
}
1238 1239

/* Common subf function */
B
Blue Swirl 已提交
1240 1241 1242
static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int add_ca, int compute_ca,
                                     int compute_ov)
B
bellard 已提交
1243
{
1244
    TCGv t0, t1;
1245

1246
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
1247
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1248
        t0 = ret;
J
j_mayer 已提交
1249
    } else {
P
pbrook 已提交
1250
        t0 = tcg_temp_local_new();
1251
    }
1252

1253
    if (add_ca) {
P
pbrook 已提交
1254
        t1 = tcg_temp_local_new();
1255
        tcg_gen_mov_tl(t1, cpu_ca);
1256 1257
    } else {
        TCGV_UNUSED(t1);
1258
    }
B
bellard 已提交
1259

1260
    if (compute_ca) {
1261
        /* Start with XER CA disabled, the most likely case */
1262 1263 1264
        tcg_gen_movi_tl(cpu_ca, 0);
    }
    if (compute_ov) {
1265
        /* Start with XER OV disabled, the most likely case */
1266
        tcg_gen_movi_tl(cpu_ov, 0);
1267 1268 1269 1270 1271 1272 1273 1274 1275
    }

    if (add_ca) {
        tcg_gen_not_tl(t0, arg1);
        tcg_gen_add_tl(t0, t0, arg2);
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
B
bellard 已提交
1276
    } else {
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
        tcg_gen_sub_tl(t0, arg2, arg1);
        if (compute_ca) {
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
        }
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }

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

P
pbrook 已提交
1289
    if (!TCGV_EQUAL(t0, ret)) {
1290 1291
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1292 1293
    }
}
1294 1295
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
B
Blue Swirl 已提交
1296
static void glue(gen_, name)(DisasContext *ctx)                                       \
1297 1298 1299 1300 1301 1302 1303 1304
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      add_ca, compute_ca, compute_ov);                        \
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
B
Blue Swirl 已提交
1305
static void glue(gen_, name)(DisasContext *ctx)                                       \
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
                      add_ca, compute_ca, compute_ov);                        \
    tcg_temp_free(t0);                                                        \
}
/* subf  subf.  subfo  subfo. */
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
/* subfc  subfc.  subfco  subfco. */
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
/* subfe  subfe.  subfeo  subfo. */
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
/* subfme  subfme.  subfmeo  subfmeo.  */
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
/* subfze  subfze.  subfzeo  subfzeo.*/
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
B
Blue Swirl 已提交
1328

1329
/* subfic */
B
Blue Swirl 已提交
1330
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1331
{
1332 1333
    /* Start with XER CA disabled, the most likely case */
    tcg_gen_movi_tl(cpu_ca, 0);
P
pbrook 已提交
1334
    TCGv t0 = tcg_temp_local_new();
1335 1336 1337 1338 1339 1340
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
    tcg_temp_free(t1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
B
bellard 已提交
1341 1342 1343
}

/***                            Integer logical                            ***/
1344
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1345
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1346
{                                                                             \
1347 1348
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1349
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1350
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1351 1352
}

1353
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1354
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1355
{                                                                             \
1356
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1357
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1358
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1359 1360 1361
}

/* and & and. */
1362
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1363
/* andc & andc. */
1364
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1365

1366
/* andi. */
B
Blue Swirl 已提交
1367
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1368
{
1369 1370
    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 已提交
1371
}
B
Blue Swirl 已提交
1372

1373
/* andis. */
B
Blue Swirl 已提交
1374
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1375
{
1376 1377
    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 已提交
1378
}
B
Blue Swirl 已提交
1379

1380
/* cntlzw */
B
Blue Swirl 已提交
1381
static void gen_cntlzw(DisasContext *ctx)
1382
{
P
pbrook 已提交
1383
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1384
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1385
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1386
}
B
bellard 已提交
1387
/* eqv & eqv. */
1388
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1389
/* extsb & extsb. */
1390
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1391
/* extsh & extsh. */
1392
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1393
/* nand & nand. */
1394
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1395
/* nor & nor. */
1396
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
Blue Swirl 已提交
1397

1398
/* or & or. */
B
Blue Swirl 已提交
1399
static void gen_or(DisasContext *ctx)
1400
{
1401 1402 1403 1404 1405 1406 1407
    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) {
1408 1409 1410 1411
        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]);
1412
        if (unlikely(Rc(ctx->opcode) != 0))
1413
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1414
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1415
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1416 1417
#if defined(TARGET_PPC64)
    } else {
1418 1419
        int prio = 0;

1420 1421 1422
        switch (rs) {
        case 1:
            /* Set process priority to low */
1423
            prio = 2;
1424 1425 1426
            break;
        case 6:
            /* Set process priority to medium-low */
1427
            prio = 3;
1428 1429 1430
            break;
        case 2:
            /* Set process priority to normal */
1431
            prio = 4;
1432
            break;
1433 1434
#if !defined(CONFIG_USER_ONLY)
        case 31:
A
aurel32 已提交
1435
            if (ctx->mem_idx > 0) {
1436
                /* Set process priority to very low */
1437
                prio = 1;
1438 1439 1440
            }
            break;
        case 5:
A
aurel32 已提交
1441
            if (ctx->mem_idx > 0) {
1442
                /* Set process priority to medium-hight */
1443
                prio = 5;
1444 1445 1446
            }
            break;
        case 3:
A
aurel32 已提交
1447
            if (ctx->mem_idx > 0) {
1448
                /* Set process priority to high */
1449
                prio = 6;
1450 1451 1452
            }
            break;
        case 7:
A
aurel32 已提交
1453
            if (ctx->mem_idx > 1) {
1454
                /* Set process priority to very high */
1455
                prio = 7;
1456 1457 1458
            }
            break;
#endif
1459 1460 1461 1462
        default:
            /* nop */
            break;
        }
1463
        if (prio) {
P
pbrook 已提交
1464
            TCGv t0 = tcg_temp_new();
1465
            gen_load_spr(t0, SPR_PPR);
1466 1467
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1468
            gen_store_spr(SPR_PPR, t0);
1469
            tcg_temp_free(t0);
1470
        }
1471
#endif
1472 1473
    }
}
B
bellard 已提交
1474
/* orc & orc. */
1475
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
Blue Swirl 已提交
1476

1477
/* xor & xor. */
B
Blue Swirl 已提交
1478
static void gen_xor(DisasContext *ctx)
1479 1480
{
    /* Optimisation for "set to zero" case */
1481
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1482
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1483 1484
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1485
    if (unlikely(Rc(ctx->opcode) != 0))
1486
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1487
}
B
Blue Swirl 已提交
1488

1489
/* ori */
B
Blue Swirl 已提交
1490
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1491
{
1492
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1493

1494 1495
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1496
        /* XXX: should handle special NOPs for POWER series */
1497
        return;
1498
    }
1499
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1500
}
B
Blue Swirl 已提交
1501

1502
/* oris */
B
Blue Swirl 已提交
1503
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1504
{
1505
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1506

1507 1508 1509
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1510
    }
1511
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1512
}
B
Blue Swirl 已提交
1513

1514
/* xori */
B
Blue Swirl 已提交
1515
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1516
{
1517
    target_ulong uimm = UIMM(ctx->opcode);
1518 1519 1520 1521 1522

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

1526
/* xoris */
B
Blue Swirl 已提交
1527
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1528
{
1529
    target_ulong uimm = UIMM(ctx->opcode);
1530 1531 1532 1533 1534

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

1538
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1539
static void gen_popcntb(DisasContext *ctx)
1540
{
1541 1542 1543 1544 1545 1546 1547 1548
    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)]);
}

1549
#if defined(TARGET_PPC64)
1550 1551 1552 1553
/* popcntd: PowerPC 2.06 specification */
static void gen_popcntd(DisasContext *ctx)
{
    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1554
}
1555
#endif
1556 1557 1558

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

1561
/* cntlzd */
B
Blue Swirl 已提交
1562
static void gen_cntlzd(DisasContext *ctx)
1563
{
P
pbrook 已提交
1564
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1565 1566 1567
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1568 1569
#endif

B
bellard 已提交
1570
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1571

1572
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1573
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1574
{
1575
    uint32_t mb, me, sh;
B
bellard 已提交
1576 1577 1578

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1579
    sh = SH(ctx->opcode);
1580 1581 1582 1583
    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 已提交
1584 1585
        TCGv t1;
        TCGv t0 = tcg_temp_new();
1586
#if defined(TARGET_PPC64)
P
pbrook 已提交
1587 1588 1589 1590 1591
        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);
1592 1593 1594
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1595
#if defined(TARGET_PPC64)
1596 1597
        mb += 32;
        me += 32;
1598
#endif
1599
        mask = MASK(mb, me);
P
pbrook 已提交
1600
        t1 = tcg_temp_new();
1601 1602 1603 1604 1605 1606
        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);
    }
1607
    if (unlikely(Rc(ctx->opcode) != 0))
1608
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1609
}
B
Blue Swirl 已提交
1610

1611
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1612
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1613 1614
{
    uint32_t mb, me, sh;
1615

B
bellard 已提交
1616 1617 1618
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1619 1620 1621 1622 1623

    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 已提交
1624
            TCGv t0 = tcg_temp_new();
1625 1626 1627 1628
            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 已提交
1629
        }
1630
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
P
pbrook 已提交
1631
        TCGv t0 = tcg_temp_new();
1632 1633 1634 1635 1636
        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 已提交
1637
        TCGv t0 = tcg_temp_new();
1638
#if defined(TARGET_PPC64)
P
pbrook 已提交
1639
        TCGv_i32 t1 = tcg_temp_new_i32();
1640 1641 1642
        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 已提交
1643
        tcg_temp_free_i32(t1);
1644 1645 1646
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1647
#if defined(TARGET_PPC64)
1648 1649
        mb += 32;
        me += 32;
1650
#endif
1651 1652 1653
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
        tcg_temp_free(t0);
    }
1654
    if (unlikely(Rc(ctx->opcode) != 0))
1655
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1656
}
B
Blue Swirl 已提交
1657

1658
/* rlwnm & rlwnm. */
B
Blue Swirl 已提交
1659
static void gen_rlwnm(DisasContext *ctx)
B
bellard 已提交
1660 1661
{
    uint32_t mb, me;
1662 1663
    TCGv t0;
#if defined(TARGET_PPC64)
P
pbrook 已提交
1664
    TCGv_i32 t1, t2;
1665
#endif
B
bellard 已提交
1666 1667 1668

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1669
    t0 = tcg_temp_new();
1670
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1671
#if defined(TARGET_PPC64)
P
pbrook 已提交
1672 1673
    t1 = tcg_temp_new_i32();
    t2 = tcg_temp_new_i32();
1674 1675 1676 1677
    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 已提交
1678 1679
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
1680 1681 1682
#else
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
1683 1684 1685 1686 1687
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1688
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1689
    } else {
1690
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
B
bellard 已提交
1691
    }
1692
    tcg_temp_free(t0);
1693
    if (unlikely(Rc(ctx->opcode) != 0))
1694
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1695 1696
}

1697 1698
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1699
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1700 1701 1702
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
B
Blue Swirl 已提交
1703 1704
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1705 1706 1707 1708
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1709
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1710 1711 1712
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1713 1714
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1715 1716 1717
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1718 1719
                                                                              \
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1720 1721 1722
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1723 1724
                                                                              \
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1725 1726 1727
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1728

B
Blue Swirl 已提交
1729 1730
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
                              uint32_t sh)
J
j_mayer 已提交
1731
{
1732 1733 1734 1735 1736
    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 已提交
1737
        TCGv t0 = tcg_temp_new();
1738
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1739
        if (likely(mb == 0 && me == 63)) {
1740
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1741 1742
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1743
        }
1744
        tcg_temp_free(t0);
J
j_mayer 已提交
1745 1746
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1747
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1748
}
1749
/* rldicl - rldicl. */
B
Blue Swirl 已提交
1750
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1751
{
J
j_mayer 已提交
1752
    uint32_t sh, mb;
1753

J
j_mayer 已提交
1754 1755
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1756
    gen_rldinm(ctx, mb, 63, sh);
1757
}
J
j_mayer 已提交
1758
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1759
/* rldicr - rldicr. */
B
Blue Swirl 已提交
1760
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1761
{
J
j_mayer 已提交
1762
    uint32_t sh, me;
1763

J
j_mayer 已提交
1764 1765
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1766
    gen_rldinm(ctx, 0, me, sh);
1767
}
J
j_mayer 已提交
1768
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1769
/* rldic - rldic. */
B
Blue Swirl 已提交
1770
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1771
{
J
j_mayer 已提交
1772
    uint32_t sh, mb;
1773

J
j_mayer 已提交
1774 1775
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1776 1777 1778 1779
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

B
Blue Swirl 已提交
1780
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
J
j_mayer 已提交
1781
{
1782
    TCGv t0;
1783 1784 1785

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1786
    t0 = tcg_temp_new();
1787
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1788
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1789
    if (unlikely(mb != 0 || me != 63)) {
1790 1791 1792 1793 1794
        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 已提交
1795
    if (unlikely(Rc(ctx->opcode) != 0))
1796
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1797
}
J
j_mayer 已提交
1798

1799
/* rldcl - rldcl. */
B
Blue Swirl 已提交
1800
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1801
{
J
j_mayer 已提交
1802
    uint32_t mb;
1803

J
j_mayer 已提交
1804
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1805
    gen_rldnm(ctx, mb, 63);
1806
}
1807
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1808
/* rldcr - rldcr. */
B
Blue Swirl 已提交
1809
static inline void gen_rldcr(DisasContext *ctx, int men)
1810
{
J
j_mayer 已提交
1811
    uint32_t me;
1812

J
j_mayer 已提交
1813
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1814
    gen_rldnm(ctx, 0, me);
1815
}
1816
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1817
/* rldimi - rldimi. */
B
Blue Swirl 已提交
1818
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1819
{
1820
    uint32_t sh, mb, me;
1821

J
j_mayer 已提交
1822 1823
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1824
    me = 63 - sh;
1825 1826 1827 1828 1829 1830
    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 已提交
1831
        t0 = tcg_temp_new();
1832
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1833
        t1 = tcg_temp_new();
1834 1835 1836 1837 1838 1839
        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 已提交
1840 1841
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1842
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1843
}
1844
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1845 1846
#endif

B
bellard 已提交
1847
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1848

1849
/* slw & slw. */
B
Blue Swirl 已提交
1850
static void gen_slw(DisasContext *ctx)
1851
{
1852
    TCGv t0, t1;
1853

1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867
    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);
1868
    tcg_temp_free(t0);
1869
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1870 1871 1872
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1873

1874
/* sraw & sraw. */
B
Blue Swirl 已提交
1875
static void gen_sraw(DisasContext *ctx)
1876
{
1877
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1878
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1879 1880 1881
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1882

1883
/* srawi & srawi. */
B
Blue Swirl 已提交
1884
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
1885
{
1886 1887 1888
    int sh = SH(ctx->opcode);
    if (sh != 0) {
        int l1, l2;
1889
        TCGv t0;
1890 1891
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1892
        t0 = tcg_temp_local_new();
1893 1894 1895 1896
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1897
        tcg_gen_movi_tl(cpu_ca, 1);
1898 1899
        tcg_gen_br(l2);
        gen_set_label(l1);
1900
        tcg_gen_movi_tl(cpu_ca, 0);
1901
        gen_set_label(l2);
1902 1903 1904
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
        tcg_temp_free(t0);
1905 1906
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1907
        tcg_gen_movi_tl(cpu_ca, 0);
1908
    }
1909
    if (unlikely(Rc(ctx->opcode) != 0))
1910
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1911
}
B
Blue Swirl 已提交
1912

1913
/* srw & srw. */
B
Blue Swirl 已提交
1914
static void gen_srw(DisasContext *ctx)
1915
{
1916
    TCGv t0, t1;
1917

1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
    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 已提交
1929
    t1 = tcg_temp_new();
1930 1931
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1932 1933
    tcg_temp_free(t1);
    tcg_temp_free(t0);
1934 1935 1936
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1937

1938 1939
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
1940
static void gen_sld(DisasContext *ctx)
1941
{
1942
    TCGv t0, t1;
1943

1944 1945 1946 1947 1948 1949 1950 1951 1952
    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);
1953
    tcg_temp_free(t0);
1954 1955 1956
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1957

1958
/* srad & srad. */
B
Blue Swirl 已提交
1959
static void gen_srad(DisasContext *ctx)
1960
{
1961
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1962
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1963 1964 1965
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1966
/* sradi & sradi. */
B
Blue Swirl 已提交
1967
static inline void gen_sradi(DisasContext *ctx, int n)
1968
{
1969
    int sh = SH(ctx->opcode) + (n << 5);
1970
    if (sh != 0) {
1971
        int l1, l2;
1972
        TCGv t0;
1973 1974
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1975
        t0 = tcg_temp_local_new();
1976
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1977 1978
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1979
        tcg_gen_movi_tl(cpu_ca, 1);
1980 1981
        tcg_gen_br(l2);
        gen_set_label(l1);
1982
        tcg_gen_movi_tl(cpu_ca, 0);
1983
        gen_set_label(l2);
1984
        tcg_temp_free(t0);
1985 1986 1987
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1988
        tcg_gen_movi_tl(cpu_ca, 0);
1989 1990
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1991
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1992
}
B
Blue Swirl 已提交
1993 1994

static void gen_sradi0(DisasContext *ctx)
1995 1996 1997
{
    gen_sradi(ctx, 0);
}
B
Blue Swirl 已提交
1998 1999

static void gen_sradi1(DisasContext *ctx)
2000 2001 2002
{
    gen_sradi(ctx, 1);
}
B
Blue Swirl 已提交
2003

2004
/* srd & srd. */
B
Blue Swirl 已提交
2005
static void gen_srd(DisasContext *ctx)
2006
{
2007
    TCGv t0, t1;
2008

2009 2010 2011 2012 2013 2014 2015 2016 2017
    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);
2018
    tcg_temp_free(t0);
2019 2020 2021
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2022
#endif
B
bellard 已提交
2023 2024

/***                       Floating-Point arithmetic                       ***/
2025
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
B
Blue Swirl 已提交
2026
static void gen_f##name(DisasContext *ctx)                                    \
2027
{                                                                             \
2028
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2029
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2030 2031
        return;                                                               \
    }                                                                         \
2032 2033
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2034
    gen_reset_fpstatus();                                                     \
2035 2036
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
A
aurel32 已提交
2037
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2038
    if (isfloat) {                                                            \
2039 2040
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
2041
    }                                                                         \
A
aurel32 已提交
2042 2043
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
                     Rc(ctx->opcode) != 0);                                   \
2044 2045
}

2046 2047 2048
#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);
2049

2050
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
2051
static void gen_f##name(DisasContext *ctx)                                    \
2052
{                                                                             \
2053
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2054
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2055 2056
        return;                                                               \
    }                                                                         \
2057 2058
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2059
    gen_reset_fpstatus();                                                     \
2060 2061
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
A
aurel32 已提交
2062
                     cpu_fpr[rB(ctx->opcode)]);                               \
2063
    if (isfloat) {                                                            \
2064 2065
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
2066
    }                                                                         \
A
aurel32 已提交
2067 2068
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2069
}
2070 2071 2072
#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);
2073

2074
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
2075
static void gen_f##name(DisasContext *ctx)                                    \
2076
{                                                                             \
2077
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2078
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2079 2080
        return;                                                               \
    }                                                                         \
2081 2082
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2083
    gen_reset_fpstatus();                                                     \
2084 2085 2086
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
                     cpu_fpr[rA(ctx->opcode)],                                \
                     cpu_fpr[rC(ctx->opcode)]);                               \
2087
    if (isfloat) {                                                            \
2088 2089
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
                        cpu_fpr[rD(ctx->opcode)]);                            \
2090
    }                                                                         \
A
aurel32 已提交
2091 2092
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2093
}
2094 2095 2096
#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);
2097

2098
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
2099
static void gen_f##name(DisasContext *ctx)                                    \
2100
{                                                                             \
2101
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2102
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2103 2104
        return;                                                               \
    }                                                                         \
2105 2106
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2107
    gen_reset_fpstatus();                                                     \
2108 2109
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
2110 2111
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2112 2113
}

2114
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
B
Blue Swirl 已提交
2115
static void gen_f##name(DisasContext *ctx)                                    \
2116
{                                                                             \
2117
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2118
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2119 2120
        return;                                                               \
    }                                                                         \
2121 2122
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2123
    gen_reset_fpstatus();                                                     \
2124 2125
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
2126 2127
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2128 2129
}

2130
/* fadd - fadds */
2131
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2132
/* fdiv - fdivs */
2133
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2134
/* fmul - fmuls */
2135
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2136

2137
/* fre */
2138
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2139

2140
/* fres */
2141
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2142

2143
/* frsqrte */
2144 2145 2146
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2147
static void gen_frsqrtes(DisasContext *ctx)
2148
{
A
aurel32 已提交
2149
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2150
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2151 2152
        return;
    }
2153 2154
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2155
    gen_reset_fpstatus();
2156 2157 2158 2159
    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 已提交
2160
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2161
}
B
bellard 已提交
2162

2163
/* fsel */
2164
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2165
/* fsub - fsubs */
2166
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2167
/* Optional: */
B
Blue Swirl 已提交
2168

2169
/* fsqrt */
B
Blue Swirl 已提交
2170
static void gen_fsqrt(DisasContext *ctx)
2171
{
2172
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2173
        gen_exception(ctx, POWERPC_EXCP_FPU);
2174 2175
        return;
    }
2176 2177
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2178
    gen_reset_fpstatus();
2179 2180
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
                     cpu_fpr[rB(ctx->opcode)]);
A
aurel32 已提交
2181
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2182
}
B
bellard 已提交
2183

B
Blue Swirl 已提交
2184
static void gen_fsqrts(DisasContext *ctx)
B
bellard 已提交
2185
{
2186
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2187
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2188 2189
        return;
    }
2190 2191
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2192
    gen_reset_fpstatus();
2193 2194 2195 2196
    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 已提交
2197
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2198 2199 2200
}

/***                     Floating-Point multiply-and-add                   ***/
2201
/* fmadd - fmadds */
2202
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2203
/* fmsub - fmsubs */
2204
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2205
/* fnmadd - fnmadds */
2206
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2207
/* fnmsub - fnmsubs */
2208
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2209 2210 2211

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2212
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2213
/* fctiwz */
2214
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2215
/* frsp */
2216
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2217 2218
#if defined(TARGET_PPC64)
/* fcfid */
2219
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2220
/* fctid */
2221
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2222
/* fctidz */
2223
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2224
#endif
B
bellard 已提交
2225

2226
/* frin */
2227
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2228
/* friz */
2229
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2230
/* frip */
2231
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2232
/* frim */
2233
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2234

B
bellard 已提交
2235
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2236

2237
/* fcmpo */
B
Blue Swirl 已提交
2238
static void gen_fcmpo(DisasContext *ctx)
B
bellard 已提交
2239
{
A
aurel32 已提交
2240
    TCGv_i32 crf;
2241
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2242
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2243 2244
        return;
    }
2245 2246
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2247
    gen_reset_fpstatus();
A
aurel32 已提交
2248
    crf = tcg_const_i32(crfD(ctx->opcode));
2249 2250
    gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2251
    tcg_temp_free_i32(crf);
2252
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2253 2254 2255
}

/* fcmpu */
B
Blue Swirl 已提交
2256
static void gen_fcmpu(DisasContext *ctx)
B
bellard 已提交
2257
{
A
aurel32 已提交
2258
    TCGv_i32 crf;
2259
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2260
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2261 2262
        return;
    }
2263 2264
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2265
    gen_reset_fpstatus();
A
aurel32 已提交
2266
    crf = tcg_const_i32(crfD(ctx->opcode));
2267 2268
    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2269
    tcg_temp_free_i32(crf);
2270
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2271 2272
}

2273 2274
/***                         Floating-point move                           ***/
/* fabs */
2275 2276
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2277 2278

/* fmr  - fmr. */
2279
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2280
static void gen_fmr(DisasContext *ctx)
2281
{
2282
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2283
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2284 2285
        return;
    }
A
aurel32 已提交
2286 2287
    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);
2288 2289 2290
}

/* fnabs */
2291 2292
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2293
/* fneg */
2294 2295
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2296

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

2299
/* mcrfs */
B
Blue Swirl 已提交
2300
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2301
{
2302
    TCGv tmp = tcg_temp_new();
2303 2304
    int bfa;

2305
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2306
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2307 2308
        return;
    }
2309
    bfa = 4 * (7 - crfS(ctx->opcode));
2310 2311 2312
    tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
    tcg_temp_free(tmp);
2313
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2314
    tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2315 2316 2317
}

/* mffs */
B
Blue Swirl 已提交
2318
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2319
{
2320
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2321
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2322 2323
        return;
    }
2324
    gen_reset_fpstatus();
2325
    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
A
aurel32 已提交
2326
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2327 2328 2329
}

/* mtfsb0 */
B
Blue Swirl 已提交
2330
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2331
{
B
bellard 已提交
2332
    uint8_t crb;
2333

2334
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2335
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2336 2337
        return;
    }
A
aurel32 已提交
2338
    crb = 31 - crbD(ctx->opcode);
2339
    gen_reset_fpstatus();
A
aurel32 已提交
2340
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2341 2342 2343 2344
        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);
2345
        gen_helper_fpscr_clrbit(cpu_env, t0);
A
aurel32 已提交
2346 2347
        tcg_temp_free_i32(t0);
    }
2348
    if (unlikely(Rc(ctx->opcode) != 0)) {
2349 2350
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2351
    }
B
bellard 已提交
2352 2353 2354
}

/* mtfsb1 */
B
Blue Swirl 已提交
2355
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2356
{
B
bellard 已提交
2357
    uint8_t crb;
2358

2359
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2360
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2361 2362
        return;
    }
A
aurel32 已提交
2363
    crb = 31 - crbD(ctx->opcode);
2364 2365
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2366
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2367 2368 2369 2370
        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);
2371
        gen_helper_fpscr_setbit(cpu_env, t0);
2372
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2373
    }
2374
    if (unlikely(Rc(ctx->opcode) != 0)) {
2375 2376
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2377 2378
    }
    /* We can raise a differed exception */
2379
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2380 2381 2382
}

/* mtfsf */
B
Blue Swirl 已提交
2383
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2384
{
2385
    TCGv_i32 t0;
B
blueswir1 已提交
2386
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2387

2388
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2389
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2390 2391
        return;
    }
2392 2393
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2394
    gen_reset_fpstatus();
B
blueswir1 已提交
2395 2396 2397 2398
    if (L)
        t0 = tcg_const_i32(0xff);
    else
        t0 = tcg_const_i32(FM(ctx->opcode));
2399
    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2400
    tcg_temp_free_i32(t0);
2401
    if (unlikely(Rc(ctx->opcode) != 0)) {
2402 2403
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2404 2405
    }
    /* We can raise a differed exception */
2406
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2407 2408 2409
}

/* mtfsfi */
B
Blue Swirl 已提交
2410
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2411
{
2412
    int bf, sh;
2413 2414
    TCGv_i64 t0;
    TCGv_i32 t1;
2415

2416
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2417
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2418 2419
        return;
    }
2420 2421
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2422 2423
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2424
    gen_reset_fpstatus();
2425
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2426
    t1 = tcg_const_i32(1 << sh);
2427
    gen_helper_store_fpscr(cpu_env, t0, t1);
2428 2429
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2430
    if (unlikely(Rc(ctx->opcode) != 0)) {
2431 2432
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2433 2434
    }
    /* We can raise a differed exception */
2435
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2436 2437
}

2438 2439
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2440 2441
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2442 2443 2444
{
    target_long simm = SIMM(ctx->opcode);

2445
    simm &= ~maskl;
A
aurel32 已提交
2446 2447 2448 2449 2450 2451
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2452
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2453
    } else if (likely(simm != 0)) {
2454
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
2466
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2467
    }
2468 2469
}

B
Blue Swirl 已提交
2470
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2471
{
A
aurel32 已提交
2472 2473 2474 2475 2476 2477
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        } else
#endif
2478
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2479
    } else {
2480
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2481 2482 2483 2484 2485 2486
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2487 2488
}

B
Blue Swirl 已提交
2489
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2490
{
A
aurel32 已提交
2491
    if (rA(ctx->opcode) == 0) {
2492
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2493 2494 2495 2496 2497 2498 2499 2500 2501 2502
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
    }
}

B
Blue Swirl 已提交
2503 2504
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2505 2506 2507 2508 2509 2510 2511
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2512 2513
}

B
Blue Swirl 已提交
2514
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2515 2516 2517 2518 2519 2520 2521 2522 2523 2524
{
    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);
2525
    gen_helper_raise_exception_err(cpu_env, t1, t2);
2526 2527 2528 2529 2530 2531
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2532
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2533
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2534 2535 2536 2537
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2538
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2539 2540 2541 2542
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2543
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2544 2545 2546
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2547
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2548
    }
A
aurel32 已提交
2549 2550
}

B
Blue Swirl 已提交
2551
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2552
{
A
aurel32 已提交
2553 2554
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2555
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2556 2557 2558 2559
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2560 2561
}

B
Blue Swirl 已提交
2562
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2563
{
A
aurel32 已提交
2564 2565
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2566
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2567
    }
A
aurel32 已提交
2568 2569
}

A
aurel32 已提交
2570
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2571
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2572
{
B
blueswir1 已提交
2573
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2574
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2575 2576
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2577
    } else
A
aurel32 已提交
2578
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2579
}
A
aurel32 已提交
2580
#endif
A
aurel32 已提交
2581

B
Blue Swirl 已提交
2582
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2583
{
A
aurel32 已提交
2584 2585
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2586
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2587
    }
A
aurel32 已提交
2588 2589
}

B
Blue Swirl 已提交
2590
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2591
{
A
aurel32 已提交
2592
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2593 2594
}

B
Blue Swirl 已提交
2595
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2596
{
A
aurel32 已提交
2597 2598 2599
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2600
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2601 2602 2603 2604 2605
        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 已提交
2606 2607
}

B
Blue Swirl 已提交
2608
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2609
{
A
aurel32 已提交
2610
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2611 2612 2613
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2614 2615 2616 2617 2618
        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 已提交
2619 2620
}

B
Blue Swirl 已提交
2621
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2622
{
A
aurel32 已提交
2623
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2624
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2625
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2626
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2627
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2628
    } else
A
aurel32 已提交
2629
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2630 2631
}

2632
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2633
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2634
{                                                                             \
A
aurel32 已提交
2635 2636 2637 2638 2639
    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 已提交
2640
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2641 2642
}

2643
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2644
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2645
{                                                                             \
A
aurel32 已提交
2646
    TCGv EA;                                                                  \
2647 2648
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2649
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2650
        return;                                                               \
2651
    }                                                                         \
A
aurel32 已提交
2652
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2653
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2654
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2655
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2656
    else                                                                      \
A
aurel32 已提交
2657 2658
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2659 2660
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2661 2662
}

2663
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2664
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2665
{                                                                             \
A
aurel32 已提交
2666
    TCGv EA;                                                                  \
2667 2668
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2669
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2670
        return;                                                               \
2671
    }                                                                         \
A
aurel32 已提交
2672
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2673
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2674 2675
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2676 2677
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2678 2679
}

2680
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
B
Blue Swirl 已提交
2681
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2682
{                                                                             \
A
aurel32 已提交
2683 2684 2685 2686 2687
    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 已提交
2688
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2689
}
2690 2691
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2692

2693 2694 2695 2696 2697
#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 已提交
2698 2699

/* lbz lbzu lbzux lbzx */
2700
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2701
/* lha lhau lhaux lhax */
2702
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2703
/* lhz lhzu lhzux lhzx */
2704
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2705
/* lwz lwzu lwzux lwzx */
2706
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2707 2708
#if defined(TARGET_PPC64)
/* lwaux */
2709
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2710
/* lwax */
2711
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2712
/* ldux */
2713
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2714
/* ldx */
2715
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2716 2717

static void gen_ld(DisasContext *ctx)
2718
{
A
aurel32 已提交
2719
    TCGv EA;
2720 2721 2722
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2723
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2724 2725 2726
            return;
        }
    }
A
aurel32 已提交
2727
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2728
    EA = tcg_temp_new();
A
aurel32 已提交
2729
    gen_addr_imm_index(ctx, EA, 0x03);
2730 2731
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2732
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2733 2734
    } else {
        /* ld - ldu */
A
aurel32 已提交
2735
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2736 2737
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2738 2739
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2740
}
B
Blue Swirl 已提交
2741

2742
/* lq */
B
Blue Swirl 已提交
2743
static void gen_lq(DisasContext *ctx)
2744 2745
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2746
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2747 2748
#else
    int ra, rd;
A
aurel32 已提交
2749
    TCGv EA;
2750 2751

    /* Restore CPU state */
A
aurel32 已提交
2752
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2753
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2754 2755 2756 2757 2758
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2759
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2760 2761
        return;
    }
A
aurel32 已提交
2762
    if (unlikely(ctx->le_mode)) {
2763
        /* Little-endian mode is not handled */
A
aurel32 已提交
2764
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2765 2766
        return;
    }
A
aurel32 已提交
2767
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2768
    EA = tcg_temp_new();
A
aurel32 已提交
2769 2770 2771 2772
    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 已提交
2773
    tcg_temp_free(EA);
2774 2775
#endif
}
2776
#endif
B
bellard 已提交
2777 2778

/***                              Integer store                            ***/
2779
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2780
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2781
{                                                                             \
A
aurel32 已提交
2782 2783 2784 2785 2786
    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 已提交
2787
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2788 2789
}

2790
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2791
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2792
{                                                                             \
A
aurel32 已提交
2793
    TCGv EA;                                                                  \
2794
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2795
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2796
        return;                                                               \
2797
    }                                                                         \
A
aurel32 已提交
2798
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2799
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2800
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2801
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2802
    else                                                                      \
A
aurel32 已提交
2803 2804
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2805 2806
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2807 2808
}

2809
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2810
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2811
{                                                                             \
A
aurel32 已提交
2812
    TCGv EA;                                                                  \
2813
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2814
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2815
        return;                                                               \
2816
    }                                                                         \
A
aurel32 已提交
2817
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2818
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2819 2820
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2821 2822
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2823 2824
}

2825 2826
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2827
{                                                                             \
A
aurel32 已提交
2828 2829 2830 2831 2832
    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 已提交
2833
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2834
}
2835 2836
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2837

2838 2839 2840 2841 2842
#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 已提交
2843 2844

/* stb stbu stbux stbx */
2845
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2846
/* sth sthu sthux sthx */
2847
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2848
/* stw stwu stwux stwx */
2849
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2850
#if defined(TARGET_PPC64)
2851 2852
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2853 2854

static void gen_std(DisasContext *ctx)
2855
{
2856
    int rs;
A
aurel32 已提交
2857
    TCGv EA;
2858 2859 2860 2861

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2862
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2863 2864
#else
        /* stq */
A
aurel32 已提交
2865
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2866
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2867 2868 2869
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2870
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2871 2872
            return;
        }
A
aurel32 已提交
2873
        if (unlikely(ctx->le_mode)) {
2874
            /* Little-endian mode is not handled */
A
aurel32 已提交
2875
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2876 2877
            return;
        }
A
aurel32 已提交
2878
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2879
        EA = tcg_temp_new();
A
aurel32 已提交
2880 2881 2882 2883
        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 已提交
2884
        tcg_temp_free(EA);
2885 2886 2887 2888 2889
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2890
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2891 2892 2893
                return;
            }
        }
A
aurel32 已提交
2894
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2895
        EA = tcg_temp_new();
A
aurel32 已提交
2896 2897
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2898
        if (Rc(ctx->opcode))
A
aurel32 已提交
2899 2900
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2901 2902 2903
    }
}
#endif
B
bellard 已提交
2904 2905
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2906
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2907
{
A
aurel32 已提交
2908 2909
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2910
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2911
    }
A
aurel32 已提交
2912
}
2913
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2914

B
bellard 已提交
2915
/* lwbrx */
2916
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2917
{
A
aurel32 已提交
2918 2919
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2920
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2921
    }
A
aurel32 已提交
2922
}
2923
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2924

2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
#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 已提交
2937
/* sthbrx */
2938
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2939
{
A
aurel32 已提交
2940 2941 2942
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2943
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2944 2945 2946 2947 2948
        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 已提交
2949
}
2950
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2951

B
bellard 已提交
2952
/* stwbrx */
2953
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2954
{
A
aurel32 已提交
2955
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2956 2957 2958
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2959 2960 2961 2962 2963
        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 已提交
2964
}
2965
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2966

2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982
#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 已提交
2983
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2984

2985
/* lmw */
B
Blue Swirl 已提交
2986
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2987
{
A
aurel32 已提交
2988 2989 2990
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2991
    /* NIP cannot be restored if the memory exception comes from an helper */
2992
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2993 2994 2995
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2996
    gen_helper_lmw(cpu_env, t0, t1);
2997 2998
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2999 3000 3001
}

/* stmw */
B
Blue Swirl 已提交
3002
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
3003
{
A
aurel32 已提交
3004 3005 3006
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
3007
    /* NIP cannot be restored if the memory exception comes from an helper */
3008
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3009 3010 3011
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
3012
    gen_helper_stmw(cpu_env, t0, t1);
3013 3014
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3015 3016 3017
}

/***                    Integer load and store strings                     ***/
3018

B
bellard 已提交
3019
/* lswi */
3020
/* PowerPC32 specification says we must generate an exception if
3021 3022 3023 3024
 * 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 已提交
3025
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
3026
{
3027 3028
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3029 3030
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3031
    int ra = rA(ctx->opcode);
B
bellard 已提交
3032 3033 3034 3035 3036
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3037 3038 3039
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
3040
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3041
        return;
B
bellard 已提交
3042
    }
A
aurel32 已提交
3043
    gen_set_access_type(ctx, ACCESS_INT);
3044
    /* NIP cannot be restored if the memory exception comes from an helper */
3045
    gen_update_nip(ctx, ctx->nip - 4);
3046
    t0 = tcg_temp_new();
A
aurel32 已提交
3047
    gen_addr_register(ctx, t0);
3048 3049
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
3050
    gen_helper_lsw(cpu_env, t0, t1, t2);
3051 3052 3053
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3054 3055 3056
}

/* lswx */
B
Blue Swirl 已提交
3057
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
3058
{
A
aurel32 已提交
3059 3060 3061
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3062
    /* NIP cannot be restored if the memory exception comes from an helper */
3063
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3064 3065 3066 3067 3068
    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));
3069
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3070 3071 3072 3073
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
3074 3075 3076
}

/* stswi */
B
Blue Swirl 已提交
3077
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
3078
{
A
aurel32 已提交
3079 3080
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3081
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3082
    gen_set_access_type(ctx, ACCESS_INT);
3083
    /* NIP cannot be restored if the memory exception comes from an helper */
3084
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3085 3086
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3087 3088
    if (nb == 0)
        nb = 32;
3089
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3090
    t2 = tcg_const_i32(rS(ctx->opcode));
3091
    gen_helper_stsw(cpu_env, t0, t1, t2);
3092 3093 3094
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3095 3096 3097
}

/* stswx */
B
Blue Swirl 已提交
3098
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
3099
{
A
aurel32 已提交
3100 3101 3102
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3103
    /* NIP cannot be restored if the memory exception comes from an helper */
3104
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3105 3106 3107
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3108 3109
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3110
    t2 = tcg_const_i32(rS(ctx->opcode));
3111
    gen_helper_stsw(cpu_env, t0, t1, t2);
3112 3113 3114
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3115 3116 3117 3118
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3119
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3120 3121 3122 3123
{
}

/* isync */
B
Blue Swirl 已提交
3124
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3125
{
A
aurel32 已提交
3126
    gen_stop_exception(ctx);
B
bellard 已提交
3127 3128
}

3129
/* lwarx */
B
Blue Swirl 已提交
3130
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3131
{
A
aurel32 已提交
3132
    TCGv t0;
3133
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3134 3135 3136
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3137
    gen_check_align(ctx, t0, 0x03);
3138
    gen_qemu_ld32u(ctx, gpr, t0);
3139
    tcg_gen_mov_tl(cpu_reserve, t0);
3140
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3141
    tcg_temp_free(t0);
B
bellard 已提交
3142 3143
}

3144 3145 3146 3147 3148 3149 3150
#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;

3151
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3152
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3153
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3154 3155 3156 3157 3158 3159 3160 3161
    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 已提交
3162
/* stwcx. */
B
Blue Swirl 已提交
3163
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3164
{
A
aurel32 已提交
3165 3166 3167 3168
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3169
    gen_check_align(ctx, t0, 0x03);
3170 3171 3172 3173 3174 3175
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
    {
        int l1;

3176
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3177 3178 3179 3180 3181 3182 3183 3184
        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
3185
    tcg_temp_free(t0);
B
bellard 已提交
3186 3187
}

J
j_mayer 已提交
3188 3189
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3190
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3191
{
A
aurel32 已提交
3192
    TCGv t0;
3193
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3194 3195 3196
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3197
    gen_check_align(ctx, t0, 0x07);
3198
    gen_qemu_ld64(ctx, gpr, t0);
3199
    tcg_gen_mov_tl(cpu_reserve, t0);
3200
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3201
    tcg_temp_free(t0);
J
j_mayer 已提交
3202 3203 3204
}

/* stdcx. */
B
Blue Swirl 已提交
3205
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3206
{
A
aurel32 已提交
3207 3208 3209 3210
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3211
    gen_check_align(ctx, t0, 0x07);
3212 3213 3214 3215 3216
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
#else
    {
        int l1;
3217
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3218 3219 3220 3221 3222 3223 3224 3225
        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
3226
    tcg_temp_free(t0);
J
j_mayer 已提交
3227 3228 3229
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3230
/* sync */
B
Blue Swirl 已提交
3231
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3232 3233 3234
{
}

3235
/* wait */
B
Blue Swirl 已提交
3236
static void gen_wait(DisasContext *ctx)
3237
{
3238
    TCGv_i32 t0 = tcg_temp_new_i32();
3239
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
3240
    tcg_temp_free_i32(t0);
3241
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3242
    gen_exception_err(ctx, EXCP_HLT, 1);
3243 3244
}

B
bellard 已提交
3245
/***                         Floating-point load                           ***/
3246
#define GEN_LDF(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
3247
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3248
{                                                                             \
3249
    TCGv EA;                                                                  \
3250
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3251
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3252 3253
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3254
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3255
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3256 3257
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3258
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3259 3260
}

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

3281
#define GEN_LDUXF(name, ldop, opc, type)                                      \
B
Blue Swirl 已提交
3282
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3283
{                                                                             \
3284
    TCGv EA;                                                                  \
3285
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3286
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3287 3288
        return;                                                               \
    }                                                                         \
3289
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3290
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3291
        return;                                                               \
3292
    }                                                                         \
A
aurel32 已提交
3293
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3294
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3295 3296
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3297 3298
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3299 3300
}

3301
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3302
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3303
{                                                                             \
3304
    TCGv EA;                                                                  \
3305
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3306
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3307 3308
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3309
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3310
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3311 3312
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3313
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3314 3315
}

3316 3317 3318 3319 3320 3321
#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 已提交
3322
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3323 3324 3325
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3326
    gen_qemu_ld32u(ctx, t0, arg2);
3327 3328
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
3329
    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3330 3331
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3332

3333 3334 3335 3336
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3337 3338

/***                         Floating-point store                          ***/
3339
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3340
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3341
{                                                                             \
3342
    TCGv EA;                                                                  \
3343
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3344
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3345 3346
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3347
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3348
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3349 3350
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3351
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3352 3353
}

3354
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3355
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3356
{                                                                             \
3357
    TCGv EA;                                                                  \
3358
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3359
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3360 3361
        return;                                                               \
    }                                                                         \
3362
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3363
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3364
        return;                                                               \
3365
    }                                                                         \
A
aurel32 已提交
3366
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3367
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3368 3369
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3370 3371
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3372 3373
}

3374
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3375
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3376
{                                                                             \
3377
    TCGv EA;                                                                  \
3378
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3379
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3380 3381
        return;                                                               \
    }                                                                         \
3382
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3383
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3384
        return;                                                               \
3385
    }                                                                         \
A
aurel32 已提交
3386
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3387
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3388 3389
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3390 3391
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3392 3393
}

3394
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3395
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3396
{                                                                             \
3397
    TCGv EA;                                                                  \
3398
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3399
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3400 3401
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3402
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3403
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3404 3405
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3406
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3407 3408
}

3409 3410 3411 3412 3413 3414
#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 已提交
3415
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3416 3417 3418
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
3419
    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3420 3421
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3422
    gen_qemu_st32(ctx, t1, arg2);
3423 3424
    tcg_temp_free(t1);
}
B
bellard 已提交
3425 3426

/* stfd stfdu stfdux stfdx */
3427
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3428
/* stfs stfsu stfsux stfsx */
3429
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3430 3431

/* Optional: */
B
Blue Swirl 已提交
3432
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3433 3434 3435
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3436
    gen_qemu_st32(ctx, t0, arg2);
3437 3438
    tcg_temp_free(t0);
}
B
bellard 已提交
3439
/* stfiwx */
3440
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3441

D
David Gibson 已提交
3442 3443 3444 3445 3446 3447 3448 3449
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 已提交
3450
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3451
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3452 3453 3454
{
    TranslationBlock *tb;
    tb = ctx->tb;
3455 3456 3457 3458
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3459
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3460
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3461
        tcg_gen_goto_tb(n);
3462
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3463
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3464
    } else {
3465
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3466 3467
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3468
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3469 3470
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3471 3472
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3473
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3474 3475 3476
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3477
                gen_debug_exception(ctx);
3478 3479
            }
        }
B
bellard 已提交
3480
        tcg_gen_exit_tb(0);
3481
    }
B
bellard 已提交
3482 3483
}

B
Blue Swirl 已提交
3484
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3485 3486
{
#if defined(TARGET_PPC64)
3487 3488
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3489 3490
    else
#endif
3491
        tcg_gen_movi_tl(cpu_lr, nip);
3492 3493
}

B
bellard 已提交
3494
/* b ba bl bla */
B
Blue Swirl 已提交
3495
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3496
{
3497
    target_ulong li, target;
B
bellard 已提交
3498

3499
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3500
    /* sign extend LI */
3501
#if defined(TARGET_PPC64)
3502 3503 3504
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3505
#endif
3506
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3507
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3508
        target = ctx->nip + li - 4;
B
bellard 已提交
3509
    else
3510
        target = li;
3511 3512
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
D
David Gibson 已提交
3513
    gen_update_cfar(ctx, ctx->nip);
3514
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3515 3516
}

3517 3518 3519 3520
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3521
static inline void gen_bcond(DisasContext *ctx, int type)
3522 3523
{
    uint32_t bo = BO(ctx->opcode);
3524
    int l1;
3525
    TCGv target;
3526

3527
    ctx->exception = POWERPC_EXCP_BRANCH;
3528
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3529
        target = tcg_temp_local_new();
3530 3531 3532 3533
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3534 3535
    } else {
        TCGV_UNUSED(target);
3536
    }
3537 3538
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3539 3540 3541
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3542
        TCGv temp = tcg_temp_new();
3543
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3544
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3545 3546 3547
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3548
#if defined(TARGET_PPC64)
3549 3550 3551
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3552
#endif
3553 3554 3555 3556 3557
            tcg_gen_mov_tl(temp, cpu_ctr);
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3558
        }
P
pbrook 已提交
3559
        tcg_temp_free(temp);
3560 3561 3562 3563 3564
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3565
        TCGv_i32 temp = tcg_temp_new_i32();
3566

3567
        if (bo & 0x8) {
3568 3569
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3570
        } else {
3571 3572
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3573
        }
P
pbrook 已提交
3574
        tcg_temp_free_i32(temp);
3575
    }
D
David Gibson 已提交
3576
    gen_update_cfar(ctx, ctx->nip);
3577
    if (type == BCOND_IM) {
3578 3579 3580 3581 3582 3583
        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 已提交
3584
        gen_set_label(l1);
3585
        gen_goto_tb(ctx, 1, ctx->nip);
3586
    } else {
3587
#if defined(TARGET_PPC64)
3588 3589 3590 3591 3592 3593 3594 3595 3596 3597
        if (!(ctx->sf_mode))
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
        else
#endif
            tcg_gen_andi_tl(cpu_nip, target, ~3);
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
#if defined(TARGET_PPC64)
        if (!(ctx->sf_mode))
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3598 3599
        else
#endif
3600
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3601
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3602
    }
3603 3604
}

B
Blue Swirl 已提交
3605
static void gen_bc(DisasContext *ctx)
3606
{
3607 3608 3609
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3610
static void gen_bcctr(DisasContext *ctx)
3611
{
3612 3613 3614
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3615
static void gen_bclr(DisasContext *ctx)
3616
{
3617 3618
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3619 3620

/***                      Condition register logical                       ***/
3621
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3622
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3623
{                                                                             \
3624 3625
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3626
    TCGv_i32 t0, t1;                                                          \
3627
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3628
    t0 = tcg_temp_new_i32();                                                  \
3629
    if (sh > 0)                                                               \
3630
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3631
    else if (sh < 0)                                                          \
3632
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3633
    else                                                                      \
3634
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3635
    t1 = tcg_temp_new_i32();                                                  \
3636 3637
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3638
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3639
    else if (sh < 0)                                                          \
3640
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3641
    else                                                                      \
3642 3643
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3644
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3645 3646 3647
    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 已提交
3648 3649
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3650 3651 3652
}

/* crand */
3653
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3654
/* crandc */
3655
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3656
/* creqv */
3657
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3658
/* crnand */
3659
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3660
/* crnor */
3661
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3662
/* cror */
3663
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3664
/* crorc */
3665
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3666
/* crxor */
3667
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3668

3669
/* mcrf */
B
Blue Swirl 已提交
3670
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3671
{
A
aurel32 已提交
3672
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3673 3674 3675
}

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

3677
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3678
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3679
{
3680
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3681
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3682 3683
#else
    /* Restore CPU state */
A
aurel32 已提交
3684
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3685
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3686
        return;
3687
    }
D
David Gibson 已提交
3688
    gen_update_cfar(ctx, ctx->nip);
3689
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3690
    gen_sync_exception(ctx);
3691
#endif
B
bellard 已提交
3692 3693
}

J
j_mayer 已提交
3694
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3695
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3696 3697
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3698
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3699 3700
#else
    /* Restore CPU state */
A
aurel32 已提交
3701
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3702
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3703 3704
        return;
    }
D
David Gibson 已提交
3705
    gen_update_cfar(ctx, ctx->nip);
3706
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3707
    gen_sync_exception(ctx);
J
j_mayer 已提交
3708 3709 3710
#endif
}

B
Blue Swirl 已提交
3711
static void gen_hrfid(DisasContext *ctx)
3712 3713
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3714
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3715 3716
#else
    /* Restore CPU state */
A
aurel32 已提交
3717
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3718
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3719 3720
        return;
    }
3721
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3722
    gen_sync_exception(ctx);
3723 3724 3725 3726
#endif
}
#endif

B
bellard 已提交
3727
/* sc */
3728 3729 3730 3731 3732
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3733
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3734
{
3735 3736 3737
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3738
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3739 3740 3741
}

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

3743
/* tw */
B
Blue Swirl 已提交
3744
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3745
{
3746
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3747 3748
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3749 3750
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3751
    tcg_temp_free_i32(t0);
B
bellard 已提交
3752 3753 3754
}

/* twi */
B
Blue Swirl 已提交
3755
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3756
{
3757 3758
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3759 3760
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3761
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3762 3763
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3764 3765
}

3766 3767
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3768
static void gen_td(DisasContext *ctx)
3769
{
3770
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3771 3772
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3773 3774
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3775
    tcg_temp_free_i32(t0);
3776 3777 3778
}

/* tdi */
B
Blue Swirl 已提交
3779
static void gen_tdi(DisasContext *ctx)
3780
{
3781 3782
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3783 3784
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3785
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3786 3787
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3788 3789 3790
}
#endif

B
bellard 已提交
3791
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3792

3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821
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);
}

3822
/* mcrxr */
B
Blue Swirl 已提交
3823
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3824
{
3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841
    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 已提交
3842 3843
}

A
aurel32 已提交
3844
/* mfcr mfocrf */
B
Blue Swirl 已提交
3845
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3846
{
3847
    uint32_t crm, crn;
3848

3849 3850
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3851
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3852
            crn = ctz32 (crm);
3853
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3854 3855
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3856
        }
3857
    } else {
A
aurel32 已提交
3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875
        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);
3876
    }
B
bellard 已提交
3877 3878 3879
}

/* mfmsr */
B
Blue Swirl 已提交
3880
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3881
{
3882
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3883
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3884
#else
A
aurel32 已提交
3885
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3886
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3887
        return;
3888
    }
3889
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3890
#endif
B
bellard 已提交
3891 3892
}

3893
static void spr_noaccess(void *opaque, int gprn, int sprn)
3894
{
3895
#if 0
3896 3897
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3898
#endif
3899 3900 3901
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3902
/* mfspr */
B
Blue Swirl 已提交
3903
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3904
{
A
aurel32 已提交
3905
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3906 3907
    uint32_t sprn = SPR(ctx->opcode);

3908
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3909
    if (ctx->mem_idx == 2)
3910
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3911
    else if (ctx->mem_idx)
3912 3913
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3914
#endif
3915
        read_cb = ctx->spr_cb[sprn].uea_read;
3916 3917
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3918
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3919 3920
        } else {
            /* Privilege exception */
3921 3922 3923 3924 3925
            /* 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) {
3926
                qemu_log("Trying to read privileged spr %d %03x at "
3927 3928 3929
                         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);
3930
            }
A
aurel32 已提交
3931
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3932
        }
3933 3934
    } else {
        /* Not defined */
3935
        qemu_log("Trying to read invalid spr %d %03x at "
3936 3937
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3938
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3939
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3940 3941 3942
    }
}

B
Blue Swirl 已提交
3943
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3944
{
3945
    gen_op_mfspr(ctx);
3946
}
3947 3948

/* mftb */
B
Blue Swirl 已提交
3949
static void gen_mftb(DisasContext *ctx)
3950 3951
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3952 3953
}

A
aurel32 已提交
3954
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3955
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3956
{
3957
    uint32_t crm, crn;
3958

3959
    crm = CRM(ctx->opcode);
M
malc 已提交
3960 3961 3962
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3963
            crn = ctz32 (crm);
M
malc 已提交
3964
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3965 3966
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3967 3968
            tcg_temp_free_i32(temp);
        }
3969
    } else {
A
aurel32 已提交
3970 3971 3972 3973 3974 3975 3976 3977
        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 已提交
3978
        tcg_temp_free_i32(temp);
3979
    }
B
bellard 已提交
3980 3981 3982
}

/* mtmsr */
J
j_mayer 已提交
3983
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3984
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3985 3986
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3987
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3988
#else
A
aurel32 已提交
3989
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3990
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3991 3992
        return;
    }
3993 3994
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3995 3996 3997 3998 3999
        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);
4000
    } else {
4001 4002 4003 4004
        /* 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
         */
4005
        gen_update_nip(ctx, ctx->nip);
4006
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
4007 4008
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4009
        gen_stop_exception(ctx);
4010
    }
J
j_mayer 已提交
4011 4012 4013 4014
#endif
}
#endif

B
Blue Swirl 已提交
4015
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
4016
{
4017
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4018
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4019
#else
A
aurel32 已提交
4020
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4021
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4022
        return;
4023
    }
4024 4025
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
4026 4027 4028 4029 4030
        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);
4031
    } else {
4032 4033
        TCGv msr = tcg_temp_new();

4034 4035 4036 4037
        /* 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
         */
4038
        gen_update_nip(ctx, ctx->nip);
4039
#if defined(TARGET_PPC64)
4040 4041 4042
        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)]);
4043
#endif
4044
        gen_helper_store_msr(cpu_env, msr);
4045
        /* Must stop the translation as machine state (may have) changed */
4046
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4047
        gen_stop_exception(ctx);
4048
    }
4049
#endif
B
bellard 已提交
4050 4051 4052
}

/* mtspr */
B
Blue Swirl 已提交
4053
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
4054
{
A
aurel32 已提交
4055
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
4056 4057
    uint32_t sprn = SPR(ctx->opcode);

4058
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4059
    if (ctx->mem_idx == 2)
4060
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
4061
    else if (ctx->mem_idx)
4062 4063
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
4064
#endif
4065
        write_cb = ctx->spr_cb[sprn].uea_write;
4066 4067
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4068
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4069 4070
        } else {
            /* Privilege exception */
4071
            qemu_log("Trying to write privileged spr %d %03x at "
4072 4073 4074
                     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 已提交
4075
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4076
        }
4077 4078
    } else {
        /* Not defined */
4079
        qemu_log("Trying to write invalid spr %d %03x at "
4080 4081
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
4082
               sprn, sprn, ctx->nip);
A
aurel32 已提交
4083
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4084 4085 4086 4087
    }
}

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

4089
/* dcbf */
B
Blue Swirl 已提交
4090
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
4091
{
J
j_mayer 已提交
4092
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
4093 4094 4095 4096 4097
    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);
4098
    tcg_temp_free(t0);
B
bellard 已提交
4099 4100 4101
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4102
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4103
{
4104
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4105
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4106
#else
A
aurel32 已提交
4107
    TCGv EA, val;
A
aurel32 已提交
4108
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4109
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4110
        return;
4111
    }
P
pbrook 已提交
4112
    EA = tcg_temp_new();
A
aurel32 已提交
4113 4114
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4115
    val = tcg_temp_new();
4116
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4117 4118
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4119 4120
    tcg_temp_free(val);
    tcg_temp_free(EA);
4121
#endif
B
bellard 已提交
4122 4123 4124
}

/* dcdst */
B
Blue Swirl 已提交
4125
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4126
{
4127
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4128 4129 4130 4131 4132
    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);
4133
    tcg_temp_free(t0);
B
bellard 已提交
4134 4135 4136
}

/* dcbt */
B
Blue Swirl 已提交
4137
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4138
{
4139
    /* interpreted as no-op */
4140 4141 4142
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4143 4144 4145
}

/* dcbtst */
B
Blue Swirl 已提交
4146
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4147
{
4148
    /* interpreted as no-op */
4149 4150 4151
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4152 4153 4154
}

/* dcbz */
B
Blue Swirl 已提交
4155
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4156
{
A
Alexander Graf 已提交
4157 4158 4159
    TCGv tcgv_addr;
    TCGv_i32 tcgv_is_dcbzl;
    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4160

A
aurel32 已提交
4161
    gen_set_access_type(ctx, ACCESS_CACHE);
4162 4163
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
4164 4165 4166 4167 4168 4169 4170 4171
    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 已提交
4172 4173
}

4174
/* dst / dstt */
B
Blue Swirl 已提交
4175
static void gen_dst(DisasContext *ctx)
4176 4177 4178 4179 4180 4181 4182 4183 4184
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4185
static void gen_dstst(DisasContext *ctx)
4186 4187 4188 4189 4190 4191 4192 4193 4194 4195
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4196
static void gen_dss(DisasContext *ctx)
4197 4198 4199 4200
{
    /* interpreted as no-op */
}

B
bellard 已提交
4201
/* icbi */
B
Blue Swirl 已提交
4202
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4203
{
A
aurel32 已提交
4204 4205
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4206 4207
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4208 4209
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4210
    gen_helper_icbi(cpu_env, t0);
4211
    tcg_temp_free(t0);
B
bellard 已提交
4212 4213 4214 4215
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4216
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4217
{
4218 4219 4220 4221
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4222 4223 4224 4225
}

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

4227
/* mfsr */
B
Blue Swirl 已提交
4228
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4229
{
4230
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4231
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4232
#else
4233
    TCGv t0;
A
aurel32 已提交
4234
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4235
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4236
        return;
4237
    }
4238
    t0 = tcg_const_tl(SR(ctx->opcode));
4239
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4240
    tcg_temp_free(t0);
4241
#endif
B
bellard 已提交
4242 4243 4244
}

/* mfsrin */
B
Blue Swirl 已提交
4245
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4246
{
4247
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4248
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4249
#else
4250
    TCGv t0;
A
aurel32 已提交
4251
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4252
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4253
        return;
4254
    }
4255 4256 4257
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4258
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4259
    tcg_temp_free(t0);
4260
#endif
B
bellard 已提交
4261 4262 4263
}

/* mtsr */
B
Blue Swirl 已提交
4264
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4265
{
4266
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4267
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4268
#else
4269
    TCGv t0;
A
aurel32 已提交
4270
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4271
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4272
        return;
4273
    }
4274
    t0 = tcg_const_tl(SR(ctx->opcode));
4275
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4276
    tcg_temp_free(t0);
4277
#endif
B
bellard 已提交
4278 4279 4280
}

/* mtsrin */
B
Blue Swirl 已提交
4281
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4282
{
4283
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4284
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4285
#else
4286
    TCGv t0;
A
aurel32 已提交
4287
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4288
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4289
        return;
4290
    }
4291 4292 4293
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4294
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4295
    tcg_temp_free(t0);
4296
#endif
B
bellard 已提交
4297 4298
}

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

4302
/* mfsr */
B
Blue Swirl 已提交
4303
static void gen_mfsr_64b(DisasContext *ctx)
4304 4305
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4306
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4307
#else
4308
    TCGv t0;
A
aurel32 已提交
4309
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4310
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4311 4312
        return;
    }
4313
    t0 = tcg_const_tl(SR(ctx->opcode));
4314
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4315
    tcg_temp_free(t0);
4316 4317 4318 4319
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4320
static void gen_mfsrin_64b(DisasContext *ctx)
4321 4322
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4323
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4324
#else
4325
    TCGv t0;
A
aurel32 已提交
4326
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4327
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4328 4329
        return;
    }
4330 4331 4332
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4333
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4334
    tcg_temp_free(t0);
4335 4336 4337 4338
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4339
static void gen_mtsr_64b(DisasContext *ctx)
4340 4341
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4342
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4343
#else
4344
    TCGv t0;
A
aurel32 已提交
4345
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4346
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4347 4348
        return;
    }
4349
    t0 = tcg_const_tl(SR(ctx->opcode));
4350
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4351
    tcg_temp_free(t0);
4352 4353 4354 4355
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4356
static void gen_mtsrin_64b(DisasContext *ctx)
4357 4358
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4359
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4360
#else
4361
    TCGv t0;
A
aurel32 已提交
4362
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4363
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4364 4365
        return;
    }
4366 4367 4368
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4369
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4370
    tcg_temp_free(t0);
4371 4372
#endif
}
B
blueswir1 已提交
4373 4374

/* slbmte */
B
Blue Swirl 已提交
4375
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4376 4377 4378 4379 4380 4381 4382 4383
{
#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;
    }
4384 4385
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
B
blueswir1 已提交
4386 4387 4388
#endif
}

4389 4390 4391 4392 4393 4394 4395 4396 4397
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;
    }
4398
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411
                             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;
    }
4412
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4413 4414 4415
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4416 4417
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4418
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4419
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4420

4421
/* tlbia */
B
Blue Swirl 已提交
4422
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4423
{
4424
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4425
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4426
#else
A
aurel32 已提交
4427
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4428
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4429
        return;
4430
    }
4431
    gen_helper_tlbia(cpu_env);
4432
#endif
B
bellard 已提交
4433 4434
}

B
blueswir1 已提交
4435
/* tlbiel */
B
Blue Swirl 已提交
4436
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4437 4438 4439 4440 4441 4442 4443 4444
{
#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;
    }
4445
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
B
blueswir1 已提交
4446 4447 4448
#endif
}

B
bellard 已提交
4449
/* tlbie */
B
Blue Swirl 已提交
4450
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4451
{
4452
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4453
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4454
#else
A
aurel32 已提交
4455
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4456
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4457
        return;
4458
    }
4459
#if defined(TARGET_PPC64)
4460 4461 4462
    if (!ctx->sf_mode) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4463
        gen_helper_tlbie(cpu_env, t0);
4464 4465
        tcg_temp_free(t0);
    } else
4466
#endif
4467
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4468
#endif
B
bellard 已提交
4469 4470 4471
}

/* tlbsync */
B
Blue Swirl 已提交
4472
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4473
{
4474
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4475
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4476
#else
A
aurel32 已提交
4477
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4478
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4479
        return;
4480 4481 4482 4483
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4484
    gen_stop_exception(ctx);
4485
#endif
B
bellard 已提交
4486 4487
}

J
j_mayer 已提交
4488 4489
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4490
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4491 4492
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4493
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4494
#else
A
aurel32 已提交
4495
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4496
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4497 4498
        return;
    }
4499
    gen_helper_slbia(cpu_env);
J
j_mayer 已提交
4500 4501 4502 4503
#endif
}

/* slbie */
B
Blue Swirl 已提交
4504
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4505 4506
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4507
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4508
#else
A
aurel32 已提交
4509
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4510
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4511 4512
        return;
    }
4513
    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4514 4515 4516 4517
#endif
}
#endif

B
bellard 已提交
4518 4519
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4520

4521
/* eciwx */
B
Blue Swirl 已提交
4522
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4523
{
A
aurel32 已提交
4524
    TCGv t0;
4525
    /* Should check EAR[E] ! */
A
aurel32 已提交
4526 4527 4528
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4529
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4530
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4531
    tcg_temp_free(t0);
4532 4533 4534
}

/* ecowx */
B
Blue Swirl 已提交
4535
static void gen_ecowx(DisasContext *ctx)
4536
{
A
aurel32 已提交
4537
    TCGv t0;
4538
    /* Should check EAR[E] ! */
A
aurel32 已提交
4539 4540 4541
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4542
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4543
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4544
    tcg_temp_free(t0);
4545 4546 4547
}

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

4549
/* abs - abs. */
B
Blue Swirl 已提交
4550
static void gen_abs(DisasContext *ctx)
4551
{
4552 4553 4554 4555 4556 4557 4558 4559
    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);
4560
    if (unlikely(Rc(ctx->opcode) != 0))
4561
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4562 4563 4564
}

/* abso - abso. */
B
Blue Swirl 已提交
4565
static void gen_abso(DisasContext *ctx)
4566
{
4567 4568 4569 4570
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
4571
    tcg_gen_movi_tl(cpu_ov, 0);
4572 4573
    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);
4574 4575
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4576 4577 4578 4579 4580 4581 4582
    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);
4583
    if (unlikely(Rc(ctx->opcode) != 0))
4584
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4585 4586 4587
}

/* clcs */
B
Blue Swirl 已提交
4588
static void gen_clcs(DisasContext *ctx)
4589
{
4590
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4591
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4592
    tcg_temp_free_i32(t0);
4593
    /* Rc=1 sets CR0 to an undefined state */
4594 4595 4596
}

/* div - div. */
B
Blue Swirl 已提交
4597
static void gen_div(DisasContext *ctx)
4598
{
4599 4600
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4601
    if (unlikely(Rc(ctx->opcode) != 0))
4602
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4603 4604 4605
}

/* divo - divo. */
B
Blue Swirl 已提交
4606
static void gen_divo(DisasContext *ctx)
4607
{
4608 4609
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4610
    if (unlikely(Rc(ctx->opcode) != 0))
4611
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4612 4613 4614
}

/* divs - divs. */
B
Blue Swirl 已提交
4615
static void gen_divs(DisasContext *ctx)
4616
{
4617 4618
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4619
    if (unlikely(Rc(ctx->opcode) != 0))
4620
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4621 4622 4623
}

/* divso - divso. */
B
Blue Swirl 已提交
4624
static void gen_divso(DisasContext *ctx)
4625
{
4626 4627
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4628
    if (unlikely(Rc(ctx->opcode) != 0))
4629
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4630 4631 4632
}

/* doz - doz. */
B
Blue Swirl 已提交
4633
static void gen_doz(DisasContext *ctx)
4634
{
4635 4636 4637 4638 4639 4640 4641 4642
    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);
4643
    if (unlikely(Rc(ctx->opcode) != 0))
4644
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4645 4646 4647
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4648
static void gen_dozo(DisasContext *ctx)
4649
{
4650 4651 4652 4653 4654 4655
    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 */
4656
    tcg_gen_movi_tl(cpu_ov, 0);
4657 4658 4659 4660 4661 4662 4663
    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);
4664 4665
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4666 4667 4668 4669 4670 4671 4672
    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);
4673
    if (unlikely(Rc(ctx->opcode) != 0))
4674
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4675 4676 4677
}

/* dozi */
B
Blue Swirl 已提交
4678
static void gen_dozi(DisasContext *ctx)
4679
{
4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690
    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)]);
4691 4692 4693
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4694
static void gen_lscbx(DisasContext *ctx)
4695
{
4696 4697 4698 4699
    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));
4700

A
aurel32 已提交
4701
    gen_addr_reg_index(ctx, t0);
4702
    /* NIP cannot be restored if the memory exception comes from an helper */
4703
    gen_update_nip(ctx, ctx->nip - 4);
4704
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4705 4706 4707
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4708
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4709
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4710
    if (unlikely(Rc(ctx->opcode) != 0))
4711 4712
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4713 4714 4715
}

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

/* maskir - maskir. */
B
Blue Swirl 已提交
4742
static void gen_maskir(DisasContext *ctx)
4743
{
4744 4745 4746 4747 4748 4749 4750
    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);
4751
    if (unlikely(Rc(ctx->opcode) != 0))
4752
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4753 4754 4755
}

/* mul - mul. */
B
Blue Swirl 已提交
4756
static void gen_mul(DisasContext *ctx)
4757
{
4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770
    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);
4771
    if (unlikely(Rc(ctx->opcode) != 0))
4772
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4773 4774 4775
}

/* mulo - mulo. */
B
Blue Swirl 已提交
4776
static void gen_mulo(DisasContext *ctx)
4777
{
4778 4779 4780 4781 4782
    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 */
4783
    tcg_gen_movi_tl(cpu_ov, 0);
4784 4785 4786 4787 4788 4789 4790 4791 4792
    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);
4793 4794
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4795 4796 4797 4798
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4799
    if (unlikely(Rc(ctx->opcode) != 0))
4800
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4801 4802 4803
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4804
static void gen_nabs(DisasContext *ctx)
4805
{
4806 4807 4808 4809 4810 4811 4812 4813
    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);
4814
    if (unlikely(Rc(ctx->opcode) != 0))
4815
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4816 4817 4818
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4819
static void gen_nabso(DisasContext *ctx)
4820
{
4821 4822 4823 4824 4825 4826 4827 4828 4829
    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 */
4830
    tcg_gen_movi_tl(cpu_ov, 0);
4831
    if (unlikely(Rc(ctx->opcode) != 0))
4832
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4833 4834 4835
}

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

/* rrib - rrib. */
B
Blue Swirl 已提交
4852
static void gen_rrib(DisasContext *ctx)
4853
{
4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864
    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);
4865
    if (unlikely(Rc(ctx->opcode) != 0))
4866
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4867 4868 4869
}

/* sle - sle. */
B
Blue Swirl 已提交
4870
static void gen_sle(DisasContext *ctx)
4871
{
4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882
    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);
4883
    if (unlikely(Rc(ctx->opcode) != 0))
4884
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4885 4886 4887
}

/* sleq - sleq. */
B
Blue Swirl 已提交
4888
static void gen_sleq(DisasContext *ctx)
4889
{
4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904
    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);
4905
    if (unlikely(Rc(ctx->opcode) != 0))
4906
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4907 4908 4909
}

/* sliq - sliq. */
B
Blue Swirl 已提交
4910
static void gen_sliq(DisasContext *ctx)
4911
{
4912 4913 4914 4915 4916 4917 4918 4919 4920 4921
    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);
4922
    if (unlikely(Rc(ctx->opcode) != 0))
4923
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4924 4925 4926
}

/* slliq - slliq. */
B
Blue Swirl 已提交
4927
static void gen_slliq(DisasContext *ctx)
4928
{
4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939
    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);
4940
    if (unlikely(Rc(ctx->opcode) != 0))
4941
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4942 4943 4944
}

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

/* slq - slq. */
B
Blue Swirl 已提交
4974
static void gen_slq(DisasContext *ctx)
4975
{
4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991
    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);
4992
    if (unlikely(Rc(ctx->opcode) != 0))
4993
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4994 4995
}

4996
/* sraiq - sraiq. */
B
Blue Swirl 已提交
4997
static void gen_sraiq(DisasContext *ctx)
4998
{
4999 5000 5001 5002 5003 5004 5005 5006
    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);
5007
    tcg_gen_movi_tl(cpu_ca, 0);
5008 5009
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
5010
    tcg_gen_movi_tl(cpu_ca, 1);
5011 5012 5013 5014
    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);
5015
    if (unlikely(Rc(ctx->opcode) != 0))
5016
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5017 5018 5019
}

/* sraq - sraq. */
B
Blue Swirl 已提交
5020
static void gen_sraq(DisasContext *ctx)
5021
{
5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040
    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);
5041
    tcg_gen_movi_tl(cpu_ca, 0);
5042 5043
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
5044
    tcg_gen_movi_tl(cpu_ca, 1);
5045 5046 5047
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
5048
    if (unlikely(Rc(ctx->opcode) != 0))
5049
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5050 5051 5052
}

/* sre - sre. */
B
Blue Swirl 已提交
5053
static void gen_sre(DisasContext *ctx)
5054
{
5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065
    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);
5066
    if (unlikely(Rc(ctx->opcode) != 0))
5067
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5068 5069 5070
}

/* srea - srea. */
B
Blue Swirl 已提交
5071
static void gen_srea(DisasContext *ctx)
5072
{
5073 5074 5075 5076 5077 5078 5079 5080
    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);
5081
    if (unlikely(Rc(ctx->opcode) != 0))
5082
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5083 5084 5085
}

/* sreq */
B
Blue Swirl 已提交
5086
static void gen_sreq(DisasContext *ctx)
5087
{
5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102
    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);
5103
    if (unlikely(Rc(ctx->opcode) != 0))
5104
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5105 5106 5107
}

/* sriq */
B
Blue Swirl 已提交
5108
static void gen_sriq(DisasContext *ctx)
5109
{
5110 5111 5112 5113 5114 5115 5116 5117 5118 5119
    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);
5120
    if (unlikely(Rc(ctx->opcode) != 0))
5121
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5122 5123 5124
}

/* srliq */
B
Blue Swirl 已提交
5125
static void gen_srliq(DisasContext *ctx)
5126
{
5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137
    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);
5138
    if (unlikely(Rc(ctx->opcode) != 0))
5139
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5140 5141 5142
}

/* srlq */
B
Blue Swirl 已提交
5143
static void gen_srlq(DisasContext *ctx)
5144
{
5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167
    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);
5168
    if (unlikely(Rc(ctx->opcode) != 0))
5169
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5170 5171 5172
}

/* srq */
B
Blue Swirl 已提交
5173
static void gen_srq(DisasContext *ctx)
5174
{
5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190
    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);
5191
    if (unlikely(Rc(ctx->opcode) != 0))
5192
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5193 5194 5195
}

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

5197
/* dsa  */
B
Blue Swirl 已提交
5198
static void gen_dsa(DisasContext *ctx)
5199 5200
{
    /* XXX: TODO */
A
aurel32 已提交
5201
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5202 5203 5204
}

/* esa */
B
Blue Swirl 已提交
5205
static void gen_esa(DisasContext *ctx)
5206 5207
{
    /* XXX: TODO */
A
aurel32 已提交
5208
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5209 5210 5211
}

/* mfrom */
B
Blue Swirl 已提交
5212
static void gen_mfrom(DisasContext *ctx)
5213 5214
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5215
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5216
#else
A
aurel32 已提交
5217
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5218
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5219 5220
        return;
    }
5221
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5222 5223 5224 5225
#endif
}

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

5227
/* tlbld */
B
Blue Swirl 已提交
5228
static void gen_tlbld_6xx(DisasContext *ctx)
5229 5230
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5231
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5232
#else
A
aurel32 已提交
5233
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5234
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5235 5236
        return;
    }
5237
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5238 5239 5240 5241
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5242
static void gen_tlbli_6xx(DisasContext *ctx)
5243 5244
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5245
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5246
#else
A
aurel32 已提交
5247
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5248
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5249 5250
        return;
    }
5251
    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5252 5253 5254
#endif
}

5255
/* 74xx TLB management */
B
Blue Swirl 已提交
5256

5257
/* tlbld */
B
Blue Swirl 已提交
5258
static void gen_tlbld_74xx(DisasContext *ctx)
5259 5260
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5261
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5262
#else
A
aurel32 已提交
5263
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5264
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5265 5266
        return;
    }
5267
    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5268 5269 5270 5271
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5272
static void gen_tlbli_74xx(DisasContext *ctx)
5273 5274
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5275
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5276
#else
A
aurel32 已提交
5277
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5278
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5279 5280
        return;
    }
5281
    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5282 5283 5284
#endif
}

5285
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5286

5287
/* clf */
B
Blue Swirl 已提交
5288
static void gen_clf(DisasContext *ctx)
5289 5290 5291 5292 5293
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5294
static void gen_cli(DisasContext *ctx)
5295
{
B
blueswir1 已提交
5296
    /* Cache line invalidate: privileged and treated as no-op */
5297
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5298
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5299
#else
A
aurel32 已提交
5300
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5301
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5302 5303 5304 5305 5306 5307
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5308
static void gen_dclst(DisasContext *ctx)
5309 5310 5311 5312
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5313
static void gen_mfsri(DisasContext *ctx)
5314 5315
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5316
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5317
#else
5318 5319 5320
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5321
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5322
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5323 5324
        return;
    }
5325
    t0 = tcg_temp_new();
A
aurel32 已提交
5326
    gen_addr_reg_index(ctx, t0);
5327 5328
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
5329
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5330
    tcg_temp_free(t0);
5331
    if (ra != 0 && ra != rd)
5332
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5333 5334 5335
#endif
}

B
Blue Swirl 已提交
5336
static void gen_rac(DisasContext *ctx)
5337 5338
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5339
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5340
#else
5341
    TCGv t0;
A
aurel32 已提交
5342
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5343
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5344 5345
        return;
    }
5346
    t0 = tcg_temp_new();
A
aurel32 已提交
5347
    gen_addr_reg_index(ctx, t0);
5348
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5349
    tcg_temp_free(t0);
5350 5351 5352
#endif
}

B
Blue Swirl 已提交
5353
static void gen_rfsvc(DisasContext *ctx)
5354 5355
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5356
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5357
#else
A
aurel32 已提交
5358
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5359
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5360 5361
        return;
    }
5362
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5363
    gen_sync_exception(ctx);
5364 5365 5366 5367 5368 5369 5370 5371 5372
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5373
static void gen_lfq(DisasContext *ctx)
5374
{
5375
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5376 5377 5378 5379 5380 5381 5382
    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);
5383
    tcg_temp_free(t0);
5384 5385 5386
}

/* lfqu */
B
Blue Swirl 已提交
5387
static void gen_lfqu(DisasContext *ctx)
5388 5389
{
    int ra = rA(ctx->opcode);
5390
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5391 5392 5393 5394 5395 5396 5397 5398
    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);
5399
    if (ra != 0)
5400 5401 5402
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5403 5404 5405
}

/* lfqux */
B
Blue Swirl 已提交
5406
static void gen_lfqux(DisasContext *ctx)
5407 5408
{
    int ra = rA(ctx->opcode);
5409
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5410 5411 5412 5413 5414 5415 5416 5417 5418
    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);
5419
    if (ra != 0)
5420 5421
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5422 5423 5424
}

/* lfqx */
B
Blue Swirl 已提交
5425
static void gen_lfqx(DisasContext *ctx)
5426
{
5427
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5428 5429 5430 5431 5432 5433 5434
    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);
5435
    tcg_temp_free(t0);
5436 5437 5438
}

/* stfq */
B
Blue Swirl 已提交
5439
static void gen_stfq(DisasContext *ctx)
5440
{
5441
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5442 5443 5444 5445 5446 5447 5448
    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);
5449
    tcg_temp_free(t0);
5450 5451 5452
}

/* stfqu */
B
Blue Swirl 已提交
5453
static void gen_stfqu(DisasContext *ctx)
5454 5455
{
    int ra = rA(ctx->opcode);
5456
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5457 5458 5459 5460 5461 5462 5463 5464 5465
    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);
5466
    if (ra != 0)
5467 5468
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5469 5470 5471
}

/* stfqux */
B
Blue Swirl 已提交
5472
static void gen_stfqux(DisasContext *ctx)
5473 5474
{
    int ra = rA(ctx->opcode);
5475
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5476 5477 5478 5479 5480 5481 5482 5483 5484
    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);
5485
    if (ra != 0)
5486 5487
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5488 5489 5490
}

/* stfqx */
B
Blue Swirl 已提交
5491
static void gen_stfqx(DisasContext *ctx)
5492
{
5493
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5494 5495 5496 5497 5498 5499 5500
    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);
5501
    tcg_temp_free(t0);
5502 5503 5504
}

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

5506
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5507
static void gen_mfapidi(DisasContext *ctx)
5508 5509
{
    /* XXX: TODO */
A
aurel32 已提交
5510
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5511 5512
}

5513
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5514
static void gen_tlbiva(DisasContext *ctx)
5515 5516
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5517
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5518
#else
5519
    TCGv t0;
A
aurel32 已提交
5520
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5521
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5522 5523
        return;
    }
5524
    t0 = tcg_temp_new();
A
aurel32 已提交
5525
    gen_addr_reg_index(ctx, t0);
5526
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5527
    tcg_temp_free(t0);
5528 5529 5530 5531
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5532 5533
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5534
{
5535 5536
    TCGv t0, t1;

P
pbrook 已提交
5537 5538
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5539

5540 5541 5542 5543 5544 5545 5546
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5547 5548 5549
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5550 5551 5552 5553 5554
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5555 5556 5557
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5558 5559 5560 5561 5562 5563 5564
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5565 5566 5567 5568
        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);
5569 5570 5571 5572 5573
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5574 5575 5576 5577
        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);
5578 5579 5580 5581 5582 5583 5584
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5585 5586
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5587 5588 5589 5590 5591
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5592 5593
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5594 5595 5596
        break;
    }
    if (opc2 & 0x04) {
5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612
        /* (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 */
5613
                tcg_gen_movi_tl(cpu_ov, 0);
5614 5615 5616 5617 5618 5619 5620
            }
            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 已提交
5621
                if (opc3 & 0x02) {
5622 5623 5624 5625 5626 5627 5628
                    /* 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 已提交
5629
                if (opc3 & 0x02) {
5630 5631 5632 5633 5634 5635
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
5636 5637
                tcg_gen_movi_tl(cpu_ov, 1);
                tcg_gen_movi_tl(cpu_so, 1);
5638 5639 5640 5641 5642 5643
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5644
    }
5645 5646
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5647 5648
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5649
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5650 5651 5652
    }
}

5653
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5654
static void glue(gen_, name)(DisasContext *ctx)                               \
5655 5656 5657 5658 5659 5660
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5661
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5662
/* macchwo   - macchwo.   */
5663
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5664
/* macchws   - macchws.   */
5665
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5666
/* macchwso  - macchwso.  */
5667
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5668
/* macchwsu  - macchwsu.  */
5669
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5670
/* macchwsuo - macchwsuo. */
5671
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5672
/* macchwu   - macchwu.   */
5673
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5674
/* macchwuo  - macchwuo.  */
5675
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5676
/* machhw    - machhw.    */
5677
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5678
/* machhwo   - machhwo.   */
5679
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5680
/* machhws   - machhws.   */
5681
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5682
/* machhwso  - machhwso.  */
5683
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5684
/* machhwsu  - machhwsu.  */
5685
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5686
/* machhwsuo - machhwsuo. */
5687
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5688
/* machhwu   - machhwu.   */
5689
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5690
/* machhwuo  - machhwuo.  */
5691
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5692
/* maclhw    - maclhw.    */
5693
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5694
/* maclhwo   - maclhwo.   */
5695
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5696
/* maclhws   - maclhws.   */
5697
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5698
/* maclhwso  - maclhwso.  */
5699
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5700
/* maclhwu   - maclhwu.   */
5701
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5702
/* maclhwuo  - maclhwuo.  */
5703
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5704
/* maclhwsu  - maclhwsu.  */
5705
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5706
/* maclhwsuo - maclhwsuo. */
5707
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5708
/* nmacchw   - nmacchw.   */
5709
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5710
/* nmacchwo  - nmacchwo.  */
5711
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5712
/* nmacchws  - nmacchws.  */
5713
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5714
/* nmacchwso - nmacchwso. */
5715
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5716
/* nmachhw   - nmachhw.   */
5717
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5718
/* nmachhwo  - nmachhwo.  */
5719
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5720
/* nmachhws  - nmachhws.  */
5721
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5722
/* nmachhwso - nmachhwso. */
5723
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5724
/* nmaclhw   - nmaclhw.   */
5725
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5726
/* nmaclhwo  - nmaclhwo.  */
5727
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5728
/* nmaclhws  - nmaclhws.  */
5729
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5730
/* nmaclhwso - nmaclhwso. */
5731
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5732 5733

/* mulchw  - mulchw.  */
5734
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5735
/* mulchwu - mulchwu. */
5736
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5737
/* mulhhw  - mulhhw.  */
5738
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5739
/* mulhhwu - mulhhwu. */
5740
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5741
/* mullhw  - mullhw.  */
5742
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5743
/* mullhwu - mullhwu. */
5744
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5745 5746

/* mfdcr */
B
Blue Swirl 已提交
5747
static void gen_mfdcr(DisasContext *ctx)
5748 5749
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5750
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5751
#else
5752
    TCGv dcrn;
A
aurel32 已提交
5753
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5754
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5755 5756
        return;
    }
5757 5758 5759
    /* 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));
5760
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5761
    tcg_temp_free(dcrn);
5762 5763 5764 5765
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5766
static void gen_mtdcr(DisasContext *ctx)
5767 5768
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5769
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5770
#else
5771
    TCGv dcrn;
A
aurel32 已提交
5772
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5773
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5774 5775
        return;
    }
5776 5777 5778
    /* 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));
5779
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5780
    tcg_temp_free(dcrn);
5781 5782 5783 5784
#endif
}

/* mfdcrx */
5785
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5786
static void gen_mfdcrx(DisasContext *ctx)
5787 5788
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5789
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5790
#else
A
aurel32 已提交
5791
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5792
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5793 5794
        return;
    }
5795 5796
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5797 5798
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5799
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5800 5801 5802 5803
#endif
}

/* mtdcrx */
5804
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5805
static void gen_mtdcrx(DisasContext *ctx)
5806 5807
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5808
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5809
#else
A
aurel32 已提交
5810
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5811
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5812 5813
        return;
    }
5814 5815
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5816 5817
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
5818
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5819 5820 5821
#endif
}

5822
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5823
static void gen_mfdcrux(DisasContext *ctx)
5824
{
5825 5826
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5827 5828
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5829 5830 5831 5832
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5833
static void gen_mtdcrux(DisasContext *ctx)
5834
{
5835 5836
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5837
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5838
                         cpu_gpr[rS(ctx->opcode)]);
5839 5840 5841
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5842
/* dccci */
B
Blue Swirl 已提交
5843
static void gen_dccci(DisasContext *ctx)
5844 5845
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5846
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5847
#else
A
aurel32 已提交
5848
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5849
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5850 5851 5852 5853 5854 5855 5856
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5857
static void gen_dcread(DisasContext *ctx)
5858 5859
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5860
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5861
#else
A
aurel32 已提交
5862
    TCGv EA, val;
A
aurel32 已提交
5863
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5864
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5865 5866
        return;
    }
A
aurel32 已提交
5867
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5868
    EA = tcg_temp_new();
A
aurel32 已提交
5869
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5870
    val = tcg_temp_new();
A
aurel32 已提交
5871
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5872 5873 5874
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5875 5876 5877 5878
#endif
}

/* icbt */
B
Blue Swirl 已提交
5879
static void gen_icbt_40x(DisasContext *ctx)
5880 5881 5882 5883 5884 5885 5886 5887
{
    /* 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 已提交
5888
static void gen_iccci(DisasContext *ctx)
5889 5890
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5891
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5892
#else
A
aurel32 已提交
5893
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5894
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5895 5896 5897 5898 5899 5900 5901
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5902
static void gen_icread(DisasContext *ctx)
5903 5904
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5905
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5906
#else
A
aurel32 已提交
5907
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5908
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5909 5910 5911 5912 5913 5914
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5915
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5916
static void gen_rfci_40x(DisasContext *ctx)
5917 5918
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5919
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5920
#else
A
aurel32 已提交
5921
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5922
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5923 5924 5925
        return;
    }
    /* Restore CPU state */
5926
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
5927
    gen_sync_exception(ctx);
5928 5929 5930
#endif
}

B
Blue Swirl 已提交
5931
static void gen_rfci(DisasContext *ctx)
5932 5933
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5934
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5935
#else
A
aurel32 已提交
5936
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5937
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5938 5939 5940
        return;
    }
    /* Restore CPU state */
5941
    gen_helper_rfci(cpu_env);
A
aurel32 已提交
5942
    gen_sync_exception(ctx);
5943 5944 5945 5946
#endif
}

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

5948
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5949
static void gen_rfdi(DisasContext *ctx)
5950 5951
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5952
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5953
#else
A
aurel32 已提交
5954
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5955
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5956 5957 5958
        return;
    }
    /* Restore CPU state */
5959
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
5960
    gen_sync_exception(ctx);
5961 5962 5963
#endif
}

5964
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5965
static void gen_rfmci(DisasContext *ctx)
5966 5967
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5968
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5969
#else
A
aurel32 已提交
5970
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5971
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5972 5973 5974
        return;
    }
    /* Restore CPU state */
5975
    gen_helper_rfmci(cpu_env);
A
aurel32 已提交
5976
    gen_sync_exception(ctx);
5977 5978
#endif
}
5979

5980
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5981

5982
/* tlbre */
B
Blue Swirl 已提交
5983
static void gen_tlbre_40x(DisasContext *ctx)
5984 5985
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5986
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5987
#else
A
aurel32 已提交
5988
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5989
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5990 5991 5992 5993
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5994 5995
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5996 5997
        break;
    case 1:
5998 5999
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
6000 6001
        break;
    default:
A
aurel32 已提交
6002
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6003
        break;
6004
    }
6005 6006 6007
#endif
}

6008
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6009
static void gen_tlbsx_40x(DisasContext *ctx)
6010 6011
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6012
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6013
#else
6014
    TCGv t0;
A
aurel32 已提交
6015
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6016
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6017 6018
        return;
    }
6019
    t0 = tcg_temp_new();
A
aurel32 已提交
6020
    gen_addr_reg_index(ctx, t0);
6021
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6022 6023 6024
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
6025
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6026 6027 6028 6029
        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);
    }
6030
#endif
B
bellard 已提交
6031 6032
}

6033
/* tlbwe */
B
Blue Swirl 已提交
6034
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
6035
{
6036
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6037
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6038
#else
A
aurel32 已提交
6039
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6040
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6041 6042 6043 6044
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
6045 6046
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6047 6048
        break;
    case 1:
6049 6050
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6051 6052
        break;
    default:
A
aurel32 已提交
6053
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6054
        break;
6055
    }
6056 6057 6058
#endif
}

6059
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
6060

6061
/* tlbre */
B
Blue Swirl 已提交
6062
static void gen_tlbre_440(DisasContext *ctx)
6063 6064
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6065
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6066
#else
A
aurel32 已提交
6067
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6068
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6069 6070 6071 6072 6073 6074
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6075 6076
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6077 6078
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
6079 6080
            tcg_temp_free_i32(t0);
        }
6081 6082
        break;
    default:
A
aurel32 已提交
6083
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6084 6085 6086 6087 6088 6089
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6090
static void gen_tlbsx_440(DisasContext *ctx)
6091 6092
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6093
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6094
#else
6095
    TCGv t0;
A
aurel32 已提交
6096
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6097
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6098 6099
        return;
    }
6100
    t0 = tcg_temp_new();
A
aurel32 已提交
6101
    gen_addr_reg_index(ctx, t0);
6102
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6103 6104 6105
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
6106
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6107 6108 6109 6110
        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);
    }
6111 6112 6113 6114
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
6115
static void gen_tlbwe_440(DisasContext *ctx)
6116 6117
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6118
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6119
#else
A
aurel32 已提交
6120
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6121
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6122 6123 6124 6125 6126 6127
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6128 6129
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6130 6131
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
6132 6133
            tcg_temp_free_i32(t0);
        }
6134 6135
        break;
    default:
A
aurel32 已提交
6136
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6137 6138 6139 6140 6141
        break;
    }
#endif
}

A
Alexander Graf 已提交
6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154
/* 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;
    }

6155
    gen_helper_booke206_tlbre(cpu_env);
A
Alexander Graf 已提交
6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178
#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)]);
6179
    gen_helper_booke206_tlbsx(cpu_env, t0);
A
Alexander Graf 已提交
6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192
#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;
    }
6193
    gen_update_nip(ctx, ctx->nip - 4);
6194
    gen_helper_booke206_tlbwe(cpu_env);
A
Alexander Graf 已提交
6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211
#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);

6212
    gen_helper_booke206_tlbivax(cpu_env, t0);
A
Alexander Graf 已提交
6213 6214 6215
#endif
}

A
Alexander Graf 已提交
6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231
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:
6232
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6233 6234
        break;
    case 1:
6235
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6236 6237
        break;
    case 3:
6238
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6239 6240 6241 6242 6243 6244 6245 6246 6247 6248
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6249

6250
/* wrtee */
B
Blue Swirl 已提交
6251
static void gen_wrtee(DisasContext *ctx)
6252 6253
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6254
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6255
#else
6256
    TCGv t0;
A
aurel32 已提交
6257
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6258
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6259 6260
        return;
    }
6261 6262 6263 6264 6265
    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 已提交
6266 6267 6268
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6269
    gen_stop_exception(ctx);
6270 6271 6272 6273
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6274
static void gen_wrteei(DisasContext *ctx)
6275 6276
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6277
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6278
#else
A
aurel32 已提交
6279
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6280
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6281 6282
        return;
    }
6283
    if (ctx->opcode & 0x00008000) {
6284 6285
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6286
        gen_stop_exception(ctx);
6287
    } else {
A
aurel32 已提交
6288
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6289
    }
6290 6291 6292
#endif
}

J
j_mayer 已提交
6293
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6294

6295
/* dlmzb */
B
Blue Swirl 已提交
6296
static void gen_dlmzb(DisasContext *ctx)
6297
{
6298
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6299 6300
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6301
    tcg_temp_free_i32(t0);
6302 6303 6304
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6305
static void gen_mbar(DisasContext *ctx)
6306 6307 6308 6309 6310
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6311
static void gen_msync_4xx(DisasContext *ctx)
6312 6313 6314 6315 6316
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6317
static void gen_icbt_440(DisasContext *ctx)
6318 6319 6320 6321 6322
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6323 6324
}

A
Alexander Graf 已提交
6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336
/* 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;
    }

6337
    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
A
Alexander Graf 已提交
6338 6339 6340
#endif
}

A
Alexander Graf 已提交
6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354
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
}

6355 6356 6357
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6358
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6359
{
A
aurel32 已提交
6360
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6361 6362 6363 6364
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6365
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6366
static void glue(gen_, name)(DisasContext *ctx)                                       \
6367
{                                                                             \
6368
    TCGv EA;                                                                  \
6369
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6370
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6371 6372
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6373
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6374
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6375
    gen_addr_reg_index(ctx, EA);                                              \
6376
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6377 6378
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6379
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6380
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6381
    } else {                                                                  \
A
aurel32 已提交
6382
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6383
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6384
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6385 6386
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6387 6388 6389
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6390
static void gen_st##name(DisasContext *ctx)                                   \
6391
{                                                                             \
6392
    TCGv EA;                                                                  \
6393
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6394
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6395 6396
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6397
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6398
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6399
    gen_addr_reg_index(ctx, EA);                                              \
6400
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6401 6402
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6403
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6404
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6405
    } else {                                                                  \
A
aurel32 已提交
6406
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6407
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6408
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6409 6410
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6411 6412
}

A
aurel32 已提交
6413
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6414
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425
    {                                                                   \
        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));                              \
6426
        gen_helper_lve##name(cpu_env, rs, EA);                          \
A
aurel32 已提交
6427 6428 6429 6430 6431
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6432
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443
    {                                                                   \
        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));                              \
6444
        gen_helper_stve##name(cpu_env, rs, EA);                         \
A
aurel32 已提交
6445 6446 6447 6448
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6449
GEN_VR_LDX(lvx, 0x07, 0x03);
6450
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6451
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6452

A
aurel32 已提交
6453 6454 6455 6456
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6457
GEN_VR_STX(svx, 0x07, 0x07);
6458
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6459
GEN_VR_STX(svxl, 0x07, 0x0F);
6460

A
aurel32 已提交
6461 6462 6463 6464
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6465
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480
{
    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 已提交
6481
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496
{
    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 已提交
6497
static void gen_mfvscr(DisasContext *ctx)
6498 6499 6500 6501 6502 6503 6504 6505
{
    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();
6506
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6507
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6508
    tcg_temp_free_i32(t);
6509 6510
}

B
Blue Swirl 已提交
6511
static void gen_mtvscr(DisasContext *ctx)
6512
{
A
aurel32 已提交
6513
    TCGv_ptr p;
6514 6515 6516 6517
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6518
    p = gen_avr_ptr(rD(ctx->opcode));
6519
    gen_helper_mtvscr(cpu_env, p);
A
aurel32 已提交
6520
    tcg_temp_free_ptr(p);
6521 6522
}

6523 6524
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6525
static void glue(gen_, name)(DisasContext *ctx)                                 \
6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540
{                                                                       \
    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);

6541
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6542
static void glue(gen_, name)(DisasContext *ctx)                                 \
6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557
{                                                                       \
    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);                                              \
}

6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568
#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));                                  \
6569
    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6570 6571 6572 6573 6574
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6575 6576 6577 6578 6579 6580
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);
6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592
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 已提交
6593 6594 6595 6596 6597 6598
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 已提交
6599 6600 6601 6602 6603 6604
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 已提交
6605 6606 6607 6608 6609 6610 6611 6612
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 已提交
6613 6614 6615
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6616 6617 6618 6619 6620 6621
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 已提交
6622 6623
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6624 6625
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637
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 已提交
6638 6639 6640
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6641 6642
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6643 6644 6645 6646 6647 6648 6649 6650
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 已提交
6651
GEN_VXFORM(vpkpx, 7, 12);
6652 6653 6654 6655 6656 6657 6658 6659 6660
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 已提交
6661

6662
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6663
static void glue(gen_, name)(DisasContext *ctx)                         \
6664 6665 6666 6667 6668 6669 6670 6671 6672
    {                                                                   \
        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));                              \
6673
        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
6674 6675 6676 6677 6678 6679 6680 6681 6682
        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)))

6683 6684 6685 6686 6687 6688 6689 6690 6691
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)
6692 6693 6694 6695
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6696

A
aurel32 已提交
6697
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6698
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716
    {                                                                   \
        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);

6717
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6718
static void glue(gen_, name)(DisasContext *ctx)                                 \
6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731
    {                                                                   \
        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);                                         \
    }

6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747
#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 已提交
6748 6749 6750 6751
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 已提交
6752 6753
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
6754 6755 6756 6757 6758 6759 6760 6761
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 已提交
6762

6763
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6764
static void glue(gen_, name)(DisasContext *ctx)                                 \
6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778
    {                                                                   \
        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);                                          \
    }

6779
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6780
static void glue(gen_, name)(DisasContext *ctx)                                 \
6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796
    {                                                                   \
        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);                                          \
    }

6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815
#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 已提交
6816 6817 6818
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
6819 6820 6821 6822
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 已提交
6823

B
Blue Swirl 已提交
6824
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6825 6826
{
    TCGv_ptr ra, rb, rd;
6827
    TCGv_i32 sh;
A
aurel32 已提交
6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839
    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);
6840
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6841 6842
}

6843
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6844
static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855
    {                                                                   \
        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)) {                                          \
6856
            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
6857
        } else {                                                        \
6858
            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
6859 6860 6861 6862 6863 6864 6865
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6866 6867
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6868
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885
{
    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 已提交
6886
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6887
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6888
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6889
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6890
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6891

6892 6893
/***                           SPE extension                               ***/
/* Register moves */
6894

6895 6896 6897 6898 6899

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6900
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6901 6902 6903 6904 6905 6906 6907 6908 6909 6910
        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,
6911
                   offsetof(CPUPPCState, spe_acc));
6912 6913 6914 6915 6916 6917 6918
#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 */
6919
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
6920 6921 6922 6923 6924 6925 6926 6927
    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 已提交
6928 6929
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6930 6931 6932
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6933
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6934
#endif
A
aurel32 已提交
6935
}
6936

B
Blue Swirl 已提交
6937 6938
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6939 6940 6941
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6942
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6943 6944 6945
    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 已提交
6946
    tcg_temp_free_i64(tmp);
6947
#endif
A
aurel32 已提交
6948
}
6949

6950
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
6951
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6952 6953 6954 6955 6956 6957 6958 6959
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6960
static inline void gen_speundef(DisasContext *ctx)
6961
{
A
aurel32 已提交
6962
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6963 6964
}

6965 6966 6967
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6968
static inline void gen_##name(DisasContext *ctx)                              \
6969 6970
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6971
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6972 6973
        return;                                                               \
    }                                                                         \
6974 6975 6976 6977 6978
    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 已提交
6979
static inline void gen_##name(DisasContext *ctx)                              \
6980 6981
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6982
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6983 6984 6985 6986 6987 6988
        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)]);                                        \
6989
}
6990 6991 6992 6993 6994 6995 6996 6997 6998 6999
#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);
7000

7001 7002 7003
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
7004
static inline void gen_##name(DisasContext *ctx)                              \
7005 7006
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7007
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7008 7009
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7010 7011 7012
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7013 7014 7015 7016
    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 已提交
7017
    tcg_temp_free_i64(t2);                                                    \
7018 7019
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7020 7021
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7022
}
7023 7024
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
7025
static inline void gen_##name(DisasContext *ctx)                              \
7026 7027
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7028
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7029 7030
        return;                                                               \
    }                                                                         \
7031 7032 7033 7034
    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));                                                 \
7035
}
7036 7037 7038 7039 7040
#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);
7041

7042 7043 7044
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7045
static inline void gen_##name(DisasContext *ctx)                              \
7046 7047
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7048
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7049 7050
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7051 7052 7053
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7054 7055 7056 7057
    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 已提交
7058
    tcg_temp_free_i64(t2);                                                    \
7059 7060
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7061 7062
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7063
}
7064
#else
P
pbrook 已提交
7065
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7066
static inline void gen_##name(DisasContext *ctx)                              \
7067 7068
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7069
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7070 7071 7072 7073 7074 7075
        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
7076

B
Blue Swirl 已提交
7077
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
7078 7079 7080
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
7081

7082 7083 7084 7085
    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 已提交
7086
    tcg_gen_mov_i32(ret, arg1);
7087 7088 7089 7090 7091 7092
    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 已提交
7093
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
7094
{
7095 7096 7097 7098
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
7099 7100
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
7101

7102 7103
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7104
static inline void gen_##name(DisasContext *ctx)                              \
7105 7106
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7107
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7108 7109
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7110 7111 7112
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
7113
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
7114 7115 7116 7117 7118 7119 7120
    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 已提交
7121
    tcg_temp_free_i64(t3);                                                    \
7122
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
7123
    tcg_temp_free_i32(t2);                                                    \
7124
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7125 7126
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7127
}
7128 7129
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7130
static inline void gen_##name(DisasContext *ctx)                              \
7131 7132
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7133
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7134 7135
        return;                                                               \
    }                                                                         \
7136 7137 7138 7139
    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)]);                                        \
7140
}
7141
#endif
7142

B
Blue Swirl 已提交
7143
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7144
{
P
pbrook 已提交
7145
    TCGv_i32 t0;
7146
    int l1, l2;
7147

7148 7149
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7150
    t0 = tcg_temp_local_new_i32();
7151 7152 7153 7154 7155 7156 7157
    /* 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);
7158
    gen_set_label(l2);
P
pbrook 已提交
7159
    tcg_temp_free_i32(t0);
7160 7161
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7162
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7163
{
P
pbrook 已提交
7164
    TCGv_i32 t0;
7165 7166 7167 7168
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7169
    t0 = tcg_temp_local_new_i32();
7170 7171 7172 7173 7174 7175 7176
    /* 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);
7177
    gen_set_label(l2);
P
pbrook 已提交
7178
    tcg_temp_free_i32(t0);
7179 7180
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7181
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7182
{
P
pbrook 已提交
7183
    TCGv_i32 t0;
7184 7185 7186 7187
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7188
    t0 = tcg_temp_local_new_i32();
7189 7190 7191 7192 7193 7194 7195
    /* 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);
7196
    gen_set_label(l2);
P
pbrook 已提交
7197
    tcg_temp_free_i32(t0);
7198 7199
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7200
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7201
{
P
pbrook 已提交
7202
    TCGv_i32 t0 = tcg_temp_new_i32();
7203 7204
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7205
    tcg_temp_free_i32(t0);
7206 7207
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7208
static inline void gen_evmergehi(DisasContext *ctx)
7209 7210
{
    if (unlikely(!ctx->spe_enabled)) {
7211
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7212 7213 7214
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7215 7216
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227
    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 已提交
7228
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7229
{
7230 7231 7232
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7233

7234 7235 7236
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7237
static inline void gen_##name(DisasContext *ctx)                              \
7238 7239
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7240
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7241 7242
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7243 7244 7245
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7246 7247 7248 7249
    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 已提交
7250
    tcg_temp_free_i64(t2);                                                    \
7251 7252
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7253 7254
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7255 7256 7257
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7258
static inline void gen_##name(DisasContext *ctx)                              \
7259 7260
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7261
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275
        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 已提交
7276
static inline void gen_##name(DisasContext *ctx)                              \
7277 7278
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7279
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7280 7281 7282 7283 7284 7285
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7286 7287 7288
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7289 7290 7291
    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 已提交
7292
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7293 7294 7295 7296 7297 7298 7299 7300 7301
    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 已提交
7302
    tcg_temp_free_i64(t2);                                                    \
7303 7304 7305 7306 7307 7308 7309 7310
    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 已提交
7311 7312
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7313 7314 7315
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7316
static inline void gen_##name(DisasContext *ctx)                              \
7317 7318
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7319
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352
        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 已提交
7353
static inline void gen_brinc(DisasContext *ctx)
7354 7355
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7356 7357
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7358
}
B
Blue Swirl 已提交
7359
static inline void gen_evmergelo(DisasContext *ctx)
7360 7361
{
    if (unlikely(!ctx->spe_enabled)) {
7362
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7363 7364 7365
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7366 7367
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7368
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7369 7370 7371 7372 7373 7374
    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)]);
7375
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7376 7377
#endif
}
B
Blue Swirl 已提交
7378
static inline void gen_evmergehilo(DisasContext *ctx)
7379 7380
{
    if (unlikely(!ctx->spe_enabled)) {
7381
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7382 7383 7384
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7385 7386
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7387
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7388 7389 7390 7391 7392 7393 7394 7395 7396
    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 已提交
7397
static inline void gen_evmergelohi(DisasContext *ctx)
7398 7399
{
    if (unlikely(!ctx->spe_enabled)) {
7400
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7401 7402 7403
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7404 7405
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7406 7407 7408 7409 7410 7411
    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
7412 7413 7414 7415 7416 7417 7418 7419 7420 7421
    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)]);
    }
7422 7423
#endif
}
B
Blue Swirl 已提交
7424
static inline void gen_evsplati(DisasContext *ctx)
7425
{
7426
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7427

7428
#if defined(TARGET_PPC64)
7429
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7430 7431 7432 7433 7434
#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 已提交
7435
static inline void gen_evsplatfi(DisasContext *ctx)
7436
{
7437
    uint64_t imm = rA(ctx->opcode) << 27;
7438

7439
#if defined(TARGET_PPC64)
7440
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7441 7442 7443 7444
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7445 7446
}

B
Blue Swirl 已提交
7447
static inline void gen_evsel(DisasContext *ctx)
7448 7449 7450 7451 7452
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7453
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7454
#if defined(TARGET_PPC64)
P
pbrook 已提交
7455 7456
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475
#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)
7476
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7477 7478 7479 7480 7481 7482
#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)
7483
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7484 7485 7486 7487
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7488
    tcg_temp_free_i32(t0);
7489 7490 7491 7492 7493 7494
#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 已提交
7495 7496

static void gen_evsel0(DisasContext *ctx)
7497 7498 7499
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7500 7501

static void gen_evsel1(DisasContext *ctx)
7502 7503 7504
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7505 7506

static void gen_evsel2(DisasContext *ctx)
7507 7508 7509
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7510 7511

static void gen_evsel3(DisasContext *ctx)
7512 7513 7514
{
    gen_evsel(ctx);
}
7515

7516 7517 7518 7519 7520 7521 7522
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7523
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551
        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)) {
7552
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7553 7554 7555 7556 7557 7558 7559 7560 7561
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7562
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7563 7564 7565 7566 7567 7568 7569 7570 7571
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7572
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584
        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 */
7585
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7586 7587 7588 7589 7590

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

    /* Store acc */
7591
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604

    /* 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)) {
7605
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638
        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));
7639
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657

    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 */
7658
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7659 7660 7661 7662 7663

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

    /* Store acc */
7664
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7665 7666 7667 7668 7669 7670 7671 7672

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701
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); ////
7702

7703
/* SPE load and stores */
B
Blue Swirl 已提交
7704
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7705 7706 7707
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7708
    if (rA(ctx->opcode) == 0) {
7709
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7710
    } else {
7711
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7712 7713 7714 7715 7716 7717
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7718
}
7719

B
Blue Swirl 已提交
7720
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7721 7722
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7723
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7724 7725
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7726
    gen_qemu_ld64(ctx, t0, addr);
7727 7728 7729 7730 7731
    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
7732
}
7733

B
Blue Swirl 已提交
7734
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7735
{
7736
#if defined(TARGET_PPC64)
7737
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7738
    gen_qemu_ld32u(ctx, t0, addr);
7739
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7740 7741
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7742 7743 7744
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7745 7746 7747
    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);
7748
#endif
7749
}
7750

B
Blue Swirl 已提交
7751
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7752 7753 7754
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7755
    gen_qemu_ld16u(ctx, t0, addr);
7756
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7757 7758
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7759 7760
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7761 7762
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7763 7764
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7765 7766
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7767
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7768
#else
A
aurel32 已提交
7769
    gen_qemu_ld16u(ctx, t0, addr);
7770
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7771 7772
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7773
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7774 7775
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7776
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7777 7778
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7779
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7780
#endif
7781
    tcg_temp_free(t0);
7782 7783
}

B
Blue Swirl 已提交
7784
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7785 7786
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7787
    gen_qemu_ld16u(ctx, t0, addr);
7788 7789 7790 7791 7792 7793 7794 7795 7796 7797
#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);
7798 7799
}

B
Blue Swirl 已提交
7800
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7801 7802
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7803
    gen_qemu_ld16u(ctx, t0, addr);
7804 7805 7806 7807 7808 7809 7810 7811
#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);
7812 7813
}

B
Blue Swirl 已提交
7814
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7815 7816
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7817
    gen_qemu_ld16s(ctx, t0, addr);
7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828
#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 已提交
7829
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7830 7831 7832
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7833
    gen_qemu_ld16u(ctx, t0, addr);
7834
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7835 7836
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7837 7838 7839
    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 已提交
7840
    gen_qemu_ld16u(ctx, t0, addr);
7841
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7842 7843
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7844 7845 7846 7847 7848
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7849
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7850 7851 7852
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7853 7854 7855
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7856 7857 7858 7859
    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 已提交
7860 7861 7862
    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);
7863 7864 7865
#endif
}

B
Blue Swirl 已提交
7866
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7867 7868 7869
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7870
    gen_qemu_ld16s(ctx, t0, addr);
7871
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7872 7873
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7874 7875 7876 7877
    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 已提交
7878 7879 7880
    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);
7881 7882 7883
#endif
}

B
Blue Swirl 已提交
7884
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7885 7886
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7887
    gen_qemu_ld32u(ctx, t0, addr);
7888
#if defined(TARGET_PPC64)
7889 7890 7891 7892 7893 7894 7895 7896 7897
    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 已提交
7898
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7899 7900 7901
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7902
    gen_qemu_ld16u(ctx, t0, addr);
7903 7904 7905
    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 已提交
7906 7907
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7908 7909 7910 7911
    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 已提交
7912
    gen_qemu_ld16u(ctx, t0, addr);
7913 7914
    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 已提交
7915 7916
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7917 7918
    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);
7919
#endif
7920 7921 7922
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7923
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7924 7925
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7926
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7927
#else
7928 7929
    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 已提交
7930
    gen_qemu_st64(ctx, t0, addr);
7931 7932 7933 7934
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7935
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7936
{
7937
#if defined(TARGET_PPC64)
7938 7939
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7940
    gen_qemu_st32(ctx, t0, addr);
7941 7942
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7943
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7944
#endif
A
aurel32 已提交
7945 7946
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7947 7948
}

B
Blue Swirl 已提交
7949
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7950 7951 7952 7953 7954 7955 7956
{
    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 已提交
7957 7958
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7959 7960
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7961
    gen_qemu_st16(ctx, t0, addr);
7962
#else
A
aurel32 已提交
7963
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7964
#endif
A
aurel32 已提交
7965
    gen_addr_add(ctx, addr, addr, 2);
7966
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7967
    gen_qemu_st16(ctx, t0, addr);
7968
    tcg_temp_free(t0);
A
aurel32 已提交
7969 7970
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7971 7972
}

B
Blue Swirl 已提交
7973
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7974 7975 7976 7977 7978 7979 7980
{
    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 已提交
7981 7982
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7983
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7984
    gen_qemu_st16(ctx, t0, addr);
7985 7986 7987
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7988
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7989 7990 7991 7992
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7993
    gen_qemu_st16(ctx, t0, addr);
7994 7995
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7996
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7997
#endif
A
aurel32 已提交
7998 7999
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8000 8001
}

B
Blue Swirl 已提交
8002
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
8003 8004 8005 8006
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
8007
    gen_qemu_st32(ctx, t0, addr);
8008 8009
    tcg_temp_free(t0);
#else
A
aurel32 已提交
8010
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
8011 8012 8013
#endif
}

B
Blue Swirl 已提交
8014
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
8015
{
A
aurel32 已提交
8016
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8017 8018 8019
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
8020
static void glue(gen_, name)(DisasContext *ctx)                                       \
8021 8022 8023
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8024
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8025 8026
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8027
    gen_set_access_type(ctx, ACCESS_INT);                                     \
8028 8029
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
8030
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
8031
    } else {                                                                  \
A
aurel32 已提交
8032
        gen_addr_reg_index(ctx, t0);                                          \
8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056
    }                                                                         \
    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);
8057 8058 8059

/* Multiply and add - TODO */
#if 0
8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127
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);
8128 8129 8130
#endif

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
8131 8132
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8133
static inline void gen_##name(DisasContext *ctx)                              \
8134
{                                                                             \
A
aurel32 已提交
8135 8136 8137 8138
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8139
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8140 8141 8142 8143 8144 8145 8146
    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);                                                        \
8147
}
A
aurel32 已提交
8148
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8149
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8150 8151 8152 8153
{                                                                             \
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
8154
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8155 8156 8157 8158 8159 8160 8161 8162 8163
    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 已提交
8164
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8165 8166 8167
{                                                                             \
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8168
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8169 8170 8171
    tcg_temp_free_i32(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8172
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8173
{                                                                             \
8174 8175
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
A
aurel32 已提交
8176 8177
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8178
static inline void gen_##name(DisasContext *ctx)                              \
8179
{                                                                             \
A
aurel32 已提交
8180 8181
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
8182
    if (unlikely(!ctx->spe_enabled)) {                                        \
8183
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8184 8185
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8186 8187 8188 8189
    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)]);                       \
8190
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8191 8192 8193 8194 8195 8196 8197 8198
    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);                                                        \
8199
}
A
aurel32 已提交
8200
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8201
static inline void gen_##name(DisasContext *ctx)                              \
8202 8203
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8204
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8205 8206
        return;                                                               \
    }                                                                         \
8207 8208
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8209
}
A
aurel32 已提交
8210
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8211
static inline void gen_##name(DisasContext *ctx)                              \
8212
{                                                                             \
A
aurel32 已提交
8213
    TCGv_i32 t0, t1;                                                          \
8214
    if (unlikely(!ctx->spe_enabled)) {                                        \
8215
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8216 8217
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8218 8219 8220 8221
    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)]);                       \
8222
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8223 8224 8225 8226
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8227
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8228 8229
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8230
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8231 8232
        return;                                                               \
    }                                                                         \
8233
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8234 8235 8236 8237
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#else
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8238
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8239
{                                                                             \
8240 8241
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
8242
}
A
aurel32 已提交
8243
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8244
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8245 8246 8247
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8248
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8249 8250 8251
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
B
Blue Swirl 已提交
8252
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8253 8254
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
8255
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8256 8257 8258 8259
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8260
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8261 8262 8263
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8264
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8265 8266 8267 8268
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8269
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8270 8271
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8272
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8273 8274
        return;                                                               \
    }                                                                         \
8275
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
A
aurel32 已提交
8276 8277 8278
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8279
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8280 8281 8282
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8283
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8284 8285 8286 8287 8288 8289
        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));                                      \
8290
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8291 8292 8293 8294 8295
    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 已提交
8296
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8297 8298
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8299
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8300 8301
        return;                                                               \
    }                                                                         \
8302
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8303 8304 8305
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8306
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8307 8308 8309
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8310
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8311 8312 8313 8314 8315 8316
        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));                                      \
8317
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8318 8319 8320 8321
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#endif
8322

8323 8324
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8325 8326 8327 8328
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 已提交
8329
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8330 8331
{
    if (unlikely(!ctx->spe_enabled)) {
8332
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8333 8334 8335
        return;
    }
#if defined(TARGET_PPC64)
8336
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8337
#else
8338 8339
    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 已提交
8340 8341
#endif
}
B
Blue Swirl 已提交
8342
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8343 8344
{
    if (unlikely(!ctx->spe_enabled)) {
8345
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8346 8347 8348
        return;
    }
#if defined(TARGET_PPC64)
8349
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8350
#else
8351 8352
    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 已提交
8353 8354
#endif
}
B
Blue Swirl 已提交
8355
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8356 8357
{
    if (unlikely(!ctx->spe_enabled)) {
8358
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8359 8360 8361
        return;
    }
#if defined(TARGET_PPC64)
8362
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8363
#else
8364 8365
    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 已提交
8366 8367 8368
#endif
}

8369
/* Conversion */
A
aurel32 已提交
8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380
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);

8381
/* Comparison */
A
aurel32 已提交
8382 8383 8384 8385 8386 8387
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);
8388 8389

/* Opcodes definitions */
8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403
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); //
8404 8405 8406

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8407 8408 8409 8410
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 已提交
8411
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8412 8413
{
    if (unlikely(!ctx->spe_enabled)) {
8414
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8415 8416
        return;
    }
8417
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8418
}
B
Blue Swirl 已提交
8419
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8420 8421
{
    if (unlikely(!ctx->spe_enabled)) {
8422
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8423 8424
        return;
    }
8425
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8426
}
B
Blue Swirl 已提交
8427
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8428 8429
{
    if (unlikely(!ctx->spe_enabled)) {
8430
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8431 8432
        return;
    }
8433
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8434 8435
}

8436
/* Conversion */
A
aurel32 已提交
8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448
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);

8449
/* Comparison */
A
aurel32 已提交
8450 8451 8452 8453 8454 8455
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);
8456 8457

/* Opcodes definitions */
8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471
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); //
8472 8473 8474

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8475 8476 8477 8478
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 已提交
8479
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8480 8481
{
    if (unlikely(!ctx->spe_enabled)) {
8482
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8483 8484 8485
        return;
    }
#if defined(TARGET_PPC64)
8486
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8487
#else
8488 8489
    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 已提交
8490 8491
#endif
}
B
Blue Swirl 已提交
8492
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8493 8494
{
    if (unlikely(!ctx->spe_enabled)) {
8495
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8496 8497 8498
        return;
    }
#if defined(TARGET_PPC64)
8499
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8500
#else
8501 8502
    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 已提交
8503 8504
#endif
}
B
Blue Swirl 已提交
8505
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8506 8507
{
    if (unlikely(!ctx->spe_enabled)) {
8508
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8509 8510 8511
        return;
    }
#if defined(TARGET_PPC64)
8512
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8513
#else
8514 8515
    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 已提交
8516 8517 8518
#endif
}

8519
/* Conversion */
A
aurel32 已提交
8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534
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);
8535 8536

/* Comparison */
A
aurel32 已提交
8537 8538 8539 8540 8541 8542
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);
8543 8544

/* Opcodes definitions */
8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560
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); //
8561

A
Anthony Liguori 已提交
8562
static opcode_t opcodes[] = {
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
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),
8594
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8595
#if defined(TARGET_PPC64)
8596
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
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
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),
8638
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8639 8640
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8641
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678
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 已提交
8679
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695
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),
8696 8697 8698
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),
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
#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 已提交
8779
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8780 8781 8782 8783 8784 8785 8786 8787
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 已提交
8788 8789 8790 8791 8792 8793 8794 8795
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 已提交
8796 8797
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8798 8799
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8800 8801
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8802
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8803
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8804
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8805 8806
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8807
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8808 8809
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 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
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
8982
#undef GEN_LDX_E
8983 8984 8985 8986 8987 8988 8989
#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),
8990 8991
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006
#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)
9007
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
9008 9009 9010 9011 9012 9013 9014
#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
9015
#undef GEN_STX_E
9016 9017 9018 9019 9020 9021 9022
#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),
9023 9024
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036
#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)
9037
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305
#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),
9306
GEN_VXFORM_NOA(vexptefp, 5, 6),
9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334
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
9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 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 9412
#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),
9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437

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

9438
#include "helper_regs.h"
A
Andreas Färber 已提交
9439
#include "translate_init.c"
B
bellard 已提交
9440

9441
/*****************************************************************************/
9442
/* Misc PowerPC helpers */
9443
void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
9444
                     int flags)
B
bellard 已提交
9445
{
9446 9447 9448
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9449 9450
    int i;

9451 9452
    cpu_synchronize_state(env);

9453
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9454
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9455
                env->nip, env->lr, env->ctr, cpu_read_xer(env));
9456 9457 9458
    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);
9459
#if !defined(NO_TIMER_DUMP)
9460
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9461
#if !defined(CONFIG_USER_ONLY)
9462
                " DECR %08" PRIu32
9463 9464
#endif
                "\n",
J
j_mayer 已提交
9465
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9466 9467 9468 9469
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9470
#endif
9471
    for (i = 0; i < 32; i++) {
9472 9473
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9474
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9475
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9476
            cpu_fprintf(f, "\n");
9477
    }
9478
    cpu_fprintf(f, "CR ");
9479
    for (i = 0; i < 8; i++)
B
bellard 已提交
9480 9481
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9482 9483 9484 9485 9486 9487 9488 9489
    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 已提交
9490
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9491
    }
9492 9493
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9494 9495 9496
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9497
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9498
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9499
            cpu_fprintf(f, "\n");
B
bellard 已提交
9500
    }
9501
    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
9502
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550
    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 已提交
9551 9552 9553 9554 9555 9556
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567
    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_620:
    case POWERPC_MMU_64B:
#endif
        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
        break;
A
Alexander Graf 已提交
9568
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586
        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;
    }
9587
#endif
B
bellard 已提交
9588

9589 9590
#undef RGPL
#undef RFPL
B
bellard 已提交
9591 9592
}

9593
void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
9594 9595 9596
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9597
    opc_handler_t **t1, **t2, **t3, *handler;
9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613
    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 已提交
9614
                                    "%016" PRIx64 " %" PRId64 "\n",
9615 9616 9617 9618 9619 9620 9621 9622
                                    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 已提交
9623
                                "%016" PRIx64 " %" PRId64 "\n",
9624 9625 9626 9627 9628 9629 9630
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9631 9632
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9633 9634 9635 9636 9637 9638 9639
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9640
/*****************************************************************************/
9641
static inline void gen_intermediate_code_internal(CPUPPCState *env,
B
Blue Swirl 已提交
9642 9643
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9644
{
9645
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9646
    opc_handler_t **table, *handler;
B
bellard 已提交
9647
    target_ulong pc_start;
B
bellard 已提交
9648
    uint16_t *gen_opc_end;
9649
    CPUBreakpoint *bp;
B
bellard 已提交
9650
    int j, lj = -1;
P
pbrook 已提交
9651 9652
    int num_insns;
    int max_insns;
B
bellard 已提交
9653 9654

    pc_start = tb->pc;
9655
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9656
    ctx.nip = pc_start;
B
bellard 已提交
9657
    ctx.tb = tb;
9658
    ctx.exception = POWERPC_EXCP_NONE;
9659
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9660 9661 9662
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9663
#if defined(TARGET_PPC64)
A
Alexander Graf 已提交
9664
    ctx.sf_mode = msr_is_64bit(env, env->msr);
D
David Gibson 已提交
9665
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9666
#endif
B
bellard 已提交
9667
    ctx.fpu_enabled = msr_fp;
9668
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9669 9670 9671
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9672 9673 9674 9675
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9676
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9677
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9678
    else
9679
        ctx.singlestep_enabled = 0;
9680
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9681 9682 9683
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9684
#if defined (DO_SINGLE_STEP) && 0
9685 9686 9687
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9688 9689 9690 9691 9692 9693
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
9694
    /* Set env in case of segfault during code fetch */
9695 9696
    while (ctx.exception == POWERPC_EXCP_NONE
            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9697 9698
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9699
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9700
                    gen_debug_exception(ctxp);
9701 9702 9703 9704
                    break;
                }
            }
        }
9705
        if (unlikely(search_pc)) {
9706
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
B
bellard 已提交
9707 9708 9709
            if (lj < j) {
                lj++;
                while (lj < j)
9710
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
9711
            }
9712
            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
9713
            tcg_ctx.gen_opc_instr_start[lj] = 1;
9714
            tcg_ctx.gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9715
        }
9716
        LOG_DISAS("----------------\n");
9717
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9718
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9719 9720
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9721
        if (unlikely(ctx.le_mode)) {
9722
            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
9723
        } else {
9724
            ctx.opcode = cpu_ldl_code(env, ctx.nip);
9725
        }
9726
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9727
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9728
                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
9729
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9730
            tcg_gen_debug_insn_start(ctx.nip);
9731
        }
B
bellard 已提交
9732
        ctx.nip += 4;
9733
        table = env->opcodes;
P
pbrook 已提交
9734
        num_insns++;
B
bellard 已提交
9735 9736 9737 9738 9739 9740 9741 9742 9743 9744
        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 ? */
9745
        if (unlikely(handler->handler == &gen_invalid)) {
9746 9747
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9748 9749 9750
                         "%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 已提交
9751
            }
9752
        } else {
9753 9754 9755 9756 9757 9758 9759 9760 9761
            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)) {
9762 9763
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9764
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9765
                             ctx.opcode & inval, opc1(ctx.opcode),
9766 9767
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9768
                }
A
aurel32 已提交
9769
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9770
                break;
B
bellard 已提交
9771 9772
            }
        }
B
bellard 已提交
9773
        (*(handler->handler))(&ctx);
9774 9775 9776
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9777
        /* Check trace mode exceptions */
9778 9779 9780 9781 9782
        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 已提交
9783
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9784
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9785
                            (env->singlestep_enabled) ||
9786
                            singlestep ||
P
pbrook 已提交
9787
                            num_insns >= max_insns)) {
9788 9789 9790
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9791
            break;
9792
        }
9793
    }
P
pbrook 已提交
9794 9795
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9796
    if (ctx.exception == POWERPC_EXCP_NONE) {
9797
        gen_goto_tb(&ctx, 0, ctx.nip);
9798
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9799
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9800
            gen_debug_exception(ctxp);
9801
        }
9802
        /* Generate the return instruction */
B
bellard 已提交
9803
        tcg_gen_exit_tb(0);
9804
    }
P
pbrook 已提交
9805
    gen_icount_end(tb, num_insns);
9806
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
9807
    if (unlikely(search_pc)) {
9808
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9809 9810
        lj++;
        while (lj <= j)
9811
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
9812
    } else {
B
bellard 已提交
9813
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9814
        tb->icount = num_insns;
9815
    }
9816
#if defined(DEBUG_DISAS)
9817
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9818
        int flags;
9819
        flags = env->bfd_mach;
A
aurel32 已提交
9820
        flags |= ctx.le_mode << 16;
9821
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
9822
        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
9823
        qemu_log("\n");
9824
    }
B
bellard 已提交
9825 9826 9827
#endif
}

9828
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9829
{
9830
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9831 9832
}

9833
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9834
{
9835
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9836
}
A
aurel32 已提交
9837

9838
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9839
{
9840
    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
9841
}