translate.c 354.4 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 22
#include "cpu.h"
#include "disas.h"
B
bellard 已提交
23
#include "tcg-op.h"
A
aurel32 已提交
24
#include "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
A
aurel32 已提交
69
static TCGv cpu_xer;
70
static TCGv cpu_reserve;
P
pbrook 已提交
71
static TCGv_i32 cpu_fpscr;
A
aurel32 已提交
72
static TCGv_i32 cpu_access_type;
A
aurel32 已提交
73

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

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");
A
aurel32 已提交
161

162
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
163
                                     offsetof(CPUPPCState, reserve_addr),
164
                                     "reserve_addr");
165

P
pbrook 已提交
166
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
167
                                       offsetof(CPUPPCState, fpscr), "fpscr");
168

A
aurel32 已提交
169
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
170
                                             offsetof(CPUPPCState, access_type), "access_type");
A
aurel32 已提交
171

A
aurel32 已提交
172
    /* register helpers */
P
pbrook 已提交
173
#define GEN_HELPER 2
A
aurel32 已提交
174 175
#include "helper.h"

P
pbrook 已提交
176 177 178
    done_init = 1;
}

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

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

B
Blue Swirl 已提交
220
static inline void gen_reset_fpstatus(void)
221
{
222
    gen_helper_reset_fpstatus();
223 224
}

B
Blue Swirl 已提交
225
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
226
{
227
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
228

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

244
    tcg_temp_free_i32(t0);
245 246
}

B
Blue Swirl 已提交
247
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
248
{
A
aurel32 已提交
249 250 251 252
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
253 254
}

B
Blue Swirl 已提交
255
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
256 257 258
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
259
        tcg_gen_movi_tl(cpu_nip, nip);
260 261
    else
#endif
A
aurel32 已提交
262
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
263 264
}

B
Blue Swirl 已提交
265
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
266 267 268 269 270 271 272 273 274 275 276 277
{
    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);
    gen_helper_raise_exception_err(t0, t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
278

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

B
Blue Swirl 已提交
291
static inline void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
292 293
{
    TCGv_i32 t0;
B
blueswir1 已提交
294

295 296
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
B
blueswir1 已提交
297
        gen_update_nip(ctx, ctx->nip);
298
    }
A
aurel32 已提交
299 300 301 302
    t0 = tcg_const_i32(EXCP_DEBUG);
    gen_helper_raise_exception(t0);
    tcg_temp_free_i32(t0);
}
303

B
Blue Swirl 已提交
304
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
305 306 307
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
308

309
/* Stop translation */
B
Blue Swirl 已提交
310
static inline void gen_stop_exception(DisasContext *ctx)
311
{
312
    gen_update_nip(ctx, ctx->nip);
313
    ctx->exception = POWERPC_EXCP_STOP;
314 315
}

316
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
317
static inline void gen_sync_exception(DisasContext *ctx)
318
{
319
    ctx->exception = POWERPC_EXCP_SYNC;
320 321
}

B
bellard 已提交
322
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
323 324 325 326
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 已提交
327

328
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
329 330 331 332
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)
333

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

345
/*****************************************************************************/
B
bellard 已提交
346 347
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
B
Blue Swirl 已提交
348
static inline uint32_t name(uint32_t opcode)                                  \
B
bellard 已提交
349 350 351 352 353
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

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

/* 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 */
384
EXTRACT_HELPER(_SPR, 11, 10);
B
Blue Swirl 已提交
385
static inline uint32_t SPR(uint32_t opcode)
386 387 388 389 390
{
    uint32_t sprn = _SPR(opcode);

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

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

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

B
Blue Swirl 已提交
428
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
429 430 431 432 433 434 435 436 437 438 439 440
{
    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 已提交
441
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
442
{
443
    target_ulong ret;
B
bellard 已提交
444

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

    return ret;
}

468 469
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
470

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

564
/* SPR load/store helpers */
B
Blue Swirl 已提交
565
static inline void gen_load_spr(TCGv t, int reg)
566
{
567
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
568
}
569

B
Blue Swirl 已提交
570
static inline void gen_store_spr(int reg, TCGv t)
571
{
572
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
573
}
574

575
/* Invalid instruction */
B
Blue Swirl 已提交
576
static void gen_invalid(DisasContext *ctx)
577
{
A
aurel32 已提交
578
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
579 580
}

A
Anthony Liguori 已提交
581
static opc_handler_t invalid_handler = {
582 583
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
584
    .type    = PPC_NONE,
585
    .type2   = PPC_NONE,
B
bellard 已提交
586 587 588
    .handler = gen_invalid,
};

589 590
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
591
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
592 593 594
{
    int l1, l2, l3;

595 596
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
597 598 599 600 601 602
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
603 604
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
605
    } else {
606 607
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
608 609 610 611 612 613 614 615 616 617 618
    }
    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 已提交
619
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
620
{
621 622 623
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
624 625 626
}

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

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

B
Blue Swirl 已提交
652
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
653 654 655 656 657 658 659 660 661 662
{
#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 已提交
663
static void gen_cmp(DisasContext *ctx)
664 665 666 667 668 669 670 671 672 673 674 675
{
#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 已提交
676
static void gen_cmpi(DisasContext *ctx)
677 678 679 680 681 682 683 684 685 686 687 688
{
#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 已提交
689
static void gen_cmpl(DisasContext *ctx)
690 691 692 693 694 695 696 697 698 699 700 701
{
#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 已提交
702
static void gen_cmpli(DisasContext *ctx)
703 704 705 706 707 708 709 710 711 712 713 714
{
#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 已提交
715
static void gen_isel(DisasContext *ctx)
716 717 718 719
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
720
    TCGv_i32 t0;
721 722 723 724 725

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

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

B
bellard 已提交
740 741
/***                           Integer arithmetic                          ***/

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

748 749 750
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
P
pbrook 已提交
751
    t0 = tcg_temp_local_new();
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    tcg_gen_xor_tl(t0, arg0, arg1);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    tcg_gen_xor_tl(t0, arg1, arg2);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free(t0);
B
bellard 已提交
773 774
}

B
Blue Swirl 已提交
775 776
static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
                                           TCGv arg2, int sub)
777 778
{
    int l1 = gen_new_label();
779 780

#if defined(TARGET_PPC64)
781 782
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
P
pbrook 已提交
783 784
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
785

786 787 788 789
        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 已提交
790
        } else {
791 792
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
793 794 795 796
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
797 798
    } else
#endif
799 800 801 802 803 804 805 806
    {
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
        } else {
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
        }
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
807
    }
808 809
}

810
/* Common add function */
B
Blue Swirl 已提交
811 812 813
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    TCGv arg2, int add_ca, int compute_ca,
                                    int compute_ov)
814 815
{
    TCGv t0, t1;
816

817
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
818
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
819 820
        t0 = ret;
    } else {
P
pbrook 已提交
821
        t0 = tcg_temp_local_new();
822
    }
B
bellard 已提交
823

824
    if (add_ca) {
P
pbrook 已提交
825
        t1 = tcg_temp_local_new();
826 827
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
828 829
    } else {
        TCGV_UNUSED(t1);
830
    }
B
bellard 已提交
831

832 833 834 835 836 837 838 839 840 841
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
B
bellard 已提交
842

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
    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 已提交
860
    if (!TCGV_EQUAL(t0, ret)) {
861 862 863
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
864
}
865 866
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
B
Blue Swirl 已提交
867
static void glue(gen_, name)(DisasContext *ctx)                                       \
868 869 870 871 872 873 874 875
{                                                                             \
    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 已提交
876
static void glue(gen_, name)(DisasContext *ctx)                                       \
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
{                                                                             \
    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 已提交
901
static void gen_addi(DisasContext *ctx)
902
{
903 904 905 906 907 908 909 910
    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);
    }
911
}
912
/* addic  addic.*/
B
Blue Swirl 已提交
913 914
static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
                                int compute_Rc0)
915
{
916 917 918 919 920 921
    target_long simm = SIMM(ctx->opcode);

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

    if (likely(simm != 0)) {
P
pbrook 已提交
922
        TCGv t0 = tcg_temp_local_new();
923 924 925 926 927 928 929 930 931 932
        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);
    }
933
}
B
Blue Swirl 已提交
934 935

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

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

945
/* addis */
B
Blue Swirl 已提交
946
static void gen_addis(DisasContext *ctx)
947
{
948 949 950 951 952 953 954 955
    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);
    }
956
}
957

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

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

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

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1062
static void gen_mulhw(DisasContext *ctx)
1063
{
P
pbrook 已提交
1064
    TCGv_i64 t0, t1;
1065

P
pbrook 已提交
1066 1067
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
P
pbrook 已提交
1080 1081
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1082 1083
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1084
}
B
Blue Swirl 已提交
1085

1086
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1087
static void gen_mulhwu(DisasContext *ctx)
1088
{
P
pbrook 已提交
1089
    TCGv_i64 t0, t1;
1090

P
pbrook 已提交
1091 1092
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1093
#if defined(TARGET_PPC64)
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
P
pbrook 已提交
1105 1106
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1107 1108
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1109
}
B
Blue Swirl 已提交
1110

1111
/* mullw  mullw. */
B
Blue Swirl 已提交
1112
static void gen_mullw(DisasContext *ctx)
1113
{
1114 1115
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1116
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1117 1118
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1119
}
B
Blue Swirl 已提交
1120

1121
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1122
static void gen_mullwo(DisasContext *ctx)
1123
{
1124
    int l1;
P
pbrook 已提交
1125
    TCGv_i64 t0, t1;
1126

P
pbrook 已提交
1127 1128
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1129 1130 1131 1132 1133 1134 1135 1136 1137
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1138
#endif
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
    tcg_gen_mul_i64(t0, t0, t1);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
#else
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
#endif
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
P
pbrook 已提交
1150 1151
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1152 1153
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1154
}
B
Blue Swirl 已提交
1155

1156
/* mulli */
B
Blue Swirl 已提交
1157
static void gen_mulli(DisasContext *ctx)
1158
{
1159 1160
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1161 1162
}
#if defined(TARGET_PPC64)
1163
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
B
Blue Swirl 已提交
1164
static void glue(gen_, name)(DisasContext *ctx)                                       \
1165
{                                                                             \
P
pbrook 已提交
1166
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1167 1168 1169
                       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)]);                           \
1170
}
1171 1172 1173 1174
/* mulhd  mulhd. */
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
/* mulhdu  mulhdu. */
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
B
Blue Swirl 已提交
1175

1176
/* mulld  mulld. */
B
Blue Swirl 已提交
1177
static void gen_mulld(DisasContext *ctx)
1178
{
1179 1180 1181 1182
    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)]);
1183
}
1184 1185
/* mulldo  mulldo. */
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1186
#endif
1187 1188

/* neg neg. nego nego. */
B
Blue Swirl 已提交
1189 1190
static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    int ov_check)
1191
{
A
aurel32 已提交
1192 1193
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1194
    TCGv t0 = tcg_temp_local_new();
1195
#if defined(TARGET_PPC64)
1196
    if (ctx->sf_mode) {
A
aurel32 已提交
1197
        tcg_gen_mov_tl(t0, arg1);
A
aurel32 已提交
1198 1199 1200 1201 1202
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
    } else
#endif
    {
        tcg_gen_ext32s_tl(t0, arg1);
1203 1204 1205 1206 1207 1208 1209 1210
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
    }
    tcg_gen_neg_tl(ret, arg1);
    if (ov_check) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
A
aurel32 已提交
1211
    tcg_gen_mov_tl(ret, t0);
1212 1213 1214 1215
    if (ov_check) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
A
aurel32 已提交
1216
    tcg_temp_free(t0);
1217 1218 1219
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
}
B
Blue Swirl 已提交
1220 1221

static void gen_neg(DisasContext *ctx)
1222
{
A
aurel32 已提交
1223
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1224
}
B
Blue Swirl 已提交
1225 1226

static void gen_nego(DisasContext *ctx)
B
bellard 已提交
1227
{
A
aurel32 已提交
1228
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
B
bellard 已提交
1229
}
1230 1231

/* Common subf function */
B
Blue Swirl 已提交
1232 1233 1234
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 已提交
1235
{
1236
    TCGv t0, t1;
1237

1238
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
1239
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1240
        t0 = ret;
J
j_mayer 已提交
1241
    } else {
P
pbrook 已提交
1242
        t0 = tcg_temp_local_new();
1243
    }
1244

1245
    if (add_ca) {
P
pbrook 已提交
1246
        t1 = tcg_temp_local_new();
1247 1248
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1249 1250
    } else {
        TCGV_UNUSED(t1);
1251
    }
B
bellard 已提交
1252

1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }

    if (add_ca) {
        tcg_gen_not_tl(t0, arg1);
        tcg_gen_add_tl(t0, t0, arg2);
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
B
bellard 已提交
1271
    } else {
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
        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 已提交
1284
    if (!TCGV_EQUAL(t0, ret)) {
1285 1286
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1287 1288
    }
}
1289 1290
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
B
Blue Swirl 已提交
1291
static void glue(gen_, name)(DisasContext *ctx)                                       \
1292 1293 1294 1295 1296 1297 1298 1299
{                                                                             \
    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 已提交
1300
static void glue(gen_, name)(DisasContext *ctx)                                       \
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
{                                                                             \
    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 已提交
1323

1324
/* subfic */
B
Blue Swirl 已提交
1325
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1326
{
1327 1328
    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
P
pbrook 已提交
1329
    TCGv t0 = tcg_temp_local_new();
1330 1331 1332 1333 1334 1335
    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 已提交
1336 1337 1338
}

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

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

/* and & and. */
1357
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1358
/* andc & andc. */
1359
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1360

1361
/* andi. */
B
Blue Swirl 已提交
1362
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1363
{
1364 1365
    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 已提交
1366
}
B
Blue Swirl 已提交
1367

1368
/* andis. */
B
Blue Swirl 已提交
1369
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1370
{
1371 1372
    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 已提交
1373
}
B
Blue Swirl 已提交
1374

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

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

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

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

1484
/* ori */
B
Blue Swirl 已提交
1485
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1486
{
1487
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1488

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

1497
/* oris */
B
Blue Swirl 已提交
1498
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1499
{
1500
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1501

1502 1503 1504
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1505
    }
1506
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1507
}
B
Blue Swirl 已提交
1508

1509
/* xori */
B
Blue Swirl 已提交
1510
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1511
{
1512
    target_ulong uimm = UIMM(ctx->opcode);
1513 1514 1515 1516 1517

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

1521
/* xoris */
B
Blue Swirl 已提交
1522
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1523
{
1524
    target_ulong uimm = UIMM(ctx->opcode);
1525 1526 1527 1528 1529

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

1533
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1534
static void gen_popcntb(DisasContext *ctx)
1535
{
1536 1537 1538 1539 1540 1541 1542 1543
    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)]);
}

1544
#if defined(TARGET_PPC64)
1545 1546 1547 1548
/* popcntd: PowerPC 2.06 specification */
static void gen_popcntd(DisasContext *ctx)
{
    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1549
}
1550
#endif
1551 1552 1553

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

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

B
bellard 已提交
1565
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1566

1567
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1568
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1569
{
1570
    uint32_t mb, me, sh;
B
bellard 已提交
1571 1572 1573

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

1606
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1607
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1608 1609
{
    uint32_t mb, me, sh;
1610

B
bellard 已提交
1611 1612 1613
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1614 1615 1616 1617 1618

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

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

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

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

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

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

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

J
j_mayer 已提交
1769 1770
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1771 1772 1773 1774
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

B
Blue Swirl 已提交
1775
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
J
j_mayer 已提交
1776
{
1777
    TCGv t0;
1778 1779 1780

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

1794
/* rldcl - rldcl. */
B
Blue Swirl 已提交
1795
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1796
{
J
j_mayer 已提交
1797
    uint32_t mb;
1798

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

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

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

B
bellard 已提交
1842
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1843

1844
/* slw & slw. */
B
Blue Swirl 已提交
1845
static void gen_slw(DisasContext *ctx)
1846
{
1847
    TCGv t0, t1;
1848

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

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

1878
/* srawi & srawi. */
B
Blue Swirl 已提交
1879
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
1880
{
1881 1882 1883
    int sh = SH(ctx->opcode);
    if (sh != 0) {
        int l1, l2;
1884
        TCGv t0;
1885 1886
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1887
        t0 = tcg_temp_local_new();
1888 1889 1890 1891
        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);
1892
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1893 1894
        tcg_gen_br(l2);
        gen_set_label(l1);
1895
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1896
        gen_set_label(l2);
1897 1898 1899
        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);
1900 1901
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1902
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1903
    }
1904
    if (unlikely(Rc(ctx->opcode) != 0))
1905
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1906
}
B
Blue Swirl 已提交
1907

1908
/* srw & srw. */
B
Blue Swirl 已提交
1909
static void gen_srw(DisasContext *ctx)
1910
{
1911
    TCGv t0, t1;
1912

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

1933 1934
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
1935
static void gen_sld(DisasContext *ctx)
1936
{
1937
    TCGv t0, t1;
1938

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

1953
/* srad & srad. */
B
Blue Swirl 已提交
1954
static void gen_srad(DisasContext *ctx)
1955
{
P
pbrook 已提交
1956 1957
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1958 1959 1960
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1961
/* sradi & sradi. */
B
Blue Swirl 已提交
1962
static inline void gen_sradi(DisasContext *ctx, int n)
1963
{
1964
    int sh = SH(ctx->opcode) + (n << 5);
1965
    if (sh != 0) {
1966
        int l1, l2;
1967
        TCGv t0;
1968 1969
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1970
        t0 = tcg_temp_local_new();
1971
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1972 1973
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1974
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1975 1976
        tcg_gen_br(l2);
        gen_set_label(l1);
1977
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1978
        gen_set_label(l2);
1979
        tcg_temp_free(t0);
1980 1981 1982
        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)]);
1983
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1984 1985
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1986
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1987
}
B
Blue Swirl 已提交
1988 1989

static void gen_sradi0(DisasContext *ctx)
1990 1991 1992
{
    gen_sradi(ctx, 0);
}
B
Blue Swirl 已提交
1993 1994

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

1999
/* srd & srd. */
B
Blue Swirl 已提交
2000
static void gen_srd(DisasContext *ctx)
2001
{
2002
    TCGv t0, t1;
2003

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

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

2039 2040 2041
#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);
2042

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

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

2087
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
2088
static void gen_f##name(DisasContext *ctx)                                    \
2089
{                                                                             \
2090
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2091
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2092 2093
        return;                                                               \
    }                                                                         \
2094 2095
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2096
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2097 2098 2099
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2100 2101
}

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

2117
/* fadd - fadds */
2118
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2119
/* fdiv - fdivs */
2120
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2121
/* fmul - fmuls */
2122
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2123

2124
/* fre */
2125
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2126

2127
/* fres */
2128
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2129

2130
/* frsqrte */
2131 2132 2133
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2134
static void gen_frsqrtes(DisasContext *ctx)
2135
{
A
aurel32 已提交
2136
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2137
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2138 2139
        return;
    }
2140 2141
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2142 2143 2144 2145
    gen_reset_fpstatus();
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2146
}
B
bellard 已提交
2147

2148
/* fsel */
2149
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2150
/* fsub - fsubs */
2151
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2152
/* Optional: */
B
Blue Swirl 已提交
2153

2154
/* fsqrt */
B
Blue Swirl 已提交
2155
static void gen_fsqrt(DisasContext *ctx)
2156
{
2157
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2158
        gen_exception(ctx, POWERPC_EXCP_FPU);
2159 2160
        return;
    }
2161 2162
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2163
    gen_reset_fpstatus();
A
aurel32 已提交
2164 2165
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2166
}
B
bellard 已提交
2167

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

/***                     Floating-Point multiply-and-add                   ***/
2183
/* fmadd - fmadds */
2184
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2185
/* fmsub - fmsubs */
2186
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2187
/* fnmadd - fnmadds */
2188
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2189
/* fnmsub - fnmsubs */
2190
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2191 2192 2193

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2194
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2195
/* fctiwz */
2196
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2197
/* frsp */
2198
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2199 2200
#if defined(TARGET_PPC64)
/* fcfid */
2201
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2202
/* fctid */
2203
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2204
/* fctidz */
2205
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2206
#endif
B
bellard 已提交
2207

2208
/* frin */
2209
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2210
/* friz */
2211
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2212
/* frip */
2213
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2214
/* frim */
2215
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2216

B
bellard 已提交
2217
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2218

2219
/* fcmpo */
B
Blue Swirl 已提交
2220
static void gen_fcmpo(DisasContext *ctx)
B
bellard 已提交
2221
{
A
aurel32 已提交
2222
    TCGv_i32 crf;
2223
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2224
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2225 2226
        return;
    }
2227 2228
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2229
    gen_reset_fpstatus();
A
aurel32 已提交
2230 2231
    crf = tcg_const_i32(crfD(ctx->opcode));
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2232
    tcg_temp_free_i32(crf);
A
aurel32 已提交
2233
    gen_helper_float_check_status();
B
bellard 已提交
2234 2235 2236
}

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

2253 2254
/***                         Floating-point move                           ***/
/* fabs */
2255 2256
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2257 2258

/* fmr  - fmr. */
2259
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2260
static void gen_fmr(DisasContext *ctx)
2261
{
2262
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2263
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2264 2265
        return;
    }
A
aurel32 已提交
2266 2267
    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);
2268 2269 2270
}

/* fnabs */
2271 2272
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2273
/* fneg */
2274 2275
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2276

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

2279
/* mcrfs */
B
Blue Swirl 已提交
2280
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2281
{
2282 2283
    int bfa;

2284
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2285
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2286 2287
        return;
    }
2288
    bfa = 4 * (7 - crfS(ctx->opcode));
2289 2290
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
A
aurel32 已提交
2291
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2292 2293 2294
}

/* mffs */
B
Blue Swirl 已提交
2295
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2296
{
2297
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2298
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2299 2300
        return;
    }
2301
    gen_reset_fpstatus();
A
aurel32 已提交
2302 2303
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2304 2305 2306
}

/* mtfsb0 */
B
Blue Swirl 已提交
2307
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2308
{
B
bellard 已提交
2309
    uint8_t crb;
2310

2311
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2312
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2313 2314
        return;
    }
A
aurel32 已提交
2315
    crb = 31 - crbD(ctx->opcode);
2316
    gen_reset_fpstatus();
A
aurel32 已提交
2317
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2318 2319 2320 2321
        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);
A
aurel32 已提交
2322 2323 2324
        gen_helper_fpscr_clrbit(t0);
        tcg_temp_free_i32(t0);
    }
2325
    if (unlikely(Rc(ctx->opcode) != 0)) {
2326
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2327
    }
B
bellard 已提交
2328 2329 2330
}

/* mtfsb1 */
B
Blue Swirl 已提交
2331
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2332
{
B
bellard 已提交
2333
    uint8_t crb;
2334

2335
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2336
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2337 2338
        return;
    }
A
aurel32 已提交
2339
    crb = 31 - crbD(ctx->opcode);
2340 2341
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2342
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2343 2344 2345 2346
        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);
A
aurel32 已提交
2347
        gen_helper_fpscr_setbit(t0);
2348
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2349
    }
2350
    if (unlikely(Rc(ctx->opcode) != 0)) {
2351
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2352 2353
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2354
    gen_helper_float_check_status();
B
bellard 已提交
2355 2356 2357
}

/* mtfsf */
B
Blue Swirl 已提交
2358
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2359
{
2360
    TCGv_i32 t0;
B
blueswir1 已提交
2361
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2362

2363
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2364
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2365 2366
        return;
    }
2367 2368
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2369
    gen_reset_fpstatus();
B
blueswir1 已提交
2370 2371 2372 2373
    if (L)
        t0 = tcg_const_i32(0xff);
    else
        t0 = tcg_const_i32(FM(ctx->opcode));
A
aurel32 已提交
2374
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2375
    tcg_temp_free_i32(t0);
2376
    if (unlikely(Rc(ctx->opcode) != 0)) {
2377
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2378 2379
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2380
    gen_helper_float_check_status();
B
bellard 已提交
2381 2382 2383
}

/* mtfsfi */
B
Blue Swirl 已提交
2384
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2385
{
2386
    int bf, sh;
2387 2388
    TCGv_i64 t0;
    TCGv_i32 t1;
2389

2390
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2391
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2392 2393
        return;
    }
2394 2395
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2396 2397
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2398
    gen_reset_fpstatus();
2399
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2400 2401
    t1 = tcg_const_i32(1 << sh);
    gen_helper_store_fpscr(t0, t1);
2402 2403
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2404
    if (unlikely(Rc(ctx->opcode) != 0)) {
2405
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2406 2407
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2408
    gen_helper_float_check_status();
B
bellard 已提交
2409 2410
}

2411 2412
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2413 2414
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2415 2416 2417
{
    target_long simm = SIMM(ctx->opcode);

2418
    simm &= ~maskl;
A
aurel32 已提交
2419 2420 2421 2422 2423 2424
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2425
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2426
    } else if (likely(simm != 0)) {
2427
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
#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
2439
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2440
    }
2441 2442
}

B
Blue Swirl 已提交
2443
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2444
{
A
aurel32 已提交
2445 2446 2447 2448 2449 2450
    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
2451
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2452
    } else {
2453
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2454 2455 2456 2457 2458 2459
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2460 2461
}

B
Blue Swirl 已提交
2462
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2463
{
A
aurel32 已提交
2464
    if (rA(ctx->opcode) == 0) {
2465
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475
    } 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 已提交
2476 2477
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2478 2479 2480 2481 2482 2483 2484
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2485 2486
}

B
Blue Swirl 已提交
2487
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
{
    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);
    gen_helper_raise_exception_err(t1, t2);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2505
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2506
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2507 2508 2509 2510
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2511
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2512 2513 2514 2515
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2516
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2517 2518 2519
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2520
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2521
    }
A
aurel32 已提交
2522 2523
}

B
Blue Swirl 已提交
2524
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2525
{
A
aurel32 已提交
2526 2527
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2528
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2529 2530 2531 2532
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2533 2534
}

B
Blue Swirl 已提交
2535
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2536
{
A
aurel32 已提交
2537 2538
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2539
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2540
    }
A
aurel32 已提交
2541 2542
}

A
aurel32 已提交
2543
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2544
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2545
{
B
blueswir1 已提交
2546
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2547
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2548 2549
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2550
    } else
A
aurel32 已提交
2551
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2552
}
A
aurel32 已提交
2553
#endif
A
aurel32 已提交
2554

B
Blue Swirl 已提交
2555
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2556
{
A
aurel32 已提交
2557 2558
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2559
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2560
    }
A
aurel32 已提交
2561 2562
}

B
Blue Swirl 已提交
2563
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2564
{
A
aurel32 已提交
2565
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2566 2567
}

B
Blue Swirl 已提交
2568
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2569
{
A
aurel32 已提交
2570 2571 2572
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2573
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2574 2575 2576 2577 2578
        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 已提交
2579 2580
}

B
Blue Swirl 已提交
2581
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2582
{
A
aurel32 已提交
2583
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2584 2585 2586
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2587 2588 2589 2590 2591
        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 已提交
2592 2593
}

B
Blue Swirl 已提交
2594
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2595
{
A
aurel32 已提交
2596
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2597
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2598
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2599
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2600
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2601
    } else
A
aurel32 已提交
2602
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2603 2604
}

2605
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2606
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2607
{                                                                             \
A
aurel32 已提交
2608 2609 2610 2611 2612
    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 已提交
2613
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2614 2615
}

2616
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2617
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2618
{                                                                             \
A
aurel32 已提交
2619
    TCGv EA;                                                                  \
2620 2621
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2622
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2623
        return;                                                               \
2624
    }                                                                         \
A
aurel32 已提交
2625
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2626
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2627
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2628
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2629
    else                                                                      \
A
aurel32 已提交
2630 2631
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2632 2633
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2634 2635
}

2636
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2637
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2638
{                                                                             \
A
aurel32 已提交
2639
    TCGv EA;                                                                  \
2640 2641
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2642
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2643
        return;                                                               \
2644
    }                                                                         \
A
aurel32 已提交
2645
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2646
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2647 2648
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2649 2650
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2651 2652
}

2653
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
B
Blue Swirl 已提交
2654
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2655
{                                                                             \
A
aurel32 已提交
2656 2657 2658 2659 2660
    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 已提交
2661
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2662
}
2663 2664
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2665

2666 2667 2668 2669 2670
#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 已提交
2671 2672

/* lbz lbzu lbzux lbzx */
2673
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2674
/* lha lhau lhaux lhax */
2675
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2676
/* lhz lhzu lhzux lhzx */
2677
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2678
/* lwz lwzu lwzux lwzx */
2679
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2680 2681
#if defined(TARGET_PPC64)
/* lwaux */
2682
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2683
/* lwax */
2684
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2685
/* ldux */
2686
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2687
/* ldx */
2688
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2689 2690

static void gen_ld(DisasContext *ctx)
2691
{
A
aurel32 已提交
2692
    TCGv EA;
2693 2694 2695
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2696
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2697 2698 2699
            return;
        }
    }
A
aurel32 已提交
2700
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2701
    EA = tcg_temp_new();
A
aurel32 已提交
2702
    gen_addr_imm_index(ctx, EA, 0x03);
2703 2704
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2705
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2706 2707
    } else {
        /* ld - ldu */
A
aurel32 已提交
2708
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2709 2710
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2711 2712
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2713
}
B
Blue Swirl 已提交
2714

2715
/* lq */
B
Blue Swirl 已提交
2716
static void gen_lq(DisasContext *ctx)
2717 2718
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2719
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2720 2721
#else
    int ra, rd;
A
aurel32 已提交
2722
    TCGv EA;
2723 2724

    /* Restore CPU state */
A
aurel32 已提交
2725
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2726
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2727 2728 2729 2730 2731
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2732
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2733 2734
        return;
    }
A
aurel32 已提交
2735
    if (unlikely(ctx->le_mode)) {
2736
        /* Little-endian mode is not handled */
A
aurel32 已提交
2737
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2738 2739
        return;
    }
A
aurel32 已提交
2740
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2741
    EA = tcg_temp_new();
A
aurel32 已提交
2742 2743 2744 2745
    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 已提交
2746
    tcg_temp_free(EA);
2747 2748
#endif
}
2749
#endif
B
bellard 已提交
2750 2751

/***                              Integer store                            ***/
2752
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2753
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2754
{                                                                             \
A
aurel32 已提交
2755 2756 2757 2758 2759
    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 已提交
2760
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2761 2762
}

2763
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2764
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2765
{                                                                             \
A
aurel32 已提交
2766
    TCGv EA;                                                                  \
2767
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2768
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2769
        return;                                                               \
2770
    }                                                                         \
A
aurel32 已提交
2771
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2772
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2773
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2774
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2775
    else                                                                      \
A
aurel32 已提交
2776 2777
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2778 2779
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2780 2781
}

2782
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2783
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2784
{                                                                             \
A
aurel32 已提交
2785
    TCGv EA;                                                                  \
2786
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2787
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2788
        return;                                                               \
2789
    }                                                                         \
A
aurel32 已提交
2790
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2791
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2792 2793
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2794 2795
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2796 2797
}

2798 2799
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2800
{                                                                             \
A
aurel32 已提交
2801 2802 2803 2804 2805
    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 已提交
2806
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2807
}
2808 2809
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2810

2811 2812 2813 2814 2815
#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 已提交
2816 2817

/* stb stbu stbux stbx */
2818
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2819
/* sth sthu sthux sthx */
2820
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2821
/* stw stwu stwux stwx */
2822
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2823
#if defined(TARGET_PPC64)
2824 2825
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2826 2827

static void gen_std(DisasContext *ctx)
2828
{
2829
    int rs;
A
aurel32 已提交
2830
    TCGv EA;
2831 2832 2833 2834

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2835
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2836 2837
#else
        /* stq */
A
aurel32 已提交
2838
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2839
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2840 2841 2842
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2843
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2844 2845
            return;
        }
A
aurel32 已提交
2846
        if (unlikely(ctx->le_mode)) {
2847
            /* Little-endian mode is not handled */
A
aurel32 已提交
2848
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2849 2850
            return;
        }
A
aurel32 已提交
2851
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2852
        EA = tcg_temp_new();
A
aurel32 已提交
2853 2854 2855 2856
        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 已提交
2857
        tcg_temp_free(EA);
2858 2859 2860 2861 2862
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2863
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2864 2865 2866
                return;
            }
        }
A
aurel32 已提交
2867
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2868
        EA = tcg_temp_new();
A
aurel32 已提交
2869 2870
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2871
        if (Rc(ctx->opcode))
A
aurel32 已提交
2872 2873
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2874 2875 2876
    }
}
#endif
B
bellard 已提交
2877 2878
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2879
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2880
{
A
aurel32 已提交
2881 2882
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2883
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2884
    }
A
aurel32 已提交
2885
}
2886
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2887

B
bellard 已提交
2888
/* lwbrx */
2889
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2890
{
A
aurel32 已提交
2891 2892
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2893
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2894
    }
A
aurel32 已提交
2895
}
2896
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2897

2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909
#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 已提交
2910
/* sthbrx */
2911
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2912
{
A
aurel32 已提交
2913 2914 2915
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2916
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2917 2918 2919 2920 2921
        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 已提交
2922
}
2923
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2924

B
bellard 已提交
2925
/* stwbrx */
2926
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2927
{
A
aurel32 已提交
2928
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2929 2930 2931
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2932 2933 2934 2935 2936
        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 已提交
2937
}
2938
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2939

2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955
#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 已提交
2956
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2957

2958
/* lmw */
B
Blue Swirl 已提交
2959
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2960
{
A
aurel32 已提交
2961 2962 2963
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2964
    /* NIP cannot be restored if the memory exception comes from an helper */
2965
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2966 2967 2968
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2969 2970 2971
    gen_helper_lmw(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2972 2973 2974
}

/* stmw */
B
Blue Swirl 已提交
2975
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
2976
{
A
aurel32 已提交
2977 2978 2979
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2980
    /* NIP cannot be restored if the memory exception comes from an helper */
2981
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2982 2983 2984
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2985 2986 2987
    gen_helper_stmw(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2988 2989 2990
}

/***                    Integer load and store strings                     ***/
2991

B
bellard 已提交
2992
/* lswi */
2993
/* PowerPC32 specification says we must generate an exception if
2994 2995 2996 2997
 * 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 已提交
2998
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
2999
{
3000 3001
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3002 3003
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3004
    int ra = rA(ctx->opcode);
B
bellard 已提交
3005 3006 3007 3008 3009
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3010 3011 3012
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
3013
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3014
        return;
B
bellard 已提交
3015
    }
A
aurel32 已提交
3016
    gen_set_access_type(ctx, ACCESS_INT);
3017
    /* NIP cannot be restored if the memory exception comes from an helper */
3018
    gen_update_nip(ctx, ctx->nip - 4);
3019
    t0 = tcg_temp_new();
A
aurel32 已提交
3020
    gen_addr_register(ctx, t0);
3021 3022 3023 3024 3025 3026
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
    gen_helper_lsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3027 3028 3029
}

/* lswx */
B
Blue Swirl 已提交
3030
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
3031
{
A
aurel32 已提交
3032 3033 3034
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3035
    /* NIP cannot be restored if the memory exception comes from an helper */
3036
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3037 3038 3039 3040 3041
    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));
3042 3043 3044 3045 3046
    gen_helper_lswx(t0, t1, t2, t3);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
3047 3048 3049
}

/* stswi */
B
Blue Swirl 已提交
3050
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
3051
{
A
aurel32 已提交
3052 3053
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3054
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3055
    gen_set_access_type(ctx, ACCESS_INT);
3056
    /* NIP cannot be restored if the memory exception comes from an helper */
3057
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3058 3059
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3060 3061
    if (nb == 0)
        nb = 32;
3062
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3063
    t2 = tcg_const_i32(rS(ctx->opcode));
3064 3065 3066 3067
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3068 3069 3070
}

/* stswx */
B
Blue Swirl 已提交
3071
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
3072
{
A
aurel32 已提交
3073 3074 3075
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3076
    /* NIP cannot be restored if the memory exception comes from an helper */
3077
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3078 3079 3080
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3081 3082
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3083
    t2 = tcg_const_i32(rS(ctx->opcode));
3084 3085 3086 3087
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3088 3089 3090 3091
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3092
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3093 3094 3095 3096
{
}

/* isync */
B
Blue Swirl 已提交
3097
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3098
{
A
aurel32 已提交
3099
    gen_stop_exception(ctx);
B
bellard 已提交
3100 3101
}

3102
/* lwarx */
B
Blue Swirl 已提交
3103
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3104
{
A
aurel32 已提交
3105
    TCGv t0;
3106
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3107 3108 3109
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3110
    gen_check_align(ctx, t0, 0x03);
3111
    gen_qemu_ld32u(ctx, gpr, t0);
3112
    tcg_gen_mov_tl(cpu_reserve, t0);
3113
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3114
    tcg_temp_free(t0);
B
bellard 已提交
3115 3116
}

3117 3118 3119 3120 3121 3122 3123
#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;

3124
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3125
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3126
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3127 3128 3129 3130 3131 3132 3133 3134
    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 已提交
3135
/* stwcx. */
B
Blue Swirl 已提交
3136
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3137
{
A
aurel32 已提交
3138 3139 3140 3141
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3142
    gen_check_align(ctx, t0, 0x03);
3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
    {
        int l1;

        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        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
3160
    tcg_temp_free(t0);
B
bellard 已提交
3161 3162
}

J
j_mayer 已提交
3163 3164
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3165
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3166
{
A
aurel32 已提交
3167
    TCGv t0;
3168
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3169 3170 3171
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3172
    gen_check_align(ctx, t0, 0x07);
3173
    gen_qemu_ld64(ctx, gpr, t0);
3174
    tcg_gen_mov_tl(cpu_reserve, t0);
3175
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3176
    tcg_temp_free(t0);
J
j_mayer 已提交
3177 3178 3179
}

/* stdcx. */
B
Blue Swirl 已提交
3180
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3181
{
A
aurel32 已提交
3182 3183 3184 3185
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3186
    gen_check_align(ctx, t0, 0x07);
3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
#else
    {
        int l1;
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        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
3203
    tcg_temp_free(t0);
J
j_mayer 已提交
3204 3205 3206
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3207
/* sync */
B
Blue Swirl 已提交
3208
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3209 3210 3211
{
}

3212
/* wait */
B
Blue Swirl 已提交
3213
static void gen_wait(DisasContext *ctx)
3214
{
3215
    TCGv_i32 t0 = tcg_temp_new_i32();
3216
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
3217
    tcg_temp_free_i32(t0);
3218
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3219
    gen_exception_err(ctx, EXCP_HLT, 1);
3220 3221
}

B
bellard 已提交
3222
/***                         Floating-point load                           ***/
3223
#define GEN_LDF(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
3224
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3225
{                                                                             \
3226
    TCGv EA;                                                                  \
3227
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3228
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3229 3230
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3231
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3232
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3233 3234
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3235
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3236 3237
}

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

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

3278
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3279
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3280
{                                                                             \
3281
    TCGv EA;                                                                  \
3282
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3283
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3284 3285
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3286
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3287
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3288 3289
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3290
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3291 3292
}

3293 3294 3295 3296 3297 3298
#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 已提交
3299
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3300 3301 3302
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3303
    gen_qemu_ld32u(ctx, t0, arg2);
3304 3305 3306 3307 3308
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
    gen_helper_float32_to_float64(arg1, t1);
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3309

3310 3311 3312 3313
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3314 3315

/***                         Floating-point store                          ***/
3316
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3317
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3318
{                                                                             \
3319
    TCGv EA;                                                                  \
3320
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3321
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3322 3323
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3324
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3325
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3326 3327
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3328
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3329 3330
}

3331
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3332
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3333
{                                                                             \
3334
    TCGv EA;                                                                  \
3335
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3336
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3337 3338
        return;                                                               \
    }                                                                         \
3339
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3340
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3341
        return;                                                               \
3342
    }                                                                         \
A
aurel32 已提交
3343
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3344
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3345 3346
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3347 3348
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3349 3350
}

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

3371
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3372
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3373
{                                                                             \
3374
    TCGv EA;                                                                  \
3375
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3376
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3377 3378
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3379
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3380
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3381 3382
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3383
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3384 3385
}

3386 3387 3388 3389 3390 3391
#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 已提交
3392
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3393 3394 3395 3396 3397 3398
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
    gen_helper_float64_to_float32(t0, arg1);
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3399
    gen_qemu_st32(ctx, t1, arg2);
3400 3401
    tcg_temp_free(t1);
}
B
bellard 已提交
3402 3403

/* stfd stfdu stfdux stfdx */
3404
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3405
/* stfs stfsu stfsux stfsx */
3406
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3407 3408

/* Optional: */
B
Blue Swirl 已提交
3409
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3410 3411 3412
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3413
    gen_qemu_st32(ctx, t0, arg2);
3414 3415
    tcg_temp_free(t0);
}
B
bellard 已提交
3416
/* stfiwx */
3417
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3418

D
David Gibson 已提交
3419 3420 3421 3422 3423 3424 3425 3426
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 已提交
3427
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3428
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3429 3430 3431
{
    TranslationBlock *tb;
    tb = ctx->tb;
3432 3433 3434 3435
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3436
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3437
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3438
        tcg_gen_goto_tb(n);
3439
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3440
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3441
    } else {
3442
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3443 3444
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3445
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3446 3447 3448
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3449
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3450 3451 3452
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3453
                gen_debug_exception(ctx);
3454 3455
            }
        }
B
bellard 已提交
3456
        tcg_gen_exit_tb(0);
3457
    }
B
bellard 已提交
3458 3459
}

B
Blue Swirl 已提交
3460
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3461 3462
{
#if defined(TARGET_PPC64)
3463 3464
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3465 3466
    else
#endif
3467
        tcg_gen_movi_tl(cpu_lr, nip);
3468 3469
}

B
bellard 已提交
3470
/* b ba bl bla */
B
Blue Swirl 已提交
3471
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3472
{
3473
    target_ulong li, target;
B
bellard 已提交
3474

3475
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3476
    /* sign extend LI */
3477
#if defined(TARGET_PPC64)
3478 3479 3480
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3481
#endif
3482
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3483
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3484
        target = ctx->nip + li - 4;
B
bellard 已提交
3485
    else
3486
        target = li;
3487 3488
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
D
David Gibson 已提交
3489
    gen_update_cfar(ctx, ctx->nip);
3490
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3491 3492
}

3493 3494 3495 3496
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3497
static inline void gen_bcond(DisasContext *ctx, int type)
3498 3499
{
    uint32_t bo = BO(ctx->opcode);
3500
    int l1;
3501
    TCGv target;
3502

3503
    ctx->exception = POWERPC_EXCP_BRANCH;
3504
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3505
        target = tcg_temp_local_new();
3506 3507 3508 3509
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3510 3511
    } else {
        TCGV_UNUSED(target);
3512
    }
3513 3514
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3515 3516 3517
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3518
        TCGv temp = tcg_temp_new();
3519
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3520
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3521 3522 3523
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3524
#if defined(TARGET_PPC64)
3525 3526 3527
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3528
#endif
3529 3530 3531 3532 3533
            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);
3534
        }
P
pbrook 已提交
3535
        tcg_temp_free(temp);
3536 3537 3538 3539 3540
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3541
        TCGv_i32 temp = tcg_temp_new_i32();
3542

3543
        if (bo & 0x8) {
3544 3545
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3546
        } else {
3547 3548
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3549
        }
P
pbrook 已提交
3550
        tcg_temp_free_i32(temp);
3551
    }
D
David Gibson 已提交
3552
    gen_update_cfar(ctx, ctx->nip);
3553
    if (type == BCOND_IM) {
3554 3555 3556 3557 3558 3559
        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 已提交
3560
        gen_set_label(l1);
3561
        gen_goto_tb(ctx, 1, ctx->nip);
3562
    } else {
3563
#if defined(TARGET_PPC64)
3564 3565 3566 3567 3568 3569 3570 3571 3572 3573
        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);
3574 3575
        else
#endif
3576
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3577
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3578
    }
3579 3580
}

B
Blue Swirl 已提交
3581
static void gen_bc(DisasContext *ctx)
3582
{
3583 3584 3585
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3586
static void gen_bcctr(DisasContext *ctx)
3587
{
3588 3589 3590
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3591
static void gen_bclr(DisasContext *ctx)
3592
{
3593 3594
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3595 3596

/***                      Condition register logical                       ***/
3597
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3598
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3599
{                                                                             \
3600 3601
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3602
    TCGv_i32 t0, t1;                                                          \
3603
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3604
    t0 = tcg_temp_new_i32();                                                  \
3605
    if (sh > 0)                                                               \
3606
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3607
    else if (sh < 0)                                                          \
3608
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3609
    else                                                                      \
3610
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3611
    t1 = tcg_temp_new_i32();                                                  \
3612 3613
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3614
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3615
    else if (sh < 0)                                                          \
3616
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3617
    else                                                                      \
3618 3619
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3620
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3621 3622 3623
    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 已提交
3624 3625
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3626 3627 3628
}

/* crand */
3629
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3630
/* crandc */
3631
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3632
/* creqv */
3633
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3634
/* crnand */
3635
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3636
/* crnor */
3637
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3638
/* cror */
3639
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3640
/* crorc */
3641
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3642
/* crxor */
3643
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3644

3645
/* mcrf */
B
Blue Swirl 已提交
3646
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3647
{
A
aurel32 已提交
3648
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3649 3650 3651
}

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

3653
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3654
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3655
{
3656
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3657
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3658 3659
#else
    /* Restore CPU state */
A
aurel32 已提交
3660
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3661
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3662
        return;
3663
    }
D
David Gibson 已提交
3664
    gen_update_cfar(ctx, ctx->nip);
3665
    gen_helper_rfi();
A
aurel32 已提交
3666
    gen_sync_exception(ctx);
3667
#endif
B
bellard 已提交
3668 3669
}

J
j_mayer 已提交
3670
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3671
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3672 3673
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3674
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3675 3676
#else
    /* Restore CPU state */
A
aurel32 已提交
3677
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3678
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3679 3680
        return;
    }
D
David Gibson 已提交
3681
    gen_update_cfar(ctx, ctx->nip);
3682
    gen_helper_rfid();
A
aurel32 已提交
3683
    gen_sync_exception(ctx);
J
j_mayer 已提交
3684 3685 3686
#endif
}

B
Blue Swirl 已提交
3687
static void gen_hrfid(DisasContext *ctx)
3688 3689
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3690
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3691 3692
#else
    /* Restore CPU state */
A
aurel32 已提交
3693
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3694
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3695 3696
        return;
    }
3697
    gen_helper_hrfid();
A
aurel32 已提交
3698
    gen_sync_exception(ctx);
3699 3700 3701 3702
#endif
}
#endif

B
bellard 已提交
3703
/* sc */
3704 3705 3706 3707 3708
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3709
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3710
{
3711 3712 3713
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3714
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3715 3716 3717
}

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

3719
/* tw */
B
Blue Swirl 已提交
3720
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3721
{
3722
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3723 3724
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3725 3726
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
B
bellard 已提交
3727 3728 3729
}

/* twi */
B
Blue Swirl 已提交
3730
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3731
{
3732 3733
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3734 3735
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3736 3737 3738
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3739 3740
}

3741 3742
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3743
static void gen_td(DisasContext *ctx)
3744
{
3745
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3746 3747
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3748 3749
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
3750 3751 3752
}

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

B
bellard 已提交
3765
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3766

3767
/* mcrxr */
B
Blue Swirl 已提交
3768
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3769
{
A
aurel32 已提交
3770 3771
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3772
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3773 3774
}

A
aurel32 已提交
3775
/* mfcr mfocrf */
B
Blue Swirl 已提交
3776
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3777
{
3778
    uint32_t crm, crn;
3779

3780 3781
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3782
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3783
            crn = ctz32 (crm);
3784
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3785 3786
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3787
        }
3788
    } else {
A
aurel32 已提交
3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806
        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);
3807
    }
B
bellard 已提交
3808 3809 3810
}

/* mfmsr */
B
Blue Swirl 已提交
3811
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3812
{
3813
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3814
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3815
#else
A
aurel32 已提交
3816
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3817
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3818
        return;
3819
    }
3820
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3821
#endif
B
bellard 已提交
3822 3823
}

3824
static void spr_noaccess(void *opaque, int gprn, int sprn)
3825
{
3826
#if 0
3827 3828
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3829
#endif
3830 3831 3832
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3833
/* mfspr */
B
Blue Swirl 已提交
3834
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3835
{
A
aurel32 已提交
3836
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3837 3838
    uint32_t sprn = SPR(ctx->opcode);

3839
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3840
    if (ctx->mem_idx == 2)
3841
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3842
    else if (ctx->mem_idx)
3843 3844
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3845
#endif
3846
        read_cb = ctx->spr_cb[sprn].uea_read;
3847 3848
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3849
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3850 3851
        } else {
            /* Privilege exception */
3852 3853 3854 3855 3856
            /* 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) {
3857
                qemu_log("Trying to read privileged spr %d %03x at "
3858 3859 3860
                         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);
3861
            }
A
aurel32 已提交
3862
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3863
        }
3864 3865
    } else {
        /* Not defined */
3866
        qemu_log("Trying to read invalid spr %d %03x at "
3867 3868
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3869
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3870
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3871 3872 3873
    }
}

B
Blue Swirl 已提交
3874
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3875
{
3876
    gen_op_mfspr(ctx);
3877
}
3878 3879

/* mftb */
B
Blue Swirl 已提交
3880
static void gen_mftb(DisasContext *ctx)
3881 3882
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3883 3884
}

A
aurel32 已提交
3885
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3886
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3887
{
3888
    uint32_t crm, crn;
3889

3890
    crm = CRM(ctx->opcode);
M
malc 已提交
3891 3892 3893
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3894
            crn = ctz32 (crm);
M
malc 已提交
3895
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3896 3897
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3898 3899
            tcg_temp_free_i32(temp);
        }
3900
    } else {
A
aurel32 已提交
3901 3902 3903 3904 3905 3906 3907 3908
        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 已提交
3909
        tcg_temp_free_i32(temp);
3910
    }
B
bellard 已提交
3911 3912 3913
}

/* mtmsr */
J
j_mayer 已提交
3914
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3915
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3916 3917
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3918
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3919
#else
A
aurel32 已提交
3920
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3921
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3922 3923
        return;
    }
3924 3925
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3926 3927 3928 3929 3930
        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);
3931
    } else {
3932 3933 3934 3935
        /* 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
         */
3936
        gen_update_nip(ctx, ctx->nip);
3937
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3938 3939
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3940
        gen_stop_exception(ctx);
3941
    }
J
j_mayer 已提交
3942 3943 3944 3945
#endif
}
#endif

B
Blue Swirl 已提交
3946
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3947
{
3948
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3949
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3950
#else
A
aurel32 已提交
3951
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3952
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3953
        return;
3954
    }
3955 3956
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3957 3958 3959 3960 3961
        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);
3962
    } else {
3963 3964
        TCGv msr = tcg_temp_new();

3965 3966 3967 3968
        /* 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
         */
3969
        gen_update_nip(ctx, ctx->nip);
3970
#if defined(TARGET_PPC64)
3971 3972 3973
        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)]);
3974
#endif
3975
        gen_helper_store_msr(msr);
3976
        /* Must stop the translation as machine state (may have) changed */
3977
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3978
        gen_stop_exception(ctx);
3979
    }
3980
#endif
B
bellard 已提交
3981 3982 3983
}

/* mtspr */
B
Blue Swirl 已提交
3984
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
3985
{
A
aurel32 已提交
3986
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3987 3988
    uint32_t sprn = SPR(ctx->opcode);

3989
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3990
    if (ctx->mem_idx == 2)
3991
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3992
    else if (ctx->mem_idx)
3993 3994
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3995
#endif
3996
        write_cb = ctx->spr_cb[sprn].uea_write;
3997 3998
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3999
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4000 4001
        } else {
            /* Privilege exception */
4002
            qemu_log("Trying to write privileged spr %d %03x at "
4003 4004 4005
                     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 已提交
4006
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4007
        }
4008 4009
    } else {
        /* Not defined */
4010
        qemu_log("Trying to write invalid spr %d %03x at "
4011 4012
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
4013
               sprn, sprn, ctx->nip);
A
aurel32 已提交
4014
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4015 4016 4017 4018
    }
}

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

4020
/* dcbf */
B
Blue Swirl 已提交
4021
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
4022
{
J
j_mayer 已提交
4023
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
4024 4025 4026 4027 4028
    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);
4029
    tcg_temp_free(t0);
B
bellard 已提交
4030 4031 4032
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4033
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4034
{
4035
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4036
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4037
#else
A
aurel32 已提交
4038
    TCGv EA, val;
A
aurel32 已提交
4039
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4040
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4041
        return;
4042
    }
P
pbrook 已提交
4043
    EA = tcg_temp_new();
A
aurel32 已提交
4044 4045
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4046
    val = tcg_temp_new();
4047
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4048 4049
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4050 4051
    tcg_temp_free(val);
    tcg_temp_free(EA);
4052
#endif
B
bellard 已提交
4053 4054 4055
}

/* dcdst */
B
Blue Swirl 已提交
4056
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4057
{
4058
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4059 4060 4061 4062 4063
    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);
4064
    tcg_temp_free(t0);
B
bellard 已提交
4065 4066 4067
}

/* dcbt */
B
Blue Swirl 已提交
4068
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4069
{
4070
    /* interpreted as no-op */
4071 4072 4073
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4074 4075 4076
}

/* dcbtst */
B
Blue Swirl 已提交
4077
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4078
{
4079
    /* interpreted as no-op */
4080 4081 4082
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4083 4084 4085
}

/* dcbz */
B
Blue Swirl 已提交
4086
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4087
{
A
aurel32 已提交
4088 4089
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4090 4091
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4092 4093
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4094 4095
    gen_helper_dcbz(t0);
    tcg_temp_free(t0);
4096 4097
}

B
Blue Swirl 已提交
4098
static void gen_dcbz_970(DisasContext *ctx)
4099
{
A
aurel32 已提交
4100 4101
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4102 4103
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4104 4105
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4106
    if (ctx->opcode & 0x00200000)
4107
        gen_helper_dcbz(t0);
4108
    else
4109 4110
        gen_helper_dcbz_970(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4111 4112
}

4113
/* dst / dstt */
B
Blue Swirl 已提交
4114
static void gen_dst(DisasContext *ctx)
4115 4116 4117 4118 4119 4120 4121 4122 4123
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4124
static void gen_dstst(DisasContext *ctx)
4125 4126 4127 4128 4129 4130 4131 4132 4133 4134
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4135
static void gen_dss(DisasContext *ctx)
4136 4137 4138 4139
{
    /* interpreted as no-op */
}

B
bellard 已提交
4140
/* icbi */
B
Blue Swirl 已提交
4141
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4142
{
A
aurel32 已提交
4143 4144
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4145 4146
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4147 4148
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4149 4150
    gen_helper_icbi(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4151 4152 4153 4154
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4155
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4156
{
4157 4158 4159 4160
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4161 4162 4163 4164
}

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

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

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

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

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

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

4241
/* mfsr */
B
Blue Swirl 已提交
4242
static void gen_mfsr_64b(DisasContext *ctx)
4243 4244
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4245
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4246
#else
4247
    TCGv t0;
A
aurel32 已提交
4248
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4249
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4250 4251
        return;
    }
4252
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4253
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4254
    tcg_temp_free(t0);
4255 4256 4257 4258
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4259
static void gen_mfsrin_64b(DisasContext *ctx)
4260 4261
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4262
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4263
#else
4264
    TCGv t0;
A
aurel32 已提交
4265
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4266
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4267 4268
        return;
    }
4269 4270 4271
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4272
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4273
    tcg_temp_free(t0);
4274 4275 4276 4277
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4278
static void gen_mtsr_64b(DisasContext *ctx)
4279 4280
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4281
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4282
#else
4283
    TCGv t0;
A
aurel32 已提交
4284
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4285
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4286 4287
        return;
    }
4288
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4289
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4290
    tcg_temp_free(t0);
4291 4292 4293 4294
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4295
static void gen_mtsrin_64b(DisasContext *ctx)
4296 4297
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4298
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4299
#else
4300
    TCGv t0;
A
aurel32 已提交
4301
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4302
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4303 4304
        return;
    }
4305 4306 4307
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4308
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4309
    tcg_temp_free(t0);
4310 4311
#endif
}
B
blueswir1 已提交
4312 4313

/* slbmte */
B
Blue Swirl 已提交
4314
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326
{
#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;
    }
    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
#endif
}

4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353
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;
    }
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
                             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;
    }
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4354 4355
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4356
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4357
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4358

4359
/* tlbia */
B
Blue Swirl 已提交
4360
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4361
{
4362
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4363
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4364
#else
A
aurel32 已提交
4365
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4366
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4367
        return;
4368
    }
4369
    gen_helper_tlbia();
4370
#endif
B
bellard 已提交
4371 4372
}

B
blueswir1 已提交
4373
/* tlbiel */
B
Blue Swirl 已提交
4374
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386
{
#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;
    }
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
#endif
}

B
bellard 已提交
4387
/* tlbie */
B
Blue Swirl 已提交
4388
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4389
{
4390
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4391
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4392
#else
A
aurel32 已提交
4393
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4394
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4395
        return;
4396
    }
4397
#if defined(TARGET_PPC64)
4398 4399 4400 4401 4402 4403
    if (!ctx->sf_mode) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
        gen_helper_tlbie(t0);
        tcg_temp_free(t0);
    } else
4404
#endif
4405
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4406
#endif
B
bellard 已提交
4407 4408 4409
}

/* tlbsync */
B
Blue Swirl 已提交
4410
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4411
{
4412
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4413
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4414
#else
A
aurel32 已提交
4415
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4416
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4417
        return;
4418 4419 4420 4421
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4422
    gen_stop_exception(ctx);
4423
#endif
B
bellard 已提交
4424 4425
}

J
j_mayer 已提交
4426 4427
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4428
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4429 4430
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4431
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4432
#else
A
aurel32 已提交
4433
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4434
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4435 4436
        return;
    }
4437
    gen_helper_slbia();
J
j_mayer 已提交
4438 4439 4440 4441
#endif
}

/* slbie */
B
Blue Swirl 已提交
4442
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4443 4444
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4445
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4446
#else
A
aurel32 已提交
4447
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4448
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4449 4450
        return;
    }
4451
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4452 4453 4454 4455
#endif
}
#endif

B
bellard 已提交
4456 4457
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4458

4459
/* eciwx */
B
Blue Swirl 已提交
4460
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4461
{
A
aurel32 已提交
4462
    TCGv t0;
4463
    /* Should check EAR[E] ! */
A
aurel32 已提交
4464 4465 4466
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4467
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4468
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4469
    tcg_temp_free(t0);
4470 4471 4472
}

/* ecowx */
B
Blue Swirl 已提交
4473
static void gen_ecowx(DisasContext *ctx)
4474
{
A
aurel32 已提交
4475
    TCGv t0;
4476
    /* Should check EAR[E] ! */
A
aurel32 已提交
4477 4478 4479
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4480
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4481
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4482
    tcg_temp_free(t0);
4483 4484 4485
}

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

4487
/* abs - abs. */
B
Blue Swirl 已提交
4488
static void gen_abs(DisasContext *ctx)
4489
{
4490 4491 4492 4493 4494 4495 4496 4497
    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);
4498
    if (unlikely(Rc(ctx->opcode) != 0))
4499
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4500 4501 4502
}

/* abso - abso. */
B
Blue Swirl 已提交
4503
static void gen_abso(DisasContext *ctx)
4504
{
4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    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);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    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);
4520
    if (unlikely(Rc(ctx->opcode) != 0))
4521
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4522 4523 4524
}

/* clcs */
B
Blue Swirl 已提交
4525
static void gen_clcs(DisasContext *ctx)
4526
{
4527 4528 4529
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
4530
    /* Rc=1 sets CR0 to an undefined state */
4531 4532 4533
}

/* div - div. */
B
Blue Swirl 已提交
4534
static void gen_div(DisasContext *ctx)
4535
{
4536
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4537
    if (unlikely(Rc(ctx->opcode) != 0))
4538
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4539 4540 4541
}

/* divo - divo. */
B
Blue Swirl 已提交
4542
static void gen_divo(DisasContext *ctx)
4543
{
4544
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4545
    if (unlikely(Rc(ctx->opcode) != 0))
4546
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4547 4548 4549
}

/* divs - divs. */
B
Blue Swirl 已提交
4550
static void gen_divs(DisasContext *ctx)
4551
{
4552
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4553
    if (unlikely(Rc(ctx->opcode) != 0))
4554
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4555 4556 4557
}

/* divso - divso. */
B
Blue Swirl 已提交
4558
static void gen_divso(DisasContext *ctx)
4559
{
4560
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4561
    if (unlikely(Rc(ctx->opcode) != 0))
4562
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4563 4564 4565
}

/* doz - doz. */
B
Blue Swirl 已提交
4566
static void gen_doz(DisasContext *ctx)
4567
{
4568 4569 4570 4571 4572 4573 4574 4575
    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);
4576
    if (unlikely(Rc(ctx->opcode) != 0))
4577
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4578 4579 4580
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4581
static void gen_dozo(DisasContext *ctx)
4582
{
4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604
    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 */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    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);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    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);
4605
    if (unlikely(Rc(ctx->opcode) != 0))
4606
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4607 4608 4609
}

/* dozi */
B
Blue Swirl 已提交
4610
static void gen_dozi(DisasContext *ctx)
4611
{
4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622
    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)]);
4623 4624 4625
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4626
static void gen_lscbx(DisasContext *ctx)
4627
{
4628 4629 4630 4631
    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));
4632

A
aurel32 已提交
4633
    gen_addr_reg_index(ctx, t0);
4634
    /* NIP cannot be restored if the memory exception comes from an helper */
4635
    gen_update_nip(ctx, ctx->nip - 4);
4636 4637 4638 4639
    gen_helper_lscbx(t0, t0, t1, t2, t3);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4640
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4641
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4642
    if (unlikely(Rc(ctx->opcode) != 0))
4643 4644
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4645 4646 4647
}

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

/* maskir - maskir. */
B
Blue Swirl 已提交
4674
static void gen_maskir(DisasContext *ctx)
4675
{
4676 4677 4678 4679 4680 4681 4682
    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);
4683
    if (unlikely(Rc(ctx->opcode) != 0))
4684
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4685 4686 4687
}

/* mul - mul. */
B
Blue Swirl 已提交
4688
static void gen_mul(DisasContext *ctx)
4689
{
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702
    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);
4703
    if (unlikely(Rc(ctx->opcode) != 0))
4704
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4705 4706 4707
}

/* mulo - mulo. */
B
Blue Swirl 已提交
4708
static void gen_mulo(DisasContext *ctx)
4709
{
4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729
    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 */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    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);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4730
    if (unlikely(Rc(ctx->opcode) != 0))
4731
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4732 4733 4734
}

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

/* nabso - nabso. */
B
Blue Swirl 已提交
4750
static void gen_nabso(DisasContext *ctx)
4751
{
4752 4753 4754 4755 4756 4757 4758 4759 4760 4761
    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 */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4762
    if (unlikely(Rc(ctx->opcode) != 0))
4763
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4764 4765 4766
}

/* rlmi - rlmi. */
B
Blue Swirl 已提交
4767
static void gen_rlmi(DisasContext *ctx)
4768
{
4769 4770 4771 4772 4773 4774 4775 4776 4777
    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);
4778
    if (unlikely(Rc(ctx->opcode) != 0))
4779
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4780 4781 4782
}

/* rrib - rrib. */
B
Blue Swirl 已提交
4783
static void gen_rrib(DisasContext *ctx)
4784
{
4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795
    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);
4796
    if (unlikely(Rc(ctx->opcode) != 0))
4797
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4798 4799 4800
}

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

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

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

/* slliq - slliq. */
B
Blue Swirl 已提交
4858
static void gen_slliq(DisasContext *ctx)
4859
{
4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
    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);
4871
    if (unlikely(Rc(ctx->opcode) != 0))
4872
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4873 4874 4875
}

/* sllq - sllq. */
B
Blue Swirl 已提交
4876
static void gen_sllq(DisasContext *ctx)
4877
{
4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899
    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);
4900
    if (unlikely(Rc(ctx->opcode) != 0))
4901
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4902 4903 4904
}

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

4927
/* sraiq - sraiq. */
B
Blue Swirl 已提交
4928
static void gen_sraiq(DisasContext *ctx)
4929
{
4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945
    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);
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
    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);
4946
    if (unlikely(Rc(ctx->opcode) != 0))
4947
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4948 4949 4950
}

/* sraq - sraq. */
B
Blue Swirl 已提交
4951
static void gen_sraq(DisasContext *ctx)
4952
{
4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978
    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);
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4979
    if (unlikely(Rc(ctx->opcode) != 0))
4980
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4981 4982 4983
}

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

/* srea - srea. */
B
Blue Swirl 已提交
5002
static void gen_srea(DisasContext *ctx)
5003
{
5004 5005 5006 5007 5008 5009 5010 5011
    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);
5012
    if (unlikely(Rc(ctx->opcode) != 0))
5013
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5014 5015 5016
}

/* sreq */
B
Blue Swirl 已提交
5017
static void gen_sreq(DisasContext *ctx)
5018
{
5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033
    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);
5034
    if (unlikely(Rc(ctx->opcode) != 0))
5035
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5036 5037 5038
}

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

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

/* srlq */
B
Blue Swirl 已提交
5074
static void gen_srlq(DisasContext *ctx)
5075
{
5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098
    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);
5099
    if (unlikely(Rc(ctx->opcode) != 0))
5100
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5101 5102 5103
}

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

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

5128
/* dsa  */
B
Blue Swirl 已提交
5129
static void gen_dsa(DisasContext *ctx)
5130 5131
{
    /* XXX: TODO */
A
aurel32 已提交
5132
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5133 5134 5135
}

/* esa */
B
Blue Swirl 已提交
5136
static void gen_esa(DisasContext *ctx)
5137 5138
{
    /* XXX: TODO */
A
aurel32 已提交
5139
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5140 5141 5142
}

/* mfrom */
B
Blue Swirl 已提交
5143
static void gen_mfrom(DisasContext *ctx)
5144 5145
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5146
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5147
#else
A
aurel32 已提交
5148
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5149
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5150 5151
        return;
    }
5152
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5153 5154 5155 5156
#endif
}

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

5158
/* tlbld */
B
Blue Swirl 已提交
5159
static void gen_tlbld_6xx(DisasContext *ctx)
5160 5161
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5162
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5163
#else
A
aurel32 已提交
5164
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5165
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5166 5167
        return;
    }
5168
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5169 5170 5171 5172
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5173
static void gen_tlbli_6xx(DisasContext *ctx)
5174 5175
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5176
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5177
#else
A
aurel32 已提交
5178
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5179
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5180 5181
        return;
    }
5182
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5183 5184 5185
#endif
}

5186
/* 74xx TLB management */
B
Blue Swirl 已提交
5187

5188
/* tlbld */
B
Blue Swirl 已提交
5189
static void gen_tlbld_74xx(DisasContext *ctx)
5190 5191
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5192
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5193
#else
A
aurel32 已提交
5194
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5195
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5196 5197
        return;
    }
5198
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5199 5200 5201 5202
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5203
static void gen_tlbli_74xx(DisasContext *ctx)
5204 5205
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5206
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5207
#else
A
aurel32 已提交
5208
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5209
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5210 5211
        return;
    }
5212
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5213 5214 5215
#endif
}

5216
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5217

5218
/* clf */
B
Blue Swirl 已提交
5219
static void gen_clf(DisasContext *ctx)
5220 5221 5222 5223 5224
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5225
static void gen_cli(DisasContext *ctx)
5226
{
B
blueswir1 已提交
5227
    /* Cache line invalidate: privileged and treated as no-op */
5228
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5229
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5230
#else
A
aurel32 已提交
5231
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5232
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5233 5234 5235 5236 5237 5238
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5239
static void gen_dclst(DisasContext *ctx)
5240 5241 5242 5243
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5244
static void gen_mfsri(DisasContext *ctx)
5245 5246
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5247
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5248
#else
5249 5250 5251
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5252
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5253
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5254 5255
        return;
    }
5256
    t0 = tcg_temp_new();
A
aurel32 已提交
5257
    gen_addr_reg_index(ctx, t0);
5258 5259 5260 5261
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
    gen_helper_load_sr(cpu_gpr[rd], t0);
    tcg_temp_free(t0);
5262
    if (ra != 0 && ra != rd)
5263
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5264 5265 5266
#endif
}

B
Blue Swirl 已提交
5267
static void gen_rac(DisasContext *ctx)
5268 5269
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5270
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5271
#else
5272
    TCGv t0;
A
aurel32 已提交
5273
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5274
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5275 5276
        return;
    }
5277
    t0 = tcg_temp_new();
A
aurel32 已提交
5278
    gen_addr_reg_index(ctx, t0);
5279 5280
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
5281 5282 5283
#endif
}

B
Blue Swirl 已提交
5284
static void gen_rfsvc(DisasContext *ctx)
5285 5286
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5287
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5288
#else
A
aurel32 已提交
5289
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5290
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5291 5292
        return;
    }
5293
    gen_helper_rfsvc();
A
aurel32 已提交
5294
    gen_sync_exception(ctx);
5295 5296 5297 5298 5299 5300 5301 5302 5303
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5304
static void gen_lfq(DisasContext *ctx)
5305
{
5306
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5307 5308 5309 5310 5311 5312 5313
    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);
5314
    tcg_temp_free(t0);
5315 5316 5317
}

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

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

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

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

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

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

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

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

5437
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5438
static void gen_mfapidi(DisasContext *ctx)
5439 5440
{
    /* XXX: TODO */
A
aurel32 已提交
5441
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5442 5443
}

5444
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5445
static void gen_tlbiva(DisasContext *ctx)
5446 5447
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5448
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5449
#else
5450
    TCGv t0;
A
aurel32 已提交
5451
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5452
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5453 5454
        return;
    }
5455
    t0 = tcg_temp_new();
A
aurel32 已提交
5456
    gen_addr_reg_index(ctx, t0);
5457 5458
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(t0);
5459 5460 5461 5462
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5463 5464
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5465
{
5466 5467
    TCGv t0, t1;

P
pbrook 已提交
5468 5469
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5470

5471 5472 5473 5474 5475 5476 5477
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5478 5479 5480
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5481 5482 5483 5484 5485
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5486 5487 5488
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5489 5490 5491 5492 5493 5494 5495
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5496 5497 5498 5499
        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);
5500 5501 5502 5503 5504
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5505 5506 5507 5508
        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);
5509 5510 5511 5512 5513 5514 5515
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5516 5517
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5518 5519 5520 5521 5522
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5523 5524
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5525 5526 5527
        break;
    }
    if (opc2 & 0x04) {
5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
        tcg_gen_mul_tl(t1, t0, t1);
        if (opc2 & 0x02) {
            /* nmultiply-and-accumulate (0x0E) */
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
        } else {
            /* multiply-and-accumulate (0x0C) */
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
        }

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

            if (opc3 & 0x10) {
                /* Start with XER OV disabled, the most likely case */
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
            }
            if (opc3 & 0x01) {
                /* Signed */
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
A
aurel32 已提交
5552
                if (opc3 & 0x02) {
5553 5554 5555 5556 5557 5558 5559
                    /* 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 已提交
5560
                if (opc3 & 0x02) {
5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5574
    }
5575 5576
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5577 5578
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5579
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5580 5581 5582
    }
}

5583
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5584
static void glue(gen_, name)(DisasContext *ctx)                               \
5585 5586 5587 5588 5589 5590
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5591
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5592
/* macchwo   - macchwo.   */
5593
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5594
/* macchws   - macchws.   */
5595
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5596
/* macchwso  - macchwso.  */
5597
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5598
/* macchwsu  - macchwsu.  */
5599
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5600
/* macchwsuo - macchwsuo. */
5601
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5602
/* macchwu   - macchwu.   */
5603
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5604
/* macchwuo  - macchwuo.  */
5605
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5606
/* machhw    - machhw.    */
5607
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5608
/* machhwo   - machhwo.   */
5609
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5610
/* machhws   - machhws.   */
5611
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5612
/* machhwso  - machhwso.  */
5613
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5614
/* machhwsu  - machhwsu.  */
5615
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5616
/* machhwsuo - machhwsuo. */
5617
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5618
/* machhwu   - machhwu.   */
5619
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5620
/* machhwuo  - machhwuo.  */
5621
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5622
/* maclhw    - maclhw.    */
5623
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5624
/* maclhwo   - maclhwo.   */
5625
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5626
/* maclhws   - maclhws.   */
5627
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5628
/* maclhwso  - maclhwso.  */
5629
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5630
/* maclhwu   - maclhwu.   */
5631
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5632
/* maclhwuo  - maclhwuo.  */
5633
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5634
/* maclhwsu  - maclhwsu.  */
5635
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5636
/* maclhwsuo - maclhwsuo. */
5637
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5638
/* nmacchw   - nmacchw.   */
5639
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5640
/* nmacchwo  - nmacchwo.  */
5641
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5642
/* nmacchws  - nmacchws.  */
5643
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5644
/* nmacchwso - nmacchwso. */
5645
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5646
/* nmachhw   - nmachhw.   */
5647
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5648
/* nmachhwo  - nmachhwo.  */
5649
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5650
/* nmachhws  - nmachhws.  */
5651
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5652
/* nmachhwso - nmachhwso. */
5653
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5654
/* nmaclhw   - nmaclhw.   */
5655
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5656
/* nmaclhwo  - nmaclhwo.  */
5657
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5658
/* nmaclhws  - nmaclhws.  */
5659
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5660
/* nmaclhwso - nmaclhwso. */
5661
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5662 5663

/* mulchw  - mulchw.  */
5664
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5665
/* mulchwu - mulchwu. */
5666
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5667
/* mulhhw  - mulhhw.  */
5668
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5669
/* mulhhwu - mulhhwu. */
5670
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5671
/* mullhw  - mullhw.  */
5672
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5673
/* mullhwu - mullhwu. */
5674
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5675 5676

/* mfdcr */
B
Blue Swirl 已提交
5677
static void gen_mfdcr(DisasContext *ctx)
5678 5679
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5680
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5681
#else
5682
    TCGv dcrn;
A
aurel32 已提交
5683
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5684
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5685 5686
        return;
    }
5687 5688 5689 5690 5691
    /* 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));
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
    tcg_temp_free(dcrn);
5692 5693 5694 5695
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5696
static void gen_mtdcr(DisasContext *ctx)
5697 5698
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5699
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5700
#else
5701
    TCGv dcrn;
A
aurel32 已提交
5702
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5703
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5704 5705
        return;
    }
5706 5707 5708 5709 5710
    /* 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));
    gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
    tcg_temp_free(dcrn);
5711 5712 5713 5714
#endif
}

/* mfdcrx */
5715
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5716
static void gen_mfdcrx(DisasContext *ctx)
5717 5718
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5719
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5720
#else
A
aurel32 已提交
5721
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5722
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5723 5724
        return;
    }
5725 5726 5727
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5728
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5729 5730 5731 5732
#endif
}

/* mtdcrx */
5733
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5734
static void gen_mtdcrx(DisasContext *ctx)
5735 5736
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5737
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5738
#else
A
aurel32 已提交
5739
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5740
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5741 5742
        return;
    }
5743 5744 5745
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5746
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5747 5748 5749
#endif
}

5750
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5751
static void gen_mfdcrux(DisasContext *ctx)
5752
{
5753 5754 5755
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5756 5757 5758 5759
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5760
static void gen_mtdcrux(DisasContext *ctx)
5761
{
5762 5763 5764
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5765 5766 5767
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

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

/* dcread */
B
Blue Swirl 已提交
5783
static void gen_dcread(DisasContext *ctx)
5784 5785
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5786
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5787
#else
A
aurel32 已提交
5788
    TCGv EA, val;
A
aurel32 已提交
5789
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5790
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5791 5792
        return;
    }
A
aurel32 已提交
5793
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5794
    EA = tcg_temp_new();
A
aurel32 已提交
5795
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5796
    val = tcg_temp_new();
A
aurel32 已提交
5797
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5798 5799 5800
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5801 5802 5803 5804
#endif
}

/* icbt */
B
Blue Swirl 已提交
5805
static void gen_icbt_40x(DisasContext *ctx)
5806 5807 5808 5809 5810 5811 5812 5813
{
    /* 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 已提交
5814
static void gen_iccci(DisasContext *ctx)
5815 5816
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5817
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5818
#else
A
aurel32 已提交
5819
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5820
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5821 5822 5823 5824 5825 5826 5827
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5828
static void gen_icread(DisasContext *ctx)
5829 5830
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5831
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5832
#else
A
aurel32 已提交
5833
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5834
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5835 5836 5837 5838 5839 5840
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5841
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5842
static void gen_rfci_40x(DisasContext *ctx)
5843 5844
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5845
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5846
#else
A
aurel32 已提交
5847
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5848
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5849 5850 5851
        return;
    }
    /* Restore CPU state */
5852
    gen_helper_40x_rfci();
A
aurel32 已提交
5853
    gen_sync_exception(ctx);
5854 5855 5856
#endif
}

B
Blue Swirl 已提交
5857
static void gen_rfci(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
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5863
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5864 5865 5866
        return;
    }
    /* Restore CPU state */
5867
    gen_helper_rfci();
A
aurel32 已提交
5868
    gen_sync_exception(ctx);
5869 5870 5871 5872
#endif
}

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

5874
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5875
static void gen_rfdi(DisasContext *ctx)
5876 5877
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5878
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5879
#else
A
aurel32 已提交
5880
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5881
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5882 5883 5884
        return;
    }
    /* Restore CPU state */
5885
    gen_helper_rfdi();
A
aurel32 已提交
5886
    gen_sync_exception(ctx);
5887 5888 5889
#endif
}

5890
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5891
static void gen_rfmci(DisasContext *ctx)
5892 5893
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5894
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5895
#else
A
aurel32 已提交
5896
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5897
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5898 5899 5900
        return;
    }
    /* Restore CPU state */
5901
    gen_helper_rfmci();
A
aurel32 已提交
5902
    gen_sync_exception(ctx);
5903 5904
#endif
}
5905

5906
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5907

5908
/* tlbre */
B
Blue Swirl 已提交
5909
static void gen_tlbre_40x(DisasContext *ctx)
5910 5911
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5912
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5913
#else
A
aurel32 已提交
5914
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5915
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5916 5917 5918 5919
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5920
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5921 5922
        break;
    case 1:
5923
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5924 5925
        break;
    default:
A
aurel32 已提交
5926
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5927
        break;
5928
    }
5929 5930 5931
#endif
}

5932
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5933
static void gen_tlbsx_40x(DisasContext *ctx)
5934 5935
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5936
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5937
#else
5938
    TCGv t0;
A
aurel32 已提交
5939
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5940
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5941 5942
        return;
    }
5943
    t0 = tcg_temp_new();
A
aurel32 已提交
5944
    gen_addr_reg_index(ctx, t0);
5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        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);
    }
5956
#endif
B
bellard 已提交
5957 5958
}

5959
/* tlbwe */
B
Blue Swirl 已提交
5960
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5961
{
5962
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5963
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5964
#else
A
aurel32 已提交
5965
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5966
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5967 5968 5969 5970
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5971
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5972 5973
        break;
    case 1:
5974
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5975 5976
        break;
    default:
A
aurel32 已提交
5977
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5978
        break;
5979
    }
5980 5981 5982
#endif
}

5983
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5984

5985
/* tlbre */
B
Blue Swirl 已提交
5986
static void gen_tlbre_440(DisasContext *ctx)
5987 5988
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5989
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5990
#else
A
aurel32 已提交
5991
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5992
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5993 5994 5995 5996 5997 5998
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5999 6000
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
E
Edgar E. Iglesias 已提交
6001
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
6002 6003
            tcg_temp_free_i32(t0);
        }
6004 6005
        break;
    default:
A
aurel32 已提交
6006
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6007 6008 6009 6010 6011 6012
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6013
static void gen_tlbsx_440(DisasContext *ctx)
6014 6015
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6016
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6017
#else
6018
    TCGv t0;
A
aurel32 已提交
6019
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6020
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6021 6022
        return;
    }
6023
    t0 = tcg_temp_new();
A
aurel32 已提交
6024
    gen_addr_reg_index(ctx, t0);
6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        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);
    }
6036 6037 6038 6039
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
6040
static void gen_tlbwe_440(DisasContext *ctx)
6041 6042
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6043
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6044
#else
A
aurel32 已提交
6045
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6046
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6047 6048 6049 6050 6051 6052
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6053 6054 6055 6056 6057
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
            tcg_temp_free_i32(t0);
        }
6058 6059
        break;
    default:
A
aurel32 已提交
6060
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6061 6062 6063 6064 6065
        break;
    }
#endif
}

A
Alexander Graf 已提交
6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116
/* 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;
    }

    gen_helper_booke206_tlbre();
#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)]);
    gen_helper_booke206_tlbsx(t0);
#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;
    }
6117
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139
    gen_helper_booke206_tlbwe();
#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);

    gen_helper_booke206_tlbivax(t0);
#endif
}

A
Alexander Graf 已提交
6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172
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:
        gen_helper_booke206_tlbilx0(t0);
        break;
    case 1:
        gen_helper_booke206_tlbilx1(t0);
        break;
    case 3:
        gen_helper_booke206_tlbilx3(t0);
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6173

6174
/* wrtee */
B
Blue Swirl 已提交
6175
static void gen_wrtee(DisasContext *ctx)
6176 6177
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6178
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6179
#else
6180
    TCGv t0;
A
aurel32 已提交
6181
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6182
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6183 6184
        return;
    }
6185 6186 6187 6188 6189
    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 已提交
6190 6191 6192
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6193
    gen_stop_exception(ctx);
6194 6195 6196 6197
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6198
static void gen_wrteei(DisasContext *ctx)
6199 6200
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6201
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6202
#else
A
aurel32 已提交
6203
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6204
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6205 6206
        return;
    }
6207
    if (ctx->opcode & 0x00008000) {
6208 6209
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6210
        gen_stop_exception(ctx);
6211
    } else {
A
aurel32 已提交
6212
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6213
    }
6214 6215 6216
#endif
}

J
j_mayer 已提交
6217
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6218

6219
/* dlmzb */
B
Blue Swirl 已提交
6220
static void gen_dlmzb(DisasContext *ctx)
6221
{
6222 6223 6224 6225
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
                     cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
6226 6227 6228
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6229
static void gen_mbar(DisasContext *ctx)
6230 6231 6232 6233 6234
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6235
static void gen_msync_4xx(DisasContext *ctx)
6236 6237 6238 6239 6240
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6241
static void gen_icbt_440(DisasContext *ctx)
6242 6243 6244 6245 6246
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6247 6248
}

A
Alexander Graf 已提交
6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264
/* 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;
    }

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

A
Alexander Graf 已提交
6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278
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
}

6279 6280 6281
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6282
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6283
{
A
aurel32 已提交
6284
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6285 6286 6287 6288
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6289
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6290
static void glue(gen_, name)(DisasContext *ctx)                                       \
6291
{                                                                             \
6292
    TCGv EA;                                                                  \
6293
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6294
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6295 6296
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6297
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6298
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6299
    gen_addr_reg_index(ctx, EA);                                              \
6300
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6301 6302
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6303
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6304
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6305
    } else {                                                                  \
A
aurel32 已提交
6306
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6307
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6308
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6309 6310
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6311 6312 6313
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6314
static void gen_st##name(DisasContext *ctx)                                   \
6315
{                                                                             \
6316
    TCGv EA;                                                                  \
6317
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6318
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6319 6320
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6321
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6322
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6323
    gen_addr_reg_index(ctx, EA);                                              \
6324
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6325 6326
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6327
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6328
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6329
    } else {                                                                  \
A
aurel32 已提交
6330
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6331
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6332
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6333 6334
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6335 6336
}

A
aurel32 已提交
6337
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6338
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355
    {                                                                   \
        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));                              \
        gen_helper_lve##name (rs, EA);                                  \
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6356
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372
    {                                                                   \
        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));                              \
        gen_helper_stve##name (rs, EA);                                 \
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6373
GEN_VR_LDX(lvx, 0x07, 0x03);
6374
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6375
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6376

A
aurel32 已提交
6377 6378 6379 6380
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6381
GEN_VR_STX(svx, 0x07, 0x07);
6382
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6383
GEN_VR_STX(svxl, 0x07, 0x0F);
6384

A
aurel32 已提交
6385 6386 6387 6388
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6389
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404
{
    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 已提交
6405
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420
{
    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 已提交
6421
static void gen_mfvscr(DisasContext *ctx)
6422 6423 6424 6425 6426 6427 6428 6429
{
    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();
6430
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6431
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6432
    tcg_temp_free_i32(t);
6433 6434
}

B
Blue Swirl 已提交
6435
static void gen_mtvscr(DisasContext *ctx)
6436
{
A
aurel32 已提交
6437
    TCGv_ptr p;
6438 6439 6440 6441
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6442 6443 6444
    p = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_mtvscr(p);
    tcg_temp_free_ptr(p);
6445 6446
}

6447 6448
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6449
static void glue(gen_, name)(DisasContext *ctx)                                 \
6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464
{                                                                       \
    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);

6465
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6466
static void glue(gen_, name)(DisasContext *ctx)                                 \
6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481
{                                                                       \
    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);                                              \
}

A
aurel32 已提交
6482 6483 6484 6485 6486 6487
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);
6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499
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 已提交
6500 6501 6502 6503 6504 6505
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 已提交
6506 6507 6508 6509 6510 6511
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 已提交
6512 6513 6514 6515 6516 6517 6518 6519
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 已提交
6520 6521 6522
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6523 6524 6525 6526 6527 6528
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 已提交
6529 6530
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6531 6532
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544
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);
A
aurel32 已提交
6545 6546 6547
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6548 6549
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6550 6551 6552 6553 6554 6555 6556 6557
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);
A
aurel32 已提交
6558
GEN_VXFORM(vpkpx, 7, 12);
6559 6560 6561 6562 6563
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);
6564 6565
GEN_VXFORM(vaddfp, 5, 0);
GEN_VXFORM(vsubfp, 5, 1);
6566 6567
GEN_VXFORM(vmaxfp, 5, 16);
GEN_VXFORM(vminfp, 5, 17);
A
aurel32 已提交
6568

6569
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6570
static void glue(gen_, name)(DisasContext *ctx)                         \
6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589
    {                                                                   \
        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_##opname (rd, ra, rb);                               \
        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)))

6590 6591 6592 6593 6594 6595 6596 6597 6598
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)
6599 6600 6601 6602
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6603

A
aurel32 已提交
6604
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6605
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623
    {                                                                   \
        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);

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

A
aurel32 已提交
6639 6640 6641 6642
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 已提交
6643 6644
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
A
aurel32 已提交
6645
GEN_VXFORM_NOA(vrefp, 5, 4);
A
aurel32 已提交
6646
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6647
GEN_VXFORM_NOA(vexptefp, 5, 6);
6648
GEN_VXFORM_NOA(vlogefp, 5, 7);
A
aurel32 已提交
6649 6650 6651 6652
GEN_VXFORM_NOA(vrfim, 5, 8);
GEN_VXFORM_NOA(vrfin, 5, 9);
GEN_VXFORM_NOA(vrfip, 5, 10);
GEN_VXFORM_NOA(vrfiz, 5, 11);
A
aurel32 已提交
6653

6654
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6655
static void glue(gen_, name)(DisasContext *ctx)                                 \
6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669
    {                                                                   \
        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);                                          \
    }

6670
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6671
static void glue(gen_, name)(DisasContext *ctx)                                 \
6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687
    {                                                                   \
        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);                                          \
    }

A
aurel32 已提交
6688 6689 6690
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
A
aurel32 已提交
6691 6692
GEN_VXFORM_UIMM(vcfux, 5, 12);
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6693 6694
GEN_VXFORM_UIMM(vctuxs, 5, 14);
GEN_VXFORM_UIMM(vctsxs, 5, 15);
A
aurel32 已提交
6695

B
Blue Swirl 已提交
6696
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6697 6698
{
    TCGv_ptr ra, rb, rd;
6699
    TCGv_i32 sh;
A
aurel32 已提交
6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711
    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);
6712
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6713 6714
}

6715
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
B
Blue Swirl 已提交
6716
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                      \
6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737
    {                                                                   \
        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)) {                                          \
            gen_helper_##name1 (rd, ra, rb, rc);                        \
        } else {                                                        \
            gen_helper_##name0 (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 已提交
6738 6739
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6740
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757
{
    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 已提交
6758
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6759
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6760
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6761
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6762
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6763

6764 6765
/***                           SPE extension                               ***/
/* Register moves */
6766

6767 6768 6769 6770 6771

static inline void gen_evmra(DisasContext *ctx)
{

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

B
Blue Swirl 已提交
6809 6810
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6811 6812 6813
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6814
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6815 6816 6817
    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 已提交
6818
    tcg_temp_free_i64(tmp);
6819
#endif
A
aurel32 已提交
6820
}
6821

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

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6832
static inline void gen_speundef(DisasContext *ctx)
6833
{
A
aurel32 已提交
6834
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6835 6836
}

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

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

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

B
Blue Swirl 已提交
6949
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6950 6951 6952
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6953

6954 6955 6956 6957
    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 已提交
6958
    tcg_gen_mov_i32(ret, arg1);
6959 6960 6961 6962 6963 6964
    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 已提交
6965
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6966
{
6967 6968 6969 6970
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6971 6972
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6973

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

B
Blue Swirl 已提交
7015
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7016
{
P
pbrook 已提交
7017
    TCGv_i32 t0;
7018
    int l1, l2;
7019

7020 7021
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7022
    t0 = tcg_temp_local_new_i32();
7023 7024 7025 7026 7027 7028 7029
    /* 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);
7030
    gen_set_label(l2);
P
pbrook 已提交
7031
    tcg_temp_free_i32(t0);
7032 7033
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7034
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7035
{
P
pbrook 已提交
7036
    TCGv_i32 t0;
7037 7038 7039 7040
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7041
    t0 = tcg_temp_local_new_i32();
7042 7043 7044 7045 7046 7047 7048
    /* 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);
7049
    gen_set_label(l2);
P
pbrook 已提交
7050
    tcg_temp_free_i32(t0);
7051 7052
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7053
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7054
{
P
pbrook 已提交
7055
    TCGv_i32 t0;
7056 7057 7058 7059
    int l1, l2;

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

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

7300
#if defined(TARGET_PPC64)
7301
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7302 7303 7304 7305 7306
#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 已提交
7307
static inline void gen_evsplatfi(DisasContext *ctx)
7308
{
7309
    uint64_t imm = rA(ctx->opcode) << 27;
7310

7311
#if defined(TARGET_PPC64)
7312
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7313 7314 7315 7316
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7317 7318
}

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

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

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

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

static void gen_evsel3(DisasContext *ctx)
7384 7385 7386
{
    gen_evsel(ctx);
}
7387

7388 7389 7390 7391 7392 7393 7394
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7395
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423
        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)) {
7424
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7425 7426 7427 7428 7429 7430 7431 7432 7433
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7434
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7435 7436 7437 7438 7439 7440 7441 7442 7443
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7444
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456
        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 */
7457
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7458 7459 7460 7461 7462

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

    /* Store acc */
7463
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476

    /* 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)) {
7477
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510
        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));
7511
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529

    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 */
7530
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7531 7532 7533 7534 7535

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

    /* Store acc */
7536
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7537 7538 7539 7540 7541 7542 7543 7544

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573
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); ////
7574

7575
/* SPE load and stores */
B
Blue Swirl 已提交
7576
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7577 7578 7579
{
    target_ulong uimm = rB(ctx->opcode);

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

B
Blue Swirl 已提交
7592
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7593 7594
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7595
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7596 7597
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7598
    gen_qemu_ld64(ctx, t0, addr);
7599 7600 7601 7602 7603
    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
7604
}
7605

B
Blue Swirl 已提交
7606
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7607
{
7608
#if defined(TARGET_PPC64)
7609
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7610
    gen_qemu_ld32u(ctx, t0, addr);
7611
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7612 7613
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7614 7615 7616
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7617 7618 7619
    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);
7620
#endif
7621
}
7622

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

B
Blue Swirl 已提交
7656
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7657 7658
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7659
    gen_qemu_ld16u(ctx, t0, addr);
7660 7661 7662 7663 7664 7665 7666 7667 7668 7669
#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);
7670 7671
}

B
Blue Swirl 已提交
7672
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7673 7674
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7675
    gen_qemu_ld16u(ctx, t0, addr);
7676 7677 7678 7679 7680 7681 7682 7683
#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);
7684 7685
}

B
Blue Swirl 已提交
7686
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7687 7688
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7689
    gen_qemu_ld16s(ctx, t0, addr);
7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700
#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 已提交
7701
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7702 7703 7704
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7705
    gen_qemu_ld16u(ctx, t0, addr);
7706
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7707 7708
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7709 7710 7711
    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 已提交
7712
    gen_qemu_ld16u(ctx, t0, addr);
7713
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7714 7715
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7716 7717 7718 7719 7720
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7721
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7722 7723 7724
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7725 7726 7727
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7728 7729 7730 7731
    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 已提交
7732 7733 7734
    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);
7735 7736 7737
#endif
}

B
Blue Swirl 已提交
7738
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7739 7740 7741
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7742
    gen_qemu_ld16s(ctx, t0, addr);
7743
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7744 7745
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7746 7747 7748 7749
    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 已提交
7750 7751 7752
    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);
7753 7754 7755
#endif
}

B
Blue Swirl 已提交
7756
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7757 7758
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7759
    gen_qemu_ld32u(ctx, t0, addr);
7760
#if defined(TARGET_PPC64)
7761 7762 7763 7764 7765 7766 7767 7768 7769
    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 已提交
7770
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7771 7772 7773
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7774
    gen_qemu_ld16u(ctx, t0, addr);
7775 7776 7777
    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 已提交
7778 7779
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7780 7781 7782 7783
    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 已提交
7784
    gen_qemu_ld16u(ctx, t0, addr);
7785 7786
    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 已提交
7787 7788
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7789 7790
    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);
7791
#endif
7792 7793 7794
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7795
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7796 7797
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7798
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7799
#else
7800 7801
    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 已提交
7802
    gen_qemu_st64(ctx, t0, addr);
7803 7804 7805 7806
    tcg_temp_free_i64(t0);
#endif
}

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

B
Blue Swirl 已提交
7821
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7822 7823 7824 7825 7826 7827 7828
{
    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 已提交
7829 7830
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7831 7832
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7833
    gen_qemu_st16(ctx, t0, addr);
7834
#else
A
aurel32 已提交
7835
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7836
#endif
A
aurel32 已提交
7837
    gen_addr_add(ctx, addr, addr, 2);
7838
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7839
    gen_qemu_st16(ctx, t0, addr);
7840
    tcg_temp_free(t0);
A
aurel32 已提交
7841 7842
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7843 7844
}

B
Blue Swirl 已提交
7845
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7846 7847 7848 7849 7850 7851 7852
{
    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 已提交
7853 7854
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7855
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7856
    gen_qemu_st16(ctx, t0, addr);
7857 7858 7859
    tcg_temp_free(t0);
}

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

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

B
Blue Swirl 已提交
7886
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7887
{
A
aurel32 已提交
7888
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7889 7890 7891
}

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

/* Multiply and add - TODO */
#if 0
7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999
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);
8000 8001 8002
#endif

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

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

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

8251
/* Comparison */
A
aurel32 已提交
8252 8253 8254 8255 8256 8257
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);
8258 8259

/* Opcodes definitions */
8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273
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); //
8274 8275 8276

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8277 8278 8279 8280
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 已提交
8281
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8282 8283
{
    if (unlikely(!ctx->spe_enabled)) {
8284
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8285 8286
        return;
    }
8287
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8288
}
B
Blue Swirl 已提交
8289
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8290 8291
{
    if (unlikely(!ctx->spe_enabled)) {
8292
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8293 8294
        return;
    }
8295
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8296
}
B
Blue Swirl 已提交
8297
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8298 8299
{
    if (unlikely(!ctx->spe_enabled)) {
8300
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8301 8302
        return;
    }
8303
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8304 8305
}

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

8319
/* Comparison */
A
aurel32 已提交
8320 8321 8322 8323 8324 8325
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);
8326 8327

/* Opcodes definitions */
8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341
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); //
8342 8343 8344

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

8389
/* Conversion */
A
aurel32 已提交
8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404
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);
8405 8406

/* Comparison */
A
aurel32 已提交
8407 8408 8409 8410 8411 8412
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);
8413 8414

/* Opcodes definitions */
8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430
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); //
8431

A
Anthony Liguori 已提交
8432
static opcode_t opcodes[] = {
8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463
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),
8464
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8465
#if defined(TARGET_PPC64)
8466
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507
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),
8508
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8509 8510
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8511
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566
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),
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
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),
8567 8568 8569
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),
8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649
#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 已提交
8650
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8651 8652 8653 8654 8655 8656 8657 8658
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 已提交
8659 8660 8661 8662 8663 8664 8665 8666
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 已提交
8667 8668
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8669 8670
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8671 8672
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8673
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8674
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8675
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8676 8677
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8678
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8679 8680
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852
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
8853
#undef GEN_LDX_E
8854 8855 8856 8857 8858 8859 8860
#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),
8861 8862
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877
#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)
8878
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
8879 8880 8881 8882 8883 8884 8885
#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
8886
#undef GEN_STX_E
8887 8888 8889 8890 8891 8892 8893
#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),
8894 8895
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907
#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)
8908
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176
#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),
9177
GEN_VXFORM_NOA(vexptefp, 5, 6),
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
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
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
#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),
9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308

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

9309
#include "translate_init.c"
9310
#include "helper_regs.h"
B
bellard 已提交
9311

9312
/*****************************************************************************/
9313
/* Misc PowerPC helpers */
9314
void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
9315
                     int flags)
B
bellard 已提交
9316
{
9317 9318 9319
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9320 9321
    int i;

9322 9323
    cpu_synchronize_state(env);

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

S
Scott Wood 已提交
9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438
    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 已提交
9439
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457
        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;
    }
9458
#endif
B
bellard 已提交
9459

9460 9461
#undef RGPL
#undef RFPL
B
bellard 已提交
9462 9463
}

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

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

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

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

9697
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9698
{
9699
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9700 9701
}

9702
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9703
{
9704
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9705
}
A
aurel32 已提交
9706

9707
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9708 9709 9710
{
    env->nip = gen_opc_pc[pc_pos];
}